Skip to content

Commit 08d7fc7

Browse files
author
wickerwaka
committed
Change how libgetopts handles options grouped together
As soon as an option is found that takes an argument, consume the rest of the string and store it into i_arg. Previously this would only happen if the character after the option was not a recognized option. Addresses issue rust-lang#16348
1 parent 1d12b6d commit 08d7fc7

File tree

1 file changed

+33
-22
lines changed

1 file changed

+33
-22
lines changed

src/libgetopts/lib.rs

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,6 @@ pub fn getopts(args: &[String], optgrps: &[OptGroup]) -> Result {
567567
}
568568
} else {
569569
let mut j = 1;
570-
let mut last_valid_opt_id = None;
571570
names = Vec::new();
572571
while j < curlen {
573572
let range = cur.as_slice().char_range_at(j);
@@ -580,27 +579,24 @@ pub fn getopts(args: &[String], optgrps: &[OptGroup]) -> Result {
580579
interpreted correctly
581580
*/
582581

583-
match find_opt(opts.as_slice(), opt.clone()) {
584-
Some(id) => last_valid_opt_id = Some(id),
585-
None => {
586-
let arg_follows =
587-
last_valid_opt_id.is_some() &&
588-
match opts[last_valid_opt_id.unwrap()]
589-
.hasarg {
590-
591-
Yes | Maybe => true,
592-
No => false
593-
};
594-
if arg_follows && j < curlen {
595-
i_arg = Some(cur.as_slice()
596-
.slice(j, curlen).to_string());
597-
break;
598-
} else {
599-
last_valid_opt_id = None;
600-
}
601-
}
602-
}
582+
let opt_id = match find_opt(opts.as_slice(), opt.clone()) {
583+
Some(id) => id,
584+
None => return Err(UnrecognizedOption(opt.to_string()))
585+
};
586+
603587
names.push(opt);
588+
589+
let arg_follows = match opts[opt_id].hasarg {
590+
Yes | Maybe => true,
591+
No => false
592+
};
593+
594+
if arg_follows && range.next < curlen {
595+
i_arg = Some(cur.as_slice()
596+
.slice(range.next, curlen).to_string());
597+
break;
598+
}
599+
604600
j = range.next;
605601
}
606602
}
@@ -613,7 +609,7 @@ pub fn getopts(args: &[String], optgrps: &[OptGroup]) -> Result {
613609
};
614610
match opts[optid].hasarg {
615611
No => {
616-
if !i_arg.is_none() {
612+
if name_pos == names.len() && !i_arg.is_none() {
617613
return Err(UnexpectedArgument(nm.to_string()));
618614
}
619615
vals.get_mut(optid).push(Given);
@@ -1437,6 +1433,21 @@ mod tests {
14371433

14381434
}
14391435

1436+
#[test]
1437+
fn test_nospace_conflict() {
1438+
let args = vec!("-vvLverbose".to_string(), "-v".to_string() );
1439+
let opts = vec!(optmulti("L", "", "library directory", "LIB"),
1440+
optflagmulti("v", "verbose", "Verbose"));
1441+
let matches = &match getopts(args.as_slice(), opts.as_slice()) {
1442+
result::Ok(m) => m,
1443+
result::Err(e) => fail!( "{}", e )
1444+
};
1445+
assert!(matches.opts_present(["L".to_string()]));
1446+
assert_eq!(matches.opts_str(["L".to_string()]).unwrap(), "verbose".to_string());
1447+
assert!(matches.opts_present(["v".to_string()]));
1448+
assert_eq!(3, matches.opt_count("v"));
1449+
}
1450+
14401451
#[test]
14411452
fn test_long_to_short() {
14421453
let mut short = Opt {

0 commit comments

Comments
 (0)