feat: add keyboard mapping display functionality for different modes
This commit is contained in:
@@ -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,
|
||||||
|
)
|
||||||
@@ -55,6 +55,9 @@ map kitty_mod+right next_tab
|
|||||||
map ctrl+tab next_tab
|
map ctrl+tab next_tab
|
||||||
map kitty_mod+q close_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
|
# Create a new window splitting the space used by the existing one so that
|
||||||
# the two windows are placed one above the other
|
# the two windows are placed one above the other
|
||||||
map f5 launch --location=hsplit
|
map f5 launch --location=hsplit
|
||||||
|
|||||||
Reference in New Issue
Block a user