fix(tui): preserve literal paste content closes #2064

This commit is contained in:
Mario Zechner
2026-03-14 04:34:40 +01:00
parent a8e3c829fa
commit ad32089f0c
2 changed files with 59 additions and 11 deletions

View File

@@ -897,17 +897,21 @@ export class Editor implements Component, Focusable {
return this.state.lines.join("\n");
}
private expandPasteMarkers(text: string): string {
let result = text;
for (const [pasteId, pasteContent] of this.pastes) {
const markerRegex = new RegExp(`\\[paste #${pasteId}( (\\+\\d+ lines|\\d+ chars))?\\]`, "g");
result = result.replace(markerRegex, () => pasteContent);
}
return result;
}
/**
* Get text with paste markers expanded to their actual content.
* Use this when you need the full content (e.g., for external editor).
*/
getExpandedText(): string {
let result = this.state.lines.join("\n");
for (const [pasteId, pasteContent] of this.pastes) {
const markerRegex = new RegExp(`\\[paste #${pasteId}( (\\+\\d+ lines|\\d+ chars))?\\]`, "g");
result = result.replace(markerRegex, pasteContent);
}
return result;
return this.expandPasteMarkers(this.state.lines.join("\n"));
}
getLines(): string[] {
@@ -1152,11 +1156,7 @@ export class Editor implements Component, Focusable {
}
private submitValue(): void {
let result = this.state.lines.join("\n").trim();
for (const [pasteId, pasteContent] of this.pastes) {
const markerRegex = new RegExp(`\\[paste #${pasteId}( (\\+\\d+ lines|\\d+ chars))?\\]`, "g");
result = result.replace(markerRegex, pasteContent);
}
const result = this.expandPasteMarkers(this.state.lines.join("\n")).trim();
this.state = { lines: [""], cursorLine: 0, cursorCol: 0 };
this.pastes.clear();

View File

@@ -3388,5 +3388,53 @@ describe("Editor component", () => {
);
}
});
it("expands large pasted content literally in getExpandedText", () => {
const editor = new Editor(createTestTUI(), defaultEditorTheme);
const pastedText = [
"line 1",
"line 2",
"line 3",
"line 4",
"line 5",
"line 6",
"line 7",
"line 8",
"line 9",
"line 10",
"tokens $1 $2 $& $$ $` $' end",
].join("\n");
editor.handleInput(`\x1b[200~${pastedText}\x1b[201~`);
assert.match(editor.getText(), /\[paste #\d+ \+\d+ lines\]/);
assert.strictEqual(editor.getExpandedText(), pastedText);
});
it("submits large pasted content literally", () => {
const editor = new Editor(createTestTUI(), defaultEditorTheme);
const pastedText = [
"line 1",
"line 2",
"line 3",
"line 4",
"line 5",
"line 6",
"line 7",
"line 8",
"line 9",
"line 10",
"tokens $1 $2 $& $$ $` $' end",
].join("\n");
let submitted = "";
editor.onSubmit = (text) => {
submitted = text;
};
editor.handleInput(`\x1b[200~${pastedText}\x1b[201~`);
editor.handleInput("\r");
assert.strictEqual(submitted, pastedText);
});
});
});