mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-15 18:01:22 +00:00
feat(tui): add symbol key support to keybinding system (#450)
- Added SymbolKey type with 32 symbol keys - Added symbol key constants to Key helper (Key.backtick, Key.comma, Key.period, etc.) - Updated matchesKey() and parseKey() to handle symbol key input - Added documentation in coding-agent README with examples
This commit is contained in:
parent
61cadc226c
commit
b836a9d2ee
2 changed files with 131 additions and 4 deletions
|
|
@ -272,7 +272,12 @@ Both modes are configurable via `/settings`: "one-at-a-time" delivers messages o
|
|||
|
||||
All keyboard shortcuts can be customized via `~/.pi/agent/keybindings.json`. Each action can be bound to one or more keys.
|
||||
|
||||
**Key format:** `modifier+key` where modifiers are `ctrl`, `shift`, `alt` and keys are `a-z`, `0-9`, `escape`, `tab`, `enter`, `space`, `backspace`, `delete`, `home`, `end`, `up`, `down`, `left`, `right`.
|
||||
**Key format:** `modifier+key` where modifiers are `ctrl`, `shift`, `alt` and keys are:
|
||||
|
||||
- Letters: `a-z`
|
||||
- Numbers: `0-9`
|
||||
- Special keys: `escape`, `tab`, `enter`, `space`, `backspace`, `delete`, `home`, `end`, `up`, `down`, `left`, `right`
|
||||
- Symbol keys: `` ` ``, `-`, `=`, `[`, `]`, `\`, `;`, `'`, `,`, `.`, `/`, `!`, `@`, `#`, `$`, `%`, `^`, `&`, `*`, `(`, `)`, `_`, `+`, `|`, `~`, `{`, `}`, `:`, `<`, `>`, `?`
|
||||
|
||||
**Configurable actions:**
|
||||
|
||||
|
|
@ -338,6 +343,21 @@ All keyboard shortcuts can be customized via `~/.pi/agent/keybindings.json`. Eac
|
|||
}
|
||||
```
|
||||
|
||||
**Example (symbol keys):**
|
||||
|
||||
```json
|
||||
{
|
||||
"submit": ["enter", "ctrl+j"],
|
||||
"newLine": ["shift+enter", "ctrl+;"],
|
||||
"toggleThinking": "ctrl+/",
|
||||
"cycleModelForward": "ctrl+.",
|
||||
"cycleModelBackward": "ctrl+,",
|
||||
"interrupt": ["escape", "ctrl+`"]
|
||||
}
|
||||
```
|
||||
|
||||
> **Note:** Some `ctrl+symbol` combinations overlap with ASCII control characters due to terminal legacy behavior (e.g., `ctrl+[` is the same as Escape, `ctrl+M` is the same as Enter). These can still be used with `ctrl+shift+key` (e.g., `ctrl+shift+]`). See [Kitty keyboard protocol: legacy ctrl mapping of ASCII keys](https://sw.kovidgoyal.net/kitty/keyboard-protocol/#legacy-ctrl-mapping-of-ascii-keys) for all unsupported keys.
|
||||
|
||||
### Bash Mode
|
||||
|
||||
Prefix commands with `!` to execute them and add output to context:
|
||||
|
|
|
|||
|
|
@ -4,6 +4,11 @@
|
|||
* Supports both legacy terminal sequences and Kitty keyboard protocol.
|
||||
* See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/
|
||||
*
|
||||
* Symbol keys are also supported, however some ctrl+symbol combos
|
||||
* overlap with ASCII codes, e.g. ctrl+[ = ESC.
|
||||
* See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/#legacy-ctrl-mapping-of-ascii-keys
|
||||
* Those can still be * used for ctrl+shift combos
|
||||
*
|
||||
* API:
|
||||
* - matchesKey(data, keyId) - Check if input matches a key identifier
|
||||
* - parseKey(data) - Parse input and return the key identifier
|
||||
|
|
@ -42,6 +47,39 @@ type Letter =
|
|||
| "y"
|
||||
| "z";
|
||||
|
||||
type SymbolKey =
|
||||
| "`"
|
||||
| "-"
|
||||
| "="
|
||||
| "["
|
||||
| "]"
|
||||
| "\\"
|
||||
| ";"
|
||||
| "'"
|
||||
| ","
|
||||
| "."
|
||||
| "/"
|
||||
| "!"
|
||||
| "@"
|
||||
| "#"
|
||||
| "$"
|
||||
| "%"
|
||||
| "^"
|
||||
| "&"
|
||||
| "*"
|
||||
| "("
|
||||
| ")"
|
||||
| "_"
|
||||
| "+"
|
||||
| "|"
|
||||
| "~"
|
||||
| "{"
|
||||
| "}"
|
||||
| ":"
|
||||
| "<"
|
||||
| ">"
|
||||
| "?";
|
||||
|
||||
type SpecialKey =
|
||||
| "escape"
|
||||
| "esc"
|
||||
|
|
@ -58,7 +96,7 @@ type SpecialKey =
|
|||
| "left"
|
||||
| "right";
|
||||
|
||||
type BaseKey = Letter | SpecialKey;
|
||||
type BaseKey = Letter | SymbolKey | SpecialKey;
|
||||
|
||||
/**
|
||||
* Union type of all valid key identifiers.
|
||||
|
|
@ -87,6 +125,7 @@ export type KeyId =
|
|||
*
|
||||
* Usage:
|
||||
* - Key.escape, Key.enter, Key.tab, etc. for special keys
|
||||
* - Key.backtick, Key.comma, Key.period, etc. for symbol keys
|
||||
* - Key.ctrl("c"), Key.alt("x") for single modifier
|
||||
* - Key.ctrlShift("p"), Key.ctrlAlt("x") for combined modifiers
|
||||
*/
|
||||
|
|
@ -107,6 +146,39 @@ export const Key = {
|
|||
left: "left" as const,
|
||||
right: "right" as const,
|
||||
|
||||
// Symbol keys
|
||||
backtick: "`" as const,
|
||||
hyphen: "-" as const,
|
||||
equals: "=" as const,
|
||||
leftbracket: "[" as const,
|
||||
rightbracket: "]" as const,
|
||||
backslash: "\\" as const,
|
||||
semicolon: ";" as const,
|
||||
quote: "'" as const,
|
||||
comma: "," as const,
|
||||
period: "." as const,
|
||||
slash: "/" as const,
|
||||
exclamation: "!" as const,
|
||||
at: "@" as const,
|
||||
hash: "#" as const,
|
||||
dollar: "$" as const,
|
||||
percent: "%" as const,
|
||||
caret: "^" as const,
|
||||
ampersand: "&" as const,
|
||||
asterisk: "*" as const,
|
||||
leftparen: "(" as const,
|
||||
rightparen: ")" as const,
|
||||
underscore: "_" as const,
|
||||
plus: "+" as const,
|
||||
pipe: "|" as const,
|
||||
tilde: "~" as const,
|
||||
leftbrace: "{" as const,
|
||||
rightbrace: "}" as const,
|
||||
colon: ":" as const,
|
||||
lessthan: "<" as const,
|
||||
greaterthan: ">" as const,
|
||||
question: "?" as const,
|
||||
|
||||
// Single modifiers
|
||||
ctrl: <K extends BaseKey>(key: K): `ctrl+${K}` => `ctrl+${key}`,
|
||||
shift: <K extends BaseKey>(key: K): `shift+${K}` => `shift+${key}`,
|
||||
|
|
@ -128,6 +200,40 @@ export const Key = {
|
|||
// Constants
|
||||
// =============================================================================
|
||||
|
||||
const SYMBOL_KEYS = new Set([
|
||||
"`",
|
||||
"-",
|
||||
"=",
|
||||
"[",
|
||||
"]",
|
||||
"\\",
|
||||
";",
|
||||
"'",
|
||||
",",
|
||||
".",
|
||||
"/",
|
||||
"!",
|
||||
"@",
|
||||
"#",
|
||||
"$",
|
||||
"%",
|
||||
"^",
|
||||
"&",
|
||||
"*",
|
||||
"(",
|
||||
")",
|
||||
"_",
|
||||
"+",
|
||||
"|",
|
||||
"~",
|
||||
"{",
|
||||
"}",
|
||||
":",
|
||||
"<",
|
||||
">",
|
||||
"?",
|
||||
]);
|
||||
|
||||
const MODIFIERS = {
|
||||
shift: 1,
|
||||
alt: 2,
|
||||
|
|
@ -403,8 +509,8 @@ export function matchesKey(data: string, keyId: KeyId): boolean {
|
|||
return matchesKittySequence(data, ARROW_CODEPOINTS.right, modifier);
|
||||
}
|
||||
|
||||
// Handle single letter keys (a-z)
|
||||
if (key.length === 1 && key >= "a" && key <= "z") {
|
||||
// Handle single letter keys (a-z) and some symbols
|
||||
if (key.length === 1 && ((key >= "a" && key <= "z") || SYMBOL_KEYS.has(key))) {
|
||||
const codepoint = key.charCodeAt(0);
|
||||
|
||||
if (ctrl && !shift && !alt) {
|
||||
|
|
@ -464,6 +570,7 @@ export function parseKey(data: string): string | undefined {
|
|||
else if (codepoint === ARROW_CODEPOINTS.left) keyName = "left";
|
||||
else if (codepoint === ARROW_CODEPOINTS.right) keyName = "right";
|
||||
else if (codepoint >= 97 && codepoint <= 122) keyName = String.fromCharCode(codepoint);
|
||||
else if (SYMBOL_KEYS.has(String.fromCharCode(codepoint))) keyName = String.fromCharCode(codepoint);
|
||||
|
||||
if (keyName) {
|
||||
return mods.length > 0 ? `${mods.join("+")}+${keyName}` : keyName;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue