From 411a29c89cdf7f7aaa13b252a040adf61982a955 Mon Sep 17 00:00:00 2001 From: Alexander Mai <alexandertmai@gmail.com> Date: Mon, 24 Jan 2022 14:43:41 -0800 Subject: [PATCH 1/9] Fix insertLineBefore indent behavior --- src/actions/commands/actions.ts | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/actions/commands/actions.ts b/src/actions/commands/actions.ts index a9840407b87..a264bbedbb2 100644 --- a/src/actions/commands/actions.ts +++ b/src/actions/commands/actions.ts @@ -1523,17 +1523,32 @@ export class CommandInsertNewLineAbove extends BaseCommand { await vimState.setCurrentMode(Mode.Insert); const count = vimState.recordedState.count || 1; + const charPos = position.getLineBeginRespectingIndent(vimState.document).character; + for (let i = 0; i < count; i++) { await vscode.commands.executeCommand('editor.action.insertLineBefore'); + const newPos = new Position( + vimState.cursorStartPosition.line - i, + vimState.cursorStartPosition.character + ); } vimState.cursors = getCursorsAfterSync(vimState.editor); + for (let i = 0; i < count; i++) { - const newPos = new Position( - vimState.cursors[0].start.line + i, - vimState.cursors[0].start.character - ); - vimState.cursors.push(new Cursor(newPos, newPos)); + const newPos = new Position(vimState.cursors[0].start.line + i, charPos); + if (i === 0) { + vimState.cursors[0] = new Cursor(newPos, newPos); + } else { + vimState.cursors.push(new Cursor(newPos, newPos)); + } + vimState.recordedState.transformer.addTransformation({ + type: 'insertText', + text: TextEditor.setIndentationLevel('', newPos.character), + position: newPos, + cursorIndex: i, + manuallySetCursorPositions: true, + }); } vimState.cursors = vimState.cursors.reverse(); vimState.isFakeMultiCursor = true; From 69a80dad9a8681b6190c3f057e5ffaeacdef8a37 Mon Sep 17 00:00:00 2001 From: Alexander Mai <alexandertmai@gmail.com> Date: Mon, 24 Jan 2022 15:02:01 -0800 Subject: [PATCH 2/9] Ooops, fixed problem with extra characters --- src/actions/commands/actions.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/actions/commands/actions.ts b/src/actions/commands/actions.ts index a264bbedbb2..3fd4fea3ac9 100644 --- a/src/actions/commands/actions.ts +++ b/src/actions/commands/actions.ts @@ -1535,13 +1535,19 @@ export class CommandInsertNewLineAbove extends BaseCommand { vimState.cursors = getCursorsAfterSync(vimState.editor); - for (let i = 0; i < count; i++) { + const firstPos = new Position(vimState.cursors[0].start.line, charPos); + vimState.cursors[0] = new Cursor(firstPos, firstPos); + vimState.recordedState.transformer.addTransformation({ + type: 'insertText', + text: TextEditor.setIndentationLevel('', firstPos.character), + position: firstPos, + cursorIndex: 0, + manuallySetCursorPositions: true, + }); + + for (let i = 1; i < count; i++) { const newPos = new Position(vimState.cursors[0].start.line + i, charPos); - if (i === 0) { - vimState.cursors[0] = new Cursor(newPos, newPos); - } else { - vimState.cursors.push(new Cursor(newPos, newPos)); - } + vimState.cursors.push(new Cursor(newPos, newPos)); vimState.recordedState.transformer.addTransformation({ type: 'insertText', text: TextEditor.setIndentationLevel('', newPos.character), From a1b8d1e915bf09325d2110486e289040080dc633 Mon Sep 17 00:00:00 2001 From: Alexander Mai <alexandertmai@gmail.com> Date: Mon, 24 Jan 2022 15:29:05 -0800 Subject: [PATCH 3/9] Fix for when insertLineBefore indented already --- .vscode/tasks.json | 2 +- src/actions/commands/actions.ts | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index d18fb11e200..c38a194606a 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -15,7 +15,7 @@ }, { "type": "gulp", - "task": "build", + "task": "build-dev", "problemMatcher": [] } ] diff --git a/src/actions/commands/actions.ts b/src/actions/commands/actions.ts index 3fd4fea3ac9..e139acb6bf1 100644 --- a/src/actions/commands/actions.ts +++ b/src/actions/commands/actions.ts @@ -1534,12 +1534,13 @@ export class CommandInsertNewLineAbove extends BaseCommand { } vimState.cursors = getCursorsAfterSync(vimState.editor); + const indentAmt = charPos - vimState.cursors[0].start.character; const firstPos = new Position(vimState.cursors[0].start.line, charPos); vimState.cursors[0] = new Cursor(firstPos, firstPos); vimState.recordedState.transformer.addTransformation({ type: 'insertText', - text: TextEditor.setIndentationLevel('', firstPos.character), + text: TextEditor.setIndentationLevel('', indentAmt), position: firstPos, cursorIndex: 0, manuallySetCursorPositions: true, @@ -1550,7 +1551,7 @@ export class CommandInsertNewLineAbove extends BaseCommand { vimState.cursors.push(new Cursor(newPos, newPos)); vimState.recordedState.transformer.addTransformation({ type: 'insertText', - text: TextEditor.setIndentationLevel('', newPos.character), + text: TextEditor.setIndentationLevel('', indentAmt), position: newPos, cursorIndex: i, manuallySetCursorPositions: true, From b90bcc45a1d3c62cb126e4f613e7618df0edbca3 Mon Sep 17 00:00:00 2001 From: Alexander Mai <alexandertmai@gmail.com> Date: Thu, 27 Jan 2022 19:43:39 -0800 Subject: [PATCH 4/9] Added tests and fixed bug --- src/actions/commands/actions.ts | 6 +-- test/actions/insertLine.test.ts | 95 +++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 5 deletions(-) create mode 100644 test/actions/insertLine.test.ts diff --git a/src/actions/commands/actions.ts b/src/actions/commands/actions.ts index e139acb6bf1..97c515cb293 100644 --- a/src/actions/commands/actions.ts +++ b/src/actions/commands/actions.ts @@ -1527,14 +1527,10 @@ export class CommandInsertNewLineAbove extends BaseCommand { for (let i = 0; i < count; i++) { await vscode.commands.executeCommand('editor.action.insertLineBefore'); - const newPos = new Position( - vimState.cursorStartPosition.line - i, - vimState.cursorStartPosition.character - ); } vimState.cursors = getCursorsAfterSync(vimState.editor); - const indentAmt = charPos - vimState.cursors[0].start.character; + const indentAmt = Math.max(charPos - vimState.cursors[0].start.character, 0); const firstPos = new Position(vimState.cursors[0].start.line, charPos); vimState.cursors[0] = new Cursor(firstPos, firstPos); diff --git a/test/actions/insertLine.test.ts b/test/actions/insertLine.test.ts new file mode 100644 index 00000000000..39f369f77da --- /dev/null +++ b/test/actions/insertLine.test.ts @@ -0,0 +1,95 @@ +import * as assert from 'assert'; +import { Position, window } from 'vscode'; +import { getCurrentParagraphBeginning, getCurrentParagraphEnd } from '../../src/textobject/paragraph'; +import { WordType } from '../../src/textobject/word'; +import { TextEditor } from '../../src/textEditor'; +import { assertEqualLines, cleanUpWorkspace, setupWorkspace } from '../testUtils'; +import { ModeHandler } from '../../src/mode/modeHandler'; +import { getAndUpdateModeHandler } from '../../extension'; +import * as vscode from 'vscode'; +import { Configuration } from '../testConfiguration'; + +suite('insertLineBefore', () => { + let modeHandler: ModeHandler; + + suiteSetup(async () => { + const configuration = new Configuration(); + configuration.tabstop = 4; + configuration.expandtab = true; + + await setupWorkspace(configuration); + await setupWorkspace(); + modeHandler = (await getAndUpdateModeHandler())!; + }); + + suiteTeardown(cleanUpWorkspace); + + test('tabs are added to match previous line even if line above does not match', async () => { + // Setup the test + await modeHandler.handleMultipleKeyEvents(['<Esc>', 'g', 'g', 'd', 'G']); + await modeHandler.handleMultipleKeyEvents('i\na'.split('')); + await modeHandler.handleMultipleKeyEvents(['<Esc>']); + await modeHandler.handleMultipleKeyEvents('2G>>ob\nc'.split('')); + + // This is the current state of the document + // + // a + // b + // c + await modeHandler.handleMultipleKeyEvents(['<Esc>', '2', 'G', 'O', 'a']); + let text = vscode.window.activeTextEditor?.document.getText().split('\n'); + assert.ok(text); + assert.strictEqual(text[1], text[2]); + }); + + test('no extra whitespace added when insertLineBefore inserts correct amount', async () => { + await modeHandler.handleMultipleKeyEvents(['<Esc>', 'g', 'g', 'd', 'G']); + await modeHandler.handleMultipleKeyEvents('i\na'.split('')); + await modeHandler.handleMultipleKeyEvents(['<Esc>']); + await modeHandler.handleMultipleKeyEvents('2G>>ob\nc'.split('')); + + // This is the current state of the document + // + // a + // b + // c + await modeHandler.handleMultipleKeyEvents(['<Esc>', '3', 'G', 'O', 'b']); + let text = vscode.window.activeTextEditor?.document.getText().split('\n'); + assert.ok(text); + assert.strictEqual(text[2], text[3]); + }); + + test('works at the top of the document', async () => { + await modeHandler.handleMultipleKeyEvents(['<Esc>', 'g', 'g', 'd', 'G']); + await modeHandler.handleMultipleKeyEvents('ia'.split('')); + await modeHandler.handleMultipleKeyEvents(['<Esc>']); + await modeHandler.handleMultipleKeyEvents('gg>>'.split('')); + + // This is the current state of the document + // a + await modeHandler.handleMultipleKeyEvents(['<Esc>', 'g', 'g', 'O', 'a']); + let text = vscode.window.activeTextEditor?.document.getText().split('\n'); + assert.ok(text); + assert.strictEqual(text[0], text[1]); + }); + + test('works with multiple cursors', async () => { + await modeHandler.handleMultipleKeyEvents(['<Esc>', 'g', 'g', 'd', 'G']); + await modeHandler.handleMultipleKeyEvents('oa'.split('')); + await modeHandler.handleMultipleKeyEvents(['<Esc>']); + await modeHandler.handleMultipleKeyEvents('2G>>'.split('')); + // This is the current state of the document + // + // a + await modeHandler.handleMultipleKeyEvents(['<Esc>', '2', 'G', '2', 'O', 'a']); + // After + // + // a + // a + // a + let text = vscode.window.activeTextEditor?.document.getText().split('\n'); + assert.ok(text); + assert.strictEqual(text[1], text[2]); + assert.strictEqual(text[2], text[3]); + }); +}); From c5c35db9c4d6b4cd134dc8b500c4ec339f4aa8ed Mon Sep 17 00:00:00 2001 From: Alexander Mai <alexandertmai@gmail.com> Date: Tue, 1 Feb 2022 09:36:56 -0800 Subject: [PATCH 5/9] Fixed let -> const --- test/actions/insertLine.test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/actions/insertLine.test.ts b/test/actions/insertLine.test.ts index 39f369f77da..defccbd15de 100644 --- a/test/actions/insertLine.test.ts +++ b/test/actions/insertLine.test.ts @@ -37,7 +37,7 @@ suite('insertLineBefore', () => { // b // c await modeHandler.handleMultipleKeyEvents(['<Esc>', '2', 'G', 'O', 'a']); - let text = vscode.window.activeTextEditor?.document.getText().split('\n'); + const text = vscode.window.activeTextEditor?.document.getText().split('\n'); assert.ok(text); assert.strictEqual(text[1], text[2]); }); @@ -54,7 +54,7 @@ suite('insertLineBefore', () => { // b // c await modeHandler.handleMultipleKeyEvents(['<Esc>', '3', 'G', 'O', 'b']); - let text = vscode.window.activeTextEditor?.document.getText().split('\n'); + const text = vscode.window.activeTextEditor?.document.getText().split('\n'); assert.ok(text); assert.strictEqual(text[2], text[3]); }); @@ -68,7 +68,7 @@ suite('insertLineBefore', () => { // This is the current state of the document // a await modeHandler.handleMultipleKeyEvents(['<Esc>', 'g', 'g', 'O', 'a']); - let text = vscode.window.activeTextEditor?.document.getText().split('\n'); + const text = vscode.window.activeTextEditor?.document.getText().split('\n'); assert.ok(text); assert.strictEqual(text[0], text[1]); }); @@ -87,7 +87,7 @@ suite('insertLineBefore', () => { // a // a // a - let text = vscode.window.activeTextEditor?.document.getText().split('\n'); + const text = vscode.window.activeTextEditor?.document.getText().split('\n'); assert.ok(text); assert.strictEqual(text[1], text[2]); assert.strictEqual(text[2], text[3]); From f49ec3c12bb92f776f4f60ea9c3c23ddde15fb05 Mon Sep 17 00:00:00 2001 From: Alexander Mai <alexandertmai@gmail.com> Date: Tue, 1 Feb 2022 09:59:55 -0800 Subject: [PATCH 6/9] Trim carrage returns in test --- test/actions/insertLine.test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/actions/insertLine.test.ts b/test/actions/insertLine.test.ts index defccbd15de..e2ec8f02bd1 100644 --- a/test/actions/insertLine.test.ts +++ b/test/actions/insertLine.test.ts @@ -37,7 +37,7 @@ suite('insertLineBefore', () => { // b // c await modeHandler.handleMultipleKeyEvents(['<Esc>', '2', 'G', 'O', 'a']); - const text = vscode.window.activeTextEditor?.document.getText().split('\n'); + const text = vscode.window.activeTextEditor?.document.getText().replace('\r', '').split('\n'); assert.ok(text); assert.strictEqual(text[1], text[2]); }); @@ -54,7 +54,7 @@ suite('insertLineBefore', () => { // b // c await modeHandler.handleMultipleKeyEvents(['<Esc>', '3', 'G', 'O', 'b']); - const text = vscode.window.activeTextEditor?.document.getText().split('\n'); + const text = vscode.window.activeTextEditor?.document.getText().replace('\r', '').split('\n'); assert.ok(text); assert.strictEqual(text[2], text[3]); }); @@ -68,7 +68,7 @@ suite('insertLineBefore', () => { // This is the current state of the document // a await modeHandler.handleMultipleKeyEvents(['<Esc>', 'g', 'g', 'O', 'a']); - const text = vscode.window.activeTextEditor?.document.getText().split('\n'); + const text = vscode.window.activeTextEditor?.document.getText().replace('\r', '').split('\n'); assert.ok(text); assert.strictEqual(text[0], text[1]); }); @@ -87,7 +87,7 @@ suite('insertLineBefore', () => { // a // a // a - const text = vscode.window.activeTextEditor?.document.getText().split('\n'); + const text = vscode.window.activeTextEditor?.document.getText().replace('\r', '').split('\n'); assert.ok(text); assert.strictEqual(text[1], text[2]); assert.strictEqual(text[2], text[3]); From ef037fc684190cbdf0a88781bae5e011ce04f30f Mon Sep 17 00:00:00 2001 From: Alexander Mai <alexandertmai@gmail.com> Date: Tue, 1 Feb 2022 13:20:05 -0800 Subject: [PATCH 7/9] Attempting to fix carriage return --- test/actions/insertLine.test.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/actions/insertLine.test.ts b/test/actions/insertLine.test.ts index e2ec8f02bd1..596599a55ed 100644 --- a/test/actions/insertLine.test.ts +++ b/test/actions/insertLine.test.ts @@ -37,9 +37,9 @@ suite('insertLineBefore', () => { // b // c await modeHandler.handleMultipleKeyEvents(['<Esc>', '2', 'G', 'O', 'a']); - const text = vscode.window.activeTextEditor?.document.getText().replace('\r', '').split('\n'); + const text = vscode.window.activeTextEditor?.document.getText().split('\n'); assert.ok(text); - assert.strictEqual(text[1], text[2]); + assert.strictEqual(text[1].replace(/[\n\r]/g, ''), text[2].replace(/[\n\r]/g, '')); }); test('no extra whitespace added when insertLineBefore inserts correct amount', async () => { @@ -54,9 +54,9 @@ suite('insertLineBefore', () => { // b // c await modeHandler.handleMultipleKeyEvents(['<Esc>', '3', 'G', 'O', 'b']); - const text = vscode.window.activeTextEditor?.document.getText().replace('\r', '').split('\n'); + const text = vscode.window.activeTextEditor?.document.getText().split('\n'); assert.ok(text); - assert.strictEqual(text[2], text[3]); + assert.strictEqual(text[2].replace(/[\n\r]/g, ''), text[3].replace(/[\n\r]/g, '')); }); test('works at the top of the document', async () => { @@ -68,9 +68,9 @@ suite('insertLineBefore', () => { // This is the current state of the document // a await modeHandler.handleMultipleKeyEvents(['<Esc>', 'g', 'g', 'O', 'a']); - const text = vscode.window.activeTextEditor?.document.getText().replace('\r', '').split('\n'); + const text = vscode.window.activeTextEditor?.document.getText().split('\n'); assert.ok(text); - assert.strictEqual(text[0], text[1]); + assert.strictEqual(text[0].replace(/[\n\r]/g, ''), text[1].replace(/[\n\r]/g, '')); }); test('works with multiple cursors', async () => { @@ -87,9 +87,9 @@ suite('insertLineBefore', () => { // a // a // a - const text = vscode.window.activeTextEditor?.document.getText().replace('\r', '').split('\n'); + const text = vscode.window.activeTextEditor?.document.getText().split('\n'); assert.ok(text); - assert.strictEqual(text[1], text[2]); - assert.strictEqual(text[2], text[3]); + assert.strictEqual(text[1].replace(/[\n\r]/g, ''), text[2].replace(/[\n\r]/g, '')); + assert.strictEqual(text[2].replace(/[\n\r]/g, ''), text[3].replace(/[\n\r]/g, '')); }); }); From 6331933cdb69aee01f9fab4d4ef1ecfd0d2f13fc Mon Sep 17 00:00:00 2001 From: Alexander Mai <alexandertmai@gmail.com> Date: Wed, 2 Feb 2022 21:26:06 -0800 Subject: [PATCH 8/9] Fixed extra whitespace added --- src/actions/commands/actions.ts | 46 +++++++++++++++++++-------------- test/actions/insertLine.test.ts | 31 +++++++++++++++++++++- 2 files changed, 56 insertions(+), 21 deletions(-) diff --git a/src/actions/commands/actions.ts b/src/actions/commands/actions.ts index 2c568715d0f..88147f81fc0 100644 --- a/src/actions/commands/actions.ts +++ b/src/actions/commands/actions.ts @@ -1536,28 +1536,34 @@ export class CommandInsertNewLineAbove extends BaseCommand { } vimState.cursors = getCursorsAfterSync(vimState.editor); - const indentAmt = Math.max(charPos - vimState.cursors[0].start.character, 0); + const endPos = vimState.cursors[0].start.character; + const indentAmt = charPos - endPos; + console.log(charPos); + console.log(indentAmt); - const firstPos = new Position(vimState.cursors[0].start.line, charPos); - vimState.cursors[0] = new Cursor(firstPos, firstPos); - vimState.recordedState.transformer.addTransformation({ - type: 'insertText', - text: TextEditor.setIndentationLevel('', indentAmt), - position: firstPos, - cursorIndex: 0, - manuallySetCursorPositions: true, - }); - - for (let i = 1; i < count; i++) { + for (let i = 0; i < count; i++) { const newPos = new Position(vimState.cursors[0].start.line + i, charPos); - vimState.cursors.push(new Cursor(newPos, newPos)); - vimState.recordedState.transformer.addTransformation({ - type: 'insertText', - text: TextEditor.setIndentationLevel('', indentAmt), - position: newPos, - cursorIndex: i, - manuallySetCursorPositions: true, - }); + if (i === 0) { + vimState.cursors[0] = new Cursor(newPos, newPos); + } else { + vimState.cursors.push(new Cursor(newPos, newPos)); + } + if (indentAmt >= 0) { + vimState.recordedState.transformer.addTransformation({ + type: 'insertText', + text: TextEditor.setIndentationLevel('', indentAmt), + position: newPos, + cursorIndex: i, + manuallySetCursorPositions: true, + }); + } else { + vimState.recordedState.transformer.addTransformation({ + type: 'deleteRange', + cursorIndex: i, + range: new vscode.Range(newPos, new Position(newPos.line, endPos)), + manuallySetCursorPositions: true, + }); + } } vimState.cursors = vimState.cursors.reverse(); vimState.isFakeMultiCursor = true; diff --git a/test/actions/insertLine.test.ts b/test/actions/insertLine.test.ts index 596599a55ed..1af27eaacb8 100644 --- a/test/actions/insertLine.test.ts +++ b/test/actions/insertLine.test.ts @@ -1,6 +1,9 @@ import * as assert from 'assert'; import { Position, window } from 'vscode'; -import { getCurrentParagraphBeginning, getCurrentParagraphEnd } from '../../src/textobject/paragraph'; +import { + getCurrentParagraphBeginning, + getCurrentParagraphEnd, +} from '../../src/textobject/paragraph'; import { WordType } from '../../src/textobject/word'; import { TextEditor } from '../../src/textEditor'; import { assertEqualLines, cleanUpWorkspace, setupWorkspace } from '../testUtils'; @@ -59,6 +62,32 @@ suite('insertLineBefore', () => { assert.strictEqual(text[2].replace(/[\n\r]/g, ''), text[3].replace(/[\n\r]/g, '')); }); + test('no extra whitespace left when insertLineBefore inserts more than correct amount', async () => { + await modeHandler.handleMultipleKeyEvents(['<Esc>', 'g', 'g', 'd', 'G']); + await modeHandler.handleMultipleKeyEvents('i\na'.split('')); + await modeHandler.handleMultipleKeyEvents(['<Esc>']); + await modeHandler.handleMultipleKeyEvents('2G>>ob\nc'.split('')); + await modeHandler.handleMultipleKeyEvents(['<Esc>']); + await modeHandler.handleMultipleKeyEvents('3G>>'.split('')); + + // This is the current state of the document + // + // a + // b + // c + await modeHandler.handleMultipleKeyEvents(['<Esc>', '4', 'G', '2', 'O', 'c']); + const text = vscode.window.activeTextEditor?.document.getText().split('\n'); + // + // a + // b + // c + // c + // c + assert.ok(text); + assert.strictEqual(text[3].replace(/[\n\r]/g, ''), text[4].replace(/[\n\r]/g, '')); + assert.strictEqual(text[4].replace(/[\n\r]/g, ''), text[5].replace(/[\n\r]/g, '')); + }); + test('works at the top of the document', async () => { await modeHandler.handleMultipleKeyEvents(['<Esc>', 'g', 'g', 'd', 'G']); await modeHandler.handleMultipleKeyEvents('ia'.split('')); From eab3ce2c98a6df2b498e2628d869ca877e6987ed Mon Sep 17 00:00:00 2001 From: Jason Fields <jasonfields4@gmail.com> Date: Sun, 6 Feb 2022 14:51:26 -0500 Subject: [PATCH 9/9] Remove `console.log` statements --- src/actions/commands/actions.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/actions/commands/actions.ts b/src/actions/commands/actions.ts index 88147f81fc0..60f2ffe3066 100644 --- a/src/actions/commands/actions.ts +++ b/src/actions/commands/actions.ts @@ -1538,8 +1538,6 @@ export class CommandInsertNewLineAbove extends BaseCommand { vimState.cursors = getCursorsAfterSync(vimState.editor); const endPos = vimState.cursors[0].start.character; const indentAmt = charPos - endPos; - console.log(charPos); - console.log(indentAmt); for (let i = 0; i < count; i++) { const newPos = new Position(vimState.cursors[0].start.line + i, charPos);