Summary

Run :set t_ut= to disable Background Color Erase. Run :redraw or press <C-L> to repaint the background. Use terminalkeys and fixkey to recognize modifier keys.

Problem

This is what you would see if you applied the Zenburn color scheme to Vim running under the TERM=xterm-256color environment inside tmux or GNU screen, which itself was attached to the xterm-256color terminal:

Here, the terminal’s background color bleeds into Vim’s and, depending on the contrast between those two colors, makes Vim use highly unpleasant.

Thankfully, you can fix this by running :set term=screen-256color inside Vim or by relaunching Vim under the TERM=screen-256color environment, as some experts recommend:

However, if you rely on Vim’s ability to sense modifier keys—such as Shift, Control, and Alt—because you use them to define custom keyboard shortcuts like I do, then you would soon discover that Vim does not recognize some of them inside the screen-256color terminal.

Thus you would be faced with a most unnerving dilemma:

Do you forfeit your custom keyboard shortcuts to gain a proper background color by running Vim inside the screen-256color terminal? Do you suffer background color bleeding to retain your custom keyboard shortcuts by running Vim inside the xterm-256color terminal?

Alas, is it truly a binary choice? Must you really forgo your personal keyboard shortcuts in order to view your chosen Vim color scheme properly? No, I would not accept such a fate; there has to be a better way! >:O

Approach

I knew about Vim’s ability to manipulate its host terminal through its t_Co setting, which lets you override how many colors Vim thinks its host terminal is capable of rendering. Thus, looking up :help t_Co in Vim revealed numerous terminal settings—which all happened to be listed in the terminal-options section of Vim’s help documentation—that could be overridden, hopefully in the same way, to perhaps solve this problem.

However, there were too many settings in the documentation to practically investigate by hand, so I narrowed down the possibilities to the following eleven settings by searching for the words “color” and then “clear”:

OUTPUT CODES option meaning t_AB set background color (ANSI) t_AF set foreground color (ANSI) t_cd clear to end of screen t_ce clear to end of line t_cl clear screen t_Co number of colors t_me Normal mode (undoes t_mr, t_mb, t_md and color) t_op reset to original color pair t_Sb set background color t_Sf set foreground color t_ut clearing uses the current background color

I then observed the values of these settings in both environments so that I could (1) compare them to discover what makes Vim render its background color correctly in the screen-256color terminal and then (2) replicate those values to achieve the same effect in the xterm-256color terminal.

screen-256color observations:

t_cd=^[[J t_ce=^[[K t_cl=^[[H^[[J t_AB=^[[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m t_AF=^[[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m t_Co=256 t_me=^[[0m t_op=^[[39;49m t_Sb= t_Sf= t_ut=

xterm-256color observations:

t_cd=^[[J t_ce=^[[K t_cl=^[[H^[[2J t_AB=^[[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m t_AF=^[[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m t_Co=256 t_me=^[[m t_op=^[[39;49m t_Sb= t_Sf= t_ut=y

Differences in observations:

--- screen-256color observations +++ xterm-256color observations @@ -1,11 +1,11 @@ t_cd=^[[J t_ce=^[[K -t_cl=^[[H^[[J +t_cl=^[[H^[[2J t_AB=^[[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m t_AF=^[[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m t_Co=256 -t_me=^[[0m +t_me=^[[m t_op=^[[39;49m t_Sb= t_Sf= -t_ut= +t_ut=y

Comparing these observations, I found that xterm-256color only differed from screen-256color in these three settings: t_cl , t_me , and t_ut .

Solution

One by one, I applied the screen-256color value of each differing setting to a Vim session that was running inside my desired xterm-256color terminal and then pressed Control-L to make Vim redraw itself. Changing t_cl and t_me had no effect but, luckily, t_ut did the trick! :-)

This makes sense because, according to Vim documentation, not only does t_ut control whether Vim “uses the current background color” to clear the screen (also known as Background Color Erase, or BCE for short) but it also takes effect only when its value is a non-empty string.

In this case, Vim used BCE in xterm-256color because, under that terminal, t_ut had value y : a non-empty string. Conversely, Vim did not use BCE in screen-256color because under that terminal, t_ut had no value.

Therefore, the solution is to simply clear Vim’s t_ut value if Vim happens to be running inside any 256-color terminal. You can automate this by adding the following snippet to your Vim configuration file: