From 7090c243218de1f12c9fd557d9ee9d98a506f1e5 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 4 Aug 2021 14:13:09 +0530 Subject: [PATCH] More work on the themes kitten --- kittens/themes/collection.py | 10 +++++ kittens/themes/main.py | 75 ++++++++++++++++++++++++++++++++++-- kittens/tui/operations.py | 10 +++++ 3 files changed, 92 insertions(+), 3 deletions(-) diff --git a/kittens/themes/collection.py b/kittens/themes/collection.py index df763383d..c3cf6c0bd 100644 --- a/kittens/themes/collection.py +++ b/kittens/themes/collection.py @@ -19,6 +19,8 @@ from kitty.config import parse_config from kitty.constants import cache_dir, config_dir from kitty.rgb import Color +from ..choose.main import match + def fetch_themes( name: str = 'kitty-themes', @@ -226,6 +228,14 @@ class Themes: ans.themes = {k: v for k, v in self.themes.items() if is_ok(v)} return ans + def apply_search(self, expression: str, mark_before: str = '\033[32m', mark_after: str = '\033[39m') -> Iterator[str]: + for k, v in tuple(self.themes.items()): + result = match(v.name, expression, mark_before=mark_before, mark_after=mark_after) + if result and result[0]: + yield result[0] + else: + del self.themes[k] + def load_themes() -> Themes: ans = Themes() diff --git a/kittens/themes/main.py b/kittens/themes/main.py index 39c8694f2..1d1833725 100644 --- a/kittens/themes/main.py +++ b/kittens/themes/main.py @@ -6,9 +6,12 @@ import os import sys import traceback from enum import Enum, auto -from typing import Any, Callable, Dict, Iterable, List, Optional, Union +from typing import ( + Any, Callable, Dict, Iterable, Iterator, List, Optional, Tuple, Union +) from kitty.config import cached_values_for +from kitty.fast_data_types import wcswidth from kitty.typing import KeyEventType from kitty.utils import ScreenSize @@ -48,6 +51,43 @@ def create_recent_filter(names: Iterable[str]) -> Callable[[Theme], bool]: return recent_filter +class ThemesList: + + def __init__(self) -> None: + self.themes = Themes() + self.current_search: str = '' + self.display_strings: Tuple[str, ...] = () + self.widths: Tuple[int, ...] = () + self.max_width = 0 + self.current_idx = 0 + + def update_themes(self, themes: Themes) -> None: + self.themes = themes + if self.current_search: + self.display_strings = tuple(self.themes.apply_search(self.current_search)) + else: + self.display_strings = tuple(t.name for t in self.themes) + self.widths = tuple(map(wcswidth, self.display_strings)) + self.max_width = max(self.widths) if self.widths else 0 + + def update_search(self, search: str = '') -> None: + if search == self.current_search: + return + self.current_search = search + self.update_themes(self.themes) + + def lines(self, num_rows: int) -> Iterator[str]: + if num_rows < 1: + return + before_num = min(self.current_idx, num_rows - 1) + start = self.current_idx - before_num + for i in range(start, min(start + num_rows, len(self.display_strings))): + line = self.display_strings[i] + if i == self.current_idx: + line = styled(line, reverse=True) + yield line + + class ThemesHandler(Handler): def __init__(self, cached_values: Dict[str, Any]) -> None: @@ -58,11 +98,13 @@ class ThemesHandler(Handler): 'dark': dark_filter, 'light': light_filter, 'all': all_filter, 'recent': create_recent_filter(self.cached_values.get('recent', ())) } + self.themes_list = ThemesList() def enforce_cursor_state(self) -> None: self.cmd.set_cursor_visible(self.state == State.fetching) def init_terminal_state(self) -> None: + self.cmd.save_colors() self.cmd.set_line_wrapping(False) self.cmd.set_window_title('Choose a theme for kitty') self.cmd.set_cursor_shape('bar') @@ -73,9 +115,26 @@ class ThemesHandler(Handler): self.fetch_themes() def finalize(self) -> None: - self.cmd.set_default_colors() + self.cmd.restore_colors() self.cmd.set_cursor_visible(True) + @property + def current_category(self) -> str: + cat: str = self.cached_values.get('category', 'all') + if cat not in self.filter_map: + cat = 'all' + return cat + + @current_category.setter + def current_category(self, cat: str) -> None: + if cat not in self.filter_map: + cat = 'all' + self.cached_values['category'] = cat + + def redraw_after_category_change(self) -> None: + self.themes_list.update_themes(self.all_themes.filtered(self.filter_map[self.current_category])) + self.draw_screen() + # Theme fetching {{{ def fetch_themes(self) -> None: @@ -86,7 +145,7 @@ class ThemesHandler(Handler): return self.all_themes: Themes = themes_or_exception self.state = State.browsing - self.draw_screen() + self.redraw_after_category_change() def fetch() -> None: try: @@ -107,6 +166,14 @@ class ThemesHandler(Handler): # }}} + # Theme browsing {{{ + def draw_tab_bar(self) -> None: + pass + + def draw_browsing_screen(self) -> None: + self.draw_tab_bar() + # }}} + def on_key_event(self, key_event: KeyEventType, in_bracketed_paste: bool = False) -> None: if self.state is State.fetching: self.on_fetching_key_event(key_event, in_bracketed_paste) @@ -116,6 +183,8 @@ class ThemesHandler(Handler): self.enforce_cursor_state() if self.state is State.fetching: self.draw_fetching_screen() + elif self.state is State.browsing: + self.draw_browsing_screen() def on_resize(self, screen_size: ScreenSize) -> None: self.screen_size = screen_size diff --git a/kittens/tui/operations.py b/kittens/tui/operations.py index 531882391..8a1a8cf06 100644 --- a/kittens/tui/operations.py +++ b/kittens/tui/operations.py @@ -350,6 +350,16 @@ def set_default_colors( return ans +@cmd +def save_colors() -> str: + return '\x1b[#P' + + +@cmd +def restore_colors() -> str: + return '\x1b[#Q' + + @cmd def write_to_clipboard(data: Union[str, bytes], use_primary: bool = False) -> str: from base64 import standard_b64encode