mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
fix(coding-agent): render session tree search cursor (#9157)
This PR adds the cursor block to the **Type to search** input in **Session Tree**. This is similar to the search input in **Resume Session**. Before: <img width="1120" height="778" alt="Screenshot 2026-09-04 at 19 25 30" src="https://github.com/user-attachments/assets/8f2e0ba9-8476-452b-a6be-1ad9b8d7d6c8" /> After: <img width="1120" height="778" alt="Screenshot 2026-09-04 at 19 25 50" src="https://github.com/user-attachments/assets/7f6ffcbf-db5a-4732-84fe-6ee0544116fa" />
This commit is contained in:
parent
c3b938e3e9
commit
2cfab7c269
2 changed files with 88 additions and 11 deletions
|
|
@ -1,5 +1,5 @@
|
|||
import { stripVTControlCharacters } from "node:util";
|
||||
import { setKeybindings, visibleWidth } from "@earendil-works/pi-tui";
|
||||
import { CURSOR_MARKER, setKeybindings, visibleWidth } from "@earendil-works/pi-tui";
|
||||
import { beforeAll, beforeEach, describe, expect, test } from "vitest";
|
||||
import { KeybindingsManager } from "../src/core/keybindings.ts";
|
||||
import type {
|
||||
|
|
@ -310,6 +310,73 @@ describe("TreeSelectorComponent", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("search cursor", () => {
|
||||
test("renders the cursor only while the selector is focused", () => {
|
||||
const tree = buildTree([userMessage("user-1", null, "hello")]);
|
||||
const selector = new TreeSelectorComponent(
|
||||
tree,
|
||||
"user-1",
|
||||
24,
|
||||
() => {},
|
||||
() => {},
|
||||
);
|
||||
|
||||
expect(selector.render(80).join("\n")).not.toContain(CURSOR_MARKER);
|
||||
|
||||
selector.focused = true;
|
||||
const focusedLines = selector.render(80);
|
||||
const cursorLines = focusedLines.filter((line) => line.includes(CURSOR_MARKER));
|
||||
expect(cursorLines).toHaveLength(1);
|
||||
expect(stripVTControlCharacters(cursorLines[0]!.replace(CURSOR_MARKER, ""))).toBe(" Type to search: ");
|
||||
expect(cursorLines[0]).toContain(`${CURSOR_MARKER}\x1b[7m \x1b[27m`);
|
||||
|
||||
selector.focused = false;
|
||||
expect(selector.render(80).join("\n")).not.toContain(CURSOR_MARKER);
|
||||
});
|
||||
|
||||
test("moves focus to the label input and restores it after cancellation", () => {
|
||||
const tree = buildTree([userMessage("user-1", null, "hello")]);
|
||||
const selector = new TreeSelectorComponent(
|
||||
tree,
|
||||
"user-1",
|
||||
24,
|
||||
() => {},
|
||||
() => {},
|
||||
);
|
||||
selector.focused = true;
|
||||
|
||||
selector.handleInput("L");
|
||||
let rendered = selector.render(80);
|
||||
let cursorLineIndex = rendered.findIndex((line) => line.includes(CURSOR_MARKER));
|
||||
expect(cursorLineIndex).toBeGreaterThan(0);
|
||||
expect(stripVTControlCharacters(rendered[cursorLineIndex - 1]!)).toContain("Label (empty to remove):");
|
||||
expect(rendered.filter((line) => line.includes(CURSOR_MARKER))).toHaveLength(1);
|
||||
|
||||
selector.handleInput("\x1b");
|
||||
rendered = selector.render(80);
|
||||
cursorLineIndex = rendered.findIndex((line) => line.includes(CURSOR_MARKER));
|
||||
expect(stripVTControlCharacters(rendered[cursorLineIndex]!)).toContain("Type to search:");
|
||||
expect(rendered.filter((line) => line.includes(CURSOR_MARKER))).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("keeps the cursor within narrow terminal widths", () => {
|
||||
const tree = buildTree([userMessage("user-1", null, "hello")]);
|
||||
const selector = new TreeSelectorComponent(
|
||||
tree,
|
||||
"user-1",
|
||||
24,
|
||||
() => {},
|
||||
() => {},
|
||||
);
|
||||
selector.focused = true;
|
||||
selector.handleInput("a long search query");
|
||||
|
||||
const cursorLine = selector.render(10).find((line) => line.includes(CURSOR_MARKER));
|
||||
expect(cursorLine).toBeDefined();
|
||||
expect(visibleWidth(cursorLine!)).toBeLessThanOrEqual(10);
|
||||
});
|
||||
});
|
||||
|
||||
describe("copy", () => {
|
||||
test("copies the full selected message with ctrl+x", () => {
|
||||
const message = `${"long message ".repeat(30)}\nsecond line`;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue