about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorJosh Matthews <josh@joshmatthews.net>2012-07-04 11:36:31 -0400
committerBrian Anderson <banderson@mozilla.com>2012-07-04 14:23:22 -0700
commit10fd19580ed1f2caed28e90893f2f4889760265d (patch)
treec4ac948d9d7a043edd616c939e206d7f8f89c0e0 /src/libstd
parent195dd54d61c32ca983b1f81237570e9b0e70abbd (diff)
When getopts encounters an option that takes an argument, it should treat the remainder of the current option string as the argument if it is non-empty. Fix #2791.
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/getopts.rs40
1 files changed, 39 insertions, 1 deletions
diff --git a/src/libstd/getopts.rs b/src/libstd/getopts.rs
index a82d131f516..6ce9ca6072a 100644
--- a/src/libstd/getopts.rs
+++ b/src/libstd/getopts.rs
@@ -220,10 +220,36 @@ fn getopts(args: ~[str], opts: ~[opt]) -> result unsafe {
                 }
             } else {
                 let mut j = 1u;
+                let mut last_valid_opt_id = option::none;
                 names = ~[];
                 while j < curlen {
                     let range = str::char_range_at(cur, j);
-                    vec::push(names, short(range.ch));
+                    let opt = short(range.ch);
+
+                    /* In a series of potential options (eg. -aheJ), if we see
+                       one which takes an argument, we assume all subsequent
+                       characters make up the argument. This allows options
+                       such as -L/usr/local/lib/foo to be interpreted correctly
+                    */
+                    alt find_opt(opts, opt) {
+                      some(id) {
+                        last_valid_opt_id = option::some(id);
+                      }
+                      none {
+                        let arg_follows = option::is_some(last_valid_opt_id) &&
+                            alt opts[option::get(last_valid_opt_id)].hasarg {
+                              yes | maybe { true }
+                              no { false }
+                            };
+                        if arg_follows && j + 1 < curlen {
+                            i_arg = option::some(str::slice(cur, j, curlen));
+                            break;
+                        } else {
+                            last_valid_opt_id = option::none;
+                        }
+                      }
+                    }
+                    vec::push(names, opt);
                     j = range.next;
                 }
             }
@@ -857,6 +883,18 @@ mod tests {
         assert opts_str(match, ~["e", "encrypt"]) == "foo";
         assert opts_str(match, ~["encrypt", "e"]) == "foo";
     }
+
+    #[test]
+    fn test_nospace() {
+        let args = ~["-Lfoo"];
+        let opts = ~[optmulti("L")];
+        let match = alt getopts(args, opts) {
+          result::ok(m) { m }
+          result::err(f) { fail; }
+        };
+        assert opts_present(match, ~["L"]);
+        assert opts_str(match, ~["L"]) == "foo";
+    }
 }
 
 // Local Variables: