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

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

网络资源(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>

导致TabCtrl-i打印 A (也在 Gvim 中),并且Ctrl-xCtrl-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

查找XASCII 表发现它的十进制值为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-F12Home其他人。在 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-QCtrl-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

相关内容