mirror of
https://github.com/clap-rs/clap
synced 2024-12-14 06:42:33 +00:00
feat(Settings): adds new setting to stop delimiting values with -- or TrailingVarArg
One can now use `AppSettings::DontDelimitTrailingValues` to stop clap's default behavior of delimiting values, even when `--` or `TrailingVarArg` is used. This is useful when passing other flags and commands through to another program. Closes #511
This commit is contained in:
parent
7db45f78d8
commit
fc3e0f5afd
3 changed files with 71 additions and 44 deletions
|
@ -112,27 +112,26 @@ macro_rules! parse_positional {
|
|||
$_self:ident,
|
||||
$p:ident,
|
||||
$arg_os:ident,
|
||||
$pos_only:ident,
|
||||
$pos_counter:ident,
|
||||
$matcher:ident
|
||||
) => {
|
||||
debugln!("macro=parse_positional!;");
|
||||
validate_multiples!($_self, $p, $matcher);
|
||||
|
||||
if let Err(e) = $_self.add_val_to_arg($p, &$arg_os, $matcher) {
|
||||
return Err(e);
|
||||
}
|
||||
if !$pos_only &&
|
||||
if !$_self.trailing_vals &&
|
||||
($_self.settings.is_set(AppSettings::TrailingVarArg) &&
|
||||
$pos_counter == $_self.positionals.len()) {
|
||||
$pos_only = true;
|
||||
$_self.trailing_vals = true;
|
||||
}
|
||||
if let Err(e) = $_self.add_val_to_arg($p, &$arg_os, $matcher) {
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
$matcher.inc_occurrence_of($p.name);
|
||||
let _ = $_self.groups_for_arg($p.name)
|
||||
.and_then(|vec| Some($matcher.inc_occurrences_of(&*vec)));
|
||||
arg_post_processing!($_self, $p, $matcher);
|
||||
// Only increment the positional counter if it doesn't allow multiples
|
||||
// Only increment the positional counter if it doesn't allow multiples
|
||||
if !$p.settings.is_set(ArgSettings::Multiple) {
|
||||
$pos_counter += 1;
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ pub struct Parser<'a, 'b>
|
|||
settings: AppFlags,
|
||||
pub g_settings: Vec<AppSettings>,
|
||||
pub meta: AppMeta<'b>,
|
||||
trailing_vals: bool,
|
||||
}
|
||||
|
||||
impl<'a, 'b> Default for Parser<'a, 'b> {
|
||||
|
@ -72,6 +73,7 @@ impl<'a, 'b> Default for Parser<'a, 'b> {
|
|||
g_settings: vec![],
|
||||
settings: AppFlags::new(),
|
||||
meta: AppMeta::new(),
|
||||
trailing_vals: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -456,7 +458,6 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
// necessary
|
||||
self.create_help_and_version();
|
||||
|
||||
let mut pos_only = false;
|
||||
let mut subcmd_name: Option<String> = None;
|
||||
let mut needs_val_of: Option<&str> = None;
|
||||
let mut pos_counter = 1;
|
||||
|
@ -475,7 +476,7 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
};
|
||||
|
||||
// Has the user already passed '--'?
|
||||
if !pos_only {
|
||||
if !self.trailing_vals {
|
||||
// Does the arg match a subcommand name, or any of it's aliases (if defined)
|
||||
let pos_sc = self.subcommands
|
||||
.iter()
|
||||
|
@ -501,7 +502,7 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
if arg_os.len_() == 2 {
|
||||
// The user has passed '--' which means only positional args follow no
|
||||
// matter what they start with
|
||||
pos_only = true;
|
||||
self.trailing_vals = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -564,7 +565,7 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
}
|
||||
|
||||
if let Some(p) = self.positionals.get(pos_counter) {
|
||||
parse_positional!(self, p, arg_os, pos_only, pos_counter, matcher);
|
||||
parse_positional!(self, p, arg_os, pos_counter, matcher);
|
||||
} else {
|
||||
if self.settings.is_set(AppSettings::AllowExternalSubcommands) {
|
||||
let mut sc_m = ArgMatcher::new();
|
||||
|
@ -1131,13 +1132,17 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
{
|
||||
debugln!("fn=add_val_to_arg;");
|
||||
let mut ret = None;
|
||||
if let Some(delim) = arg.val_delim() {
|
||||
if val.is_empty_() {
|
||||
ret = try!(self.add_single_val_to_arg(arg, val, matcher));
|
||||
} else {
|
||||
for v in val.split(delim as u32 as u8) {
|
||||
ret = try!(self.add_single_val_to_arg(arg, v, matcher));
|
||||
if !(self.trailing_vals && self.is_set(AppSettings::DontDelimitTrailingValues)) {
|
||||
if let Some(delim) = arg.val_delim() {
|
||||
if val.is_empty_() {
|
||||
ret = try!(self.add_single_val_to_arg(arg, val, matcher));
|
||||
} else {
|
||||
for v in val.split(delim as u32 as u8) {
|
||||
ret = try!(self.add_single_val_to_arg(arg, v, matcher));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ret = try!(self.add_single_val_to_arg(arg, val, matcher));
|
||||
}
|
||||
} else {
|
||||
ret = try!(self.add_single_val_to_arg(arg, val, matcher));
|
||||
|
@ -1679,6 +1684,7 @@ impl<'a, 'b> Clone for Parser<'a, 'b>
|
|||
settings: self.settings.clone(),
|
||||
g_settings: self.g_settings.clone(),
|
||||
meta: self.meta.clone(),
|
||||
trailing_vals: self.trailing_vals,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,32 +3,33 @@ use std::ascii::AsciiExt;
|
|||
|
||||
bitflags! {
|
||||
flags Flags: u32 {
|
||||
const SC_NEGATE_REQS = 0b00000000000000000000000001,
|
||||
const SC_REQUIRED = 0b00000000000000000000000010,
|
||||
const A_REQUIRED_ELSE_HELP = 0b00000000000000000000000100,
|
||||
const GLOBAL_VERSION = 0b00000000000000000000001000,
|
||||
const VERSIONLESS_SC = 0b00000000000000000000010000,
|
||||
const UNIFIED_HELP = 0b00000000000000000000100000,
|
||||
const WAIT_ON_ERROR = 0b00000000000000000001000000,
|
||||
const SC_REQUIRED_ELSE_HELP= 0b00000000000000000010000000,
|
||||
const NEEDS_LONG_HELP = 0b00000000000000000100000000,
|
||||
const NEEDS_LONG_VERSION = 0b00000000000000001000000000,
|
||||
const NEEDS_SC_HELP = 0b00000000000000010000000000,
|
||||
const DISABLE_VERSION = 0b00000000000000100000000000,
|
||||
const HIDDEN = 0b00000000000001000000000000,
|
||||
const TRAILING_VARARG = 0b00000000000010000000000000,
|
||||
const NO_BIN_NAME = 0b00000000000100000000000000,
|
||||
const ALLOW_UNK_SC = 0b00000000001000000000000000,
|
||||
const UTF8_STRICT = 0b00000000010000000000000000,
|
||||
const UTF8_NONE = 0b00000000100000000000000000,
|
||||
const LEADING_HYPHEN = 0b00000001000000000000000000,
|
||||
const NO_POS_VALUES = 0b00000010000000000000000000,
|
||||
const NEXT_LINE_HELP = 0b00000100000000000000000000,
|
||||
const DERIVE_DISP_ORDER = 0b00001000000000000000000000,
|
||||
const COLORED_HELP = 0b00010000000000000000000000,
|
||||
const COLOR_ALWAYS = 0b00100000000000000000000000,
|
||||
const COLOR_AUTO = 0b01000000000000000000000000,
|
||||
const COLOR_NEVER = 0b10000000000000000000000000,
|
||||
const SC_NEGATE_REQS = 0b000000000000000000000000001,
|
||||
const SC_REQUIRED = 0b000000000000000000000000010,
|
||||
const A_REQUIRED_ELSE_HELP = 0b000000000000000000000000100,
|
||||
const GLOBAL_VERSION = 0b000000000000000000000001000,
|
||||
const VERSIONLESS_SC = 0b000000000000000000000010000,
|
||||
const UNIFIED_HELP = 0b000000000000000000000100000,
|
||||
const WAIT_ON_ERROR = 0b000000000000000000001000000,
|
||||
const SC_REQUIRED_ELSE_HELP= 0b000000000000000000010000000,
|
||||
const NEEDS_LONG_HELP = 0b000000000000000000100000000,
|
||||
const NEEDS_LONG_VERSION = 0b000000000000000001000000000,
|
||||
const NEEDS_SC_HELP = 0b000000000000000010000000000,
|
||||
const DISABLE_VERSION = 0b000000000000000100000000000,
|
||||
const HIDDEN = 0b000000000000001000000000000,
|
||||
const TRAILING_VARARG = 0b000000000000010000000000000,
|
||||
const NO_BIN_NAME = 0b000000000000100000000000000,
|
||||
const ALLOW_UNK_SC = 0b000000000001000000000000000,
|
||||
const UTF8_STRICT = 0b000000000010000000000000000,
|
||||
const UTF8_NONE = 0b000000000100000000000000000,
|
||||
const LEADING_HYPHEN = 0b000000001000000000000000000,
|
||||
const NO_POS_VALUES = 0b000000010000000000000000000,
|
||||
const NEXT_LINE_HELP = 0b000000100000000000000000000,
|
||||
const DERIVE_DISP_ORDER = 0b000001000000000000000000000,
|
||||
const COLORED_HELP = 0b000010000000000000000000000,
|
||||
const COLOR_ALWAYS = 0b000100000000000000000000000,
|
||||
const COLOR_AUTO = 0b001000000000000000000000000,
|
||||
const COLOR_NEVER = 0b010000000000000000000000000,
|
||||
const DONT_DELIM_TRAIL = 0b100000000000000000000000000,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,7 +80,8 @@ impl AppFlags {
|
|||
DeriveDisplayOrder => DERIVE_DISP_ORDER,
|
||||
ColorAlways => COLOR_ALWAYS,
|
||||
ColorAuto => COLOR_AUTO,
|
||||
ColorNever => COLOR_NEVER
|
||||
ColorNever => COLOR_NEVER,
|
||||
DontDelimitTrailingValues => DONT_DELIM_TRAIL
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -551,6 +553,24 @@ pub enum AppSettings {
|
|||
/// .get_matches();
|
||||
/// ```
|
||||
ColorNever,
|
||||
/// Disables the automatic delimiting of values when `--` or [`AppSettings::TrailingVarArg`]
|
||||
/// was used.
|
||||
///
|
||||
/// **NOTE:** The same thing can be done manually by setting the final positional argument to
|
||||
/// [`Arg::use_delimiter(false)`]. Using this setting is safer, because it's easier to locate
|
||||
/// when making changes.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, Arg, SubCommand, AppSettings};
|
||||
/// App::new("myprog")
|
||||
/// .setting(AppSettings::DontDelimitTrailingValues)
|
||||
/// .get_matches();
|
||||
/// ```
|
||||
/// [`AppSettings::TrailingVarArg`]: ./enum.AppSettings.html#variant.TrailingVarArg
|
||||
/// [`Arg::use_delimiter(false)`]: ./struct.Arg.html#method.use_delimiter
|
||||
DontDelimitTrailingValues,
|
||||
#[doc(hidden)]
|
||||
NeedsLongVersion,
|
||||
#[doc(hidden)]
|
||||
|
@ -633,6 +653,8 @@ mod test {
|
|||
AppSettings::ColoredHelp);
|
||||
assert_eq!("hidden".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::Hidden);
|
||||
assert_eq!("dontdelimittrailingvalues".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::DontDelimitTrailingValues);
|
||||
assert!("hahahaha".parse::<AppSettings>().is_err());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue