aboutsummaryrefslogtreecommitdiff
path: root/kitty/kitty-themes/.tools
diff options
context:
space:
mode:
Diffstat (limited to 'kitty/kitty-themes/.tools')
-rw-r--r--kitty/kitty-themes/.tools/README.md9
-rwxr-xr-xkitty/kitty-themes/.tools/color_table.sh26
-rw-r--r--kitty/kitty-themes/.tools/convert.py30
-rwxr-xr-xkitty/kitty-themes/.tools/convert_conf.swift57
-rwxr-xr-xkitty/kitty-themes/.tools/extract-vscode.sh5
-rwxr-xr-xkitty/kitty-themes/.tools/generate_conf.sh10
-rwxr-xr-xkitty/kitty-themes/.tools/generate_theme_preview.sh22
-rwxr-xr-xkitty/kitty-themes/.tools/generate_themes_previews.sh32
-rwxr-xr-xkitty/kitty-themes/.tools/libcapture.sh23
-rwxr-xr-xkitty/kitty-themes/.tools/markdown.sh15
-rw-r--r--kitty/kitty-themes/.tools/palette.py91
-rw-r--r--kitty/kitty-themes/.tools/preview.py136
-rwxr-xr-xkitty/kitty-themes/.tools/previews.sh24
-rw-r--r--kitty/kitty-themes/.tools/template.conf37
-rw-r--r--kitty/kitty-themes/.tools/template.conf.j291
-rwxr-xr-xkitty/kitty-themes/.tools/windowid.swift20
16 files changed, 628 insertions, 0 deletions
diff --git a/kitty/kitty-themes/.tools/README.md b/kitty/kitty-themes/.tools/README.md
new file mode 100644
index 000000000..732115538
--- /dev/null
+++ b/kitty/kitty-themes/.tools/README.md
@@ -0,0 +1,9 @@
+# kitty-tools
+> A bunch of useful scripts used to convert schemes and generate files.
+
+## Process overview
+
+1. Find a nice theme and check the licensing, is it possible to distribute the theme?
+2. Generate the configuration file for **kitty**;
+3. Add a new preview for the theme;
+4. Update the README.md;
diff --git a/kitty/kitty-themes/.tools/color_table.sh b/kitty/kitty-themes/.tools/color_table.sh
new file mode 100755
index 000000000..b7b4559bb
--- /dev/null
+++ b/kitty/kitty-themes/.tools/color_table.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+#
+# This file echoes a bunch of color codes to the
+# terminal to demonstrate what's available. Each
+# line is the color code of one forground color,
+# out of 17 (default + 16 escapes), followed by a
+# test use of that color on all nine background
+# colors (default + 8 escapes).
+#
+
+T='gYw' # The test text
+
+echo -e "\n 40m 41m 42m 43m\
+ 44m 45m 46m 47m";
+
+for FGs in ' m' ' 1m' ' 30m' '1;30m' ' 31m' '1;31m' ' 32m' \
+ '1;32m' ' 33m' '1;33m' ' 34m' '1;34m' ' 35m' '1;35m' \
+ ' 36m' '1;36m' ' 37m' '1;37m';
+ do FG=${FGs// /}
+ echo -en " $FGs \033[$FG $T "
+ for BG in 40m 41m 42m 43m 44m 45m 46m 47m;
+ do echo -en "$EINS \033[$FG\033[$BG $T \033[0m";
+ done
+ echo;
+done
+echo
diff --git a/kitty/kitty-themes/.tools/convert.py b/kitty/kitty-themes/.tools/convert.py
new file mode 100644
index 000000000..3599ddcf1
--- /dev/null
+++ b/kitty/kitty-themes/.tools/convert.py
@@ -0,0 +1,30 @@
+import json
+from jinja2 import FileSystemLoader, Environment
+import sys
+import os
+
+
+def removeAlpha(value):
+ hex = value.lstrip("#")
+ return "#" + hex[0:6]
+
+
+filename = sys.argv[1]
+
+kitty_configuration = os.path.splitext(filename)[0] + ".conf"
+
+with open(filename, "r") as configuration_file:
+ configuration = json.load(configuration_file)
+
+loader = FileSystemLoader(".")
+env = Environment(loader=loader)
+
+env.filters['removeAlpha'] = removeAlpha
+env.trim_blocks = True
+
+template = env.get_template("template.conf.j2")
+
+output = template.render(**configuration)
+
+with open(kitty_configuration, "w") as fp:
+ fp.write(output)
diff --git a/kitty/kitty-themes/.tools/convert_conf.swift b/kitty/kitty-themes/.tools/convert_conf.swift
new file mode 100755
index 000000000..b023f5699
--- /dev/null
+++ b/kitty/kitty-themes/.tools/convert_conf.swift
@@ -0,0 +1,57 @@
+#!/usr/bin/swift
+// main.swift
+// nscolor
+//
+// Created by Fabrizio FD. Destro on 28/12/18.
+// Copyright © 2018 Fabrizio FD. Destro. All rights reserved.
+//
+
+import Foundation
+import AppKit
+
+func hex(color: NSColor) -> String {
+ return String(format: "#%02x%02x%02x", Int(color.redComponent * 0xFF), Int(color.greenComponent * 0xFF), Int(color.blueComponent * 0xFF))
+}
+
+func process_color(field: String, data: Data) {
+ let color = NSKeyedUnarchiver.unarchiveObject(with: data) as! NSColor
+ print("\(field) \(hex(color: color))");
+}
+
+func generate_conf_line(field: String, key: String, dictionary: NSDictionary){
+ if let data = dictionary[key] {
+ process_color(field: field, data: data as! Data)
+ }
+}
+
+func process(filename: String) {
+ let plist = NSDictionary(contentsOfFile: filename)!
+
+ generate_conf_line(field: "background", key: "BackgroundColor", dictionary: plist)
+ generate_conf_line(field: "foreground", key: "TextColor", dictionary: plist)
+ generate_conf_line(field: "cursor", key: "CursorColor", dictionary: plist)
+ generate_conf_line(field: "selection_background", key: "SelectionColor", dictionary: plist)
+ generate_conf_line(field: "color0", key: "ANSIBlackColor", dictionary: plist)
+ generate_conf_line(field: "color8", key: "ANSIBrightBlackColor", dictionary: plist)
+ generate_conf_line(field: "color1", key: "ANSIRedColor", dictionary: plist)
+ generate_conf_line(field: "color9", key: "ANSIBrightRedColor", dictionary: plist)
+ generate_conf_line(field: "color2", key: "ANSIGreenColor", dictionary: plist)
+ generate_conf_line(field: "color10", key: "ANSIBrightGreenColor", dictionary: plist)
+ generate_conf_line(field: "color3", key: "ANSIYellowColor", dictionary: plist)
+ generate_conf_line(field: "color11", key: "ANSIBrightYellowColor", dictionary: plist)
+ generate_conf_line(field: "color4", key: "ANSIBlueColor", dictionary: plist)
+ generate_conf_line(field: "color12", key: "ANSIBrightBlueColor", dictionary: plist)
+ generate_conf_line(field: "color5", key: "ANSIMagentaColor", dictionary: plist)
+ generate_conf_line(field: "color13", key: "ANSIBrightMagentaColor", dictionary: plist)
+ generate_conf_line(field: "color6", key: "ANSICyanColor", dictionary: plist)
+ generate_conf_line(field: "color14", key: "ANSIBrightCyanColor", dictionary: plist)
+ generate_conf_line(field: "color7", key: "ANSIWhiteColor", dictionary: plist)
+ generate_conf_line(field: "color15", key: "ANSIBrightWhiteColor", dictionary: plist)
+}
+
+if (CommandLine.argc == 2) {
+ let filename = CommandLine.arguments[1]
+ process(filename: filename)
+} else {
+ print("Missing plist's path.")
+}
diff --git a/kitty/kitty-themes/.tools/extract-vscode.sh b/kitty/kitty-themes/.tools/extract-vscode.sh
new file mode 100755
index 000000000..71a69305d
--- /dev/null
+++ b/kitty/kitty-themes/.tools/extract-vscode.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+theme=$1
+
+jq ".colors | to_entries | map(select(.key | match(\"terminal.*\"))) | map({(.key | gsub(\"\\\\.(?<a>.)\"; .a | ascii_upcase) | ltrimstr(\"terminal\") | sub(\"(?<a>.)\"; .a | ascii_downcase)):.value}) | add" < "$theme" > "terminal/${theme%.*}.json"
diff --git a/kitty/kitty-themes/.tools/generate_conf.sh b/kitty/kitty-themes/.tools/generate_conf.sh
new file mode 100755
index 000000000..db498b9ac
--- /dev/null
+++ b/kitty/kitty-themes/.tools/generate_conf.sh
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+
+find ~/github/macos-terminal-themes/schemes/ -name "*.terminal" -print0 | while read -d $'\0' -r file; do
+ filename=`basename "$file"`
+ without_ext=${filename%.*}
+ removed_spaces=${without_ext// /_}
+ # output_filename=`echo ${removed_spaces} | tr '[:upper:]' '[:lower:]'`
+ echo ${removed_spaces}.conf
+ ./convert_conf.swift "$file" > ./themes/${removed_spaces}.conf
+done
diff --git a/kitty/kitty-themes/.tools/generate_theme_preview.sh b/kitty/kitty-themes/.tools/generate_theme_preview.sh
new file mode 100755
index 000000000..040867b35
--- /dev/null
+++ b/kitty/kitty-themes/.tools/generate_theme_preview.sh
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+# This script generate all preview images for the themes
+# In order to capture previews without the to bar start kitty without decorations
+# kitty -o hide_window_decorations=yes
+
+# shellcheck source=libcapture.sh
+source libcapture.sh
+
+# read theme path from args
+id=$1
+theme=$2
+preview_filename=$3
+
+conf_filename=$(basename "$theme")
+
+lockfile=$(mktemp)
+
+kitty @ set-colors --match id:"$id" "$theme"
+kitty @ send-text --match id:"$id" "clear && figlet -f digital -t \"$conf_filename\" && unbuffer ./color_table.sh && rm \"$lockfile\"\n"
+
+# simple sync mechanism, wait for the lockfile to be removed
+( echo "$lockfile" | entr "false" 1>/dev/null 2>&1 ) || capture themes "$preview_filename"
diff --git a/kitty/kitty-themes/.tools/generate_themes_previews.sh b/kitty/kitty-themes/.tools/generate_themes_previews.sh
new file mode 100755
index 000000000..63e5825e5
--- /dev/null
+++ b/kitty/kitty-themes/.tools/generate_themes_previews.sh
@@ -0,0 +1,32 @@
+#!/usr/bin/env bash
+# This script generate all preview images for the themes
+
+root="$(git rev-parse --show-toplevel)"
+tools="$root/.tools"
+
+PATH=$tools:$PATH
+
+# new kitty window, return its id
+id=$(kitty @ new-window --title themes --window-type os --cwd "$tools")
+# start bash without reading the profile nor the configuration
+kitty @ send-text --match id:"$id" "/usr/bin/env bash --noprofile --norc\n"
+kitty @ set-font-size 24
+
+# save all preview in this directory
+previews="$root/_previews"
+if [ ! -d "$previews" ]; then
+ mkdir "$previews"
+fi
+
+while read -r theme
+do
+ echo "Genereting theme preview for $theme"
+ preview_directory=$previews/$(basename "${theme%.*}")
+ [ ! -d "$preview_directory" ] && mkdir "$preview_directory"
+ preview_filename=$previews/$(basename "${theme%.*}")/preview.png
+ generate_theme_preview.sh "$id" "$theme" "$preview_filename"
+ mogrify -resize 1024x\> "$preview_filename"
+done < /dev/stdin
+
+kitty @ close-window --match id:"$id"
+kitty @ set-font-size 16
diff --git a/kitty/kitty-themes/.tools/libcapture.sh b/kitty/kitty-themes/.tools/libcapture.sh
new file mode 100755
index 000000000..ff5159187
--- /dev/null
+++ b/kitty/kitty-themes/.tools/libcapture.sh
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+
+function capture_linux() {
+ local title="$1"
+ local output="$2"
+ import -window "$title" "$output"
+}
+
+function capture_osx() {
+ local title="$1"
+ local output="$2"
+ # get system id of the new created window
+ sys_id=$(./windowid.swift "kitty" "$title")
+ screencapture -wl"$sys_id" "$output"
+}
+
+function capture() {
+ if [[ "$OSTYPE" == "linux-gnu" ]]; then
+ capture_linux "$@"
+ elif [[ "$OSTYPE" == "darwin"* ]]; then
+ capture_osx "$@"
+ fi
+}
diff --git a/kitty/kitty-themes/.tools/markdown.sh b/kitty/kitty-themes/.tools/markdown.sh
new file mode 100755
index 000000000..0fb08bae0
--- /dev/null
+++ b/kitty/kitty-themes/.tools/markdown.sh
@@ -0,0 +1,15 @@
+#!/usr/bin/env bash
+
+previews_root=$1
+# usually this value: https://raw.githubusercontent.com/dexpota/kitty-themes-website/master
+url_root=$2
+
+for f in $(find "$previews_root/previews" -maxdepth 1 -mindepth 1 -type d | sort); do
+ preview_file="$f"/preview.png
+ theme=$(basename $f)
+ relative_path=$(realpath --relative-to="$previews_root" "$preview_file")
+ header=`basename $theme | sed 's/_/ /g'`
+ image="![image]($url_root/$relative_path)"
+ echo \#\# $header
+ echo $image
+done
diff --git a/kitty/kitty-themes/.tools/palette.py b/kitty/kitty-themes/.tools/palette.py
new file mode 100644
index 000000000..f47fd9c16
--- /dev/null
+++ b/kitty/kitty-themes/.tools/palette.py
@@ -0,0 +1,91 @@
+from argparse import ArgumentParser
+from svgwrite.shapes import Rect
+import svgwrite
+
+theme_keys = [
+ "foreground", "background", "background_opacity", "dynamic_background_opacity", "dim_opacity",
+ "selection_foreground", "selection_background", "color0", "color8", "color1", "color9", "color2", "color10",
+ "color3", "color11", "color4", "color12", "color5", "color13", "color6", "color14", "color7", "color15"
+]
+
+
+def is_valid(line):
+ """
+ Returns true if a line inside a configuration file is a valid theme configuration pair: is not a comment, is not
+ empty and the key is correct.
+
+ :param line: a line inside the configuration file
+ :type line: str
+ :return: true if is valid, false otherwise
+ :rtype: bool
+ """
+ return (not line.lstrip().startswith("#") # is not a comment
+ and len(line.strip()) != 0 # is not empty
+ and line.split(maxsplit=1)[0] in theme_keys) # key is a valid one
+
+
+def extract_configuration_pair(line):
+ """
+ Extract a configuration pair by splitting on spaces and taking the first couple of values.
+
+ :param line: a line inside the configuration file
+ :type line: str
+ :return: a key-value pair
+ :rtype: bool
+ """
+ split = line.split(maxsplit=2)
+ return split[0], split[1]
+
+
+def read_configuration(filename):
+ """
+ Read a kitty configuration file and extract only theme related keys and values.
+
+ :param filename: path to the configuration file
+ :type filename: str
+ :return: a map with theme related configuration values
+ :rtype: dict[str, str]
+ """
+ with open(filename, "r") as fp:
+ lines = fp.readlines()
+ print(filename)
+ theme_config = dict([extract_configuration_pair(line) for line in lines if is_valid(line)])
+ return theme_config
+
+
+def draw_theme_palette(theme_configuration, start_point, size, displacement):
+ rects = []
+ for k, v in theme_configuration.items():
+ rgb = tuple(int(v[i + 1:i + 3], 16) for i in (0, 2, 4))
+ rects.append(Rect(start_point, size, fill=svgwrite.utils.rgb(rgb[0], rgb[1], rgb[2])))
+ start_point = (start_point[0] + displacement[0], start_point[1] + displacement[1])
+
+ return rects
+
+
+def draw_all_palettes(themes):
+ dwg = svgwrite.Drawing('test.svg', profile='tiny')
+ y = 0
+ palettes = []
+ for theme in themes:
+ palettes += draw_theme_palette(theme, (0, y), (10, 10), (10, 0))
+ y += 10
+
+ for rect in palettes:
+ dwg.add(rect)
+ dwg.save()
+
+
+def main():
+ parser = ArgumentParser()
+ parser.add_argument("theme", type=str, nargs="+")
+
+ ns = parser.parse_args()
+
+ theme_configurations = [read_configuration(theme) for theme in ns.theme]
+
+ draw_all_palettes(theme_configurations)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/kitty/kitty-themes/.tools/preview.py b/kitty/kitty-themes/.tools/preview.py
new file mode 100644
index 000000000..c29387ae6
--- /dev/null
+++ b/kitty/kitty-themes/.tools/preview.py
@@ -0,0 +1,136 @@
+import sys
+import os
+import sys
+
+theme_keys = [
+ "cursor", "foreground", "background", "background_opacity", "dynamic_background_opacity", "dim_opacity",
+ "selection_foreground", "selection_background", "color0", "color8", "color1", "color9", "color2", "color10",
+ "color3", "color11", "color4", "color12", "color5", "color13", "color6", "color14", "color7", "color15"
+]
+
+
+def is_valid(line):
+ """
+ Returns true if a line inside a configuration file is a valid theme configuration pair: is not a comment, is not
+ empty and the key is correct.
+
+ :param line: a line inside the configuration file
+ :type line: str
+ :return: true if is valid, false otherwise
+ :rtype: bool
+ """
+ return (not line.lstrip().startswith("#") # is not a comment
+ and len(line.strip()) != 0 # is not empty
+ and line.split(maxsplit=1)[0] in theme_keys) # key is a valid one
+
+
+def extract_configuration_pair(line):
+ """
+ Extract a configuration pair by splitting on spaces and taking the first couple of values.
+
+ :param line: a line inside the configuration file
+ :type line: str
+ :return: a key-value pair
+ :rtype: bool
+ """
+ split = line.split(maxsplit=2)
+ return split[0], split[1]
+
+
+def read_configuration(filename):
+ """
+ Read a kitty configuration file and extract only theme related keys and values.
+
+ :param filename: path to the configuration file
+ :type filename: str
+ :return: a map with theme related configuration values
+ :rtype: dict[str, str]
+ """
+ with open(filename, "r") as fp:
+ lines = fp.readlines()
+ theme_config = dict([extract_configuration_pair(line) for line in lines if is_valid(line)])
+ return theme_config
+
+
+def fg(color, text):
+ rgb = tuple(int(color[i + 1:i + 3], 16) for i in (0, 2, 4))
+ return ('\x1b[38;2;%s;%s;%sm' % rgb + text + '\x1b[0m')
+
+
+def bg(color, text):
+ rgb = tuple(int(color[i + 1:i + 3], 16) for i in (0, 2, 4))
+ return ('\x1b[48;2;%s;%s;%sm' % rgb + text + '\x1b[0m')
+
+
+def print_preview(filename, configuration):
+ cursor = configuration["cursor"]
+ background = configuration["background"]
+ foreground = configuration["foreground"]
+
+ theme = os.path.basename(filename)
+
+ size = len(theme) + (2 + 2 + 16 + 2 + 16 + 1 + 2)
+ print(bg(background, " " * size))
+ print(bg(background, " "), end="")
+ print(bg(background, fg(foreground, theme)), end="")
+ print(bg(background, " "), end="")
+
+ c='a'
+ for i in range(0, 16):
+ color = configuration["color%d" % i]
+ print(bg(background, fg(color, c)), end="")
+ c = chr(ord(c) + 1)
+
+ print(bg(background, " "), end="")
+
+ selection_background = configuration["selection_background"]
+ selection_foreground = configuration["selection_foreground"]
+
+ c='A'
+ for i in range(0, 16):
+ print(bg(selection_background, fg(selection_foreground, c)), end="")
+ c = chr(ord(c) + 1)
+
+ print(bg(cursor, " "), end="")
+ print(bg(background, " "))
+
+ print(bg(background, " " * size))
+
+ print(bg(background, " "), end="")
+ print(bg(configuration["color0"], " "), end="")
+ print(bg(configuration["color1"], " "), end="")
+ print(bg(configuration["color2"], " "), end="")
+ print(bg(configuration["color3"], " "), end="")
+ print(bg(configuration["color4"], " "), end="")
+ print(bg(configuration["color5"], " "), end="")
+ print(bg(configuration["color6"], " "), end="")
+ print(bg(configuration["color7"], " "), end="")
+ print(bg(background, " "), end="")
+ print(bg(configuration["color8"], " "), end="")
+ print(bg(configuration["color9"], " "), end="")
+ print(bg(configuration["color10"], " "), end="")
+ print(bg(configuration["color11"], " "), end="")
+ print(bg(configuration["color12"], " "), end="")
+ print(bg(configuration["color13"], " "), end="")
+ print(bg(configuration["color14"], " "), end="")
+ print(bg(configuration["color15"], " "), end="")
+ print(bg(background, " " * (size - 16 - 4)), end="")
+ print()
+
+ print(bg(background, " " * size))
+ print()
+
+
+def main(directory):
+ for filename in os.listdir(directory):
+ try:
+ path = os.path.join(directory, filename)
+ configuration = read_configuration(path)
+ print_preview(path, configuration)
+ except Exception as e:
+ print(e, file=sys.stderr)
+ print("Error while processing %s" % filename, file=sys.stderr)
+
+
+if __name__ == "__main__":
+ main(sys.argv[1])
diff --git a/kitty/kitty-themes/.tools/previews.sh b/kitty/kitty-themes/.tools/previews.sh
new file mode 100755
index 000000000..c39c2c787
--- /dev/null
+++ b/kitty/kitty-themes/.tools/previews.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+# @author: @vrdhn on github
+
+SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
+cd $SCRIPT_DIR/..
+
+set_theme () {
+ cat themes/$1.conf | awk 'BEGIN {printf("kitty @ set-colors ")} {printf( "%s=%s ",$1,$2 )} END{printf("\n")}' | sh
+}
+
+list=$(find themes -type f | grep "$1" | xargs basename | cut -d. -f1)
+
+for x in $list ;
+do
+ kitty +kitten icat "previews/$x.png"
+ read -n 1 -p "$x : Next / Set / Quit :" ans
+ echo
+
+ case $ans in
+ n ) ;;
+ s ) set_theme $x ; exit ;;
+ q ) exit ;;
+ esac
+done
diff --git a/kitty/kitty-themes/.tools/template.conf b/kitty/kitty-themes/.tools/template.conf
new file mode 100644
index 000000000..0af1722da
--- /dev/null
+++ b/kitty/kitty-themes/.tools/template.conf
@@ -0,0 +1,37 @@
+background #
+foreground #
+cursor #
+cursor_text_color #
+selection_foreground #
+selection_background #
+# black
+color0 #
+color8 #
+# red
+color1 #
+# light red
+color9 #
+# green
+color2 #
+# light green
+color10 #
+# yellow
+color3 #
+# light yellow
+color11 #
+# blue
+color4 #
+# light blue
+color12 #
+# magenta
+color5 #
+# light magenta
+color13 #
+# cyan
+color6 #
+# lighy cyan
+color14 #
+# light gray
+color7 #
+# dark gray
+color15 #
diff --git a/kitty/kitty-themes/.tools/template.conf.j2 b/kitty/kitty-themes/.tools/template.conf.j2
new file mode 100644
index 000000000..8ff9450b0
--- /dev/null
+++ b/kitty/kitty-themes/.tools/template.conf.j2
@@ -0,0 +1,91 @@
+{% if background is defined %}
+background {{background}}
+{% endif %}
+{% if foreground is defined %}
+foreground {{foreground}}
+{% endif %}
+
+{% if cursorForeground is defined %}
+cursor {{cursorForeground}}
+{% endif %}
+{% if cursorBackground is defined %}
+cursor_text_color {{cursorBackground | removeAlpha}}
+{% endif %}
+{% if background is defined %}
+selection_foreground {{background | removeAlpha}}
+{% endif %}
+{% if selectionBackground is defined %}
+selection_background {{selectionBackground | removeAlpha}}
+{% endif %}
+
+{% if ansiBlack is defined %}
+# dull black
+color0 {{ansiBlack}}
+{% endif %}
+{% if ansiBrightBlack is defined %}
+# light black
+color8 {{ansiBrightBlack}}
+{% endif %}
+
+{% if ansiRed is defined %}
+# dull red
+color1 {{ansiRed}}
+{% endif %}
+{% if ansiBrightRed %}
+# light red
+color9 {{ansiBrightRed}}
+{% endif %}
+
+{% if ansiGreen is defined %}
+# dull green
+color2 {{ansiGreen}}
+{% endif %}
+{% if ansiBrightGreen is defined %}
+# light green
+color10 {{ansiBrightGreen}}
+{% endif %}
+
+{% if ansiYellow is defined %}
+# yellow
+color3 {{ansiYellow}}
+{% endif %}
+{% if ansiBrightYellow is defined %}
+# light yellow
+color11 {{ansiBrightYellow}}
+{% endif %}
+
+{% if ansiBlue is defined %}
+# blue
+color4 {{ansiBlue}}
+{% endif %}
+{% if ansiBrightBlue %}
+# light blue
+color12 {{ansiBrightBlue}}
+{% endif %}
+
+{% if ansiMagenta is defined %}
+# magenta
+color5 {{ansiMagenta}}
+{% endif %}
+{% if ansiBrightMagenta is defined %}
+# light magenta
+color13 {{ansiBrightMagenta}}
+{% endif %}
+
+{% if ansiCyan is defined %}
+# cyan
+color6 {{ansiCyan}}
+{% endif %}
+{% if ansiBrightCyan is defined %}
+# light cyan
+color14 {{ansiBrightCyan}}
+{% endif %}
+
+{% if ansiWhite is defined %}
+# dull white
+color7 {{ansiWhite}}
+{% endif %}
+{% if ansiBrightWhite is defined %}
+# bright white
+color15 {{ansiBrightWhite}}
+{% endif %}
diff --git a/kitty/kitty-themes/.tools/windowid.swift b/kitty/kitty-themes/.tools/windowid.swift
new file mode 100755
index 000000000..1dc95e6fd
--- /dev/null
+++ b/kitty/kitty-themes/.tools/windowid.swift
@@ -0,0 +1,20 @@
+#!/usr/bin/swift
+import Foundation
+import Cocoa
+import CoreGraphics.CGWindow
+
+let windows : NSArray = CGWindowListCopyWindowInfo(CGWindowListOption.excludeDesktopElements, kCGNullWindowID)! as NSArray
+
+let search_for_app = CommandLine.arguments[1]
+let search_for_win = CommandLine.arguments[2]
+
+for window in windows {
+ let window = window as! NSDictionary
+
+ let app_name = window[kCGWindowOwnerName] as! String
+ let window_name = window[kCGWindowName] as? String
+
+ if app_name == search_for_app && window_name == search_for_win {
+ print("\(window[kCGWindowNumber]!)")
+ }
+}