在 Vim 中,数字键盘上的 5 键在当前行上方插入一行 "E"

In Vim, the 5-key on the numeric keypad inserts a line above the current line with "E"

在 Linux Mint 20.2(关闭 NumLock)下使用 Vim 时,当我按下 NumPad 中心键 (5) 时,在当前行上方插入一行,出现大写字母 E , 我留在插入模式。在尝试使用 NumPad 光标键进行导航时,我经常错误地按下 5 键,我很想重新定义 NumPad 5 以使其无所事事。我已经尝试重新映射 .vimrc 中的密钥(例如,使用 noremap <Esc>[E <Esc>),但它没有任何效果。注意,当我按下 NumPad5 时产生的 ANSI 序列是 3[E

仅供参考,我有 TERM=xterm-256color

注意:此答案通常在无数字锁定上下文中讨论数字键盘。当使用 <k0>...<k9> 打开数字锁定时,可以映射数字键盘上的所有数字。因此,对键的可映射性的引用是在无数字锁定上下文中

Note, the ANSI sequence produced when I press the NumPad5 is 3[E

Vim 不这么认为。

在我的系统(X11 下的 Mint 20.2 和 Cinnamon)上,no-numlock 5 产生 ^[OEO 对于观察到的行为 非常 重要。 o 表示“转到下面的新行并进入插入模式”,O 表示完全相同的内容,但转到上面的新行。下一个 E 然后被解释为插入模式字符,因为 Vim.

此外,esc表示为^[,因此为了映射目的,您只需要<esc>。这一点在Vim:

中更容易证明

^[ 被额外视为单个字符。如果您想玩这个,请进入插入模式并按 <C-v>。您按下的下一个键(绑定)将逐字打印到屏幕上

这意味着你真正想要的是:

nnoremap <Esc>OE <nop>

请注意,我不确定这里如何应用终端输入处理;这可能只适用于某些终端,甚至只适用于 X11。

这里的另一个技巧,以及确保键码对您的终端正确的方法是,您可以键入 :nnoremap ,然后按 Ctrl +v+数字键 5。这将为您提供 Vim 看到的确切键码,然后您可以将其映射到您计划的任何内容。

但是,如果您在 gVim 中执行此操作,您会发现没有 numlock 的小键盘 5 实际上不会生成 gVim 可检测到的键码。这大概意味着它不能被映射(除非有某种我不知道的方式 - 如果有,请证明我错了)。但是因为它不会喷出终端代码,所以有一个额外的好处,即不需要 为这个特定目的重新映射它,因为它没有你试图解决的问题首先避免这里。


romainl 在 中提到了 :help key-notation,但这里有一点需要注意:

gVim 不生成键码通常意味着没有键码。 <C-v> 后跟 gVim 中的小键盘 9 产生 <kPageUp>,但后跟小键盘 5,它不产生任何东西。其次,如果阅读 :h key-notation,您会发现它只定义了 home、end、up 和 down,以及各种运算符、enter 和小数点。 2、4、6、8都注册为普通方向键,即<Down><Left><Right><Up>。无法在小键盘上专门检测到这些,但这并不重要。

如果您一直在跟踪,您会发现小键盘 5 已被排除在外。 注意: 当 numlock 开启时,<C-v> + 小键盘 5 不会在 Vim 或 gVim 中输出任何内容,因为定义是:

Insert the next non-digit literally.

参见 :h i_CTRL-V

TL;DR:

<C-v>是你的朋友。

使用:

nnoremap <Esc>OE <nop>

或使用 <C-v> 插入键码,这可能取决于也可能不取决于终端。

gVim 中不需要映射,而且可能无法实现。

您看到此行为的原因是 Vim 仅使用终端数据库的 termcap 接口。如果它使用 terminfo,它会看到更广泛的信息。

在键盘上键入键会产生误导,因为 Vim(与几乎所有终端应用程序一样)会将键盘置于 应用程序模式 ,这会导致终端发送EscapeO 而不是 Escape [ 作为前缀。在终端符号中,即 \EO。在 XTerm Control Sequences 中,它被称为 SS3(技术上用词不当,因为它适用于 output,而键盘输入是 input — 但由于没有标准适用于键盘输入,这已经足够了)。

xterm 的终端描述在某一点将 \EOE 分配给 kbeg 能力(即 terminfo,termcap 名称 @1)。那是不久前的事了,大约 1996.

terminfo 名称通常为 3-5 个字符,而 termcap 名称始终为 2.

标准 terminfo 有数量有限的特殊键(例如您熟悉的数字小键盘)。所有 standard termcap 名称对应于这些 terminfo 个名字。在标准排列中,只有五个键与键盘关联:ka1ka3kb2kc1kc3,对应termcap的K1, K2, K3, K4,以及K5。 (为什么没有标准k2,kb1,kb3,或者kc2早已被遗忘)。

寻找改进 ncurses 终端描述的方法,提出了一些不同的 standard 键布局。但最好的解决方案在于添加新密钥,使用扩展功能(自 1999 年以来 ncurses 的一个功能)。这些扩展都有名称,并且被选择为符合 terminfo 命名约定。所以...在May 2019, the terminfo building blocks xterm+keypad and vt220+keypad中进行了介绍。在前者中(用于 xterm-newxterm-256color,该键名为 kp5.

terminfo(5) 联机帮助页中列出的标准名称中没有 kp5。它是一个扩展的(用户可定义的)键。在旧方案中,一些其他密钥对应用程序不可用。

ncurses 应用程序将自动能够使用所有键,因为 ncurses 使用 terminfo(并将终端描述中的所有键添加到其特殊情况下以进行计时)。

Vim 将看不到该键的定义,因为它只查看终端描述的一小部分(大约三分之一)。由于它看不到定义,因此它不会将其添加到特殊情况中,在这种特殊情况下它将等待(短时间)以完成在该键上发送的字符序列。如另一个答案所述,在这种情况下,Vim 将看到命令 EscapeO 插入序列中的第三个字符“E”。