Mapping Control-Tab in terminal Vim
One thing keeping me away from moving away from gVim to terminal Vim was the fact, that I could not map <C-Tab>
or <C-S-Tab>
. I this to cycle through open buffers and as an UltiSnips
snippet trigger. A lot of people ask this question, but it's hard to find the right answer. Usually people just say that the terminal do not see the difference between Tab
and C-Tab
, which is, well, not quite true.
What is true, is the fact that there is no standard escape sequence for C-Tab
or C-S-Tab
, therefore terminals do quite reasonable thing and just send the escape sequence for Tab
or S-Tab
, respectively. Terminal applications only see the escape sequences, so they cannot differentiate between Tab
and C-Tab
— they receive the same escape sequence. We can, however, configure our terminal emulator to send a different escape sequence for C-Tab
, than for Tab
and then handle this properly in terminal Vim.
I use Alacritty, so I added the following two lines to key_bindings
in .config/alacritty/alacritty.yml
:
- { key: Tab, mods: Control, chars: "\x1b[1;5I" }
- { key: Tab, mods: Control|Shift, chars: "\x1b[1;6I" }
This tells alacritty to send escape sequence ^[[1;5I
when we press C-Tab
. We can check that by running sed -n l
, press the required key sequence followed by an Enter (keep in mind that ^[
, \x1b
and \033
is just the escape sequence written in a different way).
Now, we have to handle that in Vim. Vim has its own keycodes and automatically assigns terminal escape sequences to them. Our custom escape sequences are not handled that way, so we have to assigne them manually. We can assign custom escape sequences using set
command, but the Vim keycodes one can assign to are limited to the keycodes listed here. Unfortunatelly, <C-Tab>
and <C-S-Tab>
are not listed there, so it means we cannot assign escape sequence to them. We have to pick some other, unused, keycode (I used <F15>
), assign the escape sequence and create a mapping between <F15>
and <C-Tab>
, so Vim treats those keycodes the same way:
set <F15>=^[[1;5I
set <F16>=^[[1;6I
nmap <F15> <C-Tab>
nmap <F16> <C-S-Tab>
imap <F15> <C-Tab>
imap <F16> <C-S-Tab>
IMPORTANT: Please note, that you have to input the actual escape sequence, not just write individual characters ^[
. To do that enter insert mode, press C-V
and follow this with Esc
(this will insert just the escape escape sequence) and manully insert the rest of the escape sequence or with C-Tab
(this will insert the whole escape sequence).
You can read more on mapping keycodes in Vim here.