Skip to content

Commit 7b37730

Browse files
committed
Make short flags with a single-char arg work in getopts
This looks like a big patch, but it's mostly just modernization. The real change is in the fn called `getopts`, the line if arg_follows && j < curlen { Minor bugfix, no review. Closes #2822
1 parent 98fdcb0 commit 7b37730

File tree

1 file changed

+37
-34
lines changed

1 file changed

+37
-34
lines changed

src/libstd/getopts.rs

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
* Single-character options are expected to appear on the command line with a
2222
* single preceding dash; multiple-character options are expected to be
2323
* proceeded by two dashes. Options that expect an argument accept their
24-
* argument following either a space or an equals sign.
24+
* argument following either a space or an equals sign. Single-character
25+
* options don't require the space.
2526
*
2627
* # Example
2728
*
@@ -203,7 +204,7 @@ impl Matches : Eq {
203204
}
204205

205206
fn is_arg(arg: &str) -> bool {
206-
return arg.len() > 1u && arg[0] == '-' as u8;
207+
return arg.len() > 1 && arg[0] == '-' as u8;
207208
}
208209

209210
fn name_str(nm: &Name) -> ~str {
@@ -293,38 +294,37 @@ pub type Result = result::Result<Matches, Fail_>;
293294
* Use <fail_str> to get an error message.
294295
*/
295296
pub fn getopts(args: &[~str], opts: &[Opt]) -> Result unsafe {
296-
let n_opts = vec::len::<Opt>(opts);
297+
let n_opts = opts.len();
297298
fn f(_x: uint) -> ~[Optval] { return ~[]; }
298299
let vals = vec::to_mut(vec::from_fn(n_opts, f));
299300
let mut free: ~[~str] = ~[];
300-
let l = vec::len(args);
301-
let mut i = 0u;
301+
let l = args.len();
302+
let mut i = 0;
302303
while i < l {
303304
let cur = args[i];
304305
let curlen = cur.len();
305306
if !is_arg(cur) {
306307
free.push(cur);
307308
} else if cur == ~"--" {
308-
let mut j = i + 1u;
309-
while j < l { free.push(args[j]); j += 1u; }
309+
let mut j = i + 1;
310+
while j < l { free.push(args[j]); j += 1; }
310311
break;
311312
} else {
312313
let mut names;
313-
let mut i_arg = option::None::<~str>;
314+
let mut i_arg = None;
314315
if cur[1] == '-' as u8 {
315-
let tail = str::slice(cur, 2u, curlen);
316-
let tail_eq = str::splitn_char(tail, '=', 1u);
317-
if vec::len(tail_eq) <= 1u {
316+
let tail = str::slice(cur, 2, curlen);
317+
let tail_eq = str::splitn_char(tail, '=', 1);
318+
if tail_eq.len() <= 1 {
318319
names = ~[Long(tail)];
319320
} else {
320321
names =
321322
~[Long(tail_eq[0])];
322-
i_arg =
323-
option::Some::<~str>(tail_eq[1]);
323+
i_arg = Some(tail_eq[1]);
324324
}
325325
} else {
326-
let mut j = 1u;
327-
let mut last_valid_opt_id = option::None;
326+
let mut j = 1;
327+
let mut last_valid_opt_id = None;
328328
names = ~[];
329329
while j < curlen {
330330
let range = str::char_range_at(cur, j);
@@ -338,7 +338,7 @@ pub fn getopts(args: &[~str], opts: &[Opt]) -> Result unsafe {
338338
*/
339339
340340
match find_opt(opts, opt) {
341-
Some(id) => last_valid_opt_id = option::Some(id),
341+
Some(id) => last_valid_opt_id = Some(id),
342342
None => {
343343
let arg_follows =
344344
last_valid_opt_id.is_some() &&
@@ -348,21 +348,21 @@ pub fn getopts(args: &[~str], opts: &[Opt]) -> Result unsafe {
348348
Yes | Maybe => true,
349349
No => false
350350
};
351-
if arg_follows && j + 1 < curlen {
352-
i_arg = option::Some(str::slice(cur, j, curlen));
351+
if arg_follows && j < curlen {
352+
i_arg = Some(cur.slice(j, curlen));
353353
break;
354354
} else {
355-
last_valid_opt_id = option::None;
355+
last_valid_opt_id = None;
356356
}
357357
}
358358
}
359359
names.push(opt);
360360
j = range.next;
361361
}
362362
}
363-
let mut name_pos = 0u;
364-
for vec::each(names) |nm| {
365-
name_pos += 1u;
363+
let mut name_pos = 0;
364+
for names.each() |nm| {
365+
name_pos += 1;
366366
let optid = match find_opt(opts, *nm) {
367367
Some(id) => id,
368368
None => return Err(UnrecognizedOption(name_str(nm)))
@@ -377,38 +377,38 @@ pub fn getopts(args: &[~str], opts: &[Opt]) -> Result unsafe {
377377
Maybe => {
378378
if !i_arg.is_none() {
379379
vals[optid].push(Val(i_arg.get()));
380-
} else if name_pos < vec::len::<Name>(names) ||
381-
i + 1u == l || is_arg(args[i + 1u]) {
380+
} else if name_pos < names.len() ||
381+
i + 1 == l || is_arg(args[i + 1]) {
382382
vals[optid].push(Given);
383-
} else { i += 1u; vals[optid].push(Val(args[i])); }
383+
} else { i += 1; vals[optid].push(Val(args[i])); }
384384
}
385385
Yes => {
386386
if !i_arg.is_none() {
387387
vals[optid].push(Val(i_arg.get()));
388-
} else if i + 1u == l {
388+
} else if i + 1 == l {
389389
return Err(ArgumentMissing(name_str(nm)));
390-
} else { i += 1u; vals[optid].push(Val(args[i])); }
390+
} else { i += 1; vals[optid].push(Val(args[i])); }
391391
}
392392
}
393393
}
394394
}
395-
i += 1u;
395+
i += 1;
396396
}
397397
i = 0u;
398398
while i < n_opts {
399-
let n = vec::len::<Optval>(vals[i]);
399+
let n = vals[i].len();
400400
let occ = opts[i].occur;
401401
if occ == Req {
402-
if n == 0u {
402+
if n == 0 {
403403
return Err(OptionMissing(name_str(&(opts[i].name))));
404404
}
405405
}
406406
if occ != Multi {
407-
if n > 1u {
407+
if n > 1 {
408408
return Err(OptionDuplicated(name_str(&(opts[i].name))));
409409
}
410410
}
411-
i += 1u;
411+
i += 1;
412412
}
413413
return Ok({opts: vec::from_slice(opts),
414414
vals: vec::from_mut(move vals),
@@ -1275,14 +1275,17 @@ mod tests {
12751275
12761276
#[test]
12771277
fn test_nospace() {
1278-
let args = ~[~"-Lfoo"];
1279-
let opts = ~[optmulti(~"L")];
1278+
let args = ~[~"-Lfoo", ~"-M."];
1279+
let opts = ~[optmulti(~"L"), optmulti(~"M")];
12801280
let matches = &match getopts(args, opts) {
12811281
result::Ok(move m) => m,
12821282
result::Err(_) => fail
12831283
};
12841284
assert opts_present(matches, ~[~"L"]);
12851285
assert opts_str(matches, ~[~"L"]) == ~"foo";
1286+
assert opts_present(matches, ~[~"M"]);
1287+
assert opts_str(matches, ~[~"M"]) == ~".";
1288+
12861289
}
12871290
12881291
#[test]

0 commit comments

Comments
 (0)