fix(tui): handle split Shift+Enter in VS Code

This commit is contained in:
Mario Zechner 2026-01-11 04:03:28 +01:00
parent f0fd0a7d6a
commit 178a3a563f
4 changed files with 84 additions and 0 deletions

View file

@ -232,6 +232,7 @@ export class Editor implements Component {
// Bracketed paste mode buffering
private pasteBuffer: string = "";
private isInPaste: boolean = false;
private pendingShiftEnter: boolean = false;
// Prompt history for up/down navigation
private history: string[] = [];
@ -422,6 +423,21 @@ export class Editor implements Component {
return;
}
if (this.pendingShiftEnter) {
if (data === "\r") {
this.pendingShiftEnter = false;
this.addNewLine();
return;
}
this.pendingShiftEnter = false;
this.insertCharacter("\\");
}
if (data === "\\") {
this.pendingShiftEnter = true;
return;
}
// Ctrl+C - let parent handle (exit/clear)
if (kb.matches(data, "copy")) {
return;

View file

@ -16,6 +16,7 @@ export class Input implements Component {
// Bracketed paste mode buffering
private pasteBuffer: string = "";
private isInPaste: boolean = false;
private pendingShiftEnter: boolean = false;
getValue(): string {
return this.value;
@ -63,6 +64,23 @@ export class Input implements Component {
}
return;
}
if (this.pendingShiftEnter) {
if (data === "\r") {
this.pendingShiftEnter = false;
if (this.onSubmit) this.onSubmit(this.value);
return;
}
this.pendingShiftEnter = false;
this.value = `${this.value.slice(0, this.cursor)}\\${this.value.slice(this.cursor)}`;
this.cursor += 1;
}
if (data === "\\") {
this.pendingShiftEnter = true;
return;
}
const kb = getEditorKeybindings();
// Escape/Cancel

View file

@ -275,6 +275,26 @@ describe("Editor component", () => {
});
});
describe("Shift+Enter handling", () => {
it("treats split VS Code Shift+Enter as a newline", () => {
const editor = new Editor(defaultEditorTheme);
editor.handleInput("\\");
editor.handleInput("\r");
assert.strictEqual(editor.getText(), "\n");
});
it("inserts a literal backslash when not followed by Enter", () => {
const editor = new Editor(defaultEditorTheme);
editor.handleInput("\\");
editor.handleInput("x");
assert.strictEqual(editor.getText(), "\\x");
});
});
describe("Unicode text editing behavior", () => {
it("inserts mixed ASCII, umlauts, and emojis as literal text", () => {
const editor = new Editor(defaultEditorTheme);

View file

@ -0,0 +1,30 @@
import assert from "node:assert";
import { describe, it } from "node:test";
import { Input } from "../src/components/input.js";
describe("Input component", () => {
it("treats split VS Code Shift+Enter as submit", () => {
const input = new Input();
let submitted: string | undefined;
input.setValue("hello");
input.onSubmit = (value) => {
submitted = value;
};
input.handleInput("\\");
input.handleInput("\r");
assert.strictEqual(submitted, "hello");
assert.strictEqual(input.getValue(), "hello");
});
it("inserts a literal backslash when not followed by Enter", () => {
const input = new Input();
input.handleInput("\\");
input.handleInput("x");
assert.strictEqual(input.getValue(), "\\x");
});
});