如何检测24bit颜色支持

以前一直没怎么注意这个问题,直到这次我自己基于base16框架做了一个Jetbrains Gruvbox soft black 配色的 port ,发现同一个代码,在Gnome Terminal 和 tmux 下显示效果差异很大。

GNOME Terminal下显示正常:

gnome-terminal-vim-256-color-test-ok.png

tmux 下显示的颜色不对:

tmux-vim-no-256.png

于是我突然想起来,256 color 的支持问题.

事实上tmux官方仓库里有两个很好的工具,用于检测256 color 是否被支持:

curl -sSfL https://github.com/tmux/tmux/raw/master/tools/24-bit-color.sh | sh

perl 脚本那个不太容易看看出来:

curl -sSfL https://github.com/tmux/tmux/raw/master/tools/256colors.pl | perl

这两个脚本我这里也存了一份:

24-bit-color.sh

256colors.pl

24bit color:

tmux-24bit-true-color-ok.png

8bit color: tmux-8bit-color-alacritty.png

24-bit-color.sh 的识别度非常好,可以下载回来作为常规检测工具使用。

另外还有一段awk代码也不错:

awk 'BEGIN{
    s="/\\/\\/\\/\\/\\"; s=s s s s s s s s;
    for (colnum = 0; colnum<77; colnum++) {
        r = 255-(colnum*255/76);
        g = (colnum*510/76);
        b = (colnum*255/76);
        if (g>255) g = 510-g;
        printf "\033[48;2;%d;%d;%dm", r,g,b;
        printf "\033[38;2;%d;%d;%dm", 255-r,255-g,255-b;
        printf "%s\033[0m", substr(s,colnum+1,1);
    }
    printf "\n";
}'

tmux 配置

tmux must be told that the terminal outside supports RGB colour. This is done by specifying the RGB or Tc terminfo(5) flags. RGB is the official flag, Tc is a tmux extension. With tmux 3.2 and later this can be added with the terminal-features option: set -as terminal-features ",gnome*:RGB" Or for any tmux version the terminal-overrides option: set -as terminal-overrides ",gnome*:Tc"

编辑 .tmux.conf, 增加两行(注意下面,一个是适用于3.2的,一个是适用于3.1的):

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

# tmux 3.2之后
set -as terminal-features ",xterm-256color:RGB"

# tmux 3.1
set -as terminal-overrides ",xterm-256color:RGB"

# 如果tmux只在gnome terminal里打开
# set -as terminal-features ",gnome*:RGB"

# 如果tmux只在alacritty里打开
# set -ag terminal-features ",alacritty:RGB"

# 兼容方案
# set -as terminal-overrides ",xterm-256color:RGB"

terminal-overrides applies to the outside $TERM. It basically says: When starting tmux in a shell that has $TERM set to xterm-256color, add the Tc capability to tmux’s internal image of tmux-256color to signalize it to use true colors.

oh my tmux 配置

oh my tmux 默认已经内置支持了,但是默认是关闭的。

只需要编辑 .tmux.conf.local, 将tmux_conf_theme_24b_colour=true修改为true

tmux_conf_theme_24b_colour=true

它最终会执行:


run 'cut -c3- ~/.tmux.conf | sh -s _apply_configuration'

# _apply_configuration -> _apply_overrides

_apply_overrides() {
  tmux_conf_theme_24b_colour=${tmux_conf_theme_24b_colour:-false}
  if _is_enabled "$tmux_conf_theme_24b_colour"; then
  case "$TERM" in
    screen-*|tmux-*)
      ;;
    *)
      tmux set-option -ga terminal-overrides ",*256col*:Tc"
      ;;
  esac
  fi
}

# 因此实际上它是执行的
# tmux set-option -ga terminal-overrides ",*256col*:Tc"

Alacritty 支持

除非我们在tmux配置了set -ag terminal-overrides ",alacritty:RGB" (tmux 3.1) 或set -ag terminal-features ",alacritty:RGB" (tmux 3.2), 否则,默认情况下, 我们在Alacritty里运行tmux, tmux还是不能支持24bit color.

但是,如果设置set -ag terminal-overrides ",alacritty:RGB", 当tmux跑在 Gnome Terminal 下时,又失去24bit color了。

因此,为了兼容,我们需要修改Alacrity 的配置:

# Any items in the `env` entry below will be added as
# environment variables. Some entries may override variables
# set by alacritty itself.
env:
  # TERM variable
  #
  # This value is used to set the `$TERM` environment variable for
  # each instance of Alacritty. If it is not present, alacritty will
  # check the local terminfo database and use `alacritty` if it is
  # available, otherwise `xterm-256color` is used.
  # TERM: alacritty
  TERM: xterm-256color

它的TERM 默认值是 alacritty, 而当前tmux并不能识别它是不是支持256color, 因此,我们需要把它设置成兼容 xterm-256color

参考文档

https://github.com/tmux/tmux/issues/1246#issuecomment-493454336

https://jdhao.github.io/2018/10/19/tmux_nvim_true_color/

https://github.com/tmux/tmux/wiki/FAQ#how-do-i-use-rgb-colour

https://stackoverflow.com/q/15375992/6064933

Good explanation about what terminal-overrides does.

https://stackoverflow.com/q/41783367/6064933

https://www.reddit.com/r/neovim/comments/825dj7/the_endless_litany_of_tmux_and_nvim_color_problems/

Why you should not set TERM inside shell config file

You should not set TERM inside shell config file.