From 2c81aa4f7cf14bb373c10b0b9911b7e7b8d3b117 Mon Sep 17 00:00:00 2001 From: Sean Kelly Date: Thu, 8 Dec 2016 23:36:47 -0800 Subject: [PATCH] Reselect visual implemented (gv) (#1141) * fixes #986 * update roadmap for gv --- ROADMAP.md | 2 +- src/actions/actions.ts | 22 ++++++++++++++++++++++ src/mode/modeHandler.ts | 20 +++++++++++++++++++- test/mode/modeVisual.test.ts | 8 ++++++++ 4 files changed, 50 insertions(+), 2 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 14581ed9d7b..85c86ee66dd 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -388,7 +388,7 @@ Status | Command | Description :white_check_mark: | v | start highlighting characters :white_check_mark: | V | start highlighting linewise :white_check_mark:| o | exchange cursor position with start of highlighting - | gv | start highlighting on previous visual area +:white_check_mark:| gv | start highlighting on previous visual area :white_check_mark: | v | highlight characters or stop highlighting :white_check_mark: | V | highlight linewise or stop highlighting :white_check_mark: | CTRL-V | highlight blockwise or stop highlighting diff --git a/src/actions/actions.ts b/src/actions/actions.ts index 62c474d7e71..ce8add20bea 100644 --- a/src/actions/actions.ts +++ b/src/actions/actions.ts @@ -2698,6 +2698,28 @@ class CommandVisualMode extends BaseCommand { } } +@RegisterAction +class CommandReselectVisual extends BaseCommand { + modes = [ModeName.Normal]; + keys = ["g", "v"]; + + public async exec(position: Position, vimState: VimState): Promise { + // Try to restore selection only if valid + if (vimState.lastVisualSelectionEnd !== undefined && + vimState.lastVisualSelectionStart !== undefined && + vimState.lastVisualMode !== undefined) { + + if (vimState.lastVisualSelectionEnd.line <= (TextEditor.getLineCount() - 1)) { + vimState.currentMode = vimState.lastVisualMode; + vimState.cursorStartPosition = vimState.lastVisualSelectionStart; + vimState.cursorPosition = vimState.lastVisualSelectionEnd; + } + + } + return vimState; + } +} + @RegisterAction class CommandVisualBlockMode extends BaseCommand { modes = [ModeName.Normal, ModeName.Visual, ModeName.VisualBlock]; diff --git a/src/mode/modeHandler.ts b/src/mode/modeHandler.ts index 09cef1fe11d..8c37fa5f9ba 100644 --- a/src/mode/modeHandler.ts +++ b/src/mode/modeHandler.ts @@ -176,6 +176,17 @@ export class VimState { public replaceState: ReplaceState | undefined = undefined; + /** + * Stores last visual mode for gv + */ + public lastVisualMode: ModeName; + + /** + * Last selection that was active + */ + public lastVisualSelectionStart: Position; + public lastVisualSelectionEnd: Position; + /** * The mode Vim will be in once this action finishes. */ @@ -961,6 +972,13 @@ export class ModeHandler implements vscode.Disposable { vimState.historyTracker.setLastHistoryEndPosition(vimState.allCursors.map(x => x.stop)); + if (vimState.getModeObject(this).isVisualMode) { + // Store selection for commands like gv + this._vimState.lastVisualMode = this._vimState.currentMode; + this._vimState.lastVisualSelectionStart = this._vimState.cursorStartPosition; + this._vimState.lastVisualSelectionEnd = this._vimState.cursorPosition; + } + // Updated desired column const movement = action instanceof BaseMovement ? action : undefined; @@ -1035,7 +1053,7 @@ export class ModeHandler implements vscode.Disposable { vimState.allCursors[i] = vimState.allCursors[i].withNewStop(result); if (!vimState.getModeObject(this).isVisualMode && - !vimState.recordedState.operator) { + !vimState.recordedState.operator) { vimState.allCursors[i] = vimState.allCursors[i].withNewStart(result); } diff --git a/test/mode/modeVisual.test.ts b/test/mode/modeVisual.test.ts index a76b03fd122..0f4e3ff204e 100644 --- a/test/mode/modeVisual.test.ts +++ b/test/mode/modeVisual.test.ts @@ -592,4 +592,12 @@ suite("Mode Visual", () => { }); }); + newTest({ + title: "Can do gv to reselect previous selection", + start: ["tes|ttest"], + keysPressed: "vlllgvd", + end: ["tes|est"], + endMode: ModeName.Normal + }); + });