-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
feat(complete): group options by tag (in zsh)
#6334
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,7 @@ use std::ffi::OsString; | |
| use std::str::FromStr; | ||
|
|
||
| use super::EnvCompleter; | ||
| use clap::builder::StyledStr; | ||
|
|
||
| /// Bash completion adapter | ||
| #[derive(Copy, Clone, PartialEq, Eq, Debug)] | ||
|
|
@@ -376,25 +377,39 @@ function _clap_dynamic_completer_NAME() { | |
| )}") | ||
|
|
||
| if [[ -n $completions ]]; then | ||
| local -A tag_map | ||
| local -a dirs=() | ||
| local -a other=() | ||
| local completion | ||
| local tag | ||
| local value | ||
|
|
||
| for completion in $completions; do | ||
| local value="${completion%%:*}" | ||
| IFS=: read -r tag value <<< "$completion" | ||
| if [[ "$value" == */ ]]; then | ||
| local dir_no_slash="${value%/}" | ||
| if [[ "$completion" == *:* ]]; then | ||
| local desc="${completion#*:}" | ||
| if [[ "$value" == *:* ]]; then | ||
| local desc="${value#*:}" | ||
| dirs+=("$dir_no_slash:$desc") | ||
| else | ||
| dirs+=("$dir_no_slash") | ||
| fi | ||
| else | ||
| other+=("$completion") | ||
| if (( ${+tag_map["$tag"]} )); then # key exists? | ||
| tag_map["$tag"]+=$'\n'"$value" | ||
| else | ||
| tag_map["$tag"]="$value" | ||
| fi | ||
| fi | ||
|
Comment on lines
388
to
+402
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this mean we aren't getting the |
||
| done | ||
| [[ -n $dirs ]] && _describe -t dirs 'values' dirs -S '/' -r '/' | ||
| for tag in ${(k)tag_map}; do | ||
| values=("${(@f)tag_map[$tag]}") # split on newline | ||
| if [[ -n $tag ]]; then | ||
| _describe -t "$tag" "$tag options" values | ||
| else | ||
| _describe "options" values | ||
| fi | ||
| done | ||
| [[ -n $dirs ]] && _describe 'values' dirs -S '/' -r '/' | ||
| [[ -n $other ]] && _describe 'values' other | ||
| fi | ||
| } | ||
|
|
||
|
|
@@ -431,6 +446,12 @@ compdef _clap_dynamic_completer_NAME BIN"# | |
| if i != 0 { | ||
| write!(buf, "{}", ifs.as_deref().unwrap_or("\n"))?; | ||
| } | ||
| write!( | ||
| buf, | ||
| "{}:", | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is |
||
| candidate.get_tag().unwrap_or(&StyledStr::from("")), | ||
| )?; | ||
|
|
||
| write!( | ||
| buf, | ||
| "{}", | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| #compdef dynamic | ||
| function _clap_dynamic_completer_dynamic() { | ||
| local _CLAP_COMPLETE_INDEX=$(expr $CURRENT - 1) | ||
| local _CLAP_IFS=$'\n' | ||
|
|
||
| local completions=("${(@f)$( \ | ||
| _CLAP_IFS="$_CLAP_IFS" \ | ||
| _CLAP_COMPLETE_INDEX="$_CLAP_COMPLETE_INDEX" \ | ||
| COMPLETE="zsh" \ | ||
| dynamic -- "${words[@]}" 2>/dev/null \ | ||
| )}") | ||
|
|
||
| if [[ -n $completions ]]; then | ||
| local -A tag_map | ||
| local -a dirs=() | ||
| local completion | ||
| local tag | ||
| local value | ||
|
|
||
| for completion in $completions; do | ||
| IFS=: read -r tag value <<< "$completion" | ||
| if [[ "$value" == */ ]]; then | ||
| local dir_no_slash="${value%/}" | ||
| if [[ "$value" == *:* ]]; then | ||
| local desc="${value#*:}" | ||
| dirs+=("$dir_no_slash:$desc") | ||
| else | ||
| dirs+=("$dir_no_slash") | ||
| fi | ||
| else | ||
| if (( ${+tag_map["$tag"]} )); then # key exists? | ||
| tag_map["$tag"]+=$'\n'"$value" | ||
| else | ||
| tag_map["$tag"]="$value" | ||
| fi | ||
| fi | ||
| done | ||
| [[ -n $dirs ]] && _describe -t dirs 'values' dirs -S '/' -r '/' | ||
| for tag in ${(k)tag_map}; do | ||
| values=("${(@f)tag_map[$tag]}") # split on newline | ||
| if [[ -n $tag ]]; then | ||
| _describe -t "$tag" "$tag options" values | ||
| else | ||
| _describe "options" values | ||
| fi | ||
| done | ||
| fi | ||
| } | ||
|
|
||
| compdef _clap_dynamic_completer_dynamic dynamic |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -213,8 +213,8 @@ fn complete() { | |
| let expected = snapbox::str![[r#" | ||
| % exhaustive | ||
| help -- Print this message or the help of the given subcommand(s) | ||
| hint | ||
| pacman action global alias value quote empty last -- | ||
| hint | ||
| pacman action global alias value quote empty last -- | ||
| "#]]; | ||
| let actual = runtime.complete(input, &term).unwrap(); | ||
| assert_data_eq!(actual, expected); | ||
|
|
@@ -235,6 +235,7 @@ pacman action global alias value quote empty last -- | |
| #[cfg(feature = "unstable-shell-tests")] | ||
| fn register_dynamic_env() { | ||
| common::register_example::<RuntimeBuilder>("dynamic-env", "exhaustive"); | ||
| common::register_example::<RuntimeBuilder>("dynamic-env", "dynamic"); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The tests are testing using Is this unused? Do we then need to add the |
||
| } | ||
|
|
||
| #[test] | ||
|
|
@@ -253,9 +254,9 @@ fn complete_dynamic_env_toplevel() { | |
| % exhaustive | ||
| --generate -- generate | ||
| --help -- Print help | ||
| help -- Print this message or the help of the given subcommand(s) | ||
| --empty-choice alias global last quote | ||
| action empty hint pacman value | ||
| help -- Print this message or the help of the given subcommand(s) | ||
| --empty-choice alias global last quote | ||
| action empty hint pacman value | ||
| "#]]; | ||
| let actual = runtime.complete(input, &term).unwrap(); | ||
| assert_data_eq!(actual, expected); | ||
|
|
@@ -275,15 +276,21 @@ fn complete_dynamic_env_quoted_help() { | |
| let input = "exhaustive quote \t\t"; | ||
| let expected = snapbox::str![[r#" | ||
| % exhaustive quote | ||
| --help -- Print help (see more with '--help') | ||
| cmd-backslash --backslash -- Avoid '/n' | ||
| cmd-backticks --backticks -- For more information see `echo test` | ||
| cmd-brackets --brackets -- List packages [filter] | ||
| cmd-double-quotes --double-quotes -- Can be "always", "auto", or "never" | ||
| cmd-expansions --expansions -- Execute the shell command with $SHELL | ||
| cmd-single-quotes --single-quotes -- Can be 'always', 'auto', or 'never' | ||
| escape-help -- /tab/t"' | ||
| help -- Print this message or the help of the given subcommand(s) | ||
| --backslash -- Avoid '/n' | ||
| --backticks -- For more information see `echo test` | ||
| --brackets -- List packages [filter] | ||
| --double-quotes -- Can be "always", "auto", or "never" | ||
| --expansions -- Execute the shell command with $SHELL | ||
| --help -- Print help (see more with '--help') | ||
| --single-quotes -- Can be 'always', 'auto', or 'never' | ||
| cmd-backslash -- Avoid '/n' | ||
| cmd-backticks -- For more information see `echo test` | ||
| cmd-brackets -- List packages [filter] | ||
| cmd-double-quotes -- Can be "always", "auto", or "never" | ||
| cmd-expansions -- Execute the shell command with $SHELL | ||
| cmd-single-quotes -- Can be 'always', 'auto', or 'never' | ||
| escape-help -- /tab "' | ||
| help -- Print this message or the help of the given subcommand(s) | ||
| --choice | ||
| "#]]; | ||
| let actual = runtime.complete(input, &term).unwrap(); | ||
|
|
@@ -392,15 +399,21 @@ fn complete_dynamic_empty_space() { | |
| let input = "exhaustive quote -\x1b[D\x1b[D\t\t"; | ||
| let expected = snapbox::str![[r#" | ||
| % exhaustive quote - | ||
| --help -- Print help (see more with '--help') | ||
| cmd-backslash --backslash -- Avoid '/n' | ||
| cmd-backticks --backticks -- For more information see `echo test` | ||
| cmd-brackets --brackets -- List packages [filter] | ||
| cmd-double-quotes --double-quotes -- Can be "always", "auto", or "never" | ||
| cmd-expansions --expansions -- Execute the shell command with $SHELL | ||
| cmd-single-quotes --single-quotes -- Can be 'always', 'auto', or 'never' | ||
| escape-help -- /tab/t"' | ||
| help -- Print this message or the help of the given subcommand(s) | ||
| --backslash -- Avoid '/n' | ||
| --backticks -- For more information see `echo test` | ||
| --brackets -- List packages [filter] | ||
| --double-quotes -- Can be "always", "auto", or "never" | ||
| --expansions -- Execute the shell command with $SHELL | ||
| --help -- Print help (see more with '--help') | ||
| --single-quotes -- Can be 'always', 'auto', or 'never' | ||
| cmd-backslash -- Avoid '/n' | ||
| cmd-backticks -- For more information see `echo test` | ||
| cmd-brackets -- List packages [filter] | ||
| cmd-double-quotes -- Can be "always", "auto", or "never" | ||
| cmd-expansions -- Execute the shell command with $SHELL | ||
| cmd-single-quotes -- Can be 'always', 'auto', or 'never' | ||
| escape-help -- /tab "' | ||
| help -- Print this message or the help of the given subcommand(s) | ||
| --choice | ||
| "#]]; | ||
| let actual = runtime.complete(input, &term).unwrap(); | ||
|
|
@@ -435,3 +448,34 @@ tests/examples.rs tests/snapshots tests/testsuite | |
| let actual = runtime.complete(input, &term).unwrap(); | ||
| assert_data_eq!(actual, expected); | ||
| } | ||
|
|
||
| #[test] | ||
| #[cfg(all(unix, feature = "unstable-dynamic"))] | ||
| #[cfg(feature = "unstable-shell-tests")] | ||
| fn complete_dynamic_tagged_options() { | ||
| if !common::has_command(CMD) { | ||
| return; | ||
| } | ||
|
|
||
| let term = completest::Term::new(); | ||
| let mut runtime = common::load_runtime::<RuntimeBuilder>("dynamic-env", "dynamic"); | ||
|
|
||
| let input = [ | ||
| "zstyle ':completion:*' group-name ''", | ||
| "zstyle ':completion:*:descriptions' format '%d'", | ||
| "dynamic -\t\t", | ||
| ].join("\n"); | ||
|
|
||
| let expected = snapbox::str![[r#" | ||
| % zstyle ':completion:*' group-name '' | ||
| % zstyle ':completion:*:descriptions' format '%d' | ||
| % dynamic - | ||
| completing "Options" options | ||
| -F -- --format | ||
| -h -- Print help | ||
| -i -- --input | ||
| -v -- --verbose | ||
| "#]]; | ||
| let actual = runtime.complete(&input, &term).unwrap(); | ||
| assert_data_eq!(actual, expected); | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No test output changed in this commit. Are the commits not atomic or are they not covering the right behavior?