dotfiles/private_dot_config/kitty/private_executable_apply-theme-mode.sh
Anton Volnuhin addce489b4 kitty: remember the light/dark mode across restarts
kitty gives *-theme.auto.conf priority over everything -- includes and
even --override -- and has no option to stop following the OS. So the
only way to start in a chosen mode is to control what those files
contain. Make them generated:

  themes/{light,dark,no-preference}.conf  canonical, the real themes
  theme-mode                              auto | light | dark
  apply-theme-mode.sh                      writes the three .auto.conf

Under `auto` each appearance keeps its own theme, so kitty follows the
OS as before. Pinned, all three get the pinned theme, so kitty starts in
it whatever the OS says and a config reload no longer resets it.

`theme` now records the mode and reloads instead of calling set-colors,
which is why the setting survives restarts. A bare `theme` records
`auto` rather than pinning when the toggle lands on the macOS
appearance, so nothing is pinned unless it actually differs.

The kitten shim hashes the automatic theme files before running `kitten
themes` and copies whichever changed into themes/, so picking a new
light theme while pinned to dark is kept and applied on the next switch.
Covered by tests/test_theme_mode.sh.

conf.d/kitty_theme.fish is gone: theme-mode is now the source of truth,
so the universal-variable tracker it maintained is redundant.
2026-08-06 01:49:45 +03:00

69 lines
2.1 KiB
Bash

#!/bin/sh
# Regenerate the *-theme.auto.conf files kitty reads at startup from the
# canonical themes in ./themes, 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
# ./themes and these three files are generated.
set -eu
script_dir="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
config_dir=${1:-"$script_dir"}
canonical_dir="$config_dir/themes"
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"
# Adopt the current automatic themes as canonical when they have not been
# captured yet. Only safe while following the OS: under a pinned mode the
# generated files all hold the pinned theme and would overwrite the others.
if [ "$mode" = auto ]; then
for appearance in dark light no-preference; do
canonical="$canonical_dir/$appearance.conf"
generated="$config_dir/$appearance-theme.auto.conf"
if [ ! -f "$canonical" ] && [ -f "$generated" ]; then
cp "$generated" "$canonical"
fi
done
fi
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
[ -f "$generated" ] && mode_bits=$(stat -f '%Lp' "$generated")
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"