From d01ac17334f696d5749c48a6548432d3856d591c Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 7 Aug 2021 15:04:32 +0530 Subject: [PATCH] Implement placing of selected theme in kitty config dir --- kittens/themes/collection.py | 5 +++- kittens/themes/main.py | 49 ++++++++++++++++++++++++++++++++++++ kitty/config.py | 2 +- 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/kittens/themes/collection.py b/kittens/themes/collection.py index 1b9043aa7..3771201e7 100644 --- a/kittens/themes/collection.py +++ b/kittens/themes/collection.py @@ -15,7 +15,7 @@ from typing import Any, Callable, Dict, Iterator, Match, Optional, Tuple, Union from urllib.error import HTTPError from urllib.request import Request, urlopen -from kitty.config import parse_config +from kitty.config import atomic_save, parse_config from kitty.constants import cache_dir, config_dir from kitty.options.types import Options as KittyOptions from kitty.rgb import Color @@ -198,6 +198,9 @@ class Theme: self._opts = KittyOptions(options_dict=parse_config(self.raw.splitlines())) return self._opts + def save_in_dir(self, dirpath: str) -> None: + atomic_save(self.raw.encode('utf-8'), os.path.join(dirpath, f'{self.name}.conf')) + class Themes: diff --git a/kittens/themes/main.py b/kittens/themes/main.py index 5dc7b7313..e423d8d51 100644 --- a/kittens/themes/main.py +++ b/kittens/themes/main.py @@ -13,6 +13,7 @@ from typing import ( from kitty.cli import create_default_opts from kitty.config import cached_values_for +from kitty.constants import config_dir from kitty.fast_data_types import truncate_point_for_length, wcswidth from kitty.rgb import color_as_sharp, color_from_int from kitty.typing import KeyEventType @@ -42,6 +43,7 @@ class State(Enum): fetching = auto() browsing = auto() searching = auto() + accepting = auto() def dark_filter(q: Theme) -> bool: @@ -392,6 +394,12 @@ class ThemesHandler(Handler): return self.next(delta=3 - self.screen_size.rows, allow_wrapping=False) if key_event.matches('s') or key_event.matches('/'): return self.start_search() + if key_event.matches('c') or key_event.matches('enter'): + if not self.themes_list: + self.cmd.beep() + return + self.state = State.accepting + return self.draw_screen() def start_search(self) -> None: self.line_edit.clear() @@ -412,6 +420,42 @@ class ThemesHandler(Handler): self.cmd.bell() # }}} + # Accepting {{{ + def draw_accepting_screen(self) -> None: + name = self.themes_list.current_theme.name + name = styled(name, bold=True, fg="green") + kc = styled('kitty.conf', italic=True) + + def ac(x: str) -> str: + return styled(x, fg='red') + + self.cmd.set_line_wrapping(True) + self.print(f'You have chosen the {name} theme') + self.print() + self.print('What would you like to do?') + self.print() + self.print(' ', f'{ac("M")}odify {kc} to load', styled(name, bold=True, fg="green")) + self.print() + self.print(' ', f'{ac("P")}lace the theme file in {config_dir} but do not modify {kc}') + self.print() + self.print(' ', f'{ac("A")}bort and return to list of themes') + self.print() + self.print(' ', f'{ac("Q")}uit') + + def on_accepting_key_event(self, key_event: KeyEventType, in_bracketed_paste: bool = False) -> None: + if key_event.matches('q') or key_event.matches('esc'): + self.quit_loop(0) + return + if key_event.matches('a'): + self.state = State.browsing + self.draw_screen() + return + if key_event.matches('p'): + self.themes_list.current_theme.save_in_dir(config_dir) + self.quit_loop(0) + return + # }}} + 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) @@ -419,15 +463,20 @@ class ThemesHandler(Handler): self.on_browsing_key_event(key_event, in_bracketed_paste) elif self.state is State.searching: self.on_searching_key_event(key_event, in_bracketed_paste) + elif self.state is State.accepting: + self.on_accepting_key_event(key_event, in_bracketed_paste) def draw_screen(self) -> None: with self.pending_update(): self.cmd.clear_screen() self.enforce_cursor_state() + self.cmd.set_line_wrapping(False) if self.state is State.fetching: self.draw_fetching_screen() elif self.state in (State.browsing, State.searching): self.draw_browsing_screen() + elif self.state is State.accepting: + self.draw_accepting_screen() def on_resize(self, screen_size: ScreenSize) -> None: self.screen_size = screen_size diff --git a/kitty/config.py b/kitty/config.py index 4b450ad56..b6e7e30e7 100644 --- a/kitty/config.py +++ b/kitty/config.py @@ -40,7 +40,7 @@ def atomic_save(data: bytes, path: str) -> None: try: with os.fdopen(fd, 'wb') as f: f.write(data) - os.rename(p, path) + os.replace(p, path) finally: try: os.remove(p)