From 9872eba821cf9b05423d7338f9ac0117cad1eefd Mon Sep 17 00:00:00 2001 From: Benjamin Sago Date: Sat, 5 Aug 2017 19:11:00 +0100 Subject: [PATCH] Separate the matched flags from the free strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Originally, both the matched flags and the list of free strings were returned from the parsing function and then passed around to every type that had a ‘deduce’ method. This worked, but the list of free strings was carried around with it, never used. Now, only the flags are passed around. They’re in a new struct which has the methods the Matches had. Both of Matches’s fields are now just data, and all of the methods on MatchedFlags don’t ignore any fields, so it’s more cohesive, at least I think that’s the word. Building up the MatchedFlags is a bit more annoying though because the vector is now hidden behind a field. --- src/options/dir_action.rs | 8 +- src/options/filter.rs | 12 +-- src/options/help.rs | 4 +- src/options/mod.rs | 15 ++-- src/options/parser.rs | 162 +++++++++++++++++++++++--------------- src/options/view.rs | 24 +++--- 6 files changed, 131 insertions(+), 94 deletions(-) diff --git a/src/options/dir_action.rs b/src/options/dir_action.rs index f6165b9..a15f439 100644 --- a/src/options/dir_action.rs +++ b/src/options/dir_action.rs @@ -1,4 +1,4 @@ -use options::parser::Matches; +use options::parser::MatchedFlags; use options::{flags, Misfire}; use fs::dir_action::{DirAction, RecurseOptions}; @@ -7,7 +7,7 @@ use fs::dir_action::{DirAction, RecurseOptions}; impl DirAction { /// Determine which action to perform when trying to list a directory. - pub fn deduce(matches: &Matches) -> Result { + pub fn deduce(matches: &MatchedFlags) -> Result { let recurse = matches.has(&flags::RECURSE); let list = matches.has(&flags::LIST_DIRS); let tree = matches.has(&flags::TREE); @@ -36,7 +36,7 @@ impl DirAction { impl RecurseOptions { /// Determine which files should be recursed into. - pub fn deduce(matches: &Matches, tree: bool) -> Result { + pub fn deduce(matches: &MatchedFlags, tree: bool) -> Result { let max_depth = if let Some(level) = matches.get(&flags::LEVEL) { match level.to_string_lossy().parse() { Ok(l) => Some(l), @@ -75,7 +75,7 @@ mod test { let bits = $inputs.as_ref().into_iter().map(|&o| os(o)).collect::>(); let results = Args(TEST_ARGS).parse(bits.iter()); - assert_eq!($type::deduce(results.as_ref().unwrap()), $result); + assert_eq!($type::deduce(&results.unwrap().flags), $result); } }; } diff --git a/src/options/filter.rs b/src/options/filter.rs index 96d7355..5081141 100644 --- a/src/options/filter.rs +++ b/src/options/filter.rs @@ -4,14 +4,14 @@ use fs::DotFilter; use fs::filter::{FileFilter, SortField, SortCase, IgnorePatterns}; use options::{flags, Misfire}; -use options::parser::Matches; +use options::parser::MatchedFlags; impl FileFilter { /// Determines the set of file filter options to use, based on the user’s /// command-line arguments. - pub fn deduce(matches: &Matches) -> Result { + pub fn deduce(matches: &MatchedFlags) -> Result { Ok(FileFilter { list_dirs_first: matches.has(&flags::DIRS_FIRST), reverse: matches.has(&flags::REVERSE), @@ -39,7 +39,7 @@ impl SortField { /// Determine the sort field to use, based on the presence of a “sort” /// argument. This will return `Err` if the option is there, but does not /// correspond to a valid field. - fn deduce(matches: &Matches) -> Result { + fn deduce(matches: &MatchedFlags) -> Result { let word = match matches.get(&flags::SORT) { Some(w) => w, None => return Ok(SortField::default()), @@ -86,7 +86,7 @@ impl SortField { impl DotFilter { - pub fn deduce(matches: &Matches) -> Result { + pub fn deduce(matches: &MatchedFlags) -> Result { match matches.count(&flags::ALL) { 0 => Ok(DotFilter::JustFiles), 1 => Ok(DotFilter::Dotfiles), @@ -101,7 +101,7 @@ impl IgnorePatterns { /// Determines the set of file filter options to use, based on the user’s /// command-line arguments. - pub fn deduce(matches: &Matches) -> Result { + pub fn deduce(matches: &MatchedFlags) -> Result { let patterns = match matches.get(&flags::IGNORE_GLOB) { None => Ok(Vec::new()), Some(is) => is.to_string_lossy().split('|').map(|a| glob::Pattern::new(a)).collect(), @@ -139,7 +139,7 @@ mod test { let bits = $inputs.as_ref().into_iter().map(|&o| os(o)).collect::>(); let results = Args(TEST_ARGS).parse(bits.iter()); - assert_eq!($type::deduce(results.as_ref().unwrap()), $result); + assert_eq!($type::deduce(&results.unwrap().flags), $result); } }; } diff --git a/src/options/help.rs b/src/options/help.rs index ba3f7f8..2813dd6 100644 --- a/src/options/help.rs +++ b/src/options/help.rs @@ -1,7 +1,7 @@ use std::fmt; use options::flags; -use options::parser::Matches; +use options::parser::MatchedFlags; use fs::feature::xattr; @@ -72,7 +72,7 @@ impl HelpString { /// Determines how to show help, if at all, based on the user’s /// command-line arguments. This one works backwards from the other /// ‘deduce’ functions, returning Err if help needs to be shown. - pub fn deduce(matches: &Matches) -> Result<(), HelpString> { + pub fn deduce(matches: &MatchedFlags) -> Result<(), HelpString> { if matches.has(&flags::HELP) { let only_long = matches.has(&flags::LONG); let git = cfg!(feature="git"); diff --git a/src/options/mod.rs b/src/options/mod.rs index 21ed0a1..d3a7955 100644 --- a/src/options/mod.rs +++ b/src/options/mod.rs @@ -88,7 +88,7 @@ pub use self::misfire::Misfire; mod parser; mod flags; -use self::parser::Matches; +use self::parser::MatchedFlags; /// These **options** represent a parsed, error-checked versions of the @@ -113,20 +113,21 @@ impl Options { #[allow(unused_results)] pub fn getopts<'args, I>(args: I) -> Result<(Options, Vec<&'args OsStr>), Misfire> where I: IntoIterator { + use options::parser::Matches; - let matches = match flags::ALL_ARGS.parse(args) { + let Matches { flags, frees } = match flags::ALL_ARGS.parse(args) { Ok(m) => m, Err(e) => return Err(Misfire::InvalidOptions(e)), }; - HelpString::deduce(&matches).map_err(Misfire::Help)?; + HelpString::deduce(&flags).map_err(Misfire::Help)?; - if matches.has(&flags::VERSION) { + if flags.has(&flags::VERSION) { return Err(Misfire::Version); } - let options = Options::deduce(&matches)?; - Ok((options, matches.frees)) + let options = Options::deduce(&flags)?; + Ok((options, frees)) } /// Whether the View specified in this set of options includes a Git @@ -142,7 +143,7 @@ impl Options { /// Determines the complete set of options based on the given command-line /// arguments, after they’ve been parsed. - fn deduce(matches: &Matches) -> Result { + fn deduce(matches: &MatchedFlags) -> Result { let dir_action = DirAction::deduce(matches)?; let filter = FileFilter::deduce(matches)?; let view = View::deduce(matches)?; diff --git a/src/options/parser.rs b/src/options/parser.rs index e1159f9..a448bd1 100644 --- a/src/options/parser.rs +++ b/src/options/parser.rs @@ -130,7 +130,7 @@ impl Args { // The results that get built up. let mut results = Matches { - flags: Vec::new(), + flags: MatchedFlags { flags: Vec::new() }, frees: Vec::new(), }; @@ -163,7 +163,7 @@ impl Args { let arg = self.lookup_long(before)?; let flag = Flag::Long(arg.long); match arg.takes_value { - Necessary => results.flags.push((flag, Some(after))), + Necessary => results.flags.flags.push((flag, Some(after))), Forbidden => return Err(ParseError::ForbiddenValue { flag }) } } @@ -174,10 +174,10 @@ impl Args { let arg = self.lookup_long(long_arg_name)?; let flag = Flag::Long(arg.long); match arg.takes_value { - Forbidden => results.flags.push((flag, None)), + Forbidden => results.flags.flags.push((flag, None)), Necessary => { if let Some(next_arg) = inputs.next() { - results.flags.push((flag, Some(next_arg))); + results.flags.flags.push((flag, Some(next_arg))); } else { return Err(ParseError::NeedsValue { flag }) @@ -212,7 +212,7 @@ impl Args { let arg = self.lookup_short(*byte)?; let flag = Flag::Short(*byte); match arg.takes_value { - Forbidden => results.flags.push((flag, None)), + Forbidden => results.flags.flags.push((flag, None)), Necessary => return Err(ParseError::NeedsValue { flag }) } } @@ -221,7 +221,7 @@ impl Args { let arg = self.lookup_short(*arg_with_value)?; let flag = Flag::Short(arg.short.unwrap()); match arg.takes_value { - Necessary => results.flags.push((flag, Some(after))), + Necessary => results.flags.flags.push((flag, Some(after))), Forbidden => return Err(ParseError::ForbiddenValue { flag }) } } @@ -243,15 +243,15 @@ impl Args { let arg = self.lookup_short(*byte)?; let flag = Flag::Short(*byte); match arg.takes_value { - Forbidden => results.flags.push((flag, None)), + Forbidden => results.flags.flags.push((flag, None)), Necessary => { if index < bytes.len() - 1 { let remnants = &bytes[index+1 ..]; - results.flags.push((flag, Some(OsStr::from_bytes(remnants)))); + results.flags.flags.push((flag, Some(OsStr::from_bytes(remnants)))); break; } else if let Some(next_arg) = inputs.next() { - results.flags.push((flag, Some(next_arg))); + results.flags.flags.push((flag, Some(next_arg))); } else { return Err(ParseError::NeedsValue { flag }) @@ -287,20 +287,31 @@ impl Args { } -/// The **matches** are the result of parsing +/// The **matches** are the result of parsing the user’s command-line strings. #[derive(PartialEq, Debug)] pub struct Matches<'args> { - /// The flags that were - /// Long and short arguments need to be kept in the same vector, because - /// we usually want the one nearest the end to count. - pub flags: Vec<(Flag, Option<&'args OsStr>)>, + /// The flags that were parsed from the user’s input. + pub flags: MatchedFlags<'args>, - /// The strings that weren’t matched as arguments. + /// All the strings that weren’t matched as arguments, as well as anything + /// after the special "--" string. pub frees: Vec<&'args OsStr>, } -impl<'a> Matches<'a> { +#[derive(PartialEq, Debug)] +pub struct MatchedFlags<'args> { + + /// The individual flags from the user’s input, in the order they were + /// originally given. + /// + /// Long and short arguments need to be kept in the same vector because + /// we usually want the one nearest the end to count, and to know this, + /// we need to know where they are in relation to one another. + flags: Vec<(Flag, Option<&'args OsStr>)>, +} + +impl<'a> MatchedFlags<'a> { /// Whether the given argument was specified. pub fn has(&self, arg: &Arg) -> bool { @@ -424,12 +435,39 @@ mod parse_test { use super::*; macro_rules! test { - ($name:ident: $inputs:expr => $result:expr) => { + ($name:ident: $inputs:expr => frees: $frees:expr, flags: $flags:expr) => { #[test] fn $name() { + + // Annoyingly the input &strs need to be converted to OsStrings + let inputs: Vec = $inputs.as_ref().into_iter().map(|&o| os(o)).collect(); + + // Same with the frees + let frees: Vec = $frees.as_ref().into_iter().map(|&o| os(o)).collect(); + let frees: Vec<&OsStr> = frees.iter().map(|os| os.as_os_str()).collect(); + + // And again for the flags + let flags: Vec<(Flag, Option<&OsStr>)> = $flags + .as_ref() + .into_iter() + .map(|&(ref f, ref os): &(Flag, Option<&'static str>)| (f.clone(), os.map(OsStr::new))) + .collect(); + + let got = Args(TEST_ARGS).parse(inputs.iter()); + let expected = Ok(Matches { frees, flags: MatchedFlags { flags } }); + assert_eq!(got, expected); + } + }; + + ($name:ident: $inputs:expr => error $error:expr) => { + #[test] + fn $name() { + use self::ParseError::*; + let bits = $inputs.as_ref().into_iter().map(|&o| os(o)).collect::>(); - let results = Args(TEST_ARGS).parse(bits.iter()); - assert_eq!(results, $result); + let got = Args(TEST_ARGS).parse(bits.iter()); + + assert_eq!(got, Err($error)); } }; } @@ -442,52 +480,52 @@ mod parse_test { // Just filenames - test!(empty: [] => Ok(Matches { frees: vec![], flags: vec![] })); - test!(one_arg: ["exa"] => Ok(Matches { frees: vec![ &os("exa") ], flags: vec![] })); + test!(empty: [] => frees: [], flags: []); + test!(one_arg: ["exa"] => frees: [ "exa" ], flags: []); // Dashes and double dashes - test!(one_dash: ["-"] => Ok(Matches { frees: vec![ &os("-") ], flags: vec![] })); - test!(two_dashes: ["--"] => Ok(Matches { frees: vec![], flags: vec![] })); - test!(two_file: ["--", "file"] => Ok(Matches { frees: vec![ &os("file") ], flags: vec![] })); - test!(two_arg_l: ["--", "--long"] => Ok(Matches { frees: vec![ &os("--long") ], flags: vec![] })); - test!(two_arg_s: ["--", "-l"] => Ok(Matches { frees: vec![ &os("-l") ], flags: vec![] })); + test!(one_dash: ["-"] => frees: [ "-" ], flags: []); + test!(two_dashes: ["--"] => frees: [], flags: []); + test!(two_file: ["--", "file"] => frees: [ "file" ], flags: []); + test!(two_arg_l: ["--", "--long"] => frees: [ "--long" ], flags: []); + test!(two_arg_s: ["--", "-l"] => frees: [ "-l" ], flags: []); // Long args - test!(long: ["--long"] => Ok(Matches { frees: vec![], flags: vec![ (Flag::Long("long"), None) ] })); - test!(long_then: ["--long", "4"] => Ok(Matches { frees: vec![ &os("4") ], flags: vec![ (Flag::Long("long"), None) ] })); - test!(long_two: ["--long", "--verbose"] => Ok(Matches { frees: vec![], flags: vec![ (Flag::Long("long"), None), (Flag::Long("verbose"), None) ] })); + test!(long: ["--long"] => frees: [], flags: [ (Flag::Long("long"), None) ]); + test!(long_then: ["--long", "4"] => frees: [ "4" ], flags: [ (Flag::Long("long"), None) ]); + test!(long_two: ["--long", "--verbose"] => frees: [], flags: [ (Flag::Long("long"), None), (Flag::Long("verbose"), None) ]); // Long args with values - test!(bad_equals: ["--long=equals"] => Err(ParseError::ForbiddenValue { flag: Flag::Long("long") })); - test!(no_arg: ["--count"] => Err(ParseError::NeedsValue { flag: Flag::Long("count") })); - test!(arg_equals: ["--count=4"] => Ok(Matches { frees: vec![], flags: vec![ (Flag::Long("count"), Some(&*os("4"))) ] })); - test!(arg_then: ["--count", "4"] => Ok(Matches { frees: vec![], flags: vec![ (Flag::Long("count"), Some(&*os("4"))) ] })); + test!(bad_equals: ["--long=equals"] => error ForbiddenValue { flag: Flag::Long("long") }); + test!(no_arg: ["--count"] => error NeedsValue { flag: Flag::Long("count") }); + test!(arg_equals: ["--count=4"] => frees: [], flags: [ (Flag::Long("count"), Some("4")) ]); + test!(arg_then: ["--count", "4"] => frees: [], flags: [ (Flag::Long("count"), Some("4")) ]); // Short args - test!(short: ["-l"] => Ok(Matches { frees: vec![], flags: vec![ (Flag::Short(b'l'), None) ] })); - test!(short_then: ["-l", "4"] => Ok(Matches { frees: vec![ &*os("4") ], flags: vec![ (Flag::Short(b'l'), None) ] })); - test!(short_two: ["-lv"] => Ok(Matches { frees: vec![], flags: vec![ (Flag::Short(b'l'), None), (Flag::Short(b'v'), None) ] })); - test!(mixed: ["-v", "--long"] => Ok(Matches { frees: vec![], flags: vec![ (Flag::Short(b'v'), None), (Flag::Long("long"), None) ] })); + test!(short: ["-l"] => frees: [], flags: [ (Flag::Short(b'l'), None) ]); + test!(short_then: ["-l", "4"] => frees: [ "4" ], flags: [ (Flag::Short(b'l'), None) ]); + test!(short_two: ["-lv"] => frees: [], flags: [ (Flag::Short(b'l'), None), (Flag::Short(b'v'), None) ]); + test!(mixed: ["-v", "--long"] => frees: [], flags: [ (Flag::Short(b'v'), None), (Flag::Long("long"), None) ]); // Short args with values - test!(bad_short: ["-l=equals"] => Err(ParseError::ForbiddenValue { flag: Flag::Short(b'l') })); - test!(short_none: ["-c"] => Err(ParseError::NeedsValue { flag: Flag::Short(b'c') })); - test!(short_arg_eq: ["-c=4"] => Ok(Matches { frees: vec![], flags: vec![ (Flag::Short(b'c'), Some(&*os("4"))) ] })); - test!(short_arg_then: ["-c", "4"] => Ok(Matches { frees: vec![], flags: vec![ (Flag::Short(b'c'), Some(&*os("4"))) ] })); - test!(short_two_together: ["-lctwo"] => Ok(Matches { frees: vec![], flags: vec![ (Flag::Short(b'l'), None), (Flag::Short(b'c'), Some(&*os("two"))) ] })); - test!(short_two_equals: ["-lc=two"] => Ok(Matches { frees: vec![], flags: vec![ (Flag::Short(b'l'), None), (Flag::Short(b'c'), Some(&*os("two"))) ] })); - test!(short_two_next: ["-lc", "two"] => Ok(Matches { frees: vec![], flags: vec![ (Flag::Short(b'l'), None), (Flag::Short(b'c'), Some(&*os("two"))) ] })); + test!(bad_short: ["-l=equals"] => error ForbiddenValue { flag: Flag::Short(b'l') }); + test!(short_none: ["-c"] => error NeedsValue { flag: Flag::Short(b'c') }); + test!(short_arg_eq: ["-c=4"] => frees: [], flags: [(Flag::Short(b'c'), Some("4")) ]); + test!(short_arg_then: ["-c", "4"] => frees: [], flags: [(Flag::Short(b'c'), Some("4")) ]); + test!(short_two_together: ["-lctwo"] => frees: [], flags: [(Flag::Short(b'l'), None), (Flag::Short(b'c'), Some("two")) ]); + test!(short_two_equals: ["-lc=two"] => frees: [], flags: [(Flag::Short(b'l'), None), (Flag::Short(b'c'), Some("two")) ]); + test!(short_two_next: ["-lc", "two"] => frees: [], flags: [(Flag::Short(b'l'), None), (Flag::Short(b'c'), Some("two")) ]); // Unknown args - test!(unknown_long: ["--quiet"] => Err(ParseError::UnknownArgument { attempt: os("quiet") })); - test!(unknown_long_eq: ["--quiet=shhh"] => Err(ParseError::UnknownArgument { attempt: os("quiet") })); - test!(unknown_short: ["-q"] => Err(ParseError::UnknownShortArgument { attempt: b'q' })); - test!(unknown_short_2nd: ["-lq"] => Err(ParseError::UnknownShortArgument { attempt: b'q' })); - test!(unknown_short_eq: ["-q=shhh"] => Err(ParseError::UnknownShortArgument { attempt: b'q' })); - test!(unknown_short_2nd_eq: ["-lq=shhh"] => Err(ParseError::UnknownShortArgument { attempt: b'q' })); + test!(unknown_long: ["--quiet"] => error UnknownArgument { attempt: os("quiet") }); + test!(unknown_long_eq: ["--quiet=shhh"] => error UnknownArgument { attempt: os("quiet") }); + test!(unknown_short: ["-q"] => error UnknownShortArgument { attempt: b'q' }); + test!(unknown_short_2nd: ["-lq"] => error UnknownShortArgument { attempt: b'q' }); + test!(unknown_short_eq: ["-q=shhh"] => error UnknownShortArgument { attempt: b'q' }); + test!(unknown_short_2nd_eq: ["-lq=shhh"] => error UnknownShortArgument { attempt: b'q' }); } @@ -499,9 +537,8 @@ mod matches_test { ($name:ident: $input:expr, has $param:expr => $result:expr) => { #[test] fn $name() { - let frees = Vec::new(); - let flags = $input.to_vec(); - assert_eq!(Matches { frees, flags }.has(&$param), $result); + let flags = MatchedFlags { flags: $input.to_vec() }; + assert_eq!(flags.has(&$param), $result); } }; } @@ -521,9 +558,8 @@ mod matches_test { #[test] fn only_count() { let everything = os("everything"); - let frees = Vec::new(); - let flags = vec![ (Flag::Short(b'c'), Some(&*everything)) ]; - assert_eq!(Matches { frees, flags }.get(&COUNT), Some(&*everything)); + let flags = MatchedFlags { flags: vec![ (Flag::Short(b'c'), Some(&*everything)) ] }; + assert_eq!(flags.get(&COUNT), Some(&*everything)); } #[test] @@ -531,18 +567,18 @@ mod matches_test { let everything = os("everything"); let nothing = os("nothing"); - let frees = Vec::new(); - let flags = vec![ (Flag::Short(b'c'), Some(&*everything)), - (Flag::Short(b'c'), Some(&*nothing)) ]; + let flags = MatchedFlags { + flags: vec![ (Flag::Short(b'c'), Some(&*everything)), + (Flag::Short(b'c'), Some(&*nothing)) ] + }; - assert_eq!(Matches { frees, flags }.get(&COUNT), Some(&*nothing)); + assert_eq!(flags.get(&COUNT), Some(&*nothing)); } #[test] fn no_count() { - let frees = Vec::new(); - let flags = Vec::new(); + let flags = MatchedFlags { flags: Vec::new() }; - assert!(!Matches { frees, flags }.has(&COUNT)); + assert!(!flags.has(&COUNT)); } } diff --git a/src/options/view.rs b/src/options/view.rs index ecbaa41..536282e 100644 --- a/src/options/view.rs +++ b/src/options/view.rs @@ -7,7 +7,7 @@ use output::file_name::{Classify, FileStyle}; use output::time::TimeFormat; use options::{flags, Misfire}; -use options::parser::Matches; +use options::parser::MatchedFlags; use fs::feature::xattr; use info::filetype::FileExtensions; @@ -16,7 +16,7 @@ use info::filetype::FileExtensions; impl View { /// Determine which view to use and all of that view’s arguments. - pub fn deduce(matches: &Matches) -> Result { + pub fn deduce(matches: &MatchedFlags) -> Result { let mode = Mode::deduce(matches)?; let colours = Colours::deduce(matches)?; let style = FileStyle::deduce(matches); @@ -28,7 +28,7 @@ impl View { impl Mode { /// Determine the mode from the command-line arguments. - pub fn deduce(matches: &Matches) -> Result { + pub fn deduce(matches: &MatchedFlags) -> Result { use options::misfire::Misfire::*; let long = || { @@ -182,7 +182,7 @@ impl TerminalWidth { impl TableOptions { - fn deduce(matches: &Matches) -> Result { + fn deduce(matches: &MatchedFlags) -> Result { Ok(TableOptions { env: Environment::load_all(), time_format: TimeFormat::deduce(matches)?, @@ -208,7 +208,7 @@ impl SizeFormat { /// strings of digits in your head. Changing the format to anything else /// involves the `--binary` or `--bytes` flags, and these conflict with /// each other. - fn deduce(matches: &Matches) -> Result { + fn deduce(matches: &MatchedFlags) -> Result { let binary = matches.has(&flags::BINARY); let bytes = matches.has(&flags::BYTES); @@ -225,7 +225,7 @@ impl SizeFormat { impl TimeFormat { /// Determine how time should be formatted in timestamp columns. - fn deduce(matches: &Matches) -> Result { + fn deduce(matches: &MatchedFlags) -> Result { pub use output::time::{DefaultFormat, ISOFormat}; const STYLES: &[&str] = &["default", "long-iso", "full-iso", "iso"]; @@ -267,7 +267,7 @@ impl TimeTypes { /// It’s valid to show more than one column by passing in more than one /// option, but passing *no* options means that the user just wants to /// see the default set. - fn deduce(matches: &Matches) -> Result { + fn deduce(matches: &MatchedFlags) -> Result { let possible_word = matches.get(&flags::TIME); let modified = matches.has(&flags::MODIFIED); let created = matches.has(&flags::CREATED); @@ -335,7 +335,7 @@ impl Default for TerminalColours { impl TerminalColours { /// Determine which terminal colour conditions to use. - fn deduce(matches: &Matches) -> Result { + fn deduce(matches: &MatchedFlags) -> Result { const COLOURS: &[&str] = &["always", "auto", "never"]; let word = match matches.get(&flags::COLOR).or_else(|| matches.get(&flags::COLOUR)) { @@ -360,7 +360,7 @@ impl TerminalColours { impl Colours { - fn deduce(matches: &Matches) -> Result { + fn deduce(matches: &MatchedFlags) -> Result { use self::TerminalColours::*; let tc = TerminalColours::deduce(matches)?; @@ -377,7 +377,7 @@ impl Colours { impl FileStyle { - fn deduce(matches: &Matches) -> FileStyle { + fn deduce(matches: &MatchedFlags) -> FileStyle { let classify = Classify::deduce(matches); let exts = FileExtensions; FileStyle { classify, exts } @@ -385,7 +385,7 @@ impl FileStyle { } impl Classify { - fn deduce(matches: &Matches) -> Classify { + fn deduce(matches: &MatchedFlags) -> Classify { if matches.has(&flags::CLASSIFY) { Classify::AddFileIndicators } else { Classify::JustFilenames } } @@ -428,7 +428,7 @@ mod test { let bits = $inputs.as_ref().into_iter().map(|&o| os(o)).collect::>(); let results = Args(TEST_ARGS).parse(bits.iter()); - assert_eq!($type::deduce(results.as_ref().unwrap()), $result); + assert_eq!($type::deduce(&results.unwrap().flags), $result); } }; }