Skip to content

Commit bd961b3

Browse files
committed
Fix zsh nested subcommand option completion
In zsh completion context, the words array excludes the command name, so subcommands are not matched and per-subcommand options are not suggested. To fix that, use `$words[1]` instead of `$words[2]` when dispatching nested subcommands in generated zsh completions. For reference, see zshcompsys's manpage [1]: $ man zshcompsys | col -bx | grep -F -A 13 '*::message:action' *::message:action *:::message:action This describes how arguments (usually non-option arguments, those not beginning with - or +) are to be completed when neither of the first two forms was provided. Any number of arguments can be completed in this fashion. With two colons before the message, the words special array and the CURRENT special parameter are modified to refer only to the normal arguments when the action is executed or evaluated. With three colons before the message they are modified to refer only to the normal arguments covered by this description. Also confirmed that this issue is zsh-specific. Bash and fish completions work fine. [1]: https://zsh.sourceforge.io/Doc/Release/Completion-System.html
1 parent e69d51d commit bd961b3

3 files changed

Lines changed: 7 additions & 6 deletions

File tree

Library/Homebrew/completions.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ def self.generate_zsh_nested_subcommand_completion(command, subcommands)
435435
_describe -t subcommands 'subcommand' subcommands
436436
;;
437437
args)
438-
case "$words[2]" in
438+
case "$words[1]" in
439439
#{subcommand_cases.chomp}
440440
*) ;;
441441
esac

Library/Homebrew/test/completions_spec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,7 @@ def stub_nested_completion_command(command, subcommands)
464464
stub_nested_completion_command(nested_completion_command, nested_completion_subcommands)
465465
completion = klass.generate_zsh_subcommand_completion(nested_completion_command)
466466

467+
expect(completion).to include('case "$words[1]" in')
467468
expect(completion).to include("'1:subcommand:->subcommand'")
468469
expect(completion).to include(" _arguments -C \\\n '--global[Use the global test file]' \\\n " \
469470
"'1:subcommand:->subcommand'")

completions/zsh/_brew

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ _brew_analytics() {
416416
_describe -t subcommands 'subcommand' subcommands
417417
;;
418418
args)
419-
case "$words[2]" in
419+
case "$words[1]" in
420420
state)
421421
_arguments \
422422
'--debug[Display any debugging information]' \
@@ -679,7 +679,7 @@ _brew_bundle() {
679679
_describe -t subcommands 'subcommand' subcommands
680680
;;
681681
args)
682-
case "$words[2]" in
682+
case "$words[1]" in
683683
sh)
684684
_arguments \
685685
'--check[Check that all dependencies in the Brewfile are installed before starting the shell. Enabled by default if `$HOMEBREW_BUNDLE_CHECK` is set]' \
@@ -981,7 +981,7 @@ _brew_completions() {
981981
_describe -t subcommands 'subcommand' subcommands
982982
;;
983983
args)
984-
case "$words[2]" in
984+
case "$words[1]" in
985985
unlink)
986986
_arguments \
987987
'--debug[Display any debugging information]' \
@@ -1155,7 +1155,7 @@ _brew_developer() {
11551155
_describe -t subcommands 'subcommand' subcommands
11561156
;;
11571157
args)
1158-
case "$words[2]" in
1158+
case "$words[1]" in
11591159
state)
11601160
_arguments \
11611161
'--debug[Display any debugging information]' \
@@ -2056,7 +2056,7 @@ _brew_services() {
20562056
_describe -t subcommands 'subcommand' subcommands
20572057
;;
20582058
args)
2059-
case "$words[2]" in
2059+
case "$words[1]" in
20602060
stop|unload|terminate|term|t|u)
20612061
_arguments \
20622062
'(--file)--all[Stop all services and unregister them from launching at login (or boot), unless `--keep` is specified]' \

0 commit comments

Comments
 (0)