不同的vi编辑模式下使用不同的bash提示符?

124

当在Bash中使用vi模式(set -o vi)时,希望拥有一个根据当前模式(插入或命令)而变化的提示符。如何找出这个编辑模式?

顺便提一下,在ZSH中似乎可以实现这一点:链接


我也对此很好奇。一直在查找Bash文档,但没有找到相关的内容。 - Andrew Ferrier
考虑在提示符中切换单个字符以指示模式。 - FriskySaga
9个回答

74

最新的bash 4.3和readline 6.3为你们带来了一些东西,从更新日志中可以看到:

4.  New Features in Readline
j.  New user-settable variable, show-mode-in-prompt, adds a characters to the
    beginning of the prompt indicating the current editing mode.
所以将其放置。
set show-mode-in-prompt on

将以下内容添加到 /etc/inputrc 或 ~/.inputrc (感谢 stooj)可以影响所有启用 readline 的程序 ;)


有进展了吗?我正在尝试找到类似于此的东西(不是针对Bash,而是针对我使用的其他基于readline的提示符)。我已经搜索了谷歌,并没有发现任何其他更新(除了您引用的文章http://cnswww.cns.cwru.edu/php/chet/readline/CHANGES) - Mike H-R
4
从eMPee584的补充内容开始,如果您正在运行bash 4.3或更高版本,请将以下内容添加到您的~/.inputrc文件中:set show-mode-in-prompt。如果您处于编辑模式,则此项会在提示符的最左侧添加+号,如果您处于命令模式,则添加:号。 - stooj
3
虽然这个方法可行,但是否有一种方法可以移动这个vi模式字符在提示符中的位置?如果你有多行自定义提示符,它可能不太适用 :) - James Mills
对于4.3版本,它总是出现在提示符的开头,不幸的是,readline只会重绘多行提示符的最后一行。请参考“多行提示符和.inputrc”答案中的解决方法,或者查看有关使用4.4版本修补bash 4.3的答案。 - studgeek

26
Bash 4.4 / Readline 7.0将增加支持用户设置模式字符串的功能。 您可以尝试beta版本,但目前它们似乎有点不稳定。它们还不支持指定提示符中希望出现模式指示符的位置(我认为这是最重要的功能)。
如果您不想等待,并且不怕编译一点代码,我已经发布了bash 4.3和readline 6.3的修补版本到github上,支持此功能。
使用修补后的版本,您可以像这样做: enter image description here 更多详细信息,包括如何安装,请访问https://github.com/calid/bash

19

在搜索了Google、查阅了bash man页面和查看了bash源代码(lib/readline/vi_mode.c)后,我发现没有简单的方法可以在从插入模式切换到命令模式时更改提示符。不过,由于源代码中有启动和停止模式的调用,因此可能会有机会让某人修补bash源代码。

看到您的帖子后,我对bash vi模式设置产生了兴趣。我喜欢vi,并且希望在命令行上使用它。但是,很多论坛帖子指出我们必须跟踪是否处于插入模式而没有提示符更改。就其价值而言,除非按ESC键,否则始终处于插入模式。这使得操作变得稍微容易一些,但并不总是那么直观。

我对你的问题产生了兴趣,期待看到进展。


8
这是我在".inputrc"文件中的内容:

<code>〜/ .inputrc</ code>

set show-mode-in-prompt on
set vi-ins-mode-string \1\e[34;1m\2└──[ins] \1\e[0m\2
set vi-cmd-mode-string \1\e[33;1m\2└──[cmd] \1\e[0m\2

插入模式以蓝色显示。

└──[ins]

命令模式显示黄色。

└──[cmd]

这种方法的缺点是它无法在tty上显示,这意味着它只能在终端仿真器中工作并显示颜色。

7

多行提示符和 .inputrc

.inputrc 有一个选项可以在插入模式下显示 +,在正常模式下显示 :,只需在 ~/.inputrc 中添加 set show-mode-in-prompt on,就像 eMPee584 所写的那样。但是,在具有较旧版本的 bash 和 readline 的多行提示符中,这种方法效果不佳。

解决方案是使用单行 PS1 (>),并在提示符之前输出一些内容的函数。它内置于 bash 中,称为 PROMPT_COMMAND

function prompt {
    PS1=' > '
    echo -e "$(date +%R)  $PWD"
}

PROMPT_COMMAND='prompt' 

通常的提示字符串在echo或printf中不可用。使用-e来解释颜色代码,而且不需要添加\[\],因为这样做也没有效果。 插入模式:
20:57   /home/sshbio/dotfiles/bash
+ > _

正常模式:

20:57   /home/sshbio/dotfiles/bash
: > _

按下Tab键,只有PS1会重复显示,这对我来说是有意义的。
20:57   /home/sshbio/dotfiles/bash
+ > ls _
bashrc      bash_profile     inputrc
+ > ls _

预览 (源代码)


1
如果在 vi-cmd-mode-stringvi-ins-mode-string 中使用颜色,应该在前缀中加上 \1,在后缀中加上 \2。请参见此处。另外,在 printf 中仍然需要发出 \[\[,但是你需要使用 \\[\\] - Tom Hale

7

Spacemacs样式的彩色光标

这个设置会使光标按照Spacemacs的样式显示,其中dotspacemacs-colorize-cursor-according-to-state被设为t

set editing-mode vi

set vi-ins-mode-string \1\e[5 q\e]12;green\a\2
set vi-cmd-mode-string \1\e[1 q\e]12;orange\a\2

set show-mode-in-prompt on

enter image description here


2
你能解释一下那些 ANSI 术语代码是做什么的吗? - Lin
1
@Lin 我知道这是一条旧评论,甚至是一个更古老的帖子,但在翻阅了几十年前的文件后,我找到了人们在这里似乎拥有的所有神奇知识的解释。 当我想要改变我的提示符和光标颜色时,我偶然发现了两个不同的转义序列: \e[ 和 \e] 第一个被称为CSI(控制序列引导程序) 第二个被称为OSC(操作系统命令)。跟着一个;12,它告诉终端仿真器改变光标的颜色。 在这里查看:https://www.xfree86.org/current/ctlseqs.html 寻找“Change text”。 - Orel Fichman
Sam,你在使用哪个终端模拟器和操作系统?我正在使用MacOS Monterey的iTerm,但似乎对我不起作用,尽管我阅读了一些详细的文档(链接在我之前回复Lin的评论中)。我知道这是一个旧评论,但我希望你能看到并为我解决这个问题:)提前感谢。 - Orel Fichman
@OrelFichman 我正在使用带有Git Bash(Windows版Git)的Windows终端。它显示为GNU bash,版本为4.4.23(2)-release (x86_64-pc-msys)。 - Sam Hasler
@SamHasler 谢谢,在阅读了更多资料之后,我发现这似乎是一个GNU特定的转义代码。我成功地使用他们专有的转义代码在我的Iterm2上使它正常工作了。 - Orel Fichman

7

通过.inputrc设置不同的提示符和光标样式

首先,确保你正在运行高于4.3版本的bash:

$ bash --version
GNU bash, version 4.4

然后将以下行放入您的~/.inputrc文件中:
#################### VIM ####################
# FOR MORE INFORMATION CHECK:
# https://wiki.archlinux.org/index.php/Readline

# TURN ON VIM (E.G. FOR READLINE)
set editing-mode vi

# SHOW THE VIM MODE IN THE PROMPT (COMMAND OR INSERT)
set show-mode-in-prompt on

# SET THE MODE STRING AND CURSOR TO INDICATE THE VIM MODE
#   FOR THE NUMBER AFTER `\e[`:
#     0: blinking block
#     1: blinking block (default)
#     2: steady block
#     3: blinking underline
#     4: steady underline
#     5: blinking bar (xterm)
#     6: steady bar (xterm)
set vi-ins-mode-string (ins)\1\e[5 q\2
set vi-cmd-mode-string (cmd)\1\e[1 q\2

在命令模式下,光标显示为块状。
在插入模式下,光标显示为竖线。
根据模式不同,提示符本身将如下所示:
(cmd)$ ... 
(ins)$ ...

太棒了!- 谢谢!我刚学会了像这样做:set vi-cmd-mode-string \033[1;32m\1\e[1 q\2,它只会改变你的提示符号的颜色。这正是我想要的!- 不再是另一个 () - Nealium

2
针对像这样的多行提示 image 我的解决方法是这样的
我的bash提示符
export PS1=" ┌錄 \[\e[32m\]\u\[\e[m\]\[\e[32m\]@\[\e[m\]\[\e[32m\]\h\[\e[m\] \w \\$ \n "

.inputrc

set show-mode-in-prompt on
set vi-ins-mode-string " └──錄 (ins):"
set vi-cmd-mode-string " └──錄 (cmd):"

希望这有所帮助。

0

我也尝试为BASH vi模式获取一个指示器,但是你们都知道这听起来很简单,但实际上还没有找到方法。

我的当前方法是:当我不确定处于哪种模式时,按下'a'。如果在BASH提示符后出现'a',则说明我处于“插入”模式。然后,我按下“RETURN”并继续。这对我来说是解决小烦恼的简单方法。

顺便说一句,我将“a = cal”或其他内容设置为别名,以使空白的按键'a'有点用处。


2
对我来说,只需按“esc||c-["键就可以了,这比a更有意义。然后你就不必看来知道你处于什么模式;或者插入不需要的字符,你必须删除(或按回车键)。 - wom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接