The following snippet causes mcd
to be completed like mkdir
:
compdefas () {
if (($+_comps[$1])); then
compdef $_comps[$1] ${^@[2,-1]}=$1
fi
}
compdefas mkdir mcd
The way it works is to look up the current completion setting for mkdir
. The completion code for a function (generally the name of a completion function) is stored in the associative array _comps
. Thus compdef $_comps[mkdir] mcd
declares that mcd
should be completed in the same way that mkdir
is completed right now.
The function above adds a few niceties:
- The test for
(($+_comps[$1]))
ensures that if $1
doesn't have a specified completion method then no completion method is set for the other arguments.
${@[2,-1]}
is the list of arguments to the function starting with the second one, so you can specify more than one command name to define completions for. It's actually ${^@[a,-1]}
so that the text around the array expansion is replicated for each array element.
=$1
sets the service name to use. This matters only for a few commands whose completion function handles several closely-related commands. For example the completion function _gzip
handles both gzip
and gunzip
as well as pigz
and unpigz
; compdef _gzip foo
makes foo
use the default behavior of _gzip
while compdef _gzip foo=pigz
makes foo
use the behavior of _gzip
when it completes for pigz
.
Turning to your specific case, the default completion for mkdir
not only offers directories, but also options, which your function does not support. So you'd actually be better off defining mcd
as just completing existing directories. Zsh comes with a helper function for that (an undocumented wrapper around _files
).
compdef _directories mcd
The reason you were getting these bizarre-looking completions for mcd
is that it's the name of a command from a once moderately widespread suite of commands mtools.
take <directory_name>
to achieve the same behaviour as yourmcd
function. – Haltarys Jan 10 '23 at 11:36