如何创建一个重新配置 shell 配置的键绑定,而不将新命令保存在历史记录中?

如何创建一个重新配置 shell 配置的键绑定,而不将新命令保存在历史记录中?

我想使用键序列创建一个键绑定,以重新加载存储在 中C-x r的配置以及存储在 中的 readline 库之一。bash~/.bashrc~/.inputrc

要重新加载 readline 的配置,我想我可以使用re-read-init-file以下中描述的函数man 3 readline

re-read-init-file (C-x C-r)
        Read in the contents of the inputrc file, and incorporate any bindings or variable  assignments  found there.

要重新加载 的配置bash,我可以使用sourceor.命令。但是,我不确定将 shell 命令与 readline 函数结合起来的最佳方法是什么。因此,我想出了 2 个键绑定的组合:

bind '"\C-xr":      ". ~/.bashrc \C-x\C-z1\C-m"'
bind '"\C-x\C-z1":  re-read-init-file'

当我点击C-x rbash 时,会发生以下情况:

. ~/.bashrc    `~/.bashrc` is inserted on the command line
C-x C-z 1      `C-x C-z 1` is typed which is bound to `re-read-init-file`
C-m            `C-m` is hit which executes the current command line

它似乎有效,因为在 tmux 内部,如果我有 2 个窗格,一个用于编辑~/.inputrc~/.bashrc,另一个用于 shell,并且我更改配置文件,在敲入C-x rshell 后,我可以看到更改生效(无论是新别名或新键绑定),无需关闭窗格即可重新打开新 shell。

但是,有没有更好的方法来达到相同的结果呢?特别是,是否可以执行命令而不在历史记录中留下条目?因为如果我点击C-p回忆最后执行的命令,我会得到. ~/.bashrc,而我更愿意直接获取在重新获取 shell 配置之前执行的命令。

我有同样的问题zsh

bindkey -s '^Xr' '. ~/.zshrc^M'

同样,点击 后C-x r,该命令. ~/.zshrc将记录在历史记录中。有没有更好的方法来重新配置 的源zsh

答案1

不要将命令插入命令行来运行它!这是非常脆弱的——你正在尝试的假设是在当前提示符下还没有输入任何内容。相反,请将密钥绑定到 shell 命令,而不是将其绑定到行编辑命令。

在 bash 中,使用bind -x

bind -x '"\C-xr": . ~/.bashrc'

如果您还想重新读取 readline 配置,则没有一种简单的方法可以在键绑定中混合 readline 命令和 bash 命令。一种笨拙的方法是将键绑定到包含两个键序列的 readline 宏,一个绑定到要执行的 readline 命令,一个绑定到 bash 命令。

bind '"\e[99i~": re-read-init-file'
bind -x '"\e[99b~": . ~/.bashrc'
bind '"\C-xr": "\e[99i~\e[99b~"'

在 zsh 中,使用zle -N将函数声明为小部件,然后bindkey将该小部件绑定到一个键。

reread_zshrc () {
  . ~/.zshrc
}
zle -N reread_zshrc
bindkey '^Xr' reread_zshrc

答案2

在 中man bash,我找到了HISTIGNORE环境变量,其描述如下:

HISTIGNORE

        A  colon-separated list  of patterns  used to  decide which  command
        lines should be saved on the  history list. Each pattern is anchored
        at the  beginning of the line  and must match the  complete line (no
        implicit `*' is  appended). Each pattern is tested  against the line
        after the checks  specified by HISTCONTROL are  applied. In addition
        to the  normal shell  pattern matching  characters, `&'  matches the
        previous history  line. `&'  may be escaped  using a  backslash; the
        backslash  is removed  before  attempting a  match.  The second  and
        subsequent lines  of a multi-line  compound command are  not tested,
        and are added to the history regardless of the value of HISTIGNORE.

因此,我在 中导出了以下值~/.bashrc

bind '"\C-xr":   ". ~/.bashrc \C-x\C-z1\C-m"'
bind '"\C-x\C-z1":  re-read-init-file'

export HISTIGNORE="clear:history:. ~/.bashrc "

最后一行应该防止bash保存任何命令clearhistory更重要的是 . ~/.bashrc命令。


对于zsh,我找到了该HIST_IGNORE_SPACE选项,其描述如下man zshoptions

HIST_IGNORE_SPACE (-g)

        Remove command lines  from the history list when the  first character on
        the line  is a  space, or when  one of the  expanded aliases  contains a
        leading space. Only  normal aliases (not global or  suffix aliases) have
        this behaviour.  Note that the  command lingers in the  internal history
        until the  next command is entered  before it vanishes, allowing  you to
        briefly reuse or edit the line. If you want to make it vanish right away
        without entering another command, type a space and press return.

根据它的说法,如果启用此选项,zsh应从历史记录中删除任何以空格开头的命令。但是,它会暂时保留在内部历史记录中,直到执行下一个命令。因此,我在 中设置了此选项~/.zshrc,然后重新定义了键绑定以重新配置 shell 的配置,如下所示:

    setopt HIST_IGNORE_SPACE
    bindkey -s '^Xr' ' . ~/.zshrc^M ^M'
#                     │            │
#                     │            └─ command containing only a space to force `zsh`
#                     │               to “forget“ the previous command immediately
#                     └─ space added to prevent `zsh` from logging the command

相关内容