Originally published at jeffkreeftmeijer.com/vim-16-color on Nov 29, 2018.
Instead of configuring colors separately for both Vim and the rest of the terminal, limiting Vim’s color scheme to 16 ANSI colors allows setting all color preferences in the terminal’s theme. Doing so results in consistent colors among terminal utilities and a color theme that’s quick to swap out for another one.
I’ve been using a customized version of Vim’s default color scheme for the last couple of years. Unlike Vim’s default, it exclusively uses 16 ANSI colors by setting each color to a value between 0 and 15. The terminal emulator’s theme sets the specific color values instead of hard coding them into the Vim color scheme and relying on true color support.
By using the terminal theme exclusively, all utilities use the same color values. For example, I don’t configure tmux’s colors, as the green color the terminal theme uses is already a shade I like.
Terminal colors and ANSI escape sequences
Terminal emulators use ANSI escape sequences to–amongst other things like controlling the cursor’s position–read the desired text and background color when printing output.
$ echo -e "\033[31mred\033[m" # Prints “red” in red.
While most terminal emulators, including Apple’s Terminal.app, support true color now, most utilities use one of the main sixteen colors (black, red, green, yellow, blue, magenta, cyan, white, and a high intensity or bright version of each).
For example, git shows diffs with additions in green and deletions in red, and most testing frameworks print green dots for passed tests and red F’s for failures.
The terminal emulators we use today assign each of these relative named colors with a 24-bit color value. This separates the utility’s intent (“print this error in red”) from the terminal emulator’s styling (“#C31633 is a nice shade of red”). These colors are configurable in your terminal emulator’s settings, along with the used font and other options.
8-bit and 24-bit ANSI color
Beyond the first sixteen named colors numbered 1 through 16, we arrive in absolute color territory. The color codes from 16 to 255 are used to print 8-bit colors, from which 232 to 255 are grayscale values from black to white.# prints “hotpink” in #205 (HEX: #f69, RGB: 255, 102, 153) $ echo -e "\033[38;5;205mhotpink\033[m"
Then, there’s 24-bit color, also named true color, which has 16.777.216 different color values.# prints “giant goldfish” in 24-bit orange (HEX: #F38630, RGB: 243, 134, 48) $ echo -e "\033[38;2;243;134;48mgiant goldfish\033[0m"
Being absolute color values, they’re not configurable in the terminal emulator’s settings.
By changing the terminal theme, using one like appsignal.terminal or any of the hundreds of other available themes, the terminal emulator can display the relative colors in any true color value you like. Using
#C31633 for red will color deletions in git’s diff output in that exact color, for example.
Tip: In Terminal.app, use ⌘+I to open the Inspector to change the current window’s theme without opening a new terminal window.
Setting the precise color values in the terminal emulator’s profile or using a terminal theme allows the utility to mark some output as “yellow”, without having to supply an exact shade. The shade is either up to the terminal or the user’s preferences.
Vim color schemes
Unlike other utilities, Vim uses 8-bit or 24-bit color schemes that use absolute colors for each highlight group in an attempt to make the colors look the same for every configuration. These schemes don‘t use any of the named colors, so the terminal’s color preferences don‘t affect them.
When using Vim inside a terminal emulator, having consistent colors between Vim and the rest of the terminal requires duplicate color settings. First, the Vim color scheme uses an absolute color value for each highlight group. Then, the terminal emulator needs a theme that uses the same colors as the Vim scheme to customize the relative colors.
If the Vim color scheme uses
#C31633 as a red color, the terminal theme needs to use that color as the “Red” ANSI color to use that same color in git’s diffs outside of Vim, for example.
Dim: a 16-color Vim color scheme
To achieve consistent colors across all terminal utilities without requiring duplicate color settings, 4-bit Vim color schemes like Noctu and Dim exclusively use the first sixteen relative ANSI colors. This makes them compatible with 16-color terminals, but also results in consistent colors between terminal utilities.
Dim is based on Vim’s default color scheme. Although Vim’s default mostly uses relative colors, it uses 8-bit absolute colors for some of its highlight groups. By default, it colors line numbers and statements brown, diffs lightblue and darkblue, completion menus pink, and comments ANSI blue. Because that’s distracting, Dim uses gray colors for each of these.
By keeping the intent separate from the styling and the specific color values in the terminal theme, every utility in the terminal uses consistent colors. This makes changing themes—like switching between dark and light versions of a theme—a matter of pressing ⌘+I and selecting another one, without having to find a matching color scheme for Vim.