Search code examples
linuxvimtmux

What's happening here with vim inside TMUX pane?


When I open vim inside of a TMUX pane, The pane is filled with codes I don't recognise. If I just run vim, I get this:

^[[38;2;165;42;42m  1
^[[38;2;0;0;255m~

If I open a file with vim, I get something like this (top pane): enter image description here

Pretty new to both vim and TMUX. How can I solve this?


Solution

  • It seems that Vim is sending control sequences to your terminal which the latter doesn't understand.
    More specifically, the sequences you mentioned in the OP:

    ^[[38;2;165;42;42m
    ^[[38;2;0;0;255m
    

    look like they're encoding foreground true colors for the text.

    You can find their syntax here:

    CSI Pm m
    

    Where CSI stands for “Control Sequence Introducer” and is produced by the keys ESC [, and Pm stands for:

    A multiple numeric parameter composed of any number of single numeric parameters, separated by ; character(s).

    If you scroll down the page, you should find a description of a more detailed syntax:

    CSI Pm m Character Attributes (SGR).

    ...

    This variation on ISO-8613-6 is supported for compatibility with KDE konsole:

    Pm = 3 8 ; 2 ; Pr; Pg; Pb
    Set foreground color to the closest match in xterm's palette for
    the given RGB Pr/Pg/Pb.
    
    Pm = 4 8 ; 2 ; Pr; Pg; Pb
    Set background color to the closest match in xterm's palette for
    the given RGB Pr/Pg/Pb.*
    

    Applied to your first sequence, you can break it down like so:

    ┌ CSI
    │  ┌ Pm
    ├─┐├────────────┐
    ^[[38;2;165;42;42m
            ├─┘ ├┘ ├┘
            │   │  └ Pb = amount of blue
            │   └ Pg = amount of green
            └ Pr = amount of red
    

    If the terminal doesn't understand this sequence, I can see 3 explanations:

    1. the terminal doesn't support true colors
    2. tmux is not properly configured to support true colors
    3. Vim is not properly configured to support true colors

    To test whether 1. is the issue, you can write this bash function in your ~/.bashrc:

    truecolor() {
      local i r g b
      for ((i = 0; i <= 79; i++)); do
        b=$((i*255/79))
        g=$((2*b))
        r=$((255-b))
        if [[ $g -gt 255 ]]; then
          g=$((2*255 - g))
        fi
        printf -- '\e[48;2;%d;%d;%dm \e[0m' "$r" "$g" "$b"
      done
      printf -- '\n'
    }
    

    Then execute $ truecolor in your shell, outside tmux. If you get some kind of rainbow, your terminal supports true colors (at least partially). If you see some cells which are not colored, and others randomly colored, your terminal doesn't support true colors.

    Alternatively, you can try the sequences manually:

    $ printf '\e[38;2;%d;%d;%dm this text should be colored \e[0m' 165 42 42
    $ printf '\e[38;2;%d;%d;%dm this text should be colored \e[0m' 0 0 255
    

    If $ truecolor doesn't produce a rainbow, or if the $ printf commands don't change the foreground color (not the background color) of the text, you'll have to either:

    • disable 'termguicolors' in your ~/.vimrc; i.e. remove set termguicolors (or make it execute set notermguicolors)
    • try and upgrade your terminal
    • find another terminal which supports true colors

    To test whether 2. is the issue, inside tmux, you can execute this shell command:

    $ tmux info | grep Tc
    

    If the output contains [missing]:

    203: Tc: [missing]
             ^^^^^^^^^
    

    it means that tmux is not configured to support true colors. In this case, you have to include something like this in ~/.tmux.conf:

    set -as terminal-overrides ',*-256color:Tc'
         ││ ├────────────────┘   ├────────┘ ├┘
         ││ │                    │          └ tell tmux that the terminal suppors true colors
         ││ │                    └ configure the option only if `$TERM` ends with the string `-256color`
         ││ └ the option to configure is `terminal-overrides` (see `$ man tmux`)
         │└ the next option is a server option
         └ append the value to the tmux option instead of overwriting it
    

    Then restart tmux, and execute $ tmux info | grep Tc. This time the output should contain true:

    203: Tc: (flag) true
                    ^^^^
    

    If it doesn't, have a look at the output of $TERM outside tmux:

    $ echo $TERM
    

    The output should be matched by whatever pattern you write before :Tc.
    In the previous example, I used the pattern *-256color which will match any terminal whose $TERM ends with the string -256color. If it doesn't match your $TERM, you can try another pattern, or simply write * to describe any type of terminal:

    set -as terminal-overrides ',*:Tc'
    

    To test whether 3. is the issue, you can write these commands in your ~/.vimrc:

    set termguicolors
    let &t_8f = "\<Esc>[38:2:%lu:%lu:%lum"
    let &t_8b = "\<Esc>[48:2:%lu:%lu:%lum"
    

    Or:

    set termguicolors
    let &t_8f = "\<Esc>[38;2;%lu;%lu;%lum"
    let &t_8b = "\<Esc>[48;2;%lu;%lu;%lum"
    

    The only difference between the 2 versions is the delimiter between the parameters of the sequences. A colon in the first version, a semicolon in the second one. See :h xterm-true-color for more info.

    You can check the current values of these 3 options by executing successively:

    :echo &tgc
    :echo &t_8f
    :echo &t_8b
    

    They should output:

    1
    ^[[38:2:%lu:%lu:%lum
    ^[[48:2:%lu:%lu:%lum
    

    Or:

    1
    ^[[38;2;%lu;%lu;%lum
    ^[[48;2;%lu;%lu;%lum