@dungle-scrubs/tallow 0.9.3 → 0.9.6
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/dist/cli.js +7 -4
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/interactive-mode-patch.d.ts +24 -10
- package/dist/interactive-mode-patch.d.ts.map +1 -1
- package/dist/interactive-mode-patch.js +285 -148
- package/dist/interactive-mode-patch.js.map +1 -1
- package/dist/interactive-reset.d.ts +49 -0
- package/dist/interactive-reset.d.ts.map +1 -0
- package/dist/interactive-reset.js +40 -0
- package/dist/interactive-reset.js.map +1 -0
- package/dist/pi-tui-editor-patch.d.ts +10 -0
- package/dist/pi-tui-editor-patch.d.ts.map +1 -0
- package/dist/pi-tui-editor-patch.js +159 -0
- package/dist/pi-tui-editor-patch.js.map +1 -0
- package/dist/pi-tui-patch.d.ts +2 -0
- package/dist/pi-tui-patch.d.ts.map +1 -0
- package/dist/pi-tui-patch.js +563 -0
- package/dist/pi-tui-patch.js.map +1 -0
- package/dist/pi-tui-settings-list-patch.d.ts +11 -0
- package/dist/pi-tui-settings-list-patch.d.ts.map +1 -0
- package/dist/pi-tui-settings-list-patch.js +38 -0
- package/dist/pi-tui-settings-list-patch.js.map +1 -0
- package/dist/reset-diagnostics.d.ts +69 -0
- package/dist/reset-diagnostics.d.ts.map +1 -0
- package/dist/reset-diagnostics.js +41 -0
- package/dist/reset-diagnostics.js.map +1 -0
- package/dist/sdk.d.ts +5 -21
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +180 -149
- package/dist/sdk.js.map +1 -1
- package/dist/workspace-transition-interactive.d.ts +1 -0
- package/dist/workspace-transition-interactive.d.ts.map +1 -1
- package/dist/workspace-transition-interactive.js +7 -17
- package/dist/workspace-transition-interactive.js.map +1 -1
- package/extensions/__integration__/audit-findings.test.ts +6 -16
- package/extensions/__integration__/teams-runtime.test.ts +4 -1
- package/extensions/_icons/index.ts +2 -4
- package/extensions/_shared/__tests__/image-metadata.test.ts +33 -0
- package/extensions/_shared/__tests__/terminal-links.test.ts +18 -0
- package/extensions/_shared/image-metadata.ts +99 -0
- package/extensions/_shared/inline-preview.ts +1 -1
- package/extensions/_shared/pid-registry.ts +0 -1
- package/extensions/_shared/terminal-links.ts +22 -0
- package/extensions/ask-user-question-tool/index.ts +0 -3
- package/extensions/clear/__tests__/clear.test.ts +270 -3
- package/extensions/command-expansion/index.ts +1 -1
- package/extensions/context-files/index.ts +5 -1
- package/extensions/context-fork/__tests__/context-fork.test.ts +94 -1
- package/extensions/context-fork/extension.json +1 -1
- package/extensions/context-fork/index.ts +32 -0
- package/extensions/edit-tool-enhanced/index.ts +2 -1
- package/extensions/hooks/index.ts +33 -11
- package/extensions/loop/index.ts +14 -1
- package/extensions/lsp/index.ts +64 -13
- package/extensions/lsp/package.json +2 -2
- package/extensions/permissions/__tests__/permissions.test.ts +4 -4
- package/extensions/random-spinner/index.ts +7 -642
- package/extensions/read-tool-enhanced/index.ts +6 -8
- package/extensions/render-stabilizer/__tests__/render-stabilizer.test.ts +4 -5
- package/extensions/render-stabilizer/index.ts +6 -6
- package/extensions/show-system-prompt/__tests__/show-system-prompt.test.ts +1 -1
- package/extensions/slash-command-bridge/__tests__/slash-command-bridge.test.ts +26 -0
- package/extensions/slash-command-bridge/index.ts +14 -2
- package/extensions/subagent-tool/index.ts +1 -1
- package/extensions/subagent-tool/model-resolver.ts +274 -7
- package/extensions/tasks/__tests__/state-ui.test.ts +3 -3
- package/extensions/tasks/__tests__/widget-subagents.test.ts +2 -2
- package/extensions/tasks/commands/register-tasks-extension.ts +10 -10
- package/extensions/tasks/state/index.ts +1 -1
- package/extensions/tasks/ui/index.ts +2 -7
- package/extensions/teams-tool/tools/register-extension.ts +1 -3
- package/extensions/web-search-tool/index.ts +2 -1
- package/extensions/write-tool-enhanced/__tests__/write-tool-enhanced.test.ts +21 -6
- package/extensions/write-tool-enhanced/index.ts +2 -1
- package/node_modules/@mariozechner/pi-tui/README.md +56 -34
- package/node_modules/@mariozechner/pi-tui/dist/autocomplete.d.ts +18 -13
- package/node_modules/@mariozechner/pi-tui/dist/autocomplete.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/autocomplete.js +182 -113
- package/node_modules/@mariozechner/pi-tui/dist/autocomplete.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/cancellable-loader.js +3 -3
- package/node_modules/@mariozechner/pi-tui/dist/components/cancellable-loader.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/editor.d.ts +45 -36
- package/node_modules/@mariozechner/pi-tui/dist/components/editor.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/editor.js +489 -325
- package/node_modules/@mariozechner/pi-tui/dist/components/editor.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/image.d.ts +1 -99
- package/node_modules/@mariozechner/pi-tui/dist/components/image.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/image.js +17 -192
- package/node_modules/@mariozechner/pi-tui/dist/components/image.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/input.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/input.js +57 -60
- package/node_modules/@mariozechner/pi-tui/dist/components/input.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/loader.d.ts +2 -69
- package/node_modules/@mariozechner/pi-tui/dist/components/loader.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/loader.js +5 -102
- package/node_modules/@mariozechner/pi-tui/dist/components/loader.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/markdown.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/markdown.js +111 -53
- package/node_modules/@mariozechner/pi-tui/dist/components/markdown.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/select-list.d.ts +19 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/select-list.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/select-list.js +78 -67
- package/node_modules/@mariozechner/pi-tui/dist/components/select-list.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/settings-list.d.ts +0 -2
- package/node_modules/@mariozechner/pi-tui/dist/components/settings-list.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/settings-list.js +12 -23
- package/node_modules/@mariozechner/pi-tui/dist/components/settings-list.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/index.d.ts +8 -10
- package/node_modules/@mariozechner/pi-tui/dist/index.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/index.js +6 -9
- package/node_modules/@mariozechner/pi-tui/dist/index.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/keybindings.d.ts +108 -238
- package/node_modules/@mariozechner/pi-tui/dist/keybindings.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/keybindings.js +108 -365
- package/node_modules/@mariozechner/pi-tui/dist/keybindings.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/keys.d.ts +33 -48
- package/node_modules/@mariozechner/pi-tui/dist/keys.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/keys.js +239 -155
- package/node_modules/@mariozechner/pi-tui/dist/keys.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/terminal-image.d.ts +14 -94
- package/node_modules/@mariozechner/pi-tui/dist/terminal-image.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/terminal-image.js +44 -186
- package/node_modules/@mariozechner/pi-tui/dist/terminal-image.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/terminal.d.ts +13 -58
- package/node_modules/@mariozechner/pi-tui/dist/terminal.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/terminal.js +78 -111
- package/node_modules/@mariozechner/pi-tui/dist/terminal.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/tui.d.ts +24 -110
- package/node_modules/@mariozechner/pi-tui/dist/tui.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/tui.js +188 -435
- package/node_modules/@mariozechner/pi-tui/dist/tui.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/utils.d.ts +0 -18
- package/node_modules/@mariozechner/pi-tui/dist/utils.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/utils.js +251 -119
- package/node_modules/@mariozechner/pi-tui/dist/utils.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/package.json +6 -6
- package/node_modules/@mariozechner/pi-tui/src/__tests__/__snapshots__/render.test.ts.snap +3 -40
- package/node_modules/@mariozechner/pi-tui/src/__tests__/image-component.test.ts +71 -81
- package/node_modules/@mariozechner/pi-tui/src/__tests__/render.test.ts +0 -33
- package/node_modules/@mariozechner/pi-tui/src/__tests__/terminal-image.test.ts +93 -334
- package/node_modules/@mariozechner/pi-tui/src/__tests__/tui-render-scheduling.test.ts +1 -1
- package/node_modules/@mariozechner/pi-tui/src/__tests__/utils.test.ts +11 -196
- package/node_modules/@mariozechner/pi-tui/src/autocomplete.ts +228 -142
- package/node_modules/@mariozechner/pi-tui/src/components/cancellable-loader.ts +3 -3
- package/node_modules/@mariozechner/pi-tui/src/components/editor.ts +624 -390
- package/node_modules/@mariozechner/pi-tui/src/components/image.ts +17 -227
- package/node_modules/@mariozechner/pi-tui/src/components/input.ts +71 -63
- package/node_modules/@mariozechner/pi-tui/src/components/loader.ts +5 -137
- package/node_modules/@mariozechner/pi-tui/src/components/markdown.ts +143 -52
- package/node_modules/@mariozechner/pi-tui/src/components/select-list.ts +136 -70
- package/node_modules/@mariozechner/pi-tui/src/components/settings-list.ts +11 -23
- package/node_modules/@mariozechner/pi-tui/src/index.ts +17 -36
- package/node_modules/@mariozechner/pi-tui/src/keybindings.ts +148 -421
- package/node_modules/@mariozechner/pi-tui/src/keys.ts +253 -181
- package/node_modules/@mariozechner/pi-tui/src/terminal-image.ts +51 -252
- package/node_modules/@mariozechner/pi-tui/src/terminal.ts +78 -133
- package/node_modules/@mariozechner/pi-tui/src/tui.ts +202 -478
- package/node_modules/@mariozechner/pi-tui/src/utils.ts +289 -125
- package/node_modules/@mariozechner/pi-tui/tsconfig.build.json +1 -0
- package/package.json +13 -13
- package/packages/tallow-tui/node_modules/@types/mime-types/README.md +8 -2
- package/packages/tallow-tui/node_modules/@types/mime-types/index.d.ts +6 -0
- package/packages/tallow-tui/node_modules/@types/mime-types/package.json +9 -3
- package/packages/tallow-tui/node_modules/get-east-asian-width/lookup-data.js +18 -0
- package/packages/tallow-tui/node_modules/get-east-asian-width/lookup.js +116 -384
- package/packages/tallow-tui/node_modules/get-east-asian-width/package.json +5 -4
- package/packages/tallow-tui/node_modules/get-east-asian-width/utilities.js +24 -0
- package/packages/tallow-tui/node_modules/marked/README.md +5 -4
- package/packages/tallow-tui/node_modules/marked/bin/main.js +10 -8
- package/packages/tallow-tui/node_modules/marked/bin/marked.js +2 -1
- package/packages/tallow-tui/node_modules/marked/lib/marked.d.ts +156 -125
- package/packages/tallow-tui/node_modules/marked/lib/marked.esm.js +67 -2179
- package/packages/tallow-tui/node_modules/marked/lib/marked.esm.js.map +3 -3
- package/packages/tallow-tui/node_modules/marked/lib/marked.umd.js +67 -2201
- package/packages/tallow-tui/node_modules/marked/lib/marked.umd.js.map +3 -3
- package/packages/tallow-tui/node_modules/marked/man/marked.1 +4 -2
- package/packages/tallow-tui/node_modules/marked/man/marked.1.md +2 -1
- package/packages/tallow-tui/node_modules/marked/package.json +26 -34
- package/runtime/model-metadata-overrides.ts +10 -1
- package/runtime/pid-schema.ts +26 -6
- package/skills/tallow-expert/SKILL.md +1 -3
- package/node_modules/@mariozechner/pi-tui/dist/border-styles.d.ts +0 -32
- package/node_modules/@mariozechner/pi-tui/dist/border-styles.d.ts.map +0 -1
- package/node_modules/@mariozechner/pi-tui/dist/border-styles.js +0 -46
- package/node_modules/@mariozechner/pi-tui/dist/border-styles.js.map +0 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/bordered-box.d.ts +0 -52
- package/node_modules/@mariozechner/pi-tui/dist/components/bordered-box.d.ts.map +0 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/bordered-box.js +0 -89
- package/node_modules/@mariozechner/pi-tui/dist/components/bordered-box.js.map +0 -1
- package/node_modules/@mariozechner/pi-tui/dist/test-utils/capability-env.d.ts +0 -14
- package/node_modules/@mariozechner/pi-tui/dist/test-utils/capability-env.d.ts.map +0 -1
- package/node_modules/@mariozechner/pi-tui/dist/test-utils/capability-env.js +0 -55
- package/node_modules/@mariozechner/pi-tui/dist/test-utils/capability-env.js.map +0 -1
- package/node_modules/@mariozechner/pi-tui/src/__tests__/editor-change-listener.test.ts +0 -121
- package/node_modules/@mariozechner/pi-tui/src/__tests__/editor-ghost-text.test.ts +0 -112
- package/node_modules/@mariozechner/pi-tui/src/__tests__/mouse-events.test.ts +0 -134
- package/node_modules/@mariozechner/pi-tui/src/__tests__/settings-list.test.ts +0 -49
- package/node_modules/@mariozechner/pi-tui/src/__tests__/tui-diff-regression.test.ts +0 -555
- package/node_modules/@mariozechner/pi-tui/src/border-styles.ts +0 -60
- package/node_modules/@mariozechner/pi-tui/src/components/bordered-box.ts +0 -113
- package/node_modules/@mariozechner/pi-tui/src/test-utils/capability-env.ts +0 -56
- package/packages/tallow-tui/node_modules/marked/lib/marked.cjs +0 -2211
- package/packages/tallow-tui/node_modules/marked/lib/marked.cjs.map +0 -7
- package/packages/tallow-tui/node_modules/marked/lib/marked.d.cts +0 -728
- package/packages/tallow-tui/node_modules/marked/marked.min.js +0 -69
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for Editor.addChangeListener — ensures change listeners fire
|
|
3
|
-
* alongside onChange without interfering with each other.
|
|
4
|
-
*/
|
|
5
|
-
import { describe, expect, test } from "bun:test";
|
|
6
|
-
import { Editor, type EditorTheme } from "../components/editor.js";
|
|
7
|
-
import type { TUI } from "../tui.js";
|
|
8
|
-
|
|
9
|
-
/** Minimal TUI mock providing only what Editor needs. */
|
|
10
|
-
function createMockTUI(): TUI {
|
|
11
|
-
return {
|
|
12
|
-
requestRender: () => {},
|
|
13
|
-
terminal: { rows: 40, cols: 80 },
|
|
14
|
-
} as unknown as TUI;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const theme: EditorTheme = {
|
|
18
|
-
borderColor: (s: string) => s,
|
|
19
|
-
selectList: {
|
|
20
|
-
selectedBg: (s: string) => s,
|
|
21
|
-
selectedFg: (s: string) => s,
|
|
22
|
-
normalBg: (s: string) => s,
|
|
23
|
-
normalFg: (s: string) => s,
|
|
24
|
-
matchHighlight: (s: string) => s,
|
|
25
|
-
descriptionFg: (s: string) => s,
|
|
26
|
-
},
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
/** Simulate typing a string character by character. */
|
|
30
|
-
function typeText(editor: Editor, text: string): void {
|
|
31
|
-
for (const char of text) {
|
|
32
|
-
editor.handleInput(char);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
describe("Editor.addChangeListener", () => {
|
|
37
|
-
test("listener fires on character input", () => {
|
|
38
|
-
const editor = new Editor(createMockTUI(), theme);
|
|
39
|
-
const received: string[] = [];
|
|
40
|
-
editor.addChangeListener((text) => received.push(text));
|
|
41
|
-
|
|
42
|
-
typeText(editor, "hi");
|
|
43
|
-
expect(received).toEqual(["h", "hi"]);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
test("listener fires alongside onChange", () => {
|
|
47
|
-
const editor = new Editor(createMockTUI(), theme);
|
|
48
|
-
const onChangeCalls: string[] = [];
|
|
49
|
-
const listenerCalls: string[] = [];
|
|
50
|
-
|
|
51
|
-
editor.onChange = (text) => onChangeCalls.push(text);
|
|
52
|
-
editor.addChangeListener((text) => listenerCalls.push(text));
|
|
53
|
-
|
|
54
|
-
typeText(editor, "ab");
|
|
55
|
-
expect(onChangeCalls).toEqual(["a", "ab"]);
|
|
56
|
-
expect(listenerCalls).toEqual(["a", "ab"]);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
test("overwriting onChange does not affect listener", () => {
|
|
60
|
-
const editor = new Editor(createMockTUI(), theme);
|
|
61
|
-
const listenerCalls: string[] = [];
|
|
62
|
-
|
|
63
|
-
editor.addChangeListener((text) => listenerCalls.push(text));
|
|
64
|
-
|
|
65
|
-
// Simulate framework overwriting onChange (second write overwrites first)
|
|
66
|
-
editor.onChange = () => {};
|
|
67
|
-
editor.onChange = () => {}; // intentional: tests that listener survives overwrites
|
|
68
|
-
|
|
69
|
-
typeText(editor, "x");
|
|
70
|
-
expect(listenerCalls).toEqual(["x"]);
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
test("multiple listeners all fire", () => {
|
|
74
|
-
const editor = new Editor(createMockTUI(), theme);
|
|
75
|
-
const calls1: string[] = [];
|
|
76
|
-
const calls2: string[] = [];
|
|
77
|
-
const calls3: string[] = [];
|
|
78
|
-
|
|
79
|
-
editor.addChangeListener((text) => calls1.push(text));
|
|
80
|
-
editor.addChangeListener((text) => calls2.push(text));
|
|
81
|
-
editor.addChangeListener((text) => calls3.push(text));
|
|
82
|
-
|
|
83
|
-
typeText(editor, "z");
|
|
84
|
-
expect(calls1).toEqual(["z"]);
|
|
85
|
-
expect(calls2).toEqual(["z"]);
|
|
86
|
-
expect(calls3).toEqual(["z"]);
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
test("listener fires on backspace", () => {
|
|
90
|
-
const editor = new Editor(createMockTUI(), theme);
|
|
91
|
-
const received: string[] = [];
|
|
92
|
-
editor.addChangeListener((text) => received.push(text));
|
|
93
|
-
|
|
94
|
-
typeText(editor, "ab");
|
|
95
|
-
editor.handleInput("\x7f"); // backspace
|
|
96
|
-
expect(received).toEqual(["a", "ab", "a"]);
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
test("listener fires on setText", () => {
|
|
100
|
-
const editor = new Editor(createMockTUI(), theme);
|
|
101
|
-
const received: string[] = [];
|
|
102
|
-
editor.addChangeListener((text) => received.push(text));
|
|
103
|
-
|
|
104
|
-
editor.setText("hello world");
|
|
105
|
-
expect(received).toEqual(["hello world"]);
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
test("listener fires on submit (text cleared)", () => {
|
|
109
|
-
const editor = new Editor(createMockTUI(), theme);
|
|
110
|
-
const received: string[] = [];
|
|
111
|
-
editor.addChangeListener((text) => received.push(text));
|
|
112
|
-
editor.onSubmit = () => {}; // prevent default submit behavior
|
|
113
|
-
|
|
114
|
-
typeText(editor, "test");
|
|
115
|
-
received.length = 0; // clear typing events
|
|
116
|
-
|
|
117
|
-
editor.handleInput("\r"); // Enter/submit
|
|
118
|
-
// After submit, editor text is cleared — listener gets ""
|
|
119
|
-
expect(received).toContain("");
|
|
120
|
-
});
|
|
121
|
-
});
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for Editor ghost text (inline suggestion) functionality.
|
|
3
|
-
*
|
|
4
|
-
* Uses a minimal TUI mock since Editor requires a TUI instance.
|
|
5
|
-
*/
|
|
6
|
-
import { describe, expect, test } from "bun:test";
|
|
7
|
-
import { Editor, type EditorTheme } from "../components/editor.js";
|
|
8
|
-
import type { TUI } from "../tui.js";
|
|
9
|
-
|
|
10
|
-
/** Minimal TUI mock providing only what Editor needs. */
|
|
11
|
-
function createMockTUI(): TUI {
|
|
12
|
-
return {
|
|
13
|
-
requestRender: () => {},
|
|
14
|
-
terminal: { rows: 40, cols: 80 },
|
|
15
|
-
} as unknown as TUI;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const theme: EditorTheme = {
|
|
19
|
-
borderColor: (s: string) => s,
|
|
20
|
-
selectList: {
|
|
21
|
-
selectedBg: (s: string) => s,
|
|
22
|
-
selectedFg: (s: string) => s,
|
|
23
|
-
normalBg: (s: string) => s,
|
|
24
|
-
normalFg: (s: string) => s,
|
|
25
|
-
matchHighlight: (s: string) => s,
|
|
26
|
-
descriptionFg: (s: string) => s,
|
|
27
|
-
},
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
describe("Editor ghost text", () => {
|
|
31
|
-
test("setGhostText stores and getGhostText retrieves", () => {
|
|
32
|
-
const editor = new Editor(createMockTUI(), theme);
|
|
33
|
-
expect(editor.getGhostText()).toBeNull();
|
|
34
|
-
editor.setGhostText("hello world");
|
|
35
|
-
expect(editor.getGhostText()).toBe("hello world");
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
test("setGhostText(null) clears ghost text", () => {
|
|
39
|
-
const editor = new Editor(createMockTUI(), theme);
|
|
40
|
-
editor.setGhostText("suggestion");
|
|
41
|
-
editor.setGhostText(null);
|
|
42
|
-
expect(editor.getGhostText()).toBeNull();
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
test("ghost text renders as dim ANSI after cursor", () => {
|
|
46
|
-
const editor = new Editor(createMockTUI(), theme);
|
|
47
|
-
editor.setGhostText("complete me");
|
|
48
|
-
const lines = editor.render(80);
|
|
49
|
-
// Ghost text should appear as muted gray (256-color 242) in the output
|
|
50
|
-
const joined = lines.join("\n");
|
|
51
|
-
expect(joined).toContain("\x1b[38;5;242m");
|
|
52
|
-
expect(joined).toContain("complete me");
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
test("ghost text cleared when character is typed", () => {
|
|
56
|
-
const editor = new Editor(createMockTUI(), theme);
|
|
57
|
-
editor.setGhostText("suggestion");
|
|
58
|
-
editor.handleInput("a");
|
|
59
|
-
expect(editor.getGhostText()).toBeNull();
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
test("ghost text cleared on backspace", () => {
|
|
63
|
-
const editor = new Editor(createMockTUI(), theme);
|
|
64
|
-
editor.setText("hello");
|
|
65
|
-
editor.setGhostText("world");
|
|
66
|
-
// Backspace (DEL character)
|
|
67
|
-
editor.handleInput("\x7f");
|
|
68
|
-
expect(editor.getGhostText()).toBeNull();
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
test("Tab accepts ghost text into buffer", () => {
|
|
72
|
-
const editor = new Editor(createMockTUI(), theme);
|
|
73
|
-
editor.setGhostText("complete me");
|
|
74
|
-
// Tab
|
|
75
|
-
editor.handleInput("\t");
|
|
76
|
-
expect(editor.getGhostText()).toBeNull();
|
|
77
|
-
expect(editor.getText()).toBe("complete me");
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
test("Enter on empty input accepts ghost text and submits", () => {
|
|
81
|
-
const editor = new Editor(createMockTUI(), theme);
|
|
82
|
-
let submitted = "";
|
|
83
|
-
editor.onSubmit = (text: string) => {
|
|
84
|
-
submitted = text;
|
|
85
|
-
};
|
|
86
|
-
editor.setGhostText("suggested prompt");
|
|
87
|
-
// Enter (carriage return)
|
|
88
|
-
editor.handleInput("\r");
|
|
89
|
-
expect(submitted).toBe("suggested prompt");
|
|
90
|
-
expect(editor.getGhostText()).toBeNull();
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
test("Enter on non-empty input submits typed text, not ghost text", () => {
|
|
94
|
-
const editor = new Editor(createMockTUI(), theme);
|
|
95
|
-
let submitted = "";
|
|
96
|
-
editor.onSubmit = (text: string) => {
|
|
97
|
-
submitted = text;
|
|
98
|
-
};
|
|
99
|
-
editor.setText("my input");
|
|
100
|
-
editor.setGhostText("ghost suggestion");
|
|
101
|
-
editor.handleInput("\r");
|
|
102
|
-
expect(submitted).toBe("my input");
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
test("Escape dismisses ghost text", () => {
|
|
106
|
-
const editor = new Editor(createMockTUI(), theme);
|
|
107
|
-
editor.setGhostText("suggestion");
|
|
108
|
-
// Escape
|
|
109
|
-
editor.handleInput("\x1b");
|
|
110
|
-
expect(editor.getGhostText()).toBeNull();
|
|
111
|
-
});
|
|
112
|
-
});
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for SGR mouse event parsing: parseMouseEvent and isMouseEvent.
|
|
3
|
-
*/
|
|
4
|
-
import { describe, expect, it } from "bun:test";
|
|
5
|
-
import { isMouseEvent, parseMouseEvent } from "../keys.js";
|
|
6
|
-
|
|
7
|
-
// ── parseMouseEvent ──────────────────────────────────────────────────────────
|
|
8
|
-
|
|
9
|
-
describe("parseMouseEvent", () => {
|
|
10
|
-
it("parses scroll-up event", () => {
|
|
11
|
-
// SGR: \x1b[<64;10;5M — code 64 = scroll up, col 10, row 5, press
|
|
12
|
-
expect(parseMouseEvent("\x1b[<64;10;5M")).toEqual({
|
|
13
|
-
type: "scroll-up",
|
|
14
|
-
button: 0,
|
|
15
|
-
x: 10,
|
|
16
|
-
y: 5,
|
|
17
|
-
});
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it("parses scroll-down event", () => {
|
|
21
|
-
// SGR: \x1b[<65;20;15M — code 65 = scroll down, col 20, row 15, press
|
|
22
|
-
expect(parseMouseEvent("\x1b[<65;20;15M")).toEqual({
|
|
23
|
-
type: "scroll-down",
|
|
24
|
-
button: 0,
|
|
25
|
-
x: 20,
|
|
26
|
-
y: 15,
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it("parses left button press", () => {
|
|
31
|
-
// SGR: \x1b[<0;5;3M — code 0 = left button, col 5, row 3, M = press
|
|
32
|
-
expect(parseMouseEvent("\x1b[<0;5;3M")).toEqual({
|
|
33
|
-
type: "press",
|
|
34
|
-
button: 0,
|
|
35
|
-
x: 5,
|
|
36
|
-
y: 3,
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it("parses left button release", () => {
|
|
41
|
-
// SGR: \x1b[<0;5;3m — code 0, lowercase m = release
|
|
42
|
-
expect(parseMouseEvent("\x1b[<0;5;3m")).toEqual({
|
|
43
|
-
type: "release",
|
|
44
|
-
button: 0,
|
|
45
|
-
x: 5,
|
|
46
|
-
y: 3,
|
|
47
|
-
});
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it("parses middle button press", () => {
|
|
51
|
-
// SGR: \x1b[<1;12;8M — code 1 = middle button
|
|
52
|
-
expect(parseMouseEvent("\x1b[<1;12;8M")).toEqual({
|
|
53
|
-
type: "press",
|
|
54
|
-
button: 1,
|
|
55
|
-
x: 12,
|
|
56
|
-
y: 8,
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it("parses right button press", () => {
|
|
61
|
-
// SGR: \x1b[<2;30;20M — code 2 = right button
|
|
62
|
-
expect(parseMouseEvent("\x1b[<2;30;20M")).toEqual({
|
|
63
|
-
type: "press",
|
|
64
|
-
button: 2,
|
|
65
|
-
x: 30,
|
|
66
|
-
y: 20,
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it("parses drag event (bit 5 set)", () => {
|
|
71
|
-
// SGR: \x1b[<32;15;10M — code 32 = motion + left button
|
|
72
|
-
expect(parseMouseEvent("\x1b[<32;15;10M")).toEqual({
|
|
73
|
-
type: "drag",
|
|
74
|
-
button: 0,
|
|
75
|
-
x: 15,
|
|
76
|
-
y: 10,
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it("parses drag with right button", () => {
|
|
81
|
-
// SGR: \x1b[<34;15;10M — code 34 = 32 (motion) + 2 (right)
|
|
82
|
-
expect(parseMouseEvent("\x1b[<34;15;10M")).toEqual({
|
|
83
|
-
type: "drag",
|
|
84
|
-
button: 2,
|
|
85
|
-
x: 15,
|
|
86
|
-
y: 10,
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
it("handles large coordinates (beyond 223-column limit)", () => {
|
|
91
|
-
// SGR format supports arbitrary coordinates — this is why we use mode 1006
|
|
92
|
-
expect(parseMouseEvent("\x1b[<0;300;150M")).toEqual({
|
|
93
|
-
type: "press",
|
|
94
|
-
button: 0,
|
|
95
|
-
x: 300,
|
|
96
|
-
y: 150,
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
it("returns null for non-mouse input", () => {
|
|
101
|
-
expect(parseMouseEvent("a")).toBeNull();
|
|
102
|
-
expect(parseMouseEvent("\x1b[A")).toBeNull(); // arrow up
|
|
103
|
-
expect(parseMouseEvent("\x1b[1;2H")).toBeNull(); // cursor position
|
|
104
|
-
expect(parseMouseEvent("")).toBeNull();
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
it("returns null for malformed SGR sequences", () => {
|
|
108
|
-
expect(parseMouseEvent("\x1b[<0;5M")).toBeNull(); // missing y
|
|
109
|
-
expect(parseMouseEvent("\x1b[<0;5;3")).toBeNull(); // missing M/m terminator
|
|
110
|
-
expect(parseMouseEvent("\x1b[<;5;3M")).toBeNull(); // missing code
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
// ── isMouseEvent ─────────────────────────────────────────────────────────────
|
|
115
|
-
|
|
116
|
-
describe("isMouseEvent", () => {
|
|
117
|
-
it("returns true for SGR mouse sequences", () => {
|
|
118
|
-
expect(isMouseEvent("\x1b[<0;5;3M")).toBe(true);
|
|
119
|
-
expect(isMouseEvent("\x1b[<64;10;5M")).toBe(true);
|
|
120
|
-
expect(isMouseEvent("\x1b[<0;300;150m")).toBe(true);
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
it("returns false for non-mouse input", () => {
|
|
124
|
-
expect(isMouseEvent("a")).toBe(false);
|
|
125
|
-
expect(isMouseEvent("\x1b[A")).toBe(false);
|
|
126
|
-
expect(isMouseEvent("\x1b[1")).toBe(false);
|
|
127
|
-
expect(isMouseEvent("")).toBe(false);
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
it("returns false for strings shorter than minimum mouse sequence", () => {
|
|
131
|
-
// Minimum: \x1b[<N;N;NM = 9 chars
|
|
132
|
-
expect(isMouseEvent("\x1b[<0;5;")).toBe(false);
|
|
133
|
-
});
|
|
134
|
-
});
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "bun:test";
|
|
2
|
-
import { SettingsList, type SettingsListTheme } from "../components/settings-list.js";
|
|
3
|
-
|
|
4
|
-
const theme: SettingsListTheme = {
|
|
5
|
-
cursor: "> ",
|
|
6
|
-
description: (text) => text,
|
|
7
|
-
hint: (text) => text,
|
|
8
|
-
label: (text) => text,
|
|
9
|
-
value: (text) => text,
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
describe("SettingsList submenu transitions", () => {
|
|
13
|
-
it("preserves submenu height for one frame when closing back to the main list", () => {
|
|
14
|
-
let changedValue: string | undefined;
|
|
15
|
-
const list = new SettingsList(
|
|
16
|
-
[
|
|
17
|
-
{
|
|
18
|
-
id: "thinking",
|
|
19
|
-
label: "Thinking level",
|
|
20
|
-
currentValue: "medium",
|
|
21
|
-
description: "Reasoning depth",
|
|
22
|
-
submenu: (_currentValue, done) => ({
|
|
23
|
-
handleInput: () => done("high"),
|
|
24
|
-
invalidate: () => {},
|
|
25
|
-
render: () => ["submenu", "", "one", "two", "three", "four", "five", "six"],
|
|
26
|
-
}),
|
|
27
|
-
},
|
|
28
|
-
],
|
|
29
|
-
10,
|
|
30
|
-
theme,
|
|
31
|
-
(_id, newValue) => {
|
|
32
|
-
changedValue = newValue;
|
|
33
|
-
},
|
|
34
|
-
() => {}
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
const initialLines = list.render(80);
|
|
38
|
-
list.handleInput(" ");
|
|
39
|
-
const submenuLines = list.render(80);
|
|
40
|
-
list.handleInput("x");
|
|
41
|
-
const firstFrameAfterClose = list.render(80);
|
|
42
|
-
const secondFrameAfterClose = list.render(80);
|
|
43
|
-
|
|
44
|
-
expect(changedValue).toBe("high");
|
|
45
|
-
expect(submenuLines.length).toBeGreaterThan(initialLines.length);
|
|
46
|
-
expect(firstFrameAfterClose.length).toBe(submenuLines.length);
|
|
47
|
-
expect(secondFrameAfterClose.length).toBe(initialLines.length);
|
|
48
|
-
});
|
|
49
|
-
});
|