about summary refs log tree commit diff
path: root/src/libterm
diff options
context:
space:
mode:
authorMark Rousskov <mark.simulacrum@gmail.com>2019-12-22 17:42:04 -0500
committerMark Rousskov <mark.simulacrum@gmail.com>2019-12-22 17:42:47 -0500
commita06baa56b95674fc626b3c3fd680d6a65357fe60 (patch)
treecd9d867c2ca3cff5c1d6b3bd73377c44649fb075 /src/libterm
parent8eb7c58dbb7b32701af113bc58722d0d1fefb1eb (diff)
Format the world
Diffstat (limited to 'src/libterm')
-rw-r--r--src/libterm/lib.rs16
-rw-r--r--src/libterm/terminfo/mod.rs53
-rw-r--r--src/libterm/terminfo/parm.rs246
-rw-r--r--src/libterm/terminfo/parm/tests.rs105
-rw-r--r--src/libterm/terminfo/parser/compiled.rs77
-rw-r--r--src/libterm/win.rs20
6 files changed, 261 insertions, 256 deletions
diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs
index ad1a83316be..7318ced676a 100644
--- a/src/libterm/lib.rs
+++ b/src/libterm/lib.rs
@@ -30,15 +30,16 @@
 //! [win]: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682010%28v=vs.85%29.aspx
 //! [ti]: https://en.wikipedia.org/wiki/Terminfo
 
-#![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
-       html_playground_url = "https://play.rust-lang.org/",
-       test(attr(deny(warnings))))]
+#![doc(
+    html_root_url = "https://doc.rust-lang.org/nightly/",
+    html_playground_url = "https://play.rust-lang.org/",
+    test(attr(deny(warnings)))
+)]
 #![deny(missing_docs)]
-
 #![cfg_attr(windows, feature(libc))]
 
 use std::io::prelude::*;
-use std::io::{self, Stdout, Stderr};
+use std::io::{self, Stderr, Stdout};
 
 pub use terminfo::TerminfoTerminal;
 #[cfg(windows)]
@@ -86,7 +87,6 @@ pub fn stderr() -> Option<Box<StderrTerminal>> {
         .or_else(|| WinConsole::new(io::stderr()).ok().map(|t| Box::new(t) as Box<StderrTerminal>))
 }
 
-
 /// Terminal color definitions
 #[allow(missing_docs)]
 pub mod color {
@@ -192,5 +192,7 @@ pub trait Terminal: Write {
     fn get_mut(&mut self) -> &mut Self::Output;
 
     /// Returns the contained stream, destroying the `Terminal`
-    fn into_inner(self) -> Self::Output where Self: Sized;
+    fn into_inner(self) -> Self::Output
+    where
+        Self: Sized;
 }
diff --git a/src/libterm/terminfo/mod.rs b/src/libterm/terminfo/mod.rs
index 09bea80c95a..5db1d5f4278 100644
--- a/src/libterm/terminfo/mod.rs
+++ b/src/libterm/terminfo/mod.rs
@@ -8,13 +8,13 @@ use std::fs::File;
 use std::io::{self, prelude::*, BufReader};
 use std::path::Path;
 
-use crate::Attr;
 use crate::color;
+use crate::Attr;
 use crate::Terminal;
 
+use parm::{expand, Param, Variables};
+use parser::compiled::{msys_terminfo, parse};
 use searcher::get_dbpath_for_term;
-use parser::compiled::{parse, msys_terminfo};
-use parm::{expand, Variables, Param};
 
 /// A parsed terminfo database entry.
 #[derive(Debug)]
@@ -112,7 +112,6 @@ pub mod parser {
 }
 pub mod parm;
 
-
 fn cap_for_attr(attr: Attr) -> &'static str {
     match attr {
         Attr::Bold => "bold",
@@ -178,18 +177,14 @@ impl<T: Write + Send> Terminal for TerminfoTerminal<T> {
     fn reset(&mut self) -> io::Result<bool> {
         // are there any terminals that have color/attrs and not sgr0?
         // Try falling back to sgr, then op
-        let cmd = match ["sgr0", "sgr", "op"]
-                            .iter()
-                            .filter_map(|cap| self.ti.strings.get(*cap))
-                            .next() {
-            Some(op) => {
-                match expand(&op, &[], &mut Variables::new()) {
+        let cmd =
+            match ["sgr0", "sgr", "op"].iter().filter_map(|cap| self.ti.strings.get(*cap)).next() {
+                Some(op) => match expand(&op, &[], &mut Variables::new()) {
                     Ok(cmd) => cmd,
                     Err(e) => return Err(io::Error::new(io::ErrorKind::InvalidData, e)),
-                }
-            }
-            None => return Ok(false),
-        };
+                },
+                None => return Ok(false),
+            };
         self.out.write_all(&cmd).and(Ok(true))
     }
 
@@ -202,7 +197,8 @@ impl<T: Write + Send> Terminal for TerminfoTerminal<T> {
     }
 
     fn into_inner(self) -> T
-        where Self: Sized
+    where
+        Self: Sized,
     {
         self.out
     }
@@ -211,18 +207,14 @@ impl<T: Write + Send> Terminal for TerminfoTerminal<T> {
 impl<T: Write + Send> TerminfoTerminal<T> {
     /// Creates a new TerminfoTerminal with the given TermInfo and Write.
     pub fn new_with_terminfo(out: T, terminfo: TermInfo) -> TerminfoTerminal<T> {
-        let nc = if terminfo.strings.contains_key("setaf") &&
-                    terminfo.strings.contains_key("setab") {
+        let nc = if terminfo.strings.contains_key("setaf") && terminfo.strings.contains_key("setab")
+        {
             terminfo.numbers.get("colors").map_or(0, |&n| n)
         } else {
             0
         };
 
-        TerminfoTerminal {
-            out,
-            ti: terminfo,
-            num_colors: nc,
-        }
+        TerminfoTerminal { out, ti: terminfo, num_colors: nc }
     }
 
     /// Creates a new TerminfoTerminal for the current environment with the given Write.
@@ -233,27 +225,20 @@ impl<T: Write + Send> TerminfoTerminal<T> {
     }
 
     fn dim_if_necessary(&self, color: color::Color) -> color::Color {
-        if color >= self.num_colors && color >= 8 && color < 16 {
-            color - 8
-        } else {
-            color
-        }
+        if color >= self.num_colors && color >= 8 && color < 16 { color - 8 } else { color }
     }
 
     fn apply_cap(&mut self, cmd: &str, params: &[Param]) -> io::Result<bool> {
         match self.ti.strings.get(cmd) {
-            Some(cmd) => {
-                match expand(&cmd, params, &mut Variables::new()) {
-                    Ok(s) => self.out.write_all(&s).and(Ok(true)),
-                    Err(e) => Err(io::Error::new(io::ErrorKind::InvalidData, e)),
-                }
-            }
+            Some(cmd) => match expand(&cmd, params, &mut Variables::new()) {
+                Ok(s) => self.out.write_all(&s).and(Ok(true)),
+                Err(e) => Err(io::Error::new(io::ErrorKind::InvalidData, e)),
+            },
             None => Ok(false),
         }
     }
 }
 
-
 impl<T: Write> Write for TerminfoTerminal<T> {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         self.out.write(buf)
diff --git a/src/libterm/terminfo/parm.rs b/src/libterm/terminfo/parm.rs
index c7466daa2ba..2e4e917891e 100644
--- a/src/libterm/terminfo/parm.rs
+++ b/src/libterm/terminfo/parm.rs
@@ -53,16 +53,60 @@ impl Variables {
     pub fn new() -> Variables {
         Variables {
             sta_va: [
-                Number(0), Number(0), Number(0), Number(0), Number(0), Number(0), Number(0),
-                Number(0), Number(0), Number(0), Number(0), Number(0), Number(0), Number(0),
-                Number(0), Number(0), Number(0), Number(0), Number(0), Number(0), Number(0),
-                Number(0), Number(0), Number(0), Number(0), Number(0)
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
             ],
             dyn_va: [
-                Number(0), Number(0), Number(0), Number(0), Number(0), Number(0), Number(0),
-                Number(0), Number(0), Number(0), Number(0), Number(0), Number(0), Number(0),
-                Number(0), Number(0), Number(0), Number(0), Number(0), Number(0), Number(0),
-                Number(0), Number(0), Number(0), Number(0), Number(0)
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
+                Number(0),
             ],
         }
     }
@@ -86,8 +130,17 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) -> Result<Vec<
     let mut stack: Vec<Param> = Vec::new();
 
     // Copy parameters into a local vector for mutability
-    let mut mparams = [Number(0), Number(0), Number(0), Number(0), Number(0), Number(0),
-                       Number(0), Number(0), Number(0)];
+    let mut mparams = [
+        Number(0),
+        Number(0),
+        Number(0),
+        Number(0),
+        Number(0),
+        Number(0),
+        Number(0),
+        Number(0),
+        Number(0),
+    ];
     for (dst, src) in mparams.iter_mut().zip(params.iter()) {
         *dst = (*src).clone();
     }
@@ -124,81 +177,67 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) -> Result<Vec<
                     'g' => state = GetVar,
                     '\'' => state = CharConstant,
                     '{' => state = IntConstant(0),
-                    'l' => {
-                        match stack.pop() {
-                            Some(Words(s)) => stack.push(Number(s.len() as i32)),
-                            Some(_) => return Err("a non-str was used with %l".to_string()),
-                            None => return Err("stack is empty".to_string()),
-                        }
-                    }
+                    'l' => match stack.pop() {
+                        Some(Words(s)) => stack.push(Number(s.len() as i32)),
+                        Some(_) => return Err("a non-str was used with %l".to_string()),
+                        None => return Err("stack is empty".to_string()),
+                    },
                     '+' | '-' | '/' | '*' | '^' | '&' | '|' | 'm' => {
                         match (stack.pop(), stack.pop()) {
-                            (Some(Number(y)), Some(Number(x))) => {
-                                stack.push(Number(match cur {
-                                    '+' => x + y,
-                                    '-' => x - y,
-                                    '*' => x * y,
-                                    '/' => x / y,
-                                    '|' => x | y,
-                                    '&' => x & y,
-                                    '^' => x ^ y,
-                                    'm' => x % y,
-                                    _ => unreachable!("All cases handled"),
-                                }))
-                            }
+                            (Some(Number(y)), Some(Number(x))) => stack.push(Number(match cur {
+                                '+' => x + y,
+                                '-' => x - y,
+                                '*' => x * y,
+                                '/' => x / y,
+                                '|' => x | y,
+                                '&' => x & y,
+                                '^' => x ^ y,
+                                'm' => x % y,
+                                _ => unreachable!("All cases handled"),
+                            })),
                             (Some(_), Some(_)) => {
-                                return Err(format!("non-numbers on stack with {}", cur))
+                                return Err(format!("non-numbers on stack with {}", cur));
                             }
                             _ => return Err("stack is empty".to_string()),
                         }
                     }
-                    '=' | '>' | '<' | 'A' | 'O' => {
-                        match (stack.pop(), stack.pop()) {
-                            (Some(Number(y)), Some(Number(x))) => {
-                                stack.push(Number(if match cur {
-                                    '=' => x == y,
-                                    '<' => x < y,
-                                    '>' => x > y,
-                                    'A' => x > 0 && y > 0,
-                                    'O' => x > 0 || y > 0,
-                                    _ => unreachable!(),
-                                } {
-                                    1
-                                } else {
-                                    0
-                                }))
-                            }
-                            (Some(_), Some(_)) => {
-                                return Err(format!("non-numbers on stack with {}", cur))
-                            }
-                            _ => return Err("stack is empty".to_string()),
-                        }
-                    }
-                    '!' | '~' => {
-                        match stack.pop() {
-                            Some(Number(x)) => {
-                                stack.push(Number(match cur {
-                                    '!' if x > 0 => 0,
-                                    '!' => 1,
-                                    '~' => !x,
-                                    _ => unreachable!(),
-                                }))
-                            }
-                            Some(_) => return Err(format!("non-numbers on stack with {}", cur)),
-                            None => return Err("stack is empty".to_string()),
+                    '=' | '>' | '<' | 'A' | 'O' => match (stack.pop(), stack.pop()) {
+                        (Some(Number(y)), Some(Number(x))) => stack.push(Number(
+                            if match cur {
+                                '=' => x == y,
+                                '<' => x < y,
+                                '>' => x > y,
+                                'A' => x > 0 && y > 0,
+                                'O' => x > 0 || y > 0,
+                                _ => unreachable!(),
+                            } {
+                                1
+                            } else {
+                                0
+                            },
+                        )),
+                        (Some(_), Some(_)) => {
+                            return Err(format!("non-numbers on stack with {}", cur));
                         }
-                    }
-                    'i' => {
-                        match (&mparams[0], &mparams[1]) {
-                            (&Number(x), &Number(y)) => {
-                                mparams[0] = Number(x + 1);
-                                mparams[1] = Number(y + 1);
-                            }
-                            _ => {
-                                return Err("first two params not numbers with %i".to_string())
-                            }
+                        _ => return Err("stack is empty".to_string()),
+                    },
+                    '!' | '~' => match stack.pop() {
+                        Some(Number(x)) => stack.push(Number(match cur {
+                            '!' if x > 0 => 0,
+                            '!' => 1,
+                            '~' => !x,
+                            _ => unreachable!(),
+                        })),
+                        Some(_) => return Err(format!("non-numbers on stack with {}", cur)),
+                        None => return Err("stack is empty".to_string()),
+                    },
+                    'i' => match (&mparams[0], &mparams[1]) {
+                        (&Number(x), &Number(y)) => {
+                            mparams[0] = Number(x + 1);
+                            mparams[1] = Number(y + 1);
                         }
-                    }
+                        _ => return Err("first two params not numbers with %i".to_string()),
+                    },
 
                     // printf-style support for %doxXs
                     'd' | 'o' | 'x' | 'X' | 's' => {
@@ -229,16 +268,12 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) -> Result<Vec<
 
                     // conditionals
                     '?' => (),
-                    't' => {
-                        match stack.pop() {
-                            Some(Number(0)) => state = SeekIfElse(0),
-                            Some(Number(_)) => (),
-                            Some(_) => {
-                                return Err("non-number on stack with conditional".to_string())
-                            }
-                            None => return Err("stack is empty".to_string()),
-                        }
-                    }
+                    't' => match stack.pop() {
+                        Some(Number(0)) => state = SeekIfElse(0),
+                        Some(Number(_)) => (),
+                        Some(_) => return Err("non-number on stack with conditional".to_string()),
+                        None => return Err("stack is empty".to_string()),
+                    },
                     'e' => state = SeekIfEnd(0),
                     ';' => (),
                     _ => return Err(format!("unrecognized format option {}", cur)),
@@ -246,11 +281,13 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) -> Result<Vec<
             }
             PushParam => {
                 // params are 1-indexed
-                stack.push(mparams[match cur.to_digit(10) {
-                               Some(d) => d as usize - 1,
-                               None => return Err("bad param number".to_string()),
-                           }]
-                           .clone());
+                stack.push(
+                    mparams[match cur.to_digit(10) {
+                        Some(d) => d as usize - 1,
+                        None => return Err("bad param number".to_string()),
+                    }]
+                    .clone(),
+                );
             }
             SetVar => {
                 if cur >= 'A' && cur <= 'Z' {
@@ -419,14 +456,7 @@ struct Flags {
 
 impl Flags {
     fn new() -> Flags {
-        Flags {
-            width: 0,
-            precision: 0,
-            alternate: false,
-            left: false,
-            sign: false,
-            space: false,
-        }
+        Flags { width: 0, precision: 0, alternate: false, left: false, sign: false, space: false }
     }
 }
 
@@ -503,18 +533,16 @@ fn format(val: Param, op: FormatOp, flags: Flags) -> Result<Vec<u8>, String> {
             }
             .into_bytes()
         }
-        Words(s) => {
-            match op {
-                FormatOp::String => {
-                    let mut s = s.into_bytes();
-                    if flags.precision > 0 && flags.precision < s.len() {
-                        s.truncate(flags.precision);
-                    }
-                    s
+        Words(s) => match op {
+            FormatOp::String => {
+                let mut s = s.into_bytes();
+                if flags.precision > 0 && flags.precision < s.len() {
+                    s.truncate(flags.precision);
                 }
-                _ => return Err(format!("non-string on stack with %{}", op.to_char())),
+                s
             }
-        }
+            _ => return Err(format!("non-string on stack with %{}", op.to_char())),
+        },
     };
     if flags.width > s.len() {
         let n = flags.width - s.len();
diff --git a/src/libterm/terminfo/parm/tests.rs b/src/libterm/terminfo/parm/tests.rs
index 4d38715424e..b975bd2d198 100644
--- a/src/libterm/terminfo/parm/tests.rs
+++ b/src/libterm/terminfo/parm/tests.rs
@@ -5,36 +5,43 @@ use std::result::Result::Ok;
 #[test]
 fn test_basic_setabf() {
     let s = b"\\E[48;5;%p1%dm";
-    assert_eq!(expand(s, &[Number(1)], &mut Variables::new()).unwrap(),
-                "\\E[48;5;1m".bytes().collect::<Vec<_>>());
+    assert_eq!(
+        expand(s, &[Number(1)], &mut Variables::new()).unwrap(),
+        "\\E[48;5;1m".bytes().collect::<Vec<_>>()
+    );
 }
 
 #[test]
 fn test_multiple_int_constants() {
-    assert_eq!(expand(b"%{1}%{2}%d%d", &[], &mut Variables::new()).unwrap(),
-                "21".bytes().collect::<Vec<_>>());
+    assert_eq!(
+        expand(b"%{1}%{2}%d%d", &[], &mut Variables::new()).unwrap(),
+        "21".bytes().collect::<Vec<_>>()
+    );
 }
 
 #[test]
 fn test_op_i() {
     let mut vars = Variables::new();
-    assert_eq!(expand(b"%p1%d%p2%d%p3%d%i%p1%d%p2%d%p3%d",
-                        &[Number(1), Number(2), Number(3)],
-                        &mut vars),
-                Ok("123233".bytes().collect::<Vec<_>>()));
-    assert_eq!(expand(b"%p1%d%p2%d%i%p1%d%p2%d", &[], &mut vars),
-                Ok("0011".bytes().collect::<Vec<_>>()));
+    assert_eq!(
+        expand(b"%p1%d%p2%d%p3%d%i%p1%d%p2%d%p3%d", &[Number(1), Number(2), Number(3)], &mut vars),
+        Ok("123233".bytes().collect::<Vec<_>>())
+    );
+    assert_eq!(
+        expand(b"%p1%d%p2%d%i%p1%d%p2%d", &[], &mut vars),
+        Ok("0011".bytes().collect::<Vec<_>>())
+    );
 }
 
 #[test]
 fn test_param_stack_failure_conditions() {
     let mut varstruct = Variables::new();
     let vars = &mut varstruct;
-    fn get_res(fmt: &str,
-                cap: &str,
-                params: &[Param],
-                vars: &mut Variables)
-                -> Result<Vec<u8>, String> {
+    fn get_res(
+        fmt: &str,
+        cap: &str,
+        params: &[Param],
+        vars: &mut Variables,
+    ) -> Result<Vec<u8>, String> {
         let mut u8v: Vec<_> = fmt.bytes().collect();
         u8v.extend(cap.as_bytes().iter().map(|&b| b));
         expand(&u8v, params, vars)
@@ -43,35 +50,19 @@ fn test_param_stack_failure_conditions() {
     let caps = ["%d", "%c", "%s", "%Pa", "%l", "%!", "%~"];
     for &cap in caps.iter() {
         let res = get_res("", cap, &[], vars);
-        assert!(res.is_err(),
-                "Op {} succeeded incorrectly with 0 stack entries",
-                cap);
-        let p = if cap == "%s" || cap == "%l" {
-            Words("foo".to_string())
-        } else {
-            Number(97)
-        };
+        assert!(res.is_err(), "Op {} succeeded incorrectly with 0 stack entries", cap);
+        let p = if cap == "%s" || cap == "%l" { Words("foo".to_string()) } else { Number(97) };
         let res = get_res("%p1", cap, &[p], vars);
-        assert!(res.is_ok(),
-                "Op {} failed with 1 stack entry: {}",
-                cap,
-                res.unwrap_err());
+        assert!(res.is_ok(), "Op {} failed with 1 stack entry: {}", cap, res.unwrap_err());
     }
     let caps = ["%+", "%-", "%*", "%/", "%m", "%&", "%|", "%A", "%O"];
     for &cap in caps.iter() {
         let res = expand(cap.as_bytes(), &[], vars);
-        assert!(res.is_err(),
-                "Binop {} succeeded incorrectly with 0 stack entries",
-                cap);
+        assert!(res.is_err(), "Binop {} succeeded incorrectly with 0 stack entries", cap);
         let res = get_res("%{1}", cap, &[], vars);
-        assert!(res.is_err(),
-                "Binop {} succeeded incorrectly with 1 stack entry",
-                cap);
+        assert!(res.is_err(), "Binop {} succeeded incorrectly with 1 stack entry", cap);
         let res = get_res("%{1}%{2}", cap, &[], vars);
-        assert!(res.is_ok(),
-                "Binop {} failed with 2 stack entries: {}",
-                cap,
-                res.unwrap_err());
+        assert!(res.is_ok(), "Binop {} failed with 2 stack entries: {}", cap, res.unwrap_err());
     }
 }
 
@@ -118,20 +109,30 @@ fn test_conditionals() {
 fn test_format() {
     let mut varstruct = Variables::new();
     let vars = &mut varstruct;
-    assert_eq!(expand(b"%p1%s%p2%2s%p3%2s%p4%.2s",
-                        &[Words("foo".to_string()),
-                        Words("foo".to_string()),
-                        Words("f".to_string()),
-                        Words("foo".to_string())],
-                        vars),
-                Ok("foofoo ffo".bytes().collect::<Vec<_>>()));
-    assert_eq!(expand(b"%p1%:-4.2s", &[Words("foo".to_string())], vars),
-                Ok("fo  ".bytes().collect::<Vec<_>>()));
+    assert_eq!(
+        expand(
+            b"%p1%s%p2%2s%p3%2s%p4%.2s",
+            &[
+                Words("foo".to_string()),
+                Words("foo".to_string()),
+                Words("f".to_string()),
+                Words("foo".to_string())
+            ],
+            vars
+        ),
+        Ok("foofoo ffo".bytes().collect::<Vec<_>>())
+    );
+    assert_eq!(
+        expand(b"%p1%:-4.2s", &[Words("foo".to_string())], vars),
+        Ok("fo  ".bytes().collect::<Vec<_>>())
+    );
 
-    assert_eq!(expand(b"%p1%d%p1%.3d%p1%5d%p1%:+d", &[Number(1)], vars),
-                Ok("1001    1+1".bytes().collect::<Vec<_>>()));
-    assert_eq!(expand(b"%p1%o%p1%#o%p2%6.4x%p2%#6.4X",
-                        &[Number(15), Number(27)],
-                        vars),
-                Ok("17017  001b0X001B".bytes().collect::<Vec<_>>()));
+    assert_eq!(
+        expand(b"%p1%d%p1%.3d%p1%5d%p1%:+d", &[Number(1)], vars),
+        Ok("1001    1+1".bytes().collect::<Vec<_>>())
+    );
+    assert_eq!(
+        expand(b"%p1%o%p1%#o%p2%6.4x%p2%#6.4X", &[Number(15), Number(27)], vars),
+        Ok("17017  001b0X001B".bytes().collect::<Vec<_>>())
+    );
 }
diff --git a/src/libterm/terminfo/parser/compiled.rs b/src/libterm/terminfo/parser/compiled.rs
index a8653a22f25..d36adb72c8e 100644
--- a/src/libterm/terminfo/parser/compiled.rs
+++ b/src/libterm/terminfo/parser/compiled.rs
@@ -2,10 +2,10 @@
 
 //! ncurses-compatible compiled terminfo format parsing (term(5))
 
+use super::super::TermInfo;
 use std::collections::HashMap;
 use std::io;
 use std::io::prelude::*;
-use super::super::TermInfo;
 
 #[cfg(test)]
 mod tests;
@@ -195,9 +195,7 @@ pub fn parse(file: &mut dyn io::Read, longnames: bool) -> Result<TermInfo, Strin
     // Check magic number
     let magic = t!(read_le_u16(file));
     if magic != 0x011A {
-        return Err(format!("invalid magic number: expected {:x}, found {:x}",
-                           0x011A,
-                           magic));
+        return Err(format!("invalid magic number: expected {:x}, found {:x}", 0x011A, magic));
     }
 
     // According to the spec, these fields must be >= -1 where -1 means that the feature is not
@@ -209,7 +207,7 @@ pub fn parse(file: &mut dyn io::Read, longnames: bool) -> Result<TermInfo, Strin
                 -1 => 0,
                 _ => return Err("incompatible file: length fields must be  >= -1".to_string()),
             }
-        }}
+        }};
     }
 
     let names_bytes = read_nonneg!();
@@ -242,9 +240,7 @@ pub fn parse(file: &mut dyn io::Read, longnames: bool) -> Result<TermInfo, Strin
         Err(_) => return Err("input not utf-8".to_string()),
     };
 
-    let term_names: Vec<String> = names_str.split('|')
-                                           .map(|s| s.to_string())
-                                           .collect();
+    let term_names: Vec<String> = names_str.split('|').map(|s| s.to_string()).collect();
     // consume NUL
     if t!(read_byte(file)) != b'\0' {
         return Err("incompatible file: missing null terminator for names section".to_string());
@@ -271,49 +267,46 @@ pub fn parse(file: &mut dyn io::Read, longnames: bool) -> Result<TermInfo, Strin
     };
 
     let string_map: HashMap<String, Vec<u8>> = if string_offsets_count > 0 {
-        let string_offsets: Vec<u16> = t!((0..string_offsets_count)
-                                                .map(|_| read_le_u16(file))
-                                                .collect());
+        let string_offsets: Vec<u16> =
+            t!((0..string_offsets_count).map(|_| read_le_u16(file)).collect());
 
         let mut string_table = Vec::new();
         t!(file.take(string_table_bytes as u64).read_to_end(&mut string_table));
 
-        t!(string_offsets.into_iter().enumerate().filter(|&(_, offset)| {
-            // non-entry
-            offset != 0xFFFF
-        }).map(|(i, offset)| {
-            let offset = offset as usize;
-
-            let name = if snames[i] == "_" {
-                stringfnames[i]
-            } else {
-                snames[i]
-            };
-
-            if offset == 0xFFFE {
-                // undocumented: FFFE indicates cap@, which means the capability is not present
-                // unsure if the handling for this is correct
-                return Ok((name.to_string(), Vec::new()));
-            }
-
-            // Find the offset of the NUL we want to go to
-            let nulpos = string_table[offset..string_table_bytes].iter().position(|&b| b == 0);
-            match nulpos {
-                Some(len) => Ok((name.to_string(), string_table[offset..offset + len].to_vec())),
-                None => Err("invalid file: missing NUL in string_table".to_string()),
-            }
-        }).collect())
+        t!(string_offsets
+            .into_iter()
+            .enumerate()
+            .filter(|&(_, offset)| {
+                // non-entry
+                offset != 0xFFFF
+            })
+            .map(|(i, offset)| {
+                let offset = offset as usize;
+
+                let name = if snames[i] == "_" { stringfnames[i] } else { snames[i] };
+
+                if offset == 0xFFFE {
+                    // undocumented: FFFE indicates cap@, which means the capability is not present
+                    // unsure if the handling for this is correct
+                    return Ok((name.to_string(), Vec::new()));
+                }
+
+                // Find the offset of the NUL we want to go to
+                let nulpos = string_table[offset..string_table_bytes].iter().position(|&b| b == 0);
+                match nulpos {
+                    Some(len) => {
+                        Ok((name.to_string(), string_table[offset..offset + len].to_vec()))
+                    }
+                    None => Err("invalid file: missing NUL in string_table".to_string()),
+                }
+            })
+            .collect())
     } else {
         HashMap::new()
     };
 
     // And that's all there is to it
-    Ok(TermInfo {
-        names: term_names,
-        bools: bools_map,
-        numbers: numbers_map,
-        strings: string_map,
-    })
+    Ok(TermInfo { names: term_names, bools: bools_map, numbers: numbers_map, strings: string_map })
 }
 
 /// Creates a dummy TermInfo struct for msys terminals
diff --git a/src/libterm/win.rs b/src/libterm/win.rs
index e5911de8396..a789d739ab1 100644
--- a/src/libterm/win.rs
+++ b/src/libterm/win.rs
@@ -5,8 +5,8 @@
 use std::io;
 use std::io::prelude::*;
 
-use crate::Attr;
 use crate::color;
+use crate::Attr;
 use crate::Terminal;
 
 /// A Terminal implementation that uses the Win32 Console API.
@@ -73,11 +73,7 @@ fn color_to_bits(color: color::Color) -> u16 {
         _ => unreachable!(),
     };
 
-    if color >= 8 {
-        bits | 0x8
-    } else {
-        bits
-    }
+    if color >= 8 { bits | 0x8 } else { bits }
 }
 
 fn bits_to_color(bits: u16) -> color::Color {
@@ -126,11 +122,10 @@ impl<T: Write + Send + 'static> WinConsole<T> {
         let bg;
         unsafe {
             let mut buffer_info = MaybeUninit::<CONSOLE_SCREEN_BUFFER_INFO>::uninit();
-            if GetConsoleScreenBufferInfo(
-                GetStdHandle(-11i32 as DWORD),
-                buffer_info.as_mut_ptr()
-            ) != 0 {
-                let buffer_info = buffer_info.assume_init() ;
+            if GetConsoleScreenBufferInfo(GetStdHandle(-11i32 as DWORD), buffer_info.as_mut_ptr())
+                != 0
+            {
+                let buffer_info = buffer_info.assume_init();
                 fg = bits_to_color(buffer_info.wAttributes);
                 bg = bits_to_color(buffer_info.wAttributes >> 4);
             } else {
@@ -217,7 +212,8 @@ impl<T: Write + Send + 'static> Terminal for WinConsole<T> {
     }
 
     fn into_inner(self) -> T
-        where Self: Sized
+    where
+        Self: Sized,
     {
         self.buf
     }