【问题标题】:Is there a way to switch Bash or zsh from Emacs mode to vi mode with a keystroke?有没有办法通过按键将 Bash 或 zsh 从 Emacs 模式切换到 vi 模式?
【发布时间】:2010-04-14 18:49:49
【问题描述】:

我希望能够暂时从 emacs 模式切换到 vi 模式,因为 vi 模式有时更好,但我通常在我意识到我想要之前输入了一半使用 vi 模式。

我不想永久切换到 vi 模式,因为我通常更喜欢命令行上的 emacs 模式,主要是因为我已经习惯了,而且多年来许多击键已经成为第二天性。 (作为一个编辑器,我通常在 viper 模式下使用 emacs,这样我就可以同时使用 vi 和 emacs 击键,因为我发现自己一直不小心在 vi 中使用它们,并且把事情搞砸了,而且因为在某些情况下,我发现 vi 击键更容易记住和方便,而在其他情况下是 emacs。)

【问题讨论】:

    标签: bash history zsh


    【解决方案1】:

    您可以创建一个切换,因为键绑定在 vi 模式和 emacs 模式之间是分开的。

    $ set -o emacs
    $ bind '"\ee": vi-editing-mode'
    $ set -o vi
    $ bind '"\ee": emacs-editing-mode'
    

    现在 Alt-e(或 Esc e)将在模式之间切换。

    PS1 的定义中添加此内容,以便在提示符中指示您处于哪种模式。切换模式时它不会立即显示更改,但会在出现新提示时更新已发布。

    $(set -o | grep emacs.*on >/dev/null 2>&1 && echo E || echo V)
    

    【讨论】:

    • 你先生,太棒了。但是,它仍然不能在 zsh 中正常工作。通过一些小的调整,我可以让模式指示器从命令行工作:set -o | grep 'vi.*on' >|/dev/null 2>&1 && echo '[vi]' || echo '' 但是我的提示只有在我获取 .zshrc 文件时才会改变。 (我还没有在 bash 中测试过模式指示器。)
    • Zsh 行编辑器似乎不支持“vi-editing-mode”,只支持“vi-cmd-mode”。 (但是,您仍然可以使用 'set -o vi' 或 'bindkey -v' 来有效地获得完整的 vi 模式。) ^xv 默认绑定到 zsh 中的 vi-cmd-mode。它只持续到它执行的那一行,你只需点击“i”就可以退出它,这会让你回到 emacs 模式。相比之下,bash 解决方案会一直持续到您显式切换模式,然后点击“i”将使您进入 vi 插入模式。
    • 如果您将$(command) 放入您的PS1 变量的定义中,该命令将立即被评估 - 因此您的提示是静态定义的,您必须获取您的~/.zshrc 才能重新生成提示。如果您希望您的提示动态显示变量/命令,则必须修改 Zsh 在显示提示之前运行的 precmd 函数。将其放入您的 zshrc 以修复模式指示器:
    • function precmd { psvar[1]="$(set -o | grep 'emacs.*on' >/dev/null 2>&1 && echo E || echo V)" }
    • @Jabir Ali Ouassou:您可以转义美元符号(或将命令替换括在单引号中),并且命令替换将在发出提示时而不是在定义时进行评估。 Bash 需要shopt -s promptvars(这是默认设置)。 Zsh 需要setopt promptsubst
    【解决方案2】:

    啊哈!我查看了 readline 源代码,发现您可以这样做:

     "\M-v": vi-editing-mode
     "\M-e": emacs-editing-mode
    

    似乎没有切换开关,但这可能已经足够了!

    为了后代,这是我的原始答案,这对于尝试做没有 readline 功能的事情的人可能很有用。

    您可以通过以下方式进行设置,清除进程中的当前命令行。我知道,这不是您想要的,但也许它会帮助发现此问题的其他人。在 ~/.inputrc:

    "\M-v": "\C-k\C-uset -o vi\C-j" # alt (meta)-v: set vi mode
    "\M-e": "\C-k\C-uset -o vi\C-j" # alt (meta)-e: set emacs mode
    

    或切换...这应该可以:

    "\M-t": "\C-k\C-u[[ \"$SHELLOPTS\" =~ '\\bemacs\\b' ]] && set -o vi || set -o emacs\C-j"
    

    这些本质上是别名,更进一步映射到 readline 中的键,这样您就不必键入别名并按回车键。

    【讨论】:

      【解决方案3】:

      以下.inputrc 行允许Meta / Alt+Eemacsvi-insert 模式之间切换。

      同时移动 jk 将带您进入vi-command 模式。

      注意:唯一带“kj”的英文单词是“blackjack”,没有单词包含“jk”)

      set keymap emacs
      "\ee": vi-editing-mode
      "jk": "\eejk"
      "kj": "\eejk"
      
      set keymap vi-insert
      "\ee": emacs-editing-mode
      "jk": vi-movement-mode
      "kj": vi-movement-mode
      
      set keymap vi-command
      "\ee": emacs-editing-mode
      

      注意:如果您在keymap emacs 下添加绑定到vi-movement-mode 以尝试直接切换到vi-command 模式,如果您有show-mode-in-prompt on,则提示不会更新,因此需要上述解决方法.

      【讨论】:

        猜你喜欢
        • 2021-04-12
        • 2011-11-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-04
        • 1970-01-01
        • 2011-04-07
        • 2020-09-04
        相关资源
        最近更新 更多