我在 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=' ... '