My zshrc includes the following function to create a directory and then enter it:
function mcd () {
mkdir -p "$*" && cd "$*"
}
The function itself works fine but I get odd behavior with completion. If I start typing e.g. mcd ~/
and then press Tab, the message
_mtools_drives:3: command not found: mtoolstest
is inserted at the insertion point and nothing is completed. What I want is for the command to be completed just as mkdir
would be: zsh should offer me the names of existing directories.
How do I tell zsh that for completion purposes, it should treat mcd
the same as mkdir
?
Best Answer
The following snippet causes
mcd
to be completed likemkdir
: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
. Thuscompdef $_comps[mkdir] mcd
declares thatmcd
should be completed in the same way thatmkdir
is completed right now.The function above adds a few niceties:
(($+_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 bothgzip
andgunzip
as well aspigz
andunpigz
;compdef _gzip foo
makesfoo
use the default behavior of_gzip
whilecompdef _gzip foo=pigz
makesfoo
use the behavior of_gzip
when it completes forpigz
.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 definingmcd
as just completing existing directories. Zsh comes with a helper function for that (an undocumented wrapper around_files
).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.