helix icon indicating copy to clipboard operation
helix copied to clipboard

Approximate `truecolor` styles with ANSI-256 colors

Open nlordell opened this issue 3 years ago • 0 comments

The terminal emulator I use does not have true color support (specifically, Terminal.app). This means that most themes don't work.

However, it is possible to have some support ANSI-256 color terminals by approximating 24-bit RGB colors to one of 256 ANSI colors.

For my own personal use and as a quick and dirty hack, I applied the following patch to the theme loading logic in order to get true color themes working locally (disclaimer: didn't do due diligence on what the best crate for doing the color conversion is, but from a quick glance ansi_colours seemed fine to me; additionally, the conversion fits into a single-file-module and can be easily vendored into this repo):

diff --git a/helix-view/Cargo.toml b/helix-view/Cargo.toml
index 77634ce5..cdba687c 100644
--- a/helix-view/Cargo.toml
+++ b/helix-view/Cargo.toml
@@ -20,6 +20,7 @@ helix-core = { version = "0.6", path = "../helix-core" }
 helix-lsp = { version = "0.6", path = "../helix-lsp" }
 helix-dap = { version = "0.6", path = "../helix-dap" }
 crossterm = { version = "0.23", optional = true }
+ansi_colours = "1"
 
 # Conversion traits
 once_cell = "1.12"
diff --git a/helix-view/src/theme.rs b/helix-view/src/theme.rs
index 3f45aac6..0177d15e 100644
--- a/helix-view/src/theme.rs
+++ b/helix-view/src/theme.rs
@@ -225,7 +225,9 @@ impl ThemePalette {
                 u8::from_str_radix(&s[3..5], 16),
                 u8::from_str_radix(&s[5..7], 16),
             ) {
-                return Ok(Color::Rgb(red, green, blue));
+                return Ok(Color::Indexed(ansi_colours::ansi256_from_rgb((
+                    red, green, blue,
+                ))));
             }
         }

This produces some good results: image image

While this quick and dirty solution is incredibly specific to my setup, I think it would be reasonable to build-in some theme true color -> ANSI-256 approximation. I don't mind contributing it myself, I just wanted to:

  1. Make sure this is a feature the project would like to include
  2. Brainstorm how the configuration for this would look like

Regarding 2., I had imagined something like:

colors = "<mode>"

Where mode can be one of:

  • auto: behaves like true-color: false does today
  • truecolor: behaves like true-color: true does today
  • ansi256: approximates themes by converting RGB colors to ANSI-256 color codes

The downside to this suggestion is that it would be a backwards-compatibility breaking change.

nlordell avatar Aug 09 '22 10:08 nlordell

Thanks for investigating this! It's great that it's such a small change. I bet we could vendor that ansi_colours::ansi256_from_rgb function along with any config changes in around 100 lines of changes overall.

Wether this is in scope or not is a good question though. If truecolor support is the only thing older terminals are missing then IMO this would be in scope and it would be nice to expand the supported terminals with such a small change. But I'm concerned about features in terminal emulators like Bracketed-paste (see also #2239, #3233) or italics. If older terminals like Terminal.app are lacking many features, I think it may be best to explicitly not support them and instead to point to modern terminals like in the newly written Terminal Support wiki page.

I'm curious what you think about it @archseer and @sudormrfbin?

the-mikedavis avatar Aug 11 '22 16:08 the-mikedavis

For the record, of the three features mentioned on mentioned on Terminal Support, Terminal.app:

  • supports bracketed paste
  • supports focus events
  • doesn't support setting the OS clipboard via OSC 52

Those are just the three features I knew enough about to add to the page, so there may be other relevant terminal features to consider.

groves avatar Aug 11 '22 18:08 groves

Another potential option for approximating truecolor support would be to do something similar to what osc52pty does (found it in a link in the vim-oscyank README) for support OCS 52 sequences in Terminal.app.

Specifically, it could spawn hx as a child process, pipe its standard output, and intercept truecolor sequences and approximate them to ANSI-256 color codes without requiring modifications to hx itself.

I looked around and found this seemingly up-to-date list of terminal emulators that don't support truecolor (AKA direct color, TIL).

nlordell avatar Aug 11 '22 20:08 nlordell