diff --git a/src/kill-yank/index.ts b/src/kill-yank/index.ts index 04e68b3af2..27d59e560e 100644 --- a/src/kill-yank/index.ts +++ b/src/kill-yank/index.ts @@ -173,9 +173,9 @@ export class KillYanker implements vscode.Disposable { let textToAddAfterBuffer = ""; regionTexts.forEach((regionText) => { const indent = pasteCursor.character; - const regionHeight = regionText.range.end.line - regionText.range.start.line; - const regionWidth = regionText.range.end.character - regionText.range.start.character; if (regionText.rectMode) { + const regionHeight = regionText.range.end.line - regionText.range.start.line; + const regionWidth = regionText.range.end.character - regionText.range.start.character; regionText.text.split(/\r?\n/).forEach((lineToPaste, j) => { const pastedLineLength = lineToPaste.length; const targetLine = pasteCursor.line + j; @@ -192,14 +192,22 @@ export class KillYanker implements vscode.Disposable { textToAddAfterBuffer += getEolChar(this.textEditor.document.eol) + whiteSpacesFilledLine; } }); + pasteCursor = new Position(pasteCursor.line + regionHeight, pasteCursor.character + regionWidth); } else { if (pasteCursor.line < this.textEditor.document.lineCount) { editBuilder.insert(pasteCursor, regionText.text); } else { textToAddAfterBuffer += regionText.text; } + const regionHeight = regionText.range.end.line - regionText.range.start.line; + if (regionHeight === 0) { + const regionLastLineLength = regionText.range.end.character - regionText.range.start.character; + pasteCursor = new Position(pasteCursor.line, pasteCursor.character + regionLastLineLength); + } else { + const regionLastLineLength = regionText.range.end.character; + pasteCursor = new Position(pasteCursor.line + regionHeight, regionLastLineLength); + } } - pasteCursor = new Position(pasteCursor.line + regionHeight, pasteCursor.character + regionWidth); }); const endOfDoc = this.textEditor.document.lineAt(this.textEditor.document.lineCount - 1).range.end; editBuilder.insert(endOfDoc, textToAddAfterBuffer); diff --git a/src/test/suite/rectangle-mark-mode.test.ts b/src/test/suite/rectangle-mark-mode.test.ts index b0e3a09336..8d937d603b 100644 --- a/src/test/suite/rectangle-mark-mode.test.ts +++ b/src/test/suite/rectangle-mark-mode.test.ts @@ -190,6 +190,66 @@ KLcdMNOPQRST ); }); + test("killing in rectangle-mark-mode followed by multiple kill command that append killed texts including multiple lines", async () => { + setEmptyCursors(activeTextEditor, [0, 8]); + const killRing = new KillRing(3); + const emulator = new EmacsEmulator(activeTextEditor, killRing); + + emulator.rectangleMarkMode(); + + await emulator.runCommand("forwardChar"); + await emulator.runCommand("forwardChar"); + await emulator.runCommand("nextLine"); + await emulator.runCommand("nextLine"); + + assert.deepStrictEqual(activeTextEditor.selections, [ + new vscode.Selection(0, 8, 0, 10), + new vscode.Selection(1, 8, 1, 10), + new vscode.Selection(2, 8, 2, 10), + ]); + + await emulator.runCommand("killRegion"); + + assertTextEqual( + activeTextEditor, + `01234567 +abcdefgh +ABCDEFGH +klmnopqrst +KLMNOPQRST`, + ); + + assert.deepStrictEqual(activeTextEditor.selections, [new vscode.Selection(2, 8, 2, 8)]); + + await delay(); // Wait for all related event listeners to have been called + + await emulator.runCommand("killLine"); + await emulator.runCommand("killLine"); + await emulator.runCommand("killLine"); + + assertTextEqual( + activeTextEditor, + `01234567 +abcdefgh +ABCDEFGHKLMNOPQRST`, + ); + + // Yanking the killed text in the rect-mark-mode. + // The text is yanked as a rectangle and automatically indented. + setEmptyCursors(activeTextEditor, [2, 1]); + await emulator.runCommand("yank"); + assertTextEqual( + activeTextEditor, + `01234567 +abcdefgh +A89BCDEFGHKLMNOPQRST + ij + IJ +klmnopqrst +`, + ); + }); + test("Killing a region including empty lines", async () => { await clearTextEditor( activeTextEditor,