mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
tui.select.pageUp/pageDown were configurable but ignored by SelectList, SettingsList, editor autocomplete, and most coding-agent selectors. In fullscreen mode, the default PageUp/PageDown also scrolled the transcript instead of reaching the focused list. - add getSelectPageIndex() and handle page keys in SelectList, SettingsList, editor autocomplete, and the model, scoped models, auth, user message, settings submenu, llama search, and /mcp selectors - add Component.capturesViewportInput: a focused component that sets it receives fullscreen viewport keys instead of the transcript, as a focused overlay already does - let page keys move an open autocomplete menu before app actions, so a remapped Ctrl+V pages the menu instead of pasting an image closes #7629 Co-authored-by: muyiyr <940955635@qq.com>
79 lines
2.7 KiB
TypeScript
79 lines
2.7 KiB
TypeScript
import { setKeybindings, TuiMainScreen } from "@earendil-works/pi-tui";
|
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
import { defaultEditorTheme } from "../../tui/test/test-themes.ts";
|
|
import { VirtualTerminal } from "../../tui/test/virtual-terminal.ts";
|
|
import { KeybindingsManager } from "../src/core/keybindings.ts";
|
|
import { CustomEditor } from "../src/modes/interactive/components/custom-editor.ts";
|
|
|
|
afterEach(() => {
|
|
setKeybindings(new KeybindingsManager());
|
|
});
|
|
|
|
describe("CustomEditor prompt history keybindings", () => {
|
|
it("gives an explicit history binding precedence over model cycling", () => {
|
|
const keybindings = new KeybindingsManager({
|
|
"tui.editor.historyPrevious": "ctrl+p",
|
|
"tui.editor.historyNext": "ctrl+n",
|
|
});
|
|
setKeybindings(keybindings);
|
|
const editor = new CustomEditor(new TuiMainScreen(new VirtualTerminal()), defaultEditorTheme, keybindings);
|
|
let modelCycles = 0;
|
|
editor.onAction("app.model.cycleForward", () => {
|
|
modelCycles++;
|
|
});
|
|
editor.addToHistory("previous prompt");
|
|
editor.setText("draft");
|
|
|
|
editor.handleInput("\x10"); // Ctrl+P
|
|
expect(editor.getText()).toBe("previous prompt");
|
|
expect(modelCycles).toBe(0);
|
|
|
|
editor.handleInput("\x0e"); // Ctrl+N
|
|
expect(editor.getText()).toBe("draft");
|
|
});
|
|
});
|
|
|
|
describe("CustomEditor selection page keybindings", () => {
|
|
it("pages an open autocomplete menu before pasting an image with the same key (#7629)", async () => {
|
|
// Bind both explicitly: the paste default is Alt+V on Windows and WSL.
|
|
const keybindings = new KeybindingsManager({
|
|
"tui.select.pageDown": "ctrl+v",
|
|
"app.clipboard.pasteImage": "ctrl+v",
|
|
});
|
|
setKeybindings(keybindings);
|
|
const editor = new CustomEditor(new TuiMainScreen(new VirtualTerminal()), defaultEditorTheme, keybindings);
|
|
let pastes = 0;
|
|
editor.onPasteImage = () => {
|
|
pastes++;
|
|
};
|
|
let submitted = "";
|
|
editor.onSubmit = (text) => {
|
|
submitted = text;
|
|
};
|
|
editor.setAutocompleteProvider({
|
|
getSuggestions: async () => ({
|
|
items: Array.from({ length: 12 }, (_, index) => ({
|
|
value: `/command-${index}`,
|
|
label: `command-${index}`,
|
|
})),
|
|
prefix: "/",
|
|
}),
|
|
applyCompletion: (lines, cursorLine, _cursorCol, item) => ({
|
|
lines: lines.map((line, index) => (index === cursorLine ? item.value : line)),
|
|
cursorLine,
|
|
cursorCol: item.value.length,
|
|
}),
|
|
});
|
|
|
|
editor.handleInput("/");
|
|
await vi.waitFor(() => expect(editor.isShowingAutocomplete()).toBe(true));
|
|
editor.handleInput("\x16"); // Ctrl+V
|
|
editor.handleInput("\r");
|
|
|
|
expect(pastes).toBe(0);
|
|
expect(submitted).toBe("/command-5");
|
|
|
|
editor.handleInput("\x16"); // Ctrl+V with autocomplete closed pastes again
|
|
expect(pastes).toBe(1);
|
|
});
|
|
});
|