From 75af2d58070c23fc940154908da8e78031095397 Mon Sep 17 00:00:00 2001 From: jporwal05 Date: Tue, 5 Sep 2023 17:38:39 +0530 Subject: [PATCH] fix: (fish-completion) Correct value enum help text Resolves #5101 - The completion of value enums now displays accurate help text - This fix encloses help text in single quotes - Comma in help text is not escaped - This is because the the help text is now treated as literal - No variable expansion or command substitution in help text --- clap_complete/src/shells/fish.rs | 6 ++-- .../fish/fish/completions/exhaustive.fish | 8 ++--- .../tests/snapshots/sub_subcommands.fish | 2 +- clap_complete/tests/snapshots/value_help.fish | 2 ++ clap_complete/tests/snapshots/value_help.ps1 | 32 +++++++++++++++++++ clap_complete/tests/snapshots/value_hint.fish | 2 +- clap_complete/tests/testsuite/common.rs | 13 ++++++++ clap_complete/tests/testsuite/fish.rs | 12 +++++++ 8 files changed, 69 insertions(+), 8 deletions(-) create mode 100644 clap_complete/tests/snapshots/value_help.fish create mode 100644 clap_complete/tests/snapshots/value_help.ps1 diff --git a/clap_complete/src/shells/fish.rs b/clap_complete/src/shells/fish.rs index 5a069d35b56..7dae5b6d6e8 100644 --- a/clap_complete/src/shells/fish.rs +++ b/clap_complete/src/shells/fish.rs @@ -168,10 +168,12 @@ fn value_completion(option: &Arg) -> String { .filter_map(|value| if value.is_hide_set() { None } else { + // The help text after \t is wrapped in '' to make sure that the it is taken literally + // and there is no command substitution or variable expansion resulting in unexpected errors Some(format!( - "{}\t{}", + "{}\t'{}'", escape_string(value.get_name(), true).as_str(), - escape_string(&value.get_help().unwrap_or_default().to_string(), true) + escape_string(&value.get_help().unwrap_or_default().to_string(), false) )) }) .collect::>() diff --git a/clap_complete/tests/snapshots/home/static/exhaustive/fish/fish/completions/exhaustive.fish b/clap_complete/tests/snapshots/home/static/exhaustive/fish/fish/completions/exhaustive.fish index 47b42f4a4d4..14578a67779 100644 --- a/clap_complete/tests/snapshots/home/static/exhaustive/fish/fish/completions/exhaustive.fish +++ b/clap_complete/tests/snapshots/home/static/exhaustive/fish/fish/completions/exhaustive.fish @@ -1,4 +1,4 @@ -complete -c exhaustive -n "__fish_use_subcommand" -l generate -d 'generate' -r -f -a "{bash ,elvish ,fish ,powershell ,zsh }" +complete -c exhaustive -n "__fish_use_subcommand" -l generate -d 'generate' -r -f -a "{bash '',elvish '',fish '',powershell '',zsh ''}" complete -c exhaustive -n "__fish_use_subcommand" -l global -d 'everywhere' complete -c exhaustive -n "__fish_use_subcommand" -s h -l help -d 'Print help' complete -c exhaustive -n "__fish_use_subcommand" -s V -l version -d 'Print version' @@ -12,7 +12,7 @@ complete -c exhaustive -n "__fish_use_subcommand" -f -a "hint" complete -c exhaustive -n "__fish_use_subcommand" -f -a "complete" -d 'Register shell completions for this program' complete -c exhaustive -n "__fish_use_subcommand" -f -a "help" -d 'Print this message or the help of the given subcommand(s)' complete -c exhaustive -n "__fish_seen_subcommand_from action" -l set -d 'value' -r -complete -c exhaustive -n "__fish_seen_subcommand_from action" -l choice -d 'enum' -r -f -a "{first ,second }" +complete -c exhaustive -n "__fish_seen_subcommand_from action" -l choice -d 'enum' -r -f -a "{first '',second ''}" complete -c exhaustive -n "__fish_seen_subcommand_from action" -l set-true -d 'bool' complete -c exhaustive -n "__fish_seen_subcommand_from action" -l count -d 'number' complete -c exhaustive -n "__fish_seen_subcommand_from action" -l global -d 'everywhere' @@ -95,7 +95,7 @@ complete -c exhaustive -n "__fish_seen_subcommand_from alias" -s f -s F -l flag complete -c exhaustive -n "__fish_seen_subcommand_from alias" -l global -d 'everywhere' complete -c exhaustive -n "__fish_seen_subcommand_from alias" -s h -l help -d 'Print help' complete -c exhaustive -n "__fish_seen_subcommand_from alias" -s V -l version -d 'Print version' -complete -c exhaustive -n "__fish_seen_subcommand_from hint" -l choice -r -f -a "{bash ,fish ,zsh }" +complete -c exhaustive -n "__fish_seen_subcommand_from hint" -l choice -r -f -a "{bash '',fish '',zsh ''}" complete -c exhaustive -n "__fish_seen_subcommand_from hint" -l unknown -r complete -c exhaustive -n "__fish_seen_subcommand_from hint" -l other -r -f complete -c exhaustive -n "__fish_seen_subcommand_from hint" -s p -l path -r -F @@ -111,7 +111,7 @@ complete -c exhaustive -n "__fish_seen_subcommand_from hint" -l email -r -f complete -c exhaustive -n "__fish_seen_subcommand_from hint" -l global -d 'everywhere' complete -c exhaustive -n "__fish_seen_subcommand_from hint" -s h -l help -d 'Print help' complete -c exhaustive -n "__fish_seen_subcommand_from hint" -s V -l version -d 'Print version' -complete -c exhaustive -n "__fish_seen_subcommand_from complete" -l shell -d 'Specify shell to complete for' -r -f -a "{bash ,fish }" +complete -c exhaustive -n "__fish_seen_subcommand_from complete" -l shell -d 'Specify shell to complete for' -r -f -a "{bash '',fish ''}" complete -c exhaustive -n "__fish_seen_subcommand_from complete" -l register -d 'Path to write completion-registration to' -r -F complete -c exhaustive -n "__fish_seen_subcommand_from complete" -l global -d 'everywhere' complete -c exhaustive -n "__fish_seen_subcommand_from complete" -s h -l help -d 'Print help (see more with \'--help\')' diff --git a/clap_complete/tests/snapshots/sub_subcommands.fish b/clap_complete/tests/snapshots/sub_subcommands.fish index f0eccd7c061..cec51a63a1f 100644 --- a/clap_complete/tests/snapshots/sub_subcommands.fish +++ b/clap_complete/tests/snapshots/sub_subcommands.fish @@ -11,7 +11,7 @@ complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and not __fish_seen complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and not __fish_seen_subcommand_from sub_cmd; and not __fish_seen_subcommand_from help" -s V -l version -d 'Print version' complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and not __fish_seen_subcommand_from sub_cmd; and not __fish_seen_subcommand_from help" -f -a "sub_cmd" -d 'sub-subcommand' complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and not __fish_seen_subcommand_from sub_cmd; and not __fish_seen_subcommand_from help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)' -complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and __fish_seen_subcommand_from sub_cmd" -l config -d 'the other case to test' -r -f -a "{Lest quotes\, aren\'t escaped. help\,with\,comma,Second to trigger display of options }" +complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and __fish_seen_subcommand_from sub_cmd" -l config -d 'the other case to test' -r -f -a "{Lest quotes\, aren\'t escaped. 'help,with,comma',Second to trigger display of options ''}" complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and __fish_seen_subcommand_from sub_cmd" -s h -l help -d 'Print help (see more with \'--help\')' complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and __fish_seen_subcommand_from sub_cmd" -s V -l version -d 'Print version' complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and __fish_seen_subcommand_from help; and not __fish_seen_subcommand_from sub_cmd; and not __fish_seen_subcommand_from help" -f -a "sub_cmd" -d 'sub-subcommand' diff --git a/clap_complete/tests/snapshots/value_help.fish b/clap_complete/tests/snapshots/value_help.fish new file mode 100644 index 00000000000..fa1ada35088 --- /dev/null +++ b/clap_complete/tests/snapshots/value_help.fish @@ -0,0 +1,2 @@ +complete -c my-app -l choice -r -f -a "{bash 'bash shell (some, more, text)',fish 'fish shell',zsh 'zsh shell'}" +complete -c my-app -s h -l help -d 'Print help (see more with \'--help\')' diff --git a/clap_complete/tests/snapshots/value_help.ps1 b/clap_complete/tests/snapshots/value_help.ps1 new file mode 100644 index 00000000000..0f8abea2dce --- /dev/null +++ b/clap_complete/tests/snapshots/value_help.ps1 @@ -0,0 +1,32 @@ + +using namespace System.Management.Automation +using namespace System.Management.Automation.Language + +Register-ArgumentCompleter -Native -CommandName 'my-app' -ScriptBlock { + param($wordToComplete, $commandAst, $cursorPosition) + + $commandElements = $commandAst.CommandElements + $command = @( + 'my-app' + 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('-') -or + $element.Value -eq $wordToComplete) { + break + } + $element.Value + }) -join ';' + + $completions = @(switch ($command) { + 'my-app' { + [CompletionResult]::new('--choice', 'choice', [CompletionResultType]::ParameterName, 'choice') + [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help') + break + } + }) + + $completions.Where{ $_.CompletionText -like "$wordToComplete*" } | + Sort-Object -Property ListItemText +} diff --git a/clap_complete/tests/snapshots/value_hint.fish b/clap_complete/tests/snapshots/value_hint.fish index 17fbb849925..27cd24bbaa1 100644 --- a/clap_complete/tests/snapshots/value_hint.fish +++ b/clap_complete/tests/snapshots/value_hint.fish @@ -1,4 +1,4 @@ -complete -c my-app -l choice -r -f -a "{bash ,fish ,zsh }" +complete -c my-app -l choice -r -f -a "{bash '',fish '',zsh ''}" complete -c my-app -l unknown -r complete -c my-app -l other -r -f complete -c my-app -s p -l path -r -F diff --git a/clap_complete/tests/testsuite/common.rs b/clap_complete/tests/testsuite/common.rs index 2d962dbf52b..38f1086a804 100644 --- a/clap_complete/tests/testsuite/common.rs +++ b/clap_complete/tests/testsuite/common.rs @@ -252,6 +252,19 @@ pub fn value_hint_command(name: &'static str) -> clap::Command { ) } +pub fn value_help_command(name: &'static str) -> clap::Command { + clap::Command::new(name).arg( + clap::Arg::new("choice") + .long("choice") + .action(clap::ArgAction::Set) + .value_parser(clap::builder::PossibleValuesParser::new([ + PossibleValue::new("bash").help("bash shell (some, more, text)"), + PossibleValue::new("fish").help("fish shell"), + PossibleValue::new("zsh").help("zsh shell"), + ])), + ) +} + pub fn value_terminator_command(name: &'static str) -> clap::Command { clap::Command::new(name).arg( clap::Arg::new("arguments") diff --git a/clap_complete/tests/testsuite/fish.rs b/clap_complete/tests/testsuite/fish.rs index 49656a5cb47..100511e39c3 100644 --- a/clap_complete/tests/testsuite/fish.rs +++ b/clap_complete/tests/testsuite/fish.rs @@ -84,6 +84,18 @@ fn value_hint() { ); } +#[test] +fn value_help() { + let name = "my-app"; + let cmd = common::value_help_command(name); + common::assert_matches_path( + "tests/snapshots/value_help.fish", + clap_complete::shells::Fish, + cmd, + name, + ) +} + #[test] fn value_terminator() { let name = "my-app";