4

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?

1 Answer 1

5

$+functions[_expand-aliases] is 1 if the associative array functions 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.

unset 'functions[_expand-aliases]'               # unset any previous function
functions[_expand-aliases]=$BUFFER               # define a function whose body is the content of the command line
(($+functions[_expand-aliases])) &&              # if the command line is a syntactically correct function body, then …
BUFFER=${functions[_expand-aliases]#$'\t'} &&    # set the command line to the normalized function definition
CURSOR=$#BUFFER                                  # move the cursor to the end of the command line

If functions was an ordinary array then this wouldn't change the value of BUFFER (except for stripping a leading tab) and the test on the third line would always be true. But because of the “magic” nature of functions, 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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.