feat: add keyboard mapping display functionality for different modes

This commit is contained in:
2024-08-23 10:12:32 -04:00
parent 5b465d83e9
commit 284a9e64c2
2 changed files with 118 additions and 0 deletions
+115
View File
@@ -0,0 +1,115 @@
#!/usr/bin/env python3
"""Kitten to print the current list of keyboard shortcuts (consists of BOTH single keys and key
sequences).
"""
import string
import re
from collections import defaultdict
from typing import Union, Final, Dict, List
from kittens.tui.handler import result_handler
from kitty import fast_data_types
from kitty.boss import Boss
from kitty.options.utils import 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 = {
"Scrolling": r"(^scroll_|show_scrollback|show_last_command_output)",
"Tab Management": r"(^|_)tab(_|$)",
"Window Management": r"(^|_)windows?(_|$)",
"Layout Management": r"(^|_)layout(_|\b)",
"Other Shortcuts": r".",
}
ShortcutRepr = str
ActionMap = dict[str, list[ShortcutRepr]]
def main(args: list[str]) -> Union[str, None]:
pass
@result_handler(no_ui=True)
def handle_result(args: list[str], answer: str, target_window_id: int, boss: Boss):
opts = fast_data_types.get_options()
modes_categorized: Dict[str, Dict[str, ActionMap]] = {}
for mode_name, mode_data in opts.keyboard_modes.items():
# set up keymaps (single keystrokes)
# keymap: KeyMap = (
# boss.keymap
# mode_data.keymap
# ) # same as `opts.keymap`, except with global keymaps removed
# keymap: dict[Shortcut, str] = {
# Shortcut((key,)): action for key, action in keymap.items()
# }
# set up key sequences (combinations of keystrokes, separated by '>')
# seq_keymap: dict[Shortcut, str] = {
# Shortcut((inner_key.trigger, *(inner_key.rest or []))): inner_key.definition
# for key, subseq in keymap.items()
# for inner_key in subseq
# for subseq_keys, action in subseq.items()
# }
seq_keymap = {}
for key, subseq in mode_data.keymap.items():
# debug_file.write(f"{key}, {subseq}\n")
# debug_file.write(f"{type(key)}, {type(subseq)}\n")
for inner_key in subseq:
trigger = inner_key.trigger
rest = inner_key.rest or []
shortcut = Shortcut((trigger, *rest))
definition = inner_key.definition
seq_keymap[shortcut] = definition
# keymap.update(seq_keymap)
# 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 seq_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 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:
output_categorized["Other Shortcuts"][action].append(key_repr)
# emsg = f"No valid subheader found for keymap {key_repr!r}."
# raise ValueError(emsg)
modes_categorized[mode_name] = output_categorized
# print out shortcuts
output = [
"Kitty keyboard mappings",
"=======================",
"",
"My kitty_mod is {}.".format("+".join(mod_to_names(opts.kitty_mod))),
"",
]
for mode_name, output_categorized in modes_categorized.items():
hr_output_name = mode_name or "Standard"
output.append("=" * 40)
output.append(f"{hr_output_name} Mode")
output.append("=" * 40)
for category in categories:
if category not in output_categorized:
continue
output.extend([category, "=" * len(category), ""])
output.extend(sum(output_categorized[category].values(), []))
output.append("")
boss.display_scrollback(
boss.active_window,
"\n".join(output),
title="Kitty keyboard mappings",
report_cursor=False,
)
+3
View File
@@ -55,6 +55,9 @@ map kitty_mod+right next_tab
map ctrl+tab next_tab
map kitty_mod+q close_tab
# Kitty which-key
map kitty_mod+F1 kitten keymap.py
# Create a new window splitting the space used by the existing one so that
# the two windows are placed one above the other
map f5 launch --location=hsplit