mirror of
https://github.com/clap-rs/clap
synced 2024-12-14 14:52:33 +00:00
WIP
This commit is contained in:
parent
c7131e3ed4
commit
cc9518b9d4
13 changed files with 138 additions and 173 deletions
|
@ -106,7 +106,7 @@ where
|
|||
#[doc(hidden)]
|
||||
pub g_settings: AppFlags,
|
||||
#[doc(hidden)]
|
||||
pub args: MKeyMap<'a, 'b>,
|
||||
pub args: MKeyMap<Arg<'a, 'b>>,
|
||||
#[doc(hidden)]
|
||||
pub subcommands: Vec<App<'a, 'b>>,
|
||||
#[doc(hidden)]
|
||||
|
@ -988,18 +988,17 @@ impl<'a, 'b> App<'a, 'b> {
|
|||
where
|
||||
F: FnOnce(Arg<'a, 'b>) -> Arg<'a, 'b>,
|
||||
{
|
||||
let i = self
|
||||
.args
|
||||
.values()
|
||||
.enumerate()
|
||||
.filter_map(|(i, a)| if a.name == arg { Some(i) } else { None })
|
||||
.next();
|
||||
let a = if let Some(idx) = i {
|
||||
let mut a = self.args.swap_remove(idx);
|
||||
f(a)
|
||||
// let i = self
|
||||
// .args
|
||||
// .values()
|
||||
// .enumerate()
|
||||
// .filter_map(|(i, a)| if a.name == arg { Some(i) } else { None })
|
||||
// .next();
|
||||
let a = if let Some(x) = self.args.remove_by_name(arg) {
|
||||
f(x)
|
||||
} else {
|
||||
let mut a = Arg::with_name(arg);
|
||||
f(a)
|
||||
let mut x = Arg::with_name(arg);
|
||||
f(x)
|
||||
};
|
||||
self.args.push(a);
|
||||
self
|
||||
|
@ -1747,7 +1746,7 @@ impl<'a, 'b> App<'a, 'b> {
|
|||
}
|
||||
}
|
||||
pub(crate) fn contains_long(&self, l: &str) -> bool {
|
||||
longs!(self).any(|&al| al == OsString::from(l).as_os_str())
|
||||
longs!(self).any(|al| al == &OsString::from(l))
|
||||
}
|
||||
|
||||
pub(crate) fn contains_short(&self, s: char) -> bool { shorts!(self).any(|&arg_s| arg_s == s) }
|
||||
|
@ -1775,11 +1774,11 @@ impl<'a, 'b> App<'a, 'b> {
|
|||
pub fn has_positionals(&self) -> bool { positionals!(self).count() > 0 }
|
||||
|
||||
pub fn has_visible_opts(&self) -> bool {
|
||||
opts!(self).any(|(k, o)| !o.is_set(ArgSettings::Hidden))
|
||||
opts!(self).any(|o| !o.is_set(ArgSettings::Hidden))
|
||||
}
|
||||
|
||||
pub fn has_visible_flags(&self) -> bool {
|
||||
flags!(self).any(|(k, o)| !o.is_set(ArgSettings::Hidden))
|
||||
flags!(self).any(|o| !o.is_set(ArgSettings::Hidden))
|
||||
}
|
||||
|
||||
pub fn has_visible_positionals(&self) -> bool {
|
||||
|
|
|
@ -132,7 +132,7 @@ complete -F _{name} -o bashdefault -o default {name}
|
|||
p = &find_subcmd!(p, sc).unwrap();
|
||||
}
|
||||
let mut opts = String::new();
|
||||
for (_, o) in opts!(p) {
|
||||
for o in opts!(p) {
|
||||
if let Some(l) = o.long {
|
||||
opts = format!(
|
||||
"{}
|
||||
|
@ -182,7 +182,7 @@ complete -F _{name} -o bashdefault -o default {name}
|
|||
shorts = shorts!(p).fold(String::new(), |acc, s| format!("{} -{}", acc, s)),
|
||||
// Handles aliases too
|
||||
// error-handling?
|
||||
longs = longs!(p).fold(String::new(), |acc, l| format!("{} --{}", acc, l.to_str().unwrap()),
|
||||
longs = longs!(p).fold(String::new(), |acc, l| format!("{} --{}", acc, l.to_str().unwrap())),
|
||||
pos = positionals!(p).fold(String::new(), |acc, p| format!("{} {}", acc, p)),
|
||||
// Handles aliases too
|
||||
subcmds = sc_names!(p).fold(String::new(), |acc, s| format!("{} {}", acc, s))
|
||||
|
|
|
@ -80,7 +80,7 @@ where
|
|||
let mut completions = String::new();
|
||||
let preamble = String::from("\n cand ");
|
||||
|
||||
for (_, option) in opts!(p) {
|
||||
for option in opts!(p) {
|
||||
if let Some(data) = option.short {
|
||||
let tooltip = get_tooltip(option.help, data);
|
||||
completions.push_str(&preamble);
|
||||
|
@ -93,7 +93,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
for (_, flag) in flags!(p) {
|
||||
for flag in flags!(p) {
|
||||
if let Some(data) = flag.short {
|
||||
let tooltip = get_tooltip(flag.help, data);
|
||||
completions.push_str(&preamble);
|
||||
|
|
|
@ -44,7 +44,7 @@ fn gen_fish_inner(root_command: &str, comp_gen: &FishGen, subcommand: &str, buff
|
|||
basic_template.push_str(format!("\"__fish_seen_subcommand_from {}\"", subcommand).as_str());
|
||||
}
|
||||
|
||||
for (_, option) in opts!(comp_gen.0) {
|
||||
for option in opts!(comp_gen.0) {
|
||||
let mut template = basic_template.clone();
|
||||
if let Some(data) = option.short {
|
||||
template.push_str(format!(" -s {}", data).as_str());
|
||||
|
@ -62,7 +62,7 @@ fn gen_fish_inner(root_command: &str, comp_gen: &FishGen, subcommand: &str, buff
|
|||
buffer.push_str("\n");
|
||||
}
|
||||
|
||||
for (_, flag) in flags!(comp_gen.0) {
|
||||
for flag in flags!(comp_gen.0) {
|
||||
let mut template = basic_template.clone();
|
||||
if let Some(data) = flag.short {
|
||||
template.push_str(format!(" -s {}", data).as_str());
|
||||
|
|
|
@ -79,7 +79,7 @@ fn generate_inner<'a, 'b, 'p>(
|
|||
let mut completions = String::new();
|
||||
let preamble = String::from("\n [CompletionResult]::new(");
|
||||
|
||||
for (_, option) in opts!(p) {
|
||||
for option in opts!(p) {
|
||||
if let Some(data) = option.short {
|
||||
let tooltip = get_tooltip(option.help, data);
|
||||
completions.push_str(&preamble);
|
||||
|
@ -102,7 +102,7 @@ fn generate_inner<'a, 'b, 'p>(
|
|||
}
|
||||
}
|
||||
|
||||
for (_, flag) in flags!(p) {
|
||||
for flag in flags!(p) {
|
||||
if let Some(data) = flag.short {
|
||||
let tooltip = get_tooltip(flag.help, data);
|
||||
completions.push_str(&preamble);
|
||||
|
|
|
@ -334,7 +334,7 @@ fn escape_value(string: &str) -> String {
|
|||
fn write_opts_of(p: &App) -> String {
|
||||
debugln!("write_opts_of;");
|
||||
let mut ret = vec![];
|
||||
for (_, o) in opts!(p) {
|
||||
for o in opts!(p) {
|
||||
debugln!("write_opts_of:iter: o={}", o.name);
|
||||
let help = o.help.map_or(String::new(), escape_help);
|
||||
let mut conflicts = get_zsh_arg_conflicts!(p, o, INTERNAL_ERROR_MSG);
|
||||
|
@ -399,7 +399,7 @@ fn write_opts_of(p: &App) -> String {
|
|||
fn write_flags_of(p: &App) -> String {
|
||||
debugln!("write_flags_of;");
|
||||
let mut ret = vec![];
|
||||
for (_, f) in flags!(p) {
|
||||
for f in flags!(p) {
|
||||
debugln!("write_flags_of:iter: f={}", f.name);
|
||||
let help = f.help.map_or(String::new(), escape_help);
|
||||
let mut conflicts = get_zsh_arg_conflicts!(p, f, INTERNAL_ERROR_MSG);
|
||||
|
|
|
@ -586,8 +586,6 @@ mod build;
|
|||
|
||||
mod mkeymap;
|
||||
|
||||
mod completions;
|
||||
mod build;
|
||||
mod completions;
|
||||
mod output;
|
||||
mod parse;
|
||||
|
|
|
@ -910,6 +910,7 @@ macro_rules! flags {
|
|||
Position(_) => false,
|
||||
})
|
||||
.filter(|(k, a)| !a.help_heading.is_some())
|
||||
.map(|(k, v)| v)
|
||||
}};
|
||||
($app:expr) => {
|
||||
flags!($app, iter)
|
||||
|
@ -935,6 +936,7 @@ macro_rules! opts {
|
|||
Position(_) => false,
|
||||
})
|
||||
.filter(|(k, a)| !a.help_heading.is_some())
|
||||
.map(|(k, v)| v)
|
||||
}};
|
||||
($app:expr) => {
|
||||
opts!($app, iter)
|
||||
|
|
165
src/mkeymap.rs
165
src/mkeymap.rs
|
@ -4,40 +4,40 @@ use build::Arg;
|
|||
use std::collections::hash_map;
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::ffi::OsStr;
|
||||
use std::ffi::OsString;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::slice;
|
||||
// ! rustdoc
|
||||
|
||||
#[derive(Default, PartialEq, Debug, Clone)]
|
||||
pub struct MKeyMap<'a, 'b>
|
||||
where
|
||||
'a: 'b,
|
||||
pub struct MKeyMap<T>
|
||||
{
|
||||
keys: HashMap<KeyType<'a>, usize>,
|
||||
value_index: Vec<Arg<'a, 'b>>,
|
||||
keys: HashMap<KeyType, usize>,
|
||||
value_index: Vec<T>,
|
||||
values: HashMap<u64, HashSet<usize>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
|
||||
pub enum KeyType<'a> {
|
||||
pub enum KeyType {
|
||||
Short(char),
|
||||
Long(&'a OsStr),
|
||||
Long(OsString),
|
||||
Position(usize),
|
||||
}
|
||||
|
||||
impl<'a, 'b> MKeyMap<'a, 'b> {
|
||||
impl <T> MKeyMap<T>
|
||||
where T: Sized + Hash + PartialEq + Default + Eq
|
||||
{
|
||||
pub fn new() -> Self { MKeyMap::default() }
|
||||
//TODO ::from(x), ::with_capacity(n) etc
|
||||
//? set theory ops?
|
||||
|
||||
pub fn insert(&mut self, key: KeyType<'a>, value: Arg<'a, 'b>) -> usize {
|
||||
pub fn insert(&mut self, key: KeyType, value: T) -> usize {
|
||||
let index = self.push(value);
|
||||
self.keys.insert(key, index);
|
||||
index
|
||||
}
|
||||
|
||||
pub fn push(&mut self, value: Arg<'a, 'b>) -> usize {
|
||||
pub fn push(&mut self, value: T) -> usize {
|
||||
let index;
|
||||
let mut hasher = DefaultHasher::new();
|
||||
|
||||
|
@ -70,7 +70,7 @@ impl<'a, 'b> MKeyMap<'a, 'b> {
|
|||
}
|
||||
//TODO ::push_many([x, y])
|
||||
|
||||
pub fn insert_key(&mut self, key: KeyType<'a>, index: usize) {
|
||||
pub fn insert_key(&mut self, key: KeyType, index: usize) {
|
||||
if index >= self.values.len() {
|
||||
panic!("Index out of bounds");
|
||||
}
|
||||
|
@ -79,26 +79,26 @@ impl<'a, 'b> MKeyMap<'a, 'b> {
|
|||
}
|
||||
//TODO ::insert_keyset([Long, Key2])
|
||||
|
||||
pub fn insert_key_by_name(&mut self, key: KeyType<'a>, name: &str) {
|
||||
let index = self
|
||||
.value_index
|
||||
.iter()
|
||||
.position(|x| x.name == name)
|
||||
.expect("No such name found");
|
||||
// pub fn insert_key_by_name(&mut self, key: KeyType, name: &str) {
|
||||
// let index = self
|
||||
// .value_index
|
||||
// .iter()
|
||||
// .position(|x| x.name == name)
|
||||
// .expect("No such name found");
|
||||
|
||||
self.keys.insert(key, index);
|
||||
}
|
||||
// self.keys.insert(key, index);
|
||||
// }
|
||||
|
||||
// ! Arg mutation functionality
|
||||
|
||||
pub fn get(&self, key: KeyType<'a>) -> Option<&Arg<'a, 'b>> {
|
||||
pub fn get(&self, key: KeyType) -> Option<&T> {
|
||||
self.keys
|
||||
.get(&key)
|
||||
.and_then(|&idx| self.value_index.get(idx))
|
||||
}
|
||||
//TODO ::get_first([KeyA, KeyB])
|
||||
|
||||
pub fn get_mut(&mut self, key: KeyType<'a>) -> Option<&mut Arg<'a, 'b>> {
|
||||
pub fn get_mut(&mut self, key: KeyType) -> Option<&mut T> {
|
||||
if let Some(&idx) = self.keys.get(&key) {
|
||||
self.value_index.get_mut(idx)
|
||||
} else {
|
||||
|
@ -108,7 +108,9 @@ impl<'a, 'b> MKeyMap<'a, 'b> {
|
|||
|
||||
pub fn is_empty(&self) -> bool { self.keys.is_empty() && self.values.is_empty() }
|
||||
|
||||
pub fn remove(&mut self, key: KeyType) -> Option<Arg> { unimplemented!() }
|
||||
pub fn remove_by_name(&mut self, name: &str) -> Option<T> { unimplemented!() }
|
||||
|
||||
pub fn remove(&mut self, key: KeyType) -> Option<T> { unimplemented!() }
|
||||
//TODO ::remove_many([KeyA, KeyB])
|
||||
//? probably shouldn't add a possibility for removal?
|
||||
//? or remove by replacement by some dummy object, so the order is preserved
|
||||
|
@ -116,25 +118,27 @@ impl<'a, 'b> MKeyMap<'a, 'b> {
|
|||
pub fn remove_key(&mut self, key: KeyType) { unimplemented!() }
|
||||
//TODO ::remove_keys([KeyA, KeyB])
|
||||
|
||||
pub fn keys(&'a self) -> Keys<'a, usize> {
|
||||
pub fn keys(&self) -> Keys<usize> {
|
||||
Keys {
|
||||
iter: self.keys.keys(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn values(&'a self) -> Values<'a, Arg<'a, 'b>> {
|
||||
pub fn values(&self) -> Values<T>
|
||||
{
|
||||
Values {
|
||||
iter: self.value_index.iter(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn values_mut(&'a mut self) -> ValuesMut<'a, Arg<'a, 'b>> {
|
||||
pub fn values_mut(&mut self) -> ValuesMut<T>
|
||||
{
|
||||
ValuesMut {
|
||||
iter: self.value_index.iter_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> Iter {
|
||||
pub fn iter(&self) -> Iter<T> {
|
||||
Iter {
|
||||
map: self,
|
||||
keys: self.keys(),
|
||||
|
@ -142,13 +146,12 @@ impl<'a, 'b> MKeyMap<'a, 'b> {
|
|||
}
|
||||
}
|
||||
|
||||
//TODO remove generics
|
||||
pub struct Keys<'a, V: 'a> {
|
||||
iter: hash_map::Keys<'a, KeyType<'a>, V>,
|
||||
iter: hash_map::Keys<'a, KeyType, V>,
|
||||
}
|
||||
|
||||
impl<'a, V> Iterator for Keys<'a, V> {
|
||||
type Item = &'a KeyType<'a>;
|
||||
type Item = &'a KeyType;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> { self.iter.next() }
|
||||
}
|
||||
|
@ -173,21 +176,17 @@ impl<'a, V> Iterator for ValuesMut<'a, V> {
|
|||
fn next(&mut self) -> Option<Self::Item> { self.iter.next() }
|
||||
}
|
||||
|
||||
pub struct Iter<'a, 'b, 'c>
|
||||
where
|
||||
'a: 'b,
|
||||
'b: 'c,
|
||||
pub struct Iter<'c, T>
|
||||
where T: 'c
|
||||
{
|
||||
map: &'c MKeyMap<'a, 'b>,
|
||||
map: &'c MKeyMap<T>,
|
||||
keys: Keys<'c, usize>,
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'c> Iterator for Iter<'a, 'b, 'c>
|
||||
where
|
||||
'a: 'b,
|
||||
'b: 'c,
|
||||
impl<'c, T> Iterator for Iter<'c, T>
|
||||
where T: 'c + Sized + Hash + PartialEq + Default + Eq
|
||||
{
|
||||
type Item = (&'c KeyType<'a>, &'c Arg<'a, 'b>);
|
||||
type Item = (&'c KeyType, &'c T);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if let Some(key) = self.keys.next() {
|
||||
|
@ -206,12 +205,12 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn get_some_value() {
|
||||
let mut map: MKeyMap = MKeyMap::new();
|
||||
let mut map: MKeyMap<Arg> = MKeyMap::new();
|
||||
|
||||
map.insert(Long(&OsStr::new("One")), Arg::with_name("Value1"));
|
||||
map.insert(Long(OsString::from("One")), Arg::with_name("Value1"));
|
||||
|
||||
assert_eq!(
|
||||
map.get(Long(&OsStr::new("One"))),
|
||||
map.get(Long(OsString::from("One"))),
|
||||
Some(&Arg::with_name("Value1"))
|
||||
);
|
||||
}
|
||||
|
@ -219,12 +218,12 @@ mod tests {
|
|||
#[test]
|
||||
#[should_panic]
|
||||
fn get_none_value() {
|
||||
let mut map: MKeyMap = MKeyMap::new();
|
||||
let mut map: MKeyMap<Arg> = MKeyMap::new();
|
||||
|
||||
map.insert(Long(&OsStr::new("One")), Arg::with_name("Value1"));
|
||||
map.get(Long(&OsStr::new("Two")));
|
||||
map.insert(Long(OsString::from("One")), Arg::with_name("Value1"));
|
||||
map.get(Long(OsString::from("Two")));
|
||||
|
||||
assert_eq!(map.get(Long(&OsStr::new("Two"))), None);
|
||||
assert_eq!(map.get(Long(OsString::from("Two"))), None);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
|
@ -237,30 +236,30 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn insert_duplicate_key() {
|
||||
let mut map: MKeyMap = MKeyMap::new();
|
||||
let mut map: MKeyMap<Arg> = MKeyMap::new();
|
||||
|
||||
map.insert(Long(&OsStr::new("One")), Arg::with_name("Value1"));
|
||||
map.insert(Long(OsString::from("One")), Arg::with_name("Value1"));
|
||||
|
||||
assert_eq!(
|
||||
map.insert(Long(&OsStr::new("One")), Arg::with_name("Value2")),
|
||||
map.insert(Long(OsString::from("One")), Arg::with_name("Value2")),
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_duplicate_value() {
|
||||
let mut map: MKeyMap = MKeyMap::new();
|
||||
let mut map: MKeyMap<Arg> = MKeyMap::new();
|
||||
|
||||
map.insert(Long(&OsStr::new("One")), Arg::with_name("Value1"));
|
||||
map.insert(Long(OsString::from("One")), Arg::with_name("Value1"));
|
||||
|
||||
let orig_len = map.values.len();
|
||||
|
||||
map.insert(Long(&OsStr::new("Two")), Arg::with_name("Value1"));
|
||||
map.insert(Long(OsString::from("Two")), Arg::with_name("Value1"));
|
||||
|
||||
assert_eq!(map.values.len(), orig_len);
|
||||
assert_eq!(
|
||||
map.get(Long(&OsStr::new("One"))),
|
||||
map.get(Long(&OsStr::new("Two")))
|
||||
map.get(Long(OsString::from("One"))),
|
||||
map.get(Long(OsString::from("Two")))
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -275,51 +274,51 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn insert_multiple_keys() {
|
||||
let mut map: MKeyMap = MKeyMap::new();
|
||||
let index = map.insert(Long(&OsStr::new("One")), Arg::with_name("Value1"));
|
||||
let mut map: MKeyMap<Arg> = MKeyMap::new();
|
||||
let index = map.insert(Long(OsString::from("One")), Arg::with_name("Value1"));
|
||||
|
||||
map.insert_key(Long(&OsStr::new("Two")), index);
|
||||
map.insert_key(Long(OsString::from("Two")), index);
|
||||
|
||||
assert_eq!(
|
||||
map.get(Long(&OsStr::new("One"))),
|
||||
map.get(Long(&OsStr::new("Two")))
|
||||
map.get(Long(OsString::from("One"))),
|
||||
map.get(Long(OsString::from("Two")))
|
||||
);
|
||||
assert_eq!(map.values.len(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_by_name() {
|
||||
let mut map: MKeyMap = MKeyMap::new();
|
||||
let index = map.insert(Long(&OsStr::new("One")), Arg::with_name("Value1"));
|
||||
// #[test]
|
||||
// fn insert_by_name() {
|
||||
// let mut map: MKeyMap<Arg> = MKeyMap::new();
|
||||
// let index = map.insert(Long(OsString::from("One")), Arg::with_name("Value1"));
|
||||
|
||||
map.insert_key_by_name(Long(&OsStr::new("Two")), "Value1");
|
||||
// map.insert_key_by_name(Long(OsString::from("Two")), "Value1");
|
||||
|
||||
assert_eq!(
|
||||
map.get(Long(&OsStr::new("One"))),
|
||||
map.get(Long(&OsStr::new("Two")))
|
||||
);
|
||||
assert_eq!(map.values.len(), 1);
|
||||
}
|
||||
// assert_eq!(
|
||||
// map.get(Long(OsString::from("One"))),
|
||||
// map.get(Long(OsString::from("Two")))
|
||||
// );
|
||||
// assert_eq!(map.values.len(), 1);
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn get_mutable() {
|
||||
let mut map: MKeyMap = MKeyMap::new();
|
||||
let mut map: MKeyMap<Arg> = MKeyMap::new();
|
||||
|
||||
map.insert(Long(&OsStr::new("One")), Arg::with_name("Value1"));
|
||||
map.insert(Long(OsString::from("One")), Arg::with_name("Value1"));
|
||||
|
||||
assert_eq!(
|
||||
map.get_mut(Long(&OsStr::new("One"))),
|
||||
map.get_mut(Long(OsString::from("One"))),
|
||||
Some(&mut Arg::with_name("Value1"))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remove_key() {
|
||||
let mut map: MKeyMap = MKeyMap::new();
|
||||
let index = map.insert(Long(&OsStr::new("One")), Arg::with_name("Value1"));
|
||||
let mut map: MKeyMap<Arg> = MKeyMap::new();
|
||||
let index = map.insert(Long(OsString::from("One")), Arg::with_name("Value1"));
|
||||
|
||||
map.insert_key(Long(&OsStr::new("Two")), index);
|
||||
map.remove_key(Long(&OsStr::new("One")));
|
||||
map.insert_key(Long(OsString::from("Two")), index);
|
||||
map.remove_key(Long(OsString::from("One")));
|
||||
|
||||
assert_eq!(map.keys.len(), 1);
|
||||
assert_eq!(map.values.len(), 1);
|
||||
|
@ -327,17 +326,17 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn iter_keys() {
|
||||
let mut map: MKeyMap = MKeyMap::new();
|
||||
let mut map: MKeyMap<Arg> = MKeyMap::new();
|
||||
|
||||
map.insert(Long(&OsStr::new("One")), Arg::with_name("Value1"));
|
||||
map.insert(Long(&OsStr::new("Two")), Arg::with_name("Value2"));
|
||||
map.insert(Long(OsString::from("One")), Arg::with_name("Value1"));
|
||||
map.insert(Long(OsString::from("Two")), Arg::with_name("Value2"));
|
||||
map.insert(Position(1), Arg::with_name("Value1"));
|
||||
|
||||
let iter = map.keys().cloned();
|
||||
let mut ground_truth = HashSet::new();
|
||||
|
||||
ground_truth.insert(Long(&OsStr::new("One")));
|
||||
ground_truth.insert(Long(&OsStr::new("Two")));
|
||||
ground_truth.insert(Long(OsString::from("One")));
|
||||
ground_truth.insert(Long(OsString::from("Two")));
|
||||
ground_truth.insert(Position(1));
|
||||
|
||||
assert_eq!(
|
||||
|
|
|
@ -1082,7 +1082,7 @@ impl<'w> Help<'w> {
|
|||
self.write_all_args(parser)?;
|
||||
}
|
||||
b"unified" => {
|
||||
let opts_flags = parser.app.args.iter().filter(|a| a.has_switch());
|
||||
let opts_flags = parser.app.args.values().filter(|a| a.has_switch());
|
||||
self.write_args(opts_flags)?;
|
||||
}
|
||||
b"flags" => {
|
||||
|
|
|
@ -423,7 +423,7 @@ impl<'a, 'b, 'c, 'z> Usage<'a, 'b, 'c, 'z> {
|
|||
let pmap = if let Some(m) = matcher {
|
||||
desc_reqs
|
||||
.iter()
|
||||
.filter(|a| self.0.positionals.values().any(|p| &p == a))
|
||||
.filter(|a| self.0.app.args.values().any(|p| p.name == **a))
|
||||
.filter(|&pos| !m.contains(pos))
|
||||
.filter_map(|pos| find!(self.0.app, pos))
|
||||
.filter(|&pos| incl_last || !pos.is_set(ArgSettings::Last))
|
||||
|
@ -433,7 +433,7 @@ impl<'a, 'b, 'c, 'z> Usage<'a, 'b, 'c, 'z> {
|
|||
} else {
|
||||
desc_reqs
|
||||
.iter()
|
||||
.filter(|a| self.0.positionals.values().any(|p| &p == a))
|
||||
.filter(|a| self.0.app.args.values().any(|p| p.name == **a))
|
||||
.filter_map(|pos| find!(self.0.app, pos))
|
||||
.filter(|&pos| incl_last || !pos.is_set(ArgSettings::Last))
|
||||
.filter(|pos| !args_in_groups.contains(&pos.name))
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#![feature(nll)]
|
||||
// Third Party
|
||||
#[cfg(feature = "suggestions")]
|
||||
use strsim;
|
||||
|
@ -60,16 +61,16 @@ where
|
|||
return (suffix, Some(candidate));
|
||||
}
|
||||
None => for subcommand in subcommands {
|
||||
let longs = longs!(subcommand);
|
||||
let longs = longs!(subcommand).map(|x| x.to_string_lossy().into_owned()).collect::<Vec<_>>();
|
||||
|
||||
if let Some(candidate) = did_you_mean(arg, longs) {
|
||||
if let Some(candidate) = did_you_mean(arg, longs.iter()) {
|
||||
let suffix = format!(
|
||||
"\n\tDid you mean to put '{}{}' after the subcommand '{}'?",
|
||||
Format::Good("--"),
|
||||
Format::Good(candidate),
|
||||
Format::Good(subcommand.get_name())
|
||||
);
|
||||
return (suffix, Some(candidate));
|
||||
return (suffix, Some(candidate.clone()));
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
|
@ -39,8 +39,6 @@ use parse::{ArgMatcher, SubCommand};
|
|||
use util::OsStrExt2;
|
||||
use INVALID_UTF8;
|
||||
use INTERNAL_ERROR_MSG;
|
||||
use parse::features::suggestions;
|
||||
use output::Usage;
|
||||
|
||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||
#[doc(hidden)]
|
||||
|
@ -72,32 +70,6 @@ where
|
|||
cur_idx: Cell<usize>,
|
||||
}
|
||||
|
||||
// Standalone split borrow functions
|
||||
fn count_arg<'a, 'b>(
|
||||
a: &mut Arg<'a, 'b>,
|
||||
positionals: &mut VecMap<&'a str>,
|
||||
num_opts: &mut usize,
|
||||
num_flags: &mut usize,
|
||||
) {
|
||||
// Count types
|
||||
if a.index.is_some() || (a.short.is_none() && a.long.is_none()) {
|
||||
let i = if a.index.is_none() {
|
||||
(positionals.len() + 1)
|
||||
} else {
|
||||
a.index.unwrap() as usize
|
||||
};
|
||||
a.index = Some(i as u64);
|
||||
a.settings.set(ArgSettings::TakesValue);
|
||||
positionals.insert(i, a.name);
|
||||
} else if a.is_set(ArgSettings::TakesValue) {
|
||||
*num_opts += 1;
|
||||
// a.unified_ord = *num_flags + *num_opts;
|
||||
} else {
|
||||
*num_flags += 1;
|
||||
// a.unified_ord = *num_flags + *num_opts;
|
||||
}
|
||||
}
|
||||
|
||||
// Initializing Methods
|
||||
impl<'a, 'b, 'c> Parser<'a, 'b, 'c>
|
||||
where
|
||||
|
@ -337,22 +309,21 @@ where
|
|||
// Does all the initializing and prepares the parser
|
||||
pub(crate) fn _build(&mut self) {
|
||||
debugln!("Parser::_build;");
|
||||
let mut key: Vec<(KeyType, usize)> = Vec::new();
|
||||
for (i, a) in self.app.args.values().enumerate() {
|
||||
|
||||
for (i, a) in self.app.args.values_mut().enumerate() {
|
||||
if let Some(index) = a.index {
|
||||
self.app.args.insert_key(KeyType::Position(index as usize), i);
|
||||
if let Some(ref index) = a.index {
|
||||
key.push((KeyType::Position((*index) as usize), i));
|
||||
} else {
|
||||
if let Some(c) = a.short {
|
||||
self.app.args.insert_key(KeyType::Short(c), i);
|
||||
if let Some(ref c) = a.short {
|
||||
key.push((KeyType::Short(*c), i));
|
||||
}
|
||||
if let Some(l) = a.long {
|
||||
self.app.args.insert_key(KeyType::Long(&OsStr::new(l)), i);
|
||||
if let Some(ref l) = a.long {
|
||||
key.push((KeyType::Long(OsString::from(l)), i));
|
||||
}
|
||||
if let Some(v) = a.aliases {
|
||||
for (item, _) in &v {
|
||||
self.app
|
||||
.args
|
||||
.insert_key(KeyType::Long(&OsStr::new(item)), i);
|
||||
if let Some(ref v) = a.aliases {
|
||||
for (item, _) in v {
|
||||
key.push((KeyType::Long(OsString::from(item)), i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -377,13 +348,9 @@ where
|
|||
}
|
||||
self.required.push(a.name);
|
||||
}
|
||||
|
||||
count_arg(
|
||||
a,
|
||||
&mut self.positionals,
|
||||
&mut self.num_opts,
|
||||
&mut self.num_flags,
|
||||
);
|
||||
}
|
||||
for (k, i) in key.into_iter() {
|
||||
self.app.args.insert_key(k, i);
|
||||
}
|
||||
|
||||
debug_assert!(self._verify_positionals());
|
||||
|
@ -398,11 +365,8 @@ where
|
|||
.filter(|x| if let KeyType::Position(_) = x { true } else { false })
|
||||
.count())
|
||||
//? what is happening below?
|
||||
}) && self.positionals.values().last().map_or(false, |p_name| {
|
||||
!find!(self.app, p_name)
|
||||
.expect(INTERNAL_ERROR_MSG)
|
||||
.is_set(ArgSettings::Last)
|
||||
}) {
|
||||
}) && self.app.args.iter().any(|(_, v)| v.is_set(ArgSettings::Last))
|
||||
{
|
||||
self.app.settings.set(AS::LowIndexMultiplePositional);
|
||||
}
|
||||
|
||||
|
@ -1092,7 +1056,7 @@ where
|
|||
full_arg.trim_left_matches(b'-')
|
||||
};
|
||||
// opts?? Should probably now check once, then check whether it's opt or flag, or sth else
|
||||
if let Some(opt) = self.app.args.get(KeyType::Long(arg)) {
|
||||
if let Some(opt) = self.app.args.get(KeyType::Long(arg.into())) {
|
||||
debugln!(
|
||||
"Parser::parse_long_arg: Found valid opt '{}'",
|
||||
opt.to_string()
|
||||
|
@ -1511,7 +1475,7 @@ where
|
|||
};
|
||||
}
|
||||
|
||||
for (k, o) in opts!(self.app) {
|
||||
for o in opts!(self.app) {
|
||||
debug!("Parser::add_defaults:iter:{}:", o.name);
|
||||
add_val!(self, o, matcher);
|
||||
}
|
||||
|
@ -1553,16 +1517,18 @@ where
|
|||
{
|
||||
fn did_you_mean_error(&self, arg: &str, matcher: &mut ArgMatcher<'a>) -> ClapResult<()> {
|
||||
// Didn't match a flag or option
|
||||
let longs = longs!(self.app).map(|x| x.to_string_lossy().into_owned()).collect::<Vec<_>>();
|
||||
|
||||
let suffix =
|
||||
suggestions::did_you_mean_flag_suffix(arg, longs!(self.app), &*self.app.subcommands);
|
||||
suggestions::did_you_mean_flag_suffix(arg, longs.iter().map(|ref x| &x[..] ), &*self.app.subcommands);
|
||||
|
||||
// Add the arg to the matches to build a proper usage string
|
||||
if let Some(name) = suffix.1 {
|
||||
if let Some(opt) = self.app.args.get(KeyType::Long(&OsStr::new(name))) {
|
||||
if let Some(opt) = self.app.args.get(KeyType::Long(OsString::from(name))) {
|
||||
self.groups_for_arg(&*opt.name)
|
||||
.and_then(|grps| Some(matcher.inc_occurrences_of(&*grps)));
|
||||
matcher.insert(&*opt.name);
|
||||
} else if let Some(flg) = self.app.args.get(KeyType::Long(&OsStr::new(name))) {
|
||||
} else if let Some(flg) = self.app.args.get(KeyType::Long(OsString::from(name))) {
|
||||
self.groups_for_arg(&*flg.name)
|
||||
.and_then(|grps| Some(matcher.inc_occurrences_of(&*grps)));
|
||||
matcher.insert(&*flg.name);
|
||||
|
|
Loading…
Reference in a new issue