<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: gesslar</title>
    <description>The latest articles on Forem by gesslar (@gesslar).</description>
    <link>https://forem.com/gesslar</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F457343%2F0a149d47-8e4f-4fc8-8cc3-dcd1ddb92489.jpg</url>
      <title>Forem: gesslar</title>
      <link>https://forem.com/gesslar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/gesslar"/>
    <language>en</language>
    <item>
      <title>Sassy, but GUI. No. Really. That's what it's called.</title>
      <dc:creator>gesslar</dc:creator>
      <pubDate>Sun, 22 Mar 2026 05:10:01 +0000</pubDate>
      <link>https://forem.com/gesslar/sassy-but-gui-no-really-thats-what-its-called-3g03</link>
      <guid>https://forem.com/gesslar/sassy-but-gui-no-really-thats-what-its-called-3g03</guid>
      <description>&lt;p&gt;&lt;strong&gt;Sassy&lt;/strong&gt; (which is actually spelled with lowercase first 's', but English &lt;em&gt;demands&lt;/em&gt; it be capitalised. Sorry, little buddy) is a way to create VS Code themes. Or Codium. You write it in YAML and you can make it as simple or complicated as you like. You do you, boo, sassy has you covered. I wrote about it here:&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/gesslar/-stop-dont-youre-doing-it-wrong-aka-what-if-making-a-vs-code-theme-didnt-suck-gkd" class="crayons-story__hidden-navigation-link"&gt;Stop! Don't! You're doing it wrong! a.k.a. What if making a VS Code theme didn't suck?&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/gesslar" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F457343%2F0a149d47-8e4f-4fc8-8cc3-dcd1ddb92489.jpg" alt="gesslar profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/gesslar" class="crayons-story__secondary fw-medium m:hidden"&gt;
              gesslar
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                gesslar
                
              
              &lt;div id="story-author-preview-content-3297246" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/gesslar" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F457343%2F0a149d47-8e4f-4fc8-8cc3-dcd1ddb92489.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;gesslar&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/gesslar/-stop-dont-youre-doing-it-wrong-aka-what-if-making-a-vs-code-theme-didnt-suck-gkd" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Mar 1&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/gesslar/-stop-dont-youre-doing-it-wrong-aka-what-if-making-a-vs-code-theme-didnt-suck-gkd" id="article-link-3297246"&gt;
          Stop! Don't! You're doing it wrong! a.k.a. What if making a VS Code theme didn't suck?
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/vscode"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;vscode&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/themes"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;themes&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/javascript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;javascript&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/node"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;node&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/gesslar/-stop-dont-youre-doing-it-wrong-aka-what-if-making-a-vs-code-theme-didnt-suck-gkd" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;7&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/gesslar/-stop-dont-youre-doing-it-wrong-aka-what-if-making-a-vs-code-theme-didnt-suck-gkd#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              5&lt;span class="hidden s:inline"&gt; comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            15 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


&lt;p&gt;Which you've definitely all read, for sure. Anyway, I then went and finished off an extension for VS Code and Codium that lets you do all the CLI things but in a clicky clicky way. In fact, the extension has every single feature available in sassy, because I put an API in sassy. So I could write an extension. It's all very complicated.&lt;/p&gt;

&lt;p&gt;I already had another extension called &lt;strong&gt;Hex&lt;/strong&gt;, which doesn't include even a single thing that &lt;strong&gt;sassy&lt;/strong&gt; can do, because it answers a different question: what if I could make sure my resulting JSON theme file is correct? Which you can't do in a CLI because you can only access this information from within VS Code. Trust me, I tried. (But if you've found a way to do it, don't tell me. I will be upset. My Wakko figurine will be upset. It'll be a whole thing; so just keep it to yourself, or post about it.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sassy, but GUI&lt;/strong&gt; (which is spelled with a capital 'S'. Don't ask me, I wasn't invited to be on the naming committee) says "I can do  both. I can be &lt;strong&gt;sassy&lt;/strong&gt;, I can be &lt;strong&gt;Hexy&lt;/strong&gt;, I can be... ok, well, that's pretty much it."&lt;/p&gt;

&lt;p&gt;It has panels and live validation and jump links to both source and theme output (for them JSON properties/values) in diagnostics; you can see the entire palette you have defined 🎶 In Living Color 🎶; you can see what your entire theme looks like in a proof, or what the engine sees after all imports have been resolved, all séances have been decided, but before everything is evaluated to its final form; and you can see how a &lt;del&gt;bill becomes a law&lt;/del&gt; theme property grew up from a variable to a hex value.&lt;/p&gt;

&lt;p&gt;They kinda look like this?&lt;/p&gt;

&lt;h3&gt;
  
  
  Diagnostics
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqlovb8vsavbt5ooyn3l1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqlovb8vsavbt5ooyn3l1.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Resolve
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy8qkxdr2chpux99jj0af.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy8qkxdr2chpux99jj0af.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Proof
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqy5wweeh25n78elj61fl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqy5wweeh25n78elj61fl.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Palette
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ovnid9hrfqfnn1t49qa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ovnid9hrfqfnn1t49qa.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;See? EZ.&lt;/p&gt;

&lt;p&gt;The install links are here at each of the things mentioned's website. Which is, well, just one website, I guess. HAVE FUN! Or don't. I'm not your supervisor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sassy.gesslar.io/" rel="noopener noreferrer"&gt;sassy&lt;/a&gt;&lt;br&gt;
&lt;a href="https://sassy.gesslar.io/docs/sassy-but-gui/" rel="noopener noreferrer"&gt;Sassy, but GUI&lt;/a&gt;&lt;br&gt;
&lt;a href="https://sassy.gesslar.io/docs/hex/" rel="noopener noreferrer"&gt;Hex&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Postamble
&lt;/h2&gt;

&lt;p&gt;Several posts in, I realise that I seem to only be posting about things I've made. Know, however, that I am not posting my shit because I have some yucky agenda. I don't even really have a stake in anything since I don't sell anything. I don't even care if you &lt;em&gt;use&lt;/em&gt; the things I make. I'm not counting stars or followers on my repos or packages and if I could figure out how to disable those, I would.&lt;/p&gt;

&lt;p&gt;The number of fucks I give can be summed up by the &lt;a href="https://unlicense.org/" rel="noopener noreferrer"&gt;license&lt;/a&gt; I choose for practically everything.&lt;/p&gt;

&lt;p&gt;What I &lt;em&gt;do&lt;/em&gt; care about is making people cognisant of their choices so they can make very adult decisions like "WANTWANTWANT! GIMMEGIMMEGIMME!" or "EW! Grody! No! *vampire hiss*" &lt;/p&gt;

</description>
      <category>vscode</category>
      <category>extensions</category>
      <category>themes</category>
    </item>
    <item>
      <title>Stop! Don't! You're doing it wrong! a.k.a. What if making a VS Code theme didn't suck?</title>
      <dc:creator>gesslar</dc:creator>
      <pubDate>Sun, 01 Mar 2026 00:50:04 +0000</pubDate>
      <link>https://forem.com/gesslar/-stop-dont-youre-doing-it-wrong-aka-what-if-making-a-vs-code-theme-didnt-suck-gkd</link>
      <guid>https://forem.com/gesslar/-stop-dont-youre-doing-it-wrong-aka-what-if-making-a-vs-code-theme-didnt-suck-gkd</guid>
      <description>&lt;p&gt;Okay, quick sidebar? Am I the only who narrates their journey down a bossy-titled feed like "I'm not even doing that." &lt;em&gt;scroll&lt;/em&gt; "I do what I want." &lt;em&gt;scroll&lt;/em&gt; "Probably." &lt;em&gt;scroll&lt;/em&gt; "I definitely do not care about the pain points of meaningless, disconnected flat properties in 2026 when figuratively everybody else has forever been doing nested things, &lt;em&gt;including the people who wrote the spec on VS Code themes&lt;/em&gt;." &lt;em&gt;scroll&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;I wanted a pretty theme and the scant few existing solutions didn't really work in a way that passed my ick test. So, pioneering a new trope I will call "Fine, I'll do it myself," I wrote a small utility to take a YAML or JSON5 and after using a blender and a rolling pin, spit out a theme in JSON. That's it. You can resume your tikkytokkies or whatever you were doing.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Note: my ick test and your ick test will likely look very differently and nothing about my ick test says that things are actually ick.)&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;goto 80&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;You can also jump to the bottom where you can see the full feature list.&lt;/p&gt;

&lt;h2&gt;
  
  
  Welcome to my TEDtalk
&lt;/h2&gt;

&lt;p&gt;Okay, so about a year ago, I was in my VS Code and I couldn't find a theme I liked, which made me feel like a goober sitting in front of satellite TV in 1995 bemused and complaining about the lack of anything to watch. And I'm not going to lie, I'm seeing themes in the millions of downloads and I'm thinking to myself, "This? &lt;em&gt;This has 42 million downloads??&lt;/em&gt; It looks like clown ejac.." anyway, I was a hundred percent judging all of you. But then I was like, okay, but if I recall, it's just JSON, right? I can make JSON.&lt;/p&gt;

&lt;p&gt;And so, I Googled &lt;code&gt;how to make a VS Code theme like a boss and make enough money to buy 3 grilled cheese sandwiches&lt;/code&gt;. I found &lt;a href="https://code.visualstudio.com/api/extension-guides/color-theme#create-a-new-color-theme" rel="noopener noreferrer"&gt;how to create a VS Code theme&lt;/a&gt;. And in that I saw what a basic theme would look like, and I was like ooo, okay, yeah, I can do that. So I shook the Google 8-ball again and I found &lt;a href="https://code.visualstudio.com/api/references/theme-color" rel="noopener noreferrer"&gt;all of the specced faces I could beat&lt;/a&gt; (that sounds violent, but &lt;a href="https://www.urbandictionary.com/define.php?term=beat+face" rel="noopener noreferrer"&gt;it's not&lt;/a&gt;, at its worst it's an astonishing level of hubris).&lt;/p&gt;

&lt;p&gt;Then I looked at one.&lt;/p&gt;

&lt;p&gt;Good FSM, am I supposed to write a theme for Visual Studio Code in dot-delimited properties?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"editor.foreground"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#wtf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"editor.background"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#even"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"editor.is"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#this"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"editor.sinéad"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#wasright"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That seems so... 2008 - &lt;em&gt;generously&lt;/em&gt;. It's &lt;em&gt;JSON&lt;/em&gt;. You know...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"things"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"that"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"can"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"hold"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"other"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"things"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"?"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"!"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Anyway, I was like, fuck that. The problem of creating a theme in a sane way has definitely been solved by now. Ima go find me a thing to make my theme in, because the dev world is clearly &lt;em&gt;starving&lt;/em&gt; for something delightful to look at in their editors and it's up to me to be their saviour.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;[heroic origin story soundtrack swells]&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Back to shaking that Google 8-ball, I began navigating the tubes of the internet. I found several &lt;a href="https://themes.vscode.one/" rel="noopener noreferrer"&gt;points of interest&lt;/a&gt;, with some approaches being &lt;a href="https://github.com/dbanksdesign/nu-disco-vscode-theme" rel="noopener noreferrer"&gt;way more complicated&lt;/a&gt; than &lt;a href="https://vscodethemes.com/" rel="noopener noreferrer"&gt;others&lt;/a&gt;, but none really felt like &lt;em&gt;me&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;And then I saw &lt;a href="https://dev.to/zevro/making-a-vscode-theme-with-variables-3k1d"&gt;this post&lt;/a&gt; by &lt;a class="mentioned-user" href="https://dev.to/zevro"&gt;@zevro&lt;/a&gt; here on dev.to. It has like, idk, 3.14 views? Which is &lt;em&gt;criminal&lt;/em&gt;, because it's so &lt;em&gt;good&lt;/em&gt;. It's brief, yes, but it spells out exactly how to make a VSCode theme the smart way. And, frankly, the lack of viewership tracks. My articles don't do well either and I am also a genius.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements Gathering
&lt;/h2&gt;

&lt;p&gt;So what will my thing look like? If I'm gonna build a thing, and I'll be its primary audience, then for sure I'll be able to define its traits and characteristics, right?&lt;/p&gt;

&lt;p&gt;It needs to be composable, re-usable, extensible, and the language I create will need to be expressive, unintrusive, fluid, adjustable. At a bare minimum, these are non-negotiable for me both in creating a thing and using a thing. At least I'm easy to please though.&lt;/p&gt;

&lt;h2&gt;
  
  
  Definitely only ever named sassy
&lt;/h2&gt;

&lt;p&gt;And in exactly one montage later, to the day, I resurfaced with &lt;del&gt;cunty&lt;/del&gt; &lt;del&gt;Aunty Rose&lt;/del&gt; &lt;strong&gt;sassy&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I landed on the name &lt;code&gt;sassy&lt;/code&gt; for a number of reasons. You want variables? I got variables. Functions? Got'em. Whozits and whatsits galore? Yessirmadamother. So, essentially not a rip off of an existing tech, but more an evolution of ideas. Okay, so the ideas look the same, too. I promise you that sassy is different, though. It's not like other transpilers. Honest. Does Sass have &lt;em&gt;séances&lt;/em&gt;. No. I win!&lt;/p&gt;

&lt;h2&gt;
  
  
  Are you still watching?
&lt;/h2&gt;

&lt;p&gt;If you're still here then we are kindred spirits or your phone has landed on your face and you are too accustomed to being face-punched by your own Pixel 10 Pro XL to even flinch awake.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Outcome
&lt;/h2&gt;

&lt;p&gt;Sassy supports my earlier stated requirements in the following ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;like Sass, it provides for variable substitution throughout (mostly)&lt;/li&gt;
&lt;li&gt;it comes with 25 functions for lightening, adjusting alpha, contrast, mixing&lt;/li&gt;
&lt;li&gt;you can make countless theme variants by importing common palettes, using overrides, holding a séance (you think that's a joke, but you'd be wrong. this is the second time I've mentioned it. clearly it's real.)&lt;/li&gt;
&lt;li&gt;it supports any colour space that &lt;a href="https://culorijs.org/" rel="noopener noreferrer"&gt;Culori&lt;/a&gt; supports (not because I ripped them off, but because sassy uses it), which means&lt;/li&gt;
&lt;li&gt;you can use &lt;code&gt;css(rebeccapurple)&lt;/code&gt; or &lt;code&gt;css(tomato)&lt;/code&gt;, &lt;a href="https://oklch.com" rel="noopener noreferrer"&gt;OKLCH&lt;/a&gt; if you're a huge colour nerd, or even HSL and raw hexadecimal if you're a sinner&lt;/li&gt;
&lt;li&gt;I can write structured, hierarchical, nested, relational, semantic source like a fucking adult where the result is&lt;/li&gt;
&lt;li&gt;JSON that VS Code will happily ingest like a greedy goblin with a bag of cheese curds as it sits down to turn on LOST.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How my life got flipped, turned upside down
&lt;/h2&gt;

&lt;p&gt;Let's get into some demonstration, yeah?&lt;/p&gt;

&lt;h3&gt;
  
  
  Variables
&lt;/h3&gt;

&lt;p&gt;Variables come in 3 shapes. Every time I show a robot my variable syntax, I have to defend it. But, honestly, the entire point of making sassy was to create an ergonomic way to lower the barrier of entry to making themes. So, at the most basic level, I opted to support 3 different variable syntaxes, some with which you may be familiar.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;$var&lt;/code&gt; - straight up bash style&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;${var}&lt;/code&gt; - string interpolation style for my JS girlies (HEEEeeeey!)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$(var)&lt;/code&gt; - another kind because why not, I was already doing more than one&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, if you are familiar with any of these syntaxes, then you're good. And if not? You're still good. Because you're smart. Probably. The only caveat with the &lt;code&gt;$bare&lt;/code&gt; syntax being that if you have it immediately adjacent to a string, either before, after, or in the middle of one, you will need to hug it with &lt;code&gt;{}&lt;/code&gt; or &lt;code&gt;()&lt;/code&gt; because I'm a jerk and say so. Actually, the real reason is that without a bracket hug, it's impossible to tell where the variable name would end, so &lt;code&gt;$nerd-green&lt;/code&gt;, uhh, is the whole thing the variable or is it &lt;code&gt;${nerd}&lt;/code&gt; &lt;code&gt;-&lt;/code&gt; &lt;code&gt;{green}&lt;/code&gt;?? idk! you tell me! Just put a sweater around the nerd and move on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Functions
&lt;/h3&gt;

&lt;p&gt;Ok, I said there were functions and there are. All of the basic breeds of functions you would expect when working with colours are there. This is a direct copy from &lt;a href="https://sassy.gesslar.io" rel="noopener noreferrer"&gt;sassy&lt;/a&gt;'s website to prove it to you.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Function&lt;/th&gt;
&lt;th&gt;Signature&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;lighten&lt;/td&gt;
&lt;td&gt;lighten(colour, amount)&lt;/td&gt;
&lt;td&gt;Lighten by percentage (0--100). Uses OKLCH for perceptual uniformity.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;darken&lt;/td&gt;
&lt;td&gt;darken(colour, amount)&lt;/td&gt;
&lt;td&gt;Darken by percentage (0--100). Uses OKLCH for perceptual uniformity.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;invert&lt;/td&gt;
&lt;td&gt;invert(colour)&lt;/td&gt;
&lt;td&gt;Flip lightness in OKLCH space. Preserves hue and chroma.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tint&lt;/td&gt;
&lt;td&gt;tint(colour, amount)&lt;/td&gt;
&lt;td&gt;Mix with white by percentage (0--100, default 50).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;shade&lt;/td&gt;
&lt;td&gt;shade(colour, amount)&lt;/td&gt;
&lt;td&gt;Mix with black by percentage (0--100, default 50).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;saturate&lt;/td&gt;
&lt;td&gt;saturate(colour, amount)&lt;/td&gt;
&lt;td&gt;Increase chroma by percentage (0--100). Uses OKLCH.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;desaturate&lt;/td&gt;
&lt;td&gt;desaturate(colour, amount)&lt;/td&gt;
&lt;td&gt;Decrease chroma by percentage (0--100). Uses OKLCH.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;grayscale&lt;/td&gt;
&lt;td&gt;grayscale(colour)&lt;/td&gt;
&lt;td&gt;Remove all chroma. Preserves perceptual lightness.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;mute&lt;/td&gt;
&lt;td&gt;mute(colour, amount)&lt;/td&gt;
&lt;td&gt;Move toward greyscale by percentage (0--100). Opposite of pop.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pop&lt;/td&gt;
&lt;td&gt;pop(colour, amount)&lt;/td&gt;
&lt;td&gt;Move away from greyscale by percentage (0--100). Opposite of mute.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;shiftHue&lt;/td&gt;
&lt;td&gt;shiftHue(colour, degrees)&lt;/td&gt;
&lt;td&gt;Rotate hue by degrees (0--360). Uses OKLCH. No-op on achromatic colours.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;complement&lt;/td&gt;
&lt;td&gt;complement(colour)&lt;/td&gt;
&lt;td&gt;Return the 180° hue complement.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;contrast&lt;/td&gt;
&lt;td&gt;contrast(colour)&lt;/td&gt;
&lt;td&gt;Return #000000 or #ffffff, whichever is more readable against the input.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;alpha&lt;/td&gt;
&lt;td&gt;alpha(colour, value)&lt;/td&gt;
&lt;td&gt;Set alpha to an exact value (0--1). 0 = transparent, 1 = opaque.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;fade&lt;/td&gt;
&lt;td&gt;fade(colour, amount)&lt;/td&gt;
&lt;td&gt;Reduce opacity by a relative amount (0--1). Multiplies current alpha by (1 - amount).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;solidify&lt;/td&gt;
&lt;td&gt;solidify(colour, amount)&lt;/td&gt;
&lt;td&gt;Increase opacity by a relative amount (0--1). Multiplies current alpha by (1 + amount).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;mix&lt;/td&gt;
&lt;td&gt;mix(colour1, colour2[, ratio])&lt;/td&gt;
&lt;td&gt;Blend two colours. Ratio 0--100 (default 50). Always uses OKLCH interpolation.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Modifiers
&lt;/h4&gt;

&lt;p&gt;When applying a function, you will usually need to provide a modifier: how far, how much, etc. The basic rules are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;if it's rotating, it's degrees&lt;/li&gt;
&lt;li&gt;if it's alpha, it's 0-1&lt;/li&gt;
&lt;li&gt;if it's an amount, it's 0-100&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Yes, variables work here, too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Look ma, no jazz hands
&lt;/h2&gt;

&lt;p&gt;An important takeaway from all of this is that sassy was designed to &lt;em&gt;allow&lt;/em&gt; complicated, but not &lt;em&gt;require&lt;/em&gt; complicated.&lt;/p&gt;

&lt;p&gt;You can just as easily stick to writing your theme without any complexity all, and still appreciate that you can write it in a easily parseable away, but, let's face it, you're probably going to want to do &lt;em&gt;some&lt;/em&gt; doughnuts in the parking lot and if you're going to do that, you need to know where all the cementy guard thingies are that will absolutely wreck your undercarriage.&lt;/p&gt;

&lt;p&gt;So, here's the map.&lt;/p&gt;

&lt;h3&gt;
  
  
  The map
&lt;/h3&gt;

&lt;p&gt;I'm gonna do it in YAML because I'm kinky like that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# The config section of your theme file contains the basic information needed.&lt;/span&gt;
&lt;span class="c1"&gt;# $schema doesn't *have* to be there, but you're a good girl and will include&lt;/span&gt;
&lt;span class="c1"&gt;# it, yeah?&lt;/span&gt;

&lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;$schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vscode://schemas/color-theme&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Nacho Theme&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dark&lt;/span&gt;

&lt;span class="c1"&gt;# The palette is where you create the colour names that you will use throughout&lt;/span&gt;
&lt;span class="c1"&gt;# your theme. Palette may only access palette and no other namespace in your&lt;/span&gt;
&lt;span class="c1"&gt;# theme file.&lt;/span&gt;

&lt;span class="na"&gt;palette&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;black&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#000"&lt;/span&gt;
  &lt;span class="na"&gt;white&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#ffffff"&lt;/span&gt;
  &lt;span class="na"&gt;purple&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;oklch(0.7 0.1 294.42)&lt;/span&gt;
  &lt;span class="na"&gt;red&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;css(tomato)&lt;/span&gt; &lt;span class="c1"&gt;# hey! we're related!&lt;/span&gt;
  &lt;span class="na"&gt;ghostlyRed&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fade($$red, .25)&lt;/span&gt; &lt;span class="c1"&gt;# hey! we're related!&lt;/span&gt;

&lt;span class="c1"&gt;# The vars section is where you create the semantic relationships that you will&lt;/span&gt;
&lt;span class="c1"&gt;# apply throughought your theme. Think of it as semantic relationships that you&lt;/span&gt;
&lt;span class="c1"&gt;# will apply throughout your theme. $$ is shorthand for palette. so $$black&lt;/span&gt;
&lt;span class="c1"&gt;# means $palette.black&lt;/span&gt;

&lt;span class="na"&gt;vars&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;transparent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#abcdef00"&lt;/span&gt;
  &lt;span class="na"&gt;accent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$$purple&lt;/span&gt;
  &lt;span class="na"&gt;accentSecondary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$$red&lt;/span&gt;

  &lt;span class="na"&gt;fg&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$$white&lt;/span&gt;
    &lt;span class="na"&gt;inverse&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;invert($fg.main)&lt;/span&gt;

  &lt;span class="na"&gt;bg&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# yes this works :p, although giving "main" the value of a panel is&lt;/span&gt;
    &lt;span class="c1"&gt;# arguably reverse semantics, so maybe don't do that. i'm not arguing&lt;/span&gt;
    &lt;span class="c1"&gt;# against using something later defined here, only main = some panel?&lt;/span&gt;
    &lt;span class="c1"&gt;# should be the other way around.&lt;/span&gt;
    &lt;span class="na"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$bg.panel.base&lt;/span&gt;
    &lt;span class="na"&gt;highlight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$$ghostlyRed&lt;/span&gt;
    &lt;span class="na"&gt;panel&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;base&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$$black&lt;/span&gt; &lt;span class="c1"&gt;# waves from the future&lt;/span&gt;
      &lt;span class="na"&gt;secondary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;lighten($bg.panel.base, 25)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Equally valid, the above flattened would look like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;config.$schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vscode://schemas/color-theme&lt;/span&gt;
&lt;span class="na"&gt;config.name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Nacho Theme&lt;/span&gt;
&lt;span class="na"&gt;config.type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dark&lt;/span&gt;
&lt;span class="na"&gt;palette.black&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#000"&lt;/span&gt;
&lt;span class="na"&gt;palette.white&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#ffffff"&lt;/span&gt;
&lt;span class="na"&gt;palette.purple&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;oklch(0.7 0.1 294.42)&lt;/span&gt;
&lt;span class="na"&gt;palette.red&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;css(tomato)&lt;/span&gt;
&lt;span class="na"&gt;palette.ghostlyRed&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fade($$red, .25)&lt;/span&gt;
&lt;span class="na"&gt;vars.accent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$$purple&lt;/span&gt;
&lt;span class="na"&gt;vars.accentSecondary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$$red&lt;/span&gt;
&lt;span class="na"&gt;vars.fg.main&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$$white&lt;/span&gt;
&lt;span class="na"&gt;vars.fg.inverse&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;invert($fg.main)&lt;/span&gt;
&lt;span class="na"&gt;vars.bg.main&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$bg.panel.base&lt;/span&gt;
&lt;span class="na"&gt;vars.bg.highlight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$$ghostlyRed&lt;/span&gt;
&lt;span class="na"&gt;vars.bg.panel.base&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$$black&lt;/span&gt;
&lt;span class="na"&gt;vars.bg.panel.secondary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;lighten($bg.panel.base, 25)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🤢 No, thank you. But you do you!&lt;/p&gt;

&lt;h3&gt;
  
  
  Stir it up, thick
&lt;/h3&gt;

&lt;p&gt;The above are the essential ingredients and are what enable you to define your actual theme by describing the widgets and panels and editor spaces and tabs and menus with the side effect of showing that you care about your own sanity by merely assigning variables to them like it's the most obvious thing in the world:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# The theme namespace contains all of what will be ultimately your theme.&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# It can contain:&lt;/span&gt;
&lt;span class="c1"&gt;# colors               - your workbench colours as an object&lt;/span&gt;
&lt;span class="c1"&gt;# tokenColors          - syntax highlighting colours as an array of objects&lt;/span&gt;
&lt;span class="c1"&gt;# semanticTokenColors  - which is also syntax highlighting colours but as an&lt;/span&gt;
&lt;span class="c1"&gt;#                        object, because why be consistent&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# We're just gonna look at colors though&lt;/span&gt;

&lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;colors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;window&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;activeBorder&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$accent&lt;/span&gt;
      &lt;span class="na"&gt;inactiveBorder&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;grayscale($window.activeBorder)&lt;/span&gt;

    &lt;span class="na"&gt;editor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;foreground&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$fg.main&lt;/span&gt;
      &lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$bg.panel.base&lt;/span&gt;
      &lt;span class="na"&gt;selectionBackground&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$bg.highlight&lt;/span&gt;
      &lt;span class="na"&gt;lineHighlightBackground&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fade($editor.selectionBackground, 15)&lt;/span&gt; &lt;span class="c1"&gt;# fade it again!&lt;/span&gt;

    &lt;span class="c1"&gt;# Title Bar colors&lt;/span&gt;
    &lt;span class="na"&gt;titleBar&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# Active&lt;/span&gt;
      &lt;span class="na"&gt;activeForeground&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$fg.main&lt;/span&gt;
      &lt;span class="na"&gt;activeBackground&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$bg.main&lt;/span&gt;
      &lt;span class="c1"&gt;# Title Bar Border&lt;/span&gt;
      &lt;span class="na"&gt;border&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pop($accentSecondary, 50)&lt;/span&gt; &lt;span class="c1"&gt;# mmm yummy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how nothing in the &lt;code&gt;colors&lt;/code&gt; namespace directly accesses anything from the &lt;code&gt;palette&lt;/code&gt; namespace. You &lt;em&gt;can&lt;/em&gt; and sassy won't prevent it, but it will give you side-eye for doing so, because you'll be hurting &lt;code&gt;vars&lt;/code&gt;' feelings. Why are you trying to hurt vars'ses feelings??&lt;/p&gt;

&lt;h3&gt;
  
  
  Immigration
&lt;/h3&gt;

&lt;p&gt;So, you've like built a theme, but now you want to make a light variant. Because you're also a hero and refuse to let the whities subsist on dank&lt;br&gt;
and dark when they would prefer to bask in the light of 10^10^10 nits.&lt;/p&gt;

&lt;p&gt;Ok, so, to achieve this very realistic use case, just take your palette out of your theme file and put it in its own, create a light theme and import the palette into both and override some things.&lt;/p&gt;

&lt;p&gt;Fine, I'll do it for you, lazy. I'll even split out the colors and shared vars into their own files to really show you what sex on a stick looks like.&lt;/p&gt;

&lt;h4&gt;
  
  
  palette.yaml
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;palette&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;black&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#000"&lt;/span&gt;
  &lt;span class="na"&gt;white&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#ffffff"&lt;/span&gt;
  &lt;span class="na"&gt;purple&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;oklch(0.7 0.1 294.42)&lt;/span&gt;
  &lt;span class="na"&gt;red&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;css(tomato)&lt;/span&gt; &lt;span class="c1"&gt;# hey! we're related!&lt;/span&gt;
  &lt;span class="na"&gt;ghostlyRed&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fade($$red, .25)&lt;/span&gt; &lt;span class="c1"&gt;# hey! we're related!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  shared.yaml
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;vars&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;transparent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#abcdef00"&lt;/span&gt;

  &lt;span class="na"&gt;fg&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$foreground&lt;/span&gt; &lt;span class="c1"&gt;# remember, we can do this!&lt;/span&gt;
    &lt;span class="na"&gt;inverse&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;invert($fg.main)&lt;/span&gt;

  &lt;span class="na"&gt;bg&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$background&lt;/span&gt; &lt;span class="c1"&gt;# ok, we're srs now&lt;/span&gt;
    &lt;span class="na"&gt;highlight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$$ghostlyRed&lt;/span&gt;
    &lt;span class="na"&gt;panel&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;base&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$bg.main&lt;/span&gt; &lt;span class="c1"&gt;# waves from the future&lt;/span&gt;
      &lt;span class="na"&gt;secondary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;lighten($bg.panel.base, 25)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  colors.yaml
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;colors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;window&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;activeBorder&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$accent&lt;/span&gt;
      &lt;span class="na"&gt;inactiveBorder&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;grayscale($window.activeBorder)&lt;/span&gt;

    &lt;span class="na"&gt;editor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;foreground&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$fg.main&lt;/span&gt;
      &lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$bg.panel.base&lt;/span&gt;
      &lt;span class="na"&gt;selectionBackground&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$bg.highlight&lt;/span&gt;
      &lt;span class="na"&gt;lineHighlightBackground&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fade($editor.selectionBackground, 15)&lt;/span&gt; &lt;span class="c1"&gt;# fade it again!&lt;/span&gt;

    &lt;span class="na"&gt;titleBar&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;activeForeground&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$fg.main&lt;/span&gt;
      &lt;span class="na"&gt;activeBackground&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$bg.main&lt;/span&gt;
      &lt;span class="na"&gt;border&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pop($accentSecondary, 50)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now you have tiny little opinionated babies who scream and get what they want, and everything else just quietly accommodates their needs, wants, and desires.&lt;/p&gt;

&lt;h4&gt;
  
  
  nacho.yaml
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;$schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vscode://schemas/color-theme&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Nacho Theme&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dark&lt;/span&gt;

  &lt;span class="na"&gt;import&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./palette.yaml&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./shared.yaml&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./colors.yaml&lt;/span&gt;

&lt;span class="na"&gt;vars&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;foreground&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$$white&lt;/span&gt;
  &lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$$black&lt;/span&gt;
  &lt;span class="na"&gt;accent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$$purple&lt;/span&gt;
  &lt;span class="na"&gt;accentSecondary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$$red&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  solar-flare.yaml
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;$schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vscode://schemas/color-theme&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Solar Flare&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;light&lt;/span&gt;

  &lt;span class="na"&gt;import&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./palette.yaml&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./shared.yaml&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./colors.yaml&lt;/span&gt;

&lt;span class="na"&gt;vars&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;foreground&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$$black&lt;/span&gt;         &lt;span class="c1"&gt;# see?&lt;/span&gt;
  &lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$$white&lt;/span&gt;         &lt;span class="c1"&gt;# see2?&lt;/span&gt;
  &lt;span class="na"&gt;accent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$$red&lt;/span&gt;               &lt;span class="c1"&gt;# see3?&lt;/span&gt;
  &lt;span class="na"&gt;accentSecondary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$$purple&lt;/span&gt;   &lt;span class="c1"&gt;# see4?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Just the tip
&lt;/h2&gt;

&lt;p&gt;I don't want to risk making this a super long article about a niche product that nobody cares about, this is just the tip. Below is a full feature list at the time of the writing of this journal entry.&lt;/p&gt;

&lt;p&gt;In addition to all of this, you can see everything, including full documentation, examples, walk through, Theme School, testimonials at &lt;a href="https://sassy.gesslar.io" rel="noopener noreferrer"&gt;sassy&lt;/a&gt;'s website.&lt;/p&gt;

&lt;p&gt;This is a personal passion project and it is released under the Unlicense. Do what you want, idc.&lt;/p&gt;

&lt;h3&gt;
  
  
  More than just the tip
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;takes a deep breath and starts rambling off features in his best auctioneer impression&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Sassy — Feature Inventory
&lt;/h4&gt;

&lt;h5&gt;
  
  
  Authoring Formats
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;YAML Input&lt;/strong&gt; — Write themes in clean, human-readable YAML&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JSON5 Input&lt;/strong&gt; — Write themes in JSON5 with comments and trailing commas&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mixed Format Ecosystem&lt;/strong&gt; — Import YAML from JSON5 or vice versa — they compose freely&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Variable System
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Palette Layer&lt;/strong&gt; — Define raw colour values in an isolated, self-contained palette scope&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vars Layer&lt;/strong&gt; — Build semantic meaning on top of palette with a dedicated variable layer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nested Variables&lt;/strong&gt; — Define deeply nested variable hierarchies with dot-path addressing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Three Reference Syntaxes&lt;/strong&gt; — &lt;code&gt;$(var)&lt;/code&gt;, &lt;code&gt;$var&lt;/code&gt;, &lt;code&gt;${var}&lt;/code&gt; — pick the style that fits the context&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Palette Aliases&lt;/strong&gt; — &lt;code&gt;$$name&lt;/code&gt; shorthand auto-expands to &lt;code&gt;$(palette.name)&lt;/code&gt; for concise palette references&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-Layer References&lt;/strong&gt; — Variables can reference other variables, palette entries, and theme values&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recursive Resolution&lt;/strong&gt; — Multi-pass evaluation engine resolves chained variable references automatically&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Circular Dependency Detection&lt;/strong&gt; — Catches self-referential or looping variable chains before they hang&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Colour Functions
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;lighten / darken&lt;/strong&gt; — Perceptually uniform brightness adjustments via OKLCH&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;mix&lt;/strong&gt; — Blend two colours at any ratio with OKLCH interpolation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;alpha&lt;/strong&gt; — Set exact transparency on any colour&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;fade / solidify&lt;/strong&gt; — Relative opacity adjustments — reduce or increase alpha proportionally&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;invert&lt;/strong&gt; — Flip lightness while preserving hue and saturation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;saturate / desaturate&lt;/strong&gt; — Adjust chroma intensity in OKLCH space&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;mute / pop&lt;/strong&gt; — Semantic aliases for desaturation and saturation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;tint / shade&lt;/strong&gt; — Mix toward white or black by a given percentage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;shiftHue&lt;/strong&gt; — Rotate hue by arbitrary degrees&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;complement&lt;/strong&gt; — 180° hue shift in one call&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;grayscale&lt;/strong&gt; — Strip all chroma for a perceptually accurate greyscale&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;contrast&lt;/strong&gt; — Returns black or white, whichever has better contrast against the input&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;css()&lt;/strong&gt; — Use any CSS named colour (&lt;code&gt;css(tomato)&lt;/code&gt;, &lt;code&gt;css(deepskyblue)&lt;/code&gt;, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Composable Functions&lt;/strong&gt; — Nest function calls inside each other: &lt;code&gt;fade(lighten($(bg), 20), 0.5)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Colour Space Support
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hex&lt;/strong&gt; — &lt;code&gt;#rgb&lt;/code&gt;, &lt;code&gt;#rrggbb&lt;/code&gt;, &lt;code&gt;#rrggbbaa&lt;/code&gt; — with short-form auto-expansion&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RGB / RGBA&lt;/strong&gt; — &lt;code&gt;rgb(r, g, b)&lt;/code&gt; and &lt;code&gt;rgba(r, g, b, a)&lt;/code&gt; constructors&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HSL / HSLA&lt;/strong&gt; — &lt;code&gt;hsl(h, s, l)&lt;/code&gt; and &lt;code&gt;hsla(h, s, l, a)&lt;/code&gt; constructors&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HSV / HSVA&lt;/strong&gt; — &lt;code&gt;hsv(h, s, v)&lt;/code&gt; and &lt;code&gt;hsva(h, s, v, a)&lt;/code&gt; constructors&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OKLCH / OKLCHA&lt;/strong&gt; — Perceptually uniform colour space for professional palette design&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Any Culori Format&lt;/strong&gt; — LAB, LCH, HWB, Display P3, Rec. 2020 — if Culori parses it, Sassy compiles it&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-Space Mixing&lt;/strong&gt; — Freely combine colours from different spaces in the same theme&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alpha Preservation&lt;/strong&gt; — Hex alpha channels are tracked and preserved through transformations&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Import &amp;amp; Composition
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;File Imports&lt;/strong&gt; — Pull in external YAML/JSON5 files via &lt;code&gt;config.import&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deep Object Merging&lt;/strong&gt; — Palette, vars, colors, semanticTokenColors merge by deep key override&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Append-Only tokenColors&lt;/strong&gt; — Imported tokenColors prepend, your file's rules append — correct precedence by default&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-File Import Chains&lt;/strong&gt; — Import as many files as needed, merged in declaration order&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modular Theme Architecture&lt;/strong&gt; — Split palettes, variables, UI colours, syntax rules, and semantics into separate files&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shared Palettes&lt;/strong&gt; — One palette file, many theme variants&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Import Paths&lt;/strong&gt; — Use variables in import paths: &lt;code&gt;./import/palette-$(type).yaml&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Séance Operator
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Prior Value References&lt;/strong&gt; — &lt;code&gt;^&lt;/code&gt; references the same key's value from a previously imported file&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Derived Variants&lt;/strong&gt; — Create "hushed", "vivid", or any theme variant by transforming inherited values: &lt;code&gt;shade(^, 25)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-Layer Séance&lt;/strong&gt; — Chain through multiple import layers with automatic versioned tracking&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Theme Sections
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;colors&lt;/strong&gt; — Full support for VS Code workbench colour properties&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;tokenColors&lt;/strong&gt; — TextMate-style syntax highlighting rules with scope selectors&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;semanticTokenColors&lt;/strong&gt; — Semantic token colour definitions for language-aware highlighting&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;config.custom&lt;/strong&gt; — Pass-through block for arbitrary VS Code properties like &lt;code&gt;semanticHighlighting: true&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;config.$schema&lt;/strong&gt; — Embed the VS Code colour theme schema reference in output&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  CLI — Build Command
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Single or Multi-File Builds&lt;/strong&gt; — Compile one or many theme files in a single invocation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Watch Mode&lt;/strong&gt; — Live recompilation on file save with automatic dependency tracking&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependency-Aware Watching&lt;/strong&gt; — Edits to any imported file trigger a rebuild of the parent theme&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom Output Directory&lt;/strong&gt; — Route compiled output wherever you want with &lt;code&gt;--output-dir&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dry Run&lt;/strong&gt; — Print compiled JSON to stdout without writing any files&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Silent Mode&lt;/strong&gt; — Suppress all output except errors — ideal for scripts and CI&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nerd Mode&lt;/strong&gt; — Verbose error traces with full stack context for debugging&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive Watch Controls&lt;/strong&gt; — &lt;code&gt;F5&lt;/code&gt; to force rebuild, &lt;code&gt;Ctrl-C&lt;/code&gt; to quit — with a live prompt&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hash-Based Skip&lt;/strong&gt; — SHA-256 output comparison prevents unnecessary file writes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Graceful Signal Handling&lt;/strong&gt; — Clean shutdown on SIGINT, SIGTERM, SIGHUP&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  CLI — Resolve Command
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Color Resolution&lt;/strong&gt; — Trace any &lt;code&gt;colors.*&lt;/code&gt; property through its full variable chain&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;tokenColor Resolution&lt;/strong&gt; — Resolve any TextMate scope to its final foreground value&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;semanticTokenColor Resolution&lt;/strong&gt; — Resolve any semantic token scope to its final value&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full Resolution Trail&lt;/strong&gt; — See every substitution step from raw expression to final hex&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scope Disambiguation&lt;/strong&gt; — When a scope appears in multiple rules, lists all matches with selectable qualifiers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Precedence-Aware Resolution&lt;/strong&gt; — Shows when a broader scope masks your specific one&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Colour Swatches&lt;/strong&gt; — Truecolour terminal swatches next to resolved hex values&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alpha Compositing Preview&lt;/strong&gt; — &lt;code&gt;--bg&lt;/code&gt; flag composites transparent colours against a background for preview&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  CLI — Proof Command
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Composed Document View&lt;/strong&gt; — See the fully merged theme document after all imports, overrides, and séance are applied — before any evaluation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Séance Inlining&lt;/strong&gt; — &lt;code&gt;^&lt;/code&gt; operators replaced with the actual prior values so the output reads naturally: &lt;code&gt;shade(#4b8ebd, 25)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;YAML Output&lt;/strong&gt; — Outputs in the authoring language, not the compiled format — stays in your world&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Import-Free Output&lt;/strong&gt; — Imports are resolved and merged; the &lt;code&gt;import&lt;/code&gt; key is gone — what you see is what the engine sees&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aerial Debugging&lt;/strong&gt; — Orient yourself in a layered theme before reaching for &lt;code&gt;resolve&lt;/code&gt; — the map before the dig&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  CLI — Lint Command
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Duplicate Scope Detection&lt;/strong&gt; — Finds TextMate scopes that appear in multiple tokenColors rules&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Undefined Variable Detection&lt;/strong&gt; — Catches references to variables that don't exist&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unused Variable Detection&lt;/strong&gt; — Identifies vars defined but never referenced in theme content&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scope Precedence Analysis&lt;/strong&gt; — Warns when a broad scope masks a more specific one due to rule ordering&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-Section Linting&lt;/strong&gt; — Validates variables in colors, tokenColors, and semanticTokenColors&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strict Mode&lt;/strong&gt; — &lt;code&gt;--strict&lt;/code&gt; treats warnings as errors for CI enforcement&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Severity Levels&lt;/strong&gt; — Issues categorised as high/medium/low with colour-coded terminal output&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Import-Aware Analysis&lt;/strong&gt; — Lints across all imported files, not just the main theme&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Output
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;VS Code &lt;code&gt;.color-theme.json&lt;/code&gt;&lt;/strong&gt; — Standard output format, ready for use in VS Code extensions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic Output&lt;/strong&gt; — Same input always produces the same output&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pretty-Printed JSON&lt;/strong&gt; — 2-space indented, human-readable output&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic File Naming&lt;/strong&gt; — &lt;code&gt;my-theme.yaml&lt;/code&gt; → &lt;code&gt;my-theme.color-theme.json&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Architecture &amp;amp; Performance
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Compose-Then-Evaluate Pipeline&lt;/strong&gt; — Shared composition step (import → merge → séance) feeds both &lt;code&gt;compile&lt;/code&gt; and &lt;code&gt;proof&lt;/code&gt; — one source of truth, two consumers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Phase-Based Compilation&lt;/strong&gt; — Compose → decompose → evaluate → resolve → assemble — clean, predictable pipeline&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File Caching&lt;/strong&gt; — Imported files are cached and reused across themes in the same session&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Colour Caching&lt;/strong&gt; — Parsed colours and mix results are memoised for repeat calls&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OKLCH-Native Operations&lt;/strong&gt; — Lighten, darken, mix, and saturate all work in perceptually uniform space&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured Error Reporting&lt;/strong&gt; — Chained error contexts with &lt;code&gt;.trace()&lt;/code&gt; for precise failure diagnostics&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Max-Iteration Guards&lt;/strong&gt; — Bounded resolution passes prevent runaway compilation&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Programmatic API
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ES Module Exports&lt;/strong&gt; — &lt;code&gt;import { Theme, Compiler, Colour, LintCommand } from '@gesslar/sassy'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full Class Access&lt;/strong&gt; — Theme, Compiler, Evaluator, Session, Colour, and all command classes are importable&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embeddable Compilation&lt;/strong&gt; — Build themes programmatically without the CLI&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Proof API&lt;/strong&gt; — Retrieve the composed, unevaluated theme structure for external tooling&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lint API&lt;/strong&gt; — Run lint checks and get structured results for external tooling&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resolve API&lt;/strong&gt; — Programmatically resolve tokens and get structured resolution data&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Developer Experience
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero-Install Usage&lt;/strong&gt; — &lt;code&gt;npx @gesslar/sassy build&lt;/code&gt; — no global install required&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TypeScript Definitions&lt;/strong&gt; — Auto-generated &lt;code&gt;.d.ts&lt;/code&gt; files from JSDoc for editor support&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docusaurus Documentation Site&lt;/strong&gt; — Full docs at sassy.gesslar.io&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example Themes&lt;/strong&gt; — Simple and advanced examples included in the repository&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unlicense&lt;/strong&gt; — Use however you want — no restrictions&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>vscode</category>
      <category>themes</category>
      <category>javascript</category>
      <category>node</category>
    </item>
    <item>
      <title>Signal on Fedora? gtfo</title>
      <dc:creator>gesslar</dc:creator>
      <pubDate>Wed, 17 Dec 2025 15:46:07 +0000</pubDate>
      <link>https://forem.com/gesslar/signal-on-fedora-gtfo-k3f</link>
      <guid>https://forem.com/gesslar/signal-on-fedora-gtfo-k3f</guid>
      <description>&lt;p&gt;Hi.&lt;/p&gt;

&lt;p&gt;Do you love AppImages? Awesome!&lt;/p&gt;

&lt;p&gt;I don't.&lt;/p&gt;

&lt;p&gt;I get it... portability, some kind of immutability, sure, but lack of availability shouldn't be insurmountable.&lt;/p&gt;

&lt;p&gt;I recently distrohopped from Kubuntu to Fedora and was trying to figure out how to get Signal installed.&lt;/p&gt;

&lt;p&gt;Only to discover- Signal doesn't provide an .rpm.&lt;/p&gt;

&lt;p&gt;🤨&lt;/p&gt;

&lt;p&gt;It does occur from time to time that a software distribution channel is excluded, but I didn't anticipate it would be something so widely used as Signal.&lt;/p&gt;

&lt;p&gt;I Googled and I Googled and I found ... &lt;a href="https://www.reddit.com/r/Fedora/comments/1ojjx3p/reminder_how_to_install_official_signal_desktop/" rel="noopener noreferrer"&gt;what the fuck is distrobox&lt;/a&gt;??&lt;/p&gt;

&lt;p&gt;Ok, so I read through the instructions and they seemed... easy, even if said instructions definitely needed cleaning up. Put a distrobox on my box and then do a few things and boom? That was super appealing.&lt;/p&gt;

&lt;p&gt;But I was also like... meeeh containers. Containers to me have always felt like a promise that didn't quite deliver in my space. Don't get me wrong, they're awesome for a great number of use cases, but anecdotally, they never fail to feel like a TUI VM with hexagrams, weird sacrifices, and -FlaGs that when accurately pronounced will unseal a mimic, or worse, summon a butterscotch pudding.&lt;/p&gt;

&lt;p&gt;So I gave it a shot.&lt;/p&gt;

&lt;p&gt;And now I've leveled up not only my application game, but also my knowledge game, and like a good netizen (that's still a thing, right? we're still saying that?) I thought to bring you a gift.&lt;/p&gt;

&lt;p&gt;Yes, &lt;em&gt;you&lt;/em&gt;, bestie. Duh.&lt;/p&gt;

&lt;p&gt;I have this in a markdown, but you probably don't have my hand-rolled markdown reader that doubles as a not-browser-not-IDE-not-editor-with-markdown-preview-functionality markdown reader, so I'll just paste it below.&lt;/p&gt;

&lt;p&gt;It does come with a small caveat which I feel obligated to disclose: It's not really that nerdy. It's just a couple of steps and you have Signal on Fedora. Also, the pattern is repeatable for anything else. Also, if you don't like doing it all in chunks, you can also just grab the final boss and throw it at your terminal and probably maybe you'll get Signal in Fedora. OK, now that I have &lt;em&gt;that&lt;/em&gt; off my chest, here you: my copy pasta.&lt;/p&gt;

&lt;p&gt;-----BEGIN MARKDOWN MESSAGE-----&lt;/p&gt;

&lt;h1&gt;
  
  
  Install Official Signal Desktop in Fedora
&lt;/h1&gt;

&lt;p&gt;If you want the &lt;strong&gt;official Signal Desktop client&lt;/strong&gt; on Fedora, the simplest supported approach is to run it inside a Debian/Debian-flavoured container using &lt;strong&gt;&lt;a href="https://distrobox.it" rel="noopener noreferrer"&gt;Distrobox&lt;/a&gt;&lt;/strong&gt; and export it to your desktop menu.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Install Distrobox on Fedora:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;dnf &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; distrobox
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create and enter a Distrobox container
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Debian
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;distrobox create &lt;span class="nt"&gt;-n&lt;/span&gt; Debian &lt;span class="nt"&gt;-i&lt;/span&gt; debian:12
distrobox enter Debian &lt;span class="nt"&gt;-nw&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Ubuntu
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;distrobox create &lt;span class="nt"&gt;-n&lt;/span&gt; Ubuntux &lt;span class="nt"&gt;-i&lt;/span&gt; ubuntu &lt;span class="nt"&gt;-ap&lt;/span&gt; libasound2t64
distrobox enter Ubuntux &lt;span class="nt"&gt;-nw&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You are now &lt;strong&gt;inside the container&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install Signal Desktop (inside the container)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Add Signal’s signing key
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;
  &lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"Downloading and adding Signal signing key..."&lt;/span&gt;
  wget &lt;span class="nt"&gt;-qO-&lt;/span&gt; https://updates.signal.org/desktop/apt/keys.asc &lt;span class="se"&gt;\&lt;/span&gt;
    | gpg &lt;span class="nt"&gt;--dearmor&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /usr/share/keyrings/signal-desktop-keyring.gpg &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null
  &lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"Signal signing key downloaded and added."&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Add the Signal APT respository
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;
  &lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"Downloading and adding APT respository source..."&lt;/span&gt;
  &lt;span class="nb"&gt;sudo &lt;/span&gt;wget &lt;span class="nt"&gt;-qO&lt;/span&gt; /etc/apt/sources.list.d/signal-desktop.sources &lt;span class="se"&gt;\&lt;/span&gt;
    https://updates.signal.org/static/desktop/apt/signal-desktop.sources
  &lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"Signal APT respository source downloaded and added."&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Install Signal Desktop
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;
  &lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"Installing Signal..."&lt;/span&gt;
  &lt;span class="c"&gt;# Let's just shove the stdout to /yeet. We'll still get error messages.&lt;/span&gt;
  &lt;span class="c"&gt;# Is cool.&lt;/span&gt;
  &lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update 1&amp;gt;/dev/null
  &lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; signal-desktop 1&amp;gt;/dev/null
  &lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"Signal installed."&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Export Signal to the Fedora app menu
&lt;/h2&gt;

&lt;p&gt;Still inside the container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;distrobox-export &lt;span class="nt"&gt;--app&lt;/span&gt; signal-desktop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Signal will now appear in your &lt;strong&gt;host system’s application menu&lt;/strong&gt; like a proper citizen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exit the container
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Notes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Signal data is stored in:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  ~/.config/Signal/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;This directory is shared between the container and the Fedora host.&lt;/li&gt;
&lt;li&gt;The container can be reused for other Debian-only apps if desired.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You now have &lt;strong&gt;official Signal Desktop&lt;/strong&gt; running on Fedora without Flatpak weirdness,&lt;br&gt;
Snap side-eye, or AppImage nonsense.&lt;/p&gt;

&lt;h3&gt;
  
  
  All together now!
&lt;/h3&gt;

&lt;p&gt;Or, just grab it and throw it all in at once! Nice, self-contained, all-in-oners. Paste and go!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Minor differences because now we're running in a non-interactive shell via heredoc. But, it's fine. You'll be fine.&lt;/em&gt; 😇&lt;/p&gt;

&lt;h4&gt;
  
  
  Debian in One
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;
  &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail

  &lt;span class="nb"&gt;sudo &lt;/span&gt;dnf &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; distrobox 2&amp;gt;/dev/null

  &lt;span class="nv"&gt;NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Debian"&lt;/span&gt;
  &lt;span class="nv"&gt;DISTRO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"debian:12"&lt;/span&gt;

  &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PACKAGES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"signal-desktop"&lt;/span&gt;

  distrobox create &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nv"&gt;$NAME&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nv"&gt;$DISTRO&lt;/span&gt;
  distrobox enter &lt;span class="nv"&gt;$NAME&lt;/span&gt; &lt;span class="nt"&gt;-nw&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; bash &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="no"&gt;DONESIES&lt;/span&gt;&lt;span class="sh"&gt;"
#!/usr/bin/env bash

printf "&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;" "Downloading and adding Signal signing key..."
wget -qO- https://updates.signal.org/desktop/apt/keys.asc &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="sh"&gt;
  | gpg --dearmor &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="sh"&gt;
  | sudo tee /usr/share/keyrings/signal-desktop-keyring.gpg &amp;gt; /dev/null
printf "%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;" "Signal signing key downloaded and added."

printf "&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;" "Downloading and adding APT respository source..."
sudo wget -qO /etc/apt/sources.list.d/signal-desktop.sources &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="sh"&gt;
  https://updates.signal.org/static/desktop/apt/signal-desktop.sources
printf "%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;" "Signal APT respository source downloaded and added."

printf "&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;" "Installing Signal..."
# Let's just shove the stdout to /yeet. We'll still get error messages.
# Is cool.
sudo apt-get update 1&amp;gt;/dev/null
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y &lt;/span&gt;&lt;span class="nv"&gt;$PACKAGES&lt;/span&gt;&lt;span class="sh"&gt; 1&amp;gt;/dev/null
printf "%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;" "Signal installed."

distrobox-export --app signal-desktop
&lt;/span&gt;&lt;span class="no"&gt;DONESIES
&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Ubuntu in One
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;
  &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail

  &lt;span class="nb"&gt;sudo &lt;/span&gt;dnf &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; distrobox 2&amp;gt;/dev/null

  &lt;span class="nv"&gt;NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Ubuntu"&lt;/span&gt;
  &lt;span class="nv"&gt;DISTRO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"ubuntu"&lt;/span&gt;

  &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PACKAGES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"libasound2t64 signal-desktop"&lt;/span&gt;

  distrobox create &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nv"&gt;$NAME&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nv"&gt;$DISTRO&lt;/span&gt;
  distrobox enter &lt;span class="nv"&gt;$NAME&lt;/span&gt; &lt;span class="nt"&gt;-nw&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; bash &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="no"&gt;DONESIES&lt;/span&gt;&lt;span class="sh"&gt;"
#!/usr/bin/env bash

printf "&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;" "Downloading and adding Signal signing key..."
wget -qO- https://updates.signal.org/desktop/apt/keys.asc &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="sh"&gt;
  | gpg --dearmor &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="sh"&gt;
  | sudo tee /usr/share/keyrings/signal-desktop-keyring.gpg &amp;gt; /dev/null
printf "%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;" "Signal signing key downloaded and added."

printf "&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;" "Downloading and adding APT respository source..."
sudo wget -qO /etc/apt/sources.list.d/signal-desktop.sources &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="sh"&gt;
  https://updates.signal.org/static/desktop/apt/signal-desktop.sources
printf "%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;" "Signal APT respository source downloaded and added."

printf "&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;" "Installing Signal..."
# Let's just shove the stdout to /yeet. We'll still get error messages.
# Is cool.
sudo apt-get update 1&amp;gt;/dev/null
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y &lt;/span&gt;&lt;span class="nv"&gt;$PACKAGES&lt;/span&gt;&lt;span class="sh"&gt; 1&amp;gt;/dev/null
printf "%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;" "Signal installed."

distrobox-export --app signal-desktop
&lt;/span&gt;&lt;span class="no"&gt;DONESIES
&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🇨🇦 Cautionary 🇨🇦
&lt;/h2&gt;

&lt;p&gt;Before you embarass yourself, please understand that not everybody in the world spells the same as you. Further, understand that different nations have entirely different grammars from you.&lt;/p&gt;

&lt;p&gt;Before you come for me, take a moment to consider that Canada is its own domain and is permitted, as such, to choose its own spellings.&lt;/p&gt;

&lt;p&gt;Colour.&lt;br&gt;
Rancour.&lt;br&gt;
Beavour.&lt;br&gt;
Respository.&lt;br&gt;
Suspository.&lt;/p&gt;

&lt;p&gt;You get it. You're smarter than that. This entire section was unnecessary.&lt;/p&gt;

&lt;p&gt;🤗&lt;/p&gt;

&lt;p&gt;-----END MARKDOWN MESSAGE-----&lt;/p&gt;

&lt;p&gt;Nice, okay. That's over.&lt;/p&gt;

&lt;p&gt;You know what? I still don't like containers. Well, that's not true, I don't &lt;em&gt;love&lt;/em&gt; containers. But what I got out of this journey (is it still a journey if it took like 5 minutes to do?) was not just another sidequest (girl, you know I loves me some sidequests (maybe you're not a girl (but also maybe you don't know that I loves me some sidequests (we're all learning something today)))), but, OK you know what? I got me some sidequest that disentangentially rewarded me with getting what I wanted and not having to deal with containers, while simultaneously, although transparently, dealing with containers.&lt;/p&gt;

&lt;p&gt;So, everybody wins. And the prize is: no butterscotch pudding.&lt;/p&gt;

&lt;p&gt;You're welcome.&lt;/p&gt;

</description>
      <category>signal</category>
      <category>fedora</category>
      <category>distrobox</category>
      <category>christinaricci</category>
    </item>
    <item>
      <title>From MUD Colours to Modern Terminals: A Bash Colour Library That Actually Makes Sense</title>
      <dc:creator>gesslar</dc:creator>
      <pubDate>Mon, 04 Aug 2025 16:23:54 +0000</pubDate>
      <link>https://forem.com/gesslar/from-mud-colours-to-modern-terminals-a-bash-colour-library-that-actually-makes-sense-ln</link>
      <guid>https://forem.com/gesslar/from-mud-colours-to-modern-terminals-a-bash-colour-library-that-actually-makes-sense-ln</guid>
      <description>&lt;p&gt;&lt;em&gt;Or: How I brought shell scripting from 1975 into 1995.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: ANSI Escape Codes Are Tedious AF
&lt;/h2&gt;

&lt;p&gt;Let's be honest - working with terminal colours in bash is painful. You either memorise cryptic escape sequences like &lt;code&gt;\033[38;5;196m&lt;/code&gt; or constantly look them up. Want to make something bright AND red? Hope you enjoy typing &lt;code&gt;\033[1;38;5;196m&lt;/code&gt;&lt;br&gt;
every time.&lt;/p&gt;

&lt;p&gt;As someone who comes from MUD development, I am accustomed to simple colour tokens like &lt;code&gt;%^RED%^&lt;/code&gt; or &lt;code&gt;%^RESET%^&lt;/code&gt;. Why couldn't shell scripts be that elegant?&lt;/p&gt;

&lt;p&gt;How many have&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;cheat sheets for commonly used ANSI sequences? or&lt;/li&gt;
&lt;li&gt;bookmarks to &lt;a href="https://wikipedia.org/wiki/ANSI_escape_code" rel="noopener noreferrer"&gt;ANSI escape code&lt;/a&gt;??&lt;/li&gt;
&lt;li&gt;a litany of shell scripts to reference as previous examples on how to do a colour???&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Just me? &lt;em&gt;All right.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The Old Solution
&lt;/h2&gt;

&lt;p&gt;So we came up with shortcuts to use colours because early on, we decided we collectively disliked the idea of typing bare ANSI sequences everywhere. And, as a solution, we decided on this norm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Colours for output&lt;/span&gt;
&lt;span class="nv"&gt;RED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\033[0;31m'&lt;/span&gt;
&lt;span class="nv"&gt;GREEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\033[0;32m'&lt;/span&gt;
&lt;span class="nv"&gt;YELLOW&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\033[1;33m'&lt;/span&gt;
&lt;span class="nv"&gt;BLUE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\033[0;34m'&lt;/span&gt;
&lt;span class="nv"&gt;NC&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\033[0m'&lt;/span&gt; &lt;span class="c"&gt;# No Colour, reset everything to default.&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;RED&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;✗ Error: Something went wrong&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NC&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GREEN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;✓ Success: Operation completed&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NC&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;YELLOW&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;⚠ Warning: Check your input&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NC&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes, this is perfectly fine. And I don't hate this pattern, and I think it's definitely a mostly portable way to achieve it. There are other ways, that are even more portable, but the above is fairly typical nowadays. At least, that's what I see most commonly. YMMV, YEMV, YEET.&lt;/p&gt;

&lt;p&gt;Anyway, while I don't &lt;em&gt;hate&lt;/em&gt; it, I don't &lt;em&gt;love&lt;/em&gt; it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: Meet &lt;code&gt;colours&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;So I built a tiny bash library that makes terminal colours actually pleasant to use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash -i&lt;/span&gt;

&lt;span class="nb"&gt;.&lt;/span&gt; ~/bin/colours

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;F 196&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;This is red text&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;RST&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;F 046&lt;span class="si"&gt;)$(&lt;/span&gt;B 196&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;Green text on red background&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;RST&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;S BI&lt;span class="si"&gt;)$(&lt;/span&gt;F 220&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;Bright italic yellow text&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;RST&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Clean, readable, and you can actually remember the function names. And with frequent usage, as we do in the MUD community, you begin to remember the colour codes you prefer and/or frequently use! Way easier to build muscle memory in the brain. Or, what limited amount remains for us old-timer-MUDders.&lt;/p&gt;

&lt;h2&gt;
  
  
  The API: Short and Sweet
&lt;/h2&gt;

&lt;p&gt;The whole library is just 5 functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;F(n)&lt;/code&gt;&lt;/strong&gt; - Set foreground colour (0-255)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;B(n)&lt;/code&gt;&lt;/strong&gt; - Set background colour (0-255)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;S(codes)&lt;/code&gt;&lt;/strong&gt; - Composably set styles (&lt;code&gt;B&lt;/code&gt;old, &lt;code&gt;I&lt;/code&gt;talic, &lt;code&gt;U&lt;/code&gt;nderline, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;U(codes)&lt;/code&gt;&lt;/strong&gt; - Composably unset specific styles&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;RST()&lt;/code&gt;&lt;/strong&gt; - Reset everything&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Want bright italic underlined text? Just &lt;code&gt;$(S BIU)&lt;/code&gt;. Want to turn off just the italic? &lt;code&gt;$(U I)&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is it portable?
&lt;/h3&gt;

&lt;p&gt;lol, no. But I don't need portability for my scripts. Portable is definitely important for numerous use cases, but not in any of mine. Maybe someone will take it and make a portable version, or maybe there is already a portable version that is better that someone else wrote, I don't know.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Secret &lt;del&gt;Sauce&lt;/del&gt; Source: Dual Purpose Design
&lt;/h2&gt;

&lt;p&gt;Here's the fun bit - &lt;code&gt;colours&lt;/code&gt; works as both a library AND a colour picker.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;As a library&lt;/strong&gt;: Source it in your scripts for the API&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$COLOURISER&lt;/span&gt;  &lt;span class="c"&gt;# I set this in my .bashrc&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;F 219&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;Pretty colours!&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;RST&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;As a colour picker&lt;/strong&gt;: Run it directly to see all 256 colours with their numbers&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;colours
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkc5x2gh8p9sndjs50wan.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkc5x2gh8p9sndjs50wan.png" alt="Colours" width="732" height="845"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No more guessing which shade of blue is colour 75 vs 81. Just run it, pick the number you want, done.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Usage
&lt;/h2&gt;

&lt;p&gt;I use this in all my utility scripts now. Compare these two approaches:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before&lt;/strong&gt; (the bad old days):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\0&lt;/span&gt;&lt;span class="s2"&gt;33[32m✓ Success&lt;/span&gt;&lt;span class="se"&gt;\0&lt;/span&gt;&lt;span class="s2"&gt;33[0m"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\0&lt;/span&gt;&lt;span class="s2"&gt;33[31m✗ Failed&lt;/span&gt;&lt;span class="se"&gt;\0&lt;/span&gt;&lt;span class="s2"&gt;33[0m"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\0&lt;/span&gt;&lt;span class="s2"&gt;33[33m⚠ Warning&lt;/span&gt;&lt;span class="se"&gt;\0&lt;/span&gt;&lt;span class="s2"&gt;33[0m"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After&lt;/strong&gt; (living in the future):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;F 46&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;✓ Success&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;RST&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;F 196&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;✗ Failed&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;RST&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;F 220&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;⚠ Warning&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;RST&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So much cleaner! And when I want to change the exact shade of green, I just run &lt;code&gt;colours&lt;/code&gt;, pick a new number, and update one digit.&lt;/p&gt;

&lt;h2&gt;
  
  
  The MUD Heritage
&lt;/h2&gt;

&lt;p&gt;This design comes from years of MUD development where colour codes need to be:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Fast to type&lt;/strong&gt; (you use them constantly)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easy to read&lt;/strong&gt; (mixed with lots of text)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memorable&lt;/strong&gt; (no looking up codes)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Turns out these same principles make shell scripting way more pleasant too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get It
&lt;/h2&gt;

&lt;p&gt;Because life's too short for &lt;code&gt;echo -e "\033[1;38;5;196;48;5;21m"&lt;/code&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What's your favourite terminal colour? Mine's 38 - a lovely blue that makes shell messages feel less hostile.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Script
&lt;/h2&gt;

&lt;h3&gt;
  
  
  License
&lt;/h3&gt;

&lt;p&gt;This script is released under the &lt;a href="https://unlicense.org/" rel="noopener noreferrer"&gt;Unlicense&lt;/a&gt; because idgaf. Below is it, in all of its splendour and gloury. 🇨🇦&lt;/p&gt;

&lt;h3&gt;
  
  
  Behold
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash -i&lt;/span&gt;

&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail

&lt;span class="c"&gt;# colours - 256 Colour Terminal Display and Library Script&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# Clean grid with actual colour numbers for use in other scripts&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# Copyright: nope&lt;/span&gt;
&lt;span class="c"&gt;# Warranty: heh&lt;/span&gt;
&lt;span class="c"&gt;# License: The Unlicense (https://unlicense.org/)&lt;/span&gt;
&lt;span class="c"&gt;# - With love from gesslar and Claude 🥰 - 2025&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# Usage: colours                    - Display colour chart&lt;/span&gt;
&lt;span class="c"&gt;#        source colours             - Load colour functions into shell&lt;/span&gt;
&lt;span class="c"&gt;#        $COLOURISER                - Use via environment variable&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# Functions provided when sourced:&lt;/span&gt;
&lt;span class="c"&gt;#   RST()     - Reset all formatting&lt;/span&gt;
&lt;span class="c"&gt;#   F(n)      - Set foreground colour (0-255)&lt;/span&gt;
&lt;span class="c"&gt;#   B(n)      - Set background colour (0-255)&lt;/span&gt;
&lt;span class="c"&gt;#   S(codes)  - Set styles (B=bright, I=italic, U=underline, L=blink, R=reverse, S=strikethrough)&lt;/span&gt;
&lt;span class="c"&gt;#   U(codes)  - Unset styles&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# Setup Instructions:&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# 1. Create an environment variable in your main shell script (ex: .bashrc)&lt;/span&gt;
&lt;span class="c"&gt;#    pointing to this file. Example:&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;#     bash-like: export COLOURISER=". ~/bin/colours"&lt;/span&gt;
&lt;span class="c"&gt;#     fish-like: set -gx COLOURISER ". $(realpath ~/bin/colours)"&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# 2. Execute this script at the top of your script to bring in the colour&lt;/span&gt;
&lt;span class="c"&gt;#    functions. Example:&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;#     #!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;#     $COLOURISER&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;#     echo "$(F 219)This is foreground colour 219$(RST)"&lt;/span&gt;
&lt;span class="c"&gt;#     echo "$(B 196)This is bright red background$(RST)"&lt;/span&gt;
&lt;span class="c"&gt;#     echo "$(F 046)$(B 196)Green text on red background$(RST)"&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# 3. 💰💰💰💰💰💰💰&lt;/span&gt;

&lt;span class="c"&gt;# #############################################################################&lt;/span&gt;
&lt;span class="c"&gt;# Main colour functions&lt;/span&gt;
&lt;span class="c"&gt;# #############################################################################&lt;/span&gt;

&lt;span class="c"&gt;# Reset function ##############################################################&lt;/span&gt;
RST&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; &lt;span class="s1"&gt;'\033[0m'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Foreground colour function ##################################################&lt;/span&gt;
F&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\0&lt;/span&gt;&lt;span class="s2"&gt;33[38;5;&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;m"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Background colour function ##################################################&lt;/span&gt;
B&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\0&lt;/span&gt;&lt;span class="s2"&gt;33[48;5;&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;m"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Style function that accepts multiple codes ##################################&lt;/span&gt;
S&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;codes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;

  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt; &lt;span class="nv"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0&lt;span class="p"&gt;;&lt;/span&gt; i&amp;lt;&lt;span class="k"&gt;${#&lt;/span&gt;&lt;span class="nv"&gt;codes&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; i++ &lt;span class="o"&gt;))&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    case&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;codes&lt;/span&gt;:&lt;span class="nv"&gt;$i&lt;/span&gt;:1&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in
      &lt;/span&gt;B&lt;span class="p"&gt;)&lt;/span&gt; output+&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\033[1m'&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;    &lt;span class="c"&gt;# Bright&lt;/span&gt;
      D&lt;span class="p"&gt;)&lt;/span&gt; output+&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\033[2m'&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;    &lt;span class="c"&gt;# Dim&lt;/span&gt;
      I&lt;span class="p"&gt;)&lt;/span&gt; output+&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\033[3m'&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;    &lt;span class="c"&gt;# Italic&lt;/span&gt;
      U&lt;span class="p"&gt;)&lt;/span&gt; output+&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\033[4m'&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;    &lt;span class="c"&gt;# Underline&lt;/span&gt;
      L&lt;span class="p"&gt;)&lt;/span&gt; output+&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\033[5m'&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;    &lt;span class="c"&gt;# Blink&lt;/span&gt;
      R&lt;span class="p"&gt;)&lt;/span&gt; output+&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\033[7m'&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;    &lt;span class="c"&gt;# Reverse&lt;/span&gt;
      S&lt;span class="p"&gt;)&lt;/span&gt; output+&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\033[9m'&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;    &lt;span class="c"&gt;# Strikethrough&lt;/span&gt;
    &lt;span class="k"&gt;esac&lt;/span&gt;
  &lt;span class="k"&gt;done

  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$output&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Unset/turn off specific styles ##############################################&lt;/span&gt;
U&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;codes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;

  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt; &lt;span class="nv"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0&lt;span class="p"&gt;;&lt;/span&gt; i&amp;lt;&lt;span class="k"&gt;${#&lt;/span&gt;&lt;span class="nv"&gt;codes&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; i++ &lt;span class="o"&gt;))&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    case&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;codes&lt;/span&gt;:&lt;span class="nv"&gt;$i&lt;/span&gt;:1&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in
      &lt;/span&gt;B&lt;span class="p"&gt;)&lt;/span&gt; output+&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\033[22m'&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;   &lt;span class="c"&gt;# Turn off bright/dim&lt;/span&gt;
      D&lt;span class="p"&gt;)&lt;/span&gt; output+&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\033[22m'&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;   &lt;span class="c"&gt;# Turn off bright/dim&lt;/span&gt;
      I&lt;span class="p"&gt;)&lt;/span&gt; output+&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\033[23m'&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;   &lt;span class="c"&gt;# Turn off italic&lt;/span&gt;
      U&lt;span class="p"&gt;)&lt;/span&gt; output+&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\033[24m'&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;   &lt;span class="c"&gt;# Turn off underline&lt;/span&gt;
      L&lt;span class="p"&gt;)&lt;/span&gt; output+&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\033[25m'&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;   &lt;span class="c"&gt;# Turn off blink&lt;/span&gt;
      R&lt;span class="p"&gt;)&lt;/span&gt; output+&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\033[27m'&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;   &lt;span class="c"&gt;# Turn off reverse&lt;/span&gt;
      S&lt;span class="p"&gt;)&lt;/span&gt; output+&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\033[29m'&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;   &lt;span class="c"&gt;# Turn off strikethrough&lt;/span&gt;
    &lt;span class="k"&gt;esac&lt;/span&gt;
  &lt;span class="k"&gt;done

  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$output&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# #############################################################################&lt;/span&gt;
&lt;span class="c"&gt;# Display the colour chart. Pick a colour, _any colour_!!!!&lt;/span&gt;
&lt;span class="c"&gt;# #############################################################################&lt;/span&gt;

&lt;span class="c"&gt;# Only show the chart if the script is run directly, not sourced&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BASH_SOURCE&lt;/span&gt;&lt;span class="p"&gt;[0]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;0&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"                     &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;F 227&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;-= &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;F 198&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;High colour List &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;F 227&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;=-&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;RST&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt;

  &lt;span class="c"&gt;# Rainbow colours (16-231) - 3 sections, 6 rows each, 12 colours per row&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;i &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;0..2&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    for &lt;/span&gt;j &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;0..5&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
      for &lt;/span&gt;k &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;0..11&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
        &lt;/span&gt;&lt;span class="nv"&gt;colour&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;&lt;span class="m"&gt;16&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; i &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; j &lt;span class="o"&gt;+&lt;/span&gt; k &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;
        &lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;F &lt;span class="nv"&gt;$colour&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;%03d&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;RST&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;  "&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$colour&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
      &lt;span class="k"&gt;done
      &lt;/span&gt;&lt;span class="nb"&gt;echo
    &lt;/span&gt;&lt;span class="k"&gt;done
  done

  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;

  &lt;span class="c"&gt;# Grayscale (232-255) - 2 rows, 12 colours each&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;i &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;0..1&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    for &lt;/span&gt;j &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;0..11&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
      &lt;/span&gt;&lt;span class="nv"&gt;colour&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;&lt;span class="m"&gt;232&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; i &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; j&lt;span class="k"&gt;))&lt;/span&gt;
      &lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;F &lt;span class="nv"&gt;$colour&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;%03d&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;RST&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;  "&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$colour&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;done
    &lt;/span&gt;&lt;span class="nb"&gt;echo
  &lt;/span&gt;&lt;span class="k"&gt;done

  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;

  &lt;span class="c"&gt;# Base colours (0-15) - 2 rows, 8 colours each&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;i &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;0..1&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    for &lt;/span&gt;j &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;0..7&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
      &lt;/span&gt;&lt;span class="nv"&gt;colour&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;i &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; j&lt;span class="k"&gt;))&lt;/span&gt;
      &lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;F &lt;span class="nv"&gt;$colour&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;%03d&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;RST&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;  "&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$colour&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;done
    &lt;/span&gt;&lt;span class="nb"&gt;echo
  &lt;/span&gt;&lt;span class="k"&gt;done
fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Whee!
&lt;/h4&gt;

&lt;p&gt;This was my first post ever, how did I do?&lt;/p&gt;

</description>
      <category>bash</category>
    </item>
  </channel>
</rss>
