网络资源(1,2,3)声称某些组合键,其中Ctrl-Shift-letter, Ctrl-number, Ctrl-i/ Tab, Ctrl-m/ Enter, Esc/Ctrl-[无法在 Vim 中可靠地映射,因为终端无法将它们与未修改的对应组合区分开来(更多背景信息请参阅这是吉尔斯的回答和这篇 ASCII 表文章)。作为一个具体的例子,地图
nnoremap <Tab> :!echo A<CR>
noremap <C-S-X> :!echo B<CR>
noremap <C-1> :!echo C<CR>
noremap <C-F1> :!echo D<CR>
导致Tab和Ctrl-i打印 A (也在 Gvim 中),并且Ctrl-x和Ctrl-Shift-x打印 B. Ctrl-{1,2,...}和Ctrl-{F1,F2,...}无法映射,前者甚至在 Gvim 中也不能映射。
这个答案到“如何以不同方式映射 Ctrl-a 和 Ctrl-Shift-a?”简短地描述了 Xterm 的解决方案,但它缺少一些可能会被某些人忽略的棘手细节。这是试图提供更完整的答案。
尽管这是一个以 Vim 为中心的问题,但具有可自定义映射的其他终端应用程序也可以从中受益。 Vifm 就是一个明显的例子。
答案1
我将从Xterm因为它是最复杂的一个。猫咪和乌尔克斯夫特最后得到解决。
X资源
这~/.Xresources
文件配置 Xterm(以及其他一些 Xlib 应用程序)。每当您完成编辑时,发出
xrdb ~/.Xresources
并打开一个新的 Xterm 来测试更改。从...开始
XTerm*metaSendsEscape: true
XTerm*eightBitInput: false
请参阅man xterm
或配置 Xterm对于更多选项,例如颜色和字体,默认设置确实很难看。
发送键码
我们将跟随莱昂纳德的文章提案,并让终端发送
CSI codepoint;modifier u
, 其中
CSI代表 Esc 字符后跟
[
。代码点是要映射的字符的十进制 Unicode 值。 ASCII 字符在 Unicode 中具有相同的十进制表示形式。
修饰语从下表中选择:
没有任何 转移 替代 Alt+Shift 控制键 Ctrl+Shift Ctrl+Alt Ctrl+Alt+Shift 1 2 3 4 5 6 7 8
Ctrl-Shift-x
查找X
在ASCII 表发现它的十进制值为88。因此CSI 88;5 u
应该发送到Vim。这进入.Xresources
:
XTerm*Translations: #override\
Ctrl ~Meta Shift <Key>x :string("\033[88;5u")
Ctrl-Shift-x现在产生引号中的序列。波形符否定修饰符,即~Meta
表示未按下 Alt(Meta 表示 Alt)。033
是八进制的 Esc。
反斜杠后面不应有空格(Xrdb 会警告您该错误),并且如前面所见,多个绑定应使用 彼此分隔\n\
。
Tab 和 Ctrl-i
i
是十进制 105 和Tab
十进制 9,但两者都Ctrl-i
发送Tab9,作为ASCII 表文章解释说。因此
Ctrl-i必须发送不同的序列来消除它们的歧义,并且通过与之前相同的推理,我们得出结论是CSI 105;5 u
。
XTerm*Translations: #override\
Ctrl ~Meta ~Shift <Key>i :string("\033[105;5u")
也可以添加~Ctrl ~Meta ~Shift <Key>Tab :string("\011")
,但这将是多余的,因为Tab
已经发送了十进制 9(八进制 11)。
修改Tab
是特殊的,如“修改的 C0 控制”下所列。
XTerm*Translations: #override\
~Ctrl ~Meta Shift <Key>Tab :string("\033[Z") \n\
Ctrl ~Meta ~Shift <Key>Tab :string("\033[9;5u") \n\
Ctrl ~Meta Shift <Key>Tab :string("\033[1;5Z")
更多特殊按键
这里属于F1-F12和Home其他人。在 Xterm 中,它们已经有了明确的代码,可以通过Ctrl-vKey在 Vim 的插入模式下按 直接确定。例如,Ctrl-vCtrl-F1产生<ESC>[1;5P
.
维姆尔克
现在我们只需将绑定添加到.vimrc
:
" Disambiguate Tab and Ctrl-i
nnoremap <ESC>[105;5u <C-I>
nnoremap <Tab> :!echo A<CR>
noremap <ESC>[88;5u :!echo B<CR>
noremap <ESC>[49;5u :!echo C<CR>
noremap <ESC>[1;5P :!echo D<CR>
第5行非常重要:Ctrl-i,用于在跳转列表中向后移动,Tab在Xterm中不再存在;相反,它会向 Vim 发送不同的序列,因此那个序列应该映射到 Vim 下的内容Ctrl-i。
额外说明
如果您发现在插入模式下按 时有延迟Esc,请调整 Vim 的超时设置,例如
set timeoutlen=1000 ttimeoutlen=20
(请参阅timeoutlen 与 ttimeoutlen)。如果不确定应该输入什么键符号
.Xresources
,请使用xev
来查找它。例如,按左侧 Windows/Super 键输出Super_L
。在 Xterm 中,Ctrl-Q和Ctrl-S保留用于流量控制,这是一项遗留功能。要映射它们,首先通过添加来停用流量控制
" Disable XOFF/XON silent !stty -ixon " Redraw screen silent !resize>/dev/null
到
.vimrc
。要使地图对其他 TUI 程序不可见,您可以将 Vim 保留在不同的 Xterm 类名下,例如
xterm -name vimterm -e vim file
并在文件中使用
vimterm
代替。XTerm
.Xresources
如何在同一个 Vim 实例中打开新文件可能会有所帮助。
其他终端模拟器:Urxvt 和 Kitty
乌尔克斯夫特在 中使用不同的语法.Xresources
。由 ISO 14755 引起的干扰绑定也必须被禁用。
URxvt*iso14755: false
URxvt*keysym.C-i: \033[105;5u
URxvt*keysym.C-X: \033[88;5u
URxvt*keysym.C-1: \033[49;5u
URxvt*keysym.C-F1: \033[1;5P
猫咪不使用.Xresources
,绑定进入
~/.config/kitty/kitty.conf
:
map ctrl+shift+x send_text application \033[88;5u
map ctrl+i send_text application \033[105;5u
map ctrl+1 send_text application \033[49;5u
map ctrl+F1 send_text application \033[1;5P