我试图了解这个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
,您从中得到的并不是您输入的内容,它是一个规范化版本 - 特别是扩展了别名。如果函数定义在语法上不正确,则第三行的测试将失败。