tinted-theming / home

Style systems and smart build tooling for crafting high fidelity color schemes and easily using them in all your favorite apps.
MIT License
284 stars 14 forks source link

Idea: Support full ANSI schemes with 'semantic' colors #36

Open joshgoebel opened 2 years ago

joshgoebel commented 2 years ago

I wanted to write-up my idea of how to support 16-color "classic" ANSI themes inside the Base16 banner... this involves semantic colors so that we can have all 16 of our named ANSI colors and then map them (as makes the most sense) back into the non-ANSI baseXX mappings - such that ANSI schemes could continue to be used anywhere that base16 is supported.

The mapping isn't perfect... it's not 100% clear which ANSI colors should by default map to the old "orange hue" (base09) or the old brown hue (base0F)... and the larger loss, the 8 shade BG/FG gradient now would now have to shift to only a 4 color ANSI gradient:

Here is what a scheme might look like. Please ignore the rgb syntax. I'm not suggested it, it was just easiest to write up this sample without having to lookup a bunch of hexcodes.

scheme: "Default-ish Terminal"

ansi00: rgb(0,0,0) # black
ansi01: rgb(128,0,0) # red
ansi02: rgb(0,128,0) # green
ansi03: rgb(128,128,0) # brown / yellow
ansi04: rgb(0,0,128) # blue
ansi05: rgb(128,0,128) # purple
ansi06: rgb(0,128,128) # cyan
ansi07: rgb(128,128,128) # dark grey
ansi08: rgb(192,192,192) # grey
ansi09: rgb(255,0,0) # bright red
ansi0A: rgb(0,255,0) # bright green
ansi0B: rgb(255,255,0) # bright yellow
ansi0C: rgb(0,0,255) # bright blue
ansi0D: rgb(255,0,255) # bright purple
ansi0E: rgb(0,255,255) # bright cyan
ansi0F: rgb(255,255,255) # white

# here we map the black-white ANSI gradient into base00 - base 07
# note these defaults could be handled inside builder such that ANSI
# schemes only had to define the 16 ansi colors, not worry about the
# baseXX colors 
base00: ansi00 # black
base01: ansi00 # black
base02: ansi07 # dark grey
base03: ansi07 # dark grey
base04: ansi08 # grey
base05: ansi08 # grey
base06: ansi0F # white
base07: ansi0F # white
base08: ansi09 # bright red
base09: # whatever closest to orange???
base0A: ansi0B # bright yellow
base0B: ansi0A # bright green
base0C: ansi0E # bright cyan
base0D: ansi0C # bright blue
base0E: ansi0F # bright purple
base0F: ansi03 # brown / dark yellow???

Please note there are still only 16 colors here.

@belak and I spoke about this at length. It would require effort from template maintainers to support... mostly dealing with the 8 => 4 shade gradient reduction... but at the template level this could be supported via boolean flags:

{{#gradient4}}
# config for a 4 shade gradient
{{/gradient4}}

{{#gradient8}}
# config for a more traditional 8 shade gradient
{{/gradient8}}

For some app UI templates (usually app+terminal, such as Vim, Emacs, etc) this would require an investment to support both 4 and 8 color ramps... For a lot of templates (Terminal templates esp) supporting this new scheme format is even easier than what they were doing previously... since the new templates would just be mapping ansi0 - ansi15 directly to ANSI 0 to ANSI 15, no complex mappings at all.

I think an approach like this might be better than just a hard fork where we send the people who want 16 ANSI colors off to their own island to build all their own stuff... that assumes of course there are people here who are interested in actual 16 color ANSI support. For a time you might have some older templates that "don't support ANSI schemes"... it would be up to the community to fill those gaps - if they wanted ANSI everywhere".

I think going the other direction (older schemes into new templates) the ANSI palette could largely be auto-generated on the fly... so the 8 color ramp would be reduced to 4 colors (via blending) and the "hues everyone seems to use" would be mapped into the most appropriate ANSI slots and dark and light versions would be created. New templates should therefore support either BOTH (Base16ANSI and Base16) or just support ANSI and trust the auto-conversion.

So first, does anyone care about Base16 supporting 16 color ANSI light/dark/etc - just as the terminal gods originally decreed it to be? ;-)

joshgoebel commented 2 years ago

Ann example of what the console 2 config would look like:

<?xml version="1.0"?>
<settings>
 <console>
  <colors>
   <color  id="0" r="{{ ansi00-rgb-r }}" g="{{ ansi00-rgb-g }}" b="{{ ansi00-rgb-b }}"/> <!-- black -->
   <color  id="1" r="{{ ansi01-rgb-r }}" g="{{ ansi01-rgb-g }}" b="{{ ansi01-rgb-b }}"/> <!-- blue -->
   <color  id="2" r="{{ ansi02-rgb-r }}" g="{{ ansi02-rgb-g }}" b="{{ ansi02-rgb-b }}"/> <!-- green -->
   <color  id="3" r="{{ ansi03-rgb-r }}" g="{{ ansi03-rgb-g }}" b="{{ ansi03-rgb-b }}"/> <!-- cyan -->
   <color  id="4" r="{{ ansi04-rgb-r }}" g="{{ ansi04-rgb-g }}" b="{{ ansi04-rgb-b }}"/> <!-- red -->
   <color  id="5" r="{{ ansi05-rgb-r }}" g="{{ ansi05-rgb-g }}" b="{{ ansi05-rgb-b }}"/> <!-- magenta -->
   <color  id="6" r="{{ ansi06-rgb-r }}" g="{{ ansi06-rgb-g }}" b="{{ ansi06-rgb-b }}"/> <!-- yellow/brown -->
   <color  id="7" r="{{ ansi07-rgb-r }}" g="{{ ansi07-rgb-g }}" b="{{ ansi07-rgb-b }}"/> <!-- white -->
   <color  id="8" r="{{ ansi08-rgb-r }}" g="{{ ansi08-rgb-g }}" b="{{ ansi08-rgb-b }}"/> <!-- brblack -->
   <color  id="9" r="{{ ansi09-rgb-r }}" g="{{ ansi09-rgb-g }}" b="{{ ansi09-rgb-b }}"/> <!-- brblue -->
   <color id="10" r="{{ ansi0A-rgb-r }}" g="{{ ansi0A-rgb-g }}" b="{{ ansi0A-rgb-b }}"/> <!-- brgreen -->
   <color id="11" r="{{ ansi0B-rgb-r }}" g="{{ ansi0B-rgb-g }}" b="{{ ansi0B-rgb-b }}"/> <!-- brcyan -->
   <color id="12" r="{{ ansi0C-rgb-r }}" g="{{ ansi0C-rgb-g }}" b="{{ ansi0C-rgb-b }}"/> <!-- brred -->
   <color id="13" r="{{ ansi0D-rgb-r }}" g="{{ ansi0D-rgb-g }}" b="{{ ansi0D-rgb-b }}"/> <!-- brmagenta/violet -->
   <color id="14" r="{{ ansi0E-rgb-r }}" g="{{ ansi0E-rgb-g }}" b="{{ ansi0E-rgb-b }}"/> <!-- bryellow -->
   <color id="15" r="{{ ansi0F-rgb-r }}" g="{{ ansi0F-rgb-g }}" b="{{ ansi0F-rgb-b }}"/> <!-- brwhite -->
  </colors>
 </console>
</settings>

Just a direct 1-1 mapping, zero surprises.

joshgoebel commented 2 years ago

@kdrag0n @AFulgens @martinlindhe @aarowill

I didn't want to spam all the terminal authors but I noticed that you all maintain multiple base16 terminal templates so I thought I might reach out and see if you all have any thoughts on this idea on improved ANSI 16-color support for terminals rather than the current 8 color no distinction between light/dark compromise...

cskeeters commented 2 years ago

So the path forward would be to get all of the color schemes to have ansiXX variables, and then get the template repositories to swap over to using the ANSI variables rather than the baseXX variables? I'm happy to update base16-konsole once the ansiXX variables are in place in each color scheme.

In your example, the comment has color 1 set to ansi 1 and the color inside the comment is blue. Isn't ansi1 red?

Also, would there be a push to keep ansi1 the reddest color of the color scheme?

belak commented 2 years ago

So the path forward would be to get all of the color schemes to have ansiXX variables, and then get the template repositories to swap over to using the ANSI variables rather than the baseXX variables? I'm happy to update base16-konsole once the ansiXX variables are in place in each color scheme.

There are a few parts to this:

  1. This issue is about semantic names - each scheme system would provide a set of names corresponding to the 16 ansi colors. They'd be in order (black, red, green, etc).
  2. ansi16 - this one is my brainchild and is only half-baked at the moment. The idea would be to have a set of schemes which only includes the 16 ansi colors.

Eventually it should be possible to write templates against these semantic aliases so you'd be able to write a terminal template which supports base16, ansi16 and other future systems using only the aiases.

In your example, the comment has color 1 set to ansi 1 and the color inside the comment is blue. Isn't ansi1 red?

I believe this was a mistake. You're right that ansi01 is red

joshgoebel commented 2 years ago

They'd be in order (black, red, green, etc).

It'd be fine to have ansi.red and ansi.brightRed, but I could also imagine some templates just wanting to map in 0-15, no? ansi00-ansi15 actually have semantic meaning inside the ANSI system, so they don't bother me. Guess I'm not seeing why it has to be either or, or am I misunderstanding you?

I would handle this all seamlessly inside the builder/resolver...

AFulgens commented 2 years ago

(See my comment https://github.com/base16-project/home/issues/65#issuecomment-1229408401 for more details).

It's fine by me to pivot to ANSI. I would suggest to undertake this as part of the migration envisioned in #44. In case this will be carried out, I would suggest to keep the original repos as archived repos and maybe linked in the new one.

The generation of the orange will be an interesting dilemma, I currently cannot fathom a perfect solution, will look out for ideas by brigther minds :)

actionless commented 2 years ago

It'd be fine to have ansi.red and ansi.brightRed

i think it would be better than using numbered colors, to help theme-makers to not set some weird colors, like green instead of red and etc

joshgoebel commented 1 year ago

Well, theme makers are still free to be 'weird', but names instead of numbers does seem to make unintentional mistakes much harder to make. :-)