I'm trying to understand how this zsh
widget works:
expand-aliases() {
unset 'functions[_expand-aliases]'
functions[_expand-aliases]=$BUFFER
(($+functions[_expand-aliases])) &&
BUFFER=${functions[_expand-aliases]#$'\t'} &&
CURSOR=$#BUFFER
}
zle -N expand-aliases
bindkey '\e^E' expand-aliases
I found the code in this answer. Its purpose is to expand all the aliases on the command line when you hit C-M-e
.
It works but there are several things I don't understand in the code.
Here's what I think I understand and what I don't understand:
zle -N expand-aliases
This line installs a widget called expand-aliases
which will invoke the function with the same name.
bindkey '\e^E' expand-aliases
This line binds the widget to the key chord C-M-e
.
unset 'functions[_expand-aliases]'
I don't understand this line, because I don't know how the array functions
was populated.
functions[_expand-aliases]=$BUFFER
This line stores inside the associative array functions
the contents of the current command line, with the key _expand-aliases
.
(($+functions[_expand-aliases])) &&
To better understand how this line works, I've executed the following commands:
alias ls='ls --color=auto'
alias -g V='|vipe'
functions[_expand-aliases]='ls V'
echo $functions[_expand-aliases] → ls --color=auto | vipe
echo $+functions[_expand-aliases] → 1
(($+functions[_expand-aliases])); echo $? → 0
I'm not sure, but from these results, I think that $functions[_expand-aliases]
somehow expands the aliases in the current command line, and that $+functions[_expand-aliases]
returns a boolean flag which checks whether the command line is syntactically valid.
However, I don't understand the $+
token. I searched for it in all the zsh
man pages, but couldn't find it.
BUFFER=${functions[_expand-aliases]#$'\t'} &&
This line probably redefines the contents of the command line, with its expansion.
CURSOR=$#BUFFER
This line positions the cursor at the end of the command.
Could someone better explain how this code works? Or at least quote the sections in the zsh
man pages where the $+
token and the functions
array are described?
Best Answer
$+functions[_expand-aliases]
is 1 if the associative arrayfunctions
contains the key_expand-aliases
and 0 otherwise. This is described in the manual as${+name}
. Under the entry for${name}
, the manual explains that the braces are optional. I don't think the manual states explicitly that you can use an array name with a subscript instead of a name. The zsh manual is not an easy read.The
functions
array is a “magic” associative array that is tied to function definitions. Defining a function adds an element to this array where the key is the function name and the value is the function body, normalized. Conversely, adding an element to the array defines a function with the given name and body.If
functions
was an ordinary array then this wouldn't change the value ofBUFFER
(except for stripping a leading tab) and the test on the third line would always be true. But because of the “magic” nature offunctions
, what you get out of it is not what you put in, it's a normalized version — in particular, with aliases expanded. The test on the third line fails if the function definition is not syntactically correct.