在终端 Vim 中映射其他冲突或不可映射的键

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)

导致TabCtrl-i打印 A (也在 Gvim 中),并且 和Ctrl-x打印Ctrl-Shift-xB. Ctrl-{1,2,...}Ctrl-{F1,F2,...}无法映射,前者甚至在 Gvim 中也不能映射。

是“如何以不同方式映射 Ctrl-a 和 Ctrl-Shift-a?”的答案。简短地描述了 Xterm 的解决方案,但它缺少一些可能会被忽略的棘手细节。这是试图提供更完整的答案。

尽管这是一个以 Vim 为中心的问题,但具有可自定义映射的其他终端应用程序也可以从中受益。Vifm 就是一个明显的例子。

Qua*_*odo 9

我将从Xterm开始,因为它是最复杂的。KittyUrxvt最后被擒抱。

\n

X资源

\n

~/.Xresources文件配置 Xterm(以及一些\n其他 Xlib 应用程序)。每当您完成编辑时,请发出\nxrdb ~/.Xresources并打开一个新的 Xterm 来测试更改。\n从

\n
XTerm*metaSendsEscape: true\nXTerm*eightBitInput:   false\n
Run Code Online (Sandbox Code Playgroud)\n

请参阅man xterm配置 Xterm以获取更多选项,例如\n颜色和字体\xe2\x80\x94,默认值确实很难看。

\n

发送键码

\n

我们将遵循Leonard 的文章提案,并让终端发送\n CSI codepoint;modifier u,其中

\n
    \n
  • CSI代表 Esc 字符,后跟[.

    \n
  • \n
  • 代码点是要映射的字符的十进制 Unicode 值。\nASCII 字符在 Unicode 中具有相同的十进制表示形式。

    \n
  • \n
  • 修饰符从下表中选择:

    \n
    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n
    没有任何转移替代Alt+Shift控制键Ctrl+ShiftCtrl+AltCtrl+Alt+Shift
    12345678
    \n
  • \n
\n

Ctrl-Shift-x

\n

查找ASCII 表X,发现其十进制值为 88。\n因此应该发送到 Vim。这进入:CSI 88;5 u.Xresources

\n
XTerm*Translations: #override\\\n    Ctrl ~Meta  Shift <Key>x   :string("\\033[88;5u")\n
Run Code Online (Sandbox Code Playgroud)\n

Ctrl-Shift-x现在产生引号中的序列。波形符\n否定修饰符,即~Meta表示未按下Alt(Meta\n表示Alt)。033是八进制的 Esc。

\n

反斜杠后面不应该有空格(Xrdb 会警告您这个错误),并且如前面所见,多个绑定应该用 .\n 彼此分隔\\n\\

\n

Tab 和 Ctrl-i

\n

i是十进制 105 和Tab十进制 9,但两者Ctrl-iTab发送 9,如ASCII 表文章所述。因此,\nCtrl-i必须发送不同的序列来消除它们的歧义,\n并且通过与之前相同的推理,我们得出结论是CSI 105;5 u

\n
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)。

\n

修改Tab是特殊的,如“修改的 C0 控制”下所列。

\n
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

更多特殊按键

\n

这里属于F1-F12Home其他。\n在 Xterm 中,它们已经有明确的代码,可以通过Ctrl-vKey在 Vim 的插入模式下按\n直接确定。例如,Ctrl-vCtrl-F1产生<ESC>[1;5P.

\n

维姆尔克

\n

现在我们只需将绑定添加到.vimrc

\n
" 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

额外说明

\n
    \n
  • 如果您发现在插入模式下按 时有延迟Esc,请调整 Vim 的超时设置,例如set timeoutlen=1000 ttimeoutlen=20(请参阅timeoutlen 与 ttimeoutlen)。

    \n
  • \n
  • 如果不确定应该输入什么键符号.Xresources,请使用xev\n来查找它。例如,按左侧 Windows/Super 键输出Super_L

    \n
  • \n
  • 在 Xterm 中,Ctrl-QCtrl-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

    \n
  • \n
  • 要使地图对其他 TUI 程序不可见,您可以将 Vim 保存在不同的 Xterm 类名下,例如

    \n
    xterm -name vimterm -e vim file\n
    Run Code Online (Sandbox Code Playgroud)\n

    并在文件中使用vimterm代替。如何在同一个 Vim 实例中\n打开新文件可能会有所帮助。XTerm.Xresources

    \n
  • \n
\n

其他终端模拟器:Urxvt 和 Kitty

\n

Urxvt在 中使用不同的语法.Xresources。\n还必须禁用由 ISO 14755 引起的干扰绑定。

\n
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)\n

Kitty不使用.Xresources,绑定进入\n ~/.config/kitty/kitty.conf

\n
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