Nicer fix for #8124

Now colors from the auto themes are first merged onto the default colors
to ensure that themes that dont specify all colors still have correct
values for all colors.
This commit is contained in:
Kovid Goyal 2024-12-20 15:06:22 +05:30
parent 35b3ae8edb
commit 9d304ccbc6
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
2 changed files with 31 additions and 5 deletions

View file

@ -90,7 +90,9 @@ Detailed list of changes
- macOS: Fix a regression in the previous release that broke rendering of Emoji using the VS16 variation selector (:iss:`8130`)
- themes kitten: When using the *Default* theme as an auto switch theme include all the actual settings values (:iss:`8124`)
- When automatically changing colors based on OS color preference, first reset
all colors to default before applying the new theme so that even colors not
specified in the theme are correct (:iss:`8124`)
- Graphics: Fix deleted but not freed images without any references being incorrectly freed on a subsequent delete command (:disc:`8129`)

View file

@ -16,6 +16,7 @@
ColorsSpec = dict[str, Optional[int]]
TransparentBackgroundColors = tuple[tuple[Color, float], ...]
ColorSchemes = Literal['light', 'dark', 'no_preference']
Colors = tuple[ColorsSpec, TransparentBackgroundColors]
class ThemeFile(Enum):
@ -30,6 +31,29 @@ class ThemeColors:
light_mtime: int = -1
no_preference_mtime: int = -1
applied_theme: Literal['light', 'dark', 'no_preference', ''] = ''
default_colors: Optional[ColorsSpec] = None
def get_default_colors(self) -> ColorsSpec:
if self.default_colors is None:
from kitty.options.types import defaults, option_names
ans: ColorsSpec = dict.fromkeys(nullable_colors)
for name in option_names:
defval = getattr(defaults, name)
if isinstance(defval, Color):
ans[name] = int(defval)
self.default_colors = ans
return self.default_colors
def parse_colors(self, f: Iterable[str]) -> Colors:
# When parsing the theme file we first apply the default theme so that
# all colors are reset to default values first. This is needed for themes
# that don't specify all colors.
spec, tbc = parse_colors((f,))
dc_spec = self.get_default_colors()
ans = dc_spec.copy()
ans.update(spec)
return ans, tbc
def refresh(self) -> bool:
found = False
@ -39,21 +63,21 @@ def refresh(self) -> bool:
mtime = x.stat().st_mtime_ns
if mtime > self.dark_mtime:
with open(x.path) as f:
self.dark_spec, self.dark_tbc = parse_colors((f,))
self.dark_spec, self.dark_tbc = self.parse_colors(f)
self.dark_mtime = mtime
found = True
elif x.name == ThemeFile.light.value:
mtime = x.stat().st_mtime_ns
if mtime > self.light_mtime:
with open(x.path) as f:
self.light_spec, self.light_tbc = parse_colors((f,))
self.light_spec, self.light_tbc = self.parse_colors(f)
self.light_mtime = mtime
found = True
elif x.name == ThemeFile.no_preference.value:
mtime = x.stat().st_mtime_ns
if mtime > self.no_preference_mtime:
with open(x.path) as f:
self.no_preference_spec, self.no_preference_tbc = parse_colors((f,))
self.no_preference_spec, self.no_preference_tbc = self.parse_colors(f)
self.no_preference_mtime = mtime
found = True
return found
@ -123,7 +147,7 @@ def on_system_color_scheme_change(self, new_value: ColorSchemes, is_initial_valu
theme_colors = ThemeColors()
def parse_colors(args: Iterable[Union[str, Iterable[str]]]) -> tuple[ColorsSpec, TransparentBackgroundColors]:
def parse_colors(args: Iterable[Union[str, Iterable[str]]]) -> Colors:
colors: dict[str, Optional[Color]] = {}
nullable_color_map: dict[str, Optional[int]] = {}
transparent_background_colors = ()