I'll start with Xterm because it is the most complicated one. Kitty and Urxvt are tackled at the end.
~/.Xresources file configures Xterm (and some
other Xlib applications). Whenever you are done editing it, issue
xrdb ~/.Xresources and open a new Xterm to test the changes.
man xterm or configuring Xterm for further options, such as
colors and fonts — the defaults are admittedly ugly.
We will follow Leonerd's article proposal, and have the terminal send
CSI codepoint;modifier u, where
CSI stands for an Esc character followed by
codepoint is the decimal Unicode value of the character to be mapped.
ASCII characters have the same decimal representation in Unicode.
modifier is chosen from the table below:
X in an ASCII table and find that its decimal value is 88.
CSI 88;5 u should be sent to Vim. This goes in
Ctrl ~Meta Shift <Key>x :string("\033[88;5u")
Ctrl-Shift-x now produces the sequence in quotes. A tilde
negates the modifier, i.e.,
~Meta means that Alt is not pressed (Meta
033 is Esc in octals.
There should be no spaces after the backslashes (Xrdb would warn you of
the mistake) and, as will be seen ahead, multiple bindings should be
separated from each other with
Tab and Ctrl-i
i is decimal 105 and
Tab is decimal 9, but both Ctrl-i
and Tab send 9, as the ASCII table article explains. So
Ctrl-i must send a different sequence to disambiguate them,
and by the same reasoning as before, we conclude it is
CSI 105;5 u.
Ctrl ~Meta ~Shift <Key>i :string("\033[105;5u")
One could also add
~Ctrl ~Meta ~Shift <Key>Tab :string("\011") but that would
be redundant since
Tab already sends decimal 9 (octal 11).
Tab is special as listed under "Modified C0 controls".
~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")
More special keys
Here belong F1-F12, Home and others.
In Xterm they already have unambiguous codes, which can be straightforwardly
determined by pressing Ctrl-vKey in Vim's insert
mode. For example, Ctrl-vCtrl-F1 produces
Now we just have to add the bindings to
" 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>
The 5th line is very important: Ctrl-i, used to move back in
the jump list, is not Tab anymore in Xterm; instead it sends a
different sequence to Vim, thus that sequence should be mapped to what
Vim has under Ctrl-i.
If you notice a delay when Esc is pressed in insert mode,
adjust Vim's timeout settings, e.g.
set timeoutlen=1000 ttimeoutlen=20
(see timeoutlen vs ttimeoutlen).
If in doubt what keysym should go in
xev to find it
out. For example, pressing the left Windows/Super key outputs
In Xterm, Ctrl-Q and Ctrl-S are reserved for
flow control, a legacy feature. To map them, first deactivate flow control
" Disable XOFF/XON
silent !stty -ixon
" Redraw screen
To make the maps invisible to other TUI programs, you can keep Vim under
a different Xterm classname, such as
xterm -name vimterm -e vim file
vimterm instead of
XTerm in the
.Xresources file. How to
open new files in a same Vim instance may prove helpful.
Other terminal emulators: Urxvt and Kitty
Urxvt uses a different syntax in
A interfering binding caused by ISO 14755 also has to be disabled.
Kitty does not use
.Xresources, the bindings go in
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