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