@shanepadgett/tau-tui 0.33.0 → 0.34.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/package.json +1 -1
- package/src/index.ts +1 -0
- package/src/scrollable-markdown.ts +37 -0
- package/src/selectable-list.ts +39 -38
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { editorTheme } from "./editor-theme.ts";
|
|
2
2
|
export { bindingHint, bindingsHint, rawHint, type ToolKeyHint } from "./key-hints.ts";
|
|
3
3
|
export { Marker, type MarkerState } from "./marker.ts";
|
|
4
|
+
export { ScrollableMarkdown } from "./scrollable-markdown.ts";
|
|
4
5
|
export {
|
|
5
6
|
SelectableList,
|
|
6
7
|
type SelectableListActionResult,
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { getMarkdownTheme } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import { type Component, Markdown, truncateToWidth, type TUI } from "@earendil-works/pi-tui";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Scrolling markdown body for a `ToolPanel`. The panel owns key handling and
|
|
6
|
+
* calls `scroll`; this component owns the viewport window.
|
|
7
|
+
*/
|
|
8
|
+
export class ScrollableMarkdown implements Component {
|
|
9
|
+
private readonly tui: TUI;
|
|
10
|
+
private readonly markdown: Markdown;
|
|
11
|
+
private readonly chromeLines: number;
|
|
12
|
+
private offset = 0;
|
|
13
|
+
private maxOffset = 0;
|
|
14
|
+
|
|
15
|
+
constructor(tui: TUI, content: string, chromeLines: number) {
|
|
16
|
+
this.tui = tui;
|
|
17
|
+
this.markdown = new Markdown(content, 0, 0, getMarkdownTheme());
|
|
18
|
+
this.chromeLines = chromeLines;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
scroll(delta: number): void {
|
|
22
|
+
this.offset = Math.max(0, Math.min(this.maxOffset, this.offset + delta));
|
|
23
|
+
this.tui.requestRender();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
render(width: number): string[] {
|
|
27
|
+
const lines = this.markdown.render(width);
|
|
28
|
+
const height = Math.max(4, Math.floor(this.tui.terminal.rows * 0.9) - this.chromeLines);
|
|
29
|
+
this.maxOffset = Math.max(0, lines.length - height);
|
|
30
|
+
this.offset = Math.min(this.offset, this.maxOffset);
|
|
31
|
+
return lines.slice(this.offset, this.offset + height).map((line) => truncateToWidth(line, width, ""));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
invalidate(): void {
|
|
35
|
+
this.markdown.invalidate();
|
|
36
|
+
}
|
|
37
|
+
}
|
package/src/selectable-list.ts
CHANGED
|
@@ -183,61 +183,62 @@ export class SelectableList<T extends SelectableListItem> implements Component,
|
|
|
183
183
|
];
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
-
|
|
186
|
+
private handleMultiFilterKey(data: string): boolean {
|
|
187
|
+
if (this.config.selection.kind !== "multi" || !this.filterActive) return false;
|
|
187
188
|
const keybindings = getKeybindings();
|
|
188
|
-
if (
|
|
189
|
+
if (matchesKey(data, Key.ctrl("c"))) {
|
|
189
190
|
this.clearFilter();
|
|
190
|
-
return;
|
|
191
|
+
return true;
|
|
191
192
|
}
|
|
192
|
-
if (
|
|
193
|
-
this.config.selection.kind === "multi" &&
|
|
194
|
-
this.filterActive &&
|
|
195
|
-
keybindings.matches(data, "tui.select.cancel")
|
|
196
|
-
) {
|
|
193
|
+
if (keybindings.matches(data, "tui.select.cancel")) {
|
|
197
194
|
this.clearFilterFocus();
|
|
198
|
-
return;
|
|
195
|
+
return true;
|
|
199
196
|
}
|
|
200
|
-
if (
|
|
201
|
-
this.config.selection.kind === "multi" &&
|
|
202
|
-
this.filterActive &&
|
|
203
|
-
keybindings.matches(data, "tui.select.confirm")
|
|
204
|
-
) {
|
|
197
|
+
if (keybindings.matches(data, "tui.select.confirm")) {
|
|
205
198
|
this.blurFilter();
|
|
206
|
-
return;
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
private handleMultiFilterMode(data: string): boolean {
|
|
205
|
+
if (this.config.selection.kind !== "multi") return false;
|
|
206
|
+
if (this.config.filter && !this.filterActive && matchesKey(data, Key.slash)) {
|
|
207
|
+
this.activateFilter();
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
210
|
+
if (this.filterActive) {
|
|
211
|
+
this.handleFilterInput(data);
|
|
212
|
+
return true;
|
|
213
|
+
}
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
private handleConfiguredAction(data: string): boolean {
|
|
218
|
+
for (const action of this.config.actions) {
|
|
219
|
+
if (!matchesKey(data, action.key)) continue;
|
|
220
|
+
this.runAction(action);
|
|
221
|
+
return true;
|
|
207
222
|
}
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
handleInput(data: string): void {
|
|
227
|
+
if (this.handleMultiFilterKey(data)) return;
|
|
228
|
+
|
|
229
|
+
const keybindings = getKeybindings();
|
|
208
230
|
if (keybindings.matches(data, "tui.select.cancel")) {
|
|
209
231
|
this.config.onResult({ kind: "cancel" });
|
|
210
232
|
return;
|
|
211
233
|
}
|
|
212
|
-
|
|
213
234
|
if (keybindings.matches(data, "tui.select.confirm")) {
|
|
214
235
|
this.primary();
|
|
215
236
|
return;
|
|
216
237
|
}
|
|
217
|
-
|
|
218
238
|
if (this.handleListKey(data)) return;
|
|
219
239
|
if (this.config.selection.kind === "multi" && this.handleMultiSelectKey(data)) return;
|
|
220
|
-
if (
|
|
221
|
-
|
|
222
|
-
this.config.filter &&
|
|
223
|
-
!this.filterActive &&
|
|
224
|
-
matchesKey(data, Key.slash)
|
|
225
|
-
) {
|
|
226
|
-
this.activateFilter();
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
if (this.config.selection.kind === "multi" && this.filterActive) {
|
|
230
|
-
this.handleFilterInput(data);
|
|
231
|
-
return;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
for (const action of this.config.actions) {
|
|
235
|
-
if (matchesKey(data, action.key)) {
|
|
236
|
-
this.runAction(action);
|
|
237
|
-
return;
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
240
|
+
if (this.handleMultiFilterMode(data)) return;
|
|
241
|
+
if (this.handleConfiguredAction(data)) return;
|
|
241
242
|
if (this.config.filter && this.config.selection.kind === "single") this.handleFilterInput(data);
|
|
242
243
|
}
|
|
243
244
|
|