更好地理解“zsh”中扩展别名的函数

更好地理解“zsh”中扩展别名的函数

我试图了解这个zsh小部件是如何工作的:

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

我在这找到了代码回答。它的目的是当您点击 时展开命令行上的所有别名C-M-e

它有效,但代码中有几件事我不明白。

以下是我认为我理解和不理解的内容:

zle -N expand-aliases

此行安装一个名为的小部件expand-aliases,它将调用具有相同名称的函数。

bindkey '\e^E' expand-aliases

该行将小部件绑定到关键和弦C-M-e

unset 'functions[_expand-aliases]'

我不明白这一行,因为我不知道数组functions是如何填充的。

functions[_expand-aliases]=$BUFFER

该行将当前命令行的内容存储在关联数组内functions,键为_expand-aliases

(($+functions[_expand-aliases])) &&

为了更好地理解该行的工作原理,我执行了以下命令:

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

我不确定,但从这些结果来看,我认为以$functions[_expand-aliases]某种方式扩展了当前命令行中的别名,并$+functions[_expand-aliases]返回一个布尔标志,用于检查命令行在语法上是否有效。

但是,我不明白该$+令牌。我在所有手册页中搜索它zsh,但找不到它。

BUFFER=${functions[_expand-aliases]#$'\t'} &&

该行可能重新定义了命令行的内容及其扩展。

CURSOR=$#BUFFER

该行将光标定位在命令的末尾。


有人可以更好地解释这段代码是如何工作的吗?或者至少引用zsh手册页中描述$+令牌和functions数组的部分?

答案1

$+functions[_expand-aliases]如果关联数组functions包含键_expand-aliases,则为 1,否则为 0。这在手动的作为。在 的条目下,手册解释说大括号是可选的。我不认为手册明确指出您可以使用${+name}${name}带下标的数组名而不是名字。 zsh 手册并不容易阅读。

functions数组是一个与函数定义相关的“神奇”关联数组。定义函数会向该数组添加一个元素,其中键是函数名称,值是规范化的函数体。相反,向数组添加元素会定义具有给定名称和主体的函数。

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

如果functions是一个普通数组,那么这不会改变 的值BUFFER(除了去掉前导制表符),并且第三行的测试将始终为真。但由于 的“神奇”本质functions,您从中得到的并不是您输入的内容,它是一个规范化版本 - 特别是扩展了别名。如果函数定义在语法上不正确,则第三行的测试将失败。

相关内容