Skip to content

Commit dafeae8

Browse files
committed
feat: adds support changing the value delimiter
Closes #353
1 parent d05ed15 commit dafeae8

File tree

7 files changed

+194
-196
lines changed

7 files changed

+194
-196
lines changed

src/app/parser.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1058,7 +1058,7 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {
10581058
where A: AnyArg<'a, 'b> + Display {
10591059
debugln!("fn=add_val_to_arg;");
10601060
let mut ret = None;
1061-
for v in val.split(b',') {
1061+
for v in val.split(arg.val_delim().unwrap_or(',') as u32 as u8) {
10621062
debugln!("adding val: {:?}", v);
10631063
matcher.add_val_to(&*arg.name(), v);
10641064

src/args/any_arg.rs

+1
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ pub trait AnyArg<'n, 'e>: Display {
1919
fn validator(&self) -> Option<&Rc<Fn(String) -> Result<(), String>>>;
2020
fn short(&self) -> Option<char>;
2121
fn long(&self) -> Option<&'e str>;
22+
fn val_delim(&self) -> Option<char>;
2223
}

src/args/arg.rs

+59-26
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ pub struct Arg<'a, 'b> where 'a: 'b {
9090
pub overrides: Option<Vec<&'a str>>,
9191
#[doc(hidden)]
9292
pub settings: ArgFlags,
93+
// Delimiting character for value separation
94+
#[doc(hidden)]
95+
pub val_delim: Option<char>,
9396
}
9497

9598
impl<'a, 'b> Default for Arg<'a, 'b> {
@@ -111,6 +114,7 @@ impl<'a, 'b> Default for Arg<'a, 'b> {
111114
validator: None,
112115
overrides: None,
113116
settings: ArgFlags::new(),
117+
val_delim: Some(','),
114118
}
115119
}
116120
}
@@ -175,6 +179,7 @@ impl<'a, 'b> Arg<'a, 'b> {
175179
"max_values" => a.max_values(v.as_i64().unwrap() as u8),
176180
"min_values" => a.min_values(v.as_i64().unwrap() as u8),
177181
"value_name" => a.value_name(v.as_str().unwrap()),
182+
"value_delimiter" => a.value_delimiter(v.as_str().unwrap()),
178183
"value_names" => {
179184
for ys in v.as_vec().unwrap() {
180185
if let Some(s) = ys.as_str() {
@@ -199,10 +204,10 @@ impl<'a, 'b> Arg<'a, 'b> {
199204
}
200205
a
201206
}
202-
"mutually_overrides_with" => {
207+
"overrides_with" => {
203208
for ys in v.as_vec().unwrap() {
204209
if let Some(s) = ys.as_str() {
205-
a = a.mutually_overrides_with(s);
210+
a = a.overrides_with(s);
206211
}
207212
}
208213
a
@@ -430,9 +435,9 @@ impl<'a, 'b> Arg<'a, 'b> {
430435
/// ```no_run
431436
/// # use clap::{App, Arg};
432437
/// # let myprog = App::new("myprog").arg(Arg::with_name("config")
433-
/// .mutually_overrides_with("debug")
438+
/// .overrides_with("debug")
434439
/// # ).get_matches();
435-
pub fn mutually_overrides_with(mut self, name: &'a str) -> Self {
440+
pub fn overrides_with(mut self, name: &'a str) -> Self {
436441
if let Some(ref mut vec) = self.overrides {
437442
vec.push(name.as_ref());
438443
} else {
@@ -450,9 +455,9 @@ impl<'a, 'b> Arg<'a, 'b> {
450455
/// # use clap::{App, Arg};
451456
/// let config_overrides = ["debug", "input"];
452457
/// # let myprog = App::new("myprog").arg(Arg::with_name("config")
453-
/// .mutually_overrides_with_all(&config_overrides)
458+
/// .overrides_with_all(&config_overrides)
454459
/// # ).get_matches();
455-
pub fn mutually_overrides_with_all(mut self, names: &[&'a str]) -> Self {
460+
pub fn overrides_with_all(mut self, names: &[&'a str]) -> Self {
456461
if let Some(ref mut vec) = self.overrides {
457462
for s in names {
458463
vec.push(s);
@@ -810,31 +815,57 @@ impl<'a, 'b> Arg<'a, 'b> {
810815
self
811816
}
812817

818+
/// Specifies the separator to use when values are clumped together, defaults to `,` (comma).
819+
///
820+
/// **NOTE:** implicitly sets `Arg::takes_value(true)`
821+
///
822+
/// # Examples
823+
///
824+
/// ```no_run
825+
/// # use clap::{App, Arg};
826+
/// let app = App::new("fake")
827+
/// .arg(Arg::with_name("config")
828+
/// .short("c")
829+
/// .long("config")
830+
/// .value_delimiter(";"));
831+
///
832+
/// let m = app.get_matches_from(vec![
833+
/// "fake", "--config=val1;val2;val3"
834+
/// ]);
835+
///
836+
/// assert_eq!(m.values_of("config").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3"])
837+
/// ```
838+
pub fn value_delimiter(mut self, d: &str) -> Self {
839+
self = self.set(ArgSettings::TakesValue);
840+
self.val_delim = Some(d.chars()
841+
.nth(0)
842+
.expect("Failed to get value_delimiter from arg"));
843+
self
844+
}
845+
813846
/// Specifies names for values of option arguments. These names are cosmetic only, used for
814847
/// help and usage strings only. The names are **not** used to access arguments. The values of
815848
/// the arguments are accessed in numeric order (i.e. if you specify two names `one` and `two`
816849
/// `one` will be the first matched value, `two` will be the second).
817850
///
818-
/// **NOTE:** This implicitly sets `.number_of_values()` so there is no need to set that, but
819-
/// be aware that the number of "names" you set for the values, will be the *exact* number of
820-
/// values required to satisfy this argument
851+
/// **NOTE:** This implicitly sets `.number_of_values()`, but be aware that the number of
852+
/// "names" you set for the values, will be the *exact* number of values required to satisfy
853+
/// this argument
821854
///
822-
/// **NOTE:** Does *not* require `.multiple(true)` to be set. Setting `.multiple(true)` would
823-
/// allow `-f <file> <file> <file> -f <file> <file> <file>` where as *not* setting
824-
/// `.multiple(true)` would only allow one occurrence of this argument.
855+
/// **NOTE:** implicitly sets `Arg::takes_value(true)`
856+
///
857+
/// **NOTE:** Does *not* require or imply `.multiple(true)`.
825858
///
826859
/// # Examples
827860
///
828861
/// ```no_run
829862
/// # use clap::{App, Arg};
830-
/// let val_names = ["one", "two"];
831-
/// # let matches = App::new("myprog")
832-
/// # .arg(
833-
/// # Arg::with_name("debug").index(1)
834-
/// // ...
835-
/// .value_names(&val_names)
836-
/// # ).get_matches();
863+
/// Arg::with_name("speed")
864+
/// .short("s")
865+
/// .value_names(&["fast", "slow"])
866+
/// # ;
837867
pub fn value_names(mut self, names: &[&'b str]) -> Self {
868+
self.setb(ArgSettings::TakesValue);
838869
if let Some(ref mut vals) = self.val_names {
839870
let mut l = vals.len();
840871
for s in names {
@@ -878,20 +909,21 @@ impl<'a, 'b> Arg<'a, 'b> {
878909
self
879910
}
880911

881-
/// Specifies the name for value of option or positional arguments. This name is cosmetic only,
882-
/// used for help and usage strings. The name is **not** used to access arguments.
912+
/// Specifies the name for value of option or positional arguments inside of help documenation.
913+
/// This name is cosmetic only, the name is **not** used to access arguments.
914+
///
915+
/// **NOTE:** implicitly sets `Arg::takes_value(true)`
883916
///
884917
/// # Examples
885918
///
886919
/// ```no_run
887920
/// # use clap::{App, Arg};
888-
/// # let matches = App::new("myprog")
889-
/// # .arg(
890-
/// Arg::with_name("debug")
921+
/// Arg::with_name("input")
891922
/// .index(1)
892-
/// .value_name("file")
893-
/// # ).get_matches();
923+
/// .value_name("FILE")
924+
/// # ;
894925
pub fn value_name(mut self, name: &'b str) -> Self {
926+
self.setb(ArgSettings::TakesValue);
895927
if let Some(ref mut vals) = self.val_names {
896928
let l = vals.len();
897929
vals.insert(l, name);
@@ -924,6 +956,7 @@ impl<'a, 'b, 'z> From<&'z Arg<'a, 'b>>
924956
validator: a.validator.clone(),
925957
overrides: a.overrides.clone(),
926958
settings: a.settings.clone(),
959+
val_delim: a.val_delim,
927960
}
928961
}
929962
}

src/args/arg_builder/flag.rs

+2-13
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,14 @@ use args::AnyArg;
1010
use args::settings::{ArgFlags, ArgSettings};
1111

1212
#[derive(Debug)]
13+
#[doc(hidden)]
1314
pub struct FlagBuilder<'n, 'e> {
1415
pub name: &'n str,
15-
/// The long version of the flag (i.e. word)
16-
/// without the preceding `--`
1716
pub long: Option<&'e str>,
18-
/// The string of text that will displayed to
19-
/// the user when the application's `help`
20-
/// text is displayed
2117
pub help: Option<&'e str>,
22-
/// A list of names for other arguments that
23-
/// *may not* be used with this flag
2418
pub blacklist: Option<Vec<&'e str>>,
25-
/// A list of names of other arguments that
26-
/// are *required* to be used when this
27-
/// flag is used
2819
pub requires: Option<Vec<&'e str>>,
29-
/// The short version (i.e. single character)
30-
/// of the argument, no preceding `-`
3120
pub short: Option<char>,
32-
/// A list of names for other arguments that *mutually override* this flag
3321
pub overrides: Option<Vec<&'e str>>,
3422
pub settings: ArgFlags,
3523
}
@@ -192,6 +180,7 @@ impl<'n, 'e> AnyArg<'n, 'e> for FlagBuilder<'n, 'e> {
192180
fn min_vals(&self) -> Option<u8> { None }
193181
fn short(&self) -> Option<char> { self.short }
194182
fn long(&self) -> Option<&'e str> { self.long }
183+
fn val_delim(&self) -> Option<char> { None }
195184
}
196185

197186
#[cfg(test)]

src/args/arg_builder/option.rs

+5-9
Original file line numberDiff line numberDiff line change
@@ -9,30 +9,23 @@ use args::{AnyArg, Arg};
99
use args::settings::{ArgFlags, ArgSettings};
1010

1111
#[allow(missing_debug_implementations)]
12+
#[doc(hidden)]
1213
pub struct OptBuilder<'n, 'e> {
1314
pub name: &'n str,
14-
/// The short version (i.e. single character) of the argument, no preceding `-`
1515
pub short: Option<char>,
16-
/// The long version of the flag (i.e. word) without the preceding `--`
1716
pub long: Option<&'e str>,
18-
/// The string of text that will displayed to the user when the application's
19-
/// `help` text is displayed
2017
pub help: Option<&'e str>,
21-
/// A list of names for other arguments that *may not* be used with this flag
2218
pub blacklist: Option<Vec<&'e str>>,
23-
/// A list of possible values for this argument
2419
pub possible_vals: Option<Vec<&'e str>>,
25-
/// A list of names of other arguments that are *required* to be used when
26-
/// this flag is used
2720
pub requires: Option<Vec<&'e str>>,
2821
pub num_vals: Option<u8>,
2922
pub min_vals: Option<u8>,
3023
pub max_vals: Option<u8>,
3124
pub val_names: Option<VecMap<&'e str>>,
3225
pub validator: Option<Rc<Fn(String) -> StdResult<(), String>>>,
33-
/// A list of names for other arguments that *mutually override* this flag
3426
pub overrides: Option<Vec<&'e str>>,
3527
pub settings: ArgFlags,
28+
pub val_delim: Option<char>,
3629
}
3730

3831
impl<'n, 'e> Default for OptBuilder<'n, 'e> {
@@ -52,6 +45,7 @@ impl<'n, 'e> Default for OptBuilder<'n, 'e> {
5245
validator: None,
5346
overrides: None,
5447
settings: ArgFlags::new(),
48+
val_delim: Some(','),
5549
}
5650
}
5751
}
@@ -81,6 +75,7 @@ impl<'n, 'e> OptBuilder<'n, 'e> {
8175
min_vals: a.min_vals,
8276
max_vals: a.max_vals,
8377
val_names: a.val_names.clone(),
78+
val_delim: a.val_delim,
8479
..Default::default()
8580
};
8681
if a.is_set(ArgSettings::Multiple) {
@@ -253,6 +248,7 @@ impl<'n, 'e> AnyArg<'n, 'e> for OptBuilder<'n, 'e> {
253248
fn min_vals(&self) -> Option<u8> { self.min_vals }
254249
fn short(&self) -> Option<char> { self.short }
255250
fn long(&self) -> Option<&'e str> { self.long }
251+
fn val_delim(&self) -> Option<char> { self.val_delim }
256252
}
257253

258254
#[cfg(test)]

src/args/arg_builder/positional.rs

+11-22
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,29 @@ use std::result::Result as StdResult;
33
use std::rc::Rc;
44
use std::io;
55

6+
use vec_map::VecMap;
7+
68
use Arg;
79
use args::AnyArg;
810
use args::settings::{ArgFlags, ArgSettings};
911

1012
#[allow(missing_debug_implementations)]
13+
#[doc(hidden)]
1114
pub struct PosBuilder<'n, 'e> {
1215
pub name: &'n str,
13-
/// The string of text that will displayed to the user when the application's
14-
/// `help` text is displayed
1516
pub help: Option<&'e str>,
16-
/// A list of names of other arguments that are *required* to be used when
17-
/// this flag is used
1817
pub requires: Option<Vec<&'e str>>,
19-
/// A list of names for other arguments that *may not* be used with this flag
2018
pub blacklist: Option<Vec<&'e str>>,
21-
/// A list of possible values for this argument
2219
pub possible_vals: Option<Vec<&'e str>>,
23-
/// The index of the argument
2420
pub index: u8,
2521
pub num_vals: Option<u8>,
2622
pub max_vals: Option<u8>,
2723
pub min_vals: Option<u8>,
24+
pub val_names: Option<VecMap<&'e str>>,
2825
pub validator: Option<Rc<Fn(String) -> StdResult<(), String>>>,
29-
/// A list of names for other arguments that *mutually override* this flag
3026
pub overrides: Option<Vec<&'e str>>,
3127
pub settings: ArgFlags,
28+
pub val_delim: Option<char>,
3229
}
3330

3431
impl<'n, 'e> Default for PosBuilder<'n, 'e> {
@@ -41,11 +38,13 @@ impl<'n, 'e> Default for PosBuilder<'n, 'e> {
4138
possible_vals: None,
4239
index: 0,
4340
num_vals: None,
44-
max_vals: None,
4541
min_vals: None,
42+
max_vals: None,
43+
val_names: None,
4644
validator: None,
4745
overrides: None,
4846
settings: ArgFlags::new(),
47+
val_delim: Some(','),
4948
}
5049
}
5150
}
@@ -66,19 +65,6 @@ impl<'n, 'e> PosBuilder<'n, 'e> {
6665
a.name);
6766
}
6867

69-
if a.is_set(ArgSettings::TakesValue) {
70-
panic!("Argument \"{}\" has conflicting requirements, both index() and \
71-
takes_value(true) were supplied\n\n\tArguments with an index automatically \
72-
take a value, you do not need to specify it manually",
73-
a.name);
74-
}
75-
76-
if a.val_names.is_some() {
77-
panic!("Positional arguments (\"{}\") do not support named values, instead \
78-
consider multiple positional arguments",
79-
a.name);
80-
}
81-
8268
// Create the Positional Argument Builder with each HashSet = None to only
8369
// allocate
8470
// those that require it
@@ -88,7 +74,9 @@ impl<'n, 'e> PosBuilder<'n, 'e> {
8874
num_vals: a.num_vals,
8975
min_vals: a.min_vals,
9076
max_vals: a.max_vals,
77+
val_names: a.val_names.clone(),
9178
help: a.help,
79+
val_delim: a.val_delim,
9280
..Default::default()
9381
};
9482
if a.is_set(ArgSettings::Multiple) || a.num_vals.is_some() || a.max_vals.is_some() || a.min_vals.is_some() {
@@ -204,6 +192,7 @@ impl<'n, 'e> AnyArg<'n, 'e> for PosBuilder<'n, 'e> {
204192
fn min_vals(&self) -> Option<u8> { self.min_vals }
205193
fn short(&self) -> Option<char> { None }
206194
fn long(&self) -> Option<&'e str> { None }
195+
fn val_delim(&self) -> Option<char> { self.val_delim }
207196
}
208197

209198
#[cfg(test)]

0 commit comments

Comments
 (0)