In zsh, I'm trying to get an idea of which commands have an existing completion so that I can write completions for commands that don't.
Is there a way to list the commands that zsh will complete without grepping the completion files? For instance, is there a built-in command that will list them?
The list of known completions is stored in the associative array _comps
. The command names and other completion contexts are used as keys for _comps
, while the corresponding completion functions are stored as values.
You can get a full list of commands with associated completions with the following command:
for command completion in ${(kv)_comps:#-*(-|-,*)}
do
printf "%-32s %s\n" $command $completion
done | sort
for command completion in LIST; COMMAND
takes iterates over LIST
while taking two elements, command
and completion
, on every iteration and running COMMAND
for them. This is also a short form of the for
-loop that does not require do
and done
.${(kv)ASSOC_ARRAY}
expands the associative array ASSOC_ARRAY
to a space separated list of key-value pairs. So it is an alternating list of "key1 value1 key2 value2 key3 value3 …", which is taken up by the two arguments of the for
-loop. $ASSOC_ARRAY
would only expand to a list of values.${ASSOC_ARRAY:#PATTERN}
filters out all elements of ASSOC_ARRAY
from its expansion, where the key matches PATTERN
.-*(-|-,*)
matches the names of all special contexts, like -math-
, -parameter-
or -value-,NAME,COMMAND
. It would also filter any command name that either matches -*-
or -*-,*
, should such a command have a completion on your system. (You could just leave out the pattern filter to be sure)printf "%-32s %s\n" $command $completion
does a formatted output so that you get a nice table. $command
is printed in place of %-32s
, padded to 32 characters with left-alignment (-
). $completion
is printed in place of %s
.| sort
: associative arrays are unordered, so output of the loop needs to be run through sort
in order to get a ordered list.