Преглед на файлове

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.
Mahmoud Al-Qudsi преди 8 години
родител
ревизия
36cf5df044
променени са 1 файла, в които са добавени 25 реда и са изтрити 5 реда
  1. 25 5
      src/options/parser.rs

+ 25 - 5
src/options/parser.rs

@@ -92,6 +92,9 @@ pub enum TakesValue {
 
 
     /// This flag will throw an error if there’s a value after it.
     /// This flag will throw an error if there’s a value after it.
     Forbidden,
     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 arg = self.lookup_long(before)?;
                     let flag = Flag::Long(arg.long);
                     let flag = Flag::Long(arg.long);
                     match arg.takes_value {
                     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 })
                         Forbidden  => return Err(ParseError::ForbiddenValue { flag })
                     }
                     }
                 }
                 }
@@ -190,6 +193,14 @@ impl Args {
                             else {
                             else {
                                 return Err(ParseError::NeedsValue { flag })
                                 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 arg = self.lookup_short(*byte)?;
                         let flag = Flag::Short(*byte);
                         let flag = Flag::Short(*byte);
                         match arg.takes_value {
                         match arg.takes_value {
-                            Forbidden  => result_flags.push((flag, None)),
+                            Forbidden|Optional  => result_flags.push((flag, None)),
                             Necessary  => return Err(ParseError::NeedsValue { flag })
                             Necessary  => return Err(ParseError::NeedsValue { flag })
                         }
                         }
                     }
                     }
@@ -229,7 +240,7 @@ impl Args {
                     let arg = self.lookup_short(*arg_with_value)?;
                     let arg = self.lookup_short(*arg_with_value)?;
                     let flag = Flag::Short(arg.short.unwrap());
                     let flag = Flag::Short(arg.short.unwrap());
                     match arg.takes_value {
                     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 })
                         Forbidden  => return Err(ParseError::ForbiddenValue { flag })
                     }
                     }
                 }
                 }
@@ -252,7 +263,7 @@ impl Args {
                         let flag = Flag::Short(*byte);
                         let flag = Flag::Short(*byte);
                         match arg.takes_value {
                         match arg.takes_value {
                             Forbidden  => result_flags.push((flag, None)),
                             Forbidden  => result_flags.push((flag, None)),
-                            Necessary  => {
+                            Necessary|Optional  => {
                                 if index < bytes.len() - 1 {
                                 if index < bytes.len() - 1 {
                                     let remnants = &bytes[index+1 ..];
                                     let remnants = &bytes[index+1 ..];
                                     result_flags.push((flag, Some(OsStr::from_bytes(remnants))));
                                     result_flags.push((flag, Some(OsStr::from_bytes(remnants))));
@@ -262,8 +273,17 @@ impl Args {
                                     result_flags.push((flag, Some(next_arg)));
                                     result_flags.push((flag, Some(next_arg)));
                                 }
                                 }
                                 else {
                                 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));
+                                        }
+                                    }
                                 }
                                 }
+
                             }
                             }
                         }
                         }
                     }
                     }