Skip to content

Revert #81, #82, #83 #84

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 1 commit into from
Aug 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 38 additions & 44 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ impl Options {
.ok_or_else(|| Fail::UnrecognizedOption(format!("{:?}", i.as_ref())))
.map(|s| s.to_owned())
}).collect::<::std::result::Result<Vec<_>, _>>()?;
let mut args = args.into_iter().peekable();
let mut args = args.into_iter();
let mut arg_pos = 0;
while let Some(cur) = args.next() {
if !is_arg(&cur) {
Expand All @@ -380,9 +380,8 @@ impl Options {
free.extend(args);
break;
} else {
let mut names;
let mut name = None;
let mut i_arg = None;
let mut was_long = true;
if cur.as_bytes()[1] == b'-' || self.long_only {
let tail = if cur.as_bytes()[1] == b'-' {
&cur[2..]
Expand All @@ -391,81 +390,71 @@ impl Options {
&cur[1..]
};
let mut parts = tail.splitn(2, '=');
names = vec![Name::from_str(parts.next().unwrap())];
name = Some(Name::from_str(parts.next().unwrap()));
if let Some(rest) = parts.next() {
i_arg = Some(rest.to_string());
}
} else {
was_long = false;
names = Vec::new();
for (j, ch) in cur.char_indices().skip(1) {
let opt = Short(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
*/

let opt_id = match find_opt(&opts, &opt) {
Some(id) => id,
None => return Err(UnrecognizedOption(opt.to_string())),
};

names.push(opt);

// 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
let arg_follows = match opts[opt_id].hasarg {
Yes | Maybe => true,
No => false,
};

if arg_follows {
name = Some(opt);
let next = j + ch.len_utf8();
if next < cur.len() {
i_arg = Some(cur[next..].to_string());
break;
}
} else {
vals[opt_id].push((arg_pos, Given));
}
}
}
let mut name_pos = 0;
for nm in names.iter() {
name_pos += 1;
let optid = match find_opt(&opts, &nm) {
if let Some(nm) = name {
let opt_id = match find_opt(&opts, &nm) {
Some(id) => id,
None => return Err(UnrecognizedOption(nm.to_string())),
};
match opts[optid].hasarg {
match opts[opt_id].hasarg {
No => {
if name_pos == names.len() && i_arg.is_some() {
if i_arg.is_some() {
return Err(UnexpectedArgument(nm.to_string()));
}
vals[optid].push((arg_pos, Given));
vals[opt_id].push((arg_pos, Given));
}
Maybe => {
// Note that here we do not handle `--arg value`.
// This matches GNU getopt behavior; but also
// makes sense, because if this were accepted,
// then users could only write a "Maybe" long
// option at the end of the arguments when
// FloatingFrees is in use.
// Note that here we do not handle `--arg value` or
// `-a value`. This matches GNU getopt behavior; but
// also makes sense, because if this were accepted,
// then users could only write a "Maybe" option at
// the end of the arguments when FloatingFrees is in
// use.
if let Some(i_arg) = i_arg.take() {
vals[optid].push((arg_pos, Val(i_arg)));
} else if was_long
|| name_pos < names.len()
|| args.peek().map_or(true, |n| is_arg(&n))
{
vals[optid].push((arg_pos, Given));
vals[opt_id].push((arg_pos, Val(i_arg)));
} else {
vals[optid].push((arg_pos, Val(args.next().unwrap())));
vals[opt_id].push((arg_pos, Given));
}
}
Yes => {
if let Some(i_arg) = i_arg.take() {
vals[optid].push((arg_pos, Val(i_arg)));
vals[opt_id].push((arg_pos, Val(i_arg)));
} else if let Some(n) = args.next() {
vals[optid].push((arg_pos, Val(n)));
vals[opt_id].push((arg_pos, Val(n)));
} else {
return Err(ArgumentMissing(nm.to_string()));
}
Expand Down Expand Up @@ -551,10 +540,6 @@ impl Options {
row.push_str(&short_name);
if long_name.width() > 0 {
row.push_str(", ");
} else {
// Only a single space here, so that any
// argument is printed in the correct spot.
row.push(' ');
}
}
// FIXME: refer issue #7.
Expand All @@ -567,16 +552,21 @@ impl Options {
_ => {
row.push_str(if self.long_only { "-" } else { "--" });
row.push_str(&long_name);
row.push(' ');
}
}

// arg
match hasarg {
No => {}
Yes => row.push_str(&hint),
Yes => {
row.push(' ');
row.push_str(&hint);
}
Maybe => {
row.push('[');
if !long_name.is_empty() {
row.push('=');
}
row.push_str(&hint);
row.push(']');
}
Expand Down Expand Up @@ -979,9 +969,13 @@ fn format_option(opt: &OptGroup) -> String {
}

if opt.hasarg != No {
line.push(' ');
if opt.hasarg == Maybe {
line.push('[');
if opt.short_name.is_empty() {
line.push('=');
}
} else {
line.push(' ');
}
line.push_str(&opt.hint);
if opt.hasarg == Maybe {
Expand Down
39 changes: 22 additions & 17 deletions src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,8 +379,8 @@ fn test_optflagopt() {
let short_args = vec!["-t".to_string(), "x".to_string()];
match opts.parse(&short_args) {
Ok(ref m) => {
assert_eq!(m.opt_str("t").unwrap(), "x");
assert_eq!(m.opt_str("test").unwrap(), "x");
assert_eq!(m.opt_str("t"), None);
assert_eq!(m.opt_str("test"), None);
}
_ => panic!(),
}
Expand Down Expand Up @@ -763,6 +763,8 @@ fn test_usage() {
opts.optopt("a", "012345678901234567890123456789", "Desc", "VAL");
opts.optflag("k", "kiwi", "Desc");
opts.optflagopt("p", "", "Desc", "VAL");
opts.optflagopt("", "pea", "Desc", "VAL");
opts.optflagopt("c", "cherry", "Desc", "VAL");
opts.optmulti("l", "", "Desc", "VAL");
opts.optflag("", "starfruit", "Starfruit");

Expand All @@ -773,7 +775,9 @@ Options:
-a, --012345678901234567890123456789 VAL
Desc
-k, --kiwi Desc
-p [VAL] Desc
-p[VAL] Desc
--pea[=VAL] Desc
-c, --cherry[=VAL] Desc
-l VAL Desc
--starfruit Starfruit
";
Expand Down Expand Up @@ -820,7 +824,7 @@ Options:

debug!("expected: <<{}>>", expected);
debug!("generated: <<{}>>", usage);
assert!(usage == expected)
assert_eq!(usage, expected)
}

#[test]
Expand Down Expand Up @@ -851,7 +855,7 @@ Options:

debug!("expected: <<{}>>", expected);
debug!("generated: <<{}>>", usage);
assert!(usage == expected)
assert_eq!(usage, expected)
}

#[test]
Expand Down Expand Up @@ -882,7 +886,7 @@ Options:

debug!("expected: <<{}>>", expected);
debug!("generated: <<{}>>", usage);
assert!(usage == expected)
assert_eq!(usage, expected)
}

#[test]
Expand All @@ -909,7 +913,7 @@ Options:
-c, --brûlée brûlée quite long description
-k, --kiwi€ kiwi description
-o, --orange‹ orange description
-r, --raspberry-but-making-this-option-way-too-long\u{0020}
-r, --raspberry-but-making-this-option-way-too-long
raspberry description is also quite long indeed longer
than every other piece of text we might encounter here
and thus will be automatically broken up
Expand All @@ -919,7 +923,7 @@ Options:

debug!("expected: <<{}>>", expected);
debug!("generated: <<{}>>", usage);
assert!(usage == expected)
assert_eq!(usage, expected)
}

#[test]
Expand All @@ -934,13 +938,13 @@ fn test_usage_short_only() {
Options:
-k VAL Kiwi
-s Starfruit
-a [TYPE] Apple
-a[TYPE] Apple
";

let usage = opts.usage("Usage: fruits");
debug!("expected: <<{}>>", expected);
debug!("generated: <<{}>>", usage);
assert!(usage == expected)
assert_eq!(usage, expected)
}

#[test]
Expand All @@ -955,13 +959,13 @@ fn test_usage_long_only() {
Options:
--kiwi VAL Kiwi
--starfruit Starfruit
--apple [TYPE] Apple
--apple[=TYPE] Apple
";

let usage = opts.usage("Usage: fruits");
debug!("expected: <<{}>>", expected);
debug!("generated: <<{}>>", usage);
assert!(usage == expected)
assert_eq!(usage, expected)
}

#[test]
Expand All @@ -971,9 +975,10 @@ fn test_short_usage() {
opts.optopt("a", "012345678901234567890123456789", "Desc", "VAL");
opts.optflag("k", "kiwi", "Desc");
opts.optflagopt("p", "", "Desc", "VAL");
opts.optmulti("l", "", "Desc", "VAL");
opts.optflagopt("", "pea", "Desc", "VAL");
opts.optflagopt("c", "cherry", "Desc", "VAL");

let expected = "Usage: fruits -b VAL [-a VAL] [-k] [-p [VAL]] [-l VAL]..".to_string();
let expected = "Usage: fruits -b VAL [-a VAL] [-k] [-p[VAL]] [--pea[=VAL]] [-c[VAL]]".to_string();
let generated_usage = opts.short_usage("fruits");

debug!("expected: <<{}>>", expected);
Expand Down Expand Up @@ -1026,7 +1031,7 @@ Options:

debug!("expected: <<{}>>", expected);
debug!("generated: <<{}>>", usage);
assert!(usage == expected)
assert_eq!(usage, expected)
}

#[test]
Expand Down Expand Up @@ -1148,7 +1153,7 @@ fn test_opt_get() {
opts.optflagopt("p", "percent", "Description", "0.0 .. 10.0");
opts.long_only(false);

let args: Vec<String> = ["-i", "true", "-p", "1.1"]
let args: Vec<String> = ["--ignore=true", "-p1.1"]
.iter()
.map(|x| x.to_string())
.collect();
Expand All @@ -1173,7 +1178,7 @@ fn test_opt_get_default() {
opts.optflagopt("p", "percent", "Description", "0.0 .. 10.0");
opts.long_only(false);

let args: Vec<String> = ["-i", "true", "-p", "1.1"]
let args: Vec<String> = ["--ignore=true", "-p1.1"]
.iter()
.map(|x| x.to_string())
.collect();
Expand Down