mirror of
https://github.com/clap-rs/clap
synced 2024-09-20 14:31:58 +00:00
wip
This commit is contained in:
parent
1498910971
commit
de36cd18c0
22 changed files with 483 additions and 516 deletions
|
@ -1,5 +1,4 @@
|
||||||
[package]
|
[package]
|
||||||
|
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "3.0.0-beta.1"
|
version = "3.0.0-beta.1"
|
||||||
authors = ["Kevin K. <kbknapp@gmail.com>"]
|
authors = ["Kevin K. <kbknapp@gmail.com>"]
|
||||||
|
|
|
@ -1,2 +1,4 @@
|
||||||
|
type_punctuation_density = "Compressed"
|
||||||
format_strings = false
|
format_strings = false
|
||||||
fn_single_line = true
|
fn_single_line = true
|
||||||
|
where_pred_indent = "Visual"
|
272
src/args_map.rs
272
src/args_map.rs
|
@ -1,272 +0,0 @@
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::collections::hash_map::Keys;
|
|
||||||
use std::ffi::{OsStr, OsString};
|
|
||||||
use std::slice::{Iter, IterMut};
|
|
||||||
|
|
||||||
use build::{ArgSettings, Arg};
|
|
||||||
use util::hash;
|
|
||||||
|
|
||||||
// LE
|
|
||||||
fn short_to_bytes(s: char) -> [u8; 8] {
|
|
||||||
let bytes = ['-', s];
|
|
||||||
let h = '-' as u32;
|
|
||||||
let c = s as u32;
|
|
||||||
|
|
||||||
let b1 : u8 = ((h >> 24) & 0xff) as u8;
|
|
||||||
let b2 : u8 = ((h >> 16) & 0xff) as u8;
|
|
||||||
let b3 : u8 = ((h >> 8) & 0xff) as u8;
|
|
||||||
let b4 : u8 = (h & 0xff) as u8;
|
|
||||||
let b5 : u8 = ((c >> 24) & 0xff) as u8;
|
|
||||||
let b6 : u8 = ((c >> 16) & 0xff) as u8;
|
|
||||||
let b7 : u8 = ((c >> 8) & 0xff) as u8;
|
|
||||||
let b8 : u8 = (c & 0xff) as u8;
|
|
||||||
|
|
||||||
[b1, b1, b3, b4, b5, b6, b7, b8]
|
|
||||||
}
|
|
||||||
|
|
||||||
// LE
|
|
||||||
fn u64_to_bytes(u: u64) -> [u8; 8] {
|
|
||||||
let b1 : u8 = ((u >> 56) & 0xff) as u8;
|
|
||||||
let b2 : u8 = ((u >> 48) & 0xff) as u8;
|
|
||||||
let b3 : u8 = ((u >> 40) & 0xff) as u8;
|
|
||||||
let b4 : u8 = ((u >> 32) & 0xff) as u8;
|
|
||||||
let b5 : u8 = ((u >> 24) & 0xff) as u8;
|
|
||||||
let b6 : u8 = ((u >> 16) & 0xff) as u8;
|
|
||||||
let b7 : u8 = ((u >> 8) & 0xff) as u8;
|
|
||||||
let b8 : u8 = (u & 0xff) as u8;
|
|
||||||
|
|
||||||
[b1, b1, b3, b4, b5, b6, b7, b8]
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Debug, Clone)]
|
|
||||||
pub struct ArgsMap<'help> {
|
|
||||||
pub index_map: HashMap<u64, usize>,
|
|
||||||
pub args: Vec<Arg<'help>>,
|
|
||||||
built: bool, // mutation isn't possible after being built
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'help> ArgsMap<'help> {
|
|
||||||
pub fn new() -> Self { ArgsMap::default() }
|
|
||||||
//TODO ::from(x), ::with_capacity(n) etc
|
|
||||||
|
|
||||||
pub fn contains_long(&self, l: &str) -> bool { self.index_map.get(&hash(l.as_bytes())).is_some() }
|
|
||||||
|
|
||||||
pub fn contains_short(&self, c: char) -> bool { self.index_map.get(&hash(short_to_bytes(c))).is_some() }
|
|
||||||
|
|
||||||
pub fn insert(&mut self, arg: Arg<'help>) -> usize {
|
|
||||||
assert!(!self.built, "Cannot add Args to the map after the map is built");
|
|
||||||
|
|
||||||
let index = self.args.len();
|
|
||||||
self.insert_keys(&arg, index);
|
|
||||||
self.args.push(arg);
|
|
||||||
index
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push(&mut self, arg: Arg<'help>) -> usize {
|
|
||||||
assert!(!self.built, "Cannot add Args to the map after the map is built");
|
|
||||||
|
|
||||||
let index = self.args.len();
|
|
||||||
self.args.push(arg);
|
|
||||||
index
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO ::push_many([x, y])
|
|
||||||
|
|
||||||
pub fn insert_short_key(&mut self, key: char, index: usize) {
|
|
||||||
self.index_map.insert(hash(short_to_bytes(key)), index);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert_long_key(&mut self, key: &str, index: usize) {
|
|
||||||
self.index_map.insert(hash(key.as_bytes()), index);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert_positional_key(&mut self, key: u64, index: usize) {
|
|
||||||
self.index_map.insert(hash(u64_to_bytes(key)), index);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_by_id(&self, key: u64) -> Option<&Arg<'help>> {
|
|
||||||
self.args.get(*self.index_map.get(&key)?)
|
|
||||||
}
|
|
||||||
pub fn get_by_index(&self, key: usize) -> Option<&Arg<'help>> {
|
|
||||||
self.args.get(key)
|
|
||||||
}
|
|
||||||
pub fn get_by_short(&self, key: char) -> Option<&Arg<'help>> {
|
|
||||||
self.args.get(*self.index_map.get(&hash(short_to_bytes(key)))?)
|
|
||||||
}
|
|
||||||
// &[u8] better?
|
|
||||||
pub fn get_by_short_with_hyphen(&self, key: [u8; 8]) -> Option<&Arg<'help>> {
|
|
||||||
self.args.get(*self.index_map.get(&hash(&key))?)
|
|
||||||
}
|
|
||||||
pub fn get_by_long(&self, key: &str) -> Option<&Arg<'help>> {
|
|
||||||
self.args.get(*self.index_map.get(&hash(key.as_bytes()))?)
|
|
||||||
}
|
|
||||||
pub fn get_by_long_with_hyphen(&self, key: &[u8]) -> Option<&Arg<'help>> {
|
|
||||||
self.args.get(*self.index_map.get(&hash(key))?)
|
|
||||||
}
|
|
||||||
pub fn get_by_positional(&self, key: u64) -> Option<&Arg<'help>> {
|
|
||||||
self.args.get(*self.index_map.get(&hash(u64_to_bytes(key)))?)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_mut_by_id(&mut self, key: u64) -> Option<&mut Arg<'help>> {
|
|
||||||
self.args.get_mut(*self.index_map.get(&key)?)
|
|
||||||
}
|
|
||||||
pub fn get_mut_by_index(&mut self, key: usize) -> Option<&mut Arg<'help>> {
|
|
||||||
self.args.get_mut(key)
|
|
||||||
}
|
|
||||||
pub fn get_mut_by_short(&mut self, key: char) -> Option<&mut Arg<'help>> {
|
|
||||||
self.args.get_mut(*self.index_map.get(&hash(short_to_bytes(key)))?)
|
|
||||||
}
|
|
||||||
// &[u8] better?
|
|
||||||
pub fn get_mut_by_short_with_hyphen(&mut self, key: [u8; 8]) -> Option<&mut Arg<'help>> {
|
|
||||||
self.args.get_mut(*self.index_map.get(&hash(&key))?)
|
|
||||||
}
|
|
||||||
pub fn get_mut_by_long(&mut self, key: &str) -> Option<&mut Arg<'help>> {
|
|
||||||
self.args.get_mut(*self.index_map.get(&hash(key.as_bytes()))?)
|
|
||||||
}
|
|
||||||
pub fn get_mut_by_long_with_hyphen(&mut self, key: &[u8]) -> Option<&mut Arg<'help>> {
|
|
||||||
self.args.get_mut(*self.index_map.get(&hash(key))?)
|
|
||||||
}
|
|
||||||
pub fn get_mut_by_positional(&mut self, key: u64) -> Option<&mut Arg<'help>> {
|
|
||||||
self.args.get_mut(*self.index_map.get(&hash(u64_to_bytes(key)))?)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_empty(&self) -> bool { self.args.is_empty() }
|
|
||||||
|
|
||||||
// Remove Key
|
|
||||||
pub fn remove_id_key(&mut self, key: u64) -> Option<usize> {
|
|
||||||
self.index_map.remove(&key)
|
|
||||||
}
|
|
||||||
pub fn remove_short_key(&mut self, key: char) -> Option<usize> {
|
|
||||||
self.index_map.remove(&hash(short_to_bytes(key)))
|
|
||||||
}
|
|
||||||
pub fn remove_short_key_with_hyphen(&mut self, key: [u8; 8]) -> Option<usize> {
|
|
||||||
self.index_map.remove(&hash(&key))
|
|
||||||
}
|
|
||||||
pub fn remove_long_key(&mut self, key: &str) -> Option<usize> {
|
|
||||||
self.index_map.remove(&hash(key.as_bytes()))
|
|
||||||
}
|
|
||||||
pub fn remove_long_key_with_hyphen(&mut self, key: &[u8]) -> Option<usize> {
|
|
||||||
self.index_map.remove(&hash(key))
|
|
||||||
}
|
|
||||||
pub fn remove_positional_key(&mut self, key: u64) -> Option<usize> {
|
|
||||||
self.index_map.remove(&hash(u64_to_bytes(key)))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn remove_by_id(&mut self, id: u64) -> Option<Arg> {
|
|
||||||
assert!(!self.built, "Cannot remove args once built");
|
|
||||||
let i = self.index_map.remove(&id)?;
|
|
||||||
Some(self.args.swap_remove(i))
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO ::remove_keys([KeyA, KeyB])
|
|
||||||
|
|
||||||
fn insert_keys(&mut self, arg: &Arg, index: usize) {
|
|
||||||
self.index_map.insert(arg.id, index);
|
|
||||||
if let Some(p) = arg.index {
|
|
||||||
self.index_map.insert(hash(u64_to_bytes(p)), index);
|
|
||||||
} else {
|
|
||||||
if let Some(s) = arg.short {
|
|
||||||
self.index_map.insert(hash(short_to_bytes(s)), index);
|
|
||||||
}
|
|
||||||
if let Some(l) = arg.long {
|
|
||||||
self.index_map.insert(hash(l.as_bytes()), index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _build(&mut self) {
|
|
||||||
self.built = true;
|
|
||||||
|
|
||||||
for (i, arg) in self.args.iter().enumerate() {
|
|
||||||
self.insert_keys(arg, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn find_by_name(&mut self, name: u64) -> usize {
|
|
||||||
self.args
|
|
||||||
.iter()
|
|
||||||
.position(|x| x.id == name)
|
|
||||||
.expect("No such name found")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Iter getters
|
|
||||||
impl<'help> ArgsMap<'help> {
|
|
||||||
pub fn iter_args(&self) -> Iter<Arg<'help>> {
|
|
||||||
self.args.iter()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn iter_args_mut(&mut self) -> IterMut<Arg<'help>> {
|
|
||||||
self.args.iter_mut()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn flags(&self) -> impl Iterator<Item=&Arg<'help>> {
|
|
||||||
self.args.iter().filter(|x| !x.is_set(ArgSettings::TakesValue) && x.has_switch())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn opts(&self) -> impl Iterator<Item=&Arg<'help>> {
|
|
||||||
self.args.iter().filter(|x| x.is_set(ArgSettings::TakesValue) && x.has_switch())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn positionals(&self) -> impl Iterator<Item=&Arg<'help>> {
|
|
||||||
self.args.iter().filter(|x| x.index.is_some())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn global_args(&self) -> impl Iterator<Item=&Arg<'help>> {
|
|
||||||
self.args.iter().filter(|a| a.is_set(ArgSettings::Global))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use util::hash;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn get_some_value() {
|
|
||||||
let mut map: ArgsMap = ArgsMap::new();
|
|
||||||
|
|
||||||
map.insert(Arg::new("Value1").long("value"));
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
map.get_by_long_with_hyphen("--value".as_bytes()).unwrap().id,
|
|
||||||
hash("Value1")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn get_none_value() {
|
|
||||||
let mut map: ArgsMap = ArgsMap::new();
|
|
||||||
|
|
||||||
map.insert(Arg::new("Value1").long("value"));
|
|
||||||
|
|
||||||
assert_eq!(map.get_by_long("none"), None);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn insert_multiple_keys() {
|
|
||||||
let mut map: ArgsMap = ArgsMap::new();
|
|
||||||
let index = map.insert(Arg::new("Value1").long("value"));
|
|
||||||
|
|
||||||
map.insert_long_key("other", index);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
map.get_by_long("value"),
|
|
||||||
map.get_by_long("other"),
|
|
||||||
);
|
|
||||||
assert_eq!(map.args.len(), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn remove_key() {
|
|
||||||
let mut map: ArgsMap = ArgsMap::new();
|
|
||||||
let index = map.insert(Arg::new("Value1").long("value"));
|
|
||||||
map.insert_long_key("other", index);
|
|
||||||
|
|
||||||
map.remove_long_key("other");
|
|
||||||
|
|
||||||
assert_eq!(map.index_map.len(), 1);
|
|
||||||
assert_eq!(map.args.len(), 1);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -17,13 +17,14 @@ use std::process;
|
||||||
use yaml_rust::Yaml;
|
use yaml_rust::Yaml;
|
||||||
|
|
||||||
// Internal
|
// Internal
|
||||||
use build::{Arg, ArgGroup, ArgSettings, Terminal, HelpMsg, VersionMsg, Aliases};
|
use crate::build::{Arg, ArgGroup, ArgSettings, Terminal, HelpMsg, VersionMsg, Aliases};
|
||||||
use args_map::ArgsMap;
|
use crate::build::args::Args;
|
||||||
use output::fmt::ColorWhen;
|
use crate::output::fmt::ColorWhen;
|
||||||
use output::{Help, Usage};
|
use crate::output::{Help, Usage};
|
||||||
use parse::errors::Result as ClapResult;
|
use crate::parse::errors::Result as ClapResult;
|
||||||
use parse::{ArgMatcher, ArgMatches, Parser};
|
use crate::parse::{ArgMatcher, ArgMatches, Parser};
|
||||||
use util::hash;
|
use crate::util::hash;
|
||||||
|
use crate::build::args::Find;
|
||||||
use INTERNAL_ERROR_MSG;
|
use INTERNAL_ERROR_MSG;
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
@ -91,7 +92,7 @@ pub struct App<'help> {
|
||||||
pub g_settings: AppFlags,
|
pub g_settings: AppFlags,
|
||||||
// The list of valid arguments
|
// The list of valid arguments
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub args: ArgsMap<'help>,
|
pub args: Args<'help>,
|
||||||
// A list of valid subcommands
|
// A list of valid subcommands
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub subcommands: Vec<App<'help>>,
|
pub subcommands: Vec<App<'help>>,
|
||||||
|
@ -127,6 +128,40 @@ impl<'help> App<'help> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Preallocate `args` number of Arguments
|
||||||
|
pub fn with_args<S: AsRef<str>>(n: S, args: usize) -> Self where S: 'help {
|
||||||
|
let name = n.as_ref();
|
||||||
|
App {
|
||||||
|
id: hash(name),
|
||||||
|
name,
|
||||||
|
args: Args::with_capacity(args),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Preallocate `scs` number of SubCommands
|
||||||
|
pub fn with_subcommands<S: AsRef<str>>(n: S, scs: usize) -> Self where S: 'help {
|
||||||
|
let name = n.as_ref();
|
||||||
|
App {
|
||||||
|
id: hash(name),
|
||||||
|
name,
|
||||||
|
subcommands: Vec::with_capacity(scs),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Preallocate `args` number of Arguments and `scs` number of SubCommands (not recursive)
|
||||||
|
pub fn with_args_and_subcommands<S: AsRef<str>>(n: S, args: usize, scs: usize) -> Self where S: 'help {
|
||||||
|
let name = n.as_ref();
|
||||||
|
App {
|
||||||
|
id: hash(name),
|
||||||
|
name,
|
||||||
|
args: Args::with_capacity(args),
|
||||||
|
subcommands: Vec::with_capacity(scs),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the name of the app
|
/// Get the name of the app
|
||||||
pub fn get_name(&self) -> &str { &self.name }
|
pub fn get_name(&self) -> &str { &self.name }
|
||||||
|
|
||||||
|
@ -962,7 +997,7 @@ impl<'help> App<'help> {
|
||||||
{
|
{
|
||||||
let a = self
|
let a = self
|
||||||
.args
|
.args
|
||||||
.remove_by_id(hash(arg))
|
.remove(hash(arg))
|
||||||
.unwrap_or_else(|| Arg::new(arg));
|
.unwrap_or_else(|| Arg::new(arg));
|
||||||
self.args.push(f(a));
|
self.args.push(f(a));
|
||||||
|
|
||||||
|
@ -1365,8 +1400,7 @@ impl<'a, 'help> App<'help> {
|
||||||
|
|
||||||
let global_arg_vec: Vec<u64> = self
|
let global_arg_vec: Vec<u64> = self
|
||||||
.args
|
.args
|
||||||
.args
|
.args()
|
||||||
.iter()
|
|
||||||
.filter(|a| a.is_set(ArgSettings::Global))
|
.filter(|a| a.is_set(ArgSettings::Global))
|
||||||
.map(|ga| ga.id)
|
.map(|ga| ga.id)
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -1401,8 +1435,7 @@ impl<'a, 'help> App<'help> {
|
||||||
true
|
true
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut pos_counter = 1;
|
for a in self.args.args_mut() {
|
||||||
for a in self.args.args.iter_mut() {
|
|
||||||
// Figure out implied settings
|
// Figure out implied settings
|
||||||
if a.is_set(ArgSettings::Last) {
|
if a.is_set(ArgSettings::Last) {
|
||||||
// if an arg has `Last` set, we need to imply DontCollapseArgsInUsage so that args
|
// if an arg has `Last` set, we need to imply DontCollapseArgsInUsage so that args
|
||||||
|
@ -1411,10 +1444,6 @@ impl<'a, 'help> App<'help> {
|
||||||
self.set(AppSettings::ContainsLast);
|
self.set(AppSettings::ContainsLast);
|
||||||
}
|
}
|
||||||
a._build();
|
a._build();
|
||||||
if a.short.is_none() && a.long.is_none() && a.index.is_none() {
|
|
||||||
a.index = Some(pos_counter);
|
|
||||||
pos_counter += 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_assert!(self._app_debug_asserts());
|
debug_assert!(self._app_debug_asserts());
|
||||||
|
@ -1425,8 +1454,8 @@ impl<'a, 'help> App<'help> {
|
||||||
// Perform some expensive assertions on the Parser itself
|
// Perform some expensive assertions on the Parser itself
|
||||||
fn _app_debug_asserts(&mut self) -> bool {
|
fn _app_debug_asserts(&mut self) -> bool {
|
||||||
debugln!("App::_app_debug_asserts;");
|
debugln!("App::_app_debug_asserts;");
|
||||||
for id in self.args.args.iter().map(|x| x.id) {
|
for id in self.args.args.args().map(|x| x.id) {
|
||||||
if self.args.args.iter().filter(|x| x.id == id).count() > 1 {
|
if self.args.args.args().filter(|x| x.id == id).count() > 1 {
|
||||||
panic!("Arg names must be unique");
|
panic!("Arg names must be unique");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1471,7 +1500,7 @@ impl<'a, 'help> App<'help> {
|
||||||
pub(crate) fn _create_help_and_version(&mut self) {
|
pub(crate) fn _create_help_and_version(&mut self) {
|
||||||
debugln!("App::_create_help_and_version;");
|
debugln!("App::_create_help_and_version;");
|
||||||
// @TODO @perf hardcode common hashes?
|
// @TODO @perf hardcode common hashes?
|
||||||
if !(self.args.get_by_long("help").is_some() || self.args.get_by_id(hash("help")).is_some())
|
if !(self.args.find("help").is_some() || self.args.get_by_id(hash("help")).is_some())
|
||||||
{
|
{
|
||||||
debugln!("App::_create_help_and_version: Building --help");
|
debugln!("App::_create_help_and_version: Building --help");
|
||||||
let mut help = Arg::new("help")
|
let mut help = Arg::new("help")
|
||||||
|
@ -1541,31 +1570,27 @@ impl<'a, 'help> App<'help> {
|
||||||
debugln!("App::_arg_debug_asserts:{}", a.name);
|
debugln!("App::_arg_debug_asserts:{}", a.name);
|
||||||
|
|
||||||
// Long conflicts
|
// Long conflicts
|
||||||
if let Some(l) = a.long {
|
for l in a.longs() {
|
||||||
assert!(
|
assert!(
|
||||||
self.args.args.iter().filter(|x| x.long == Some(l)).count() < 2,
|
self.args.args().filter(|x| x.uses_long(l)).count() < 2,
|
||||||
"Argument long must be unique\n\n\t--{} is already in use",
|
"Argument long must be unique\n\n\t--{} is already in use",
|
||||||
l
|
l
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Short conflicts
|
// Short conflicts
|
||||||
if let Some(s) = a.short {
|
if let Some(s) = a.get_short() {
|
||||||
assert!(
|
assert!(
|
||||||
self.args.args.iter().filter(|x| x.short == Some(s)).count() < 2,
|
self.args.args().filter(|x| x.uses_short(s)).count() < 2,
|
||||||
"Argument short must be unique\n\n\t-{} is already in use",
|
"Argument short must be unique\n\n\t-{} is already in use",
|
||||||
s
|
s
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(idx) = a.index {
|
if let Some(idx) = a.get_position() {
|
||||||
// No index conflicts
|
// No index conflicts
|
||||||
assert!(
|
assert!(
|
||||||
self.args.positionals().fold(0, |acc, p| if p.index == Some(idx as u64) {
|
self.args.positionals().filter(|x| x.uses_position(idx)).count() < 2,
|
||||||
acc + 1
|
|
||||||
} else {
|
|
||||||
acc
|
|
||||||
}) < 2,
|
|
||||||
"Argument '{}' has the same index as another positional \
|
"Argument '{}' has the same index as another positional \
|
||||||
argument\n\n\tUse Arg::setting(ArgSettings::MultipleValues) to allow one \
|
argument\n\n\tUse Arg::setting(ArgSettings::MultipleValues) to allow one \
|
||||||
positional argument to take multiple values",
|
positional argument to take multiple values",
|
||||||
|
@ -1574,14 +1599,8 @@ impl<'a, 'help> App<'help> {
|
||||||
}
|
}
|
||||||
if a.is_set(ArgSettings::Last) {
|
if a.is_set(ArgSettings::Last) {
|
||||||
assert!(
|
assert!(
|
||||||
a.long.is_none(),
|
a.has_switch(),
|
||||||
"Flags or Options may not have last(true) set. {} has both a long and \
|
"Flags or Options may not have last(true) set. {} has either a long or short and \
|
||||||
last(true) set.",
|
|
||||||
a.id
|
|
||||||
);
|
|
||||||
assert!(
|
|
||||||
a.short.is_none(),
|
|
||||||
"Flags or Options may not have last(true) set. {} has both a short and \
|
|
||||||
last(true) set.",
|
last(true) set.",
|
||||||
a.id
|
a.id
|
||||||
);
|
);
|
||||||
|
@ -1690,20 +1709,6 @@ impl<'help> App<'help> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn contains_long(&self, l: &str) -> bool {
|
|
||||||
if !self.is_set(AppSettings::Propagated) {
|
|
||||||
panic!("If App::_build hasn't been called, manually search through Arg longs");
|
|
||||||
}
|
|
||||||
self.args.contains_long(l)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn contains_short(&self, s: char) -> bool {
|
|
||||||
if !self.is_set(AppSettings::Propagated) {
|
|
||||||
panic!("If App::_build hasn't been called, manually search through Arg shorts");
|
|
||||||
}
|
|
||||||
self.args.contains_short(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_set(&self, s: AppSettings) -> bool {
|
pub fn is_set(&self, s: AppSettings) -> bool {
|
||||||
self.settings.is_set(s) || self.g_settings.is_set(s)
|
self.settings.is_set(s) || self.g_settings.is_set(s)
|
||||||
}
|
}
|
||||||
|
@ -1718,28 +1723,6 @@ impl<'help> App<'help> {
|
||||||
|
|
||||||
pub fn has_subcommands(&self) -> bool { !self.subcommands.is_empty() }
|
pub fn has_subcommands(&self) -> bool { !self.subcommands.is_empty() }
|
||||||
|
|
||||||
pub fn has_args(&self) -> bool { !self.args.is_empty() }
|
|
||||||
|
|
||||||
pub fn has_opts(&self) -> bool { self.args.has_opts() }
|
|
||||||
|
|
||||||
pub fn has_flags(&self) -> bool { self.args.has_flags() }
|
|
||||||
|
|
||||||
pub fn has_positionals(&self) -> bool { self.args.has_positionals() }
|
|
||||||
|
|
||||||
pub fn has_visible_opts(&self) -> bool { self.args.opts().any(|o| !o.is_set(ArgSettings::Hidden)) }
|
|
||||||
|
|
||||||
pub fn has_visible_flags(&self) -> bool { self.args.flags().any(|o| !o.is_set(ArgSettings::Hidden)) }
|
|
||||||
|
|
||||||
pub fn has_visible_positionals(&self) -> bool {
|
|
||||||
self.args.positionals().any(|o| !o.is_set(ArgSettings::Hidden))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn has_visible_subcommands(&self) -> bool {
|
|
||||||
self.subcommands.iter()
|
|
||||||
.filter(|sc| sc.name != "help")
|
|
||||||
.any(|sc| !sc.is_set(AppSettings::Hidden))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn unroll_args_in_group(&self, group: u64) -> Vec<u64> {
|
pub(crate) fn unroll_args_in_group(&self, group: u64) -> Vec<u64> {
|
||||||
let mut g_vec = vec![group];
|
let mut g_vec = vec![group];
|
||||||
let mut args = vec![];
|
let mut args = vec![];
|
||||||
|
@ -1754,7 +1737,7 @@ impl<'help> App<'help> {
|
||||||
.iter()
|
.iter()
|
||||||
{
|
{
|
||||||
if !args.contains(n) {
|
if !args.contains(n) {
|
||||||
if self.find(*n).is_some() {
|
if self.args.find(*n).is_some() {
|
||||||
args.push(*n)
|
args.push(*n)
|
||||||
} else {
|
} else {
|
||||||
g_vec.push(*n);
|
g_vec.push(*n);
|
|
@ -1,37 +1,31 @@
|
||||||
// @TODO @p2 @docs remove Arg::setting(foo) in examples, we are sticking with Arg::foo(true) isntead
|
// @TODO @p2 @docs remove Arg::setting(foo) in examples, we are sticking with Arg::foo(true) instead
|
||||||
|
|
||||||
mod settings;
|
mod settings;
|
||||||
mod key;
|
mod key;
|
||||||
mod short;
|
|
||||||
mod long;
|
|
||||||
pub use self::settings::{ArgFlags, ArgSettings};
|
|
||||||
|
|
||||||
// Std
|
|
||||||
#[cfg(any(target_os = "windows", target_arch = "wasm32"))]
|
|
||||||
use osstringext::OsStrExt3;
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::ffi::{OsStr, OsString};
|
use std::ffi::{OsStr, OsString};
|
||||||
use std::fmt::{self, Display, Formatter};
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
use std::hash::Hash;
|
||||||
#[cfg(not(any(target_os = "windows", target_arch = "wasm32")))]
|
#[cfg(not(any(target_os = "windows", target_arch = "wasm32")))]
|
||||||
use std::os::unix::ffi::OsStrExt;
|
use std::os::unix::ffi::OsStrExt;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::str;
|
use std::str;
|
||||||
use std::hash::Hash;
|
|
||||||
|
|
||||||
// Third Party
|
|
||||||
use util::VecMap;
|
|
||||||
#[cfg(feature = "yaml")]
|
#[cfg(feature = "yaml")]
|
||||||
use yaml_rust;
|
use yaml_rust;
|
||||||
|
|
||||||
// Internal
|
|
||||||
use build::UsageParser;
|
use build::UsageParser;
|
||||||
use INTERNAL_ERROR_MSG;
|
use INTERNAL_ERROR_MSG;
|
||||||
|
#[cfg(any(target_os = "windows", target_arch = "wasm32"))]
|
||||||
|
use osstringext::OsStrExt3;
|
||||||
use util::hash;
|
use util::hash;
|
||||||
use self::key::Key;
|
use util::VecMap;
|
||||||
|
|
||||||
type Validator = Rc<Fn(String) -> Result<(), String>>;
|
pub use self::key::{Key, Position, Short, Long};
|
||||||
type ValidatorOs = Rc<Fn(&OsStr) -> Result<(), String>>;
|
pub use self::settings::{ArgFlags, ArgSettings};
|
||||||
|
|
||||||
|
pub type ArgId = u64;
|
||||||
|
|
||||||
/// 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.
|
||||||
|
@ -59,13 +53,16 @@ type ValidatorOs = Rc<Fn(&OsStr) -> Result<(), String>>;
|
||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone)]
|
||||||
pub struct Arg<'help> {
|
pub struct Arg<'help> {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub id: u64,
|
pub id: ArgId,
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
key: Key<'help>,
|
key: Key<'help>,
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub settings: ArgFlags,
|
settings: ArgFlags,
|
||||||
#[doc(hidden)]
|
value: Option<Value>,
|
||||||
pub env: Option<(&'help OsStr, Option<OsString>)>,
|
help: HelpMessage,
|
||||||
|
occurrence: Occurrence,
|
||||||
|
validation: ValidationRules<'help>,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'help> Arg<'help> {
|
impl<'help> Arg<'help> {
|
||||||
|
@ -86,35 +83,15 @@ impl<'help> Arg<'help> {
|
||||||
/// ```
|
/// ```
|
||||||
/// [`Arg::takes_value(true)`]: ./struct.Arg.html#method.takes_value
|
/// [`Arg::takes_value(true)`]: ./struct.Arg.html#method.takes_value
|
||||||
/// [`Arg`]: ./struct.Arg.html
|
/// [`Arg`]: ./struct.Arg.html
|
||||||
pub fn new<T>(id: T) -> Self where T: Hash {
|
pub fn new<T>(id: T) -> Self where T: Hash{
|
||||||
Arg {
|
Arg {
|
||||||
id: hash(id),
|
id: hash(id),
|
||||||
disp_ord: 999,
|
|
||||||
unified_ord: 999,
|
|
||||||
help: None,
|
|
||||||
long_help: None,
|
|
||||||
blacklist: None,
|
|
||||||
settings: ArgFlags::default(),
|
settings: ArgFlags::default(),
|
||||||
r_unless: None,
|
|
||||||
overrides: None,
|
|
||||||
requires: None,
|
|
||||||
key: Key::new(),
|
key: Key::new(),
|
||||||
possible_vals: None,
|
value: None,
|
||||||
val_names: None,
|
help: HelpMessage::new(),
|
||||||
num_vals: None,
|
occurrence: Occurrence::new(),
|
||||||
num_vals_per_occ: None,
|
validation: ValidationRules::new(),
|
||||||
max_vals: None,
|
|
||||||
min_vals: None,
|
|
||||||
validator: None,
|
|
||||||
validator_os: None,
|
|
||||||
val_delim: None,
|
|
||||||
default_val: None,
|
|
||||||
default_vals_ifs: None,
|
|
||||||
env: None,
|
|
||||||
terminator: None,
|
|
||||||
index: None,
|
|
||||||
r_ifs: None,
|
|
||||||
help_heading: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,7 +328,7 @@ impl<'help> Arg<'help> {
|
||||||
/// ```
|
/// ```
|
||||||
/// [`Arg::long_help`]: ./struct.Arg.html#method.long_help
|
/// [`Arg::long_help`]: ./struct.Arg.html#method.long_help
|
||||||
pub fn help(mut self, h: &'help str) -> Self {
|
pub fn help(mut self, h: &'help str) -> Self {
|
||||||
self.help = Some(h);
|
self.help.short_message(h);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -422,7 +399,7 @@ impl<'help> Arg<'help> {
|
||||||
/// ```
|
/// ```
|
||||||
/// [`Arg::help`]: ./struct.Arg.html#method.help
|
/// [`Arg::help`]: ./struct.Arg.html#method.help
|
||||||
pub fn long_help(mut self, h: &'help str) -> Self {
|
pub fn long_help(mut self, h: &'help str) -> Self {
|
||||||
self.long_help = Some(h);
|
self.help.long_message(h);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -484,11 +461,10 @@ impl<'help> Arg<'help> {
|
||||||
/// [`Arg::required_unless(name)`]: ./struct.Arg.html#method.required_unless
|
/// [`Arg::required_unless(name)`]: ./struct.Arg.html#method.required_unless
|
||||||
pub fn required_unless<T>(mut self, other: T) -> Self where T: Hash {
|
pub fn required_unless<T>(mut self, other: T) -> Self where T: Hash {
|
||||||
let id = hash(other);
|
let id = hash(other);
|
||||||
if let Some(ref mut vec) = self.r_unless {
|
self.validation.self_required_rule(
|
||||||
vec.push(id);
|
Rule::new()
|
||||||
} else {
|
.rule_modifier(RuleModifier::Unless)
|
||||||
self.r_unless = Some(vec![id]);
|
.condition(Condition::new(id)));
|
||||||
}
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -556,14 +532,13 @@ impl<'help> Arg<'help> {
|
||||||
/// [`Arg::required_unless_one`]: ./struct.Arg.html#method.required_unless_one
|
/// [`Arg::required_unless_one`]: ./struct.Arg.html#method.required_unless_one
|
||||||
/// [`Arg::required_unless_all(names)`]: ./struct.Arg.html#method.required_unless_all
|
/// [`Arg::required_unless_all(names)`]: ./struct.Arg.html#method.required_unless_all
|
||||||
pub fn required_unless_all<T>(mut self, others: &[T]) -> Self where T: Hash {
|
pub fn required_unless_all<T>(mut self, others: &[T]) -> Self where T: Hash {
|
||||||
if let Some(ref mut vec) = self.r_unless {
|
self.validation.self_required_rule(
|
||||||
for s in others {
|
Rule::new()
|
||||||
vec.push(hash(s));
|
.rule_modifier(RuleModifier::Unless)
|
||||||
}
|
.conditions_modifier(ConditionsModifier::All)
|
||||||
} else {
|
.conditions(
|
||||||
self.r_unless = Some(others.iter().map(hash).collect());
|
others.iter().map(|x| Condition::new(hash(x)))));
|
||||||
}
|
self
|
||||||
self.setting(ArgSettings::RequiredUnlessAll)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets args that override this arg's [required] setting. (i.e. this arg will be required
|
/// Sets args that override this arg's [required] setting. (i.e. this arg will be required
|
||||||
|
@ -631,13 +606,11 @@ impl<'help> Arg<'help> {
|
||||||
/// [`Arg::required_unless_one(names)`]: ./struct.Arg.html#method.required_unless_one
|
/// [`Arg::required_unless_one(names)`]: ./struct.Arg.html#method.required_unless_one
|
||||||
/// [`Arg::required_unless_all`]: ./struct.Arg.html#method.required_unless_all
|
/// [`Arg::required_unless_all`]: ./struct.Arg.html#method.required_unless_all
|
||||||
pub fn required_unless_one<T>(mut self, others: &[T]) -> Self where T: Hash {
|
pub fn required_unless_one<T>(mut self, others: &[T]) -> Self where T: Hash {
|
||||||
if let Some(ref mut vec) = self.r_unless {
|
self.validation.self_required_rule(
|
||||||
for s in others {
|
Rule::new()
|
||||||
vec.push(hash(s));
|
.rule_modifier(RuleModifier::Unless)
|
||||||
}
|
.conditions(
|
||||||
} else {
|
others.iter().map(|x| Condition::new(hash(x)))));
|
||||||
self.r_unless = Some(others.iter().map(hash).collect());
|
|
||||||
}
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -680,11 +653,9 @@ impl<'help> Arg<'help> {
|
||||||
/// ```
|
/// ```
|
||||||
pub fn conflicts_with<T>(mut self, other: T) -> Self where T: Hash {
|
pub fn conflicts_with<T>(mut self, other: T) -> Self where T: Hash {
|
||||||
let id = hash(other);
|
let id = hash(other);
|
||||||
if let Some(ref mut vec) = self.blacklist {
|
self.validation.conflicts_rule(
|
||||||
vec.push(id);
|
Rule::new()
|
||||||
} else {
|
.condition(Condition::new(id)));
|
||||||
self.blacklist = Some(vec![id]);
|
|
||||||
}
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -730,13 +701,10 @@ impl<'help> Arg<'help> {
|
||||||
/// ```
|
/// ```
|
||||||
/// [`Arg::conflicts_with`]: ./struct.Arg.html#method.conflicts_with
|
/// [`Arg::conflicts_with`]: ./struct.Arg.html#method.conflicts_with
|
||||||
pub fn conflicts_with_all<T>(mut self, others: &[T]) -> Self where T: Hash {
|
pub fn conflicts_with_all<T>(mut self, others: &[T]) -> Self where T: Hash {
|
||||||
if let Some(ref mut vec) = self.blacklist {
|
self.validation.conflicts_rule(
|
||||||
for s in others {
|
Rule::new()
|
||||||
vec.push(hash(s));
|
.conditions_modifier(ConditionsModifier::All)
|
||||||
}
|
.conditions(otheres.iter().map(|x| Condition::new(hash(x)))));
|
||||||
} else {
|
|
||||||
self.blacklist = Some(others.iter().map(hash).collect());
|
|
||||||
}
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -842,12 +810,9 @@ impl<'help> Arg<'help> {
|
||||||
/// [`Multiple*`]: ./enum.ArgSettings.html#variant.MultipleValues
|
/// [`Multiple*`]: ./enum.ArgSettings.html#variant.MultipleValues
|
||||||
/// [`UseValueDelimiter`]: ./enum.ArgSettings.html#variant.UseValueDelimiter
|
/// [`UseValueDelimiter`]: ./enum.ArgSettings.html#variant.UseValueDelimiter
|
||||||
pub fn overrides_with<T>(mut self, other: T) -> Self where T: Hash {
|
pub fn overrides_with<T>(mut self, other: T) -> Self where T: Hash {
|
||||||
let id = hash(other);
|
self.validation.overrides_rule(
|
||||||
if let Some(ref mut vec) = self.overrides {
|
Rule::new()
|
||||||
vec.push(id);
|
.condition(Condition::new(hash(other))));
|
||||||
} else {
|
|
||||||
self.overrides = Some(vec![id]);
|
|
||||||
}
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -878,14 +843,11 @@ impl<'help> Arg<'help> {
|
||||||
/// assert!(!m.is_present("debug"));
|
/// assert!(!m.is_present("debug"));
|
||||||
/// assert!(!m.is_present("flag"));
|
/// assert!(!m.is_present("flag"));
|
||||||
/// ```
|
/// ```
|
||||||
pub fn overrides_with_all<T>(mut self, others: &[T]) -> Self where T: Hash{
|
pub fn overrides_with_all<T>(mut self, others: &[T]) -> Self where T: Hash {
|
||||||
if let Some(ref mut vec) = self.overrides {
|
self.validation.overrides_rule(
|
||||||
for s in others {
|
Rule::new()
|
||||||
vec.push(hash(s));
|
.conditions_modifier(ConditionsModifier::All)
|
||||||
}
|
.conditions(others.iter().map(|x| Condition::new(hash(x)))));
|
||||||
} else {
|
|
||||||
self.overrides = Some(others.iter().map(hash).collect());
|
|
||||||
}
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -945,14 +907,9 @@ impl<'help> Arg<'help> {
|
||||||
/// [Conflicting]: ./struct.Arg.html#method.conflicts_with
|
/// [Conflicting]: ./struct.Arg.html#method.conflicts_with
|
||||||
/// [override]: ./struct.Arg.html#method.overrides_with
|
/// [override]: ./struct.Arg.html#method.overrides_with
|
||||||
pub fn requires<T>(mut self, other: T) -> Self where T: Hash {
|
pub fn requires<T>(mut self, other: T) -> Self where T: Hash {
|
||||||
let id = hash(other);
|
self.validation.requirements_rule(
|
||||||
if let Some(ref mut vec) = self.requires {
|
Rule::new()
|
||||||
vec.push((None, id));
|
.condition(Condition::new(hash(other))));
|
||||||
} else {
|
|
||||||
let mut vec = vec![];
|
|
||||||
vec.push((None, id));
|
|
||||||
self.requires = Some(vec);
|
|
||||||
}
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1016,12 +973,10 @@ impl<'help> Arg<'help> {
|
||||||
/// [Conflicting]: ./struct.Arg.html#method.conflicts_with
|
/// [Conflicting]: ./struct.Arg.html#method.conflicts_with
|
||||||
/// [override]: ./struct.Arg.html#method.overrides_with
|
/// [override]: ./struct.Arg.html#method.overrides_with
|
||||||
pub fn requires_if<T>(mut self, val: &'help str, other: T) -> Self where T: Hash {
|
pub fn requires_if<T>(mut self, val: &'help str, other: T) -> Self where T: Hash {
|
||||||
let id = hash(other);
|
// need self val and other val...have to re-think
|
||||||
if let Some(ref mut vec) = self.requires {
|
self.validation.requirements_rule(
|
||||||
vec.push((Some(val), id));
|
Rule::new()
|
||||||
} else {
|
.condition(Condition::new(hash(other))));
|
||||||
self.requires = Some(vec![(Some(val), id)]);
|
|
||||||
}
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1384,7 +1339,7 @@ impl<'help> Arg<'help> {
|
||||||
/// [`App`]: ./struct.App.html
|
/// [`App`]: ./struct.App.html
|
||||||
/// [`panic!`]: https://doc.rust-lang.org/std/macro.panic!.html
|
/// [`panic!`]: https://doc.rust-lang.org/std/macro.panic!.html
|
||||||
pub fn index(mut self, idx: u64) -> Self {
|
pub fn index(mut self, idx: u64) -> Self {
|
||||||
self.index = Some(idx);
|
self.key.index(idx);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1434,8 +1389,7 @@ impl<'help> Arg<'help> {
|
||||||
/// [`number_of_values`]: ./struct.Arg.html#method.number_of_values
|
/// [`number_of_values`]: ./struct.Arg.html#method.number_of_values
|
||||||
/// [`max_values`]: ./struct.Arg.html#method.max_values
|
/// [`max_values`]: ./struct.Arg.html#method.max_values
|
||||||
pub fn value_terminator(mut self, term: &'help str) -> Self {
|
pub fn value_terminator(mut self, term: &'help str) -> Self {
|
||||||
self.setb(ArgSettings::TakesValue);
|
self.value.terminator(term);
|
||||||
self.terminator = Some(term);
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1487,7 +1441,6 @@ impl<'help> Arg<'help> {
|
||||||
/// [options]: ./struct.Arg.html#method.takes_value
|
/// [options]: ./struct.Arg.html#method.takes_value
|
||||||
/// [positional arguments]: ./struct.Arg.html#method.index
|
/// [positional arguments]: ./struct.Arg.html#method.index
|
||||||
pub fn possible_values(mut self, values: &[&'help str]) -> Self {
|
pub fn possible_values(mut self, values: &[&'help str]) -> Self {
|
||||||
self.setb(ArgSettings::TakesValue);
|
|
||||||
if let Some(ref mut vec) = self.possible_vals {
|
if let Some(ref mut vec) = self.possible_vals {
|
||||||
for s in values {
|
for s in values {
|
||||||
vec.push(s);
|
vec.push(s);
|
||||||
|
@ -1552,7 +1505,6 @@ impl<'help> Arg<'help> {
|
||||||
/// [options]: ./struct.Arg.html#method.takes_value
|
/// [options]: ./struct.Arg.html#method.takes_value
|
||||||
/// [positional arguments]: ./struct.Arg.html#method.index
|
/// [positional arguments]: ./struct.Arg.html#method.index
|
||||||
pub fn possible_value(mut self, value: &'help str) -> Self {
|
pub fn possible_value(mut self, value: &'help str) -> Self {
|
||||||
self.setb(ArgSettings::TakesValue);
|
|
||||||
if let Some(ref mut vec) = self.possible_vals {
|
if let Some(ref mut vec) = self.possible_vals {
|
||||||
vec.push(value);
|
vec.push(value);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1598,7 +1550,6 @@ impl<'help> Arg<'help> {
|
||||||
/// ```
|
/// ```
|
||||||
/// [`Arg::multiple(true)`]: ./struct.Arg.html#method.multiple
|
/// [`Arg::multiple(true)`]: ./struct.Arg.html#method.multiple
|
||||||
pub fn number_of_values(mut self, qty: u64) -> Self {
|
pub fn number_of_values(mut self, qty: u64) -> Self {
|
||||||
self.setb(ArgSettings::TakesValue);
|
|
||||||
self.num_vals = Some(qty);
|
self.num_vals = Some(qty);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -1639,7 +1590,6 @@ impl<'help> Arg<'help> {
|
||||||
/// ```
|
/// ```
|
||||||
/// [`Arg::multiple(true)`]: ./struct.Arg.html#method.multiple
|
/// [`Arg::multiple(true)`]: ./struct.Arg.html#method.multiple
|
||||||
pub fn number_of_values_per_occurrence(mut self, qty: u64) -> Self {
|
pub fn number_of_values_per_occurrence(mut self, qty: u64) -> Self {
|
||||||
self.setb(ArgSettings::TakesValue);
|
|
||||||
self.num_vals_per_occ = Some(qty);
|
self.num_vals_per_occ = Some(qty);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -1681,9 +1631,9 @@ impl<'help> Arg<'help> {
|
||||||
/// [`Err(String)`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err
|
/// [`Err(String)`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err
|
||||||
/// [`Rc`]: https://doc.rust-lang.org/std/rc/struct.Rc.html
|
/// [`Rc`]: https://doc.rust-lang.org/std/rc/struct.Rc.html
|
||||||
pub fn validator<F, O, E>(mut self, f: F) -> Self
|
pub fn validator<F, O, E>(mut self, f: F) -> Self
|
||||||
where
|
where
|
||||||
F: Fn(String) -> Result<O, E> + 'static,
|
F: Fn(String) -> Result<O, E> + 'static,
|
||||||
E: ToString,
|
E: ToString,
|
||||||
{
|
{
|
||||||
self.validator = Some(Rc::new(move |s| {
|
self.validator = Some(Rc::new(move |s| {
|
||||||
f(s).map(|_| ()).map_err(|e| e.to_string())
|
f(s).map(|_| ()).map_err(|e| e.to_string())
|
||||||
|
@ -1722,8 +1672,8 @@ impl<'help> Arg<'help> {
|
||||||
/// [`Err(String)`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err
|
/// [`Err(String)`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err
|
||||||
/// [`Rc`]: https://doc.rust-lang.org/std/rc/struct.Rc.html
|
/// [`Rc`]: https://doc.rust-lang.org/std/rc/struct.Rc.html
|
||||||
pub fn validator_os<F, O>(mut self, f: F) -> Self
|
pub fn validator_os<F, O>(mut self, f: F) -> Self
|
||||||
where
|
where
|
||||||
F: Fn(&OsStr) -> Result<O, String> + 'static,
|
F: Fn(&OsStr) -> Result<O, String> + 'static,
|
||||||
{
|
{
|
||||||
self.validator_os = Some(Rc::new(move |s| f(s).map(|_| ())));
|
self.validator_os = Some(Rc::new(move |s| f(s).map(|_| ())));
|
||||||
self
|
self
|
||||||
|
@ -1786,8 +1736,6 @@ impl<'help> Arg<'help> {
|
||||||
/// ```
|
/// ```
|
||||||
/// [`Arg::multiple(true)`]: ./struct.Arg.html#method.multiple
|
/// [`Arg::multiple(true)`]: ./struct.Arg.html#method.multiple
|
||||||
pub fn max_values(mut self, qty: u64) -> Self {
|
pub fn max_values(mut self, qty: u64) -> Self {
|
||||||
self.setb(ArgSettings::TakesValue);
|
|
||||||
self.setb(ArgSettings::MultipleValues);
|
|
||||||
self.max_vals = Some(qty);
|
self.max_vals = Some(qty);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -1851,7 +1799,7 @@ impl<'help> Arg<'help> {
|
||||||
/// [`Arg::multiple(true)`]: ./struct.Arg.html#method.multiple
|
/// [`Arg::multiple(true)`]: ./struct.Arg.html#method.multiple
|
||||||
pub fn min_values(mut self, qty: u64) -> Self {
|
pub fn min_values(mut self, qty: u64) -> Self {
|
||||||
self.min_vals = Some(qty);
|
self.min_vals = Some(qty);
|
||||||
self.setting(ArgSettings::TakesValue)
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Specifies the separator to use when values are clumped together, defaults to `,` (comma).
|
/// Specifies the separator to use when values are clumped together, defaults to `,` (comma).
|
||||||
|
@ -1878,9 +1826,6 @@ impl<'help> Arg<'help> {
|
||||||
/// [`Arg::use_delimiter(true)`]: ./struct.Arg.html#method.use_delimiter
|
/// [`Arg::use_delimiter(true)`]: ./struct.Arg.html#method.use_delimiter
|
||||||
/// [`Arg::takes_value(true)`]: ./struct.Arg.html#method.takes_value
|
/// [`Arg::takes_value(true)`]: ./struct.Arg.html#method.takes_value
|
||||||
pub fn value_delimiter(mut self, d: &str) -> Self {
|
pub fn value_delimiter(mut self, d: &str) -> Self {
|
||||||
self.unsetb(ArgSettings::ValueDelimiterNotSet);
|
|
||||||
self.setb(ArgSettings::TakesValue);
|
|
||||||
self.setb(ArgSettings::UseValueDelimiter);
|
|
||||||
self.val_delim = Some(
|
self.val_delim = Some(
|
||||||
d.chars()
|
d.chars()
|
||||||
.nth(0)
|
.nth(0)
|
||||||
|
@ -1949,11 +1894,6 @@ impl<'help> Arg<'help> {
|
||||||
/// [`Arg::takes_value(true)`]: ./struct.Arg.html#method.takes_value
|
/// [`Arg::takes_value(true)`]: ./struct.Arg.html#method.takes_value
|
||||||
/// [`Arg::multiple(true)`]: ./struct.Arg.html#method.multiple
|
/// [`Arg::multiple(true)`]: ./struct.Arg.html#method.multiple
|
||||||
pub fn value_names(mut self, names: &[&'help str]) -> Self {
|
pub fn value_names(mut self, names: &[&'help str]) -> Self {
|
||||||
self.setb(ArgSettings::TakesValue);
|
|
||||||
if self.is_set(ArgSettings::ValueDelimiterNotSet) {
|
|
||||||
self.unsetb(ArgSettings::ValueDelimiterNotSet);
|
|
||||||
self.setb(ArgSettings::UseValueDelimiter);
|
|
||||||
}
|
|
||||||
if let Some(ref mut vals) = self.val_names {
|
if let Some(ref mut vals) = self.val_names {
|
||||||
let mut l = vals.len();
|
let mut l = vals.len();
|
||||||
for s in names {
|
for s in names {
|
||||||
|
@ -2017,7 +1957,6 @@ impl<'help> Arg<'help> {
|
||||||
/// [positional]: ./struct.Arg.html#method.index
|
/// [positional]: ./struct.Arg.html#method.index
|
||||||
/// [`Arg::takes_value(true)`]: ./struct.Arg.html#method.takes_value
|
/// [`Arg::takes_value(true)`]: ./struct.Arg.html#method.takes_value
|
||||||
pub fn value_name(mut self, name: &'help str) -> Self {
|
pub fn value_name(mut self, name: &'help str) -> Self {
|
||||||
self.setb(ArgSettings::TakesValue);
|
|
||||||
if let Some(ref mut vals) = self.val_names {
|
if let Some(ref mut vals) = self.val_names {
|
||||||
let l = vals.len();
|
let l = vals.len();
|
||||||
vals.insert(l, name);
|
vals.insert(l, name);
|
||||||
|
@ -2101,7 +2040,6 @@ impl<'help> Arg<'help> {
|
||||||
/// [`Arg::default_value`]: ./struct.Arg.html#method.default_value
|
/// [`Arg::default_value`]: ./struct.Arg.html#method.default_value
|
||||||
/// [`OsStr`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html
|
/// [`OsStr`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html
|
||||||
pub fn default_value_os(mut self, val: &'help OsStr) -> Self {
|
pub fn default_value_os(mut self, val: &'help OsStr) -> Self {
|
||||||
self.setb(ArgSettings::TakesValue);
|
|
||||||
self.default_val = Some(val);
|
self.default_val = Some(val);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -2221,7 +2159,6 @@ impl<'help> Arg<'help> {
|
||||||
default: &'help OsStr,
|
default: &'help OsStr,
|
||||||
) -> Self where T: Hash {
|
) -> Self where T: Hash {
|
||||||
let id = hash(arg);
|
let id = hash(arg);
|
||||||
self.setb(ArgSettings::TakesValue);
|
|
||||||
if let Some(ref mut vm) = self.default_vals_ifs {
|
if let Some(ref mut vm) = self.default_vals_ifs {
|
||||||
let l = vm.len();
|
let l = vm.len();
|
||||||
vm.insert(l, (id, val, default));
|
vm.insert(l, (id, val, default));
|
||||||
|
@ -2333,7 +2270,7 @@ impl<'help> Arg<'help> {
|
||||||
/// [`Arg::default_value_ifs`]: ./struct.Arg.html#method.default_value_ifs
|
/// [`Arg::default_value_ifs`]: ./struct.Arg.html#method.default_value_ifs
|
||||||
/// [`OsStr`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html
|
/// [`OsStr`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html
|
||||||
#[cfg_attr(feature = "lints", allow(explicit_counter_loop))]
|
#[cfg_attr(feature = "lints", allow(explicit_counter_loop))]
|
||||||
pub fn default_value_ifs_os<T>(mut self, ifs: &[(T, Option<&'help OsStr>, &'help OsStr)]) -> Self where T: Hash{
|
pub fn default_value_ifs_os<T>(mut self, ifs: &[(T, Option<&'help OsStr>, &'help OsStr)]) -> Self where T: Hash {
|
||||||
for &(arg, val, default) in ifs {
|
for &(arg, val, default) in ifs {
|
||||||
self = self.default_value_if_os(arg, val, default);
|
self = self.default_value_if_os(arg, val, default);
|
||||||
}
|
}
|
||||||
|
@ -2445,8 +2382,6 @@ impl<'help> Arg<'help> {
|
||||||
/// from the environment if available in the exact same manner as [`Arg::env`] only using
|
/// from the environment if available in the exact same manner as [`Arg::env`] only using
|
||||||
/// [`OsStr`]s instead.
|
/// [`OsStr`]s instead.
|
||||||
pub fn env_os(mut self, name: &'help OsStr) -> Self {
|
pub fn env_os(mut self, name: &'help OsStr) -> Self {
|
||||||
self.setb(ArgSettings::TakesValue);
|
|
||||||
|
|
||||||
self.env = Some((name, env::var_os(name)));
|
self.env = Some((name, env::var_os(name)));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -3831,7 +3766,7 @@ impl<'help> Arg<'help> {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn _build(&mut self) {
|
pub fn _build(&mut self) {
|
||||||
self.set_default_delimiter();
|
self.set_default_delimiter();
|
||||||
if self.key.is_positional() {
|
if self.is_positional() {
|
||||||
if self.max_vals.is_some()
|
if self.max_vals.is_some()
|
||||||
|| self.min_vals.is_some()
|
|| self.min_vals.is_some()
|
||||||
|| (self.num_vals.is_some() && self.num_vals.unwrap() > 1)
|
|| (self.num_vals.is_some() && self.num_vals.unwrap() > 1)
|
||||||
|
@ -3926,7 +3861,7 @@ impl<'help> Display for Arg<'help> {
|
||||||
}
|
}
|
||||||
if self.settings.is_set(ArgSettings::MultipleValues)
|
if self.settings.is_set(ArgSettings::MultipleValues)
|
||||||
&& (self.val_names.is_none()
|
&& (self.val_names.is_none()
|
||||||
|| (self.val_names.is_some() && self.val_names.as_ref().unwrap().len() == 1))
|
|| (self.val_names.is_some() && self.val_names.as_ref().unwrap().len() == 1))
|
||||||
{
|
{
|
||||||
write!(f, "...")?;
|
write!(f, "...")?;
|
||||||
}
|
}
|
||||||
|
@ -4137,16 +4072,16 @@ impl<'help> From<&'help yaml_rust::Yaml> for Arg<'help> {
|
||||||
|
|
||||||
a
|
a
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flags
|
// Flags
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::Arg;
|
|
||||||
use build::ArgSettings;
|
use build::ArgSettings;
|
||||||
use util::VecMap;
|
use util::VecMap;
|
||||||
|
|
||||||
|
use super::Arg;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn flag_display() {
|
fn flag_display() {
|
||||||
let mut f = Arg::new("flg");
|
let mut f = Arg::new("flg");
|
|
@ -1,8 +1,25 @@
|
||||||
|
#[derive(Default)]
|
||||||
pub struct HelpMessage<'help> {
|
pub struct HelpMessage<'help> {
|
||||||
short_message: &'help str,
|
short: Option<&'help str>,
|
||||||
long_message: &'help str,
|
long: Option<&'help str>,
|
||||||
value_names: VecMap<ValueName>,
|
value_names: VecMap<ValueName>,
|
||||||
display_order: DisplayOrder,
|
display_order: DisplayOrder,
|
||||||
unified_order: DisplayOrder, // @TODO remove?
|
unified_order: DisplayOrder, // @TODO remove?
|
||||||
heading: &'help str, // @TODO multiple?
|
heading: &'help str, // @TODO multiple?
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'help> HelpMessage<'help> {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
HelpMessage::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn short_message(&mut self, m: &'help str) {
|
||||||
|
self.short = Some(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn long_message(&mut self, m: &'help str) {
|
||||||
|
self.long = Some(m);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,10 @@
|
||||||
use build::arg::{Short, Long, Position};
|
mod long;
|
||||||
|
mod short;
|
||||||
|
mod position;
|
||||||
|
|
||||||
|
pub use self::long::Long;
|
||||||
|
pub use self::short::Short;
|
||||||
|
pub use self::position::Position;
|
||||||
|
|
||||||
pub struct Key<'help> {
|
pub struct Key<'help> {
|
||||||
short: Option<Short>,
|
short: Option<Short>,
|
||||||
|
@ -20,12 +26,16 @@ impl<'help> Key<'help> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn short(&mut self, short: char) {
|
pub fn short(&mut self, short: char) {
|
||||||
self.short.replace(short);
|
self.short.replace(Short(short));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn long(&mut self, l: &'help str) {
|
pub fn long(&mut self, l: &'help str) {
|
||||||
self.long.add_long(l);
|
self.long.add_long(l);
|
||||||
}
|
}
|
||||||
|
pub fn index(&mut self, i: u64) {
|
||||||
|
self.index = Some(Position::at(i));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn hidden_long(&mut self, l: &'help str) {
|
pub fn hidden_long(&mut self, l: &'help str) {
|
||||||
self.long.add_hidden_long(l);
|
self.long.add_hidden_long(l);
|
||||||
}
|
}
|
|
@ -7,7 +7,11 @@ impl Default for Position {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Position {
|
impl Position {
|
||||||
fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Position(1)
|
Position(1)
|
||||||
}
|
}
|
||||||
|
pub fn at(i: u64) -> Self {
|
||||||
|
assert!(i>0, "Positional Index cannot be less than 1");
|
||||||
|
Position(i)
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,3 +1 @@
|
||||||
pub struct Short {
|
pub struct Short(char);
|
||||||
short: char
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,5 +1,34 @@
|
||||||
#[derive(Default, Copy, Clone, PartialEq, Eq)]
|
use std::u64;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
pub struct Occurrence {
|
pub struct Occurrence {
|
||||||
min: u64,
|
min: u64,
|
||||||
max: u64
|
max: u64
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Occurrence {
|
||||||
|
fn default() -> Self {
|
||||||
|
Occurrence {
|
||||||
|
min: 1,
|
||||||
|
max: u64::MAX
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Occurrence {
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn min(&mut self, num: u64) {
|
||||||
|
self.min = num;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn max(&mut self, num: u64) {
|
||||||
|
self.max = num;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn exact(&mut self, num: u64) {
|
||||||
|
self.max = num;
|
||||||
|
self.min = num;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,17 +1,49 @@
|
||||||
pub struct Rule<'help> {
|
#[derive(Default)]
|
||||||
other_arg: u64,
|
|
||||||
self_value: Option<&'help str>,
|
|
||||||
other_value: Option<&'help str>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Rules<'help> {
|
|
||||||
rules: Vec<Rule<'help>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ValidationRules<'help> {
|
pub struct ValidationRules<'help> {
|
||||||
occurrence: Occurrence,
|
occurrence: Occurrence,
|
||||||
conflicts: Rules<'help>,
|
conflicts: Vec<Rule<'help>>,
|
||||||
requirements: Rules<'help>,
|
requirements: Vec<Rule<'help>>,
|
||||||
overrides: Rules<'help>,
|
self_required: Vec<Rule<'help>>,
|
||||||
requirements_unless: Rules<'help>,
|
overrides: Vec<Rule<'help>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'help> ValidationRules<'help> {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
ValidationRules::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn requirement_rule(&mut self, r: Rule) {
|
||||||
|
self.requirements.push(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn self_required_rule(&mut self, r: Rule) {
|
||||||
|
self.self_required.push(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn conflicts_rule(&mut self, r: Rule) {
|
||||||
|
self.conflicts.push(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn overrides_rule(&mut self, r: Rule) {
|
||||||
|
self.overrides.push(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn max_occurs(&mut self, num: usize) {
|
||||||
|
self.occurrence.max(num);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn min_occurs(&mut self, num: usize) {
|
||||||
|
self.occurrence.min(num);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn exact_occurs(&mut self, num: usize) {
|
||||||
|
self.occurrence.exact(num);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
43
src/build/arg/validation_rules/conditions.rs
Normal file
43
src/build/arg/validation_rules/conditions.rs
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
pub enum ConditionsModifier {
|
||||||
|
All,
|
||||||
|
Any,
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ConditionsModifer {
|
||||||
|
fn default() -> Self {
|
||||||
|
ConditionsModifier::Any
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Condition<'help> {
|
||||||
|
arg: u64,
|
||||||
|
arg_value: Option<&'help str>,
|
||||||
|
other_value: Option<&'help str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'help> Condition<'help> {
|
||||||
|
pub fn new(id: ArgId) -> Self {
|
||||||
|
Condition {
|
||||||
|
arg: id,
|
||||||
|
arg_value: None,
|
||||||
|
other_value: None,
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn arg(mut self, id: ArgId) -> Self {
|
||||||
|
self.arg = id;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn arg_value(mut self, val: &'help str) -> Self {
|
||||||
|
self.arg_value = Some(val);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn other_value(mut self, val: &'help str) -> Self {
|
||||||
|
self.other_value = Some(val);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
52
src/build/arg/validation_rules/rules.rs
Normal file
52
src/build/arg/validation_rules/rules.rs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
use super::ConditionsModifier;
|
||||||
|
|
||||||
|
pub enum RuleModifer {
|
||||||
|
Unless,
|
||||||
|
With,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for RuleModifer {
|
||||||
|
fn default() -> Self {
|
||||||
|
RuleModifer::With
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Rule<'help> {
|
||||||
|
rule_mod: RuleModifer,
|
||||||
|
conditions_mod: ConditionsModifier,
|
||||||
|
conditions: Vec<Condition<'help>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'help> Rule<'help> {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Rule::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rule_modifier(mut self, rm: RuleModifer) -> Self {
|
||||||
|
self.rule_mod = rm;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn conditions_mod(mut self, cm: ConditionsModifier) -> Self {
|
||||||
|
self.conditions_mod = cm;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn condition(mut self, c: Condition) -> Self {
|
||||||
|
self.conditions.push(c);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn conditions(mut self, conds: &dyn Iterator<Item=Condition>) -> Self {
|
||||||
|
for c in conds {
|
||||||
|
self.conditions.push(cond);
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_conditions(&mut self) {
|
||||||
|
self.conditions.clear()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,20 @@
|
||||||
|
mod default_values;
|
||||||
|
mod delimiter;
|
||||||
|
mod filter;
|
||||||
|
mod possible_values;
|
||||||
|
mod terminator;
|
||||||
|
mod value_name;
|
||||||
|
|
||||||
pub struct Value<'help> {
|
pub struct Value<'help> {
|
||||||
defaults: Option<DefaultValues>,
|
defaults: Option<DefaultValues>,
|
||||||
filter: Filter,
|
filter: Filter,
|
||||||
occurrence: Occurrence,
|
occurrence: Occurrence,
|
||||||
requires_equals: bool,
|
requires_equals: bool,
|
||||||
delimiter: Delimiter,
|
delimiter: Delimiter,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'help> Value<'help> {
|
||||||
|
fn new() -> Self {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
4
src/build/arg/value/filter/validators.rs
Normal file
4
src/build/arg/value/filter/validators.rs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
pub type Validator = Rc<Fn(String) -> Result<(), String>>;
|
||||||
|
pub type ValidatorOs = Rc<Fn(&OsStr) -> Result<(), String>>;
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// Maybe move to help message? Or keep here in case we integrate into Value at some point?
|
||||||
|
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
pub struct ValueName<'help>(&'help str);
|
pub struct ValueName<'help>(&'help str);
|
||||||
|
|
113
src/build/args.rs
Normal file
113
src/build/args.rs
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
use std::ops::Index;
|
||||||
|
|
||||||
|
use crate::Arg;
|
||||||
|
use crate::build::arg::{ArgId, Position};
|
||||||
|
|
||||||
|
pub trait Find<By> {
|
||||||
|
type Output;
|
||||||
|
fn find(&self, by: By) -> Option<<Self as Find<By>>::Output>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait FindMut<By> {
|
||||||
|
type Output;
|
||||||
|
fn find(&mut self, by: By) -> Option<<Self as FindMut<By>>::Output>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Args<'help> {
|
||||||
|
inner: Vec<Arg<'help>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'help> Args<'help> {
|
||||||
|
pub fn contains_short(&self, s: char) -> bool {
|
||||||
|
self.args().any(|x| x.uses_short(c))
|
||||||
|
}
|
||||||
|
pub fn contains_long(&self, l: &str) -> bool {
|
||||||
|
self.args().any(|x| x.uses_long(l))
|
||||||
|
}
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.inner.is_empty()
|
||||||
|
}
|
||||||
|
pub fn has_flags(&self) -> bool {
|
||||||
|
self.flags().any(|x| x.is_flag())
|
||||||
|
}
|
||||||
|
pub fn has_options(&self) -> bool {
|
||||||
|
self.options().any(|x| x.is_option())
|
||||||
|
}
|
||||||
|
pub fn has_positionals(&self) -> bool {
|
||||||
|
self.positionals().any(|x| x.is_positional())
|
||||||
|
}
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.inner.len()
|
||||||
|
}
|
||||||
|
pub fn push(&mut self, arg: Arg<'help>) {
|
||||||
|
self.inner.push(arg)
|
||||||
|
}
|
||||||
|
pub fn remove(&mut self, id: ArgId) -> Option<Arg<'help>> {
|
||||||
|
let opt_i = self.args().enumerate().find(|(x, i)| x.id == id).map(|x| x.0);
|
||||||
|
if let Some(i) = opt_i {
|
||||||
|
Some(self.inner.swap_remove(i))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn find(&self, id: ArgId) -> Option<&Arg<'help>> {
|
||||||
|
self.args().find(|x| x.id == id)
|
||||||
|
}
|
||||||
|
pub fn find_short(&self, s: char) -> Option<&Arg<'help>> {
|
||||||
|
self.args().find(|x| x.uses_short(s))
|
||||||
|
}
|
||||||
|
pub fn find_long(&self, l: &str) -> Option<&Arg<'help>> {
|
||||||
|
self.args().find(|x| x.uses_long(l))
|
||||||
|
}
|
||||||
|
pub fn find_position(&self, p: Position) -> Option<&Arg<'help>> {
|
||||||
|
self.positionals().find(|x| x.uses_position(p))
|
||||||
|
}
|
||||||
|
pub fn find_mut(&mut self, id: ArgId) -> Option<&mut Arg<'help>> {
|
||||||
|
self.args_mut().find(|x| x.id == id)
|
||||||
|
}
|
||||||
|
pub fn find_short_mut(&mut self, s: char) -> Option<&mut Arg<'help>> {
|
||||||
|
self.args_mut().find(|x| x.uses_short(s))
|
||||||
|
}
|
||||||
|
pub fn find_long_mut(&mut self, l: &str) -> Option<&mut Arg<'help>> {
|
||||||
|
self.args_mut().find(|x| x.uses_long(l))
|
||||||
|
}
|
||||||
|
pub fn find_position_mut(&mut self, p: Position) -> Option<&mut Arg<'help>> {
|
||||||
|
self.positionals_mut().find(|x| x.uses_position(p))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterator Getters
|
||||||
|
impl<'help> Args<'help> {
|
||||||
|
pub fn args(&self) -> impl Iterator<Item=&Arg> {
|
||||||
|
self.inner.iter()
|
||||||
|
}
|
||||||
|
pub fn flags(&self) -> impl Iterator<Item=&Arg> {
|
||||||
|
self.args().filter(|x| x.is_flat())
|
||||||
|
}
|
||||||
|
pub fn options(&self) -> impl Iterator<Item=&Arg> {
|
||||||
|
self.args().filter(|x| x.is_option())
|
||||||
|
}
|
||||||
|
pub fn positionals(&self) -> impl Iterator<Item=&Arg> {
|
||||||
|
self.args().filter(|x| x.is_positional())
|
||||||
|
}
|
||||||
|
pub fn args_mut(&mut self) -> impl Iterator<Item=&mut Arg> {
|
||||||
|
self.inner.iter_mut()
|
||||||
|
}
|
||||||
|
pub fn flags_mut(&mut self) -> impl Iterator<Item=&mut Arg> {
|
||||||
|
self.args_mut().filter(|x| x.is_flat())
|
||||||
|
}
|
||||||
|
pub fn options_mut(&mut self) -> impl Iterator<Item=&mut Arg> {
|
||||||
|
self.args_mut().filter(|x| x.is_option())
|
||||||
|
}
|
||||||
|
pub fn positionals_mut(&mut self) -> impl Iterator<Item=&mut Arg> {
|
||||||
|
self.args_mut().filter(|x| x.is_positional())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'help> Index<usize> for Args<'help> {
|
||||||
|
type Output = &'a Arg<'help>;
|
||||||
|
|
||||||
|
fn index(&'a self, index: usize) -> &'a Arg<'help> {
|
||||||
|
self.inner[index]
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ mod aliases;
|
||||||
|
|
||||||
pub mod app;
|
pub mod app;
|
||||||
pub mod arg;
|
pub mod arg;
|
||||||
|
pub mod args;
|
||||||
|
|
||||||
mod arg_group;
|
mod arg_group;
|
||||||
mod usage_parser;
|
mod usage_parser;
|
||||||
|
|
|
@ -578,7 +578,6 @@ use std::result::Result as StdResult;
|
||||||
mod macros;
|
mod macros;
|
||||||
|
|
||||||
mod build;
|
mod build;
|
||||||
mod args_map;
|
|
||||||
mod output;
|
mod output;
|
||||||
mod parse;
|
mod parse;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
|
|
||||||
|
const MAGIC_INIT: u64 = 0x811C9DC5;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn hash<T>(t: T) -> u64 where T: Hash {
|
pub(crate) fn hash<T>(t: T) -> u64
|
||||||
|
where
|
||||||
|
T: Hash,
|
||||||
|
{
|
||||||
let mut hasher = FnvHasher::new();
|
let mut hasher = FnvHasher::new();
|
||||||
t.hash(&mut hasher);
|
t.hash(&mut hasher);
|
||||||
hasher.finish()
|
hasher.finish()
|
||||||
|
@ -10,9 +15,7 @@ pub(crate) fn hash<T>(t: T) -> u64 where T: Hash {
|
||||||
pub(crate) struct FnvHasher(u64);
|
pub(crate) struct FnvHasher(u64);
|
||||||
|
|
||||||
impl FnvHasher {
|
impl FnvHasher {
|
||||||
pub(crate) fn new() -> Self {
|
pub(crate) fn new() -> Self { FnvHasher(MAGIC_INIT) }
|
||||||
FnvHasher(0x811C9DC5)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Hasher for FnvHasher {
|
impl Hasher for FnvHasher {
|
||||||
|
@ -27,4 +30,4 @@ impl Hasher for FnvHasher {
|
||||||
|
|
||||||
*self = FnvHasher(hash);
|
*self = FnvHasher(hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue