Vim

在終端 Vim 中映射其他衝突或不可映射的鍵

  • March 18, 2021

網路中的資源 ( 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>

導致TabandCtrl-i都列印 A(也在 Gvim 中)和 both Ctrl-xandCtrl-Shift-x列印 B. Ctrl-{1,2,...}andCtrl-{F1,F2,...}不能被映射,前者甚至在 Gvim 中也沒有。

這個回答“如何以不同的方式映射 Ctrl-a 和 Ctrl-Shift-a?” 簡短地描述了 Xterm 的解決方案,但它缺少一些可能會漏掉的棘手細節。這是試圖提供更完整的答案。

儘管這是一個以 Vim 為中心的問題,但其他具有可自定義映射的終端應用程序也可以從中受益。Vifm 是一個明顯的例子。

我將從Xterm開始,因為它是最複雜的一個。最後解決了KittyUrxvt

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

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

ModifiedTab是特殊的,如“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-F12Home其他人。在 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,用來在跳轉列表中向後移動,現在TabXterm 中沒有了;相反,它會向 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

引用自:https://unix.stackexchange.com/questions/631241