Merge pull request #2349 from logansquirel/master

imp: Visible aliases for arguments in completions
This commit is contained in:
Pavan Kumar Sunkara 2021-02-22 09:09:25 +00:00 committed by GitHub
commit 90a74044ee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 559 additions and 183 deletions

View file

@ -140,19 +140,33 @@ pub trait Generator {
.collect()
}
/// Gets all the long options and flags of a [`clap::App`](../clap/struct.App.html).
/// Gets all the long options, their visible aliases and flags of a [`clap::App`](../clap/struct.App.html).
/// Includes `help` and `version` depending on the [`clap::AppSettings`](../clap/enum.AppSettings.html).
fn longs(p: &App) -> Vec<String> {
fn longs_and_visible_aliases(p: &App) -> Vec<String> {
debug!("longs: name={}", p.get_name());
p.get_arguments()
.filter_map(|a| {
if a.get_index().is_none() && a.get_long().is_some() {
Some(a.get_long().unwrap().to_string())
if a.get_index().is_none() {
if a.get_visible_aliases().is_some() && a.get_long().is_some() {
let mut visible_aliases: Vec<_> = a
.get_visible_aliases()
.unwrap()
.into_iter()
.map(|s| s.to_string())
.collect();
visible_aliases.push(a.get_long().unwrap().to_string());
Some(visible_aliases)
} else if a.get_visible_aliases().is_none() && a.get_long().is_some() {
Some(vec![a.get_long().unwrap().to_string()])
} else {
None
}
} else {
None
}
})
.flatten()
.collect()
}
@ -187,7 +201,8 @@ mod tests {
.short('f')
.short_alias('c')
.visible_short_alias('p')
.long("file"),
.long("file")
.visible_alias("path"),
),
)
.subcommand(App::new("hello"))
@ -274,17 +289,19 @@ mod tests {
#[test]
fn test_longs() {
let app = common();
let longs = Foo::longs(&app);
let longs = Foo::longs_and_visible_aliases(&app);
assert_eq!(longs.len(), 2);
assert_eq!(longs[0], "help");
assert_eq!(longs[1], "version");
let sc_longs = Foo::longs(Foo::find_subcommand_with_path(&app, vec!["test"]));
let sc_longs =
Foo::longs_and_visible_aliases(Foo::find_subcommand_with_path(&app, vec!["test"]));
assert_eq!(sc_longs.len(), 3);
assert_eq!(sc_longs[0], "file");
assert_eq!(sc_longs[1], "help");
assert_eq!(sc_longs[2], "version");
assert_eq!(sc_longs.len(), 4);
assert_eq!(sc_longs[0], "path");
assert_eq!(sc_longs[1], "file");
assert_eq!(sc_longs[2], "help");
assert_eq!(sc_longs[3], "version");
}
}

View file

@ -147,30 +147,34 @@ fn option_details_for_path(app: &App, path: &str) -> String {
let mut opts = String::new();
for o in p.get_opts() {
if let Some(l) = o.get_long() {
opts = format!(
"{}
if let Some(longs) = o.get_long_and_visible_aliases() {
for long in longs {
opts = format!(
"{}
--{})
COMPREPLY=({})
return 0
;;",
opts,
l,
vals_for(o)
);
opts,
long,
vals_for(o)
);
}
}
if let Some(s) = o.get_short() {
opts = format!(
"{}
-{})
if let Some(shorts) = o.get_short_and_visible_aliases() {
for short in shorts {
opts = format!(
"{}
-{})
COMPREPLY=({})
return 0
;;",
opts,
s,
vals_for(o)
);
opts,
short,
vals_for(o)
);
}
}
}
@ -198,7 +202,7 @@ fn all_options_for_path(app: &App, path: &str) -> String {
shorts = Bash::shorts_and_visible_aliases(p)
.iter()
.fold(String::new(), |acc, s| format!("{} -{}", acc, s)),
longs = Bash::longs(p)
longs = Bash::longs_and_visible_aliases(p)
.iter()
.fold(String::new(), |acc, l| format!("{} --{}", acc, l)),
pos = p

View file

@ -78,48 +78,38 @@ fn generate_inner<'help>(
let preamble = String::from("\n cand ");
for option in p.get_opts() {
if let Some(data) = option.get_short() {
let tooltip = get_tooltip(option.get_about(), data);
completions.push_str(&preamble);
completions.push_str(format!("-{} '{}'", data, tooltip).as_str());
if let Some(short_aliases) = option.get_visible_short_aliases() {
for data in short_aliases {
completions.push_str(&preamble);
completions.push_str(format!("-{} '{}'", data, tooltip).as_str());
}
if let Some(shorts) = option.get_short_and_visible_aliases() {
let tooltip = get_tooltip(option.get_about(), shorts[0]);
for short in shorts {
completions.push_str(&preamble);
completions.push_str(format!("-{} '{}'", short, tooltip).as_str());
}
}
if let Some(data) = option.get_long() {
let tooltip = get_tooltip(option.get_about(), data);
completions.push_str(&preamble);
completions.push_str(format!("--{} '{}'", data, tooltip).as_str());
if let Some(longs) = option.get_long_and_visible_aliases() {
let tooltip = get_tooltip(option.get_about(), longs[0]);
for long in longs {
completions.push_str(&preamble);
completions.push_str(format!("--{} '{}'", long, tooltip).as_str());
}
}
}
for flag in Elvish::flags(p) {
if let Some(data) = flag.get_short() {
let tooltip = get_tooltip(flag.get_about(), data);
completions.push_str(&preamble);
completions.push_str(format!("-{} '{}'", data, tooltip).as_str());
if let Some(short_aliases) = flag.get_visible_short_aliases() {
for data in short_aliases {
completions.push_str(&preamble);
completions.push_str(format!("-{} '{}'", data, tooltip).as_str());
}
if let Some(shorts) = flag.get_short_and_visible_aliases() {
let tooltip = get_tooltip(flag.get_about(), shorts[0]);
for short in shorts {
completions.push_str(&preamble);
completions.push_str(format!("-{} '{}'", short, tooltip).as_str());
}
}
if let Some(data) = flag.get_long() {
let tooltip = get_tooltip(flag.get_about(), data);
completions.push_str(&preamble);
completions.push_str(format!("--{} '{}'", data, tooltip).as_str());
if let Some(longs) = flag.get_long_and_visible_aliases() {
let tooltip = get_tooltip(flag.get_about(), longs[0]);
for long in longs {
completions.push_str(&preamble);
completions.push_str(format!("--{} '{}'", long, tooltip).as_str());
}
}
}

View file

@ -59,18 +59,16 @@ fn gen_fish_inner(root_command: &str, app: &App, buffer: &mut String) {
for option in app.get_opts() {
let mut template = basic_template.clone();
if let Some(data) = option.get_short() {
template.push_str(format!(" -s {}", data).as_str());
if let Some(short_aliases) = option.get_visible_short_aliases() {
for data in short_aliases {
template.push_str(format!(" -s {}", data).as_str());
}
if let Some(shorts) = option.get_short_and_visible_aliases() {
for short in shorts {
template.push_str(format!(" -s {}", short).as_str());
}
}
if let Some(data) = option.get_long() {
template.push_str(format!(" -l {}", data).as_str());
if let Some(longs) = option.get_long_and_visible_aliases() {
for long in longs {
template.push_str(format!(" -l {}", escape_string(long)).as_str());
}
}
if let Some(data) = option.get_about() {
@ -86,18 +84,16 @@ fn gen_fish_inner(root_command: &str, app: &App, buffer: &mut String) {
for flag in Fish::flags(app) {
let mut template = basic_template.clone();
if let Some(data) = flag.get_short() {
template.push_str(format!(" -s {}", data).as_str());
if let Some(short_aliases) = flag.get_visible_short_aliases() {
for data in short_aliases {
template.push_str(format!(" -s {}", data).as_str());
}
if let Some(shorts) = flag.get_short_and_visible_aliases() {
for short in shorts {
template.push_str(format!(" -s {}", short).as_str());
}
}
if let Some(data) = flag.get_long() {
template.push_str(format!(" -l {}", data).as_str());
if let Some(longs) = flag.get_long_and_visible_aliases() {
for long in longs {
template.push_str(format!(" -l {}", escape_string(long)).as_str());
}
}
if let Some(data) = flag.get_about() {

View file

@ -85,84 +85,62 @@ fn generate_inner<'help>(
let preamble = String::from("\n [CompletionResult]::new(");
for option in p.get_opts() {
if let Some(data) = option.get_short() {
let tooltip = get_tooltip(option.get_about(), data);
completions.push_str(&preamble);
completions.push_str(
format!(
"'-{}', '{}', {}, '{}')",
data, data, "[CompletionResultType]::ParameterName", tooltip
)
.as_str(),
);
if let Some(short_aliases) = option.get_visible_short_aliases() {
for data in short_aliases {
completions.push_str(&preamble);
completions.push_str(
format!(
"'-{}', '{}', {}, '{}')",
data, data, "[CompletionResultType]::ParameterName", tooltip
)
.as_str(),
);
}
if let Some(shorts) = option.get_short_and_visible_aliases() {
let tooltip = get_tooltip(option.get_about(), shorts[0]);
for short in shorts {
completions.push_str(&preamble);
completions.push_str(
format!(
"'-{}', '{}', {}, '{}')",
short, short, "[CompletionResultType]::ParameterName", tooltip
)
.as_str(),
);
}
}
if let Some(data) = option.get_long() {
let tooltip = get_tooltip(option.get_about(), data);
completions.push_str(&preamble);
completions.push_str(
format!(
"'--{}', '{}', {}, '{}')",
data, data, "[CompletionResultType]::ParameterName", tooltip
)
.as_str(),
);
if let Some(longs) = option.get_long_and_visible_aliases() {
let tooltip = get_tooltip(option.get_about(), longs[0]);
for long in longs {
completions.push_str(&preamble);
completions.push_str(
format!(
"'--{}', '{}', {}, '{}')",
long, long, "[CompletionResultType]::ParameterName", tooltip
)
.as_str(),
);
}
}
}
for flag in PowerShell::flags(p) {
if let Some(data) = flag.get_short() {
let tooltip = get_tooltip(flag.get_about(), data);
completions.push_str(&preamble);
completions.push_str(
format!(
"'-{}', '{}', {}, '{}')",
data, data, "[CompletionResultType]::ParameterName", tooltip
)
.as_str(),
);
if let Some(short_aliases) = flag.get_visible_short_aliases() {
for data in short_aliases {
completions.push_str(&preamble);
completions.push_str(
format!(
"'-{}', '{}', {}, '{}')",
data, data, "[CompletionResultType]::ParameterName", tooltip
)
.as_str(),
);
}
if let Some(shorts) = flag.get_short_and_visible_aliases() {
let tooltip = get_tooltip(flag.get_about(), shorts[0]);
for short in shorts {
completions.push_str(&preamble);
completions.push_str(
format!(
"'-{}', '{}', {}, '{}')",
short, short, "[CompletionResultType]::ParameterName", tooltip
)
.as_str(),
);
}
}
if let Some(data) = flag.get_long() {
let tooltip = get_tooltip(flag.get_about(), data);
completions.push_str(&preamble);
completions.push_str(
format!(
"'--{}', '{}', {}, '{}')",
data, data, "[CompletionResultType]::ParameterName", tooltip
)
.as_str(),
);
if let Some(longs) = flag.get_long_and_visible_aliases() {
let tooltip = get_tooltip(flag.get_about(), longs[0]);
for long in longs {
completions.push_str(&preamble);
completions.push_str(
format!(
"'--{}', '{}', {}, '{}')",
long, long, "[CompletionResultType]::ParameterName", tooltip
)
.as_str(),
);
}
}
}

View file

@ -422,48 +422,35 @@ fn write_opts_of(p: &App, p_global: Option<&App>) -> String {
None => "".to_string(),
};
if let Some(short) = o.get_short() {
let s = format!(
"'{conflicts}{multiple}-{arg}+[{help}]{value_completion}' \\",
conflicts = conflicts,
multiple = multiple,
arg = short,
value_completion = vc,
help = help
);
if let Some(shorts) = o.get_short_and_visible_aliases() {
for short in shorts {
let s = format!(
"'{conflicts}{multiple}-{arg}+[{help}]{value_completion}' \\",
conflicts = conflicts,
multiple = multiple,
arg = short,
value_completion = vc,
help = help
);
debug!("write_opts_of:iter: Wrote...{}", &*s);
ret.push(s);
if let Some(short_aliases) = o.get_visible_short_aliases() {
for alias in short_aliases {
let s = format!(
"'{conflicts}{multiple}-{arg}+[{help}]{value_completion}' \\",
conflicts = conflicts,
multiple = multiple,
arg = alias,
value_completion = vc,
help = help
);
debug!("write_opts_of:iter: Wrote...{}", &*s);
ret.push(s);
}
debug!("write_opts_of:iter: Wrote...{}", &*s);
ret.push(s);
}
}
if let Some(longs) = o.get_long_and_visible_aliases() {
for long in longs {
let l = format!(
"'{conflicts}{multiple}--{arg}=[{help}]{value_completion}' \\",
conflicts = conflicts,
multiple = multiple,
arg = long,
value_completion = vc,
help = help
);
if let Some(long) = o.get_long() {
let l = format!(
"'{conflicts}{multiple}--{arg}=[{help}]{value_completion}' \\",
conflicts = conflicts,
multiple = multiple,
arg = long,
value_completion = vc,
help = help
);
debug!("write_opts_of:iter: Wrote...{}", &*l);
ret.push(l);
debug!("write_opts_of:iter: Wrote...{}", &*l);
ret.push(l);
}
}
}
@ -567,6 +554,22 @@ fn write_flags_of(p: &App, p_global: Option<&App>) -> String {
debug!("write_flags_of:iter: Wrote...{}", &*l);
ret.push(l);
if let Some(aliases) = f.get_visible_aliases() {
for alias in aliases {
let l = format!(
"'{conflicts}{multiple}--{arg}[{help}]' \\",
conflicts = conflicts,
multiple = multiple,
arg = alias,
help = help
);
debug!("write_flags_of:iter: Wrote...{}", &*l);
ret.push(l);
}
}
}
}

View file

@ -252,3 +252,91 @@ static BASH_SPECIAL_CMDS: &str = r#"_my_app() {
complete -F _my_app -o bashdefault -o default my_app
"#;
#[test]
fn bash_with_aliases() {
let mut app = build_app_with_aliases();
common::<Bash>(&mut app, "cmd", BASH_ALIASES);
}
fn build_app_with_aliases() -> App<'static> {
App::new("cmd")
.about("testing bash completions")
.arg(
Arg::new("flag")
.short('f')
.visible_short_alias('F')
.long("flag")
.visible_alias("flg")
.about("cmd flag"),
)
.arg(
Arg::new("option")
.short('o')
.visible_short_alias('O')
.long("option")
.visible_alias("opt")
.about("cmd option")
.takes_value(true),
)
.arg(Arg::new("positional"))
}
static BASH_ALIASES: &str = r#"_cmd() {
local i cur prev opts cmds
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
cmd=""
opts=""
for i in ${COMP_WORDS[@]}
do
case "${i}" in
cmd)
cmd="cmd"
;;
*)
;;
esac
done
case "${cmd}" in
cmd)
opts=" -h -V -F -f -O -o --help --version --flg --flag --opt --option <positional> "
if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
fi
case "${prev}" in
--option)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--opt)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
-o)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
-O)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
*)
COMPREPLY=()
;;
esac
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
;;
esac
}
complete -F _cmd -o bashdefault -o default cmd
"#;

View file

@ -145,3 +145,67 @@ edit:completion:arg-completer[my_app] = [@words]{
$completions[$command]
}
"#;
#[test]
fn elvish_with_aliases() {
let mut app = build_app_with_aliases();
common::<Elvish>(&mut app, "cmd", ELVISH_ALIASES);
}
fn build_app_with_aliases() -> App<'static> {
App::new("cmd")
.about("testing bash completions")
.arg(
Arg::new("flag")
.short('f')
.visible_short_alias('F')
.long("flag")
.visible_alias("flg")
.about("cmd flag"),
)
.arg(
Arg::new("option")
.short('o')
.visible_short_alias('O')
.long("option")
.visible_alias("opt")
.about("cmd option")
.takes_value(true),
)
.arg(Arg::new("positional"))
}
static ELVISH_ALIASES: &str = r#"
edit:completion:arg-completer[cmd] = [@words]{
fn spaces [n]{
repeat $n ' ' | joins ''
}
fn cand [text desc]{
edit:complex-candidate $text &display-suffix=' '(spaces (- 14 (wcswidth $text)))$desc
}
command = 'cmd'
for word $words[1:-1] {
if (has-prefix $word '-') {
break
}
command = $command';'$word
}
completions = [
&'cmd'= {
cand -o 'cmd option'
cand -O 'cmd option'
cand --option 'cmd option'
cand --opt 'cmd option'
cand -h 'Prints help information'
cand --help 'Prints help information'
cand -V 'Prints version information'
cand --version 'Prints version information'
cand -f 'cmd flag'
cand -F 'cmd flag'
cand --flag 'cmd flag'
cand --flg 'cmd flag'
}
]
$completions[$command]
}
"#;

View file

@ -121,3 +121,38 @@ complete -c my_app -n "__fish_use_subcommand" -l backslash -d 'Avoid \'\\n\''
complete -c my_app -n "__fish_use_subcommand" -l brackets -d 'List packages [filter]'
complete -c my_app -n "__fish_use_subcommand" -l expansions -d 'Execute the shell command with $SHELL'
"#;
#[test]
fn fish_with_aliases() {
let mut app = build_app_with_aliases();
common::<Fish>(&mut app, "cmd", FISH_ALIASES);
}
fn build_app_with_aliases() -> App<'static> {
App::new("cmd")
.about("testing bash completions")
.arg(
Arg::new("flag")
.short('f')
.visible_short_alias('F')
.long("flag")
.visible_alias("flg")
.about("cmd flag"),
)
.arg(
Arg::new("option")
.short('o')
.visible_short_alias('O')
.long("option")
.visible_alias("opt")
.about("cmd option")
.takes_value(true),
)
.arg(Arg::new("positional"))
}
static FISH_ALIASES: &str = r#"complete -c cmd -n "__fish_use_subcommand" -s o -s O -l option -l opt -d 'cmd option' -r
complete -c cmd -n "__fish_use_subcommand" -s h -l help -d 'Prints help information'
complete -c cmd -n "__fish_use_subcommand" -s V -l version -d 'Prints version information'
complete -c cmd -n "__fish_use_subcommand" -s f -s F -l flag -l flg -d 'cmd flag'
"#;

View file

@ -12,6 +12,14 @@ fn build_app_with_name(s: &'static str) -> App<'static> {
.value_hint(ValueHint::FilePath)
.about("some input file"),
)
.arg(
Arg::new("config")
.about("some config file")
.short('c')
.visible_short_alias('C')
.long("config")
.visible_alias("conf"),
)
.subcommand(
App::new("test").about("tests things").arg(
Arg::new("case")
@ -54,6 +62,10 @@ Register-ArgumentCompleter -Native -CommandName 'my_app' -ScriptBlock {
[CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Prints help information')
[CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Prints version information')
[CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Prints version information')
[CompletionResult]::new('-c', 'c', [CompletionResultType]::ParameterName, 'some config file')
[CompletionResult]::new('-C', 'C', [CompletionResultType]::ParameterName, 'some config file')
[CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'some config file')
[CompletionResult]::new('--conf', 'conf', [CompletionResultType]::ParameterName, 'some config file')
[CompletionResult]::new('test', 'test', [CompletionResultType]::ParameterValue, 'tests things')
[CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Prints this message or the help of the given subcommand(s)')
break
@ -125,6 +137,10 @@ Register-ArgumentCompleter -Native -CommandName 'my_app' -ScriptBlock {
[CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Prints help information')
[CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Prints version information')
[CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Prints version information')
[CompletionResult]::new('-c', 'c', [CompletionResultType]::ParameterName, 'some config file')
[CompletionResult]::new('-C', 'C', [CompletionResultType]::ParameterName, 'some config file')
[CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'some config file')
[CompletionResult]::new('--conf', 'conf', [CompletionResultType]::ParameterName, 'some config file')
[CompletionResult]::new('test', 'test', [CompletionResultType]::ParameterValue, 'tests things')
[CompletionResult]::new('some_cmd', 'some_cmd', [CompletionResultType]::ParameterValue, 'tests other things')
[CompletionResult]::new('some-cmd-with-hypens', 'some-cmd-with-hypens', [CompletionResultType]::ParameterValue, 'some-cmd-with-hypens')
@ -167,3 +183,75 @@ Register-ArgumentCompleter -Native -CommandName 'my_app' -ScriptBlock {
Sort-Object -Property ListItemText
}
"#;
#[test]
fn powershell_with_aliases() {
let mut app = build_app_with_aliases();
common::<PowerShell>(&mut app, "cmd", POWERSHELL_ALIASES);
}
fn build_app_with_aliases() -> App<'static> {
App::new("cmd")
.about("testing bash completions")
.arg(
Arg::new("flag")
.short('f')
.visible_short_alias('F')
.long("flag")
.visible_alias("flg")
.about("cmd flag"),
)
.arg(
Arg::new("option")
.short('o')
.visible_short_alias('O')
.long("option")
.visible_alias("opt")
.about("cmd option")
.takes_value(true),
)
.arg(Arg::new("positional"))
}
static POWERSHELL_ALIASES: &str = r#"
using namespace System.Management.Automation
using namespace System.Management.Automation.Language
Register-ArgumentCompleter -Native -CommandName 'cmd' -ScriptBlock {
param($wordToComplete, $commandAst, $cursorPosition)
$commandElements = $commandAst.CommandElements
$command = @(
'cmd'
for ($i = 1; $i -lt $commandElements.Count; $i++) {
$element = $commandElements[$i]
if ($element -isnot [StringConstantExpressionAst] -or
$element.StringConstantType -ne [StringConstantType]::BareWord -or
$element.Value.StartsWith('-')) {
break
}
$element.Value
}) -join ';'
$completions = @(switch ($command) {
'cmd' {
[CompletionResult]::new('-o', 'o', [CompletionResultType]::ParameterName, 'cmd option')
[CompletionResult]::new('-O', 'O', [CompletionResultType]::ParameterName, 'cmd option')
[CompletionResult]::new('--option', 'option', [CompletionResultType]::ParameterName, 'cmd option')
[CompletionResult]::new('--opt', 'opt', [CompletionResultType]::ParameterName, 'cmd option')
[CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Prints help information')
[CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Prints help information')
[CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Prints version information')
[CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Prints version information')
[CompletionResult]::new('-f', 'f', [CompletionResultType]::ParameterName, 'cmd flag')
[CompletionResult]::new('-F', 'F', [CompletionResultType]::ParameterName, 'cmd flag')
[CompletionResult]::new('--flag', 'flag', [CompletionResultType]::ParameterName, 'cmd flag')
[CompletionResult]::new('--flg', 'flg', [CompletionResultType]::ParameterName, 'cmd flag')
break
}
})
$completions.Where{ $_.CompletionText -like "$wordToComplete*" } |
Sort-Object -Property ListItemText
}
"#;

View file

@ -422,3 +422,74 @@ _my_app__second__third_commands() {
}
_my_app "$@""#;
#[test]
fn zsh_with_aliases() {
let mut app = build_app_with_aliases();
common::<Zsh>(&mut app, "cmd", ZSH_ALIASES);
}
fn build_app_with_aliases() -> App<'static> {
App::new("cmd")
.about("testing bash completions")
.arg(
Arg::new("flag")
.short('f')
.visible_short_alias('F')
.long("flag")
.visible_alias("flg")
.about("cmd flag"),
)
.arg(
Arg::new("option")
.short('o')
.visible_short_alias('O')
.long("option")
.visible_alias("opt")
.about("cmd option")
.takes_value(true),
)
.arg(Arg::new("positional"))
}
static ZSH_ALIASES: &str = r#"#compdef cmd
autoload -U is-at-least
_cmd() {
typeset -A opt_args
typeset -a _arguments_options
local ret=1
if is-at-least 5.2; then
_arguments_options=(-s -S -C)
else
_arguments_options=(-s -C)
fi
local context curcontext="$curcontext" state line
_arguments "${_arguments_options[@]}" \
'-o+[cmd option]' \
'-O+[cmd option]' \
'--option=[cmd option]' \
'--opt=[cmd option]' \
'-h[Prints help information]' \
'--help[Prints help information]' \
'-V[Prints version information]' \
'--version[Prints version information]' \
'-f[cmd flag]' \
'-F[cmd flag]' \
'--flag[cmd flag]' \
'--flg[cmd flag]' \
'::positional:' \
&& ret=0
}
(( $+functions[_cmd_commands] )) ||
_cmd_commands() {
local commands; commands=()
_describe -t commands 'cmd commands' commands "$@"
}
_cmd "$@""#;

View file

@ -160,12 +160,54 @@ impl<'help> Arg<'help> {
}
}
/// Get the short option name and its visible aliases, if any
#[inline]
pub fn get_short_and_visible_aliases(&self) -> Option<Vec<char>> {
let mut shorts = match self.short {
Some(short) => vec![short],
None => return None,
};
if let Some(aliases) = self.get_visible_short_aliases() {
shorts.extend(aliases);
}
Some(shorts)
}
/// Get the long option name for this argument, if any
#[inline]
pub fn get_long(&self) -> Option<&str> {
self.long
}
/// Get visible aliases for this argument, if any
#[inline]
pub fn get_visible_aliases(&self) -> Option<Vec<&str>> {
if self.aliases.is_empty() {
None
} else {
Some(
self.aliases
.iter()
.filter_map(|(s, v)| if *v { Some(s) } else { None })
.copied()
.collect(),
)
}
}
/// Get the long option name and its visible aliases, if any
#[inline]
pub fn get_long_and_visible_aliases(&self) -> Option<Vec<&str>> {
let mut longs = match self.long {
Some(long) => vec![long],
None => return None,
};
if let Some(aliases) = self.get_visible_aliases() {
longs.extend(aliases);
}
Some(longs)
}
/// Get the list of the possible values for this argument, if any
#[inline]
pub fn get_possible_values(&self) -> Option<&[&str]> {