将 vi 模式字符串移动到 bash 提示符的末尾

将 vi 模式字符串移动到 bash 提示符的末尾

我在 bash 中使用 vi 编辑模式。我在 ~/.inputrc 中将“show-mode-in-prompt”设置为“on”。

提示时显示模式(关闭)

如果设置为 On,则在提示符开头添加一个字符串,指示编辑模式:emacs、vi 命令或 vi 插入。模式字符串可由用户设置(例如 emacs-mode-string)。

所以现在我可以在提示的开头看到编辑模式。

i:$ # This is ins mode
c?$ # This is cmd mode
i:$ cat ~/.inputrc
set editing-mode vi
set show-mode-in-prompt on
set vi-ins-mode-string "\1\e[1;32m\2i:\1\e[0m\2"
set vi-cmd-mode-string "\1\e[1;31m\2c?\1\e[0m\2"
set colored-stats on
i:$ echo $PS1
$

我真的很想在提示符的末尾加上这个,并在前面加上当前目录,即

/current/dir/here $ i:

但我不确定这是否可以实现。我的第一个想法是在 PS1 中使用回车符,但不幸的是这会覆盖模式字符串。

i:$ PS1='\r\w $ '
~/projects $

我的第二个想法是以某种方式获取模式字符串并将其插入 $PROMPT_COMMAND,而不是让 readline 将其写入提示。我可以使用以下命令获取当前模式:

i:$ bind -v | grep keymap | awk '{print $3}'
vi-insert

但是 PROMPT_COMMAND 值仅在发出提示之前执行,所以我看不到模式改变。

第三次尝试包括填充模式字符串,以便为目录留出空间。这可以工作,但我不知道如何使空间量可变。此外,提示将在模式字符串之前启动,模式字符串将被我的命令覆盖,如果我切换模式,我输入的文本将被整个模式字符串替换,从而有效地清除了空格。

                                i:  cat ~/.inputrc
set editing-mode vi
set show-mode-in-prompt on
set vi-ins-mode-string "                                \1\e[1;32m\2i:\1\e[0m\2"
set vi-cmd-mode-string "                                \1\e[1;31m\2c?\1\e[0m\2"
set colored-stats on
                                i:  PS1="\r\w $ "
~/projects $                    i:
~/projects $ # typing stuff     i:
~/projects $ # typing more stuff overwrites the mode line
~/projects $                    c?verwrites the mode line

还有其他巧妙的方法可以做到这一点吗?也许像回车符这样的控制字符会跳转到行首但不会覆盖现有字符?

i:$ echo $BASH_VERSION
5.0.7(1)-release

答案1

您可以通过为 cmd 和 insert 模式设置一个非常长的模式字符串来实现这一点,该模式字符串包括您希望在提示符中显示的其他项目。请注意,这意味着您将无法使用 PS1 中提供的特殊快捷方式,例如\w“漂亮”地打印当前目录。但您可能可以在执行相同操作的 shell 代码中实现相同的效果。

bind "set vi-ins-mode-string \"...\""您可以使用和命令设置 readline 变量bind "set vi-cmd-mode-string \"...\""。(help bind有关详细信息,请参阅。)您可以从中进行设置PROMPT_COMMAND,以便在每次提示之前重置它(因此,如果您包含目录、日期和时间的变化,它将反映它们等。)

引用可能会很棘手:-)

对于您自己使用的示例:

/current/dir/here $ i:

你可以使用这个:

reset_readline_prompt_mode_strings () {
    bind "set vi-ins-mode-string \"$PWD \$ \1\e[1;32m\2i:\1\e[0m\2\""
    bind "set vi-cmd-mode-string \"$PWD \$ \1\e[1;31m\2c?\1\e[0m\2\""
}
PROMPT_COMMAND=reset_readline_prompt_mode_strings
PS1=' '

如上所述,的扩展$PWD将包含完整路径,并且不会使用等的相对路径~

您可以获得相同的提示中使用的扩展通过使用 bash 的${variable@P}运算符扩展:

EMBEDDED_PS1='\w $ '
reset_readline_prompt_mode_strings () {
    bind "set vi-ins-mode-string \"${EMBEDDED_PS1@P}\1\e[1;32m\2i:\1\e[0m\2\""
    bind "set vi-cmd-mode-string \"${EMBEDDED_PS1@P}\1\e[1;31m\2c?\1\e[0m\2\""
}

请注意,您需要PS1将其设置为非空值,否则根本不会打印任何提示。在这种情况下,您可以使用单个空格。您可能需要考虑PS2适当设置,以便进行行延续。

ins顺便说一句,我对和模式字符串的符号和颜色的建议cmd是:

  • cmd应该使用:(与在 Vim 中从正常模式输入:命令相同)并且应该使用绿色(因为这是光线在“正常”模式的状态行中。)
  • ins应该使用+(这是 Vim 用来显示缓冲区被修改的符号,当你插入时,你就修改了它)并且应该使用蓝色(Vim 使用的默认颜色光线在“插入”模式的状态行中。)

我个人认为下面这些非常酷:

EMBEDDED_PS1='\w $ '
reset_readline_prompt_mode_strings () {
    bind "set vi-ins-mode-string \"${EMBEDDED_PS1@P}\1\e[32m\2: >\1\e[92m\2>\1\e[0m\2>\""
    bind "set vi-cmd-mode-string \"${EMBEDDED_PS1@P}\1\e[34m\2+ >\1\e[94m\2>\1\e[0m\2>\""
}
PROMPT_COMMAND=reset_readline_prompt_mode_strings
PS1=' '
PS2=' ... '

相关内容