diff --git a/.config/kitty/kitty.conf b/.config/kitty/kitty.conf index 310c4b7..4a865fa 100644 --- a/.config/kitty/kitty.conf +++ b/.config/kitty/kitty.conf @@ -9,7 +9,7 @@ enable_audio_bell no window_alert_on_bell no # 下划线位置(偏下) -modify_font underline_position 1 +modify_font underline_position 2 # 更细的边框线条字符 box_drawing_scale 0.001, 0.1, 1, 2 @@ -38,7 +38,6 @@ map kitty_mod+f scroll_page_down map kitty_mod+b scroll_page_up ### 标签页和窗口 -map ctrl+g>ctrl+t new_tab map ctrl+g>t detach_tab ask #### 插入 diff --git a/.config/kitty/scripts/list_keys.py b/.config/kitty/scripts/list_keys.py index ac975c5..2a324c5 100644 --- a/.config/kitty/scripts/list_keys.py +++ b/.config/kitty/scripts/list_keys.py @@ -2,24 +2,27 @@ """Kitten to print the current list of keyboard shortcuts (consists of BOTH single keys and key sequences). -https://github.com/kovidgoyal/kitty/issues/2164#issuecomment-1501097471 +https://github.com/kovidgoyal/kitty/issues/2164#issuecomment-2566950824 """ import re from collections import defaultdict -from typing import Optional, Union, Final +from collections.abc import Sequence +from typing import TypeAlias from kittens.tui.handler import result_handler from kitty import fast_data_types from kitty.boss import Boss -from kitty.options.utils import KeyMap, MouseEvent, SequenceMap +from kitty.options.types import Options as KittyOpts +from kitty.options.utils import KeyboardMode, KeyDefinition, KeyMap from kitty.tab_bar import Formatter as fmt from kitty.types import Shortcut, mod_to_names # List of categories and regular expressions to match actions on -categories: Final = { - "Scrollback": r"(^scroll_|show_scrollback|.*show.*_command_output)", - "Tab Management": r"(^|_)tab( |_|$)", +# Keyboard modes are categorized into their own category +categories: dict[str, str | None] = { + "Scrollback": r"(^scroll_|show_scrollback|show_last_command_output)", + "Tab Management": r"(^|_)tab(_|$| )", "Window Management": r"(^|_)windows?(_|$)", "Layout Management": r"(^|_)layout(_|\b)", "Hints": r"(_|\b)hints\b", @@ -30,60 +33,80 @@ categories: Final = { "Other Shortcuts": r".", } -ShortcutRepr = str -ActionMap = dict[str, list[ShortcutRepr]] +Shortcut2Defn: TypeAlias = dict[Shortcut, str] +ShortcutRepr: TypeAlias = str +ActionMap: TypeAlias = dict[str, list[ShortcutRepr]] -def main(args: list[str]) -> Optional[str]: +def main(_args: list[str]) -> str | None: pass @result_handler(no_ui=True) -def handle_result(args: list[str], answer: str, target_window_id: int, boss: Boss): +def handle_result( + _args: list[str], _answer: str, _target_window_id: int, boss: Boss +): if boss.active_window is None: return - opts = fast_data_types.get_options() + opts: KittyOpts = fast_data_types.get_options() - # set up keymaps (single keystrokes) - _keymap: KeyMap = ( - boss.keymap - ) # same as `opts.keymap`, except with global keymaps removed - keymap: dict[Union[Shortcut, MouseEvent], str] = { - Shortcut((key,)): action for key, action in _keymap.items() - } - # set up key sequences (combinations of keystrokes, separated by '>') - _seq_keymap: SequenceMap = opts.sequence_map - seq_keymap: dict[Shortcut, str] = { - Shortcut((key, *subseq_keys)): action - for key, subseq in _seq_keymap.items() - for subseq_keys, action in subseq.items() - } - keymap.update(seq_keymap.items()) + output_categorized: dict[str, ActionMap] = defaultdict( + lambda: defaultdict(list) + ) + for mode in opts.keyboard_modes.values(): + mode: KeyboardMode + mode_name: str = mode.name or "default" + mode_keymap: KeyMap = mode.keymap - # and mousemap - mousemap: dict[MouseEvent, str] = opts.mousemap - keymap.update(mousemap.items()) + # set up keymaps (single keystrokes) + key sequences (combinations of keystrokes) + key_mappings: Shortcut2Defn = {} + for key, definitions in mode_keymap.items(): + # key: SingleKey + definitions: Sequence[KeyDefinition] - # categorize shortcuts - # because each action can have multiple shortcuts associated with it, we also attempt to - # group shortcuts with the same actions together. - output_categorized: dict[str, ActionMap] = defaultdict(lambda: defaultdict(list)) - for key, action in keymap.items(): - key_repr: ShortcutRepr = key.human_repr(kitty_mod=opts.kitty_mod) - key_repr = f"{key_repr:<15} {fmt.fg.red}→{fmt.fg.default} {action}" + for defn in definitions: + action = defn.human_repr() + if defn.is_sequence: + key_mappings[Shortcut((defn.trigger,) + defn.rest)] = ( + action + ) + else: + key_mappings[Shortcut((key,))] = action - for subheader, re_pat in categories.items(): - if re.search(re_pat, action): - action_map: ActionMap = output_categorized[subheader] - action_map[action].append(key_repr) - break - else: - emsg = f"No valid subheader found for keymap {key_repr!r}." - raise ValueError(emsg) + # categorize the default mode shortcuts + # because each action can have multiple shortcuts associated with it, we also attempt to + # group shortcuts with the same actions together. + for key, action in key_mappings.items(): + key_repr: ShortcutRepr = key.human_repr(kitty_mod=opts.kitty_mod) + key_repr = f"{key_repr:<18} {fmt.fg.red}→{fmt.fg.default}" + if match := re.search(r"^push_keyboard_mode (\w+)$", action): + # bold the mode name if found + action_fmt = f"push_keyboard_mode {fmt.bold}{match.group(1)}{fmt.nobold}" + key_repr = f"{key_repr} {action_fmt}" + else: + key_repr = f"{key_repr} {action}" + + if mode_name != "default": + mn = f"Mode {mode_name}" + categories[mn] = ( + None # register this mode as a valid "category" + ) + output_categorized[mn][action].append(key_repr) + continue + + for subheader, re_pat in categories.items(): + if re_pat and re.search(re_pat, action): + action_map: ActionMap = output_categorized[subheader] + action_map[action].append(key_repr) + break + else: + emsg = f"No valid subheader found for keymap {key_repr!r}." + raise ValueError(emsg) # print out shortcuts output = [ + "=======================", "Kitty keyboard mappings", "=======================", "", @@ -93,7 +116,9 @@ def handle_result(args: list[str], answer: str, target_window_id: int, boss: Bos for category in categories: if category not in output_categorized: continue - output.extend([category, "=" * len(category), ""]) + output.extend( + [f"{fmt.bold}{category}{fmt.nobold}", "=" * len(category), ""] + ) output.extend(sum(output_categorized[category].values(), [])) output.append("") diff --git a/.config/kitty/scripts/pyproject.toml b/.config/kitty/scripts/pyproject.toml index a8926a1..18a5f07 100644 --- a/.config/kitty/scripts/pyproject.toml +++ b/.config/kitty/scripts/pyproject.toml @@ -1,2 +1,5 @@ [tool.pyright] extraPaths = ["/usr/lib/kitty"] + +[tool.ruff] +line-length = 79