Skip to content

Commit 0d10cb6

Browse files
committed
fix(tui): restore cursorUp start-of-line jump when input is non-empty
1 parent b0c8f65 commit 0d10cb6

2 files changed

Lines changed: 16 additions & 4 deletions

File tree

packages/tui/src/components/editor.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,10 @@ export class Editor implements Component, Focusable {
390390
}
391391
}
392392

393+
private isEditorEmpty(): boolean {
394+
return this.state.lines.length === 1 && this.state.lines[0] === "";
395+
}
396+
393397
private isOnFirstVisualLine(): boolean {
394398
const visualLines = this.buildVisualLineMap(this.lastWidth);
395399
const currentVisualLine = this.findCurrentVisualLine(visualLines);
@@ -803,7 +807,10 @@ export class Editor implements Component, Focusable {
803807

804808
// Arrow key navigation (with history support)
805809
if (kb.matches(data, "tui.editor.cursorUp")) {
806-
if (this.isOnFirstVisualLine() && this.history.length > 0) {
810+
if (
811+
this.isOnFirstVisualLine() &&
812+
(this.isEditorEmpty() || this.historyIndex > -1 || this.state.cursorCol === 0)
813+
) {
807814
this.navigateHistory(-1);
808815
} else if (this.isOnFirstVisualLine()) {
809816
// Already at top - jump to start of line

packages/tui/test/editor.test.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,20 +79,24 @@ describe("Editor component", () => {
7979
assert.strictEqual(editor.getText(), "first");
8080
});
8181

82-
it("restores draft on Down arrow after browsing history", () => {
82+
it("jumps to start before entering history from a non-empty draft", () => {
8383
const editor = new Editor(createTestTUI(), defaultEditorTheme);
8484

8585
editor.addToHistory("prompt");
8686
editor.setText("draft");
8787
editor.handleInput("\x1b[D");
8888
editor.handleInput("\x1b[D");
8989

90-
editor.handleInput("\x1b[A"); // Up - shows "prompt"
90+
editor.handleInput("\x1b[A"); // Up - jumps to start before history browsing
91+
assert.strictEqual(editor.getText(), "draft");
92+
assert.deepStrictEqual(editor.getCursor(), { line: 0, col: 0 });
93+
94+
editor.handleInput("\x1b[A"); // Up at start - shows "prompt"
9195
assert.strictEqual(editor.getText(), "prompt");
9296

9397
editor.handleInput("\x1b[B"); // Down - restores draft
9498
assert.strictEqual(editor.getText(), "draft");
95-
assert.deepStrictEqual(editor.getCursor(), { line: 0, col: 3 });
99+
assert.deepStrictEqual(editor.getCursor(), { line: 0, col: 0 });
96100
});
97101

98102
it("navigates forward through history with Down arrow", () => {
@@ -104,6 +108,7 @@ describe("Editor component", () => {
104108
editor.setText("draft");
105109

106110
// Go to oldest
111+
editor.handleInput("\x1b[A"); // start of draft
107112
editor.handleInput("\x1b[A"); // third
108113
editor.handleInput("\x1b[A"); // second
109114
editor.handleInput("\x1b[A"); // first

0 commit comments

Comments
 (0)