mirror of
https://github.com/clap-rs/clap
synced 2024-12-14 14:52:33 +00:00
Merge #1736
1736: WIP: get rig of pub doc(hidden) r=pksunkara a=CreepySkeleton Co-authored-by: CreepySkeleton <creepy-skeleton@yandex.ru>
This commit is contained in:
commit
874fbcf807
14 changed files with 295 additions and 238 deletions
|
@ -4,7 +4,7 @@ mod shells;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
// Internal
|
// Internal
|
||||||
use clap::{find_subcmd, flags, match_alias, subcommands, App, AppSettings, Arg};
|
use clap::{find_subcmd, flags, match_alias, App, AppSettings, Arg};
|
||||||
pub use shells::*;
|
pub use shells::*;
|
||||||
|
|
||||||
/// Generator trait which can be used to write generators
|
/// Generator trait which can be used to write generators
|
||||||
|
@ -61,7 +61,11 @@ pub trait Generator {
|
||||||
fn all_subcommands(app: &App) -> Vec<(String, String)> {
|
fn all_subcommands(app: &App) -> Vec<(String, String)> {
|
||||||
let mut subcmds: Vec<_> = Self::subcommands(app);
|
let mut subcmds: Vec<_> = Self::subcommands(app);
|
||||||
|
|
||||||
for sc_v in subcommands!(app).map(|s| Self::all_subcommands(&s)) {
|
for sc_v in app
|
||||||
|
.get_subcommands()
|
||||||
|
.iter()
|
||||||
|
.map(|s| Self::all_subcommands(&s))
|
||||||
|
{
|
||||||
subcmds.extend(sc_v);
|
subcmds.extend(sc_v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +92,7 @@ pub trait Generator {
|
||||||
/// Subcommand `rustup toolchain install` would be converted to
|
/// Subcommand `rustup toolchain install` would be converted to
|
||||||
/// `("install", "rustup toolchain install")`.
|
/// `("install", "rustup toolchain install")`.
|
||||||
fn subcommands(p: &App) -> Vec<(String, String)> {
|
fn subcommands(p: &App) -> Vec<(String, String)> {
|
||||||
debugln!("subcommands: name={}", p.name);
|
debugln!("subcommands: name={}", p.get_name());
|
||||||
debugln!("subcommands: Has subcommands...{:?}", p.has_subcommands());
|
debugln!("subcommands: Has subcommands...{:?}", p.has_subcommands());
|
||||||
|
|
||||||
let mut subcmds = vec![];
|
let mut subcmds = vec![];
|
||||||
|
@ -97,16 +101,16 @@ pub trait Generator {
|
||||||
return subcmds;
|
return subcmds;
|
||||||
}
|
}
|
||||||
|
|
||||||
for sc in &p.subcommands {
|
for sc in p.get_subcommands() {
|
||||||
let sc_bin_name = sc.get_bin_name().unwrap();
|
let sc_bin_name = sc.get_bin_name().unwrap();
|
||||||
|
|
||||||
debugln!(
|
debugln!(
|
||||||
"subcommands:iter: name={}, bin_name={}",
|
"subcommands:iter: name={}, bin_name={}",
|
||||||
sc.name,
|
sc.get_name(),
|
||||||
sc_bin_name
|
sc_bin_name
|
||||||
);
|
);
|
||||||
|
|
||||||
subcmds.push((sc.name.clone(), sc_bin_name.to_string()));
|
subcmds.push((sc.get_name().to_string(), sc_bin_name.to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
subcmds
|
subcmds
|
||||||
|
@ -115,15 +119,14 @@ pub trait Generator {
|
||||||
/// Gets all the short options and flags of a [`clap::App`](../clap/struct.App.html).
|
/// Gets all the short options and flags of a [`clap::App`](../clap/struct.App.html).
|
||||||
/// Includes `h` and `V` depending on the [`clap::AppSettings`](../clap/enum.AppSettings.html).
|
/// Includes `h` and `V` depending on the [`clap::AppSettings`](../clap/enum.AppSettings.html).
|
||||||
fn shorts<'b>(p: &'b App<'b>) -> Vec<char> {
|
fn shorts<'b>(p: &'b App<'b>) -> Vec<char> {
|
||||||
debugln!("shorts: name={}", p.name);
|
debugln!("shorts: name={}", p.get_name());
|
||||||
|
|
||||||
let mut shorts: Vec<char> = p
|
let mut shorts: Vec<char> = p
|
||||||
.args
|
.get_arguments()
|
||||||
.args
|
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|a| {
|
.filter_map(|a| {
|
||||||
if a.index.is_none() && a.short.is_some() {
|
if a.get_index().is_none() && a.get_short().is_some() {
|
||||||
Some(a.short.unwrap())
|
Some(a.get_short().unwrap())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -144,15 +147,14 @@ pub trait Generator {
|
||||||
/// Gets all the long options and flags of a [`clap::App`](../clap/struct.App.html).
|
/// Gets all the long options and flags of a [`clap::App`](../clap/struct.App.html).
|
||||||
/// Includes `help` and `version` depending on the [`clap::AppSettings`](../clap/enum.AppSettings.html).
|
/// Includes `help` and `version` depending on the [`clap::AppSettings`](../clap/enum.AppSettings.html).
|
||||||
fn longs<'b>(p: &'b App<'b>) -> Vec<String> {
|
fn longs<'b>(p: &'b App<'b>) -> Vec<String> {
|
||||||
debugln!("longs: name={}", p.name);
|
debugln!("longs: name={}", p.get_name());
|
||||||
|
|
||||||
let mut longs: Vec<String> = p
|
let mut longs: Vec<String> = p
|
||||||
.args
|
.get_arguments()
|
||||||
.args
|
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|a| {
|
.filter_map(|a| {
|
||||||
if a.index.is_none() && a.long.is_some() {
|
if a.get_index().is_none() && a.get_long().is_some() {
|
||||||
Some(a.long.unwrap().to_string())
|
Some(a.get_long().unwrap().to_string())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -175,11 +177,11 @@ pub trait Generator {
|
||||||
/// Gets all the flags of a [`clap::App`](../clap/struct.App.html).
|
/// Gets all the flags of a [`clap::App`](../clap/struct.App.html).
|
||||||
/// Includes `help` and `version` depending on the [`clap::AppSettings`](../clap/enum.AppSettings.html).
|
/// Includes `help` and `version` depending on the [`clap::AppSettings`](../clap/enum.AppSettings.html).
|
||||||
fn flags<'b>(p: &'b App<'b>) -> Vec<Arg> {
|
fn flags<'b>(p: &'b App<'b>) -> Vec<Arg> {
|
||||||
debugln!("flags: name={}", p.name);
|
debugln!("flags: name={}", p.get_name());
|
||||||
|
|
||||||
let mut flags: Vec<_> = flags!(p).cloned().collect();
|
let mut flags: Vec<_> = flags!(p).cloned().collect();
|
||||||
|
|
||||||
if flags.iter().find(|x| x.name == "help").is_none() {
|
if flags.iter().find(|x| x.get_name() == "help").is_none() {
|
||||||
flags.push(
|
flags.push(
|
||||||
Arg::with_name("help")
|
Arg::with_name("help")
|
||||||
.short('h')
|
.short('h')
|
||||||
|
@ -189,7 +191,7 @@ pub trait Generator {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !p.is_set(AppSettings::DisableVersion)
|
if !p.is_set(AppSettings::DisableVersion)
|
||||||
&& flags.iter().find(|x| x.name == "version").is_none()
|
&& flags.iter().find(|x| x.get_name() == "version").is_none()
|
||||||
{
|
{
|
||||||
flags.push(
|
flags.push(
|
||||||
Arg::with_name("version")
|
Arg::with_name("version")
|
||||||
|
@ -267,7 +269,7 @@ mod tests {
|
||||||
let app = common();
|
let app = common();
|
||||||
let sc_app = Foo::find_subcommand_with_path(&app, "test config".split(' ').collect());
|
let sc_app = Foo::find_subcommand_with_path(&app, "test config".split(' ').collect());
|
||||||
|
|
||||||
assert_eq!(sc_app.name, "config");
|
assert_eq!(sc_app.get_name(), "config");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -276,15 +278,15 @@ mod tests {
|
||||||
let flags = Foo::flags(&app);
|
let flags = Foo::flags(&app);
|
||||||
|
|
||||||
assert_eq!(flags.len(), 2);
|
assert_eq!(flags.len(), 2);
|
||||||
assert_eq!(flags[0].long, Some("help"));
|
assert_eq!(flags[0].get_long(), Some("help"));
|
||||||
assert_eq!(flags[1].long, Some("version"));
|
assert_eq!(flags[1].get_long(), Some("version"));
|
||||||
|
|
||||||
let sc_flags = Foo::flags(Foo::find_subcommand_with_path(&app, vec!["test"]));
|
let sc_flags = Foo::flags(Foo::find_subcommand_with_path(&app, vec!["test"]));
|
||||||
|
|
||||||
assert_eq!(sc_flags.len(), 3);
|
assert_eq!(sc_flags.len(), 3);
|
||||||
assert_eq!(sc_flags[0].long, Some("file"));
|
assert_eq!(sc_flags[0].get_long(), Some("file"));
|
||||||
assert_eq!(sc_flags[1].long, Some("help"));
|
assert_eq!(sc_flags[1].get_long(), Some("help"));
|
||||||
assert_eq!(sc_flags[2].long, Some("version"));
|
assert_eq!(sc_flags[2].get_long(), Some("version"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -147,7 +147,7 @@ fn option_details_for_path(app: &App, path: &str) -> String {
|
||||||
let mut opts = String::new();
|
let mut opts = String::new();
|
||||||
|
|
||||||
for o in opts!(p) {
|
for o in opts!(p) {
|
||||||
if let Some(l) = o.long {
|
if let Some(l) = o.get_long() {
|
||||||
opts = format!(
|
opts = format!(
|
||||||
"{}
|
"{}
|
||||||
--{})
|
--{})
|
||||||
|
@ -160,7 +160,7 @@ fn option_details_for_path(app: &App, path: &str) -> String {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(s) = o.short {
|
if let Some(s) = o.get_short() {
|
||||||
opts = format!(
|
opts = format!(
|
||||||
"{}
|
"{}
|
||||||
-{})
|
-{})
|
||||||
|
@ -180,7 +180,7 @@ fn option_details_for_path(app: &App, path: &str) -> String {
|
||||||
fn vals_for(o: &Arg) -> String {
|
fn vals_for(o: &Arg) -> String {
|
||||||
debugln!("Bash::vals_for: o={}", o.name);
|
debugln!("Bash::vals_for: o={}", o.name);
|
||||||
|
|
||||||
if let Some(ref vals) = o.possible_vals {
|
if let Some(ref vals) = o.get_possible_values() {
|
||||||
format!("$(compgen -W \"{}\" -- ${{cur}})", vals.join(" "))
|
format!("$(compgen -W \"{}\" -- ${{cur}})", vals.join(" "))
|
||||||
} else {
|
} else {
|
||||||
String::from("$(compgen -f ${cur})")
|
String::from("$(compgen -f ${cur})")
|
||||||
|
|
|
@ -71,22 +71,22 @@ fn generate_inner<'b>(
|
||||||
let command_name = if previous_command_name.is_empty() {
|
let command_name = if previous_command_name.is_empty() {
|
||||||
p.get_bin_name().expect(INTERNAL_ERROR_MSG).to_string()
|
p.get_bin_name().expect(INTERNAL_ERROR_MSG).to_string()
|
||||||
} else {
|
} else {
|
||||||
format!("{};{}", previous_command_name, &p.name)
|
format!("{};{}", previous_command_name, &p.get_name())
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut completions = String::new();
|
let mut completions = String::new();
|
||||||
let preamble = String::from("\n cand ");
|
let preamble = String::from("\n cand ");
|
||||||
|
|
||||||
for option in opts!(p) {
|
for option in opts!(p) {
|
||||||
if let Some(data) = option.short {
|
if let Some(data) = option.get_short() {
|
||||||
let tooltip = get_tooltip(option.help, data);
|
let tooltip = get_tooltip(option.get_help(), data);
|
||||||
|
|
||||||
completions.push_str(&preamble);
|
completions.push_str(&preamble);
|
||||||
completions.push_str(format!("-{} '{}'", data, tooltip).as_str());
|
completions.push_str(format!("-{} '{}'", data, tooltip).as_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(data) = option.long {
|
if let Some(data) = option.get_long() {
|
||||||
let tooltip = get_tooltip(option.help, data);
|
let tooltip = get_tooltip(option.get_help(), data);
|
||||||
|
|
||||||
completions.push_str(&preamble);
|
completions.push_str(&preamble);
|
||||||
completions.push_str(format!("--{} '{}'", data, tooltip).as_str());
|
completions.push_str(format!("--{} '{}'", data, tooltip).as_str());
|
||||||
|
@ -94,24 +94,24 @@ fn generate_inner<'b>(
|
||||||
}
|
}
|
||||||
|
|
||||||
for flag in Elvish::flags(p) {
|
for flag in Elvish::flags(p) {
|
||||||
if let Some(data) = flag.short {
|
if let Some(data) = flag.get_short() {
|
||||||
let tooltip = get_tooltip(flag.help, data);
|
let tooltip = get_tooltip(flag.get_help(), data);
|
||||||
|
|
||||||
completions.push_str(&preamble);
|
completions.push_str(&preamble);
|
||||||
completions.push_str(format!("-{} '{}'", data, tooltip).as_str());
|
completions.push_str(format!("-{} '{}'", data, tooltip).as_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(data) = flag.long {
|
if let Some(data) = flag.get_long() {
|
||||||
let tooltip = get_tooltip(flag.help, data);
|
let tooltip = get_tooltip(flag.get_help(), data);
|
||||||
|
|
||||||
completions.push_str(&preamble);
|
completions.push_str(&preamble);
|
||||||
completions.push_str(format!("--{} '{}'", data, tooltip).as_str());
|
completions.push_str(format!("--{} '{}'", data, tooltip).as_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for subcommand in &p.subcommands {
|
for subcommand in p.get_subcommands() {
|
||||||
let data = &subcommand.name;
|
let data = &subcommand.get_name();
|
||||||
let tooltip = get_tooltip(subcommand.about, data);
|
let tooltip = get_tooltip(subcommand.get_about(), data);
|
||||||
|
|
||||||
completions.push_str(&preamble);
|
completions.push_str(&preamble);
|
||||||
completions.push_str(format!("{} '{}'", data, tooltip).as_str());
|
completions.push_str(format!("{} '{}'", data, tooltip).as_str());
|
||||||
|
@ -124,7 +124,7 @@ fn generate_inner<'b>(
|
||||||
&command_name, completions
|
&command_name, completions
|
||||||
);
|
);
|
||||||
|
|
||||||
for subcommand in &p.subcommands {
|
for subcommand in p.get_subcommands() {
|
||||||
let subcommand_subcommands_cases = generate_inner(&subcommand, &command_name, names);
|
let subcommand_subcommands_cases = generate_inner(&subcommand, &command_name, names);
|
||||||
subcommands_cases.push_str(&subcommand_subcommands_cases);
|
subcommands_cases.push_str(&subcommand_subcommands_cases);
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ fn gen_fish_inner(root_command: &str, app: &App, buffer: &mut String) {
|
||||||
if root_command == bin_name {
|
if root_command == bin_name {
|
||||||
basic_template.push_str("\"__fish_use_subcommand\"");
|
basic_template.push_str("\"__fish_use_subcommand\"");
|
||||||
} else {
|
} else {
|
||||||
bin_name = &app.name;
|
bin_name = &app.get_name();
|
||||||
basic_template.push_str(format!("\"__fish_seen_subcommand_from {}\"", bin_name).as_str());
|
basic_template.push_str(format!("\"__fish_seen_subcommand_from {}\"", bin_name).as_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,19 +57,19 @@ fn gen_fish_inner(root_command: &str, app: &App, buffer: &mut String) {
|
||||||
for option in opts!(app) {
|
for option in opts!(app) {
|
||||||
let mut template = basic_template.clone();
|
let mut template = basic_template.clone();
|
||||||
|
|
||||||
if let Some(data) = option.short {
|
if let Some(data) = option.get_short() {
|
||||||
template.push_str(format!(" -s {}", data).as_str());
|
template.push_str(format!(" -s {}", data).as_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(data) = option.long {
|
if let Some(data) = option.get_long() {
|
||||||
template.push_str(format!(" -l {}", data).as_str());
|
template.push_str(format!(" -l {}", data).as_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(data) = option.help {
|
if let Some(data) = option.get_help() {
|
||||||
template.push_str(format!(" -d '{}'", escape_string(data)).as_str());
|
template.push_str(format!(" -d '{}'", escape_string(data)).as_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref data) = option.possible_vals {
|
if let Some(ref data) = option.get_possible_values() {
|
||||||
template.push_str(format!(" -r -f -a \"{}\"", data.join(" ")).as_str());
|
template.push_str(format!(" -r -f -a \"{}\"", data.join(" ")).as_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,15 +80,15 @@ fn gen_fish_inner(root_command: &str, app: &App, buffer: &mut String) {
|
||||||
for flag in Fish::flags(app) {
|
for flag in Fish::flags(app) {
|
||||||
let mut template = basic_template.clone();
|
let mut template = basic_template.clone();
|
||||||
|
|
||||||
if let Some(data) = flag.short {
|
if let Some(data) = flag.get_short() {
|
||||||
template.push_str(format!(" -s {}", data).as_str());
|
template.push_str(format!(" -s {}", data).as_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(data) = flag.long {
|
if let Some(data) = flag.get_long() {
|
||||||
template.push_str(format!(" -l {}", data).as_str());
|
template.push_str(format!(" -l {}", data).as_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(data) = flag.help {
|
if let Some(data) = flag.get_help() {
|
||||||
template.push_str(format!(" -d '{}'", escape_string(data)).as_str());
|
template.push_str(format!(" -d '{}'", escape_string(data)).as_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,13 +96,13 @@ fn gen_fish_inner(root_command: &str, app: &App, buffer: &mut String) {
|
||||||
buffer.push_str("\n");
|
buffer.push_str("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
for subcommand in &app.subcommands {
|
for subcommand in app.get_subcommands() {
|
||||||
let mut template = basic_template.clone();
|
let mut template = basic_template.clone();
|
||||||
|
|
||||||
template.push_str(" -f");
|
template.push_str(" -f");
|
||||||
template.push_str(format!(" -a \"{}\"", &subcommand.name).as_str());
|
template.push_str(format!(" -a \"{}\"", &subcommand.get_name()).as_str());
|
||||||
|
|
||||||
if let Some(data) = subcommand.about {
|
if let Some(data) = subcommand.get_about() {
|
||||||
template.push_str(format!(" -d '{}'", escape_string(data)).as_str())
|
template.push_str(format!(" -d '{}'", escape_string(data)).as_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ fn gen_fish_inner(root_command: &str, app: &App, buffer: &mut String) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate options of subcommands
|
// generate options of subcommands
|
||||||
for subcommand in &app.subcommands {
|
for subcommand in app.get_subcommands() {
|
||||||
gen_fish_inner(root_command, subcommand, buffer);
|
gen_fish_inner(root_command, subcommand, buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,15 +78,15 @@ fn generate_inner<'b>(
|
||||||
let command_name = if previous_command_name.is_empty() {
|
let command_name = if previous_command_name.is_empty() {
|
||||||
p.get_bin_name().expect(INTERNAL_ERROR_MSG).to_string()
|
p.get_bin_name().expect(INTERNAL_ERROR_MSG).to_string()
|
||||||
} else {
|
} else {
|
||||||
format!("{};{}", previous_command_name, &p.name)
|
format!("{};{}", previous_command_name, &p.get_name())
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut completions = String::new();
|
let mut completions = String::new();
|
||||||
let preamble = String::from("\n [CompletionResult]::new(");
|
let preamble = String::from("\n [CompletionResult]::new(");
|
||||||
|
|
||||||
for option in opts!(p) {
|
for option in opts!(p) {
|
||||||
if let Some(data) = option.short {
|
if let Some(data) = option.get_short() {
|
||||||
let tooltip = get_tooltip(option.help, data);
|
let tooltip = get_tooltip(option.get_help(), data);
|
||||||
|
|
||||||
completions.push_str(&preamble);
|
completions.push_str(&preamble);
|
||||||
completions.push_str(
|
completions.push_str(
|
||||||
|
@ -98,8 +98,8 @@ fn generate_inner<'b>(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(data) = option.long {
|
if let Some(data) = option.get_long() {
|
||||||
let tooltip = get_tooltip(option.help, data);
|
let tooltip = get_tooltip(option.get_help(), data);
|
||||||
|
|
||||||
completions.push_str(&preamble);
|
completions.push_str(&preamble);
|
||||||
completions.push_str(
|
completions.push_str(
|
||||||
|
@ -113,8 +113,8 @@ fn generate_inner<'b>(
|
||||||
}
|
}
|
||||||
|
|
||||||
for flag in PowerShell::flags(p) {
|
for flag in PowerShell::flags(p) {
|
||||||
if let Some(data) = flag.short {
|
if let Some(data) = flag.get_short() {
|
||||||
let tooltip = get_tooltip(flag.help, data);
|
let tooltip = get_tooltip(flag.get_help(), data);
|
||||||
|
|
||||||
completions.push_str(&preamble);
|
completions.push_str(&preamble);
|
||||||
completions.push_str(
|
completions.push_str(
|
||||||
|
@ -126,8 +126,8 @@ fn generate_inner<'b>(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(data) = flag.long {
|
if let Some(data) = flag.get_long() {
|
||||||
let tooltip = get_tooltip(flag.help, data);
|
let tooltip = get_tooltip(flag.get_help(), data);
|
||||||
|
|
||||||
completions.push_str(&preamble);
|
completions.push_str(&preamble);
|
||||||
completions.push_str(
|
completions.push_str(
|
||||||
|
@ -140,9 +140,9 @@ fn generate_inner<'b>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for subcommand in subcommands!(p) {
|
for subcommand in p.get_subcommands() {
|
||||||
let data = &subcommand.name;
|
let data = &subcommand.get_name();
|
||||||
let tooltip = get_tooltip(subcommand.about, data);
|
let tooltip = get_tooltip(subcommand.get_about(), data);
|
||||||
|
|
||||||
completions.push_str(&preamble);
|
completions.push_str(&preamble);
|
||||||
completions.push_str(
|
completions.push_str(
|
||||||
|
@ -162,7 +162,7 @@ fn generate_inner<'b>(
|
||||||
&command_name, completions
|
&command_name, completions
|
||||||
);
|
);
|
||||||
|
|
||||||
for subcommand in &p.subcommands {
|
for subcommand in p.get_subcommands() {
|
||||||
let subcommand_subcommands_cases = generate_inner(&subcommand, &command_name, names);
|
let subcommand_subcommands_cases = generate_inner(&subcommand, &command_name, names);
|
||||||
subcommands_cases.push_str(&subcommand_subcommands_cases);
|
subcommands_cases.push_str(&subcommand_subcommands_cases);
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,7 +149,7 @@ fn subcommands_of(p: &App) -> String {
|
||||||
"\"{name}:{help}\" \\",
|
"\"{name}:{help}\" \\",
|
||||||
name = n,
|
name = n,
|
||||||
help = sc
|
help = sc
|
||||||
.about
|
.get_about()
|
||||||
.unwrap_or("")
|
.unwrap_or("")
|
||||||
.replace("[", "\\[")
|
.replace("[", "\\[")
|
||||||
.replace("]", "\\]")
|
.replace("]", "\\]")
|
||||||
|
@ -161,17 +161,15 @@ fn subcommands_of(p: &App) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
// The subcommands
|
// The subcommands
|
||||||
for sc in subcommands!(p) {
|
for sc in p.get_subcommands() {
|
||||||
debugln!("Zsh::subcommands_of:iter: subcommand={}", sc.name);
|
debugln!("Zsh::subcommands_of:iter: subcommand={}", sc.get_name());
|
||||||
|
|
||||||
add_sc(sc, &sc.name, &mut ret);
|
add_sc(sc, &sc.get_name(), &mut ret);
|
||||||
|
|
||||||
if let Some(ref v) = sc.aliases {
|
for alias in sc.get_visible_aliases() {
|
||||||
for alias in v.iter().filter(|&&(_, vis)| vis).map(|&(n, _)| n) {
|
|
||||||
add_sc(sc, alias, &mut ret);
|
add_sc(sc, alias, &mut ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ret.join("\n")
|
ret.join("\n")
|
||||||
}
|
}
|
||||||
|
@ -248,7 +246,7 @@ fn get_subcommands_of(p: &App) -> String {
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
esac",
|
esac",
|
||||||
name = p.name,
|
name = p.get_name(),
|
||||||
name_hyphen = p.get_bin_name().unwrap().replace(" ", "-"),
|
name_hyphen = p.get_bin_name().unwrap().replace(" ", "-"),
|
||||||
subcommands = subcmds.join("\n"),
|
subcommands = subcmds.join("\n"),
|
||||||
pos = positionals!(p).count() + 1
|
pos = positionals!(p).count() + 1
|
||||||
|
@ -297,14 +295,14 @@ fn get_args_of(p: &App) -> String {
|
||||||
let sc_or_a = if p.has_subcommands() {
|
let sc_or_a = if p.has_subcommands() {
|
||||||
format!(
|
format!(
|
||||||
"\":: :_{name}_commands\" \\",
|
"\":: :_{name}_commands\" \\",
|
||||||
name = p.bin_name.as_ref().unwrap().replace(" ", "__")
|
name = p.get_bin_name().as_ref().unwrap().replace(" ", "__")
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
String::new()
|
String::new()
|
||||||
};
|
};
|
||||||
|
|
||||||
let sc = if p.has_subcommands() {
|
let sc = if p.has_subcommands() {
|
||||||
format!("\"*::: :->{name}\" \\", name = p.name)
|
format!("\"*::: :->{name}\" \\", name = p.get_name())
|
||||||
} else {
|
} else {
|
||||||
String::new()
|
String::new()
|
||||||
};
|
};
|
||||||
|
@ -358,16 +356,10 @@ fn write_opts_of(p: &App) -> String {
|
||||||
let mut ret = vec![];
|
let mut ret = vec![];
|
||||||
|
|
||||||
for o in opts!(p) {
|
for o in opts!(p) {
|
||||||
debugln!("Zsh::write_opts_of:iter: o={}", o.name);
|
debugln!("Zsh::write_opts_of:iter: o={}", o.get_name());
|
||||||
|
|
||||||
let help = o.help.map_or(String::new(), escape_help);
|
let help = o.get_help().map_or(String::new(), escape_help);
|
||||||
let mut conflicts = get_zsh_arg_conflicts!(p, o, INTERNAL_ERROR_MSG);
|
let conflicts = arg_conflicts(p, o);
|
||||||
|
|
||||||
conflicts = if conflicts.is_empty() {
|
|
||||||
String::new()
|
|
||||||
} else {
|
|
||||||
format!("({})", conflicts)
|
|
||||||
};
|
|
||||||
|
|
||||||
// @TODO @soundness should probably be either multiple occurrences or multiple values and
|
// @TODO @soundness should probably be either multiple occurrences or multiple values and
|
||||||
// not both
|
// not both
|
||||||
|
@ -379,7 +371,7 @@ fn write_opts_of(p: &App) -> String {
|
||||||
""
|
""
|
||||||
};
|
};
|
||||||
|
|
||||||
let pv = if let Some(ref pv_vec) = o.possible_vals {
|
let pv = if let Some(ref pv_vec) = o.get_possible_values() {
|
||||||
format!(
|
format!(
|
||||||
": :({})",
|
": :({})",
|
||||||
pv_vec
|
pv_vec
|
||||||
|
@ -392,7 +384,7 @@ fn write_opts_of(p: &App) -> String {
|
||||||
String::new()
|
String::new()
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(short) = o.short {
|
if let Some(short) = o.get_short() {
|
||||||
let s = format!(
|
let s = format!(
|
||||||
"'{conflicts}{multiple}-{arg}+[{help}]{possible_values}' \\",
|
"'{conflicts}{multiple}-{arg}+[{help}]{possible_values}' \\",
|
||||||
conflicts = conflicts,
|
conflicts = conflicts,
|
||||||
|
@ -406,7 +398,7 @@ fn write_opts_of(p: &App) -> String {
|
||||||
ret.push(s);
|
ret.push(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(long) = o.long {
|
if let Some(long) = o.get_long() {
|
||||||
let l = format!(
|
let l = format!(
|
||||||
"'{conflicts}{multiple}--{arg}=[{help}]{possible_values}' \\",
|
"'{conflicts}{multiple}--{arg}=[{help}]{possible_values}' \\",
|
||||||
conflicts = conflicts,
|
conflicts = conflicts,
|
||||||
|
@ -424,22 +416,37 @@ fn write_opts_of(p: &App) -> String {
|
||||||
ret.join("\n")
|
ret.join("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn arg_conflicts(app: &App, arg: &Arg) -> String {
|
||||||
|
let conflicts = app.get_arg_conflicts_with(arg);
|
||||||
|
|
||||||
|
if conflicts.is_empty() {
|
||||||
|
return String::new();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut res = vec![];
|
||||||
|
for conflict in conflicts {
|
||||||
|
if let Some(s) = conflict.get_short() {
|
||||||
|
res.push(format!("-{}", s));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(l) = conflict.get_long() {
|
||||||
|
res.push(format!("--{}", l));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
format!("({})", res.join(" "))
|
||||||
|
}
|
||||||
|
|
||||||
fn write_flags_of(p: &App) -> String {
|
fn write_flags_of(p: &App) -> String {
|
||||||
debugln!("Zsh::write_flags_of;");
|
debugln!("Zsh::write_flags_of;");
|
||||||
|
|
||||||
let mut ret = vec![];
|
let mut ret = vec![];
|
||||||
|
|
||||||
for f in Zsh::flags(p) {
|
for f in Zsh::flags(p) {
|
||||||
debugln!("Zsh::write_flags_of:iter: f={}", f.name);
|
debugln!("Zsh::write_flags_of:iter: f={}", f.get_name());
|
||||||
|
|
||||||
let help = f.help.map_or(String::new(), escape_help);
|
let help = f.get_help().map_or(String::new(), escape_help);
|
||||||
let mut conflicts = get_zsh_arg_conflicts!(p, f, INTERNAL_ERROR_MSG);
|
let conflicts = arg_conflicts(p, &f);
|
||||||
|
|
||||||
conflicts = if conflicts.is_empty() {
|
|
||||||
String::new()
|
|
||||||
} else {
|
|
||||||
format!("({})", conflicts)
|
|
||||||
};
|
|
||||||
|
|
||||||
let multiple = if f.is_set(ArgSettings::MultipleOccurrences) {
|
let multiple = if f.is_set(ArgSettings::MultipleOccurrences) {
|
||||||
"*"
|
"*"
|
||||||
|
@ -447,7 +454,7 @@ fn write_flags_of(p: &App) -> String {
|
||||||
""
|
""
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(short) = f.short {
|
if let Some(short) = f.get_short() {
|
||||||
let s = format!(
|
let s = format!(
|
||||||
"'{conflicts}{multiple}-{arg}[{help}]' \\",
|
"'{conflicts}{multiple}-{arg}[{help}]' \\",
|
||||||
multiple = multiple,
|
multiple = multiple,
|
||||||
|
@ -461,7 +468,7 @@ fn write_flags_of(p: &App) -> String {
|
||||||
ret.push(s);
|
ret.push(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(long) = f.long {
|
if let Some(long) = f.get_long() {
|
||||||
let l = format!(
|
let l = format!(
|
||||||
"'{conflicts}{multiple}--{arg}[{help}]' \\",
|
"'{conflicts}{multiple}--{arg}[{help}]' \\",
|
||||||
conflicts = conflicts,
|
conflicts = conflicts,
|
||||||
|
@ -485,7 +492,7 @@ fn write_positionals_of(p: &App) -> String {
|
||||||
let mut ret = vec![];
|
let mut ret = vec![];
|
||||||
|
|
||||||
for arg in positionals!(p) {
|
for arg in positionals!(p) {
|
||||||
debugln!("Zsh::write_positionals_of:iter: arg={}", arg.name);
|
debugln!("Zsh::write_positionals_of:iter: arg={}", arg.get_name());
|
||||||
|
|
||||||
let optional = if !arg.is_set(ArgSettings::Required) {
|
let optional = if !arg.is_set(ArgSettings::Required) {
|
||||||
":"
|
":"
|
||||||
|
@ -496,16 +503,15 @@ fn write_positionals_of(p: &App) -> String {
|
||||||
let a = format!(
|
let a = format!(
|
||||||
"'{optional}:{name}{help}:{action}' \\",
|
"'{optional}:{name}{help}:{action}' \\",
|
||||||
optional = optional,
|
optional = optional,
|
||||||
name = arg.name,
|
name = arg.get_name(),
|
||||||
help = arg
|
help = arg
|
||||||
.help
|
.get_help()
|
||||||
.map_or("".to_owned(), |v| " -- ".to_owned() + v)
|
.map_or("".to_owned(), |v| " -- ".to_owned() + v)
|
||||||
.replace("[", "\\[")
|
.replace("[", "\\[")
|
||||||
.replace("]", "\\]")
|
.replace("]", "\\]")
|
||||||
.replace(":", "\\:"),
|
.replace(":", "\\:"),
|
||||||
action = arg
|
action = arg
|
||||||
.possible_vals
|
.get_possible_values()
|
||||||
.as_ref()
|
|
||||||
.map_or("_files".to_owned(), |values| {
|
.map_or("_files".to_owned(), |values| {
|
||||||
format!(
|
format!(
|
||||||
"({})",
|
"({})",
|
||||||
|
|
|
@ -178,7 +178,7 @@ where
|
||||||
G: Generator,
|
G: Generator,
|
||||||
S: Into<String>,
|
S: Into<String>,
|
||||||
{
|
{
|
||||||
app.bin_name = Some(bin_name.into());
|
app.set_bin_name(bin_name);
|
||||||
|
|
||||||
if !app.is_set(clap::AppSettings::Built) {
|
if !app.is_set(clap::AppSettings::Built) {
|
||||||
app._build();
|
app._build();
|
||||||
|
|
|
@ -7,30 +7,6 @@ macro_rules! w {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! get_zsh_arg_conflicts {
|
|
||||||
($app:expr, $arg:ident, $msg:ident) => {
|
|
||||||
if let Some(ref conf_vec) = $arg.blacklist {
|
|
||||||
let mut v = vec![];
|
|
||||||
|
|
||||||
for arg_name in conf_vec {
|
|
||||||
let arg = find!($app, arg_name).expect($msg);
|
|
||||||
|
|
||||||
if let Some(s) = arg.short {
|
|
||||||
v.push(format!("-{}", s));
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(l) = arg.long {
|
|
||||||
v.push(format!("--{}", l));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
v.join(" ")
|
|
||||||
} else {
|
|
||||||
String::new()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "debug")]
|
#[cfg(feature = "debug")]
|
||||||
#[cfg_attr(feature = "debug", macro_use)]
|
#[cfg_attr(feature = "debug", macro_use)]
|
||||||
#[cfg_attr(feature = "debug", allow(unused_macros))]
|
#[cfg_attr(feature = "debug", allow(unused_macros))]
|
||||||
|
@ -70,18 +46,3 @@ mod debug_macros {
|
||||||
($fmt:expr, $($arg:tt)*) => {};
|
($fmt:expr, $($arg:tt)*) => {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! find {
|
|
||||||
($app:expr, $name:expr, $what:ident) => {
|
|
||||||
$what!($app).find(|a| &a.name == $name)
|
|
||||||
};
|
|
||||||
($app:expr, $name:expr) => {
|
|
||||||
$app.args.args.iter().find(|a| {
|
|
||||||
if let Some(v) = a.index {
|
|
||||||
&v == $name
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
|
@ -70,20 +70,16 @@ pub(crate) enum Propagation {
|
||||||
#[derive(Default, Debug, Clone)]
|
#[derive(Default, Debug, Clone)]
|
||||||
pub struct App<'b> {
|
pub struct App<'b> {
|
||||||
pub(crate) id: Id,
|
pub(crate) id: Id,
|
||||||
#[doc(hidden)]
|
pub(crate) name: String,
|
||||||
pub name: String,
|
pub(crate) bin_name: Option<String>,
|
||||||
#[doc(hidden)]
|
|
||||||
pub bin_name: Option<String>,
|
|
||||||
pub(crate) author: Option<&'b str>,
|
pub(crate) author: Option<&'b str>,
|
||||||
pub(crate) version: Option<&'b str>,
|
pub(crate) version: Option<&'b str>,
|
||||||
pub(crate) long_version: Option<&'b str>,
|
pub(crate) long_version: Option<&'b str>,
|
||||||
#[doc(hidden)]
|
pub(crate) about: Option<&'b str>,
|
||||||
pub about: Option<&'b str>,
|
|
||||||
pub(crate) long_about: Option<&'b str>,
|
pub(crate) long_about: Option<&'b str>,
|
||||||
pub(crate) more_help: Option<&'b str>,
|
pub(crate) more_help: Option<&'b str>,
|
||||||
pub(crate) pre_help: Option<&'b str>,
|
pub(crate) pre_help: Option<&'b str>,
|
||||||
#[doc(hidden)]
|
pub(crate) aliases: Option<Vec<(&'b str, bool)>>, // (name, visible)
|
||||||
pub aliases: Option<Vec<(&'b str, bool)>>, // (name, visible)
|
|
||||||
pub(crate) usage_str: Option<&'b str>,
|
pub(crate) usage_str: Option<&'b str>,
|
||||||
pub(crate) usage: Option<String>,
|
pub(crate) usage: Option<String>,
|
||||||
pub(crate) help_str: Option<&'b str>,
|
pub(crate) help_str: Option<&'b str>,
|
||||||
|
@ -93,15 +89,88 @@ pub struct App<'b> {
|
||||||
pub(crate) template: Option<&'b str>,
|
pub(crate) template: Option<&'b str>,
|
||||||
pub(crate) settings: AppFlags,
|
pub(crate) settings: AppFlags,
|
||||||
pub(crate) g_settings: AppFlags,
|
pub(crate) g_settings: AppFlags,
|
||||||
#[doc(hidden)]
|
pub(crate) args: MKeyMap<'b>,
|
||||||
pub args: MKeyMap<'b>,
|
pub(crate) subcommands: Vec<App<'b>>,
|
||||||
#[doc(hidden)]
|
|
||||||
pub subcommands: Vec<App<'b>>,
|
|
||||||
pub(crate) replacers: HashMap<&'b str, &'b [&'b str]>,
|
pub(crate) replacers: HashMap<&'b str, &'b [&'b str]>,
|
||||||
pub(crate) groups: Vec<ArgGroup<'b>>,
|
pub(crate) groups: Vec<ArgGroup<'b>>,
|
||||||
pub(crate) help_headings: Vec<Option<&'b str>>,
|
pub(crate) help_headings: Vec<Option<&'b str>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'b> App<'b> {
|
||||||
|
/// Get the name of the app
|
||||||
|
pub fn get_name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the name of the binary
|
||||||
|
pub fn get_bin_name(&self) -> Option<&str> {
|
||||||
|
self.bin_name.as_deref()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set binary name. Uses `&mut self` instead of `self`
|
||||||
|
pub fn set_bin_name<S: Into<String>>(&mut self, name: S) {
|
||||||
|
self.bin_name = Some(name.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the help message specified via [`App::about`]
|
||||||
|
pub fn get_about(&self) -> Option<&str> {
|
||||||
|
self.about.as_deref()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Iterate through the *visible* aliases for this subcommand.
|
||||||
|
pub fn get_visible_aliases(&self) -> impl Iterator<Item = &str> {
|
||||||
|
self.aliases
|
||||||
|
.as_ref()
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|aliases| aliases.iter().filter(|(_, vis)| *vis).map(|a| a.0))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Iterate through the set of *all* the aliases for this subcommand, both visible and hidden.
|
||||||
|
pub fn get_all_aliases(&self) -> impl Iterator<Item = &str> {
|
||||||
|
self.aliases
|
||||||
|
.as_ref()
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|aliases| aliases.iter().map(|a| a.0))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the list of subcommands
|
||||||
|
pub fn get_subcommands(&self) -> &[App<'b>] {
|
||||||
|
&self.subcommands
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the list of subcommands
|
||||||
|
pub fn get_subcommands_mut(&mut self) -> &mut [App<'b>] {
|
||||||
|
&mut self.subcommands
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the list of arguments
|
||||||
|
pub fn get_arguments(&self) -> &[Arg<'b>] {
|
||||||
|
&self.args.args
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the list of arguments the given argument conflicts with
|
||||||
|
///
|
||||||
|
/// ### Panics
|
||||||
|
///
|
||||||
|
/// Panics if the given arg conflicts with an argument that is unknown to this application
|
||||||
|
pub fn get_arg_conflicts_with<'a, 'x, 'y>(&'a self, arg: &'x Arg<'y>) -> Vec<&Arg<'b>> // FIXME: This could probably have been an iterator
|
||||||
|
{
|
||||||
|
if let Some(black_ids) = arg.blacklist.as_ref() {
|
||||||
|
black_ids
|
||||||
|
.iter()
|
||||||
|
.map(|id| {
|
||||||
|
self.args.args.iter().find(|arg| arg.id == *id).expect(
|
||||||
|
"App::get_arg_conflicts_with: \
|
||||||
|
The passed arg conflicts with an arg unknown to the app",
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'b> App<'b> {
|
impl<'b> App<'b> {
|
||||||
/// Creates a new instance of an application requiring a name. The name may be, but doesn't
|
/// Creates a new instance of an application requiring a name. The name may be, but doesn't
|
||||||
/// have to be, same as the binary. The name will be displayed to the user when they request to
|
/// have to be, same as the binary. The name will be displayed to the user when they request to
|
||||||
|
@ -125,16 +194,6 @@ impl<'b> App<'b> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the name of the app
|
|
||||||
pub fn get_name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the name of the binary
|
|
||||||
pub fn get_bin_name(&self) -> Option<&str> {
|
|
||||||
self.bin_name.as_deref()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets a string of author(s) that will be displayed to the user when they
|
/// Sets a string of author(s) that will be displayed to the user when they
|
||||||
/// request the help information with `--help` or `-h`.
|
/// request the help information with `--help` or `-h`.
|
||||||
///
|
///
|
||||||
|
@ -1715,7 +1774,7 @@ impl<'b> App<'b> {
|
||||||
}
|
}
|
||||||
if self.has_subcommands()
|
if self.has_subcommands()
|
||||||
&& !self.is_set(AppSettings::DisableHelpSubcommand)
|
&& !self.is_set(AppSettings::DisableHelpSubcommand)
|
||||||
&& !subcommands!(self).any(|s| s.id == HELP_HASH)
|
&& !self.subcommands.iter().any(|s| s.id == HELP_HASH)
|
||||||
{
|
{
|
||||||
debugln!("App::_create_help_and_version: Building help");
|
debugln!("App::_create_help_and_version: Building help");
|
||||||
self.subcommands.push(
|
self.subcommands.push(
|
||||||
|
@ -1738,14 +1797,16 @@ impl<'b> App<'b> {
|
||||||
{
|
{
|
||||||
a.disp_ord = i;
|
a.disp_ord = i;
|
||||||
}
|
}
|
||||||
for (i, mut sc) in &mut subcommands!(self, iter_mut)
|
for (i, mut sc) in &mut self
|
||||||
|
.subcommands
|
||||||
|
.iter_mut()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.filter(|&(_, ref sc)| sc.disp_ord == 999)
|
.filter(|&(_, ref sc)| sc.disp_ord == 999)
|
||||||
{
|
{
|
||||||
sc.disp_ord = i;
|
sc.disp_ord = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for sc in subcommands!(self, iter_mut) {
|
for sc in &mut self.subcommands {
|
||||||
sc._derive_display_order();
|
sc._derive_display_order();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1754,7 +1815,7 @@ impl<'b> App<'b> {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn _build_bin_names(&mut self) {
|
pub fn _build_bin_names(&mut self) {
|
||||||
debugln!("App::_build_bin_names;");
|
debugln!("App::_build_bin_names;");
|
||||||
for mut sc in subcommands!(self, iter_mut) {
|
for mut sc in &mut self.subcommands {
|
||||||
debug!("Parser::build_bin_names:iter: bin_name set...");
|
debug!("Parser::build_bin_names:iter: bin_name set...");
|
||||||
if sc.bin_name.is_none() {
|
if sc.bin_name.is_none() {
|
||||||
sdebugln!("No");
|
sdebugln!("No");
|
||||||
|
@ -1880,7 +1941,8 @@ impl<'b> App<'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn has_visible_subcommands(&self) -> bool {
|
pub(crate) fn has_visible_subcommands(&self) -> bool {
|
||||||
subcommands!(self)
|
self.subcommands
|
||||||
|
.iter()
|
||||||
.filter(|sc| sc.name != "help")
|
.filter(|sc| sc.name != "help")
|
||||||
.any(|sc| !sc.is_set(AppSettings::Hidden))
|
.any(|sc| !sc.is_set(AppSettings::Hidden))
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,28 +56,22 @@ type Id = u64;
|
||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone)]
|
||||||
pub struct Arg<'help> {
|
pub struct Arg<'help> {
|
||||||
pub(crate) id: Id,
|
pub(crate) id: Id,
|
||||||
#[doc(hidden)]
|
pub(crate) name: &'help str,
|
||||||
pub name: &'help str,
|
pub(crate) help: Option<&'help str>,
|
||||||
#[doc(hidden)]
|
|
||||||
pub help: Option<&'help str>,
|
|
||||||
pub(crate) long_help: Option<&'help str>,
|
pub(crate) long_help: Option<&'help str>,
|
||||||
#[doc(hidden)]
|
pub(crate) blacklist: Option<Vec<Id>>,
|
||||||
pub blacklist: Option<Vec<Id>>,
|
|
||||||
pub(crate) settings: ArgFlags,
|
pub(crate) settings: ArgFlags,
|
||||||
pub(crate) overrides: Option<Vec<Id>>,
|
pub(crate) overrides: Option<Vec<Id>>,
|
||||||
pub(crate) groups: Option<Vec<Id>>,
|
pub(crate) groups: Option<Vec<Id>>,
|
||||||
pub(crate) requires: Option<Vec<(Option<&'help str>, Id)>>,
|
pub(crate) requires: Option<Vec<(Option<&'help str>, Id)>>,
|
||||||
pub(crate) r_ifs: Option<Vec<(Id, &'help str)>>,
|
pub(crate) r_ifs: Option<Vec<(Id, &'help str)>>,
|
||||||
pub(crate) r_unless: Option<Vec<Id>>,
|
pub(crate) r_unless: Option<Vec<Id>>,
|
||||||
#[doc(hidden)]
|
pub(crate) short: Option<char>,
|
||||||
pub short: Option<char>,
|
pub(crate) long: Option<&'help str>,
|
||||||
#[doc(hidden)]
|
|
||||||
pub long: Option<&'help str>,
|
|
||||||
pub(crate) aliases: Option<Vec<(&'help str, bool)>>, // (name, visible)
|
pub(crate) aliases: Option<Vec<(&'help str, bool)>>, // (name, visible)
|
||||||
pub(crate) disp_ord: usize,
|
pub(crate) disp_ord: usize,
|
||||||
pub(crate) unified_ord: usize,
|
pub(crate) unified_ord: usize,
|
||||||
#[doc(hidden)]
|
pub(crate) possible_vals: Option<Vec<&'help str>>,
|
||||||
pub possible_vals: Option<Vec<&'help str>>,
|
|
||||||
pub(crate) val_names: Option<VecMap<&'help str>>,
|
pub(crate) val_names: Option<VecMap<&'help str>>,
|
||||||
pub(crate) num_vals: Option<u64>,
|
pub(crate) num_vals: Option<u64>,
|
||||||
pub(crate) max_vals: Option<u64>,
|
pub(crate) max_vals: Option<u64>,
|
||||||
|
@ -89,14 +83,50 @@ pub struct Arg<'help> {
|
||||||
pub(crate) default_vals_ifs: Option<VecMap<(Id, Option<&'help OsStr>, &'help OsStr)>>,
|
pub(crate) default_vals_ifs: Option<VecMap<(Id, Option<&'help OsStr>, &'help OsStr)>>,
|
||||||
pub(crate) env: Option<(&'help OsStr, Option<OsString>)>,
|
pub(crate) env: Option<(&'help OsStr, Option<OsString>)>,
|
||||||
pub(crate) terminator: Option<&'help str>,
|
pub(crate) terminator: Option<&'help str>,
|
||||||
#[doc(hidden)]
|
pub(crate) index: Option<u64>,
|
||||||
pub index: Option<u64>,
|
pub(crate) help_heading: Option<&'help str>,
|
||||||
#[doc(hidden)]
|
|
||||||
pub help_heading: Option<&'help str>,
|
|
||||||
pub(crate) global: bool,
|
pub(crate) global: bool,
|
||||||
pub(crate) exclusive: bool,
|
pub(crate) exclusive: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Getters
|
||||||
|
impl<'help> Arg<'help> {
|
||||||
|
/// Get the name o the argument
|
||||||
|
pub fn get_name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the help specified for this argument, if any
|
||||||
|
pub fn get_help(&self) -> Option<&str> {
|
||||||
|
self.help
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the help heading specified for this argument, if any
|
||||||
|
pub fn get_help_heading(&self) -> Option<&str> {
|
||||||
|
self.help_heading
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the short option name for this argument, if any
|
||||||
|
pub fn get_short(&self) -> Option<char> {
|
||||||
|
self.short
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the long option name for this argument, if any
|
||||||
|
pub fn get_long(&self) -> Option<&str> {
|
||||||
|
self.long
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the list of the possible values for this argument, if any
|
||||||
|
pub fn get_possible_values(&self) -> Option<&[&str]> {
|
||||||
|
self.possible_vals.as_deref()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the index of this argument, if any
|
||||||
|
pub fn get_index(&self) -> Option<u64> {
|
||||||
|
self.index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'help> Arg<'help> {
|
impl<'help> Arg<'help> {
|
||||||
/// @TODO @p2 @docs @v3-beta1: Write Docs
|
/// @TODO @p2 @docs @v3-beta1: Write Docs
|
||||||
pub fn new<T: Key>(t: T) -> Self {
|
pub fn new<T: Key>(t: T) -> Self {
|
||||||
|
|
|
@ -929,11 +929,10 @@ macro_rules! write_nspaces {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
macro_rules! flags {
|
macro_rules! flags {
|
||||||
($app:expr, $how:ident) => {{
|
($app:expr, $how:ident) => {{
|
||||||
$app.args
|
$app.get_arguments()
|
||||||
.args
|
|
||||||
.$how()
|
.$how()
|
||||||
.filter(|a| !a.is_set($crate::ArgSettings::TakesValue) && a.index.is_none())
|
.filter(|a| !a.is_set($crate::ArgSettings::TakesValue) && a.get_index().is_none())
|
||||||
.filter(|a| !a.help_heading.is_some())
|
.filter(|a| !a.get_help_heading().is_some())
|
||||||
}};
|
}};
|
||||||
($app:expr) => {
|
($app:expr) => {
|
||||||
$crate::flags!($app, iter)
|
$crate::flags!($app, iter)
|
||||||
|
@ -944,11 +943,10 @@ macro_rules! flags {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
macro_rules! opts {
|
macro_rules! opts {
|
||||||
($app:expr, $how:ident) => {{
|
($app:expr, $how:ident) => {{
|
||||||
$app.args
|
$app.get_arguments()
|
||||||
.args
|
|
||||||
.$how()
|
.$how()
|
||||||
.filter(|a| a.is_set($crate::ArgSettings::TakesValue) && a.index.is_none())
|
.filter(|a| a.is_set($crate::ArgSettings::TakesValue) && a.get_index().is_none())
|
||||||
.filter(|a| !a.help_heading.is_some())
|
.filter(|a| !a.get_help_heading().is_some())
|
||||||
}};
|
}};
|
||||||
($app:expr) => {
|
($app:expr) => {
|
||||||
opts!($app, iter)
|
opts!($app, iter)
|
||||||
|
@ -958,26 +956,11 @@ macro_rules! opts {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
macro_rules! positionals {
|
macro_rules! positionals {
|
||||||
($app:expr, $how:ident) => {{
|
($app:expr) => {{
|
||||||
$app.args
|
$app.get_arguments()
|
||||||
.args
|
.iter()
|
||||||
.$how()
|
.filter(|a| !(a.get_short().is_some() || a.get_long().is_some()))
|
||||||
.filter(|a| !(a.short.is_some() || a.long.is_some()))
|
|
||||||
}};
|
}};
|
||||||
($app:expr) => {
|
|
||||||
positionals!($app, iter)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
#[doc(hidden)]
|
|
||||||
macro_rules! subcommands {
|
|
||||||
($app:expr, $how:ident) => {
|
|
||||||
$app.subcommands.$how()
|
|
||||||
};
|
|
||||||
($app:expr) => {
|
|
||||||
subcommands!($app, iter)
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! groups_for_arg {
|
macro_rules! groups_for_arg {
|
||||||
|
@ -992,21 +975,30 @@ macro_rules! groups_for_arg {
|
||||||
|
|
||||||
macro_rules! find_subcmd_cloned {
|
macro_rules! find_subcmd_cloned {
|
||||||
($app:expr, $sc:expr) => {{
|
($app:expr, $sc:expr) => {{
|
||||||
subcommands!($app)
|
$app.get_subcommands()
|
||||||
|
.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
.find(|a| match_alias!(a, $sc, &*a.name))
|
.find(|a| match_alias!(a, $sc, a.get_name()))
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
macro_rules! find_subcmd {
|
macro_rules! find_subcmd {
|
||||||
($app:expr, $sc:expr, $how:ident) => {{
|
($app:expr, $sc:expr) => {{
|
||||||
subcommands!($app, $how).find(|a| match_alias!(a, $sc, &*a.name))
|
$app.get_subcommands()
|
||||||
|
.iter()
|
||||||
|
.find(|a| match_alias!(a, $sc, a.get_name()))
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
#[doc(hidden)]
|
||||||
|
macro_rules! find_subcmd_mut {
|
||||||
|
($app:expr, $sc:expr) => {{
|
||||||
|
$app.get_subcommands_mut()
|
||||||
|
.find(|a| match_alias!(a, $sc, a.get_name()))
|
||||||
}};
|
}};
|
||||||
($app:expr, $sc:expr) => {
|
|
||||||
find_subcmd!($app, $sc, iter)
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! longs {
|
macro_rules! longs {
|
||||||
|
@ -1029,11 +1021,11 @@ macro_rules! longs {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
macro_rules! names {
|
macro_rules! names {
|
||||||
(@args $app:expr) => {{
|
(@args $app:expr) => {{
|
||||||
$app.args.args.iter().map(|a| &*a.name)
|
$app.get_arguments().iter().map(|a| &*a.get_name())
|
||||||
}};
|
}};
|
||||||
(@sc $app:expr) => {{
|
(@sc $app:expr) => {{
|
||||||
$app.subcommands.iter().map(|s| &*s.name).chain(
|
$app.get_subcommands().iter().map(|s| &*s.get_name()).chain(
|
||||||
$app.subcommands
|
$app.get_subcommands()
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|s| s.aliases.is_some())
|
.filter(|s| s.aliases.is_some())
|
||||||
.flat_map(|s| s.aliases.as_ref().unwrap().iter().map(|&(n, _)| n)),
|
.flat_map(|s| s.aliases.as_ref().unwrap().iter().map(|&(n, _)| n)),
|
||||||
|
@ -1053,13 +1045,6 @@ macro_rules! sc_names {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
macro_rules! match_alias {
|
macro_rules! match_alias {
|
||||||
($a:expr, $to:expr, $what:expr) => {{
|
($a:expr, $to:expr, $what:expr) => {{
|
||||||
$what == $to
|
$what == $to || $a.get_all_aliases().any(|alias| alias == $to)
|
||||||
|| ($a.aliases.is_some()
|
|
||||||
&& $a
|
|
||||||
.aliases
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.iter()
|
|
||||||
.any(|alias| alias.0 == $to))
|
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
|
@ -747,7 +747,11 @@ impl<'b, 'c, 'd, 'w> Help<'b, 'c, 'd, 'w> {
|
||||||
// The shortest an arg can legally be is 2 (i.e. '-x')
|
// The shortest an arg can legally be is 2 (i.e. '-x')
|
||||||
self.longest = 2;
|
self.longest = 2;
|
||||||
let mut ord_m = VecMap::new();
|
let mut ord_m = VecMap::new();
|
||||||
for sc in subcommands!(app).filter(|s| !s.is_set(AppSettings::Hidden)) {
|
for sc in app
|
||||||
|
.subcommands
|
||||||
|
.iter()
|
||||||
|
.filter(|s| !s.is_set(AppSettings::Hidden))
|
||||||
|
{
|
||||||
let btm = ord_m.entry(sc.disp_ord).or_insert(BTreeMap::new());
|
let btm = ord_m.entry(sc.disp_ord).or_insert(BTreeMap::new());
|
||||||
self.longest = cmp::max(self.longest, str_width(sc.name.as_str()));
|
self.longest = cmp::max(self.longest, str_width(sc.name.as_str()));
|
||||||
btm.insert(sc.name.clone(), sc.clone());
|
btm.insert(sc.name.clone(), sc.clone());
|
||||||
|
|
|
@ -642,7 +642,14 @@ where
|
||||||
.count();
|
.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(p) = positionals!(self.app).find(|p| p.index == Some(pos_counter as u64)) {
|
if let Some(p) = self
|
||||||
|
.app
|
||||||
|
.args
|
||||||
|
.args
|
||||||
|
.iter()
|
||||||
|
.filter(|a| a.short.is_none() && a.long.is_none())
|
||||||
|
.find(|p| p.index == Some(pos_counter as u64))
|
||||||
|
{
|
||||||
if p.is_set(ArgSettings::Last) && !self.is_set(AS::TrailingValues) {
|
if p.is_set(ArgSettings::Last) && !self.is_set(AS::TrailingValues) {
|
||||||
return Err(ClapError::unknown_argument(
|
return Err(ClapError::unknown_argument(
|
||||||
&*arg_os.to_string_lossy(),
|
&*arg_os.to_string_lossy(),
|
||||||
|
@ -984,7 +991,7 @@ where
|
||||||
self.app._propagate(Propagation::To(id));
|
self.app._propagate(Propagation::To(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(sc) = subcommands!(self.app, iter_mut).find(|s| s.name == sc_name) {
|
if let Some(sc) = self.app.subcommands.iter_mut().find(|s| s.name == sc_name) {
|
||||||
let mut sc_matcher = ArgMatcher::default();
|
let mut sc_matcher = ArgMatcher::default();
|
||||||
// bin_name should be parent's bin_name + [<reqs>] + the sc's name separated by
|
// bin_name should be parent's bin_name + [<reqs>] + the sc's name separated by
|
||||||
// a space
|
// a space
|
||||||
|
@ -1091,7 +1098,7 @@ where
|
||||||
|
|
||||||
self.app.long_about.is_some()
|
self.app.long_about.is_some()
|
||||||
|| self.app.args.args.iter().any(|f| should_long(&f))
|
|| self.app.args.args.iter().any(|f| should_long(&f))
|
||||||
|| subcommands!(self.app).any(|s| s.long_about.is_some())
|
|| self.app.subcommands.iter().any(|s| s.long_about.is_some())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_long_arg(
|
fn parse_long_arg(
|
||||||
|
|
|
@ -65,7 +65,7 @@ fn quoted_app_name() {
|
||||||
(@arg scpositional: index(1) "tests positionals"))
|
(@arg scpositional: index(1) "tests positionals"))
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(app.name, "app name with spaces-and-hyphens");
|
assert_eq!(app.get_name(), "app name with spaces-and-hyphens");
|
||||||
|
|
||||||
let mut help_text = vec![];
|
let mut help_text = vec![];
|
||||||
app.write_help(&mut help_text)
|
app.write_help(&mut help_text)
|
||||||
|
|
Loading…
Reference in a new issue