#!/bin/sh # Regenerate the *-theme.auto.conf files kitty reads at startup from the # canonical themes in ./theme-modes, honouring the mode recorded in ./theme-mode: # # auto every appearance keeps its own theme, so kitty follows the OS # light every appearance gets the light theme, so kitty stays light # dark every appearance gets the dark theme, so kitty stays dark # # kitty gives the automatic theme files priority over everything else -- includes # and even --override -- so pinning a mode means writing the wanted theme into # whichever file the OS makes kitty pick. That is why the real themes live in # ./theme-modes and these three files are generated. (./themes is separate: # that is where the themes kitten looks for user themes.) set -eu # Permission bits of a file, or 600 if they cannot be read. GNU stat spells this # `-c %a` while BSD/macOS spells it `-f %Lp`, and each mis-parses the other's # form -- GNU treats `-f` as --file-system and prints a block of filesystem info # before failing -- so try one at a time and only accept an octal answer. file_mode() { _m=$(stat -c '%a' "$1" 2>/dev/null) || _m='' case "$_m" in [0-7][0-7][0-7] | [0-7][0-7][0-7][0-7]) printf '%s\n' "$_m"; return 0 ;; esac _m=$(stat -f '%Lp' "$1" 2>/dev/null) || _m='' case "$_m" in [0-7][0-7][0-7] | [0-7][0-7][0-7][0-7]) printf '%s\n' "$_m"; return 0 ;; esac printf '600\n' } script_dir="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)" config_dir=${1:-"$script_dir"} canonical_dir="$config_dir/theme-modes" mode_file="$config_dir/theme-mode" mode=auto if [ -f "$mode_file" ]; then mode=$(tr -d ' \t\r\n' < "$mode_file") fi case "$mode" in auto | light | dark) ;; *) mode=auto ;; esac mkdir -p "$canonical_dir" # Checksums of the files as this script last wrote them. Anything that differs # now was rewritten by something else -- in practice the themes kitten saving a # theme for that appearance -- so it is a new choice and becomes canonical. # Recording it here rather than in the fish `kitten` wrapper means the choice # survives however the kitten was launched: `kitty +kitten themes`, a keybinding # or another shell all bypass that wrapper. state_file="$config_dir/.theme-generated" # cksum is POSIX, unlike shasum/sha256sum which differ across platforms. sum_of() { [ -f "$1" ] || return 1 cksum < "$1" } recorded_sum() { [ -f "$state_file" ] || return 1 awk -v want="$1" '$1 == want { $1 = ""; sub(/^ /, ""); print; found = 1 } END { exit !found }' "$state_file" } for appearance in dark light no-preference; do canonical="$canonical_dir/$appearance.conf" generated="$config_dir/$appearance-theme.auto.conf" [ -f "$generated" ] || continue # First adoption of an existing setup: take whatever is there, but only # while following the OS. Under a pinned mode every generated file holds # the pinned theme, so adopting them would overwrite the other appearances. if [ ! -f "$canonical" ]; then [ "$mode" = auto ] && cp "$generated" "$canonical" continue fi # With no state yet we cannot tell a fresh choice from a file we wrote, so # leave canonical alone; the checksums recorded below make the next run # able to tell. now=$(sum_of "$generated") || continue was=$(recorded_sum "$appearance") || continue [ "$now" = "$was" ] || cp "$generated" "$canonical" done for appearance in dark light no-preference; do if [ "$mode" = auto ]; then source_name=$appearance else source_name=$mode fi canonical="$canonical_dir/$source_name.conf" [ -f "$canonical" ] || continue generated="$config_dir/$appearance-theme.auto.conf" mode_bits=600 if [ -f "$generated" ]; then mode_bits=$(file_mode "$generated") fi tmp=$(mktemp "$generated.tmp.XXXXXX") trap 'rm -f "$tmp"' EXIT HUP INT TERM cat "$canonical" > "$tmp" chmod "$mode_bits" "$tmp" mv -f "$tmp" "$generated" trap - EXIT HUP INT TERM done "$script_dir/repair-auto-themes.sh" "$config_dir" # Record what we ended up with, after the repair step, so the next run can tell # an externally-saved theme from one of ours. tmp_state=$(mktemp "$state_file.tmp.XXXXXX") trap 'rm -f "$tmp_state"' EXIT HUP INT TERM for appearance in dark light no-preference; do generated="$config_dir/$appearance-theme.auto.conf" [ -f "$generated" ] || continue printf '%s %s\n' "$appearance" "$(sum_of "$generated")" >> "$tmp_state" done chmod 600 "$tmp_state" mv -f "$tmp_state" "$state_file" trap - EXIT HUP INT TERM