Compare commits

...

2 Commits

Author SHA1 Message Date
Anton Volnuhin
9c339fb730 theme small changes and fixes 2026-07-28 04:57:07 +03:00
Anton Volnuhin
a68b138d38 fix(kitty): preserve tab styling across themes 2026-07-28 04:53:48 +03:00
6 changed files with 254 additions and 31 deletions

View File

@ -0,0 +1,28 @@
#!/bin/sh
set -eu
config_dir=${1:-"$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"}
for appearance in dark light no-preference; do
config_file="$config_dir/$appearance-theme.auto.conf"
[ -f "$config_file" ] || continue
if awk '
$1 == "macos_titlebar_color" {
count++
if ($2 == "background") correct++
}
END { exit !(count == 1 && correct == 1) }
' "$config_file"; then
continue
fi
tmp=$(mktemp "$config_file.tmp.XXXXXX")
trap 'rm -f "$tmp"' EXIT HUP INT TERM
awk '$1 != "macos_titlebar_color"' "$config_file" > "$tmp"
printf '\nmacos_titlebar_color background\n' >> "$tmp"
chmod "$(stat -f '%Lp' "$config_file")" "$tmp"
mv -f "$tmp" "$config_file"
trap - EXIT HUP INT TERM
done

View File

@ -1,28 +1,23 @@
background #ffffff
foreground #4c4c4c
cursor #4c4c4c
selection_background #d6d6d6
background #f8f8f8
foreground #2a2b33
cursor #bbbbbb
selection_background #e5e5e6
color0 #000000
color8 #000000
color1 #c82828
color9 #c82828
color2 #708b00
color10 #708b00
color3 #e9b600
color11 #e9b600
color4 #4170ae
color12 #4170ae
color5 #8958a7
color13 #8958a7
color6 #3d999f
color14 #3d999f
color7 #fffefe
color15 #fffefe
selection_foreground #ffffff
active_tab_foreground #ffffff
active_tab_background #2e84e6
inactive_tab_foreground #2e84e6
inactive_tab_background #ffffff
color1 #de3d35
color9 #de3d35
color2 #3e953a
color10 #3e953a
color3 #d2b67b
color11 #d2b67b
color4 #2f5af3
color12 #2f5af3
color5 #950095
color13 #a00095
color6 #3e953a
color14 #3e953a
color7 #bbbbbb
color15 #ffffff
selection_foreground #2a2b33
macos_titlebar_color background

View File

@ -0,0 +1,65 @@
#!/bin/sh
set -eu
root=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT HUP INT TERM
config_dir="$tmpdir/config"
fake_bin="$tmpdir/bin"
log="$tmpdir/commands.log"
mkdir -p "$config_dir" "$fake_bin"
printf 'background #111111\n' > "$config_dir/dark-theme.auto.conf"
printf 'background #eeeeee\nmacos_titlebar_color system\n' \
> "$config_dir/light-theme.auto.conf"
printf 'background #222222\nmacos_titlebar_color background\n' \
> "$config_dir/no-preference-theme.auto.conf"
"$root/repair-auto-themes.sh" "$config_dir"
"$root/tests/verify_auto_themes.sh" "$config_dir"
for appearance in dark light no-preference; do
count=$(grep -c '^macos_titlebar_color background$' \
"$config_dir/$appearance-theme.auto.conf")
[ "$count" -eq 1 ]
done
before=$(shasum "$config_dir"/*-theme.auto.conf)
"$root/repair-auto-themes.sh" "$config_dir"
after=$(shasum "$config_dir"/*-theme.auto.conf)
[ "$before" = "$after" ]
cat > "$fake_bin/kitten" <<'EOF'
#!/bin/sh
printf 'kitten %s\n' "$*" >> "$TEST_LOG"
exit 0
EOF
cat > "$fake_bin/kitty" <<'EOF'
#!/bin/sh
printf 'kitty %s\n' "$*" >> "$TEST_LOG"
exit 0
EOF
chmod +x "$fake_bin/kitten" "$fake_bin/kitty"
printf 'background #fafafa\n' > "$config_dir/light-theme.auto.conf"
TEST_LOG="$log" PATH="$fake_bin:$PATH" \
KITTY_CONFIG_DIRECTORY="$config_dir" KITTY_WINDOW_ID=1 \
fish --no-config -c \
'source "$HOME/.config/fish/functions/kitten.fish"; kitten themes Tomorrow'
grep -q '^kitten themes Tomorrow$' "$log"
grep -q '^kitty @ load-config$' "$log"
"$root/tests/verify_auto_themes.sh" "$config_dir"
: > "$log"
TEST_LOG="$log" PATH="$fake_bin:$PATH" \
KITTY_CONFIG_DIRECTORY="$config_dir" KITTY_WINDOW_ID=1 \
fish --no-config -c \
'source "$HOME/.config/fish/functions/kitten.fish"; kitten icat image.png'
grep -q '^kitten icat image.png$' "$log"
if grep -q '^kitty ' "$log"; then
echo "non-theme kitten command triggered a Kitty reload" >&2
exit 1
fi
echo "PASS: theme repair is idempotent and the Fish shim only intercepts themes"

View File

@ -0,0 +1,93 @@
from importlib.util import module_from_spec, spec_from_file_location
from pathlib import Path
from kitty.fast_data_types import Color
from kitty.tab_bar import DrawData, ExtraData, TabBarData, as_rgb
class Cursor:
x = 0
fg = as_rgb(0xFEDCBA)
bg = as_rgb(0xABCDEF)
class RecordingScreen:
def __init__(self) -> None:
self.cursor = Cursor()
self.draws: list[tuple[str, int, int]] = []
def draw(self, text: str) -> None:
self.draws.append((text, self.cursor.fg, self.cursor.bg))
self.cursor.x += len(text)
def load_renderer():
path = Path.cwd() / "tab_bar.py"
spec = spec_from_file_location("kitty_user_tab_bar", path)
if spec is None or spec.loader is None:
raise RuntimeError(f"cannot load {path}")
module = module_from_spec(spec)
spec.loader.exec_module(module)
return module
def draw_data(theme_bg: int) -> DrawData:
return DrawData(
0,
"",
0,
"",
(),
Color(0x11, 0x11, 0x11),
Color(0xAB, 0xCD, 0xEF),
Color(0xFE, 0xDC, 0xBA),
Color(0x22, 0x22, 0x22),
Color((theme_bg >> 16) & 0xFF, (theme_bg >> 8) & 0xFF, theme_bg & 0xFF),
"",
None,
"",
"default",
"top",
0,
0,
)
renderer = load_renderer()
for theme_bg in (0xF8F8F8, 0x1C2836):
roles = renderer.tab_colors(draw_data(theme_bg).default_bg)
actual_roles = tuple(int(value) for value in roles)
expected_roles = (theme_bg, 0x2E84E6, 0x2E84E6, theme_bg)
if actual_roles != expected_roles:
raise RuntimeError(
f"theme #{theme_bg:06x}: expected roles {expected_roles!r}, "
f"got {actual_roles!r}"
)
for is_active, expected in (
(True, (as_rgb(theme_bg), as_rgb(0x2E84E6))),
(False, (as_rgb(0x2E84E6), as_rgb(theme_bg))),
):
screen = RecordingScreen()
renderer.draw_tab(
draw_data(theme_bg),
screen,
TabBarData("tab", is_active=is_active),
0,
1,
1,
True,
ExtraData(),
)
_, actual_fg, actual_bg = screen.draws[0]
if (actual_fg, actual_bg) != expected:
raise RuntimeError(
f"theme #{theme_bg:06x}, active={is_active}: "
f"expected cursor colors {expected!r}, "
f"got {(actual_fg, actual_bg)!r}"
)
print(
"PASS: tab colors ignore theme-provided tab roles "
"for light and dark backgrounds"
)

View File

@ -1,16 +1,35 @@
from kitty.fast_data_types import Screen
from typing import NamedTuple
from kitty.fast_data_types import Color, Screen
from kitty.tab_bar import DrawData, ExtraData, TabBarData, as_rgb, draw_title
class TabColors(NamedTuple):
active_fg: Color
active_bg: Color
inactive_fg: Color
inactive_bg: Color
TAB_ACCENT = Color(0x2e, 0x84, 0xe6)
def tab_colors(theme_bg: Color) -> TabColors:
return TabColors(theme_bg, TAB_ACCENT, TAB_ACCENT, theme_bg)
def draw_tab(
draw_data: DrawData, screen: Screen, tab: TabBarData,
before: int, max_title_length: int, index: int, is_last: bool,
extra_data: ExtraData
) -> int:
active_fg = draw_data.default_bg
colors = tab_colors(draw_data.default_bg)
fg = colors.active_fg if tab.is_active else colors.inactive_fg
bg = colors.active_bg if tab.is_active else colors.inactive_bg
default_bg = as_rgb(int(draw_data.default_bg))
orig_fg = as_rgb(int(active_fg)) if tab.is_active else screen.cursor.fg
orig_bg = screen.cursor.bg if tab.is_active else default_bg
title_draw_data = draw_data._replace(active_fg=active_fg) if tab.is_active else draw_data
orig_fg = as_rgb(int(fg))
orig_bg = as_rgb(int(bg))
title_draw_data = draw_data._replace(**colors._asdict())
screen.cursor.fg = orig_fg
screen.cursor.bg = orig_bg
left_sep, right_sep = ('', '')

View File

@ -0,0 +1,23 @@
function kitten --description 'Run kitten and restore Kitty theme overrides'
command kitten $argv
set -l kitten_status $status
if test $kitten_status -eq 0
and test (count $argv) -gt 0
and test "$argv[1]" = themes
set -l config_dir "$HOME/.config/kitty"
if set -q KITTY_CONFIG_DIRECTORY
set config_dir "$KITTY_CONFIG_DIRECTORY"
end
"$HOME/.config/kitty/repair-auto-themes.sh" "$config_dir"
or return $status
if set -q KITTY_WINDOW_ID
command kitty @ load-config
or return $status
end
end
return $kitten_status
end