1 use crate::options::{flags, vars, Vars, OptionsError};
2 use crate::options::parser::MatchedFlags;
3 use crate::theme::{Options, UseColours, ColourScale, Definitions};
4 
5 
6 impl Options {
7     pub fn deduce<V: Vars>(matches: &MatchedFlags<'_>, vars: &V) -> Result<Self, OptionsError> {
8         let use_colours = UseColours::deduce(matches)?;
9         let colour_scale = ColourScale::deduce(matches)?;
10 
11         let definitions = if use_colours == UseColours::Never {
12                 Definitions::default()
13             }
14             else {
15                 Definitions::deduce(vars)
16             };
17 
18         Ok(Self { use_colours, colour_scale, definitions })
19     }
20 }
21 
22 
23 impl UseColours {
24     fn deduce(matches: &MatchedFlags<'_>) -> Result<Self, OptionsError> {
25         let word = match matches.get_where(|f| f.matches(&flags::COLOR) || f.matches(&flags::COLOUR))? {
26             Some(w)  => w,
27             None     => return Ok(Self::Automatic),
28         };
29 
30         if word == "always" {
31             Ok(Self::Always)
32         }
33         else if word == "auto" || word == "automatic" {
34             Ok(Self::Automatic)
35         }
36         else if word == "never" {
37             Ok(Self::Never)
38         }
39         else {
40             Err(OptionsError::BadArgument(&flags::COLOR, word.into()))
41         }
42     }
43 }
is_valid_apev2_key(key)44 
45 
46 impl ColourScale {
47     fn deduce(matches: &MatchedFlags<'_>) -> Result<Self, OptionsError> {
48         if matches.has_where(|f| f.matches(&flags::COLOR_SCALE) || f.matches(&flags::COLOUR_SCALE))?.is_some() {
49             Ok(Self::Gradient)
50         }
51         else {
52             Ok(Self::Fixed)
53         }
54     }
55 }
56 
57 
58 impl Definitions {
59     fn deduce<V: Vars>(vars: &V) -> Self {
60         let ls =  vars.get(vars::LS_COLORS) .map(|e| e.to_string_lossy().to_string());
61         let exa = vars.get(vars::EXA_COLORS).map(|e| e.to_string_lossy().to_string());
62         Self { ls, exa }
63     }
64 }
65 
66 
67 #[cfg(test)]
68 mod terminal_test {
69     use super::*;
70     use std::ffi::OsString;
71     use crate::options::flags;
72     use crate::options::parser::{Flag, Arg};
73 
74     use crate::options::test::parse_for_test;
75     use crate::options::test::Strictnesses::*;
76 
77     static TEST_ARGS: &[&Arg] = &[ &flags::COLOR,       &flags::COLOUR,
78                                    &flags::COLOR_SCALE, &flags::COLOUR_SCALE, ];
79 
80     macro_rules! test {
81         ($name:ident:  $type:ident <- $inputs:expr;  $stricts:expr => $result:expr) => {
82             #[test]
83             fn $name() {
84                 for result in parse_for_test($inputs.as_ref(), TEST_ARGS, $stricts, |mf| $type::deduce(mf)) {
85                     assert_eq!(result, $result);
86                 }
87             }
88         };
89 
90         ($name:ident:  $type:ident <- $inputs:expr;  $stricts:expr => err $result:expr) => {
91             #[test]
92             fn $name() {
93                 for result in parse_for_test($inputs.as_ref(), TEST_ARGS, $stricts, |mf| $type::deduce(mf)) {
94                     assert_eq!(result.unwrap_err(), $result);
95                 }
96             }
97         };
98     }
99 
100     struct MockVars {
101         ls: &'static str,
102         exa: &'static str,
103     }
104 
105     // Test impl that just returns the value it has.
106     impl Vars for MockVars {
107         fn get(&self, name: &'static str) -> Option<OsString> {
108             if name == vars::LS_COLORS && ! self.ls.is_empty() {
109                 Some(OsString::from(self.ls.clone()))
110             }
111             else if name == vars::EXA_COLORS && ! self.exa.is_empty() {
112                 Some(OsString::from(self.exa.clone()))
113             }
114             else {
115                 None
116             }
117         }
118     }
119 
120 
121 
122     // Default
123     test!(empty:         UseColours <- [];                     Both => Ok(UseColours::Automatic));
124 
125     // --colour
126     test!(u_always:      UseColours <- ["--colour=always"];    Both => Ok(UseColours::Always));
127     test!(u_auto:        UseColours <- ["--colour", "auto"];   Both => Ok(UseColours::Automatic));
128     test!(u_never:       UseColours <- ["--colour=never"];     Both => Ok(UseColours::Never));
129 
130     // --color
131     test!(no_u_always:   UseColours <- ["--color", "always"];  Both => Ok(UseColours::Always));
132     test!(no_u_auto:     UseColours <- ["--color=auto"];       Both => Ok(UseColours::Automatic));
133     test!(no_u_never:    UseColours <- ["--color", "never"];   Both => Ok(UseColours::Never));
134 
135     // Errors
136     test!(no_u_error:    UseColours <- ["--color=upstream"];   Both => err OptionsError::BadArgument(&flags::COLOR, OsString::from("upstream")));  // the error is for --color
137     test!(u_error:       UseColours <- ["--colour=lovers"];    Both => err OptionsError::BadArgument(&flags::COLOR, OsString::from("lovers")));    // and so is this one!
138 
139     // Overriding
140     test!(overridden_1:  UseColours <- ["--colour=auto", "--colour=never"];  Last => Ok(UseColours::Never));
141     test!(overridden_2:  UseColours <- ["--color=auto",  "--colour=never"];  Last => Ok(UseColours::Never));
142     test!(overridden_3:  UseColours <- ["--colour=auto", "--color=never"];   Last => Ok(UseColours::Never));
143     test!(overridden_4:  UseColours <- ["--color=auto",  "--color=never"];   Last => Ok(UseColours::Never));
144 
145     test!(overridden_5:  UseColours <- ["--colour=auto", "--colour=never"];  Complain => err OptionsError::Duplicate(Flag::Long("colour"), Flag::Long("colour")));
146     test!(overridden_6:  UseColours <- ["--color=auto",  "--colour=never"];  Complain => err OptionsError::Duplicate(Flag::Long("color"),  Flag::Long("colour")));
147     test!(overridden_7:  UseColours <- ["--colour=auto", "--color=never"];   Complain => err OptionsError::Duplicate(Flag::Long("colour"), Flag::Long("color")));
148     test!(overridden_8:  UseColours <- ["--color=auto",  "--color=never"];   Complain => err OptionsError::Duplicate(Flag::Long("color"),  Flag::Long("color")));
149 
150     test!(scale_1:  ColourScale <- ["--color-scale", "--colour-scale"];   Last => Ok(ColourScale::Gradient));
151     test!(scale_2:  ColourScale <- ["--color-scale",                 ];   Last => Ok(ColourScale::Gradient));
152     test!(scale_3:  ColourScale <- [                 "--colour-scale"];   Last => Ok(ColourScale::Gradient));
153     test!(scale_4:  ColourScale <- [                                 ];   Last => Ok(ColourScale::Fixed));
154 
155     test!(scale_5:  ColourScale <- ["--color-scale", "--colour-scale"];   Complain => err OptionsError::Duplicate(Flag::Long("color-scale"),  Flag::Long("colour-scale")));
156     test!(scale_6:  ColourScale <- ["--color-scale",                 ];   Complain => Ok(ColourScale::Gradient));
157     test!(scale_7:  ColourScale <- [                 "--colour-scale"];   Complain => Ok(ColourScale::Gradient));
158     test!(scale_8:  ColourScale <- [                                 ];   Complain => Ok(ColourScale::Fixed));
159 }
160