How to get shift+arrows and ctrl+arrows working in Vim in tmux?

This is all in iTerm2 on OS X.

I used to have

export TERM='xterm-256color'

in my .bashrc. This meant Vim in tmux did use 256 colors.

And once I added

set -g xterm-keys on

then keyboard shortcuts with modifiers worked fine in Vim. Namely: shift+left/right that I mapped to switch Vim tabs, ctrl+up/down that I mapped to move ("bubble") lines, and shift+left/right which worked out of the box to jump by word in the command-line mode (e.g. when typing something like :e foo bar baz).

However, this setup had the problem that the Vim background color only shows behind text, as mentioned here.

So I removed

export TERM='xterm-256color'

from my .bashrc and instead put this in my .tmux.conf:

set -g default-terminal "screen-256color"

That fixed the Vim background color, but broke the keyboard shortcuts - they do unexpected things (move the cursor, delete text) instead.

By using ctrl+v to insert the verbatim output from the key combinations (as described here), I was able to work around it:

map [1;5A <C-Up>
map [1;5B <C-Down>
map [1;2D <S-Left>
map [1;2C <S-Right>
cmap [1;2D <S-Left>
cmap [1;2C <S-Right>

This makes the shortcuts work, but it doesn't feel like the right solution. Could anyone tell me what's happening here and how to fix it?


You need to set the tmux window option xterm-keys so that tmux will pass these keys through to its terminals. You probably want to put this in your ~/.tmux.conf:

set-window-option -g xterm-keys on

Vim will usually automatically set up its handling of these keys when TERM is xterm-something, but it skips this since TERM is screen-256color. You can manually configure these keys in your ~/.vimrc like this:

if &term =~ '^screen'
    " tmux will send xterm-style keys when its xterm-keys option is on
    execute "set <xUp>=\e[1;*A"
    execute "set <xDown>=\e[1;*B"
    execute "set <xRight>=\e[1;*C"
    execute "set <xLeft>=\e[1;*D"
endif

At least that way you do not have to map all the various combinations.


As explained here, disable Background Color Erase (BCE) by clearing the t_ut terminal option (run :set t_ut= in Vim and then press Control+L to refresh the terminal's display) so that color schemes work properly when Vim is used inside tmux and GNU screen.

This way, you can keep your TERM value as xterm-256color for proper key detection while also getting proper Vim color scheme rendering too! :-)