How colorschemes work in terminal

As a daily user of the terminal, I find coloring my terminal very useful and aesthetically pleasing compared to the usual black and white default theme. Personally, I’ve been using the default dark base16 theme. In particular, I’m using scripts from the base16-shell repo because I can simply add the setup to my rc file and make it work for whatever machine I’m using. I never really bothered to understand how the coloring works, it’s been pure magic to me. A few days ago, however, I’m having some coloring issue with MobaXterm and I decided to actually take a look at how the script colors my terminal. There are a few things to understand to build the whole picture.

Type of terminal

We have to understand that “terminal” is just a term to describe a device that entering data into and displaying data from a computer. There were many implementations in the past and they work differently and have different capabilities. For example, we have vt100, vt220, xterm, and xterm-256color. To write programs/libraries (e.g. ncurses) that works on many different terminals, there are libraries like termcap and terminfo which provides a device independent software API. Besides these libraries, there is another way to communicate with the terminal, which is called “ANSI escape sequence”.

ANSI escape sequence

According to Wikipedia,

ANSI escape sequences are a standard for in-band signaling to control the cursor location, color, and other options on video text terminals and terminal emulators.

Basically, it works by embedding non-printing byte sequences to the text that you print on the terminal. Therefore, you can send commands to the terminal by simplying doing echo or printf in your shell. You may have already seen it if you wrote scripts that print colored text. These escape sequences usually start with Esc which can be access by \e, \033, and \x1B in the shell. For example, you can do the following to print red text (try it yourself!).

$ printf "\033[31mI'm RED\033\n[0m"

Here is a full list of escape sequences that you can send. For this post, let’s focus on the ones that control the colors.

Changing the color

In the link above, under “Operating System Controls”, we find what we are looking for. There is a 4;c;name option which says change color #c to name. The full syntax is \033]4;<color>;<name> (you can read up on the syntax from the above link). The name here follows the XParseColor syntax, e.g. rgb:18/18/18. In the terminal we usually have 16 or 256 colors and this sequence allows us to change the mapping from color IDs to actual RGB values. Suppose we set color 01 (which represent red) to a blue-ish rgb:7c/af/c2, your terminal will actually print blue text when you run the above printf command! Looking at the source code of base16-shell, that’s exactly what the scripts are doing. They run printf to change color 00 to 21 to form a 22 color palette based on the exact theme you chose. Cool, now I understands how my terminal is colored!

Conclusion

In this post, I talked about how a terminal is colored with what’s called ANSI escape sequences. For me, it was quite fun researching about all these information. I didn’t expect it to be this simple, I thought it was some complicated magic to make it work. I hope you find my post a fun to read and helpful for understanding a bit of the history in computing! Cheers!

References

 
comments powered by Disqus