summaryrefslogtreecommitdiffstats
path: root/src/options/theme.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/options/theme.rs')
-rw-r--r--src/options/theme.rs159
1 files changed, 159 insertions, 0 deletions
diff --git a/src/options/theme.rs b/src/options/theme.rs
new file mode 100644
index 0000000..02309f7
--- /dev/null
+++ b/src/options/theme.rs
@@ -0,0 +1,159 @@
+use crate::options::{flags, vars, Vars, OptionsError};
+use crate::options::parser::MatchedFlags;
+use crate::theme::{Options, UseColours, ColourScale, Definitions};
+
+
+impl Options {
+ pub fn deduce<V: Vars>(matches: &MatchedFlags<'_>, vars: &V) -> Result<Self, OptionsError> {
+ let use_colours = UseColours::deduce(matches)?;
+ let colour_scale = ColourScale::deduce(matches)?;
+
+ let definitions = if use_colours == UseColours::Never {
+ Definitions::default()
+ }
+ else {
+ Definitions::deduce(vars)
+ };
+
+ Ok(Self { use_colours, colour_scale, definitions })
+ }
+}
+
+
+impl UseColours {
+ fn deduce(matches: &MatchedFlags<'_>) -> Result<Self, OptionsError> {
+ let word = match matches.get_where(|f| f.matches(&flags::COLOR) || f.matches(&flags::COLOUR))? {
+ Some(w) => w,
+ None => return Ok(Self::Automatic),
+ };
+
+ if word == "always" {
+ Ok(Self::Always)
+ }
+ else if word == "auto" || word == "automatic" {
+ Ok(Self::Automatic)
+ }
+ else if word == "never" {
+ Ok(Self::Never)
+ }
+ else {
+ Err(OptionsError::BadArgument(&flags::COLOR, word.into()))
+ }
+ }
+}
+
+
+impl ColourScale {
+ fn deduce(matches: &MatchedFlags<'_>) -> Result<Self, OptionsError> {
+ if matches.has_where(|f| f.matches(&flags::COLOR_SCALE) || f.matches(&flags::COLOUR_SCALE))?.is_some() {
+ Ok(Self::Gradient)
+ }
+ else {
+ Ok(Self::Fixed)
+ }
+ }
+}
+
+
+impl Definitions {
+ fn deduce<V: Vars>(vars: &V) -> Self {
+ let ls = vars.get(vars::LS_COLORS) .map(|e| e.to_string_lossy().to_string());
+ let exa = vars.get(vars::EXA_COLORS).map(|e| e.to_string_lossy().to_string());
+ Self { ls, exa }
+ }
+}
+
+
+#[cfg(test)]
+mod terminal_test {
+ use super::*;
+ use std::ffi::OsString;
+ use crate::options::flags;
+ use crate::options::parser::{Flag, Arg};
+
+ use crate::options::test::parse_for_test;
+ use crate::options::test::Strictnesses::*;
+
+ 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) => {
+ #[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) => {
+ #[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);
+ }
+ }
+ };
+ }
+
+ struct MockVars {
+ ls: &'static str,
+ exa: &'static str,
+ }
+
+ // Test impl that just returns the value it has.
+ impl Vars for MockVars {
+ fn get(&self, name: &'static str) -> Option<OsString> {
+ if name == vars::LS_COLORS && ! self.ls.is_empty() {
+ Some(OsString::from(self.ls.clone()))
+ }
+ else if name == vars::EXA_COLORS && ! self.exa.is_empty() {
+ Some(OsString::from(self.exa.clone()))
+ }
+ else {
+ None
+ }
+ }
+ }
+
+
+
+ // Default
+ test!(empty: UseColours <- []; Both => Ok(UseColours::Automatic));
+
+ // --colour
+ test!(u_always: UseColours <- ["--colour=always"]; Both => Ok(UseColours::Always));
+ test!(u_auto: UseColours <- ["--colour", "auto"]; Both => Ok(UseColours::Automatic));
+ test!(u_never: UseColours <- ["--colour=never"]; Both => Ok(UseColours::Never));
+
+ // --color
+ test!(no_u_always: UseColours <- ["--color", "always"]; Both => Ok(UseColours::Always));
+ test!(no_u_auto: UseColours <- ["--color=auto"]; Both => Ok(UseColours::Automatic));
+ test!(no_u_never: UseColours <- ["--color", "never"]; Both => Ok(UseColours::Never));
+
+ // Errors
+ test!(no_u_error: UseColours <- ["--color=upstream"]; Both => err OptionsError::BadArgument(&flags::COLOR, OsString::from("upstream"))); // the error is for --color
+ test!(u_error: UseColours <- ["--colour=lovers"]; Both => err OptionsError::BadArgument(&flags::COLOR, OsString::from("lovers"))); // and so is this one!
+
+ // Overriding
+ test!(overridden_1: UseColours <- ["--colour=auto", "--colour=never"]; Last => Ok(UseColours::Never));
+ test!(overridden_2: UseColours <- ["--color=auto", "--colour=never"]; Last => Ok(UseColours::Never));
+ test!(overridden_3: UseColours <- ["--colour=auto", "--color=never"]; Last => Ok(UseColours::Never));
+ test!(overridden_4: UseColours <- ["--color=auto", "--color=never"]; Last => Ok(UseColours::Never));
+
+ test!(overridden_5: UseColours <- ["--colour=auto", "--colour=never"]; Complain => err OptionsError::Duplicate(Flag::Long("colour"), Flag::Long("colour")));
+ test!(overridden_6: UseColours <- ["--color=auto", "--colour=never"]; Complain => err OptionsError::Duplicate(Flag::Long("color"), Flag::Long("colour")));
+ test!(overridden_7: UseColours <- ["--colour=auto", "--color=never"]; Complain => err OptionsError::Duplicate(Flag::Long("colour"), Flag::Long("color")));
+ test!(overridden_8: UseColours <- ["--color=auto", "--color=never"]; Complain => err OptionsError::Duplicate(Flag::Long("color"), Flag::Long("color")));
+
+ test!(scale_1: ColourScale <- ["--color-scale", "--colour-scale"]; Last => Ok(ColourScale::Gradient));
+ test!(scale_2: ColourScale <- ["--color-scale", ]; Last => Ok(ColourScale::Gradient));
+ test!(scale_3: ColourScale <- [ "--colour-scale"]; Last => Ok(ColourScale::Gradient));
+ test!(scale_4: ColourScale <- [ ]; Last => Ok(ColourScale::Fixed));
+
+ test!(scale_5: ColourScale <- ["--color-scale", "--colour-scale"]; Complain => err OptionsError::Duplicate(Flag::Long("color-scale"), Flag::Long("colour-scale")));
+ test!(scale_6: ColourScale <- ["--color-scale", ]; Complain => Ok(ColourScale::Gradient));
+ test!(scale_7: ColourScale <- [ "--colour-scale"]; Complain => Ok(ColourScale::Gradient));
+ test!(scale_8: ColourScale <- [ ]; Complain => Ok(ColourScale::Fixed));
+}