@m4ike1/ion-tui 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +114 -0
- package/dist/alt-screen-search.d.ts +46 -0
- package/dist/alt-screen-search.d.ts.map +1 -0
- package/dist/alt-screen-search.js +282 -0
- package/dist/alt-screen-search.js.map +1 -0
- package/dist/autocomplete.d.ts +75 -0
- package/dist/autocomplete.d.ts.map +1 -0
- package/dist/autocomplete.js +749 -0
- package/dist/autocomplete.js.map +1 -0
- package/dist/components/alt-screen-flash.d.ts +13 -0
- package/dist/components/alt-screen-flash.d.ts.map +1 -0
- package/dist/components/alt-screen-flash.js +37 -0
- package/dist/components/alt-screen-flash.js.map +1 -0
- package/dist/components/box.d.ts +24 -0
- package/dist/components/box.d.ts.map +1 -0
- package/dist/components/box.js +133 -0
- package/dist/components/box.js.map +1 -0
- package/dist/components/cancellable-loader.d.ts +22 -0
- package/dist/components/cancellable-loader.d.ts.map +1 -0
- package/dist/components/cancellable-loader.js +35 -0
- package/dist/components/cancellable-loader.js.map +1 -0
- package/dist/components/editor.d.ts +266 -0
- package/dist/components/editor.d.ts.map +1 -0
- package/dist/components/editor.js +2087 -0
- package/dist/components/editor.js.map +1 -0
- package/dist/components/h-stack.d.ts +7 -0
- package/dist/components/h-stack.d.ts.map +1 -0
- package/dist/components/h-stack.js +43 -0
- package/dist/components/h-stack.js.map +1 -0
- package/dist/components/image.d.ts +28 -0
- package/dist/components/image.d.ts.map +1 -0
- package/dist/components/image.js +90 -0
- package/dist/components/image.js.map +1 -0
- package/dist/components/input.d.ts +48 -0
- package/dist/components/input.d.ts.map +1 -0
- package/dist/components/input.js +417 -0
- package/dist/components/input.js.map +1 -0
- package/dist/components/loader.d.ts +33 -0
- package/dist/components/loader.d.ts.map +1 -0
- package/dist/components/loader.js +76 -0
- package/dist/components/loader.js.map +1 -0
- package/dist/components/markdown.d.ts +103 -0
- package/dist/components/markdown.d.ts.map +1 -0
- package/dist/components/markdown.js +858 -0
- package/dist/components/markdown.js.map +1 -0
- package/dist/components/mouse-region.d.ts +12 -0
- package/dist/components/mouse-region.d.ts.map +1 -0
- package/dist/components/mouse-region.js +21 -0
- package/dist/components/mouse-region.js.map +1 -0
- package/dist/components/scroll-view.d.ts +68 -0
- package/dist/components/scroll-view.d.ts.map +1 -0
- package/dist/components/scroll-view.js +199 -0
- package/dist/components/scroll-view.js.map +1 -0
- package/dist/components/select-list.d.ts +53 -0
- package/dist/components/select-list.d.ts.map +1 -0
- package/dist/components/select-list.js +206 -0
- package/dist/components/select-list.js.map +1 -0
- package/dist/components/settings-list.d.ts +60 -0
- package/dist/components/settings-list.d.ts.map +1 -0
- package/dist/components/settings-list.js +252 -0
- package/dist/components/settings-list.js.map +1 -0
- package/dist/components/spacer.d.ts +12 -0
- package/dist/components/spacer.d.ts.map +1 -0
- package/dist/components/spacer.js +23 -0
- package/dist/components/spacer.js.map +1 -0
- package/dist/components/stack.d.ts +32 -0
- package/dist/components/stack.d.ts.map +1 -0
- package/dist/components/stack.js +111 -0
- package/dist/components/stack.js.map +1 -0
- package/dist/components/text.d.ts +19 -0
- package/dist/components/text.d.ts.map +1 -0
- package/dist/components/text.js +90 -0
- package/dist/components/text.js.map +1 -0
- package/dist/components/truncated-text.d.ts +13 -0
- package/dist/components/truncated-text.d.ts.map +1 -0
- package/dist/components/truncated-text.js +51 -0
- package/dist/components/truncated-text.js.map +1 -0
- package/dist/components/v-stack.d.ts +8 -0
- package/dist/components/v-stack.d.ts.map +1 -0
- package/dist/components/v-stack.js +26 -0
- package/dist/components/v-stack.js.map +1 -0
- package/dist/components/virtual-list.d.ts +51 -0
- package/dist/components/virtual-list.d.ts.map +1 -0
- package/dist/components/virtual-list.js +170 -0
- package/dist/components/virtual-list.js.map +1 -0
- package/dist/editor-component.d.ts +39 -0
- package/dist/editor-component.d.ts.map +1 -0
- package/dist/editor-component.js +2 -0
- package/dist/editor-component.js.map +1 -0
- package/dist/fuzzy.d.ts +16 -0
- package/dist/fuzzy.d.ts.map +1 -0
- package/dist/fuzzy.js +110 -0
- package/dist/fuzzy.js.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +46 -0
- package/dist/index.js.map +1 -0
- package/dist/keybindings.d.ts +366 -0
- package/dist/keybindings.d.ts.map +1 -0
- package/dist/keybindings.js +331 -0
- package/dist/keybindings.js.map +1 -0
- package/dist/keys.d.ts +184 -0
- package/dist/keys.d.ts.map +1 -0
- package/dist/keys.js +1174 -0
- package/dist/keys.js.map +1 -0
- package/dist/kill-ring.d.ts +28 -0
- package/dist/kill-ring.d.ts.map +1 -0
- package/dist/kill-ring.js +44 -0
- package/dist/kill-ring.js.map +1 -0
- package/dist/latex.d.ts +10 -0
- package/dist/latex.d.ts.map +1 -0
- package/dist/latex.js +1285 -0
- package/dist/latex.js.map +1 -0
- package/dist/layout-node.d.ts +59 -0
- package/dist/layout-node.d.ts.map +1 -0
- package/dist/layout-node.js +12 -0
- package/dist/layout-node.js.map +1 -0
- package/dist/layout.d.ts +42 -0
- package/dist/layout.d.ts.map +1 -0
- package/dist/layout.js +404 -0
- package/dist/layout.js.map +1 -0
- package/dist/native-modifiers.d.ts +4 -0
- package/dist/native-modifiers.d.ts.map +1 -0
- package/dist/native-modifiers.js +13 -0
- package/dist/native-modifiers.js.map +1 -0
- package/dist/native-module-path.d.ts +7 -0
- package/dist/native-module-path.d.ts.map +1 -0
- package/dist/native-module-path.js +19 -0
- package/dist/native-module-path.js.map +1 -0
- package/dist/native-platform.d.ts +18 -0
- package/dist/native-platform.d.ts.map +1 -0
- package/dist/native-platform.js +42 -0
- package/dist/native-platform.js.map +1 -0
- package/dist/pty-host.d.ts +224 -0
- package/dist/pty-host.d.ts.map +1 -0
- package/dist/pty-host.js +347 -0
- package/dist/pty-host.js.map +1 -0
- package/dist/stdin-buffer.d.ts +56 -0
- package/dist/stdin-buffer.d.ts.map +1 -0
- package/dist/stdin-buffer.js +366 -0
- package/dist/stdin-buffer.js.map +1 -0
- package/dist/terminal-colors.d.ts +10 -0
- package/dist/terminal-colors.d.ts.map +1 -0
- package/dist/terminal-colors.js +59 -0
- package/dist/terminal-colors.js.map +1 -0
- package/dist/terminal-image.d.ts +118 -0
- package/dist/terminal-image.d.ts.map +1 -0
- package/dist/terminal-image.js +550 -0
- package/dist/terminal-image.js.map +1 -0
- package/dist/terminal.d.ts +123 -0
- package/dist/terminal.d.ts.map +1 -0
- package/dist/terminal.js +442 -0
- package/dist/terminal.js.map +1 -0
- package/dist/tui-alt-screen.d.ts +165 -0
- package/dist/tui-alt-screen.d.ts.map +1 -0
- package/dist/tui-alt-screen.js +1515 -0
- package/dist/tui-alt-screen.js.map +1 -0
- package/dist/tui-main-screen.d.ts +39 -0
- package/dist/tui-main-screen.d.ts.map +1 -0
- package/dist/tui-main-screen.js +594 -0
- package/dist/tui-main-screen.js.map +1 -0
- package/dist/tui.d.ts +431 -0
- package/dist/tui.d.ts.map +1 -0
- package/dist/tui.js +1142 -0
- package/dist/tui.js.map +1 -0
- package/dist/undo-stack.d.ts +17 -0
- package/dist/undo-stack.d.ts.map +1 -0
- package/dist/undo-stack.js +25 -0
- package/dist/undo-stack.js.map +1 -0
- package/dist/utils.d.ts +98 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +1200 -0
- package/dist/utils.js.map +1 -0
- package/dist/word-navigation.d.ts +25 -0
- package/dist/word-navigation.d.ts.map +1 -0
- package/dist/word-navigation.js +96 -0
- package/dist/word-navigation.js.map +1 -0
- package/native/clipboard.h +170 -0
- package/native/darwin/README.md +22 -0
- package/native/darwin/build.sh +69 -0
- package/native/darwin/prebuilds/darwin-arm64/darwin-platform.node +0 -0
- package/native/darwin/prebuilds/darwin-x64/darwin-platform.node +0 -0
- package/native/darwin/src/darwin-platform.m +93 -0
- package/native/linux/README.md +23 -0
- package/native/linux/build.sh +65 -0
- package/native/linux/prebuilds/linux-arm64/linux-platform-x11.node +0 -0
- package/native/linux/prebuilds/linux-x64/linux-platform-x11.node +0 -0
- package/native/linux/src/clipboard-worker.h +70 -0
- package/native/linux/src/linux-platform-x11.c +274 -0
- package/native/napi.h +89 -0
- package/native/win32/README.md +31 -0
- package/native/win32/build.mjs +232 -0
- package/native/win32/prebuilds/win32-arm64/win32-platform.node +0 -0
- package/native/win32/prebuilds/win32-x64/win32-platform.node +0 -0
- package/native/win32/src/win32-platform.c +241 -0
- package/package.json +62 -0
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
import { matchesKey } from "./keys.js";
|
|
2
|
+
export const TUI_KEYBINDINGS = {
|
|
3
|
+
"tui.editor.cursorUp": { context: "editor", defaultKeys: "up", description: "Move cursor up" },
|
|
4
|
+
"tui.editor.cursorDown": { context: "editor", defaultKeys: "down", description: "Move cursor down" },
|
|
5
|
+
"tui.editor.historyPrevious": {
|
|
6
|
+
context: "editor",
|
|
7
|
+
defaultKeys: [],
|
|
8
|
+
description: "Select previous prompt history entry",
|
|
9
|
+
},
|
|
10
|
+
"tui.editor.historyNext": {
|
|
11
|
+
context: "editor",
|
|
12
|
+
defaultKeys: [],
|
|
13
|
+
description: "Select next prompt history entry",
|
|
14
|
+
},
|
|
15
|
+
"tui.editor.cursorLeft": {
|
|
16
|
+
context: "editor",
|
|
17
|
+
defaultKeys: ["left", "ctrl+b"],
|
|
18
|
+
description: "Move cursor left",
|
|
19
|
+
},
|
|
20
|
+
"tui.editor.cursorRight": {
|
|
21
|
+
context: "editor",
|
|
22
|
+
defaultKeys: ["right", "ctrl+f"],
|
|
23
|
+
description: "Move cursor right",
|
|
24
|
+
},
|
|
25
|
+
"tui.editor.cursorWordLeft": {
|
|
26
|
+
context: "editor",
|
|
27
|
+
defaultKeys: ["alt+left", "ctrl+left", "alt+b"],
|
|
28
|
+
description: "Move cursor word left",
|
|
29
|
+
},
|
|
30
|
+
"tui.editor.cursorWordRight": {
|
|
31
|
+
context: "editor",
|
|
32
|
+
defaultKeys: ["alt+right", "ctrl+right", "alt+f"],
|
|
33
|
+
description: "Move cursor word right",
|
|
34
|
+
},
|
|
35
|
+
"tui.editor.cursorLineStart": {
|
|
36
|
+
context: "editor",
|
|
37
|
+
defaultKeys: ["home", "ctrl+home", "ctrl+a"],
|
|
38
|
+
description: "Move to line start",
|
|
39
|
+
},
|
|
40
|
+
"tui.editor.cursorLineEnd": {
|
|
41
|
+
context: "editor",
|
|
42
|
+
defaultKeys: ["end", "ctrl+end", "ctrl+e"],
|
|
43
|
+
description: "Move to line end",
|
|
44
|
+
},
|
|
45
|
+
"tui.editor.jumpForward": {
|
|
46
|
+
context: "editor",
|
|
47
|
+
defaultKeys: "ctrl+]",
|
|
48
|
+
description: "Jump forward to character",
|
|
49
|
+
},
|
|
50
|
+
"tui.editor.jumpBackward": {
|
|
51
|
+
context: "editor",
|
|
52
|
+
defaultKeys: "ctrl+alt+]",
|
|
53
|
+
description: "Jump backward to character",
|
|
54
|
+
},
|
|
55
|
+
"tui.editor.pageUp": {
|
|
56
|
+
context: "editor",
|
|
57
|
+
defaultKeys: ["pageUp", "ctrl+pageUp"],
|
|
58
|
+
description: "Page up",
|
|
59
|
+
},
|
|
60
|
+
"tui.editor.pageDown": {
|
|
61
|
+
context: "editor",
|
|
62
|
+
defaultKeys: ["pageDown", "ctrl+pageDown"],
|
|
63
|
+
description: "Page down",
|
|
64
|
+
},
|
|
65
|
+
"tui.editor.deleteCharBackward": {
|
|
66
|
+
context: "editor",
|
|
67
|
+
defaultKeys: "backspace",
|
|
68
|
+
description: "Delete character backward",
|
|
69
|
+
},
|
|
70
|
+
"tui.editor.deleteCharForward": {
|
|
71
|
+
context: "editor",
|
|
72
|
+
defaultKeys: ["delete", "ctrl+d"],
|
|
73
|
+
description: "Delete character forward",
|
|
74
|
+
},
|
|
75
|
+
"tui.editor.deleteWordBackward": {
|
|
76
|
+
context: "editor",
|
|
77
|
+
defaultKeys: ["ctrl+w", "alt+backspace"],
|
|
78
|
+
description: "Delete word backward",
|
|
79
|
+
},
|
|
80
|
+
"tui.editor.deleteWordForward": {
|
|
81
|
+
context: "editor",
|
|
82
|
+
defaultKeys: ["alt+d", "alt+delete"],
|
|
83
|
+
description: "Delete word forward",
|
|
84
|
+
},
|
|
85
|
+
"tui.editor.deleteToLineStart": {
|
|
86
|
+
context: "editor",
|
|
87
|
+
defaultKeys: "ctrl+u",
|
|
88
|
+
description: "Delete to line start",
|
|
89
|
+
},
|
|
90
|
+
"tui.editor.deleteToLineEnd": {
|
|
91
|
+
context: "editor",
|
|
92
|
+
defaultKeys: "ctrl+k",
|
|
93
|
+
description: "Delete to line end",
|
|
94
|
+
},
|
|
95
|
+
"tui.editor.yank": { context: "editor", defaultKeys: "ctrl+y", description: "Yank" },
|
|
96
|
+
"tui.editor.yankPop": { context: "editor", defaultKeys: "alt+y", description: "Yank pop" },
|
|
97
|
+
"tui.editor.undo": { context: "editor", defaultKeys: "ctrl+-", description: "Undo" },
|
|
98
|
+
"tui.input.newLine": {
|
|
99
|
+
context: "editor",
|
|
100
|
+
defaultKeys: ["shift+enter", "ctrl+j"],
|
|
101
|
+
description: "Insert newline",
|
|
102
|
+
},
|
|
103
|
+
"tui.input.submit": { context: "editor", defaultKeys: "enter", description: "Submit input" },
|
|
104
|
+
"tui.input.tab": { context: "editor", defaultKeys: "tab", description: "Tab / autocomplete" },
|
|
105
|
+
"tui.input.copy": { context: "editor", defaultKeys: "ctrl+c", description: "Copy selection" },
|
|
106
|
+
// Selection lists share keys (up/down/enter/escape/...) with editor and
|
|
107
|
+
// transcript bindings by design; the single focus owner resolves them.
|
|
108
|
+
"tui.select.up": { context: "dialog", defaultKeys: "up", description: "Move selection up" },
|
|
109
|
+
"tui.select.down": { context: "dialog", defaultKeys: "down", description: "Move selection down" },
|
|
110
|
+
"tui.select.pageUp": { context: "dialog", defaultKeys: "pageUp", description: "Selection page up" },
|
|
111
|
+
"tui.select.pageDown": {
|
|
112
|
+
context: "dialog",
|
|
113
|
+
defaultKeys: "pageDown",
|
|
114
|
+
description: "Selection page down",
|
|
115
|
+
},
|
|
116
|
+
"tui.select.confirm": { context: "dialog", defaultKeys: "enter", description: "Confirm selection" },
|
|
117
|
+
"tui.select.cancel": {
|
|
118
|
+
context: "dialog",
|
|
119
|
+
defaultKeys: ["escape", "ctrl+c"],
|
|
120
|
+
description: "Cancel selection",
|
|
121
|
+
},
|
|
122
|
+
// These intentionally shadow the unmodified editor bindings in fullscreen mode.
|
|
123
|
+
// Viewport navigation shares keys (pageUp/pageDown/home/end/enter/escape/...)
|
|
124
|
+
// with editor and dialog bindings by design; the focus owner resolves them.
|
|
125
|
+
"tui.altScreen.pageUp": {
|
|
126
|
+
context: "transcript",
|
|
127
|
+
defaultKeys: "pageUp",
|
|
128
|
+
description: "Scroll viewport up one page",
|
|
129
|
+
},
|
|
130
|
+
"tui.altScreen.pageDown": {
|
|
131
|
+
context: "transcript",
|
|
132
|
+
defaultKeys: "pageDown",
|
|
133
|
+
description: "Scroll viewport down one page",
|
|
134
|
+
},
|
|
135
|
+
"tui.altScreen.halfPageUp": {
|
|
136
|
+
context: "transcript",
|
|
137
|
+
defaultKeys: [],
|
|
138
|
+
description: "Scroll viewport up half a page",
|
|
139
|
+
},
|
|
140
|
+
"tui.altScreen.halfPageDown": {
|
|
141
|
+
context: "transcript",
|
|
142
|
+
defaultKeys: [],
|
|
143
|
+
description: "Scroll viewport down half a page",
|
|
144
|
+
},
|
|
145
|
+
"tui.altScreen.lineUp": {
|
|
146
|
+
context: "transcript",
|
|
147
|
+
defaultKeys: [],
|
|
148
|
+
description: "Scroll viewport up one line",
|
|
149
|
+
},
|
|
150
|
+
"tui.altScreen.lineDown": {
|
|
151
|
+
context: "transcript",
|
|
152
|
+
defaultKeys: [],
|
|
153
|
+
description: "Scroll viewport down one line",
|
|
154
|
+
},
|
|
155
|
+
"tui.altScreen.previousPrompt": {
|
|
156
|
+
context: "transcript",
|
|
157
|
+
defaultKeys: ["ctrl+shift+up", "ctrl+up"],
|
|
158
|
+
description: "Jump to previous semantic prompt",
|
|
159
|
+
},
|
|
160
|
+
"tui.altScreen.nextPrompt": {
|
|
161
|
+
context: "transcript",
|
|
162
|
+
defaultKeys: ["ctrl+shift+down", "ctrl+down"],
|
|
163
|
+
description: "Jump to next semantic prompt",
|
|
164
|
+
},
|
|
165
|
+
"tui.altScreen.search": {
|
|
166
|
+
context: "transcript",
|
|
167
|
+
defaultKeys: "ctrl+shift+f",
|
|
168
|
+
description: "Search the primary scroll view",
|
|
169
|
+
},
|
|
170
|
+
"tui.altScreen.searchNext": {
|
|
171
|
+
context: "transcript",
|
|
172
|
+
defaultKeys: ["enter", "ctrl+g"],
|
|
173
|
+
description: "Select the next search match",
|
|
174
|
+
},
|
|
175
|
+
"tui.altScreen.searchPrevious": {
|
|
176
|
+
context: "transcript",
|
|
177
|
+
defaultKeys: ["shift+enter", "ctrl+shift+g"],
|
|
178
|
+
description: "Select the previous search match",
|
|
179
|
+
},
|
|
180
|
+
"tui.altScreen.searchClose": {
|
|
181
|
+
context: "transcript",
|
|
182
|
+
defaultKeys: "escape",
|
|
183
|
+
description: "Close transcript search",
|
|
184
|
+
},
|
|
185
|
+
"tui.altScreen.top": { context: "transcript", defaultKeys: "home", description: "Scroll viewport to top" },
|
|
186
|
+
"tui.altScreen.bottom": { context: "transcript", defaultKeys: "end", description: "Scroll viewport to bottom" },
|
|
187
|
+
};
|
|
188
|
+
function normalizeKeys(keys) {
|
|
189
|
+
if (keys === undefined)
|
|
190
|
+
return [];
|
|
191
|
+
const keyList = Array.isArray(keys) ? keys : [keys];
|
|
192
|
+
const seen = new Set();
|
|
193
|
+
const result = [];
|
|
194
|
+
for (const key of keyList) {
|
|
195
|
+
if (!seen.has(key)) {
|
|
196
|
+
seen.add(key);
|
|
197
|
+
result.push(key);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return result;
|
|
201
|
+
}
|
|
202
|
+
export class KeybindingsManager {
|
|
203
|
+
definitions;
|
|
204
|
+
userBindings;
|
|
205
|
+
keysById = new Map();
|
|
206
|
+
conflicts = [];
|
|
207
|
+
constructor(definitions, userBindings = {}) {
|
|
208
|
+
this.definitions = definitions;
|
|
209
|
+
this.userBindings = userBindings;
|
|
210
|
+
this.rebuild();
|
|
211
|
+
}
|
|
212
|
+
rebuild() {
|
|
213
|
+
this.keysById.clear();
|
|
214
|
+
this.conflicts = [];
|
|
215
|
+
const userClaims = new Map();
|
|
216
|
+
for (const [keybinding, keys] of Object.entries(this.userBindings)) {
|
|
217
|
+
if (!(keybinding in this.definitions))
|
|
218
|
+
continue;
|
|
219
|
+
for (const key of normalizeKeys(keys)) {
|
|
220
|
+
const claimants = userClaims.get(key) ?? new Set();
|
|
221
|
+
claimants.add(keybinding);
|
|
222
|
+
userClaims.set(key, claimants);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
for (const [key, keybindings] of userClaims) {
|
|
226
|
+
if (keybindings.size > 1) {
|
|
227
|
+
this.conflicts.push({ key, keybindings: [...keybindings] });
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
for (const [id, definition] of Object.entries(this.definitions)) {
|
|
231
|
+
const userKeys = this.userBindings[id];
|
|
232
|
+
const keys = userKeys === undefined ? normalizeKeys(definition.defaultKeys) : normalizeKeys(userKeys);
|
|
233
|
+
this.keysById.set(id, keys);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
matches(data, keybinding) {
|
|
237
|
+
const keys = this.keysById.get(keybinding) ?? [];
|
|
238
|
+
for (const key of keys) {
|
|
239
|
+
if (matchesKey(data, key))
|
|
240
|
+
return true;
|
|
241
|
+
}
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
getKeys(keybinding) {
|
|
245
|
+
return [...(this.keysById.get(keybinding) ?? [])];
|
|
246
|
+
}
|
|
247
|
+
getDefinition(keybinding) {
|
|
248
|
+
return this.definitions[keybinding];
|
|
249
|
+
}
|
|
250
|
+
getConflicts() {
|
|
251
|
+
return this.conflicts.map((conflict) => ({ ...conflict, keybindings: [...conflict.keybindings] }));
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Routing context declared for a binding. Extension bindings without a
|
|
255
|
+
* declared context default to `global`.
|
|
256
|
+
*/
|
|
257
|
+
getContext(keybinding) {
|
|
258
|
+
return this.definitions[keybinding]?.context ?? "global";
|
|
259
|
+
}
|
|
260
|
+
/** All binding ids declared for one routing context. */
|
|
261
|
+
getBindingsByContext(context) {
|
|
262
|
+
const result = [];
|
|
263
|
+
for (const id of Object.keys(this.definitions)) {
|
|
264
|
+
if (this.getContext(id) === context) {
|
|
265
|
+
result.push(id);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return result;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Same-key claims within a single routing context across resolved bindings
|
|
272
|
+
* (defaults plus user overrides). Cross-context sharing (e.g. `enter` for
|
|
273
|
+
* both editor submit and dialog confirm) is intentional and resolved by the
|
|
274
|
+
* focus owner, so it is not reported here.
|
|
275
|
+
*/
|
|
276
|
+
getContextConflicts() {
|
|
277
|
+
const claims = new Map();
|
|
278
|
+
for (const [id, keys] of this.keysById) {
|
|
279
|
+
const context = this.getContext(id);
|
|
280
|
+
for (const key of keys) {
|
|
281
|
+
let byContext = claims.get(key);
|
|
282
|
+
if (!byContext) {
|
|
283
|
+
byContext = new Map();
|
|
284
|
+
claims.set(key, byContext);
|
|
285
|
+
}
|
|
286
|
+
let keybindings = byContext.get(context);
|
|
287
|
+
if (!keybindings) {
|
|
288
|
+
keybindings = new Set();
|
|
289
|
+
byContext.set(context, keybindings);
|
|
290
|
+
}
|
|
291
|
+
keybindings.add(id);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
const conflicts = [];
|
|
295
|
+
for (const [key, byContext] of claims) {
|
|
296
|
+
for (const [context, keybindings] of byContext) {
|
|
297
|
+
if (keybindings.size > 1) {
|
|
298
|
+
conflicts.push({ key, context, keybindings: [...keybindings].sort() });
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
conflicts.sort((a, b) => a.context.localeCompare(b.context) || a.key.localeCompare(b.key));
|
|
303
|
+
return conflicts;
|
|
304
|
+
}
|
|
305
|
+
setUserBindings(userBindings) {
|
|
306
|
+
this.userBindings = userBindings;
|
|
307
|
+
this.rebuild();
|
|
308
|
+
}
|
|
309
|
+
getUserBindings() {
|
|
310
|
+
return { ...this.userBindings };
|
|
311
|
+
}
|
|
312
|
+
getResolvedBindings() {
|
|
313
|
+
const resolved = {};
|
|
314
|
+
for (const id of Object.keys(this.definitions)) {
|
|
315
|
+
const keys = this.keysById.get(id) ?? [];
|
|
316
|
+
resolved[id] = keys.length === 1 ? keys[0] : [...keys];
|
|
317
|
+
}
|
|
318
|
+
return resolved;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
let globalKeybindings = null;
|
|
322
|
+
export function setKeybindings(keybindings) {
|
|
323
|
+
globalKeybindings = keybindings;
|
|
324
|
+
}
|
|
325
|
+
export function getKeybindings() {
|
|
326
|
+
if (!globalKeybindings) {
|
|
327
|
+
globalKeybindings = new KeybindingsManager(TUI_KEYBINDINGS);
|
|
328
|
+
}
|
|
329
|
+
return globalKeybindings;
|
|
330
|
+
}
|
|
331
|
+
//# sourceMappingURL=keybindings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keybindings.js","sourceRoot":"","sources":["../src/keybindings.ts"],"names":[],"mappings":"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","sourcesContent":["import { type KeyId, matchesKey } from \"./keys.ts\";\n\n/**\n * Global keybinding registry.\n * Downstream packages can add keybindings via declaration merging.\n */\nexport interface Keybindings {\n\t// Editor navigation and editing\n\t\"tui.editor.cursorUp\": true;\n\t\"tui.editor.cursorDown\": true;\n\t\"tui.editor.historyPrevious\": true;\n\t\"tui.editor.historyNext\": true;\n\t\"tui.editor.cursorLeft\": true;\n\t\"tui.editor.cursorRight\": true;\n\t\"tui.editor.cursorWordLeft\": true;\n\t\"tui.editor.cursorWordRight\": true;\n\t\"tui.editor.cursorLineStart\": true;\n\t\"tui.editor.cursorLineEnd\": true;\n\t\"tui.editor.jumpForward\": true;\n\t\"tui.editor.jumpBackward\": true;\n\t\"tui.editor.pageUp\": true;\n\t\"tui.editor.pageDown\": true;\n\t\"tui.editor.deleteCharBackward\": true;\n\t\"tui.editor.deleteCharForward\": true;\n\t\"tui.editor.deleteWordBackward\": true;\n\t\"tui.editor.deleteWordForward\": true;\n\t\"tui.editor.deleteToLineStart\": true;\n\t\"tui.editor.deleteToLineEnd\": true;\n\t\"tui.editor.yank\": true;\n\t\"tui.editor.yankPop\": true;\n\t\"tui.editor.undo\": true;\n\t// Generic input actions\n\t\"tui.input.newLine\": true;\n\t\"tui.input.submit\": true;\n\t\"tui.input.tab\": true;\n\t\"tui.input.copy\": true;\n\t// Generic selection actions\n\t\"tui.select.up\": true;\n\t\"tui.select.down\": true;\n\t\"tui.select.pageUp\": true;\n\t\"tui.select.pageDown\": true;\n\t\"tui.select.confirm\": true;\n\t\"tui.select.cancel\": true;\n\t// Alternate-screen viewport navigation\n\t\"tui.altScreen.pageUp\": true;\n\t\"tui.altScreen.pageDown\": true;\n\t\"tui.altScreen.halfPageUp\": true;\n\t\"tui.altScreen.halfPageDown\": true;\n\t\"tui.altScreen.lineUp\": true;\n\t\"tui.altScreen.lineDown\": true;\n\t\"tui.altScreen.previousPrompt\": true;\n\t\"tui.altScreen.nextPrompt\": true;\n\t\"tui.altScreen.search\": true;\n\t\"tui.altScreen.searchNext\": true;\n\t\"tui.altScreen.searchPrevious\": true;\n\t\"tui.altScreen.searchClose\": true;\n\t\"tui.altScreen.top\": true;\n\t\"tui.altScreen.bottom\": true;\n}\n\nexport type Keybinding = keyof Keybindings;\n\n/**\n * Routing context for a keybinding.\n *\n * - `global`: active regardless of focus. Reserved for downstream app bindings;\n * no stock `tui.*` binding uses it.\n * - `transcript`: fullscreen viewport navigation. Consumed by the viewport input\n * listener before the focused component sees the key.\n * - `editor`: prompt editing. Handled by the focused editor.\n * - `dialog`: selection lists and modal prompts. Handled by the focused overlay.\n *\n * Same-key claims across different contexts are intentional sharing, resolved by\n * the single focus owner. Same-key claims within one context are reported by\n * {@link KeybindingsManager.getContextConflicts}.\n */\nexport type KeybindingContext = \"global\" | \"transcript\" | \"editor\" | \"dialog\";\n\nexport interface KeybindingDefinition {\n\tdefaultKeys: KeyId | KeyId[];\n\tdescription?: string;\n\t/**\n\t * Routing context for this binding. Required on every stock `tui.*` binding\n\t * (enforced by test); optional for downstream extension bindings, which\n\t * default to `global` when omitted.\n\t */\n\tcontext?: KeybindingContext;\n}\n\nexport type KeybindingDefinitions = Record<string, KeybindingDefinition>;\nexport type KeybindingsConfig = Record<string, KeyId | KeyId[] | undefined>;\n\nexport const TUI_KEYBINDINGS = {\n\t\"tui.editor.cursorUp\": { context: \"editor\", defaultKeys: \"up\", description: \"Move cursor up\" },\n\t\"tui.editor.cursorDown\": { context: \"editor\", defaultKeys: \"down\", description: \"Move cursor down\" },\n\t\"tui.editor.historyPrevious\": {\n\t\tcontext: \"editor\",\n\t\tdefaultKeys: [],\n\t\tdescription: \"Select previous prompt history entry\",\n\t},\n\t\"tui.editor.historyNext\": {\n\t\tcontext: \"editor\",\n\t\tdefaultKeys: [],\n\t\tdescription: \"Select next prompt history entry\",\n\t},\n\t\"tui.editor.cursorLeft\": {\n\t\tcontext: \"editor\",\n\t\tdefaultKeys: [\"left\", \"ctrl+b\"],\n\t\tdescription: \"Move cursor left\",\n\t},\n\t\"tui.editor.cursorRight\": {\n\t\tcontext: \"editor\",\n\t\tdefaultKeys: [\"right\", \"ctrl+f\"],\n\t\tdescription: \"Move cursor right\",\n\t},\n\t\"tui.editor.cursorWordLeft\": {\n\t\tcontext: \"editor\",\n\t\tdefaultKeys: [\"alt+left\", \"ctrl+left\", \"alt+b\"],\n\t\tdescription: \"Move cursor word left\",\n\t},\n\t\"tui.editor.cursorWordRight\": {\n\t\tcontext: \"editor\",\n\t\tdefaultKeys: [\"alt+right\", \"ctrl+right\", \"alt+f\"],\n\t\tdescription: \"Move cursor word right\",\n\t},\n\t\"tui.editor.cursorLineStart\": {\n\t\tcontext: \"editor\",\n\t\tdefaultKeys: [\"home\", \"ctrl+home\", \"ctrl+a\"],\n\t\tdescription: \"Move to line start\",\n\t},\n\t\"tui.editor.cursorLineEnd\": {\n\t\tcontext: \"editor\",\n\t\tdefaultKeys: [\"end\", \"ctrl+end\", \"ctrl+e\"],\n\t\tdescription: \"Move to line end\",\n\t},\n\t\"tui.editor.jumpForward\": {\n\t\tcontext: \"editor\",\n\t\tdefaultKeys: \"ctrl+]\",\n\t\tdescription: \"Jump forward to character\",\n\t},\n\t\"tui.editor.jumpBackward\": {\n\t\tcontext: \"editor\",\n\t\tdefaultKeys: \"ctrl+alt+]\",\n\t\tdescription: \"Jump backward to character\",\n\t},\n\t\"tui.editor.pageUp\": {\n\t\tcontext: \"editor\",\n\t\tdefaultKeys: [\"pageUp\", \"ctrl+pageUp\"],\n\t\tdescription: \"Page up\",\n\t},\n\t\"tui.editor.pageDown\": {\n\t\tcontext: \"editor\",\n\t\tdefaultKeys: [\"pageDown\", \"ctrl+pageDown\"],\n\t\tdescription: \"Page down\",\n\t},\n\t\"tui.editor.deleteCharBackward\": {\n\t\tcontext: \"editor\",\n\t\tdefaultKeys: \"backspace\",\n\t\tdescription: \"Delete character backward\",\n\t},\n\t\"tui.editor.deleteCharForward\": {\n\t\tcontext: \"editor\",\n\t\tdefaultKeys: [\"delete\", \"ctrl+d\"],\n\t\tdescription: \"Delete character forward\",\n\t},\n\t\"tui.editor.deleteWordBackward\": {\n\t\tcontext: \"editor\",\n\t\tdefaultKeys: [\"ctrl+w\", \"alt+backspace\"],\n\t\tdescription: \"Delete word backward\",\n\t},\n\t\"tui.editor.deleteWordForward\": {\n\t\tcontext: \"editor\",\n\t\tdefaultKeys: [\"alt+d\", \"alt+delete\"],\n\t\tdescription: \"Delete word forward\",\n\t},\n\t\"tui.editor.deleteToLineStart\": {\n\t\tcontext: \"editor\",\n\t\tdefaultKeys: \"ctrl+u\",\n\t\tdescription: \"Delete to line start\",\n\t},\n\t\"tui.editor.deleteToLineEnd\": {\n\t\tcontext: \"editor\",\n\t\tdefaultKeys: \"ctrl+k\",\n\t\tdescription: \"Delete to line end\",\n\t},\n\t\"tui.editor.yank\": { context: \"editor\", defaultKeys: \"ctrl+y\", description: \"Yank\" },\n\t\"tui.editor.yankPop\": { context: \"editor\", defaultKeys: \"alt+y\", description: \"Yank pop\" },\n\t\"tui.editor.undo\": { context: \"editor\", defaultKeys: \"ctrl+-\", description: \"Undo\" },\n\t\"tui.input.newLine\": {\n\t\tcontext: \"editor\",\n\t\tdefaultKeys: [\"shift+enter\", \"ctrl+j\"],\n\t\tdescription: \"Insert newline\",\n\t},\n\t\"tui.input.submit\": { context: \"editor\", defaultKeys: \"enter\", description: \"Submit input\" },\n\t\"tui.input.tab\": { context: \"editor\", defaultKeys: \"tab\", description: \"Tab / autocomplete\" },\n\t\"tui.input.copy\": { context: \"editor\", defaultKeys: \"ctrl+c\", description: \"Copy selection\" },\n\t// Selection lists share keys (up/down/enter/escape/...) with editor and\n\t// transcript bindings by design; the single focus owner resolves them.\n\t\"tui.select.up\": { context: \"dialog\", defaultKeys: \"up\", description: \"Move selection up\" },\n\t\"tui.select.down\": { context: \"dialog\", defaultKeys: \"down\", description: \"Move selection down\" },\n\t\"tui.select.pageUp\": { context: \"dialog\", defaultKeys: \"pageUp\", description: \"Selection page up\" },\n\t\"tui.select.pageDown\": {\n\t\tcontext: \"dialog\",\n\t\tdefaultKeys: \"pageDown\",\n\t\tdescription: \"Selection page down\",\n\t},\n\t\"tui.select.confirm\": { context: \"dialog\", defaultKeys: \"enter\", description: \"Confirm selection\" },\n\t\"tui.select.cancel\": {\n\t\tcontext: \"dialog\",\n\t\tdefaultKeys: [\"escape\", \"ctrl+c\"],\n\t\tdescription: \"Cancel selection\",\n\t},\n\t// These intentionally shadow the unmodified editor bindings in fullscreen mode.\n\t// Viewport navigation shares keys (pageUp/pageDown/home/end/enter/escape/...)\n\t// with editor and dialog bindings by design; the focus owner resolves them.\n\t\"tui.altScreen.pageUp\": {\n\t\tcontext: \"transcript\",\n\t\tdefaultKeys: \"pageUp\",\n\t\tdescription: \"Scroll viewport up one page\",\n\t},\n\t\"tui.altScreen.pageDown\": {\n\t\tcontext: \"transcript\",\n\t\tdefaultKeys: \"pageDown\",\n\t\tdescription: \"Scroll viewport down one page\",\n\t},\n\t\"tui.altScreen.halfPageUp\": {\n\t\tcontext: \"transcript\",\n\t\tdefaultKeys: [],\n\t\tdescription: \"Scroll viewport up half a page\",\n\t},\n\t\"tui.altScreen.halfPageDown\": {\n\t\tcontext: \"transcript\",\n\t\tdefaultKeys: [],\n\t\tdescription: \"Scroll viewport down half a page\",\n\t},\n\t\"tui.altScreen.lineUp\": {\n\t\tcontext: \"transcript\",\n\t\tdefaultKeys: [],\n\t\tdescription: \"Scroll viewport up one line\",\n\t},\n\t\"tui.altScreen.lineDown\": {\n\t\tcontext: \"transcript\",\n\t\tdefaultKeys: [],\n\t\tdescription: \"Scroll viewport down one line\",\n\t},\n\t\"tui.altScreen.previousPrompt\": {\n\t\tcontext: \"transcript\",\n\t\tdefaultKeys: [\"ctrl+shift+up\", \"ctrl+up\"],\n\t\tdescription: \"Jump to previous semantic prompt\",\n\t},\n\t\"tui.altScreen.nextPrompt\": {\n\t\tcontext: \"transcript\",\n\t\tdefaultKeys: [\"ctrl+shift+down\", \"ctrl+down\"],\n\t\tdescription: \"Jump to next semantic prompt\",\n\t},\n\t\"tui.altScreen.search\": {\n\t\tcontext: \"transcript\",\n\t\tdefaultKeys: \"ctrl+shift+f\",\n\t\tdescription: \"Search the primary scroll view\",\n\t},\n\t\"tui.altScreen.searchNext\": {\n\t\tcontext: \"transcript\",\n\t\tdefaultKeys: [\"enter\", \"ctrl+g\"],\n\t\tdescription: \"Select the next search match\",\n\t},\n\t\"tui.altScreen.searchPrevious\": {\n\t\tcontext: \"transcript\",\n\t\tdefaultKeys: [\"shift+enter\", \"ctrl+shift+g\"],\n\t\tdescription: \"Select the previous search match\",\n\t},\n\t\"tui.altScreen.searchClose\": {\n\t\tcontext: \"transcript\",\n\t\tdefaultKeys: \"escape\",\n\t\tdescription: \"Close transcript search\",\n\t},\n\t\"tui.altScreen.top\": { context: \"transcript\", defaultKeys: \"home\", description: \"Scroll viewport to top\" },\n\t\"tui.altScreen.bottom\": { context: \"transcript\", defaultKeys: \"end\", description: \"Scroll viewport to bottom\" },\n} as const satisfies KeybindingDefinitions;\n\nexport interface KeybindingConflict {\n\tkey: KeyId;\n\tkeybindings: string[];\n}\n\n/**\n * Same key claimed by multiple bindings within one routing context. Unlike\n * {@link KeybindingConflict} (user overrides only), this covers resolved\n * bindings including defaults, so a conflict is visible at the declaration\n * site instead of being discovered at runtime.\n */\nexport interface KeybindingContextConflict {\n\tkey: KeyId;\n\tcontext: KeybindingContext;\n\tkeybindings: string[];\n}\n\nfunction normalizeKeys(keys: KeyId | KeyId[] | undefined): KeyId[] {\n\tif (keys === undefined) return [];\n\tconst keyList = Array.isArray(keys) ? keys : [keys];\n\tconst seen = new Set<KeyId>();\n\tconst result: KeyId[] = [];\n\tfor (const key of keyList) {\n\t\tif (!seen.has(key)) {\n\t\t\tseen.add(key);\n\t\t\tresult.push(key);\n\t\t}\n\t}\n\treturn result;\n}\n\nexport class KeybindingsManager {\n\tprivate definitions: KeybindingDefinitions;\n\tprivate userBindings: KeybindingsConfig;\n\tprivate keysById = new Map<Keybinding, KeyId[]>();\n\tprivate conflicts: KeybindingConflict[] = [];\n\n\tconstructor(definitions: KeybindingDefinitions, userBindings: KeybindingsConfig = {}) {\n\t\tthis.definitions = definitions;\n\t\tthis.userBindings = userBindings;\n\t\tthis.rebuild();\n\t}\n\n\tprivate rebuild(): void {\n\t\tthis.keysById.clear();\n\t\tthis.conflicts = [];\n\n\t\tconst userClaims = new Map<KeyId, Set<Keybinding>>();\n\t\tfor (const [keybinding, keys] of Object.entries(this.userBindings)) {\n\t\t\tif (!(keybinding in this.definitions)) continue;\n\t\t\tfor (const key of normalizeKeys(keys)) {\n\t\t\t\tconst claimants = userClaims.get(key) ?? new Set<Keybinding>();\n\t\t\t\tclaimants.add(keybinding as Keybinding);\n\t\t\t\tuserClaims.set(key, claimants);\n\t\t\t}\n\t\t}\n\n\t\tfor (const [key, keybindings] of userClaims) {\n\t\t\tif (keybindings.size > 1) {\n\t\t\t\tthis.conflicts.push({ key, keybindings: [...keybindings] });\n\t\t\t}\n\t\t}\n\n\t\tfor (const [id, definition] of Object.entries(this.definitions)) {\n\t\t\tconst userKeys = this.userBindings[id];\n\t\t\tconst keys = userKeys === undefined ? normalizeKeys(definition.defaultKeys) : normalizeKeys(userKeys);\n\t\t\tthis.keysById.set(id as Keybinding, keys);\n\t\t}\n\t}\n\n\tmatches(data: string, keybinding: Keybinding): boolean {\n\t\tconst keys = this.keysById.get(keybinding) ?? [];\n\t\tfor (const key of keys) {\n\t\t\tif (matchesKey(data, key)) return true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tgetKeys(keybinding: Keybinding): KeyId[] {\n\t\treturn [...(this.keysById.get(keybinding) ?? [])];\n\t}\n\n\tgetDefinition(keybinding: Keybinding): KeybindingDefinition {\n\t\treturn this.definitions[keybinding];\n\t}\n\n\tgetConflicts(): KeybindingConflict[] {\n\t\treturn this.conflicts.map((conflict) => ({ ...conflict, keybindings: [...conflict.keybindings] }));\n\t}\n\n\t/**\n\t * Routing context declared for a binding. Extension bindings without a\n\t * declared context default to `global`.\n\t */\n\tgetContext(keybinding: Keybinding): KeybindingContext {\n\t\treturn this.definitions[keybinding]?.context ?? \"global\";\n\t}\n\n\t/** All binding ids declared for one routing context. */\n\tgetBindingsByContext(context: KeybindingContext): Keybinding[] {\n\t\tconst result: Keybinding[] = [];\n\t\tfor (const id of Object.keys(this.definitions)) {\n\t\t\tif (this.getContext(id as Keybinding) === context) {\n\t\t\t\tresult.push(id as Keybinding);\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * Same-key claims within a single routing context across resolved bindings\n\t * (defaults plus user overrides). Cross-context sharing (e.g. `enter` for\n\t * both editor submit and dialog confirm) is intentional and resolved by the\n\t * focus owner, so it is not reported here.\n\t */\n\tgetContextConflicts(): KeybindingContextConflict[] {\n\t\tconst claims = new Map<KeyId, Map<KeybindingContext, Set<string>>>();\n\t\tfor (const [id, keys] of this.keysById) {\n\t\t\tconst context = this.getContext(id);\n\t\t\tfor (const key of keys) {\n\t\t\t\tlet byContext = claims.get(key);\n\t\t\t\tif (!byContext) {\n\t\t\t\t\tbyContext = new Map<KeybindingContext, Set<string>>();\n\t\t\t\t\tclaims.set(key, byContext);\n\t\t\t\t}\n\t\t\t\tlet keybindings = byContext.get(context);\n\t\t\t\tif (!keybindings) {\n\t\t\t\t\tkeybindings = new Set<string>();\n\t\t\t\t\tbyContext.set(context, keybindings);\n\t\t\t\t}\n\t\t\t\tkeybindings.add(id);\n\t\t\t}\n\t\t}\n\t\tconst conflicts: KeybindingContextConflict[] = [];\n\t\tfor (const [key, byContext] of claims) {\n\t\t\tfor (const [context, keybindings] of byContext) {\n\t\t\t\tif (keybindings.size > 1) {\n\t\t\t\t\tconflicts.push({ key, context, keybindings: [...keybindings].sort() });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tconflicts.sort((a, b) => a.context.localeCompare(b.context) || a.key.localeCompare(b.key));\n\t\treturn conflicts;\n\t}\n\n\tsetUserBindings(userBindings: KeybindingsConfig): void {\n\t\tthis.userBindings = userBindings;\n\t\tthis.rebuild();\n\t}\n\n\tgetUserBindings(): KeybindingsConfig {\n\t\treturn { ...this.userBindings };\n\t}\n\n\tgetResolvedBindings(): KeybindingsConfig {\n\t\tconst resolved: KeybindingsConfig = {};\n\t\tfor (const id of Object.keys(this.definitions)) {\n\t\t\tconst keys = this.keysById.get(id as Keybinding) ?? [];\n\t\t\tresolved[id] = keys.length === 1 ? keys[0]! : [...keys];\n\t\t}\n\t\treturn resolved;\n\t}\n}\n\nlet globalKeybindings: KeybindingsManager | null = null;\n\nexport function setKeybindings(keybindings: KeybindingsManager): void {\n\tglobalKeybindings = keybindings;\n}\n\nexport function getKeybindings(): KeybindingsManager {\n\tif (!globalKeybindings) {\n\t\tglobalKeybindings = new KeybindingsManager(TUI_KEYBINDINGS);\n\t}\n\treturn globalKeybindings;\n}\n"]}
|
package/dist/keys.d.ts
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keyboard input handling for terminal applications.
|
|
3
|
+
*
|
|
4
|
+
* Supports both legacy terminal sequences and Kitty keyboard protocol.
|
|
5
|
+
* See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/
|
|
6
|
+
* Reference: https://github.com/sst/opentui/blob/7da92b4088aebfe27b9f691c04163a48821e49fd/packages/core/src/lib/parse.keypress.ts
|
|
7
|
+
*
|
|
8
|
+
* Symbol keys are also supported, however some ctrl+symbol combos
|
|
9
|
+
* overlap with ASCII codes, e.g. ctrl+[ = ESC.
|
|
10
|
+
* See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/#legacy-ctrl-mapping-of-ascii-keys
|
|
11
|
+
* Those can still be * used for ctrl+shift combos
|
|
12
|
+
*
|
|
13
|
+
* API:
|
|
14
|
+
* - matchesKey(data, keyId) - Check if input matches a key identifier
|
|
15
|
+
* - parseKey(data) - Parse input and return the key identifier
|
|
16
|
+
* - Key - Helper object for creating typed key identifiers
|
|
17
|
+
* - setKittyProtocolActive(active) - Set global Kitty protocol state
|
|
18
|
+
* - isKittyProtocolActive() - Query global Kitty protocol state
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Set the global Kitty keyboard protocol state.
|
|
22
|
+
* Called by ProcessTerminal after detecting protocol support.
|
|
23
|
+
*/
|
|
24
|
+
export declare function setKittyProtocolActive(active: boolean): void;
|
|
25
|
+
/**
|
|
26
|
+
* Query whether Kitty keyboard protocol is currently active.
|
|
27
|
+
*/
|
|
28
|
+
export declare function isKittyProtocolActive(): boolean;
|
|
29
|
+
type Letter = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z";
|
|
30
|
+
type Digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
|
|
31
|
+
type SymbolKey = "`" | "-" | "=" | "[" | "]" | "\\" | ";" | "'" | "," | "." | "/" | "!" | "@" | "#" | "$" | "%" | "^" | "&" | "*" | "(" | ")" | "_" | "+" | "|" | "~" | "{" | "}" | ":" | "<" | ">" | "?";
|
|
32
|
+
type SpecialKey = "escape" | "esc" | "enter" | "return" | "tab" | "space" | "backspace" | "delete" | "insert" | "clear" | "home" | "end" | "pageUp" | "pageDown" | "up" | "down" | "left" | "right" | "f1" | "f2" | "f3" | "f4" | "f5" | "f6" | "f7" | "f8" | "f9" | "f10" | "f11" | "f12";
|
|
33
|
+
type BaseKey = Letter | Digit | SymbolKey | SpecialKey;
|
|
34
|
+
type ModifierName = "ctrl" | "shift" | "alt" | "super";
|
|
35
|
+
type ModifiedKeyId<Key extends string, RemainingModifiers extends ModifierName = ModifierName> = {
|
|
36
|
+
[M in RemainingModifiers]: `${M}+${Key}` | `${M}+${ModifiedKeyId<Key, Exclude<RemainingModifiers, M>>}`;
|
|
37
|
+
}[RemainingModifiers];
|
|
38
|
+
/**
|
|
39
|
+
* Union type of all valid key identifiers.
|
|
40
|
+
* Provides autocomplete and catches typos at compile time.
|
|
41
|
+
*/
|
|
42
|
+
export type KeyId = BaseKey | ModifiedKeyId<BaseKey>;
|
|
43
|
+
/**
|
|
44
|
+
* Helper object for creating typed key identifiers with autocomplete.
|
|
45
|
+
*
|
|
46
|
+
* Usage:
|
|
47
|
+
* - Key.escape, Key.enter, Key.tab, etc. for special keys
|
|
48
|
+
* - Key.backtick, Key.comma, Key.period, etc. for symbol keys
|
|
49
|
+
* - Key.ctrl("c"), Key.alt("x"), Key.super("k") for single modifiers
|
|
50
|
+
* - Key.ctrlShift("p"), Key.ctrlAlt("x"), Key.ctrlSuper("k") for combined modifiers
|
|
51
|
+
*/
|
|
52
|
+
export declare const Key: {
|
|
53
|
+
readonly escape: "escape";
|
|
54
|
+
readonly esc: "esc";
|
|
55
|
+
readonly enter: "enter";
|
|
56
|
+
readonly return: "return";
|
|
57
|
+
readonly tab: "tab";
|
|
58
|
+
readonly space: "space";
|
|
59
|
+
readonly backspace: "backspace";
|
|
60
|
+
readonly delete: "delete";
|
|
61
|
+
readonly insert: "insert";
|
|
62
|
+
readonly clear: "clear";
|
|
63
|
+
readonly home: "home";
|
|
64
|
+
readonly end: "end";
|
|
65
|
+
readonly pageUp: "pageUp";
|
|
66
|
+
readonly pageDown: "pageDown";
|
|
67
|
+
readonly up: "up";
|
|
68
|
+
readonly down: "down";
|
|
69
|
+
readonly left: "left";
|
|
70
|
+
readonly right: "right";
|
|
71
|
+
readonly f1: "f1";
|
|
72
|
+
readonly f2: "f2";
|
|
73
|
+
readonly f3: "f3";
|
|
74
|
+
readonly f4: "f4";
|
|
75
|
+
readonly f5: "f5";
|
|
76
|
+
readonly f6: "f6";
|
|
77
|
+
readonly f7: "f7";
|
|
78
|
+
readonly f8: "f8";
|
|
79
|
+
readonly f9: "f9";
|
|
80
|
+
readonly f10: "f10";
|
|
81
|
+
readonly f11: "f11";
|
|
82
|
+
readonly f12: "f12";
|
|
83
|
+
readonly backtick: "`";
|
|
84
|
+
readonly hyphen: "-";
|
|
85
|
+
readonly equals: "=";
|
|
86
|
+
readonly leftbracket: "[";
|
|
87
|
+
readonly rightbracket: "]";
|
|
88
|
+
readonly backslash: "\\";
|
|
89
|
+
readonly semicolon: ";";
|
|
90
|
+
readonly quote: "'";
|
|
91
|
+
readonly comma: ",";
|
|
92
|
+
readonly period: ".";
|
|
93
|
+
readonly slash: "/";
|
|
94
|
+
readonly exclamation: "!";
|
|
95
|
+
readonly at: "@";
|
|
96
|
+
readonly hash: "#";
|
|
97
|
+
readonly dollar: "$";
|
|
98
|
+
readonly percent: "%";
|
|
99
|
+
readonly caret: "^";
|
|
100
|
+
readonly ampersand: "&";
|
|
101
|
+
readonly asterisk: "*";
|
|
102
|
+
readonly leftparen: "(";
|
|
103
|
+
readonly rightparen: ")";
|
|
104
|
+
readonly underscore: "_";
|
|
105
|
+
readonly plus: "+";
|
|
106
|
+
readonly pipe: "|";
|
|
107
|
+
readonly tilde: "~";
|
|
108
|
+
readonly leftbrace: "{";
|
|
109
|
+
readonly rightbrace: "}";
|
|
110
|
+
readonly colon: ":";
|
|
111
|
+
readonly lessthan: "<";
|
|
112
|
+
readonly greaterthan: ">";
|
|
113
|
+
readonly question: "?";
|
|
114
|
+
readonly ctrl: <K extends BaseKey>(key: K) => `ctrl+${K}`;
|
|
115
|
+
readonly shift: <K extends BaseKey>(key: K) => `shift+${K}`;
|
|
116
|
+
readonly alt: <K extends BaseKey>(key: K) => `alt+${K}`;
|
|
117
|
+
readonly super: <K extends BaseKey>(key: K) => `super+${K}`;
|
|
118
|
+
readonly ctrlShift: <K extends BaseKey>(key: K) => `ctrl+shift+${K}`;
|
|
119
|
+
readonly shiftCtrl: <K extends BaseKey>(key: K) => `shift+ctrl+${K}`;
|
|
120
|
+
readonly ctrlAlt: <K extends BaseKey>(key: K) => `ctrl+alt+${K}`;
|
|
121
|
+
readonly altCtrl: <K extends BaseKey>(key: K) => `alt+ctrl+${K}`;
|
|
122
|
+
readonly shiftAlt: <K extends BaseKey>(key: K) => `shift+alt+${K}`;
|
|
123
|
+
readonly altShift: <K extends BaseKey>(key: K) => `alt+shift+${K}`;
|
|
124
|
+
readonly ctrlSuper: <K extends BaseKey>(key: K) => `ctrl+super+${K}`;
|
|
125
|
+
readonly superCtrl: <K extends BaseKey>(key: K) => `super+ctrl+${K}`;
|
|
126
|
+
readonly shiftSuper: <K extends BaseKey>(key: K) => `shift+super+${K}`;
|
|
127
|
+
readonly superShift: <K extends BaseKey>(key: K) => `super+shift+${K}`;
|
|
128
|
+
readonly altSuper: <K extends BaseKey>(key: K) => `alt+super+${K}`;
|
|
129
|
+
readonly superAlt: <K extends BaseKey>(key: K) => `super+alt+${K}`;
|
|
130
|
+
readonly ctrlShiftAlt: <K extends BaseKey>(key: K) => `ctrl+shift+alt+${K}`;
|
|
131
|
+
readonly ctrlShiftSuper: <K extends BaseKey>(key: K) => `ctrl+shift+super+${K}`;
|
|
132
|
+
};
|
|
133
|
+
/**
|
|
134
|
+
* Event types from Kitty keyboard protocol (flag 2)
|
|
135
|
+
* 1 = key press, 2 = key repeat, 3 = key release
|
|
136
|
+
*/
|
|
137
|
+
export type KeyEventType = "press" | "repeat" | "release";
|
|
138
|
+
/**
|
|
139
|
+
* Check if the last parsed key event was a key release.
|
|
140
|
+
* Only meaningful when Kitty keyboard protocol with flag 2 is active.
|
|
141
|
+
*/
|
|
142
|
+
export declare function isKeyRelease(data: string): boolean;
|
|
143
|
+
/**
|
|
144
|
+
* Check if the last parsed key event was a key repeat.
|
|
145
|
+
* Only meaningful when Kitty keyboard protocol with flag 2 is active.
|
|
146
|
+
*/
|
|
147
|
+
export declare function isKeyRepeat(data: string): boolean;
|
|
148
|
+
/**
|
|
149
|
+
* Match input data against a key identifier string.
|
|
150
|
+
*
|
|
151
|
+
* Supported key identifiers:
|
|
152
|
+
* - Single keys: "escape", "tab", "enter", "backspace", "delete", "home", "end", "space"
|
|
153
|
+
* - Arrow keys: "up", "down", "left", "right"
|
|
154
|
+
* - Ctrl combinations: "ctrl+c", "ctrl+z", etc.
|
|
155
|
+
* - Shift combinations: "shift+tab", "shift+enter"
|
|
156
|
+
* - Alt combinations: "alt+enter", "alt+backspace"
|
|
157
|
+
* - Super combinations: "super+k", "super+enter"
|
|
158
|
+
* - Combined modifiers: "shift+ctrl+p", "ctrl+alt+x", "ctrl+super+k"
|
|
159
|
+
*
|
|
160
|
+
* Use the Key helper for autocomplete: Key.ctrl("c"), Key.escape, Key.ctrlShift("p"), Key.super("k")
|
|
161
|
+
*
|
|
162
|
+
* @param data - Raw input data from terminal
|
|
163
|
+
* @param keyId - Key identifier (e.g., "ctrl+c", "escape", Key.ctrl("c"))
|
|
164
|
+
*/
|
|
165
|
+
export declare function matchesKey(data: string, keyId: KeyId): boolean;
|
|
166
|
+
export declare function parseKey(data: string): string | undefined;
|
|
167
|
+
/**
|
|
168
|
+
* Decode a Kitty CSI-u sequence into a printable character, if applicable.
|
|
169
|
+
*
|
|
170
|
+
* When Kitty keyboard protocol flag 1 (disambiguate) is active, terminals send
|
|
171
|
+
* CSI-u sequences for all keys, including plain printable characters. This
|
|
172
|
+
* function extracts the printable character from such sequences.
|
|
173
|
+
*
|
|
174
|
+
* Only accepts plain or Shift-modified keys. Rejects Ctrl, Alt, and unsupported
|
|
175
|
+
* modifier combinations (those are handled by keybinding matching instead).
|
|
176
|
+
* Prefers the shifted keycode when Shift is held and a shifted key is reported.
|
|
177
|
+
*
|
|
178
|
+
* @param data - Raw input data from terminal
|
|
179
|
+
* @returns The printable character, or undefined if not a printable CSI-u sequence
|
|
180
|
+
*/
|
|
181
|
+
export declare function decodeKittyPrintable(data: string): string | undefined;
|
|
182
|
+
export declare function decodePrintableKey(data: string): string | undefined;
|
|
183
|
+
export {};
|
|
184
|
+
//# sourceMappingURL=keys.d.ts.map
|