diff --git a/packages/tui/src/components/editor.ts b/packages/tui/src/components/editor.ts index bedd01057..3b55dc552 100644 --- a/packages/tui/src/components/editor.ts +++ b/packages/tui/src/components/editor.ts @@ -999,6 +999,8 @@ export class Editor implements Component, Focusable { this.cancelAutocomplete(); this.lastAction = null; this.exitHistoryBrowsing(); + this.pastes.clear(); + this.pasteCounter = 0; const normalized = this.normalizeText(text); // Push undo snapshot if content differs (makes programmatic changes undoable) if (this.getText() !== normalized) { @@ -1267,13 +1269,37 @@ export class Editor implements Component, Focusable { this.pushUndoSnapshot(); // Delete grapheme before cursor (handles emojis, combining characters, etc.) - const line = this.state.lines[this.state.cursorLine] || ""; + let line = this.state.lines[this.state.cursorLine] || ""; const beforeCursor = line.slice(0, this.state.cursorCol); // Find the last grapheme in the text before cursor const graphemes = [...this.segment(beforeCursor, "grapheme")]; const lastGrapheme = graphemes[graphemes.length - 1]; const graphemeLength = lastGrapheme ? lastGrapheme.segment.length : 1; + const isPastedSegmented = PASTE_MARKER_SINGLE.exec(lastGrapheme.segment); + + if (isPastedSegmented) { + // This contains the id part e.g 4 from [paste #4 +123 lines] + const targetId = Number(isPastedSegmented[1]); + this.pastes.delete(targetId); + this.pasteCounter--; + + // We got to update id of markers which are greater than the removed one + this.state.lines = this.state.lines.map((line) => + line.replace(PASTE_MARKER_REGEX, (fullMatch, idGroup, suffixGroup) => { + const x = Number(idGroup); + if (x <= targetId) return fullMatch; + + // [paste #3] become [paste #2] if we remove [paste #1] + const newText = `[paste #${x - 1}${suffixGroup}]`; + this.pastes.set(x - 1, this.pastes.get(x) ?? newText); + this.pastes.delete(x); + return newText; + }), + ); + } + + line = this.state.lines[this.state.cursorLine] || ""; const before = line.slice(0, this.state.cursorCol - graphemeLength); const after = line.slice(this.state.cursorCol);