From 0bf6ebde91998730762a5708d9552118a92884ef Mon Sep 17 00:00:00 2001 From: Elliott Linder Date: Sat, 16 Mar 2019 13:37:19 +0200 Subject: [PATCH] Add yank highlighting Partially fixes #2991 Fixes #2333 Fixes #2916 Supersedes #3129 Co-authored-by: Esa-Matti Suuronen --- README.md | 3 +++ package.json | 15 +++++++++++++ src/actions/operator.ts | 35 +++++++++++++++++++++++------ src/configuration/configuration.ts | 7 ++++++ src/configuration/iconfiguration.ts | 22 ++++++++++++++++++ test/testConfiguration.ts | 5 +++++ 6 files changed, 80 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 3d216b6c250..8c9367adf74 100644 --- a/README.md +++ b/README.md @@ -123,6 +123,9 @@ These settings are specific to VSCodeVim. | vim.substituteGlobalFlag | Similar to Vim's `gdefault` setting. `/g` flag in a substitute command replaces all occurrences in the line. Without this flag, replacement occurs only for the first occurrence in each line. With this setting enabled, the `g` is on by default. | Boolean | false | | vim.useCtrlKeys | Enable Vim ctrl keys overriding common VS Code operations such as copy, paste, find, etc. | Boolean | true | | vim.visualstar | In visual mode, start a search with `*` or `#` using the current selection | Boolean | false | +| vim.highlightedyank.enable | Enable highlighting when yanking | Boolean | false | +| vim.highlightedyank.color | Set the color of yank highlights | String | rgba(250, 240, 170, 0.5) | +| vim.highlightedyank.duration | Set the duration of yank highlights | Number | 200 | ### Neovim Integration diff --git a/package.json b/package.json index 960a7af91e1..93a4c6e29bc 100644 --- a/package.json +++ b/package.json @@ -383,6 +383,21 @@ "type": "string", "description": "Color of the search highlight." }, + "vim.highlightedyank.enable": { + "type": "boolean", + "description": "Enable highlighting when yanking.", + "default": false + }, + "vim.highlightedyank.color": { + "type": "string", + "description": "Color of the yank highlight.", + "default": "rgba(250, 240, 170, 0.5)" + }, + "vim.highlightedyank.duration": { + "type": "number", + "description": "Duration in milliseconds of the yank highlight.", + "default": 200 + }, "vim.useSystemClipboard": { "type": "boolean", "description": "Use system clipboard for unnamed register.", diff --git a/src/actions/operator.ts b/src/actions/operator.ts index 2d71378d1b7..dd78fa30976 100644 --- a/src/actions/operator.ts +++ b/src/actions/operator.ts @@ -11,6 +11,7 @@ import { BaseAction, RegisterAction } from './base'; import { CommandNumber } from './commands/actions'; import { TextObjectMovement } from './textobject'; import { ReportLinesChanged, ReportLinesYanked } from '../util/statusBarTextUtils'; +import { IHighlightedYankConfiguration } from '../configuration/iconfiguration'; export class BaseOperator extends BaseAction { constructor(multicursorIndex?: number) { @@ -101,6 +102,19 @@ export class BaseOperator extends BaseAction { position.getDownByCount(Math.max(0, count - 1)).getLineEnd() ); } + + public highlightYankedRanges(vimState: VimState, ranges: vscode.Range[]) { + if (!configuration.highlightedyank.enable) { + return; + } + + const yankDecoration = vscode.window.createTextEditorDecorationType({ + backgroundColor: configuration.highlightedyank.color, + }); + + vimState.editor.setDecorations(yankDecoration, ranges); + setTimeout(() => yankDecoration.dispose(), configuration.highlightedyank.duration); + } } @RegisterAction @@ -268,7 +282,8 @@ export class YankOperator extends BaseOperator { extendedEnd = extendedEnd.getLineEnd(); } - let text = TextEditor.getText(new vscode.Range(start, extendedEnd)); + const range = new vscode.Range(start, extendedEnd); + let text = TextEditor.getText(range); // If we selected the newline character, add it as well. if ( @@ -278,6 +293,8 @@ export class YankOperator extends BaseOperator { text = text + '\n'; } + this.highlightYankedRanges(vimState, [range]); + Register.put(text, vimState, this.multicursorIndex); if (vimState.currentMode === ModeName.Visual || vimState.currentMode === ModeName.VisualLine) { @@ -648,12 +665,14 @@ export class YankVisualBlockMode extends BaseOperator { return false; } - public async run(vimState: VimState, start: Position, end: Position): Promise { + public async run(vimState: VimState, startPos: Position, endPos: Position): Promise { let toCopy: string = ''; + const ranges: vscode.Range[] = []; - const isMultiline = start.line !== end.line; + const isMultiline = startPos.line !== endPos.line; - for (const { line } of Position.IterateLine(vimState)) { + for (const { line, start, end } of Position.IterateLine(vimState)) { + ranges.push(new vscode.Range(start, end)); if (isMultiline) { toCopy += line + '\n'; } else { @@ -663,16 +682,18 @@ export class YankVisualBlockMode extends BaseOperator { vimState.currentRegisterMode = RegisterMode.BlockWise; + this.highlightYankedRanges(vimState, ranges); + Register.put(toCopy, vimState, this.multicursorIndex); - vimState.historyTracker.addMark(start, '<'); - vimState.historyTracker.addMark(end, '>'); + vimState.historyTracker.addMark(startPos, '<'); + vimState.historyTracker.addMark(endPos, '>'); const numLinesYanked = toCopy.split('\n').length; ReportLinesYanked(numLinesYanked, vimState); await vimState.setCurrentMode(ModeName.Normal); - vimState.cursorStopPosition = start; + vimState.cursorStopPosition = startPos; return vimState; } } diff --git a/src/configuration/configuration.ts b/src/configuration/configuration.ts index c7d6d337fcc..a751092ec80 100644 --- a/src/configuration/configuration.ts +++ b/src/configuration/configuration.ts @@ -11,6 +11,7 @@ import { IModeSpecificStrings, IAutoSwitchInputMethod, IDebugConfiguration, + IHighlightedYankConfiguration, ICamelCaseMotionConfiguration, } from './iconfiguration'; @@ -240,6 +241,12 @@ class Configuration implements IConfiguration { }) searchHighlightColor: string; + highlightedyank: IHighlightedYankConfiguration = { + enable: false, + color: 'rgba(250, 240, 170, 0.5)', + duration: 200, + }; + @overlapSetting({ settingName: 'tabSize', defaultValue: 8 }) tabstop: number; diff --git a/src/configuration/iconfiguration.ts b/src/configuration/iconfiguration.ts index c824d9225c2..6102ff4c470 100644 --- a/src/configuration/iconfiguration.ts +++ b/src/configuration/iconfiguration.ts @@ -42,6 +42,23 @@ export interface IDebugConfiguration { loggingLevelForConsole: 'error' | 'warn' | 'info' | 'verbose' | 'debug'; } +export interface IHighlightedYankConfiguration { + /** + * Boolean indicating whether yank highlighting should be enabled. + */ + enable: boolean; + + /** + * Color of the yank highlight. + */ + color: string; + + /** + * Duration in milliseconds of the yank highlight. + */ + duration: number; +} + export interface ICamelCaseMotionConfiguration { /** * Enable CamelCaseMotion plugin or not @@ -185,6 +202,11 @@ export interface IConfiguration { */ searchHighlightColor: string; + /** + * Yank highlight settings. + */ + highlightedyank: IHighlightedYankConfiguration; + /** * Size of a tab character. */ diff --git a/test/testConfiguration.ts b/test/testConfiguration.ts index ce011581e24..f642e71df56 100644 --- a/test/testConfiguration.ts +++ b/test/testConfiguration.ts @@ -60,6 +60,11 @@ export class Configuration implements IConfiguration { loggingLevelForConsole: 'debug'; }; searchHighlightColor = 'rgba(150, 150, 255, 0.3)'; + highlightedyank: { + enable: false; + color: 'rgba(250, 240, 170, 0.5)'; + duration: 200; + }; tabstop = 2; editorCursorStyle = vscode.TextEditorCursorStyle.Line; expandtab = true;