Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Build your own Command Line with ANSI escape codes (2016) (lihaoyi.com)
62 points by lihaoyi on Feb 5, 2021 | hide | past | favorite | 13 comments


I didn’t see it mentioned in the article so I’ll say it here:

Please please please don’t using anything more than the 8 (plus 8 “bright”) colours when doing text interfaces in the terminal. The reason being that the 8 colour palettes are defined by the terminal emulator where as the 256 (and other ANSI palettes not discussed in that article) are defined by the programmer.

Why does this matter? Simply because not everyone uses the same terminal colour scheme. If a programmer chooses a colour from the 8 colour palette then your terminal will (hopefully) render the text in a colour that’s distinct enough from the other text and background colours to be readable. However if you, as a programmer, choose the colour yourself there will be a great many terminal configurations where the colour you’ve chosen isn’t readable.

For example not everyone has a black background. macOS Terminal defaults to white whereas I tend to use Solarised Dark colour schemes that are more of a plum colour.


When I need my programs to use specific colors, I tend to use the RGB variety - which works regardless of preferences: "\e[0;48;2;R;G;Bm"

While my "color1" might be different than yours, terminals don't usually fiddle with RGB.


That's the exact opposite of my plee. If you're drawing graphics to the screen or something else that's dependant on being colour accurate, then what you say is fine. But the overwhelming majority of CLI tools aren't. My point was that for regular command line / TUIs, the programmer should not chose specific colours and instead respect the terminal preferences of the users. Terminal preferences differ wildly and you may quickly find people cannot use your terminal app because it is unreadable on their terminal.

You'd be surprised just how wildly different some peoples preferences are. For example I know of people who choose different colour schemes for a DB server (red background) vs a web server (green background). Or a dev server vs prod server. Myself, I choose a non-black background due to dyslexia (coloured background are easier for me to read than black backgrounds). Others might have chosen a non-default background colour to reduce eye strain.

CLI don't need to be artistically brilliant and for a great many people it's an essential productivity tool. So please don't impose your preferences onto others. If developers want to add their own design flair to UIs then they can expose a HTTP endpoint as well, or even an optional "--true-colour" flag or similar environmental variable. But if they want to release a UNIX-like CLI tool then please stick to 8+bright colours by default.

## TTYs

Also, while one this topic, if anyone does add colours by default (even if it is just the 8+bright) then also please check that the output terminal is a TTY. If it isn't then please don't output any ANSI escape sequences at all. This is so that your application works being piped. eg

    # foo's STDOUT is a TTY
    $ foo    

    # foo's STDOUT is not a TTY
    $ foo | grep bar
In the later example, if you're not detecting whether STDOUT is a TTY and subsequently not including ANSI escape sequences then `grep` (et al) will receive them and that could cause weird behaviour in the subsequent applications (I do appreciate there are occasions when you do specifically want to pipe ANSI escape sequences. But those occasions are less common than the UNIX norm of auto-disabling escape sequences when STDOUT != TTY).


Please don't do this, please let us look at your program in whatever colours we want to.


Even the 8 colors can be suboptimal depending on the scheme.

E.g. Vim and Emacs try to determine whether your terminal background is light or dark, and use a somewhat different scheme depending on that.

However, determining whether it is light or dark is not straight forward. I did some research on how other tools (Vim, Emacs, many others) do it: https://stackoverflow.com/a/54652367/133374


Please don't.

Or rather, please think about whether adding rich text to your command line application actually makes it more useful before you do this.

One great benefit of command line applications on Unix is that they can be composed in pipelines. There is a convention that everything is just text. Escape codes throw a wrench in this. And once you start changing your output based on whether you're writing to a tty or a pipe, you run the risk of surprising users with divergent behavior.

More selfishly, not everyone is using a conventional terminal. Your app might get called from a text editor or IDE which doesn't support escape codes. Or a simplified, pure-text interface like 9term.


Most better terminal programs detect if they are writing to a pipe and disable the ansi support.

Some CI tools seem to mess this up somehow, but “why not both” is an option.


To add to the "please don't" comments, if one still wants to, there are terminfo and termcap to interact with terminals properly, in a portable way.


You can always go completely crazy with stuff like this: https://gist.github.com/dom111/8967a1ab9737fd253977a324c58d9...


Obligatory reference to Blessings [1], a very pythonic approach to terminal manipulation, inspired by curses and the complete opposite of it.

See the 'Before and After' example in the readme for enlightenment.

[1] https://github.com/erikrose/blessings


Blessings is no longer maintained, but the blessed fork adds window OS, keyboard input, and 24-bit color support and still makes regular improvements.

I co-maintain blessings and made the blessed fork because blessings development stalled by the primary maintainer 5 or more years ago

Also please mention rich another great library!

Best wishes all and make great CLI apps!! Happy Friday :)

https://blessed.readthedocs.io/en/latest/intro.html https://pypi.org/project/rich/


This reminds me of when adding color to your MUD was considered cutting edge. It actually was pretty cool at the time. Supporting non ANSI clients was fun too. If I recall we just punted and made color a setting rather than trying to somehow determine if a client would render the escapes properly.


Is there any reason why one would want CSI <huge-number> D instead of plain old CR?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: