如何在Vim中在普通模式和插入模式之间切换光标?

158

我想知道如何在Vim中根据模式更改光标(颜色、形状等),如果可能的话。

我经常忘记自己不在插入模式下,开始输入代码,结果会发生各种奇怪的事情。如果光标有某种视觉指示,这将是很有帮助的。


29
我建议你学习一个规则:停止输入就退出插入模式。这样你就永远不会遇到忘记自己不在插入模式的情况了。 - ZyX
6
除非你忘记退出插入模式,否则不会出现这种情况,呵呵。 - gented
13
@ZyX 这是一个好的规则,我一直遵守,但视觉指示仍然很重要。现在大麻合法了,我经常会忘记自己在做什么。 - felwithe
12个回答

154
以下内容在Linux上的xterm,urxvt和其他终端模拟器中有效;在macOS上的iTerm2;在Windows上使用ConEmu的Git Bash以及更多终端(请参见评论)也同样有效:
let &t_SI = "\e[6 q"
let &t_EI = "\e[2 q"

" reset the cursor on start (for older versions of vim, usually not required)
augroup myCmds
au!
autocmd VimEnter * silent !echo -ne "\e[2 q"
augroup END

其他选项(将\e[后面的数字替换为所需选项):

Ps = 0  -> blinking block.
Ps = 1  -> blinking block (default).
Ps = 2  -> steady block.
Ps = 3  -> blinking underline.
Ps = 4  -> steady underline.
Ps = 5  -> blinking bar (xterm).
Ps = 6  -> steady bar (xterm).

使用tmux时,很重要的一点是不要使用转义字符\<Esc>Ptmux;,这样tmux可以在切换窗口/窗格时正确追踪光标形状。

如果这对你不起作用,请尝试在启动tmux之前设置TERM=xterm-256color,或将此内容添加到您的.tmux.conf文件中(感谢@Steven Lu的帮助:来源):

set -ga terminal-overrides ',*:Ss=\E[%p1%d q:Se=\E[2 q'

4
现在在 alacritty 中表现得很好。 - Steven Lu
1
我的更新:终于在我的tmux配置中使用set -ga terminal-overrides',*:Ss=\E[%p1%d q:Se=\E[2 q'。显然,如果您在terminal-overrides中使用set而没有使用-a,它将覆盖默认设置。 - Steven Lu
2
该解决方案在简单终端(suckless st)上从插入模式到正常模式的形状转换存在显著延迟。 - daGo
tmux 的部分非常有启发性!非常感谢! - Gordon Bai
对于GNU screen,您需要将其包装在\eP终端代码\e\\中。 - Mikhail Modin
显示剩余11条评论

135
一种常用的方法是通过切换cursorline选项来表示进入和退出插入模式,该选项决定当前屏幕行是否高亮显示(参见:help cursorline)。
:autocmd InsertEnter * set cursorline
:autocmd InsertLeave * set nocursorline

或者,另外选择:
:autocmd InsertEnter,InsertLeave * set cul!

修改CursorLine高亮组,以您喜欢的样式改变光标行的样式(参见:help :highlight:help highlight-groups)。
当然,这种方法假设您在正常模式下不使用光标行高亮。

9
我还将cul设置为突出显示背景而不是默认的下划线:hi CursorLine cterm=NONE ctermbg=black - Niki Tonsky
1
这个在cygwin的vim里为什么不能工作呢?我已经在编辑器中输入了两组代码,但是除了全列或全行高亮之外,我无法设置任何其他类型的高亮。 - TankorSmash
1
@Tankor:cursorline选项不依赖于任何特定平台的功能;它在任何编译了+syntax特性的Vim实例中都可用(通常情况下都是这样)。 - ib.
1
当然,将其保存到您的/.vimrc中以实现永久性,如下所示:`echo 'autocmd InsertEnter,InsertLeave * set cul!' >>/.vimrc` - alchemy

31

不确定是否有其他人在按下 Esc 键返回正常模式后遇到延迟的问题,但如果确实存在,这是我解决它的方法。

实际上,我正在 macOS 终端中使用 iTerm2 并在其中使用 Vim。当进入插入模式时,光标仍然是块状的,这有点令人困惑,因为您无法确定当前处于插入模式还是正常模式。

我希望在插入模式下显示细线作为光标,在正常模式下重新变成块状,就像 MacVim 一样。要做到这一点,很简单,只需将此添加到我的.vimrc文件中,如这里描述的

let &t_SI = "\<Esc>]50;CursorShape=1\x7"
let &t_SR = "\<Esc>]50;CursorShape=2\x7"
let &t_EI = "\<Esc>]50;CursorShape=0\x7"

enter image description here

但是,正如您所看到的,在按下ESC键以退出插入模式返回普通模式并再次显示块作为光标时出现了延迟。因此,为了解决这个问题,我找到了以下内容:

set ttimeout
set ttimeoutlen=1
set ttyfast

现在它的效果非常好,你可以看到:

修复光标返回块时的延迟

我希望它能帮助其他人!


2
模式切换的延迟问题一直困扰着我很久,谢谢! - outerSpace
2
@leedreit 我也是直到我找到了这个解决方法! - alexventuraio

20
如果您在macOS上使用tmux和iTerm2,以下代码可以将光标从块状改为竖线并高亮当前行。
if exists('$TMUX')
  let &t_SI = "\<Esc>Ptmux;\<Esc>\<Esc>]50;CursorShape=1\x7\<Esc>\\"
  let &t_EI = "\<Esc>Ptmux;\<Esc>\<Esc>]50;CursorShape=0\x7\<Esc>\\"
else
  let &t_SI = "\<Esc>]50;CursorShape=1\x7"
  let &t_EI = "\<Esc>]50;CursorShape=0\x7"
endif
:autocmd InsertEnter * set cul
:autocmd InsertLeave * set nocul

来源: https://gist.github.com/andyfowler/1195581


1
请注意,这是特定于iTerm的。虽然标准终端实际上也可以工作,但也适用于所有其他支持的终端,这可能是错误的答案。请查看此处--> https://dev59.com/rWw15IYBdhLWcg3wntOh#42118416 - Steven Lu
@StevenLu,实际上你建议的答案对于iTerm2(Mac)并没有起作用,而这个可以。这些东西比你想象的要棘手。 - C S
这个光标的东西绝对是其中比较棘手的事情之一。我刚意识到我甚至没有一个合适的设置,因为 tmux 似乎没有执行光标状态跟踪,一些答案表明这是可能的。我非常高兴能让 vim 在插入模式下处理将光标设置到某一行。 - Steven Lu
我弄清楚了这个问题。解决方案是调整tmux以正确处理它,但这可能不明显。我需要做的是确保我的tmux配置文件的“terminal-overrides”只被附加到,这样它就不会覆盖“terminal-overrides”的“,*:Ss=\E[%p1%d q:Se=\E[2 q”部分。所以我的配置看起来像这样:“set -sa terminal-overrides“,xterm-256color-italic:Tc”(设置24位颜色启用而不破坏光标样式Ss/Se)。 - Steven Lu

13

要在不同模式下更改光标的形状,您可以将以下内容添加到.vimrc文件中。

适用于GNOME终端(版本2.26):

if has("autocmd")
  au InsertEnter * silent execute "!gconftool-2 --type string --set /apps/gnome-terminal/profiles/Default/cursor_shape ibeam"
  au InsertLeave * silent execute "!gconftool-2 --type string --set /apps/gnome-terminal/profiles/Default/cursor_shape block"
  au VimLeave * silent execute "!gconftool-2 --type string --set /apps/gnome-terminal/profiles/Default/cursor_shape ibeam"
endif

如果您在GNOME终端中使用多个配置文件,则可能需要根据您的配置文件进行调整。

对于KDE4中的Konsole:

let &t_SI = "\<Esc>]50;CursorShape=1\x7"
let &t_EI = "\<Esc>]50;CursorShape=0\x7"

这适用于多个选项卡和窗口。

另请参阅:更改不同模式下的光标形状Vim技巧Wiki 上。


14
我主要使用Putty通过SSH连接tmux上的vim。是否有更通用的选项? - lanrat
1
通过gconftool-2命令更改gnome-terminal的设置是一个非常糟糕的想法。它不仅会影响您正在运行vim的终端,还会影响相同配置文件的所有其他当前和未来的gnome-terminal选项卡。 - egmont
1
这对于konsole有效,谢谢。但是有一个问题是退出插入模式很慢,不确定为什么。 - Hoang Tran
1
@HoangTran 使用 set ttimeoutlen=0 - Bananach
如何将此应用于所有配置文件。例如,我有One light和Foxnight配置文件 - 当我使用默认配置文件时,它只适用于Foxnight配置文件。 - daGo

11

您可以尝试使用 Terminus Vim 插件:

在插入模式下,光标形状会变成细的垂直条。在替换模式下,它将变为下划线。返回到正常模式后,它将恢复为标准的“块”形状。


这似乎是最明智的解决方案。VIM中应该直接有一个:set来实现这个功能,这是标准的。 - user12711
要求:gnome-terminal(https://wiki.gnome.org/Apps/Terminal)和其他使用VTE库(https://github.com/GNOME/vte)的终端:部分支持(例如,支持光标形状更改但不支持焦点报告)。在我的情况下(gnome-terminal 3.6.2),它根本不起作用。 - daGo

10

我发现仅在插入模式下让光标闪烁,并使其在其他模式下保持静态是很有用的。

set guicursor+=n-v-c:blinkon0

1
此解决方案会导致光标在所有模式下闪烁。 - Adam Michalak

8
根据 "Vim Tips WiKi" 上的 post
"要在不同模式下更改光标的形状,您可以将以下内容添加到您的 vimrc 文件中:"
"对于 macOS 终端"
"Mode Settings

let &t_SI.="\e[5 q" "SI = INSERT mode
let &t_SR.="\e[4 q" "SR = REPLACE mode
let &t_EI.="\e[1 q" "EI = NORMAL mode (ELSE)

"Cursor settings:

"  1 -> blinking block
"  2 -> solid block 
"  3 -> blinking underscore
"  4 -> solid underscore
"  5 -> blinking vertical bar
"  6 -> solid vertical bar

该帖子中还包括其他操作系统的脚本。


1

我认为这并没有为其他人已经提供的答案增加很多内容,但我想以某种方式将事情总结在一个地方,并且还有相关引用的链接。

这是我.vimrc中相关代码片段的样子:

    " Cursor appearance
    "
    " See also: [1]'ANSI Control Functions Summary', [2]DECSCUSR, [3]xterm+tmux
    "   entry in terminfo.src.
    " [1] https://www.vt100.net/docs/vt510-rm/chapter4.html
    " [2] https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
    " [3] https://raw.githubusercontent.com/mirror/ncurses/master/misc/terminfo.src
    "
    " On:
    " - entered insert mode
    let &t_SI = "^[[5 q^[]12;Magenta\007" " blinking bar (Ss) in magenta (Cs)
    " - entered replace mode
    let &t_SR = "^[[0 q^[]12;Red\007" " blinking block (Ss) in red (Cs)
    " - leaving insert/replace mode
    let &t_EI = "^[[2 q^[]112\007" " terminal power-on style (Se) and colour (Cr)

注意:'^[''字符实际上是一个ESC(转义序列)控制字符。

1
如果你正在使用现代版本的nvim并想要实现这个目标,你可以避免上面列出的一些花哨的解决方法。
以下设置将从普通模式下的块状光标切换到替换模式下的下划线光标以及插入模式下的行光标。
# ~/.tmux.conf
set -g default-terminal "screen-256color"
set -ga terminal-overrides ",*256col*:Tc"
set -ga terminal-overrides '*:Ss=\E[%p1%d q:Se=\E[ q',w


" ~/.vimrc
" Sets cursor styles
" Block in normal, line in insert, underline in replace
set guicursor=n-v-c-sm:block,i-ci-ve:ver25-Cursor,r-cr-o:hor20

我通过参考以下两个来源,成功地使用了以下设置: tui-cursor-shape guicursor

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