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:
- Ask the user what file they'd like to convert
- If the provided file exists, continue
- If the provided file doesn't exist, ask for a different file
- Convert the given JSON file into a Python object that's easier for me to work with
- Ask the user what the CSS file should be named
- If a file of the same name already exists, ask for a different name
- If a file of the same name doesn't already exist, create a CSS file with the provided name.
- Write a
:rootwith 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
- The JSON format should be from terminal.sexy's Export as JSON Scheme.
- You will need colorama to run this code. I just thought it looked confusing when all the text was one color.
# 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!")