From fe707b41f0a8ff33d9cad215cadc21f4cc3cae0c Mon Sep 17 00:00:00 2001 From: Jason Poon Date: Fri, 1 Feb 2019 20:38:05 -0800 Subject: [PATCH] fix: ensure cursor is in bounds. closes #3441 --- src/common/motion/range.ts | 4 ++++ src/mode/modeHandler.ts | 38 ++++++++++++++++++++++++-------------- src/state/vimState.ts | 11 +++++------ 3 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/common/motion/range.ts b/src/common/motion/range.ts index adf239d4fa2..a5f60ff3244 100644 --- a/src/common/motion/range.ts +++ b/src/common/motion/range.ts @@ -20,6 +20,10 @@ export class Range { this._stop = stop; } + public isValid(textEditor: vscode.TextEditor) { + return this._start.isValid(textEditor) && this._stop.isValid(textEditor); + } + /** * Create a range from a VSCode selection. */ diff --git a/src/mode/modeHandler.ts b/src/mode/modeHandler.ts index c67520362bf..3a536fae41d 100644 --- a/src/mode/modeHandler.ts +++ b/src/mode/modeHandler.ts @@ -606,25 +606,35 @@ export class ModeHandler implements vscode.Disposable { // Ensure cursor is within bounds if (!vimState.editor.document.isClosed && vimState.editor === vscode.window.activeTextEditor) { - for (const { stop, i } of Range.IterateRanges(vimState.allCursors)) { - if (stop.line >= TextEditor.getLineCount()) { - vimState.allCursors[i] = vimState.allCursors[i].withNewStop( - vimState.cursorPosition.getDocumentEnd(vimState.editor) - ); + const cursors = new Array(); + for (let { range } of Range.IterateRanges(vimState.allCursors)) { + // adjust start/stop + const documentEndPosition = vimState.cursorPosition.getDocumentEnd(vimState.editor); + const documentLineCount = TextEditor.getLineCount(vimState.editor); + if (range.start.line >= documentLineCount) { + range = range.withNewStart(documentEndPosition); + } + if (range.stop.line >= documentLineCount) { + range = range.withNewStop(documentEndPosition); } - const currentLineLength = TextEditor.getLineAt(stop).text.length; + // adjust column + if (vimState.currentMode === ModeName.Normal) { + const currentLineLength = TextEditor.getLineAt(range.stop).text.length; + if (currentLineLength > 0) { + const lineEndPosition = range.start.getLineEnd().getLeftThroughLineBreaks(true); + if (range.start.character >= currentLineLength) { + range = range.withNewStart(lineEndPosition); + } - if ( - vimState.currentMode === ModeName.Normal && - stop.character >= currentLineLength && - currentLineLength > 0 - ) { - vimState.allCursors[i] = vimState.allCursors[i].withNewStop( - stop.getLineEnd().getLeftThroughLineBreaks(true) - ); + if (range.stop.character >= currentLineLength) { + range = range.withNewStop(lineEndPosition); + } + } } + cursors.push(range); } + vimState.allCursors = cursors; } // Update the current history step to have the latest cursor position diff --git a/src/state/vimState.ts b/src/state/vimState.ts index 09468361728..0cc3a8246fc 100644 --- a/src/state/vimState.ts +++ b/src/state/vimState.ts @@ -150,15 +150,14 @@ export class VimState implements vscode.Disposable { return this._allCursors; } - public set allCursors(value: Range[]) { - for (const cursor of value) { - if (!cursor.start.isValid(this.editor) || !cursor.stop.isValid(this.editor)) { - this.logger.debug('invalid value for set cursor position.'); + public set allCursors(cursors: Range[]) { + for (const cursor of cursors) { + if (!cursor.isValid(this.editor)) { + this.logger.warn(`invalid cursor position. ${cursor.toString()}.`); } } - this._allCursors = value; - + this._allCursors = cursors; this.isMultiCursor = this._allCursors.length > 1; }