diff --git a/kitty/config.py b/kitty/config.py index 406049e3e..4a3287361 100644 --- a/kitty/config.py +++ b/kitty/config.py @@ -7,8 +7,8 @@ from contextlib import contextmanager, suppress from functools import partial from typing import ( - Any, Callable, Dict, FrozenSet, Generator, Iterable, List, Optional, - Tuple, Type + Any, Callable, Dict, FrozenSet, Generator, Iterable, List, Optional, Tuple, + Type ) from .conf.definition import as_conf_file, config_lines @@ -17,32 +17,17 @@ parse_config_base, to_bool ) from .config_data import all_options -from .constants import cache_dir, defconf, is_macos -from .options_stub import Options as OptionsStub +from .constants import cache_dir, defconf from .options.utils import ( - KeyDefinition, KeyMap, MouseMap, MouseMapping, SequenceMap, env, - font_features, kitten_alias, parse_map, parse_mouse_map, symbol_map + KeyDefinition, KeyMap, MouseMap, MouseMapping, SequenceMap, + deprecated_hide_window_decorations_aliases, + deprecated_macos_show_window_title_in_menubar_alias, env, font_features, + kitten_alias, parse_map, parse_mouse_map, parse_send_text, symbol_map ) +from .options_stub import Options as OptionsStub from .typing import TypedDict from .utils import log_error - -def parse_send_text(val: str, key_definitions: List[KeyDefinition]) -> None: - parts = val.split(' ') - - def abort(msg: str) -> None: - log_error('Send text: {} is invalid ({}), ignoring'.format( - val, msg)) - - if len(parts) < 3: - return abort('Incomplete') - mode, sc = parts[:2] - text = ' '.join(parts[2:]) - key_str = '{} send_text {} {}'.format(sc, mode, text) - for k in parse_map(key_str): - key_definitions.append(k) - - SpecialHandlerFunc = Callable[[str, str, Dict[str, Any]], None] special_handlers: Dict[str, SpecialHandlerFunc] = {} @@ -93,7 +78,7 @@ def handle_kitten_alias(key: str, val: str, ans: Dict[str, Any]) -> None: @special_handler def handle_send_text(key: str, val: str, ans: Dict[str, Any]) -> None: # For legacy compatibility - parse_send_text(val, ans['key_definitions']) + parse_send_text(val, ans) @special_handler @@ -104,31 +89,12 @@ def handle_clear_all_shortcuts(key: str, val: str, ans: Dict[str, Any]) -> None: @deprecated_handler('x11_hide_window_decorations', 'macos_hide_titlebar') def handle_deprecated_hide_window_decorations_aliases(key: str, val: str, ans: Dict[str, Any]) -> None: - if not hasattr(handle_deprecated_hide_window_decorations_aliases, key): - setattr(handle_deprecated_hide_window_decorations_aliases, key, True) - log_error('The option {} is deprecated. Use hide_window_decorations instead.'.format(key)) - if to_bool(val): - if is_macos and key == 'macos_hide_titlebar' or (not is_macos and key == 'x11_hide_window_decorations'): - ans['hide_window_decorations'] = True + deprecated_hide_window_decorations_aliases(key, val, ans) @deprecated_handler('macos_show_window_title_in_menubar') def handle_deprecated_macos_show_window_title_in_menubar_alias(key: str, val: str, ans: Dict[str, Any]) -> None: - if not hasattr(handle_deprecated_macos_show_window_title_in_menubar_alias, key): - setattr(handle_deprecated_macos_show_window_title_in_menubar_alias, 'key', True) - log_error('The option {} is deprecated. Use macos_show_window_title_in menubar instead.'.format(key)) - macos_show_window_title_in = ans.get('macos_show_window_title_in', 'all') - if to_bool(val): - if macos_show_window_title_in == 'none': - macos_show_window_title_in = 'menubar' - elif macos_show_window_title_in == 'window': - macos_show_window_title_in = 'all' - else: - if macos_show_window_title_in == 'all': - macos_show_window_title_in = 'window' - elif macos_show_window_title_in == 'menubar': - macos_show_window_title_in = 'none' - ans['macos_show_window_title_in'] = macos_show_window_title_in + deprecated_macos_show_window_title_in_menubar_alias(key, val, ans) @special_handler diff --git a/kitty/options/utils.py b/kitty/options/utils.py index 1ea5b2380..48c806c6d 100644 --- a/kitty/options/utils.py +++ b/kitty/options/utils.py @@ -18,7 +18,7 @@ key_func, positive_float, positive_int, python_string, to_bool, to_cmdline, to_color, uniq, unit_float ) -from kitty.constants import config_dir +from kitty.constants import config_dir, is_macos from kitty.fonts import FontFeature from kitty.key_names import ( character_key_name_aliases, functional_key_name_aliases, @@ -907,3 +907,46 @@ def parse_mouse_map(val: str) -> Iterable[MouseMapping]: return for mode in specified_modes: yield MouseMapping(button, mods, count, mode == 'grabbed', paction) + + +def deprecated_hide_window_decorations_aliases(key: str, val: str, ans: Dict[str, Any]) -> None: + if not hasattr(deprecated_hide_window_decorations_aliases, key): + setattr(deprecated_hide_window_decorations_aliases, key, True) + log_error('The option {} is deprecated. Use hide_window_decorations instead.'.format(key)) + if to_bool(val): + if is_macos and key == 'macos_hide_titlebar' or (not is_macos and key == 'x11_hide_window_decorations'): + ans['hide_window_decorations'] = True + + +def deprecated_macos_show_window_title_in_menubar_alias(key: str, val: str, ans: Dict[str, Any]) -> None: + if not hasattr(deprecated_macos_show_window_title_in_menubar_alias, key): + setattr(deprecated_macos_show_window_title_in_menubar_alias, 'key', True) + log_error('The option {} is deprecated. Use macos_show_window_title_in menubar instead.'.format(key)) + macos_show_window_title_in = ans.get('macos_show_window_title_in', 'all') + if to_bool(val): + if macos_show_window_title_in == 'none': + macos_show_window_title_in = 'menubar' + elif macos_show_window_title_in == 'window': + macos_show_window_title_in = 'all' + else: + if macos_show_window_title_in == 'all': + macos_show_window_title_in = 'window' + elif macos_show_window_title_in == 'menubar': + macos_show_window_title_in = 'none' + ans['macos_show_window_title_in'] = macos_show_window_title_in + + +def parse_send_text(val: str, ans: Dict[str, Any]) -> None: + parts = val.split(' ') + + def abort(msg: str) -> None: + log_error('Send text: {} is invalid ({}), ignoring'.format( + val, msg)) + + if len(parts) < 3: + return abort('Incomplete') + mode, sc = parts[:2] + text = ' '.join(parts[2:]) + key_str = '{} send_text {} {}'.format(sc, mode, text) + for k in parse_map(key_str): + ans['key_definitions'].append(k) diff --git a/kitty/utils.py b/kitty/utils.py index 014f55107..b831869c9 100644 --- a/kitty/utils.py +++ b/kitty/utils.py @@ -72,9 +72,10 @@ def safe_print(*a: Any, **k: Any) -> None: def log_error(*a: Any, **k: str) -> None: from .fast_data_types import log_error_string + output = getattr(log_error, 'redirect', log_error_string) with suppress(Exception): - msg = k.get('sep', ' ').join(map(str, a)) + k.get('end', '') - log_error_string(msg.replace('\0', '')) + msg = k.get('sep', ' ').join(map(str, a)) + k.get('end', '').replace('\0', '') + output(msg) def ceil_int(x: float) -> int: diff --git a/kitty_tests/options.py b/kitty_tests/options.py index 15d92e837..74be590f0 100644 --- a/kitty_tests/options.py +++ b/kitty_tests/options.py @@ -4,10 +4,18 @@ from . import BaseTest +from kitty.utils import log_error class TestConfParsing(BaseTest): + def setUp(self): + self.error_messages = [] + log_error.redirect = self.error_messages.append + + def tearDown(self): + del log_error.redirect + def test_conf_parsing(self): from kitty.config import load_config, defaults from kitty.constants import is_macos @@ -16,6 +24,7 @@ def test_conf_parsing(self): def p(*lines, bad_line_num=0): del bad_lines[:] + del self.error_messages[:] ans = load_config(overrides=lines, accumulate_bad_lines=bad_lines) self.ae(len(bad_lines), bad_line_num) return ans @@ -44,3 +53,9 @@ def keys_for_func(opts, name): opts = p('kitty_mod alt') self.ae(opts.kitty_mod, to_modifiers('alt')) self.ae(next(keys_for_func(opts, 'next_layout')).mods, opts.kitty_mod) + # deprecation handling + opts = p('clear_all_shortcuts y', 'send_text all f1 hello') + self.ae(len(opts.keymap), 1) + opts = p('x11_hide_window_decorations y') + self.assertTrue(opts.hide_window_decorations) + self.ae(len(self.error_messages), 1)