Files
GenericAgent/frontends/keysym.py
T
dd3xp b1352f2de1 chore: sync framework to upstream lsdefine/GenericAgent @ b365945
上次同步点是 1eb8c4c (我们 fork 上为 8f89766),lsdefine 自那以来 102 个

commit,包括飞书 IM 插件、TUI v2 修、conductor OOP 重构、L4 scheduler

mkdir 修复、checklist 系统、computer_use SOP 等。

处理分桶:

  - 45 个 lsdefine-only 文件:整文件覆盖(safe,无我方改动)

  - 17 个 ours-only 文件:完全保留(桌面前端 + bridge + plan_state)

  - 4 个双方都动:逐个 3-way 合

      * .gitignore: 取并集(lsdefine 新增 + 我们 /BUG_*.md)

      * reflect/scheduler.py: 已字节对齐 lsdefine,无操作

      * frontends/conductor.py: lsdefine OOP 重构作 base,我们 6 处

          改动(CORS / add_chat files+images / cost_tracker / token-stats

          / WS running / WS receive files+images)原样塞进新结构

      * frontends/conductor.html: lsdefine 重组作 base,我们 40 行

          输入字数限制 + toast 原样塞进 keydown 监听之后

未触动 desktop_bridge.py(memory 规则约定 exclude bridge)。

已 grep 全文件无 <<<<<< / ======= / >>>>>> 冲突标记残留。

我们改动一行未漏,全部按原代码原文落实,没有自创新代码。
2026-06-06 23:05:59 +08:00

73 lines
2.5 KiB
Python

"""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"]