diff --git a/src/actions/commands/actions.ts b/src/actions/commands/actions.ts index 47c52bdb48c..e46c1ff746a 100644 --- a/src/actions/commands/actions.ts +++ b/src/actions/commands/actions.ts @@ -1089,6 +1089,10 @@ export class PutCommand extends BaseCommand { runsOnceForEachCountPrefix = true; canBeRepeatedWithDot = true; + constructor(multicursorIndex?: number) { + super(); + this.multicursorIndex = multicursorIndex; + } public static async GetText(vimState: VimState, multicursorIndex: number | undefined = undefined): Promise { const register = await Register.get(vimState); @@ -1350,11 +1354,12 @@ export class PutCommandVisual extends BaseCommand { // The reason we need to handle Delete and Yank separately is because of // linewise mode. If we're in visualLine mode, then we want to copy // linewise but not necessarily delete linewise. - let result = await new PutCommand().exec(start, vimState, true); + let result = await new PutCommand(this.multicursorIndex).exec(start, vimState, true); result.currentRegisterMode = isLineWise ? RegisterMode.LineWise : RegisterMode.CharacterWise; result = await new operator.YankOperator(this.multicursorIndex).run(result, start, end); result.currentRegisterMode = RegisterMode.CharacterWise; result = await new operator.DeleteOperator(this.multicursorIndex).run(result, start, end.getLeftIfEOL(), false); + result.currentRegisterMode = RegisterMode.FigureItOutFromCurrentMode; return result; } @@ -1771,6 +1776,7 @@ class CommandExitVisualMode extends BaseCommand { class CommandVisualMode extends BaseCommand { modes = [ModeName.Normal]; keys = ["v"]; + isCompleteAction = false; public async exec(position: Position, vimState: VimState): Promise { vimState.currentMode = ModeName.Visual; diff --git a/src/mode/modeHandler.ts b/src/mode/modeHandler.ts index 0101d092003..0db17ea4ec9 100644 --- a/src/mode/modeHandler.ts +++ b/src/mode/modeHandler.ts @@ -1019,10 +1019,7 @@ export class ModeHandler implements vscode.Disposable { } ranRepeatableAction = (ranRepeatableAction && vimState.currentMode === ModeName.Normal) || this.createUndoPointForBrackets(vimState); - - // Don't record an undo point for every action of a macro, only at the very end - - ranAction = ranAction && vimState.currentMode === ModeName.Normal; + ranAction = ranAction && (vimState.currentMode === ModeName.Normal || vimState.currentMode === ModeName.Visual); // Record down previous action and flush temporary state if (ranRepeatableAction) { @@ -1033,6 +1030,20 @@ export class ModeHandler implements vscode.Disposable { } } + // Updated desired column + const movement = action instanceof BaseMovement ? action : undefined; + + if ((movement && !movement.doesntChangeDesiredColumn) || + (!movement && vimState.currentMode !== ModeName.VisualBlock)) { + // We check !operator here because e.g. d$ should NOT set the desired column to EOL. + + if (movement && movement.setsDesiredColumnToEOL && !recordedState.operator) { + vimState.desiredColumn = Number.POSITIVE_INFINITY; + } else { + vimState.desiredColumn = vimState.cursorPosition.character; + } + } + if (ranAction) { vimState.recordedState = new RecordedState(); @@ -1106,21 +1117,6 @@ export class ModeHandler implements vscode.Disposable { this._vimState.lastVisualSelectionEnd = this._vimState.cursorPosition; } - // Updated desired column - - const movement = action instanceof BaseMovement ? action : undefined; - - if ((movement && !movement.doesntChangeDesiredColumn) || - (recordedState.command && - vimState.currentMode !== ModeName.VisualBlock)) { - // We check !operator here because e.g. d$ should NOT set the desired column to EOL. - - if (movement && movement.setsDesiredColumnToEOL && !recordedState.operator) { - vimState.desiredColumn = Number.POSITIVE_INFINITY; - } else { - vimState.desiredColumn = vimState.cursorPosition.character; - } - } // Make sure no two cursors are at the same location. // This is a consequence of the fact that allCursors is not a Set.