我使用的是zsh
5.3.1版本:
% zsh --version
zsh 5.3.1 (x86_64-pc-linux-gnu)
我正在尝试使用键序列定义键绑定,C-x r
以重新加载 的配置zsh
。谢谢@吉尔斯,我将此代码包含在我的~/.zshrc
:
reread_zshrc () {
. ~/.zshrc
}
zle -N reread_zshrc
bindkey '^Xr' reread_zshrc
它有效,除了当我点击 时C-x r
,zsh
抱怨错误:
stty: 'standard input': Bad file descriptor
stty: 'standard input': Bad file descriptor
dircolors: /home/user/.dircolors: Bad file descriptor
我可以用以下最少的内容重现这些错误zshrc
:
stty -ixon
stty quit undef
eval "$(dircolors -b ~/.dircolors)"
reread_zshrc () {
. ~/.zshrc
}
zle -N reread_zshrc
bindkey '^Xr' reread_zshrc
以下是我包含这 2 个stty
命令以及该dircolors
命令在我的zshrc
.
stty -ixon
防止终端驱动程序解释C-s
并C-q
作为终端流控制:默认情况下,C-s
冻结终端并C-q
解冻它。它允许在 shell 或文本编辑器的键绑定中使用C-s
和C-q
,而无需冻结终端。
stty quit undef
防止终端驱动程序SIGQUIT
在C-\
按下 时发送信号。同样,它允许在键绑定中使用此键,而无需退出前台进程。
eval "$(dircolors -b ~/.dircolors)"
要求ls
命令从 读取其配置~/.dircolors
。它允许根据命令的输出自定义颜色ls
。
zsh
我想如果这 3 行已经在当前 shell 中执行过,我需要保护它们不被重新分配。但我不知道该写哪个条件:
if <stty and dircolors haven't been executed already>; then
stty -ixon
stty quit undef
eval "$(dircolors -b ~/.dircolors)"
if
此外,我想更好地理解这些错误消息,因为如果我在交互式zsh
shell 中执行它们,它们不会导致任何问题。为什么他们只从这个键绑定中引发错误。
答案1
在zle
小部件中,它似乎zsh
关闭了标准输入。我zsh
想避免这些小部件中的命令直接干扰用户输入,但从 /dev/null 重定向 stdin 会更明智(这将在下一个版本中修复)。
当标准输入(文件描述符 0)关闭时,这意味着命令打开的第一个文件将成为其标准输入(因为文件描述符是从第一个空闲文件分配的)。
在 中dircolors
,这会触发一个错误。dircolors
打开您的~/.dircolors
,然后尝试将其设为标准输入,而不会注意到它已经是其标准输入(因为那是 fdopen()
返回的)。因此,dup2(0,0)
(将 stdin 复制到自身上)失败并报告 EBADF 错误dircolors
。
stty
设置在其标准输入上打开的终端的设置。此处,stdin 已关闭,因此stty
返回错误。
在这里,您可以更改您的小部件,以便它将标准输入恢复到终端:
reread_zshrc () . ~/.zshrc < $TTY
但请注意,从小部件内更改 tty 设置zle
(尽管我不知道您的stty
命令的作用)是一个坏主意,因为zle
将 tty 设置为特殊模式以进行行编辑,您不想弄乱它(并且在编辑结束时,无论如何都会恢复正常的 tty 设置,因此您所做的更改将会丢失)。
所以也许你应该制作 stdin /dev/null
(因为你真的不想在那里用终端做事),但stty
仍然会抱怨(因为/dev/null
不是 tty 设备),所以你可能还想将 stderr 重定向到 /dev/ null 来隐藏这些错误消息(尽管它会隐藏全部错误消息):
reread_zshrc() . ~/.zshrc < /dev/null 2> /dev/null