Inchwyrm barks at nothing

Making a JSON to CSS colorscheme converter

I recently made a 16-color theme for Bear, and I'm thinking about making a similar theme for a general website, so I figured I'd need an easy way to get new terminal colorschemes into a format I can use for that purpose. I'm trying to get more comfortable with coding, so this seemed like the perfect opportunity! Once again in the spirit of learning in public, here's how it all went down.


The idea

I know that terminal.sexy makes it easy to export both custom and premade 16-color schemes to various formats, including JSON. I know how to read and write files with Python, and I also know how to interpret JSON with it. All I had to do was create a program that reads the JSON from terminal.sexy and then writes a CSS file with the variables that my theme uses.


The execution

Here's what the program does:

  1. Ask the user what file they'd like to convert
    1. If the provided file exists, continue
    2. If the provided file doesn't exist, ask for a different file
  2. Convert the given JSON file into a Python object that's easier for me to work with
  3. Ask the user what the CSS file should be named
    1. If a file of the same name already exists, ask for a different name
    2. If a file of the same name doesn't already exist, create a CSS file with the provided name.
  4. Write a :root with the correct variable names to the new file

After that, I just copy the contents of the created file to my clipboard and paste it into the CSS to change the colorscheme. I use the kitty terminal, so that command looks like this: $ cat example.css | kitten clipboard


You can use it if you want

Go ahead and put this code wherever you'd like and try it out or modify it yourself! I keep it in the place where I put all my little Python programs, and I made an alias in my .zshrc to use this program with the same, short command wherever I happen to be.

Requirements

# Terminal CSS
# version 1.0
#
# convert json exported from terminal.sexy into named css variables
# for use with inchwyrm's 16-color terminal theme for bear blog

# things to add in the future:
# - decide whether to copy to clipboard or save a file or both
# - automatically choose accent and link colors
# - better ui

import json
from colorama import Fore, Style

# === CLASSES ===

class Colorscheme:
    def __init__(self, json_file):

        # Converts json_file into a python dictionary called json_colors
        json_colors = json.loads(json_file.read())

        self.name = json_colors['name']
        self.author = json_colors['author']

        self.foreground = json_colors['foreground']
        self.background = json_colors['background']

        a = hex_to_rgb(self.background)
        b = list(a)
        b.append(0.7)
        self.background_rgba = tuple(b)

        self.black = json_colors['color'][0]
        self.bright_black = json_colors['color'][8]

        self.red = json_colors['color'][1]
        self.bright_red = json_colors['color'][9]

        self.green = json_colors['color'][2]
        self.bright_green = json_colors['color'][10]

        self.yellow = json_colors['color'][3]
        self.bright_yellow = json_colors['color'][11]

        self.blue = json_colors['color'][4]
        self.bright_blue = json_colors['color'][12]

        self.magenta = json_colors['color'][5]
        self.bright_magenta = json_colors['color'][13]

        self.cyan = json_colors['color'][6]
        self.bright_cyan = json_colors['color'][14]

        self.white = json_colors['color'][7]
        self.bright_white = json_colors['color'][15]


# === FUNCTIONS ===

def hex_to_rgb(hex_color):
    """
    converts hex code to rgb equivalent.
    adapted from https://www.askpython.com/python/examples/convert-hex-to-rgb
    """
    if '#' in hex_color:
        hex_color = hex_color.replace('#', '')
    return tuple(int(hex_color[i:i+2],16) for i in (0, 2, 4))


# === MAIN ===

gray = Fore.WHITE + Style.DIM
normal = Style.RESET_ALL
green = Fore.GREEN
red = Fore.RED

print('\nTERMINAL.SEXY JSON TO CSS')
print(f'{gray}version 1.0{normal}')

# Makes sure the user-provided file is recognized
while True:
    filename = input(f'\nWhat file would you like to convert?\n{green}>>>{normal} ')

    try:
        contents = open(filename)
    except:
        print(f'\n{red}Not a recognized file. Try again.{normal}')
    else:
        print(f"\n{gray}Loading {filename}.{normal}")
        break

colorscheme = Colorscheme(contents)
print(f"{gray}Preparing to convert {colorscheme.name} by {colorscheme.author}...{normal}")

# Prompts the user to name the new file
# Makes sure that a file by that name doesn't already exist.
while True:
    global new_filename
    new_filename = input(f"\nWhat would you like to name your new file?\n{green}>>>{normal} ")
    new_filename = new_filename + ".css"

    try:
        open(new_filename, "x")
    except:
        print(f"\n{red}That file already exists. Please choose a different name.{normal}")
    else:
        break

print(f"\n{gray}Creating {new_filename}...{normal}")

with open(new_filename, "a") as f:

    f.write(":root {\n")

    f.write("\t--font: monospace;\n")
    f.write("\t--width: 750px;\n\n")

    f.write(f"\t--foreground: {colorscheme.foreground};\n")
    f.write(f"\t--background: {colorscheme.background};\n\n")

    f.write(f"\t/* change the final value here if you want to edit background transparency. */\n")
    f.write(f"\t--background-rgba: rgba{str(colorscheme.background_rgba)};\n\n")

    f.write(f"\t--black: {colorscheme.black};\n")
    f.write(f"\t--bright-black: {colorscheme.bright_black};\n\n")

    f.write(f"\t--red: {colorscheme.red};\n")
    f.write(f"\t--bright-red: {colorscheme.bright_red};\n\n")

    f.write(f"\t--green: {colorscheme.green};\n")
    f.write(f"\t--bright-green: {colorscheme.bright_green};\n\n")

    f.write(f"\t--yellow: {colorscheme.yellow};\n")
    f.write(f"\t--bright-yellow: {colorscheme.bright_yellow};\n\n")

    f.write(f"\t--blue: {colorscheme.blue};\n")
    f.write(f"\t--bright-blue: {colorscheme.bright_blue};\n\n")

    f.write(f"\t--magenta: {colorscheme.magenta};\n")
    f.write(f"\t--bright-magenta: {colorscheme.bright_magenta};\n\n")

    f.write(f"\t--cyan: {colorscheme.cyan};\n")
    f.write(f"\t--bright-cyan: {colorscheme.bright_cyan};\n\n")

    f.write(f"\t--white: {colorscheme.white};\n")
    f.write(f"\t--bright-white: {colorscheme.bright_white};\n\n")

    f.write(f"\t/* replace these with your favorite accent color */\n")
    f.write(f"\t--accent: var(--green);\n")
    f.write(f"\t--bright-accent: var(--bright-green);\n\n")

    f.write(f"\t/* replace these with your preferred link color */\n")
    f.write(f"\t--link: var(--blue);\n")
    f.write(f"\t--bright-link: var(--bright-blue);\n")
    f.write("}")

print(f"{green}Done!{normal}")
print(f"Copy the contents of {new_filename} into the :root of your CSS.")
print("Thanks for using Terminal.sexy JSON to CSS!")

#technology #technology/code #technology/code/python