Просмотр исходного кода

Move colour options to their own file

Benjamin Sago 8 лет назад
Родитель
Сommit
4907565baf
3 измененных файлов с 204 добавлено и 116 удалено
  1. 201 0
      src/options/colours.rs
  2. 1 0
      src/options/mod.rs
  3. 2 116
      src/options/view.rs

+ 201 - 0
src/options/colours.rs

@@ -0,0 +1,201 @@
+use output::Colours;
+
+use options::{flags, Misfire};
+use options::parser::MatchedFlags;
+
+
+
+/// Under what circumstances we should display coloured, rather than plain,
+/// output to the terminal.
+///
+/// By default, we want to display the colours when stdout can display them.
+/// Turning them on when output is going to, say, a pipe, would make programs
+/// such as `grep` or `more` not work properly. So the `Automatic` mode does
+/// this check and only displays colours when they can be truly appreciated.
+#[derive(PartialEq, Debug)]
+enum TerminalColours {
+
+    /// Display them even when output isn’t going to a terminal.
+    Always,
+
+    /// Display them when output is going to a terminal, but not otherwise.
+    Automatic,
+
+    /// Never display them, even when output is going to a terminal.
+    Never,
+}
+
+impl Default for TerminalColours {
+    fn default() -> TerminalColours {
+        TerminalColours::Automatic
+    }
+}
+
+const COLOURS: &[&str] = &["always", "auto", "never"];
+
+impl TerminalColours {
+
+    /// Determine which terminal colour conditions to use.
+    fn deduce(matches: &MatchedFlags) -> Result<TerminalColours, Misfire> {
+
+        let word = match matches.get_where(|f| f.matches(&flags::COLOR) || f.matches(&flags::COLOUR))? {
+            Some(w) => w,
+            None    => return Ok(TerminalColours::default()),
+        };
+
+        if word == "always" {
+            Ok(TerminalColours::Always)
+        }
+        else if word == "auto" || word == "automatic" {
+            Ok(TerminalColours::Automatic)
+        }
+        else if word == "never" {
+            Ok(TerminalColours::Never)
+        }
+        else {
+            Err(Misfire::bad_argument(&flags::COLOR, word, COLOURS))
+        }
+    }
+}
+
+
+impl Colours {
+    pub fn deduce<TW>(matches: &MatchedFlags, widther: TW) -> Result<Colours, Misfire>
+    where TW: Fn() -> Option<usize> {
+        use self::TerminalColours::*;
+
+        let tc = TerminalColours::deduce(matches)?;
+        if tc == Always || (tc == Automatic && widther().is_some()) {
+            let scale = matches.has_where(|f| f.matches(&flags::COLOR_SCALE) || f.matches(&flags::COLOUR_SCALE))?;
+            Ok(Colours::colourful(scale.is_some()))
+        }
+        else {
+            Ok(Colours::plain())
+        }
+    }
+}
+
+
+#[cfg(test)]
+mod test {
+    use super::*;
+    use std::ffi::OsString;
+    use options::flags;
+    use options::parser::{Flag, Arg};
+
+    use options::test::parse_for_test;
+    use options::test::Strictnesses::*;
+
+    pub fn os(input: &'static str) -> OsString {
+        let mut os = OsString::new();
+        os.push(input);
+        os
+    }
+
+    static TEST_ARGS: &[&Arg] = &[ &flags::COLOR,       &flags::COLOUR,
+                                   &flags::COLOR_SCALE, &flags::COLOUR_SCALE ];
+
+    macro_rules! test {
+
+        ($name:ident: $type:ident <- $inputs:expr; $stricts:expr => $result:expr) => {
+            /// Macro that writes a test.
+            /// If testing both strictnesses, they’ll both be done in the same function.
+            #[test]
+            fn $name() {
+                for result in parse_for_test($inputs.as_ref(), TEST_ARGS, $stricts, |mf| $type::deduce(mf)) {
+                    assert_eq!(result, $result);
+                }
+            }
+        };
+
+        ($name:ident: $type:ident <- $inputs:expr; $stricts:expr => err $result:expr) => {
+            /// Special macro for testing Err results.
+            /// This is needed because sometimes the Ok type doesn’t implement PartialEq.
+            #[test]
+            fn $name() {
+                for result in parse_for_test($inputs.as_ref(), TEST_ARGS, $stricts, |mf| $type::deduce(mf)) {
+                    assert_eq!(result.unwrap_err(), $result);
+                }
+            }
+        };
+
+        ($name:ident: $type:ident <- $inputs:expr; $stricts:expr => like $pat:pat) => {
+            /// More general macro for testing against a pattern.
+            /// Instead of using PartialEq, this just tests if it matches a pat.
+            #[test]
+            fn $name() {
+                for result in parse_for_test($inputs.as_ref(), TEST_ARGS, $stricts, |mf| $type::deduce(mf)) {
+                    println!("Testing {:?}", result);
+                    match result {
+                        $pat => assert!(true),
+                        _    => assert!(false),
+                    }
+                }
+            }
+        };
+
+
+        ($name:ident: $type:ident <- $inputs:expr, $vars:expr; $stricts:expr => err $result:expr) => {
+            /// Like above, but with $vars.
+            #[test]
+            fn $name() {
+                for result in parse_for_test($inputs.as_ref(), TEST_ARGS, $stricts, |mf| $type::deduce(mf, &$vars)) {
+                    assert_eq!(result.unwrap_err(), $result);
+                }
+            }
+        };
+
+        ($name:ident: $type:ident <- $inputs:expr, $vars:expr; $stricts:expr => like $pat:pat) => {
+            /// Like further above, but with $vars.
+            #[test]
+            fn $name() {
+                for result in parse_for_test($inputs.as_ref(), TEST_ARGS, $stricts, |mf| $type::deduce(mf, &$vars)) {
+                    println!("Testing {:?}", result);
+                    match result {
+                        $pat => assert!(true),
+                        _    => assert!(false),
+                    }
+                }
+            }
+        };
+    }
+
+
+    // Default
+    test!(empty:        TerminalColours <- [];                     Both => Ok(TerminalColours::default()));
+
+    // --colour
+    test!(u_always:     TerminalColours <- ["--colour=always"];    Both => Ok(TerminalColours::Always));
+    test!(u_auto:       TerminalColours <- ["--colour", "auto"];   Both => Ok(TerminalColours::Automatic));
+    test!(u_never:      TerminalColours <- ["--colour=never"];     Both => Ok(TerminalColours::Never));
+
+    // --color
+    test!(no_u_always:  TerminalColours <- ["--color", "always"];  Both => Ok(TerminalColours::Always));
+    test!(no_u_auto:    TerminalColours <- ["--color=auto"];       Both => Ok(TerminalColours::Automatic));
+    test!(no_u_never:   TerminalColours <- ["--color", "never"];   Both => Ok(TerminalColours::Never));
+
+    // Errors
+    test!(no_u_error:   TerminalColours <- ["--color=upstream"];   Both => err Misfire::bad_argument(&flags::COLOR, &os("upstream"), super::COLOURS));  // the error is for --color
+    test!(u_error:      TerminalColours <- ["--colour=lovers"];    Both => err Misfire::bad_argument(&flags::COLOR, &os("lovers"),   super::COLOURS));  // and so is this one!
+
+    // Overriding
+    test!(overridden_1: TerminalColours <- ["--colour=auto", "--colour=never"];  Last => Ok(TerminalColours::Never));
+    test!(overridden_2: TerminalColours <- ["--color=auto",  "--colour=never"];  Last => Ok(TerminalColours::Never));
+    test!(overridden_3: TerminalColours <- ["--colour=auto", "--color=never"];   Last => Ok(TerminalColours::Never));
+    test!(overridden_4: TerminalColours <- ["--color=auto",  "--color=never"];   Last => Ok(TerminalColours::Never));
+
+    test!(overridden_5: TerminalColours <- ["--colour=auto", "--colour=never"];  Complain => err Misfire::Duplicate(Flag::Long("colour"), Flag::Long("colour")));
+    test!(overridden_6: TerminalColours <- ["--color=auto",  "--colour=never"];  Complain => err Misfire::Duplicate(Flag::Long("color"),  Flag::Long("colour")));
+    test!(overridden_7: TerminalColours <- ["--colour=auto", "--color=never"];   Complain => err Misfire::Duplicate(Flag::Long("colour"), Flag::Long("color")));
+    test!(overridden_8: TerminalColours <- ["--color=auto",  "--color=never"];   Complain => err Misfire::Duplicate(Flag::Long("color"),  Flag::Long("color")));
+
+    test!(scale_1: Colours <- ["--color=always", "--color-scale", "--colour-scale"], || None;   Last => like Ok(Colours { scale: true,  .. }));
+    test!(scale_2: Colours <- ["--color=always", "--color-scale",                 ], || None;   Last => like Ok(Colours { scale: true,  .. }));
+    test!(scale_3: Colours <- ["--color=always",                  "--colour-scale"], || None;   Last => like Ok(Colours { scale: true,  .. }));
+    test!(scale_4: Colours <- ["--color=always",                                  ], || None;   Last => like Ok(Colours { scale: false, .. }));
+
+    test!(scale_5: Colours <- ["--color=always", "--color-scale", "--colour-scale"], || None;   Complain => err Misfire::Duplicate(Flag::Long("color-scale"),  Flag::Long("colour-scale")));
+    test!(scale_6: Colours <- ["--color=always", "--color-scale",                 ], || None;   Complain => like Ok(Colours { scale: true,  .. }));
+    test!(scale_7: Colours <- ["--color=always",                  "--colour-scale"], || None;   Complain => like Ok(Colours { scale: true,  .. }));
+    test!(scale_8: Colours <- ["--color=always",                                  ], || None;   Complain => like Ok(Colours { scale: false, .. }));
+}

+ 1 - 0
src/options/mod.rs

@@ -75,6 +75,7 @@ use fs::dir_action::DirAction;
 use fs::filter::FileFilter;
 use output::{View, Mode, details, grid_details};
 
+mod colours;
 mod dir_action;
 mod filter;
 mod view;

+ 2 - 116
src/options/view.rs

@@ -11,12 +11,13 @@ use options::parser::MatchedFlags;
 use fs::feature::xattr;
 use info::filetype::FileExtensions;
 
+
 impl View {
 
     /// Determine which view to use and all of that view’s arguments.
     pub fn deduce<V: Vars>(matches: &MatchedFlags, vars: &V) -> Result<View, Misfire> {
         let mode = Mode::deduce(matches, vars)?;
-        let colours = Colours::deduce(matches)?;
+        let colours = Colours::deduce(matches, || *TERM_WIDTH)?;
         let style = FileStyle::deduce(matches)?;
         Ok(View { mode, colours, style })
     }
@@ -330,77 +331,6 @@ impl TimeTypes {
 }
 
 
-/// Under what circumstances we should display coloured, rather than plain,
-/// output to the terminal.
-///
-/// By default, we want to display the colours when stdout can display them.
-/// Turning them on when output is going to, say, a pipe, would make programs
-/// such as `grep` or `more` not work properly. So the `Automatic` mode does
-/// this check and only displays colours when they can be truly appreciated.
-#[derive(PartialEq, Debug)]
-enum TerminalColours {
-
-    /// Display them even when output isn’t going to a terminal.
-    Always,
-
-    /// Display them when output is going to a terminal, but not otherwise.
-    Automatic,
-
-    /// Never display them, even when output is going to a terminal.
-    Never,
-}
-
-impl Default for TerminalColours {
-    fn default() -> TerminalColours {
-        TerminalColours::Automatic
-    }
-}
-
-const COLOURS: &[&str] = &["always", "auto", "never"];
-
-impl TerminalColours {
-
-    /// Determine which terminal colour conditions to use.
-    fn deduce(matches: &MatchedFlags) -> Result<TerminalColours, Misfire> {
-
-        let word = match matches.get_where(|f| f.matches(&flags::COLOR) || f.matches(&flags::COLOUR))? {
-            Some(w) => w,
-            None    => return Ok(TerminalColours::default()),
-        };
-
-        if word == "always" {
-            Ok(TerminalColours::Always)
-        }
-        else if word == "auto" || word == "automatic" {
-            Ok(TerminalColours::Automatic)
-        }
-        else if word == "never" {
-            Ok(TerminalColours::Never)
-        }
-        else {
-            Err(Misfire::bad_argument(&flags::COLOR, word, COLOURS))
-        }
-    }
-}
-
-
-impl Colours {
-    fn deduce(matches: &MatchedFlags) -> Result<Colours, Misfire> {
-        use self::TerminalColours::*;
-
-        let tc = TerminalColours::deduce(matches)?;
-        if tc == Always || (tc == Automatic && TERM_WIDTH.is_some()) {
-            let scale = matches.has_where(|f| f.matches(&flags::COLOR_SCALE) || f.matches(&flags::COLOUR_SCALE))?;
-            Ok(Colours::colourful(scale.is_some()))
-        }
-        else {
-            Ok(Colours::plain())
-        }
-    }
-}
-
-
-
 impl FileStyle {
     fn deduce(matches: &MatchedFlags) -> Result<FileStyle, Misfire> {
         let classify = Classify::deduce(matches)?;
@@ -452,7 +382,6 @@ mod test {
 
     static TEST_ARGS: &[&Arg] = &[ &flags::BINARY, &flags::BYTES,    &flags::TIME_STYLE,
                                    &flags::TIME,   &flags::MODIFIED, &flags::CREATED, &flags::ACCESSED,
-                                   &flags::COLOR,  &flags::COLOUR,  &flags::COLOR_SCALE, &flags::COLOUR_SCALE,
                                    &flags::HEADER, &flags::GROUP,  &flags::INODE, &flags::GIT,
                                    &flags::LINKS,  &flags::BLOCKS, &flags::LONG,  &flags::LEVEL,
                                    &flags::GRID,   &flags::ACROSS, &flags::ONE_LINE ];
@@ -611,49 +540,6 @@ mod test {
     }
 
 
-    mod colourses {
-        use super::*;
-
-        // Default
-        test!(empty:        TerminalColours <- [];                     Both => Ok(TerminalColours::default()));
-
-        // --colour
-        test!(u_always:     TerminalColours <- ["--colour=always"];    Both => Ok(TerminalColours::Always));
-        test!(u_auto:       TerminalColours <- ["--colour", "auto"];   Both => Ok(TerminalColours::Automatic));
-        test!(u_never:      TerminalColours <- ["--colour=never"];     Both => Ok(TerminalColours::Never));
-
-        // --color
-        test!(no_u_always:  TerminalColours <- ["--color", "always"];  Both => Ok(TerminalColours::Always));
-        test!(no_u_auto:    TerminalColours <- ["--color=auto"];       Both => Ok(TerminalColours::Automatic));
-        test!(no_u_never:   TerminalColours <- ["--color", "never"];   Both => Ok(TerminalColours::Never));
-
-        // Errors
-        test!(no_u_error:   TerminalColours <- ["--color=upstream"];   Both => err Misfire::bad_argument(&flags::COLOR, &os("upstream"), super::COLOURS));  // the error is for --color
-        test!(u_error:      TerminalColours <- ["--colour=lovers"];    Both => err Misfire::bad_argument(&flags::COLOR, &os("lovers"),   super::COLOURS));  // and so is this one!
-
-        // Overriding
-        test!(overridden_1: TerminalColours <- ["--colour=auto", "--colour=never"];  Last => Ok(TerminalColours::Never));
-        test!(overridden_2: TerminalColours <- ["--color=auto",  "--colour=never"];  Last => Ok(TerminalColours::Never));
-        test!(overridden_3: TerminalColours <- ["--colour=auto", "--color=never"];   Last => Ok(TerminalColours::Never));
-        test!(overridden_4: TerminalColours <- ["--color=auto",  "--color=never"];   Last => Ok(TerminalColours::Never));
-
-        test!(overridden_5: TerminalColours <- ["--colour=auto", "--colour=never"];  Complain => err Misfire::Duplicate(Flag::Long("colour"), Flag::Long("colour")));
-        test!(overridden_6: TerminalColours <- ["--color=auto",  "--colour=never"];  Complain => err Misfire::Duplicate(Flag::Long("color"),  Flag::Long("colour")));
-        test!(overridden_7: TerminalColours <- ["--colour=auto", "--color=never"];   Complain => err Misfire::Duplicate(Flag::Long("colour"), Flag::Long("color")));
-        test!(overridden_8: TerminalColours <- ["--color=auto",  "--color=never"];   Complain => err Misfire::Duplicate(Flag::Long("color"),  Flag::Long("color")));
-
-        test!(scale_1: Colours <- ["--color=always", "--color-scale", "--colour-scale"];   Last => like Ok(Colours { scale: true,  .. }));
-        test!(scale_2: Colours <- ["--color=always", "--color-scale",                 ];   Last => like Ok(Colours { scale: true,  .. }));
-        test!(scale_3: Colours <- ["--color=always",                  "--colour-scale"];   Last => like Ok(Colours { scale: true,  .. }));
-        test!(scale_4: Colours <- ["--color=always",                                  ];   Last => like Ok(Colours { scale: false, .. }));
-
-        test!(scale_5: Colours <- ["--color=always", "--color-scale", "--colour-scale"];   Complain => err Misfire::Duplicate(Flag::Long("color-scale"),  Flag::Long("colour-scale")));
-        test!(scale_6: Colours <- ["--color=always", "--color-scale",                 ];   Complain => like Ok(Colours { scale: true,  .. }));
-        test!(scale_7: Colours <- ["--color=always",                  "--colour-scale"];   Complain => like Ok(Colours { scale: true,  .. }));
-        test!(scale_8: Colours <- ["--color=always",                                  ];   Complain => like Ok(Colours { scale: false, .. }));
-    }
-
-
     mod views {
         use super::*;
         use output::grid::Options as GridOptions;