From 47aa61ceab94327e4f178ee18d93163e07b9e403 Mon Sep 17 00:00:00 2001 From: Jason Fields Date: Mon, 27 Jun 2022 18:48:57 -0400 Subject: [PATCH] Cache search decorations when possible This actually saves a *lot* of work on simple keystrokes like `hjkl` when you've got a lot of search results highlighted. --- src/mode/modeHandler.ts | 27 ++++++++++++++++++++++++--- src/util/decorationUtils.ts | 8 ++------ 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/mode/modeHandler.ts b/src/mode/modeHandler.ts index 6fde97aeb..29dbe5819 100644 --- a/src/mode/modeHandler.ts +++ b/src/mode/modeHandler.ts @@ -17,7 +17,7 @@ import { PairMatcher } from './../common/matching/matcher'; import { laterOf } from './../common/motion/position'; import { Cursor } from '../common/motion/cursor'; import { RecordedState } from './../state/recordedState'; -import { IBaseAction } from "../actions/types"; +import { IBaseAction } from '../actions/types'; import { Register, RegisterMode } from './../register/register'; import { Remappers } from '../configuration/remapper'; import { StatusBar } from '../statusBar'; @@ -46,6 +46,7 @@ import { Position, Uri } from 'vscode'; import { RemapState } from '../state/remapState'; import * as process from 'process'; import { EasyMotion } from '../actions/plugins/easymotion/easymotion'; +import { SearchState } from '../state/searchState'; interface IModeHandlerMap { get(editorId: Uri): ModeHandler | undefined; @@ -63,6 +64,10 @@ export class ModeHandler implements vscode.Disposable, IModeHandler { public focusChanged = false; + private searchDecorationCacheKey: + | { searchState: SearchState; documentVersion: number } + | undefined; + private readonly disposables: vscode.Disposable[] = []; private readonly handlerMap: IModeHandlerMap; private readonly remappers: Remappers; @@ -1156,6 +1161,9 @@ export class ModeHandler implements vscode.Disposable, IModeHandler { } public updateSearchHighlights(showHighlights: boolean) { + const cacheKey = this.searchDecorationCacheKey; + this.searchDecorationCacheKey = undefined; + let decorations: SearchDecorations | undefined; if (showHighlights) { if ( @@ -1163,11 +1171,24 @@ export class ModeHandler implements vscode.Disposable, IModeHandler { this.vimState.modeData.mode === Mode.SearchInProgressMode ) { decorations = this.vimState.modeData.commandLine.getDecorations(this.vimState); - } else { + } else if (globalState.searchState) { + if ( + cacheKey && + cacheKey.searchState === globalState.searchState && + cacheKey.documentVersion === this.vimState.document.version + ) { + // The decorations are fine as-is, don't waste time re-calculating + this.searchDecorationCacheKey = cacheKey; + return; + } // If there are no decorations from the command line, get decorations for previous SearchState decorations = getDecorationsForSearchMatchRanges( - globalState.searchState?.getMatchRanges(this.vimState) + globalState.searchState.getMatchRanges(this.vimState) ); + this.searchDecorationCacheKey = { + searchState: globalState.searchState, + documentVersion: this.vimState.document.version, + }; } } diff --git a/src/util/decorationUtils.ts b/src/util/decorationUtils.ts index 5f51bb85c..3990d5109 100644 --- a/src/util/decorationUtils.ts +++ b/src/util/decorationUtils.ts @@ -24,7 +24,7 @@ export type SearchDecorations = { * character. */ export function ensureVisible(range: Range): DecorationOptions { - return range.start.isLineEnd() && (range.isEmpty || range.end.isLineBeginning()) + return (range.isEmpty || range.end.isLineBeginning()) && range.start.isLineEnd() ? { // range is at EOL, possibly containing EOL char(s). range: range.with(undefined, range.start), @@ -61,13 +61,9 @@ export function formatDecorationText( * @returns search decorations for the given ranges, taking into account the current match */ export function getDecorationsForSearchMatchRanges( - ranges: Range[] | undefined, + ranges: Range[], currentMatchIndex?: number ): SearchDecorations { - if (ranges === undefined) { - return {}; - } - const searchHighlight: DecorationOptions[] = []; const searchMatch: DecorationOptions[] = [];