Most terminal emulators ship with a garbage default colour scheme. So change that.
Personally I'm a fan of Solarized (specifically dark, but I like their light theme too). However even if you don't like Solarized, there are plenty of other themes that are readable with any colour against the default backgrounds.
Step 2:
Avoid any CLI tool that uses escape sequences for 8bit or 24bit colours by default. This might be an unpopular opinion, but I actually consider that as user hostile. Reason being: I've already chosen a the best terminal colour scheme for my readability requirements (remember, this will differ for different people). Having a developer override that because they fancy themselves as a pseudo-designer is not helpful. By all means, they can have an option to enable themes in their tool if they wish, but that should be opt-in, not the default.
As someone who spends most of their life in the terminal, following those two rules is enough to provide a consistent and easy terminal reading environment with almost-zero configuration overhead.
I think the real problem is that we indulge developers using 8bit and 24bit colour escape codes.
> By all means, they can have an option to enable themes in their tool if they wish, but that should be opt-in, not the default.
This touches on the problem of good defaults. If the user has to configure it then the user must know that it is configurable and then do it. This is a serious hurdle and only a tiny fraction of users will do it.
Over the years I've come to the conclusion that you must throw your new features into the face and shove good defaults down the throats of users, otherwise these feature are hardly used.
8bit and 24bit colors are already opt-in and you can configure it. Your TERM and COLORTERM environmental variables determine if a (well behaved) terminal program will use those colors.
> Over the years I've come to the conclusion that you must throw your new features into the face and shove good defaults down the throats of users, otherwise these feature are hardly used.
Agreed to an extent. I wouldn't call ignoring the systems colour preferences as "good defaults". But I do agree with your more general point.
> 8bit and 24bit colors are already opt-in and you can configure it. Your TERM and COLORTERM environmental variables determine if a (well behaved) terminal program will use those colors.
Unfortunately it's not that simple. Both the "256color" suffix to $TERM and $COLORTERM env vars report terminal compatibility -- not user preference.
Neither are standards either. It's a push to even call them a de facto standard because they're often not used by either terminal emulators nor application developer alike.
There is another env var that does report user preferences: $COLORFGBG, but that receives even less support than the former two vars.
There's also $NO_COLOR (or is $NOCOLOR?), which seems to be honored a little better. However the problem with this is it turns colour off completely. ie you cannot specify "use 4bit but not 8bit nor 24bit colour".
Like all things terminal detection wise, it's all a big fat steaming mess of inconsistencies. Which is why I think the best default is 3/4bit or no colour at all if $NO_COLOR / not a TTY. And have all the cool 24bit themes as an optional extra.
It's also the case that a lot of modern CLI tools will absolutely ignore your termcap and your $TERM env var and barf out whatever extension to ANSI is used by the currently most popular terminal emulators.
Unless it's a TUI app that I'm going to spend a lot of time in (e.g., Emacs), I do not want it theming itself. I want it to look at my termcap to see if it has ANSI color support, and if it does, then emit ANSI color codes. I use base16-shell to set my terminal colors and I want CLI and TUI apps to respect them.
> Unfortunately it's not that simple. Both the "256color" suffix to $TERM and $COLORTERM env vars report terminal compatibility -- not user preference.
Terminal compatibility that is expected to be used. If you only want the 16 base colors then this is the way to go. This is the most reliable and best supported way to get that in the terminal.
If you want some tools to still output 256 colors, you can change the TERM variable on the fly: "TERM=$TERM-256color infocmp -L".
You also should unset COLORTERM. It's for specifying that this terminal supports 24bit colors.
You’re basically just demonstrating my point that this gets very complicated very quickly and thus the polite way to handle this is tool authors to default to 4bit.
A lot of the complexity comes not only from technology that has been dragged along for almost 50 years now but also that the maintainer of ncurses/terminfo has been stubbornly refusing to add new capabilities to the terminfo library.
Using terminfo will give you at least a standard approach to what defaults to use. If you don't want to configure your terminal then you are asking others to do something you are not willing to do.
If we are supposed to go with the lowest common denominator without terminfo capabilities, we would even lose 4bit colors. Then only the basic 8 colors are safe because there a lot of terminals now that don't support the workaround of "bold plus basic color gives bright color" anymore.
That is a massive over simplification and you're pointing the fingers at the wrong culprits.
I've talked a lot recently about the problems with env vars for terminal detection and the problems with developers not understanding how to correctly query terminal capabilities. Heck, some don't even correctly support non-TTY outputs (ie pipes). And then there's the issue that terminfo is a C library so a lot of languages with average to no-C FFI support cannot use it without fork()ing -- which is slow. Plus terminfo is POSIX only which eliminates platforms like Windows -- which is increasingly a target now that Windows Terminal supports ANSI escape sequences.
It's a mess and blaming that on history and terminfo really misunderstands that the real problem is modern tools not respecting or having compatibility with that history, rather than the history breaking things.
> If we are supposed to go with the lowest common denominator without terminfo capabilities, we would even lose 4bit colors. Then only the basic 8 colors are safe because there a lot of terminals now that don't support the workaround of "bold plus basic color gives bright color" anymore.
You're missing the point. It's not about supporting the lowest common denominator -- though I'd love you to give some example of terminal emulators in common use that don't support 4-bit colours ;)
It's about supporting user defaults. Themes based on 8-bit and 24-bit colour pallets are defined by the developer. Whereas themes based on 3 and 4-bit colour pallets are defined by the terminal user.
Hence why I say applications should default to the terminal defaults (defined by the user)
There's times when applications should support 24-bit regardless of the user preferences. Such as image rendering in the terminal. But those are exceptions rather than the norm. And precisely why things like `256-color` and $COlORTERM need to be defining terminal support not user preference.
> And then there's the issue that terminfo is a C library so a lot of languages with average to no-C FFI support cannot use it without fork()ing -- which is slow. Plus terminfo is POSIX only which eliminates platforms like Windows -- which is increasingly a target now that Windows Terminal supports ANSI escape sequences.
export TERM=ms-terminal
Windows is POSIX. Windows NT always had a POSIX layer.
Terminfo is mostly a file based database collection. You don't need to link to the C library, you just must be able to read the terminal infos.
> You're missing the point. It's not about supporting the lowest common denominator -- though I'd love you to give some example of terminal emulators in common use that don't support 4-bit colours ;)
The question is not about support but about how to get them to be display. Which escape sequences produces colors 8-15? The answer is different from terminal to terminal and that's the problem.
1. That then breaks any applications that look for either `xterm` or `256-colors` in the TERM string. Unfortunately these days $TERM behaves more like a User-Agent string in HTTP-land so most terminal emulators are forced to pretend to be `xterm` even when they're not.
2. `export` is a Bourne Shell-ism. Powershell's syntax looks a little more like:
> Terminfo is mostly a file based database collection. You don't need to link to the C library, you just must be able to read the terminal infos.
mostly is doing a lot of heavy lifting there.
Also reading those databases without C is non-trivial as well. For example try manually parsing the output of /usr/share/terminfo/74/tmux-256color on macOS.
It's also worth noting here that there's two different database formats: terminfo and termcap. And different locations each platform (and users!) might configure those databases to reside.
Also tools like `tput` do more than just look up $TERM against terminfo. There are actually a few different places where terminal capabilities are hidden. Including ANSI escape codes, which was originally used in the hardware terminal days before $TERM existed and are still expected to be supported by modern terminal emulators.
Let's not forget that you also need to check if you're reading from, or writing to, a TTY. It might actually be a pipe, or even just a regular file. And while there is a standard C API for checking if a file descriptor is a TTY, `isatty()`, that itself is just a hack because there's no ABI in TTYs to return true/false if they are a TTY. So instead isatty() has to send ioctl calls to alter the state of the TTY, but a state that's only supported by TTYs (ie incompatible with pipes and regular files). It's a hack that's worked well for decades, but it's yet another class of edge cases that people take for granted.
> The question is not about support but about how to get them to be display. Which escape sequences produces colors 8-15? The answer is different from terminal to terminal and that's the problem.
What differs is the shade of colours that are produced with those escape codes. And that's exactly why I advocate that developers should stick to 3/4-bit code.
The point I'm making is that those colours are defined by the terminal and configurable by the user. Which means individuals can set a colour profile that is readable for them. This is why CLI and TUI developers should default to, and respect, those preferences.
Take a read through my comment history. I'm an author of a multitude of advanced CLI and TUI applications as well as terminal emulator and thus I've discussed these topics at great lengths with other people.
Solarized Dark, specifically, is not well-suited for terminal use, because the author has assigned "bright black" to nearly the same color as the background. Many applications expect that 'bright black' text will be visible against the background. See here for many examples: https://github.com/altercation/solarized/issues/220
Nearly all other colorschemes represent 'bright black' as a gray color, which is readable against the black background.
> themes that are readable with any colour against the default backgrounds.
Yes, but then there are applications that set both the text and background colour. For example pamix sets the background to black, or tmux's statusline, or ngrok. And you end up in a rabbit hole trying to deal with that.
I don't know what pamix is but my rule of thumb is to use only apps that supports themes that are common in most terminals, text/code editor like solarized, gruvbox...
>> Avoid any CLI tool that uses escape sequences for 8bit or 24bit colours by default.
I was going to point out that the author never takes a step back and asks "What would be the best way to handle this?" The problem there is we have to define what "best" is. IMHO that involves a number of principles. My preferences are:
1) Any user customization should be in one place.
2) The impact on programs should be minimal (in LoC for example).
Both of those suggest the solution belongs in the terminal.
IMHO it starts with terminal programs having sane default colors. What that means is fuzzy, but so is this whole discussion. IMHO colors should follow the "standard" so that blue is still recognizably blue. But consideration should be given to the common forms of color blindness - for example I have a hard time reading pure red on black (adding a bit of anything helps this, don't just use ff0000).
Once terminals get fixed to have sane defaults, CLI programs should use those 16 standard colors. Any attempt to use 24bit here is either saying "I give up on getting those terminal folks to offer sanity" or it's saying something like "I know best", but either way users end up with N programs they have to configure. Lets not define themes in cli apps OK? Remember, this is my answer to "what would be the best way to handle this?"
I have similar thoughts when it comes to web sites and fonts. Present content in HTML so users can configure how they want to see it. Similar for page formatting - it's not a magazine layout, let it flow.
Also stuff in desktop software. IMHO Wayland compositors should remember window placement. It was stupid for every X program to store and restore its window position. Wayland says knowing about the environment is a security issue (and I agree) but then it becomes the DEs job to handle this memory. It also unburdens ALL the apps from having code for this.
There are other areas where that question comes up "Where in the software stack should this thing be handled?" Whatever your opinion, I believe you should start by answering the questions around that word "should". What are the goals in selecting where a thing gets handled? My answers always lean toward simplicity and maintainability. What other principles might I adopt to answer these questions?
Avoid any CLI tool that uses escape sequences for 8bit or 24bit colours by default.
How difficult is this in practice?
(Julia's article mentions this idea too without going deeper into the struggles)
A related topic is: Do terminal color schemes only concern themselves with the 16 base colors or do they also meddle with the RGB and greyscale parts. I mean you could also adapt the 8bit and 16bit colors to your readability requirements.
There is no 16bit. You cannot alter the 24bit (at least not on your average terminal emulator).
Same is true for 8bit. Most terminal emulators tend not to support altering those colours either.
In practice, the only application I use that I've had to configure the colours for was tmux. But I tend to forget about tmux because its one of those applications that needs a lot of a configuration from the outset anyway (in my opinion at least).
There might be other "must have" tools that set the background colours too. I've either not needed them personally, or have completely forgotten about them
Step2: do agree with the fact someone making a CLI tool should respect user preferences. it's also much easier just not to use the sequences in the tool so I don't get why people would do that in the first place :S.
Step 1: I think here maybe the default setting should be solarized-dark/light on terminals. It's honestly a good and sane default. It's purpose built to be less hostile on the eyes in my opinion, which should likely be what's aimed for in a default setting... the themes and colors are there for people who like to stare at their terminal all day (if you only use it once or twice then you don't care about what color it has) so it should be eye-friendly defaults. if people want to muck about changing it to their own custom theme they won't be bothered about defaults anyway since they will immediately customize it.
I personally hate the fact I even need to swap a theme, or download and reformat some Xresources file tediously (while looking at godawful colors in the process!). I just want my eyes not to burn.. don't care what colors yield that result.
I would disagree that solarized is a good default, the colour it uses for blue (which is used by `ls' to show directories) is so low contrast it wears my eyes out.
Seconded. By all means, people should use what they personally like, but solarized is really not designed to be a terminal mapping. Half the brights get mapped to totally different hues and the other half get mapped to indistinguishable shades of gray. Yes, the standard terminal color values are hideous, but we can do better than solarized.
To reiterate, I'm not here to say anyone is wrong for using solarized, only that as a terminal default it would eliminate the ability of terminal applications to assume that bright green, bright blue, bright cyan, and bright yellow are anything other than shades of gray. If that's fine for your use case, then no harm. And plenty of people tweak solarized to make these colors usable and distinguishable, but of course this obviates the whole light mode/dark mode party trick that is solarized's raison d'etre.
There are lots of websites out there where people have shared their terminal color schemes, I would recommend seeking one out and looking for a screenshot of one that catches your eye.
Don’t worry, I wasn’t taking your comment as personal critique. :)
And to be fair to Solarized, it was really novel when it came out. But we’ve had years to improve upon it since.
So I’m genuinely interested to hear some recommendations. Ideally themes that are “standardised” (for lack of a better phrase) so that I’m likely to find a VSCode theme as well as iTerm2 etc.
I know I could just look online myself but customisation can quickly end up becoming an “addiction” (again, for want a better phrase) where you spend more time “configuring” than “doing”. A procrastination trap I’ve fallen into many times before. The appeal of Solarized is its better than most defaults and it’s easy to find so that stops me from spending too much time playing. And the appeal of having someone else tell me to use something else is that I also don’t fall into that proverbial rabbit hole.
Totally fair. In truth, modern terminal emulators have come a long way since the days of opening up CMD.exe or Putty and cringing at their peaked RGB sliders. Nowadays when I install a new terminal it tends to come with a decent color scheme out of the box. But if you insist, I could extract the color scheme that I made for myself a decade ago, though I decline to give it its own name or website. :P
For some reason that blue is a problem in a lot of color schemes. It's a good test for me though. If I can't read the output of ls, I dump the color scheme.
I completely agree. And for what it's worth, I set Solarized dark as the default theme on the terminal emulator I've written. Though it's not quite ready to be used as anyone's primary TERM just yet.
Step 1:
Most terminal emulators ship with a garbage default colour scheme. So change that.
Personally I'm a fan of Solarized (specifically dark, but I like their light theme too). However even if you don't like Solarized, there are plenty of other themes that are readable with any colour against the default backgrounds.
Step 2:
Avoid any CLI tool that uses escape sequences for 8bit or 24bit colours by default. This might be an unpopular opinion, but I actually consider that as user hostile. Reason being: I've already chosen a the best terminal colour scheme for my readability requirements (remember, this will differ for different people). Having a developer override that because they fancy themselves as a pseudo-designer is not helpful. By all means, they can have an option to enable themes in their tool if they wish, but that should be opt-in, not the default.
As someone who spends most of their life in the terminal, following those two rules is enough to provide a consistent and easy terminal reading environment with almost-zero configuration overhead.
I think the real problem is that we indulge developers using 8bit and 24bit colour escape codes.