From 36cf5df044cea9f89bb9569cb6a42f072c12fdea Mon Sep 17 00:00:00 2001 From: Mahmoud Al-Qudsi Date: Wed, 13 Sep 2017 18:48:59 -0500 Subject: [PATCH] Add support for optional argument/flag with optional value TakesValue::Optional introduced which allows for an optional flag with an optional value (equivalent to getopts' optflagopt mode). Can be used where a default value for a modifier could exist, but the user might prefer to override. Will be used to implement #284, permitting --time to default to "sort by modification date" for compatibility with GNU/posix ls but keeping support for exa's previous behavior. --- src/options/parser.rs | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/options/parser.rs b/src/options/parser.rs index 29bd709..a7ce72d 100644 --- a/src/options/parser.rs +++ b/src/options/parser.rs @@ -92,6 +92,9 @@ pub enum TakesValue { /// This flag will throw an error if there’s a value after it. Forbidden, + + /// This flag may be followed by a value to override its defaults + Optional, } @@ -171,7 +174,7 @@ impl Args { let arg = self.lookup_long(before)?; let flag = Flag::Long(arg.long); match arg.takes_value { - Necessary => result_flags.push((flag, Some(after))), + Necessary|Optional => result_flags.push((flag, Some(after))), Forbidden => return Err(ParseError::ForbiddenValue { flag }) } } @@ -190,6 +193,14 @@ impl Args { else { return Err(ParseError::NeedsValue { flag }) } + }, + Optional => { + if let Some(next_arg) = inputs.next() { + result_flags.push((flag, Some(next_arg))); + } + else { + result_flags.push((flag, None)); + } } } } @@ -220,7 +231,7 @@ impl Args { let arg = self.lookup_short(*byte)?; let flag = Flag::Short(*byte); match arg.takes_value { - Forbidden => result_flags.push((flag, None)), + Forbidden|Optional => result_flags.push((flag, None)), Necessary => return Err(ParseError::NeedsValue { flag }) } } @@ -229,7 +240,7 @@ impl Args { let arg = self.lookup_short(*arg_with_value)?; let flag = Flag::Short(arg.short.unwrap()); match arg.takes_value { - Necessary => result_flags.push((flag, Some(after))), + Necessary|Optional => result_flags.push((flag, Some(after))), Forbidden => return Err(ParseError::ForbiddenValue { flag }) } } @@ -252,7 +263,7 @@ impl Args { let flag = Flag::Short(*byte); match arg.takes_value { Forbidden => result_flags.push((flag, None)), - Necessary => { + Necessary|Optional => { if index < bytes.len() - 1 { let remnants = &bytes[index+1 ..]; result_flags.push((flag, Some(OsStr::from_bytes(remnants)))); @@ -262,8 +273,17 @@ impl Args { result_flags.push((flag, Some(next_arg))); } else { - return Err(ParseError::NeedsValue { flag }) + match arg.takes_value { + Forbidden => assert!(false), + Necessary => { + return Err(ParseError::NeedsValue { flag }); + }, + Optional => { + result_flags.push((flag, None)); + } + } } + } } }