3

I'm trying to use 16 color colorscheme in vim8.2 1-677 in my ubuntu18.04 /dev/tty3(ctrl-alt-f3).

This is what I have done so far:

Change tty color in my bashrc:

if [[ "$TERM" = linux ]]; then
    echo -en "\e]P0282828" #black
    ...
    echo -en "\e]PFebdbb2" #white
    clear
fi

execute sudo dpkg-reconfigure console-setup, pick a small codeset to avoid loosing color bit.

By default, TERM is linux for tty, the bright foreground is achieved with bold attribute:

tput bold ; tput setaf 1 ; echo red

the bright background is achieved with blink attribute:

tput blink ; tput setab 1 ; echo red

(Check this page if your TERM is not linux)

:h cterm-colors says it support the bold foreground as bright foreground color, but it won't work for background colors. So I change my TERM to linux-16color:

TERM=linux-16color
infocmp -f linux-16color
-----------
        setab=\E[4
                %p1%{8}%m%d
                %?
                        %p1%{7}%>
                        %t;5
                %e
                        ;25
                %;
                m,
        setaf=\E[3
                %p1%{8}%m%d
                %?
                        %p1%{7}%>
                        %t;1
                %e
                        ;21
                %;
                m,

It changed setaf and setab to use bold(1 as on, 21 as off) or blink(5 as on, 25 as off) when the color index is greater then 7, check this answer for more explanation.

Then I test 16 foreground and background colors:

for ((c = 0; c < 16; c++)); do
printf "|%s%3d%s" "$(tput setaf "$c")" "$c" "$(tput sgr0)"
done
for ((c = 0; c < 16; c++)); do
printf "|%s%3d%s" "$(tput setab "$c")" "$c" "$(tput sgr0)"
done

update

The color test failed, Foreground 0-7 stop working (I missed that in the original post), they all refer to the 6th foreground color. enter image description here

I checked the output sequence:

printf "%q\n" $(tput setaf 2)
--------
$'\E[32;21m'

The sequence works fine without 21(bold off), something must be wrong.

  • 1
    Typically you need to modify your terms colorscheme some to fit their color palette or otherwise indicate 256 v. truecolor – D. Ben Knoble May 5 at 13:44
  • @D.BenKnoble I think you are talking the first step: change tty color. – dedowsdi May 5 at 13:46
  • 2
    I think so too... but to be honest this question could probably use a screenshot or two to show what’s really happening. And you might have better luck talking with the colorscheme maintainers, since they probably see this stuff more often. – D. Ben Knoble May 5 at 13:48
2

Final result

It should be the same as it's 256color brother (without bold, underline, italic,...)

enter image description here

Warning

It's not easy, don't do it unless you really want to spend a lot of time in vc(virtual console).

Setup terminal

Switch to vc, change TERM:

TERM=linux-16color

Some important desription for linux-16color from ncurse terminfo, pls read it:

# 16-color linux console entry; this works with a 256-character
# console font but bright background colors turn into dim ones when
# you use a 512-character console font. This uses bold for bright
# foreground colors and blink for bright background colors.
...

run sudo dpkg-reconfig console-setup, choose a small character set(the one starts with #) to avoid loosing bright bg color.

Run this script to see if your vc is capable of displaying 16 distinct fg and bg colors:

#!/usr/bin/env bash

printf "Colors 0 to 15 for the standard 16 foreground colors\n"
for ((c = 0; c < 16; c++)); do
    printf "|%s%3d%s" "$(tput setaf "$c")" "$c" "$(tput sgr0)"
done
printf "|\n\n"

printf "Colors 0 to 15 for the standard 16 background colors\n"
for ((c = 0; c < 16; c++)); do
    printf "|%s%3d%s" "$(tput setab "$c")" "$c" "$(tput sgr0)"
done
printf "|\n\n"

There is a good chance you see only 8 distinct fg colors(0-7 are all cyan): enter image description here

it's a bug, your linux-16color use 21 to clear bold instead of 22.

read !infocmp -f linux-16color | grep -A10 setaf
--------
    setaf=\E[3
        %p1%{8}%m%d
        %?
            %p1%{7}%>
            %t;1
        %e
            ;21  <------------------it's here
        %;
        m,

You can see Parameterized Strings section of man terminfo if you are confucsed by the grammar.

man console_codes
--------
...
       21      set normal intensity (ECMA-48 says "doubly underlined")
       22      set normal intensity
...

ncurse terminfo shows history of this bug.

Change 21 to 22, recompile it with tic(If you don't know how to do it, you can copy terminfo from above link to a file and run tic your_copy), run the test script again, you should see 16 distinct bg and fg colors.

Setup tmux (you can skip this if you don't use it)

We must use screen family terminfo for tmux, we will try screen-16color first, change TERM, try above script, you should see only 8 distinct bg colors(n and n+8 is the same): enter image description here

Definition of screen-16color is:

screen-16color|GNU Screen with 16 colors,
        use=ibm+16color, use=screen4,

ibm+16color use 90-97 and 100-107 ansi SGR code to render bright fg and bg color:

        setab=\E[%?%p1%{8}%<%t%p1%{40}%+%e%p1%{92}%+%;%dm,
        setaf=\E[%?%p1%{8}%<%t%p1%{30}%+%e%p1%{82}%+%;%dm,

AFAIK, linux vc doesn't support 100-107 SGR code, echo -e '\e[101mxxxx' will only give you normal red bg. To fix it, my first thought is to use setab of linux-16color directly, but that failed, so I embed the blink attribute into the setab instead:

        setab=\E[%?%p1%{8}%<%t25;%p1%{40}%+%e5;%p1%{92}%+%;%dm,
   turn off if < 8 -----------^              ^--------------turn on otherwise

I have used it for a few days, it works fine.

Find or make a suitable colorscheme

It's hard to find a colorscheme for linux-16color, lots of colorschemes have this kind of guard:

if !(has('termguicolors') && &termguicolors) && !has('gui_running') && &t_Co != 256
  finish
endif

There are still some colorscheme in github use only 16 ansicolors, but most of of them are degraded version of it's 256color brother, I don't like it.

I want a color scheme that look exactly like it's 256color brother (without bold, underline, italic, ...). The best I can find is solarized.

Some extra work need to be done to make solarized look exactly the same between 16color and 256color.:

" ---------------------------------------------------------------------
" ABOUT REVERSE
" ---------------------------------------------------------------------
" linux-16color doesn't have full support for reverse, these commands
" are equal:
"
" tput setaf 1 ; tput setab 10 ; tput rev ; echo 123
" tput setaf 2 ; tput setab 9 ; echo 123
"
" 2 = 10%2, 9 = 1 + 8
"
" bold(1) and blink(5) is used to make fg or bg color brighter(+8), rev works on
" color%8 , bold or blink stays unchanged.
"
" You can only use rev if both fg and bg is greater or less equal to 7. The same
" rule applies to standout, it's better to stay away from them.
...

vim-colors-solarized has stopped updating for years, so I use my own fork instead.

| improve this answer | |
  • 2
    I want a color scheme that look exactly like it's 256color brother (without bold, underline, italic, ...) Sort of self-promotion, but here is my own colorscheme with 8/16/256/truecolor light/dark support. Though I can't claim it has "an exact same" look in all cases. – Matt May 13 at 13:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.