I just wanted Emacs to look nice – Using 24-bit color in terminals
chadaustin.me
chadaustin.me
EDIT: for iTerm+zsh, I collected some functions for setting tab colors: https://gist.github.com/aclarknexient/84ebe33c1879f921685304...
EDIT2: Contrast terminfo with the old-school method of connecting to HTTP or SMTP with telnet. Yeah, it's simple text but that text is being displayed by a complex application that supports all sorts of wild stuff!
A basic terminal can be fairly small - mine is ~1800 lines of Ruby at the moment, which I consider disappointingly large. For comparison st is ~8k lines, I think, and xterm is ~88k. But you can do a working terminal in far less than my 1800, even in more verbose languages, so it's a nice space to play in where you can get something that works in very little (set TERM to a dumber terminal than rxvt, dump any escape sequences your terminal doesn't yet understand to a log, and run the apps you need, then iterate...), and build up in whichever direction you want to something quite usable very quickly. Then you can spend a lifetime polishing quirky little details nobody with you will ever care about... ;)
It's fine when it's just you. Unfortunately, there are some widely used terminals that default to claiming to be xterm, but are not xterm compatible.
But conversely, if distributed like that, I'd also feel that this implicitly means any failure to act like xterm is a bug they've implicitly suggested it is reasonable to report or complain about (and if the version number doesn't imply it's an early stage release, and it still doesn't work well with its defaults, I'd get cranky)
The nasty part is that RXVT violates ISO 2022 structure in weird ways. It's not alone in that, but most of the other-program violations are much more easily fixed.
The huge amount of work comes from nailing all the quirks you will have to deal with if you let a bunch of other users loose on it, with their expectations of running all kinds of applications I've never tested that does weird stuff.
If you're building a program that takes over the terminal screen, you probably should use one of the established libraries that abstracts over terminfo and over old non-ANSI Windows consoles. But if you're doing light terminal handling in an application that doesn't take over the screen, such as emitting colors or doing simple cursor control, forget about terminfo and just handle two or three cases: ANSI, optionally old pre-ANSI Windows consoles, and files/terminals with no support for anything. Rounding ancient terminals or terminal emulators to "no support" and giving them the same thing you'd give a redirection to a file seems entirely reasonable for a new program.
If there was any remotely standard way of signaling the preferred default, and a remotely standard command line option to toggle that default, it'd make things a lot nicer, because I totally understand where you're coming from; I get equally annoyed just in the opposite scenarios, so the situation is a nuisance for both of us.
Any tool whose output is ever parsed, including "parsing" as simple as "tool | grep xyz", shouldn't emit terminal escapes to a pipe by default. If `xyz` has an embedded color sequence in it, that grep will fail. Or worse, produce unexpected results. (The standard color sequences end in `m`; a grep for 'msomething' could match 'something' preceded by a color sequence.)
I think my ideal expected behaviour (which would still not be perfect) would be something like:
* Tools defaulting to unescaped output in scripts, but with a standard short option and/or ENV var to trigger colour output.
* Tools default to colour/escaped output when run in an interactive shell even if in a pipe.
* Tools being escape sequence aware, maybe with switches to turn that behaviour off if you genuinely e.g. do want to grep for sequences that may include escapes and you want them considered.
But I'm not sure there is a good solution to this other than decoupling UI and API and having different defaults for tools that are expected to be "user facing" vs treated as API. I have an "ls" replacement on my system, for example, which changes formatting and adds more colour to my ls output, and it's obviously not named ls because the amount of stuff that breaks if "ls" isn't reliably the same as always is significant. It's still not great to have to separate this given that part of the ease of composing pipelines etc. is familiarity with the output, but maybe if coupling that with reasonably standard switches to turn on/off machine-friendly output.
I think we might be able to do better in something that isn't a traditional shell, and that uses ptys instead of pipes, together with builtins that replace standard UNIX tools with escape-aware tools.
I'm halfway tempted to replace my shell with one that is more integrated with my terminal and do something like the last bit you suggested, given it can be very trivial[1] if you explicitly make the choice that for any scripting you'll use a "regular" shell.
[1] there is, in fact, a tiny single-file Ruby shell that I might be tempted to extend.
Also, as a pet peeve: always read your input from stdin, and if stdin isn't readable, do not assume that if stdout/stderr is a tty you're allowed to use that for input. (This assumption is broken in batch/CI/etc systems where stdout/stderr may be a tty so that a program emits color/etc, while making stdin /dev/null because there's no user interaction possible.)
I got a big dose of Telecoms standards early in my career, including some X.25 and networking stuff. After the clarity and simplicity of SUPDUP, my reaction to Big Standards could best be described as "allergic".
[Marshall Rose and Michael Padlipski are good reading on this subject. To this day I use the word "octet" as an epithet]
use standards
not too many
mostly plain ones
In my ~/.Xdefaults for rxvt-unicode:
! yellow
Rxvt*color3:rgb:F5/79/00
! magenta
Rxvt*color5:rgb:AD/7F/A8
! cyan
Rxvt*color6:rgb:88/8A/85
! white
Rxvt*color7:rgb:BA/BD/B6
! ...
And in my custom theme .el: (if (display-graphic-p)
(setq color-yellow "#f57900"
color-bright-yellow "#fce94f"
color-red "#ff6464"
color-bright-red "#ef2929"
...
color-cyan "#888a85")
(setq color-black "black"
color-white "white"
...
color-bright-magenta "brightmagenta"))
I then use these to set various faces `(minibuffer-prompt
((t (:foreground ,color-blue))))
`(highlight
((t (:background ,color-bright-yellow))))
`(region
((t (:background ,color-bright-blue))))
`(shadow
((t (:foreground ,color-bright-cyan))))
`(secondary-selection
((t (:background ,color-bright-magenta))))
etc.As a bonus, colored `ls` output etc. is nicer too. The raw 16 color palette is too saturated and often has bad contrast.
This right here. Emacs actually supports graphical output (X11, Cocoa, Win32). Additional bonuses include: Esc is actually Esc; you can bind Ctrl+Shift or Cmd; you can use more than one font at a time; you can display a picture; change the shape of the cursor... It's like a time machine that takes you 20 years forward - into 1989.
Clipboard integration and mouse cursor support are the two reasons I generally break out emacs-ui (my shell script for it), otherwise it's emacs-nox, generally.
The red wire was a lot of red, and only red, or nothing and when the intensity wire is added, 100 percent red happened. Wash, rinse, repeat
This is partly due to the maintainer of ncurses being somewhat ... conservative and the new fangled terminal devs wanna move things fast.
If unsetting COLORTERM fixes the display problem then it is a program issuing 24bit colors but the terminal (in your case screen) not understanding the escape sequences.
The other thing is that I like to close my laptop, reopen it the next day, and have access to the same remote buffers. (Maybe this is possible with TRAMP.)
Ultimately I just use emacs in tmux over ssh, with CLICOLOR defined appropriately, and this gets me 95% of what I want.
I wish I could get rid of those last <50ms of keypress latency. And variable-sized fonts for eglot inlay type annotations. They are quite distracting when they're the same size as the code.
As of Emacs 28. You still need the terminfo database in older versions of Emacs.
The issue I had with COLORTERM is that not every program respects it. In fact, I've had this in my .bashrc for a while:
case $TERM in
linux | screen*)
unset COLORTERM
;;
*)
export COLORTERM=truecolor
;;
esac
(Screen does support 24-bit color now, so that case probably came from Ubuntu 18.)A fork of terminfo may be needed if the description of modern terminal capabilities can't be added -- or if old and deprecated attributes repurposed for that job (like in your padding example): if you're automating the correction/creation of terminfos in ~/, IMHO, it may be better to piggyback on tic as much as possible.
Anyway, to backport modern terminal descriptions to legacy programs, creating correct binary terminfos in ~/.terminfo seems the best practice. You can also invent new TERM. When I wanted to have italics etc about everywhere, personally that's just what I did for sixel-tmux: https://github.com/csdvrx/sixel-tmux/?tab=readme-ov-file#ste... : just declare a new $TERM you know to be right, and use that in the apps that let you use a little logic in their configuration file
I do that in my .vimrc:
" If Vim doesn't know the escape codes to switch to italic
let &t_ZH="\e[3m"
let &t_ZR="\e[23m"
" Italics pseudo-auto toggle: force italics if we recognize it's supported from TERM
if match($TERM, "xterm-256color-italic")==0
highlight Comment cterm=italic
endif
BTW you should package your emacs config file with the emacs APE from https://cosmo.zip/pub/cosmos/bin/emacs to do a cuteemacs, to carry your config files and everything in a portable binary: https://github.com/csdvrx/CuteVimAnother idea: have you considered that the "program that would be run by .bashrc" to generate the "unambiguous 24-bit color capabilities" could set environment variables to communicate them? Like, if you can't stuff them in terminfo, stuff them in environment variables! Env var work well on Windows, and the configuration files of terminal programs could just use these when available to override.
It's be like adding friends to your proposed TERMVERSION: TERMSETF24 etc where you've have a finer control than COLORTERM
Visually, graphical Emacs looks so much like Emacs running in a terminal that if the tool bar has been turned off (and most users decide to turn it off) most non-users of Emacs will assume (incorrectly) that a graphical Emacs window they see running on a colleague's computer is a terminal window (unless perhaps the window is currently displaying an image). (Graphical Emacs is an image viewer among other things.)
In a survey of Emacs users, 80% said that they use one of the graphical front ends.
ControlMaster auto
ControlPersist yes
ControlPath ~/.ssh/control/%C
You should also use key–based authentication so that TRAMP never has to ask for a password, but this is less important once you are using persistent connections. Add something like this to your ssh config: Host orod-na-thon
Hostname 192.168.2.133
User db48x
IdentityFile ~/.ssh/id_ed25519_your_private_key
Now go to Emacs and open up /ssh:orod-na-thon:~/.ssh/authorized_keys. This is the TRAMP path for your authorized_keys file on the machine named orod-na-thon. It will ask you for your password. Paste in your public key (which you can get by opening up the .pub file that goes alongside the private key in ~/ssh), and save it. Now future connections to orod-na-thon will be able to authenticate automatically using this key pair, and there will be no password prompt when you open a file there.Anyone aware of a solution of how to start the local editor from the remote to open the remote file?
No, in Emacs you always open a file by typing `C-x C-f`. (Unless you rebound it to some other key, in which case make the obvious substitution.)
Any time you hit `C-x C-f` to open a file it defaults to opening files from the working directory of the current buffer. The working directory of the eshell buffer is on the remote server, so the default list of files that you see are all the ones you were already looking at with `ls`. You can start typing a filename and autocomplete will do the rest.
This is an even deeper and more convenient composition of the shell and the editor than having special commands for tasks like opening a remote file in the local editor.
https://www.masteringemacs.org/article/running-shells-in-ema...
`C-x C-f` calls the `find-file` function which can be called directly from eshell
All Emacs Lisp functions are Eshell commands. Say 'find-file <filename>' at Eshell and you're in.
Vim has had the ability to open files remotely over ssh, sftp, etc. for a long time using the built-in plugin netwr [1].
Neovim takes it to another level [2]:
Nvim's RPC functionality allows clients to programmatically control Nvim.
Nvim itself takes command-line arguments that cause it to become a client to
another Nvim running as a server. These arguments match those provided by
Vim's clientserver option.
[1]: https://vonheikemen.github.io/devlog/tools/using-netrw-vim-b... /remote:/the/path/<tab>
and autocomplete the file name.Additionally, you can just do dired:
/remote:/the/path <return>
and scroll to the remote file I want to edit and press enterTry some variant of this in your remote .bash_profile or what-not:
if [ "$PS1" ]; then
export PS1='\h:\w\$ '
if [[ "x${TERM}" = "xeterm" || "x${TERM}" = "xeterm-color" ]]; then
function set-eterm-dir {
echo -e "\033AnSiTu" $(whoami)
echo -e "\033AnSiTc" $(pwd)
echo -e "\033AnSiTh" $(hostname -f)
}
PROMPT_COMMAND=set-eterm-dir
fi
fi
Now, locally, invoke M-x ansi-term, then within the ansi-term ssh to the remote machine. Change dirs, hit C-x C-f to open a file in the current (remote) directory.See also the ansi-term hints on emacswiki
https://www.emacswiki.org/emacs/AnsiTermHints#h5o-5
or the comments in /usr/local/share/emacs/*/lisp/term.el
Edit: formatting
db48x has a great answer below.
for i in "$@"; do
ssh "${SSH_CONNECTION%% *}" emacsclient --no-wait "/ssh:$(hostname):$(realpath "$i")"
done
should work.For best results, use ssh-agent + agent forwarding to avoid password prompts.
(require 'mouse)
(xterm-mouse-mode t)
(mouse-wheel-mode t)
(setq mouse-wheel-scroll-amount '(1 ((shift) . 1))) ;; scroll one line at a time
(setq mouse-wheel-progressive-speed nil) ;; don't accelerate scrolling
(setq mouse-wheel-follow-mouse 't) ;; scroll window under mouse
(setq scroll-step 1) ;; scroll smoothly
Also, I should point out that I use `(setq auto-save-default nil)` - as God intended.People are going to be using Emacs with a monitor. It's more bloat to have to have a GUI application that emulates a terminal and then run Emacs inside that emulator instead of just having Emacs be the GUI itself.
The emacs GUI inside a terminal window - invoked w/ xterm-mouse-mode - is still rather minimal. I'm thinking more about emacs-gtk or Aquamacs. You could argue that the GUI gives you access to more system capabilities in a straightforward way - buttons/controls v keybindings - but this isn't a dealbreaker for me.
As long as I have a readily available reference for keybindings, that's good enough for me.
There’s just no way that the GUI adds bloat in any meaningful sense; it’s the same program either way.
Emacs keybindings are complicated enough that I'd rather keep the ability to click a button available at all times even if I don't use it regularly - see my prior comment re BBEdit.
Such is life that I have some physical issues with my hands that make a purely keyboard driven interface occasionally uncomfortable. The chorded keystrokes in Vim were not satisfying to me, so I went in an emacs direction ¯\_(ツ)_/¯
When I started building out my init.el, it became apparent that I needed an escape hatch from time to time - this is it.
I remember that logic making sense when I tried to run Emacs on an 8MB 486... but that was about the last time it did.
While I've been using X11 off and on since the 90s, I still do not understand how to deal with fonts beyond helplessly googling for a constructive command I eventually stumble on something that works and then I have to leave it alone.
The display performance of most terminal programs is still noticeably faster than the X11 setup I end up with in a corporate environment.
'(default ((t (:family "FantasqueSansM Nerd Font Mono" :foundry "PfEd" :slant normal :weight regular :height 98 :width normal)))))
Which emacs knows how to modify, too.It's not the most featureful or fastest terminal emulator, but I can jump around the buffer like any other buffer and seamlessly access it along with the other content I'm editing.
On a remote computer where I can't run a graphical emacs, I either remotely edit files via tramp, or run a headless emacs server process and connect remotely with a graphical emacsclient.
These days I've pretty much settled on having and emacs window and GNOME Terminal side by side as my two main work windows, and it's pretty comfortable. I like that I can mouse select and copy from the terminal window and then C-y into emacs and vice versa.
If I really have some need I might still open a shell or ansi-term session but it's pretty rare now. Sometimes it's convenient when I find myself in a remote shell session and want to have a text editor and shell vertically tiled, I'll just run emacs with ansiterm because for the life of me I can't ever remember the screen keyboard shortcuts for splitting windows.
advantages include fonts (even different ones at the same time), menus, mouse, colors, multiple frames/windows, and more...
You can also run the graphics locally use tramp to access remote systems. I can edit config files on a remote linux-based router which basically has busybox, with all the bells and whistles.
a much better experience.
emacs -nw
If it looks good when you apply a theme, great.If not add the following to .bashrc, .zshrc, .fishrc (you know the drill):
export COLORTERM=truecolor
(reload the shell, or just execute this line and start emacs -nw again, voila.)For some reason, this article makes it look like you need to dig into terminfo, generally you won't need to, maybe 10 years ago, not now.
(I quickly retested just now, to be sure, on Macos iTerm & Linux, Alacritty, Kitty, Gnome Terminal. 24Bit xterm is commonly supported these days.)
Try (not possible to copy paste, see [1]):
echo ^[[48;2;255;0;0mHello^[[0m
Hello is printed with a red (RGB(255,0,0)) background. "^[[0m" resets back to normal colors.[1]: You can type ^[ (escape) by pressing CTRL-'['. Don't type ^ and [ as separate chars, that won't work.
DEVICE=C:\DOS\ANSI.SYS
to your C:\CONFIG.SYS file.You can also use the \x1b escape code(or the \e alias) together with a command that accepts escape code in order to avoid nonprintable characters on the command-line:
echo -e '\e[48;2;255;0;0mHello\e[0m'
For scripts, always use printf though since echo -e is nonstandard and even plain echo differs in edge cases: printf '\e[48;2;255;0;0mHello\e[0m\n'I know about gVim and hundreds of half-baked neovim frontends, but the default way of running emacs is through a bonafide GUI, and I love that.
Terminals are alright, but they have too much historic cruft and limitations that actually do not make any sense in this day and age.
If your issue is running Emacs on a remote server, there's TRAMP and emacsclient (does it work over TCP?)
On net I'm not sure it's an improvement. Being a pure ncurses-esque console app limits the richness of what you're able to display. Native controls and dialogs are in fact a good thing and not a cardinal sin.
Huh? Just use Ctrl+Shift+V or even Ctrl+V if your terminal emulator of choice allows that? I don't see where the minefield is
Not true. There are lots of native front-ends for Neovim; Neovim was architected from the start to enable them [1]:
[1]: https://github.com/neovim/neovim/wiki/Related-projects#gui
(in case anyone thinks that's serious, it's a joke. I only use Cool Retro Term for presentations)
edit: apparently my emacs works with 24 bit colour out of the box: https://imgur.com/a/BM5OTxp. The syntax highlighting is a bit annoying though.
IMHO none of the other retro terms look nearly as good.
Cool Retro Term is great, I want to use it in a presentation as well.
I don't want my editor to read usenet or play solitaire. I want it to edit text and surface useful contextual information, and otherwise stay out of the way and let me devote my mental energy to the task at hand and not futzing with the damn editor config.
Emacs with Org-mode it's far more than an editor or a mail/usenet/elisp interpreter.
It's literally what you want.
I want to edit code. Nothing else.
With Org you can export that into a PDF, html5 files, whatever.
I don't understand how there are so many passionate users of Orgmode yet apparently not a single one of them is a mobile developer who sometimes takes notes on their phone.
In that time I've carried on using Emacs, and have regretted it several times ;)
However, Emacs has come on a lot. It's much easier to configure than it used to be, and LSP has brought its semantic features back into the range of other editors. Its text processing abilities have always been stellar and far outshone anything else I've tried.
I'm very happy I stuck with it. I've kept many years of muscle memory and tricks and avoided having to reconfigure 3 different editors. Plus there are killer features like magit and org-mode.
> We used semicolon (like other SGR parameters) for separating the R/G/B values in the escape sequence, since a copy of ITU T.416 (ISO-8613-6) which presumably clarified the use of colon for this feature was costly.
Non-free standards are self-defeating. What's the point of the standard if the people who need them to implement stuff can't read them?
Maybe I'll try it again in a few years when its in more terminfo packages.
(I use kitty on Mac and Windows Terminal on Windows, but it ends up not mattering because I'm always in tmux, so that's the terminfo that remote machines need. I never bothered setting up 24 bit color though, so I have no idea if that would work with my setup. I switched to TERM=tmux-direct to get italic fonts in Emacs running on Linux inside tmux inside an SSH session from Windows Terminal. It works!)
I use the ssh kitten, it works fine.
Some systems only have ancient versions of emacs available in repos, limiting packages I could install.
Maybe I should try again. Terminal mode works but requires a lot of workarounds and copy/paste integration isn't perfect.
The problem with getting lsp modes working in things like docker containers is:
- docker containers set PATH - tramp doesn't use PATH by default - even using `(add-to-list 'tramp-remote-path 'tramp-own-remote-path)` doesn't work
tramp-own-remote-path doesn't work because:
*Note* that this works only if your remote ‘/bin/sh’ shell supports
the login argument ‘-l’.
For whatever reason this doesn't work in many docker containers or perhaps is a NixOS issue... not totally sure.I need to revisit this at some point, because otherwise you have to update your tramp connections every time the PATH in the docker file changes, which for many make it a non-starter.
I'm sympathetic to the security first approach of why tramp doesn't just use PATH or the behavior of `tramp-own-remote-path` by default, but it makes working with the insecure by default rest of the IT ecosystem more difficult.
Related threads:
https://www.mail-archive.com/tramp-devel@gnu.org/msg05953.ht... https://github.com/NixOS/nixpkgs/issues/220187
The solutions are better these days for session handling in emacs with save-place-mode and one of:
persp-mode bufler (using bookmarks)
However one of the biggest advantages for me is also having things like eshell or vterm get restored. That's arguably a less emacs friendly way of doing things than say using a compile buffer or async-shell-command with proper history, but... can't change over everything all at once :)
It seems possible to offer graceful degradation for non-supporting terminals, and I'd be surprised if the number of Terminal.app users that would even notice the difference would be that high:
Surely everybody who cares about a good terminal experience uses some third-party client already? Then again, maybe I'm underestimating managed/corporate devices that don't allow third-party terminal emulators, since they do have quite critical access in the end.
iTerm2: (https://iterm2.com/)
Kitty terminal (https://sw.kovidgoyal.net/kitty/)
WezTerm termina (https://wezfurlong.org/wezterm/index.html)
Alacritty (https://github.com/alacritty/alacritty)
My daily driver is WezTerm…
- Runs on Linux, macOS, Windows 10 and FreeBSD
- Multiplex terminal panes, tabs and windows on local and remote hosts, with native mouse and scrollback (https://wezfurlong.org/wezterm/multiplexing.html)
- Ligatures (https://github.com/tonsky/FiraCode#fira-code-monospaced-font...), Color Emoji and font fallback, with true color and dynamic color schemes (https://wezfurlong.org/wezterm/config/appearance.html#colors).
- Hyperlinks (https://wezfurlong.org/wezterm/hyperlinks.html)
- Searchable Scrollback (https://wezfurlong.org/wezterm/scrollback.html) (use mouse wheel and `Shift-PageUp` and `Shift PageDown` to navigate, Ctrl-Shift-F to activate search mode)
- xterm style selection of text with mouse; paste selection via `Shift-Insert` (bracketed paste is supported!)
- SGR style mouse reporting (works in vim and tmux)
- Render underline, double-underline, italic, bold, strikethrough (most other terminal emulators do not support as many render attributes)
- Configuration via a configuration file (https://wezfurlong.org/wezterm/config/files.html) with hot reloading
- Multiple Windows (Hotkey: `Super-N`)
- Splits/Panes (Split horizontally/vertically: `Ctrl-Shift-Alt-%` and `Ctrl-Shift-Alt-"`, move between panes: `Ctrl-Shift-ArrowKey`)
- Tabs (Hotkey: `Super-T`, next/prev: `Super-Shift-[` and `Super-Shift-]`, go-to: `Super-[1-9]`)
- SSH client with native tabs (https://wezfurlong.org/wezterm/ssh.html)
- Connect to serial ports for embedded/Arduino work (https://wezfurlong.org/wezterm/serial.html)
- Connect to a local multiplexer server over unix domain sockets
- Connect to a remote multiplexer using SSH or TLS over TCP/IP
- iTerm2 compatible image protocol support, and built-in imgcat command (https://wezfurlong.org/wezterm/imgcat.html)
- Kitty graphics support
- Sixel graphics support (experimental: starting in `20200620-160318-e00b076c`)
Unclear. The built-in Terminal app is pretty good otherwise, and true color isn't necessary for a lot (most?) of common terminal usage. It's not so poor that all command line users would definitely have a third party app.
My system seems to have TERM=xterm-256color
I wonder what would happen with a 24-bit color terminfo file.
They are fucking incredible and you only need to look at their readme to see the the intense duty of care. It’s not just aesthetics it’s accessibility.
My blog is built by emacs and I use modus-operandi for syntax highlighting.
I also have icons in my terminal by using nerd icons.
Apparently there is a copy in Germany https://search.worldcat.org/title/1069189730
Unless you're showing pictures in your terminal, why would you want true color and the overhead that introduces? If you're just doing a status bar on a black background, your eye won't really see the difference between FF0000 and FF1515 (which I picked because the next 16 bit color is FF3333 which you can already barely tell the difference from).
I'm just saying I'm not sure I would want that much color choice, it would just give me anxiety about picking the right color!
Developers of themes for Emacs often target the GUI first, where 24-bit color is the default. If you're a hardcore terminal Emacs user (and there are many legit reasons for this) you're stuck by default with 256 colors, and the themes just don't look right due to having to map the carefully chosen colors to the nearest color in the 256 color palette.
Even if 256 colors are available it's not enough. The palette of the 256 colors is gruesome. You can clearly see that a technical person without any knowledge of color theory designed it.
From this article I found the command "toe -a" and was able to try various TERM values until I found one that makes Magit readable: vt100. This turns off colors entirely, which may not be pretty, but at least I can read everything now.
If you must, use just a couple of colors--or even just shades of gray or bold--to highlight important things like functions.
But that's what indentation is for. You indent/format your code to help find things. It seems to work well in books. And that works everywhere without any work involved to make it happen.
Hard to say how rarely. I've been using 24-bit color in bash prompts and neovim scheme for a while. Can't go back to 16 or 256 color ones, they are just too limited.
I wish tty terminal also supported 24-bit color.
For setting the color in bash I use something like:
printf "\x1b[38;2;${r};${g};${b}m"
or printf "\x1b[${f};38;2;${r};${g};${b}m"
If I need to set extra bits like bold.(I run most of my emacsen inside VS Code.)
It's the only thing stopping me from using Emacs remotely over a terminal: I really do need my Super modifier. Hyper I can live without, but being able to do shift-super-f for example is fundamental.
I enjoyed tinkering for years. One day my Vim colors wouldn’t work in Tmux for like the 5th time in my life. I said, you know what? I’m done with all of this.
I appreciate that what you did is fun. I just thought I’d share a perspective that sometimes we’re sick of tinkering.