mirror of
https://github.com/clap-rs/clap
synced 2024-12-13 14:22:34 +00:00
Merge pull request #3438 from epage/flatten
refactor: Flatten directory heirarcy
This commit is contained in:
commit
c422ed24df
15 changed files with 183 additions and 183 deletions
|
@ -1,11 +1,3 @@
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
mod debug_asserts;
|
|
||||||
mod settings;
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests;
|
|
||||||
|
|
||||||
pub use self::settings::{AppFlags, AppSettings};
|
|
||||||
|
|
||||||
// Std
|
// Std
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
|
@ -23,6 +15,7 @@ use os_str_bytes::RawOsStr;
|
||||||
use yaml_rust::Yaml;
|
use yaml_rust::Yaml;
|
||||||
|
|
||||||
// Internal
|
// Internal
|
||||||
|
use crate::build::app_settings::{AppFlags, AppSettings};
|
||||||
use crate::build::{arg::ArgProvider, Arg, ArgGroup, ArgPredicate};
|
use crate::build::{arg::ArgProvider, Arg, ArgGroup, ArgPredicate};
|
||||||
use crate::error::ErrorKind;
|
use crate::error::ErrorKind;
|
||||||
use crate::error::Result as ClapResult;
|
use crate::error::Result as ClapResult;
|
||||||
|
@ -32,6 +25,9 @@ use crate::parse::{ArgMatcher, ArgMatches, Input, Parser};
|
||||||
use crate::util::{color::ColorChoice, Id, Key};
|
use crate::util::{color::ColorChoice, Id, Key};
|
||||||
use crate::{Error, INTERNAL_ERROR_MSG};
|
use crate::{Error, INTERNAL_ERROR_MSG};
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
use crate::build::debug_asserts::assert_app;
|
||||||
|
|
||||||
/// Build a command-line interface.
|
/// Build a command-line interface.
|
||||||
///
|
///
|
||||||
/// This includes defining arguments, subcommands, parser behavior, and help output.
|
/// This includes defining arguments, subcommands, parser behavior, and help output.
|
||||||
|
@ -2802,14 +2798,14 @@ impl<'help> App<'help> {
|
||||||
self.args._build();
|
self.args._build();
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
self::debug_asserts::assert_app(self);
|
assert_app(self);
|
||||||
self.settings.set(AppSettings::Built);
|
self.settings.set(AppSettings::Built);
|
||||||
} else {
|
} else {
|
||||||
debug!("App::_build: already built");
|
debug!("App::_build: already built");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _panic_on_missing_help(&self, help_required_globally: bool) {
|
pub(crate) fn _panic_on_missing_help(&self, help_required_globally: bool) {
|
||||||
if self.is_set(AppSettings::HelpExpected) || help_required_globally {
|
if self.is_set(AppSettings::HelpExpected) || help_required_globally {
|
||||||
let args_missing_help: Vec<String> = self
|
let args_missing_help: Vec<String> = self
|
||||||
.args
|
.args
|
||||||
|
@ -2831,7 +2827,7 @@ impl<'help> App<'help> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
fn two_args_of<F>(&self, condition: F) -> Option<(&Arg<'help>, &Arg<'help>)>
|
pub(crate) fn two_args_of<F>(&self, condition: F) -> Option<(&Arg<'help>, &Arg<'help>)>
|
||||||
where
|
where
|
||||||
F: Fn(&Arg) -> bool,
|
F: Fn(&Arg) -> bool,
|
||||||
{
|
{
|
|
@ -1,17 +1,3 @@
|
||||||
mod arg_predicate;
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
pub mod debug_asserts;
|
|
||||||
mod possible_value;
|
|
||||||
mod settings;
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests;
|
|
||||||
mod value_hint;
|
|
||||||
|
|
||||||
pub use self::possible_value::PossibleValue;
|
|
||||||
pub use self::settings::{ArgFlags, ArgSettings};
|
|
||||||
pub use self::value_hint::ValueHint;
|
|
||||||
pub(crate) use arg_predicate::ArgPredicate;
|
|
||||||
|
|
||||||
// Std
|
// Std
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
|
@ -29,17 +15,16 @@ use std::{env, ffi::OsString};
|
||||||
use yaml_rust::Yaml;
|
use yaml_rust::Yaml;
|
||||||
|
|
||||||
// Internal
|
// Internal
|
||||||
use crate::{
|
use crate::build::usage_parser::UsageParser;
|
||||||
build::usage_parser::UsageParser,
|
use crate::build::ArgPredicate;
|
||||||
util::{Id, Key},
|
use crate::util::{Id, Key};
|
||||||
INTERNAL_ERROR_MSG,
|
use crate::PossibleValue;
|
||||||
};
|
use crate::ValueHint;
|
||||||
|
use crate::INTERNAL_ERROR_MSG;
|
||||||
|
use crate::{ArgFlags, ArgSettings};
|
||||||
|
|
||||||
#[cfg(feature = "regex")]
|
#[cfg(feature = "regex")]
|
||||||
mod regex;
|
use crate::build::RegexRef;
|
||||||
|
|
||||||
#[cfg(feature = "regex")]
|
|
||||||
pub use self::regex::RegexRef;
|
|
||||||
|
|
||||||
/// The abstract representation of a command line argument. Used to set all the options and
|
/// The abstract representation of a command line argument. Used to set all the options and
|
||||||
/// relationships that define a valid argument for the program.
|
/// relationships that define a valid argument for the program.
|
|
@ -1,135 +0,0 @@
|
||||||
use crate::{Arg, ValueHint};
|
|
||||||
|
|
||||||
pub(crate) fn assert_arg(arg: &Arg) {
|
|
||||||
debug!("Arg::_debug_asserts:{}", arg.name);
|
|
||||||
|
|
||||||
// Self conflict
|
|
||||||
// TODO: this check should be recursive
|
|
||||||
assert!(
|
|
||||||
!arg.blacklist.iter().any(|x| *x == arg.id),
|
|
||||||
"Argument '{}' cannot conflict with itself",
|
|
||||||
arg.name,
|
|
||||||
);
|
|
||||||
|
|
||||||
if arg.value_hint != ValueHint::Unknown {
|
|
||||||
assert!(
|
|
||||||
arg.is_takes_value_set(),
|
|
||||||
"Argument '{}' has value hint but takes no value",
|
|
||||||
arg.name
|
|
||||||
);
|
|
||||||
|
|
||||||
if arg.value_hint == ValueHint::CommandWithArguments {
|
|
||||||
assert!(
|
|
||||||
arg.is_multiple_values_set(),
|
|
||||||
"Argument '{}' uses hint CommandWithArguments and must accept multiple values",
|
|
||||||
arg.name
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if arg.index.is_some() {
|
|
||||||
assert!(
|
|
||||||
arg.is_positional(),
|
|
||||||
"Argument '{}' is a positional argument and can't have short or long name versions",
|
|
||||||
arg.name
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if arg.is_required_set() {
|
|
||||||
assert!(
|
|
||||||
arg.default_vals.is_empty(),
|
|
||||||
"Argument '{}' is required and can't have a default value",
|
|
||||||
arg.name
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_arg_flags(arg);
|
|
||||||
|
|
||||||
assert_defaults(arg, "default_value", arg.default_vals.iter().copied());
|
|
||||||
assert_defaults(
|
|
||||||
arg,
|
|
||||||
"default_missing_value",
|
|
||||||
arg.default_missing_vals.iter().copied(),
|
|
||||||
);
|
|
||||||
assert_defaults(
|
|
||||||
arg,
|
|
||||||
"default_value_if",
|
|
||||||
arg.default_vals_ifs
|
|
||||||
.iter()
|
|
||||||
.filter_map(|(_, _, default)| *default),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn assert_arg_flags(arg: &Arg) {
|
|
||||||
macro_rules! checker {
|
|
||||||
($a:ident requires $($b:ident)|+) => {
|
|
||||||
if arg.$a() {
|
|
||||||
let mut s = String::new();
|
|
||||||
|
|
||||||
$(
|
|
||||||
if !arg.$b() {
|
|
||||||
s.push_str(&format!(" Arg::{} is required when Arg::{} is set.\n", std::stringify!($b), std::stringify!($a)));
|
|
||||||
}
|
|
||||||
)+
|
|
||||||
|
|
||||||
if !s.is_empty() {
|
|
||||||
panic!("Argument {:?}\n{}", arg.get_name(), s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
checker!(is_forbid_empty_values_set requires is_takes_value_set);
|
|
||||||
checker!(is_require_value_delimiter_set requires is_takes_value_set);
|
|
||||||
checker!(is_require_value_delimiter_set requires is_use_value_delimiter_set);
|
|
||||||
checker!(is_hide_possible_values_set requires is_takes_value_set);
|
|
||||||
checker!(is_allow_hyphen_values_set requires is_takes_value_set);
|
|
||||||
checker!(is_require_equals_set requires is_takes_value_set);
|
|
||||||
checker!(is_last_set requires is_takes_value_set);
|
|
||||||
checker!(is_hide_default_value_set requires is_takes_value_set);
|
|
||||||
checker!(is_multiple_values_set requires is_takes_value_set);
|
|
||||||
checker!(is_ignore_case_set requires is_takes_value_set);
|
|
||||||
checker!(is_allow_invalid_utf8_set requires is_takes_value_set);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn assert_defaults<'d>(
|
|
||||||
arg: &Arg,
|
|
||||||
field: &'static str,
|
|
||||||
defaults: impl IntoIterator<Item = &'d std::ffi::OsStr>,
|
|
||||||
) {
|
|
||||||
for default_os in defaults {
|
|
||||||
if let Some(default_s) = default_os.to_str() {
|
|
||||||
if !arg.possible_vals.is_empty() {
|
|
||||||
assert!(
|
|
||||||
arg.possible_vals.iter().any(|possible_val| {
|
|
||||||
possible_val.matches(default_s, arg.is_ignore_case_set())
|
|
||||||
}),
|
|
||||||
"Argument `{}`'s {}={} doesn't match possible values",
|
|
||||||
arg.name,
|
|
||||||
field,
|
|
||||||
default_s
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(validator) = arg.validator.as_ref() {
|
|
||||||
let mut validator = validator.lock().unwrap();
|
|
||||||
if let Err(err) = validator(default_s) {
|
|
||||||
panic!(
|
|
||||||
"Argument `{}`'s {}={} failed validation: {}",
|
|
||||||
arg.name, field, default_s, err
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(validator) = arg.validator_os.as_ref() {
|
|
||||||
let mut validator = validator.lock().unwrap();
|
|
||||||
if let Err(err) = validator(default_os) {
|
|
||||||
panic!(
|
|
||||||
"Argument `{}`'s {}={:?} failed validation: {}",
|
|
||||||
arg.name, field, default_os, err
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +1,10 @@
|
||||||
use crate::{
|
|
||||||
build::arg::{debug_asserts::assert_arg, ArgProvider},
|
|
||||||
mkeymap::KeyType,
|
|
||||||
util::Id,
|
|
||||||
App, AppSettings, Arg, ValueHint,
|
|
||||||
};
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
|
use crate::build::arg::ArgProvider;
|
||||||
|
use crate::mkeymap::KeyType;
|
||||||
|
use crate::util::Id;
|
||||||
|
use crate::{App, AppSettings, Arg, ValueHint};
|
||||||
|
|
||||||
pub(crate) fn assert_app(app: &App) {
|
pub(crate) fn assert_app(app: &App) {
|
||||||
debug!("App::_debug_asserts");
|
debug!("App::_debug_asserts");
|
||||||
|
|
||||||
|
@ -577,3 +576,137 @@ fn _verify_positionals(app: &App) -> bool {
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn assert_arg(arg: &Arg) {
|
||||||
|
debug!("Arg::_debug_asserts:{}", arg.name);
|
||||||
|
|
||||||
|
// Self conflict
|
||||||
|
// TODO: this check should be recursive
|
||||||
|
assert!(
|
||||||
|
!arg.blacklist.iter().any(|x| *x == arg.id),
|
||||||
|
"Argument '{}' cannot conflict with itself",
|
||||||
|
arg.name,
|
||||||
|
);
|
||||||
|
|
||||||
|
if arg.value_hint != ValueHint::Unknown {
|
||||||
|
assert!(
|
||||||
|
arg.is_takes_value_set(),
|
||||||
|
"Argument '{}' has value hint but takes no value",
|
||||||
|
arg.name
|
||||||
|
);
|
||||||
|
|
||||||
|
if arg.value_hint == ValueHint::CommandWithArguments {
|
||||||
|
assert!(
|
||||||
|
arg.is_multiple_values_set(),
|
||||||
|
"Argument '{}' uses hint CommandWithArguments and must accept multiple values",
|
||||||
|
arg.name
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if arg.index.is_some() {
|
||||||
|
assert!(
|
||||||
|
arg.is_positional(),
|
||||||
|
"Argument '{}' is a positional argument and can't have short or long name versions",
|
||||||
|
arg.name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if arg.is_required_set() {
|
||||||
|
assert!(
|
||||||
|
arg.default_vals.is_empty(),
|
||||||
|
"Argument '{}' is required and can't have a default value",
|
||||||
|
arg.name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_arg_flags(arg);
|
||||||
|
|
||||||
|
assert_defaults(arg, "default_value", arg.default_vals.iter().copied());
|
||||||
|
assert_defaults(
|
||||||
|
arg,
|
||||||
|
"default_missing_value",
|
||||||
|
arg.default_missing_vals.iter().copied(),
|
||||||
|
);
|
||||||
|
assert_defaults(
|
||||||
|
arg,
|
||||||
|
"default_value_if",
|
||||||
|
arg.default_vals_ifs
|
||||||
|
.iter()
|
||||||
|
.filter_map(|(_, _, default)| *default),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn assert_arg_flags(arg: &Arg) {
|
||||||
|
macro_rules! checker {
|
||||||
|
($a:ident requires $($b:ident)|+) => {
|
||||||
|
if arg.$a() {
|
||||||
|
let mut s = String::new();
|
||||||
|
|
||||||
|
$(
|
||||||
|
if !arg.$b() {
|
||||||
|
s.push_str(&format!(" Arg::{} is required when Arg::{} is set.\n", std::stringify!($b), std::stringify!($a)));
|
||||||
|
}
|
||||||
|
)+
|
||||||
|
|
||||||
|
if !s.is_empty() {
|
||||||
|
panic!("Argument {:?}\n{}", arg.get_name(), s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checker!(is_forbid_empty_values_set requires is_takes_value_set);
|
||||||
|
checker!(is_require_value_delimiter_set requires is_takes_value_set);
|
||||||
|
checker!(is_require_value_delimiter_set requires is_use_value_delimiter_set);
|
||||||
|
checker!(is_hide_possible_values_set requires is_takes_value_set);
|
||||||
|
checker!(is_allow_hyphen_values_set requires is_takes_value_set);
|
||||||
|
checker!(is_require_equals_set requires is_takes_value_set);
|
||||||
|
checker!(is_last_set requires is_takes_value_set);
|
||||||
|
checker!(is_hide_default_value_set requires is_takes_value_set);
|
||||||
|
checker!(is_multiple_values_set requires is_takes_value_set);
|
||||||
|
checker!(is_ignore_case_set requires is_takes_value_set);
|
||||||
|
checker!(is_allow_invalid_utf8_set requires is_takes_value_set);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn assert_defaults<'d>(
|
||||||
|
arg: &Arg,
|
||||||
|
field: &'static str,
|
||||||
|
defaults: impl IntoIterator<Item = &'d std::ffi::OsStr>,
|
||||||
|
) {
|
||||||
|
for default_os in defaults {
|
||||||
|
if let Some(default_s) = default_os.to_str() {
|
||||||
|
if !arg.possible_vals.is_empty() {
|
||||||
|
assert!(
|
||||||
|
arg.possible_vals.iter().any(|possible_val| {
|
||||||
|
possible_val.matches(default_s, arg.is_ignore_case_set())
|
||||||
|
}),
|
||||||
|
"Argument `{}`'s {}={} doesn't match possible values",
|
||||||
|
arg.name,
|
||||||
|
field,
|
||||||
|
default_s
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(validator) = arg.validator.as_ref() {
|
||||||
|
let mut validator = validator.lock().unwrap();
|
||||||
|
if let Err(err) = validator(default_s) {
|
||||||
|
panic!(
|
||||||
|
"Argument `{}`'s {}={} failed validation: {}",
|
||||||
|
arg.name, field, default_s, err
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(validator) = arg.validator_os.as_ref() {
|
||||||
|
let mut validator = validator.lock().unwrap();
|
||||||
|
if let Err(err) = validator(default_os) {
|
||||||
|
panic!(
|
||||||
|
"Argument `{}`'s {}={:?} failed validation: {}",
|
||||||
|
arg.name, field, default_os, err
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,12 +4,33 @@ mod macros;
|
||||||
pub mod app;
|
pub mod app;
|
||||||
pub mod arg;
|
pub mod arg;
|
||||||
|
|
||||||
|
mod app_settings;
|
||||||
mod arg_group;
|
mod arg_group;
|
||||||
|
mod arg_predicate;
|
||||||
|
mod arg_settings;
|
||||||
|
mod possible_value;
|
||||||
mod usage_parser;
|
mod usage_parser;
|
||||||
|
mod value_hint;
|
||||||
|
|
||||||
pub use self::{
|
#[cfg(feature = "regex")]
|
||||||
app::{App, AppFlags, AppSettings},
|
mod regex;
|
||||||
arg::{Arg, ArgFlags, ArgSettings, PossibleValue, ValueHint},
|
|
||||||
arg_group::ArgGroup,
|
#[cfg(debug_assertions)]
|
||||||
};
|
mod debug_asserts;
|
||||||
pub(crate) use arg::ArgPredicate;
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod app_tests;
|
||||||
|
#[cfg(test)]
|
||||||
|
mod arg_tests;
|
||||||
|
|
||||||
|
pub use app::App;
|
||||||
|
pub use app_settings::{AppFlags, AppSettings};
|
||||||
|
pub use arg::Arg;
|
||||||
|
pub use arg_group::ArgGroup;
|
||||||
|
pub(crate) use arg_predicate::ArgPredicate;
|
||||||
|
pub use arg_settings::{ArgFlags, ArgSettings};
|
||||||
|
pub use possible_value::PossibleValue;
|
||||||
|
pub use value_hint::ValueHint;
|
||||||
|
|
||||||
|
#[cfg(feature = "regex")]
|
||||||
|
pub use self::regex::RegexRef;
|
||||||
|
|
|
@ -65,7 +65,7 @@ mod macros;
|
||||||
mod derive;
|
mod derive;
|
||||||
|
|
||||||
#[cfg(feature = "regex")]
|
#[cfg(feature = "regex")]
|
||||||
pub use crate::build::arg::RegexRef;
|
pub use crate::build::RegexRef;
|
||||||
|
|
||||||
pub mod error;
|
pub mod error;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// Internal
|
// Internal
|
||||||
use crate::build::{arg::PossibleValue, App, AppSettings as AS, Arg, ArgPredicate};
|
use crate::build::{App, AppSettings as AS, Arg, ArgPredicate, PossibleValue};
|
||||||
use crate::error::{Error, Result as ClapResult};
|
use crate::error::{Error, Result as ClapResult};
|
||||||
use crate::output::Usage;
|
use crate::output::Usage;
|
||||||
use crate::parse::{ArgMatcher, MatchedArg, ParseState, Parser};
|
use crate::parse::{ArgMatcher, MatchedArg, ParseState, Parser};
|
||||||
|
|
Loading…
Reference in a new issue