fix(tui-v2): add missing keysym.py — tuiapp_v2 ImportError on fresh clone
`tuiapp_v2.py:27` imports `fmt_key`, `fmt_keys` from `keysym`, but the module file was never tracked. PR #513 (tui v2/v3 fixes) is unusable on a fresh checkout without this. Adds the cross-platform shortcut formatter that turns binding strings into mac/Win-Linux key labels (e.g. `"ctrl+b"` → `"⌃B"` / `"Ctrl+B"`), honoring `GA_KEYSYM_STYLE`.
This commit is contained in:
1 parent
5f92cd1b80
commit
bebc3ba9e8
1 file changed
+72
@@ -0,0 +1,72 @@
|
||||
"""Cross-platform keyboard-shortcut display formatter.
|
||||
|
||||
One job: turn a Textual binding string like ``"ctrl+b"`` into a human-facing
|
||||
label such as ``"Ctrl+B"`` on Win/Linux or ``"⌃B"`` on macOS.
|
||||
|
||||
Binding strings (the *physical* keys Textual captures) are NOT touched —
|
||||
this module only formats labels for tips / footers / help panels.
|
||||
|
||||
Override with env ``GA_KEYSYM_STYLE=auto|mac|ascii`` (default ``auto``).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
_STYLE = os.environ.get("GA_KEYSYM_STYLE", "auto").lower()
|
||||
IS_MAC = _STYLE == "mac" or (_STYLE != "ascii" and sys.platform == "darwin")
|
||||
|
||||
# Modifier display per style. mac uses Apple HIG glyphs; others use words.
|
||||
_MOD = {
|
||||
"ctrl": "⌃" if IS_MAC else "Ctrl",
|
||||
"shift": "⇧" if IS_MAC else "Shift",
|
||||
"alt": "⌥" if IS_MAC else "Alt",
|
||||
"meta": "⌘" if IS_MAC else "Alt",
|
||||
"super": "⌘" if IS_MAC else "Win",
|
||||
"cmd": "⌘" if IS_MAC else "Win",
|
||||
}
|
||||
|
||||
# Bare-key display. Arrows / slash are universal; rest mac-glyphs vs words.
|
||||
_KEY = {
|
||||
"enter": "⏎" if IS_MAC else "Enter",
|
||||
"tab": "⇥" if IS_MAC else "Tab",
|
||||
"escape": "⎋" if IS_MAC else "Esc",
|
||||
"esc": "⎋" if IS_MAC else "Esc",
|
||||
"backspace": "⌫" if IS_MAC else "Backspace",
|
||||
"delete": "⌦" if IS_MAC else "Del",
|
||||
"space": "␣" if IS_MAC else "Space",
|
||||
"up": "↑", "down": "↓", "left": "←", "right": "→",
|
||||
"slash": "/", "underscore": "_",
|
||||
}
|
||||
|
||||
# Joiner between modifier and key. mac concatenates (⌃B); others use '+'.
|
||||
_JOIN = "" if IS_MAC else "+"
|
||||
|
||||
|
||||
def fmt_key(combo: str) -> str:
|
||||
"""``"ctrl+b"`` → ``"⌃B"`` (mac) / ``"Ctrl+B"`` (Win/Linux).
|
||||
|
||||
Unknown single-char keys are upper-cased (``"b"`` → ``"B"``);
|
||||
multi-char names fall back to the original token unchanged.
|
||||
"""
|
||||
parts = [p.strip() for p in combo.lower().split("+") if p.strip()]
|
||||
if not parts:
|
||||
return combo
|
||||
mods, key = parts[:-1], parts[-1]
|
||||
key_disp = _KEY.get(key) or (key.upper() if len(key) == 1 else key)
|
||||
mod_disp = [_MOD.get(m, m) for m in mods]
|
||||
if not mod_disp:
|
||||
return key_disp
|
||||
return _JOIN.join(mod_disp) + _JOIN + key_disp
|
||||
|
||||
|
||||
def fmt_keys(*combos: str, sep: str = " / ") -> str:
|
||||
"""Join multiple combos: ``fmt_keys("ctrl+j", "ctrl+enter")`` →
|
||||
``"Ctrl+J / Ctrl+Enter"`` or ``"⌃J / ⌃⏎"``."""
|
||||
return sep.join(fmt_key(c) for c in combos)
|
||||
|
||||
|
||||
# Convenience constants for f-string templates.
|
||||
CTRL = _MOD["ctrl"]
|
||||
SHIFT = _MOD["shift"]
|
||||
ALT = _MOD["alt"]
|
||||
Reference in new issue
Block a user