Skip to content

Commit ad55748

Browse files
committed
feat(from_usage): adds ability to add value names or num of vals in usage string
Allows new usage strings with value names or number of values. If the names are consecutive, they are counted to represent the number of values (if they all have the same name), or if their names are different they are used as value names. Closes #98
1 parent a87d970 commit ad55748

File tree

2 files changed

+249
-16
lines changed

2 files changed

+249
-16
lines changed

src/args/arg.rs

Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::iter::IntoIterator;
2+
use std::collections::HashSet;
23

34
use usageparser::{UsageParser, UsageToken};
45

@@ -79,7 +80,7 @@ pub struct Arg<'n, 'l, 'h, 'g, 'p, 'r> {
7980
#[doc(hidden)]
8081
pub group: Option<&'g str>,
8182
#[doc(hidden)]
82-
pub val_names: Option<Vec<&'p str>>,
83+
pub val_names: Option<Vec<&'n str>>,
8384
#[doc(hidden)]
8485
pub num_vals: Option<u8>,
8586
#[doc(hidden)]
@@ -229,34 +230,57 @@ impl<'n, 'l, 'h, 'g, 'p, 'r> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
229230
let mut required = false;
230231
let mut takes_value = false;
231232
let mut multiple = false;
233+
let mut num_names = 1;
234+
let mut name_first = false;
235+
let mut consec_names = false;
236+
let mut val_names = HashSet::new();
232237

233238
let parser = UsageParser::with_usage(u);
234239
for_match!{ parser,
235240
UsageToken::Name(n, req) => {
236-
if name.is_none() {
241+
if consec_names {
242+
num_names += 1;
243+
}
244+
let mut use_req = false;
245+
let mut use_name = false;
246+
if name.is_none() && long.is_none() && short.is_none() {
247+
name_first = true;
248+
use_name = true;
249+
use_req = true;
250+
} else if let Some(l) = long {
251+
if l == name.unwrap_or("") {
252+
if !name_first {
253+
use_name = true;
254+
use_req = true;
255+
}
256+
}
257+
} else {
258+
// starting with short
259+
if !name_first {
260+
use_name = true;
261+
use_req = true;
262+
}
263+
}
264+
if use_name && !consec_names {
237265
name = Some(n);
266+
}
267+
if use_req && !consec_names {
238268
if let Some(r) = req {
239269
required = r;
240270
}
241-
} else if let Some(l) = long {
242-
if l == name.unwrap() {
243-
if let Some(r) = req {
244-
required = r;
245-
}
246-
name = Some(n);
247-
} else if n != l {
248-
name = Some(n);
249-
}
250-
251271
}
252272
if short.is_some() || long.is_some() {
273+
val_names.insert(n);
253274
takes_value = true;
254275
}
276+
consec_names = true;
255277
},
256278
UsageToken::Short(s) => {
279+
consec_names = false;
257280
short = Some(s);
258281
},
259282
UsageToken::Long(l) => {
283+
consec_names = false;
260284
long = Some(l);
261285
if name.is_none() {
262286
name = Some(l);
@@ -270,6 +294,15 @@ impl<'n, 'l, 'h, 'g, 'p, 'r> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
270294
}
271295
}
272296

297+
if let Some(l) = long {
298+
val_names.remove(l);
299+
if val_names.len() > 1 {
300+
if name.unwrap() != l && !name_first {
301+
name = Some(l);
302+
}
303+
}
304+
}
305+
273306
Arg {
274307
name: name.unwrap(),
275308
short: short,
@@ -282,8 +315,8 @@ impl<'n, 'l, 'h, 'g, 'p, 'r> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
282315
possible_vals: None,
283316
blacklist: None,
284317
requires: None,
285-
num_vals: None,
286-
val_names: None,
318+
num_vals: if num_names > 1 { Some(num_names) } else { None },
319+
val_names: if val_names.len() > 1 {Some(val_names.iter().map(|s| *s).collect::<Vec<_>>())}else{None},
287320
max_vals: None,
288321
min_vals: None,
289322
group: None,
@@ -765,8 +798,8 @@ impl<'n, 'l, 'h, 'g, 'p, 'r> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
765798
/// # ).get_matches();
766799
pub fn value_names<T, I>(mut self, names: I)
767800
-> Arg<'n, 'l, 'h, 'g, 'p, 'r>
768-
where T: AsRef<str> + 'p,
769-
I: IntoIterator<Item=&'p T> {
801+
where T: AsRef<str> + 'n,
802+
I: IntoIterator<Item=&'n T> {
770803
if let Some(ref mut vec) = self.val_names {
771804
names.into_iter().map(|s| vec.push(s.as_ref())).collect::<Vec<_>>();
772805
} else {

0 commit comments

Comments
 (0)