From e8b7a0eeb47eb12ecd44b1ed24a8a4c5fbfcc459 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 27 Apr 2020 13:29:41 +0200 Subject: [PATCH] Fixes #95591 --- src/vs/editor/common/commands/shiftCommand.ts | 17 +++++++++----- .../test/linesOperations.test.ts | 19 ++++++++++++++++ .../test/browser/controller/cursor.test.ts | 22 +++++++++++++++++++ 3 files changed, 52 insertions(+), 6 deletions(-) diff --git a/src/vs/editor/common/commands/shiftCommand.ts b/src/vs/editor/common/commands/shiftCommand.ts index 742ad42fa9c88..52473fd2793a6 100644 --- a/src/vs/editor/common/commands/shiftCommand.ts +++ b/src/vs/editor/common/commands/shiftCommand.ts @@ -103,14 +103,14 @@ export class ShiftCommand implements ICommand { const { tabSize, indentSize, insertSpaces } = this._opts; const shouldIndentEmptyLines = (startLine === endLine); - // if indenting or outdenting on a whitespace only line - if (this._selection.isEmpty()) { - if (/^\s*$/.test(model.getLineContent(startLine))) { - this._useLastEditRangeForCursorEndPosition = true; + if (this._opts.useTabStops) { + // if indenting or outdenting on a whitespace only line + if (this._selection.isEmpty()) { + if (/^\s*$/.test(model.getLineContent(startLine))) { + this._useLastEditRangeForCursorEndPosition = true; + } } - } - if (this._opts.useTabStops) { // keep track of previous line's "miss-alignment" let previousLineExtraSpaces = 0, extraSpaces = 0; for (let lineNumber = startLine; lineNumber <= endLine; lineNumber++, previousLineExtraSpaces = extraSpaces) { @@ -188,6 +188,11 @@ export class ShiftCommand implements ICommand { } } else { + // if indenting or outdenting on a whitespace only line + if (!this._opts.isUnshift && this._selection.isEmpty() && model.getLineLength(startLine) === 0) { + this._useLastEditRangeForCursorEndPosition = true; + } + const oneIndent = (insertSpaces ? cachedStringRepeat(' ', indentSize) : '\t'); for (let lineNumber = startLine; lineNumber <= endLine; lineNumber++) { diff --git a/src/vs/editor/contrib/linesOperations/test/linesOperations.test.ts b/src/vs/editor/contrib/linesOperations/test/linesOperations.test.ts index 6090bd19e7ebe..d0dc6b5728558 100644 --- a/src/vs/editor/contrib/linesOperations/test/linesOperations.test.ts +++ b/src/vs/editor/contrib/linesOperations/test/linesOperations.test.ts @@ -960,6 +960,25 @@ suite('Editor Contrib - Line Operations', () => { model.dispose(); }); + test('Indenting on empty line should move cursor', () => { + const model = createTextModel( + [ + '' + ].join('\n') + ); + + withTestCodeEditor(null, { model: model, useTabStops: false }, (editor) => { + const indentLinesAction = new IndentLinesAction(); + editor.setPosition(new Position(1, 1)); + + executeAction(indentLinesAction, editor); + assert.equal(model.getLineContent(1), ' '); + assert.deepEqual(editor.getSelection(), new Selection(1, 5, 1, 5)); + }); + + model.dispose(); + }); + test('issue #62112: Delete line does not work properly when multiple cursors are on line', () => { const TEXT = [ 'a', diff --git a/src/vs/editor/test/browser/controller/cursor.test.ts b/src/vs/editor/test/browser/controller/cursor.test.ts index 72fcf78f900cc..b37d17d3ce69a 100644 --- a/src/vs/editor/test/browser/controller/cursor.test.ts +++ b/src/vs/editor/test/browser/controller/cursor.test.ts @@ -1428,6 +1428,28 @@ suite('Editor Controller - Regression tests', () => { model.dispose(); }); + test('issue #95591: Unindenting moves cursor to beginning of line', () => { + let model = createTextModel( + [ + ' ' + ].join('\n') + ); + + withTestCodeEditor(null, { + model: model, + useTabStops: false + }, (editor, cursor) => { + moveTo(cursor, 1, 9, false); + assertCursor(cursor, new Selection(1, 9, 1, 9)); + + CoreEditingCommands.Outdent.runEditorCommand(null, editor, null); + assert.equal(model.getLineContent(1), ' '); + assertCursor(cursor, new Selection(1, 5, 1, 5)); + }); + + model.dispose(); + }); + test('Bug #16657: [editor] Tab on empty line of zero indentation moves cursor to position (1,1)', () => { let model = createTextModel( [