在終端 Vim 中映射其他衝突或不可映射的鍵
網路中的資源 ( 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>
導致
Tab
andCtrl-i
都列印 A(也在 Gvim 中)和 bothCtrl-x
andCtrl-Shift-x
列印 B.Ctrl-{1,2,...}
andCtrl-{F1,F2,...}
不能被映射,前者甚至在 Gvim 中也沒有。這個回答“如何以不同的方式映射 Ctrl-a 和 Ctrl-Shift-a?” 簡短地描述了 Xterm 的解決方案,但它缺少一些可能會漏掉的棘手細節。這是試圖提供更完整的答案。
儘管這是一個以 Vim 為中心的問題,但其他具有可自定義映射的終端應用程序也可以從中受益。Vifm 是一個明顯的例子。
我將從Xterm開始,因為它是最複雜的一個。最後解決了Kitty和Urxvt。
X 資源
該
~/.Xresources
文件配置 Xterm(和一些其他 Xlib 應用程序)。每當您完成編輯它時,發出xrdb ~/.Xresources
並打開一個新的 Xterm 來測試更改。從…開始XTerm*metaSendsEscape: true XTerm*eightBitInput: false
請參閱
man xterm
或配置 Xterm以獲取更多選項,例如顏色和字型——預設設置確實很難看。發送鍵碼
我們將按照Leonerd 的文章建議,並讓終端發送
CSI codepoint;modifier u
,其中
- CSI代表 Esc 字元後跟
[
.- codepoint是要映射的字元的十進制 Unicode 值。ASCII 字元在 Unicode 中具有相同的十進製表示。
- 修飾符選自下表:
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
發送Tab
9,正如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)。Modified
Tab
是特殊的,如“Modified C0 controls”下所列。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-v``Key
在 Vim 的插入模式下直接確定。例如,Ctrl-v``Ctrl-F1
產生<ESC>[1;5P
.vimrc
現在我們只需要將綁定添加到
.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
而不是。如何在同一個 Vim 實例中打開新文件可能會很有幫助。XTerm``.Xresources
其他終端仿真器:Urxvt 和 Kitty
Urxvt在
.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