fix(tui): restore cursorUp start-of-line jump when input is non-empty (#5789)
This commit is contained in:
@@ -390,6 +390,10 @@ export class Editor implements Component, Focusable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private isEditorEmpty(): boolean {
|
||||||
|
return this.state.lines.length === 1 && this.state.lines[0] === "";
|
||||||
|
}
|
||||||
|
|
||||||
private isOnFirstVisualLine(): boolean {
|
private isOnFirstVisualLine(): boolean {
|
||||||
const visualLines = this.buildVisualLineMap(this.lastWidth);
|
const visualLines = this.buildVisualLineMap(this.lastWidth);
|
||||||
const currentVisualLine = this.findCurrentVisualLine(visualLines);
|
const currentVisualLine = this.findCurrentVisualLine(visualLines);
|
||||||
@@ -803,7 +807,10 @@ export class Editor implements Component, Focusable {
|
|||||||
|
|
||||||
// Arrow key navigation (with history support)
|
// Arrow key navigation (with history support)
|
||||||
if (kb.matches(data, "tui.editor.cursorUp")) {
|
if (kb.matches(data, "tui.editor.cursorUp")) {
|
||||||
if (this.isOnFirstVisualLine() && this.history.length > 0) {
|
if (
|
||||||
|
this.isOnFirstVisualLine() &&
|
||||||
|
(this.isEditorEmpty() || this.historyIndex > -1 || this.state.cursorCol === 0)
|
||||||
|
) {
|
||||||
this.navigateHistory(-1);
|
this.navigateHistory(-1);
|
||||||
} else if (this.isOnFirstVisualLine()) {
|
} else if (this.isOnFirstVisualLine()) {
|
||||||
// Already at top - jump to start of line
|
// Already at top - jump to start of line
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ describe("Editor component", () => {
|
|||||||
assert.strictEqual(editor.getText(), "first");
|
assert.strictEqual(editor.getText(), "first");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("restores draft on Down arrow after browsing history", () => {
|
it("jumps to start before entering history from a non-empty draft", () => {
|
||||||
const editor = new Editor(createTestTUI(), defaultEditorTheme);
|
const editor = new Editor(createTestTUI(), defaultEditorTheme);
|
||||||
|
|
||||||
editor.addToHistory("prompt");
|
editor.addToHistory("prompt");
|
||||||
@@ -87,12 +87,16 @@ describe("Editor component", () => {
|
|||||||
editor.handleInput("\x1b[D");
|
editor.handleInput("\x1b[D");
|
||||||
editor.handleInput("\x1b[D");
|
editor.handleInput("\x1b[D");
|
||||||
|
|
||||||
editor.handleInput("\x1b[A"); // Up - shows "prompt"
|
editor.handleInput("\x1b[A"); // Up - jumps to start before history browsing
|
||||||
|
assert.strictEqual(editor.getText(), "draft");
|
||||||
|
assert.deepStrictEqual(editor.getCursor(), { line: 0, col: 0 });
|
||||||
|
|
||||||
|
editor.handleInput("\x1b[A"); // Up at start - shows "prompt"
|
||||||
assert.strictEqual(editor.getText(), "prompt");
|
assert.strictEqual(editor.getText(), "prompt");
|
||||||
|
|
||||||
editor.handleInput("\x1b[B"); // Down - restores draft
|
editor.handleInput("\x1b[B"); // Down - restores draft
|
||||||
assert.strictEqual(editor.getText(), "draft");
|
assert.strictEqual(editor.getText(), "draft");
|
||||||
assert.deepStrictEqual(editor.getCursor(), { line: 0, col: 3 });
|
assert.deepStrictEqual(editor.getCursor(), { line: 0, col: 0 });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("navigates forward through history with Down arrow", () => {
|
it("navigates forward through history with Down arrow", () => {
|
||||||
@@ -104,6 +108,7 @@ describe("Editor component", () => {
|
|||||||
editor.setText("draft");
|
editor.setText("draft");
|
||||||
|
|
||||||
// Go to oldest
|
// Go to oldest
|
||||||
|
editor.handleInput("\x1b[A"); // start of draft
|
||||||
editor.handleInput("\x1b[A"); // third
|
editor.handleInput("\x1b[A"); // third
|
||||||
editor.handleInput("\x1b[A"); // second
|
editor.handleInput("\x1b[A"); // second
|
||||||
editor.handleInput("\x1b[A"); // first
|
editor.handleInput("\x1b[A"); // first
|
||||||
|
|||||||
Reference in New Issue
Block a user