From 41b4581ba239a0a550fa454d80fa3e5cb7ea61b0 Mon Sep 17 00:00:00 2001 From: andreamah Date: Thu, 11 Jan 2024 18:59:05 -0800 Subject: [PATCH 1/6] Implement preview on highlighting quickpick in quick search Fixes #191259 --- .../search/browser/anythingQuickAccess.ts | 189 ++++++++++-------- .../quickTextSearch/textSearchQuickAccess.ts | 59 +++++- 2 files changed, 152 insertions(+), 96 deletions(-) diff --git a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts index 00c019964888b..53907795f0a25 100644 --- a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts @@ -71,95 +71,128 @@ function isEditorSymbolQuickPickItem(pick?: IAnythingQuickPickItem): pick is IEd return !!candidate?.range && !!candidate.resource; } -export class AnythingQuickAccessProvider extends PickerQuickAccessProvider { +export class PickState { + picker: IQuickPick | undefined = undefined; - static PREFIX = ''; + editorViewState: { + editor: EditorInput; + group: IEditorGroup; + state: ICodeEditorViewState | IDiffEditorViewState | undefined; + } | undefined = undefined; - private static readonly NO_RESULTS_PICK: IAnythingQuickPickItem = { - label: localize('noAnythingResults', "No matching results") - }; + scorerCache: FuzzyScorerCache = Object.create(null); + fileQueryCache: FileQueryCacheState | undefined = undefined; - private static readonly MAX_RESULTS = 512; + lastOriginalFilter: string | undefined = undefined; + lastFilter: string | undefined = undefined; + lastRange: IRange | undefined = undefined; - private static readonly TYPING_SEARCH_DELAY = 200; // this delay accommodates for the user typing a word and then stops typing to start searching + lastGlobalPicks: PicksWithActive | undefined = undefined; - private static SYMBOL_PICKS_MERGE_DELAY = 200; // allow some time to merge fast and slow picks to reduce flickering + isQuickNavigating: boolean | undefined = undefined; - private readonly pickState = new class { + private readonly fileQueryBuilder = this.instantiationService.createInstance(QueryBuilder); - picker: IQuickPick | undefined = undefined; + constructor( + private readonly instantiationService: IInstantiationService, + private readonly contextService: IWorkspaceContextService, + private readonly searchService: ISearchService, + private readonly editorService: IEditorService) { } + + set(picker: IQuickPick): void { + + // Picker for this run + this.picker = picker; + Event.once(picker.onDispose)(() => { + if (picker === this.picker) { + this.picker = undefined; // clear the picker when disposed to not keep it in memory for too long + } + }); - editorViewState: { - editor: EditorInput; - group: IEditorGroup; - state: ICodeEditorViewState | IDiffEditorViewState | undefined; - } | undefined = undefined; + // Caches + const isQuickNavigating = !!picker.quickNavigate; + if (!isQuickNavigating) { + this.fileQueryCache = this.createFileQueryCache(); + this.scorerCache = Object.create(null); + } - scorerCache: FuzzyScorerCache = Object.create(null); - fileQueryCache: FileQueryCacheState | undefined = undefined; + // Other + this.isQuickNavigating = isQuickNavigating; + this.lastOriginalFilter = undefined; + this.lastFilter = undefined; + this.lastRange = undefined; + this.lastGlobalPicks = undefined; + this.editorViewState = undefined; + } - lastOriginalFilter: string | undefined = undefined; - lastFilter: string | undefined = undefined; - lastRange: IRange | undefined = undefined; + rememberEditorViewState(): void { + if (this.editorViewState) { + return; // return early if already done + } - lastGlobalPicks: PicksWithActive | undefined = undefined; + const activeEditorPane = this.editorService.activeEditorPane; + if (activeEditorPane) { + this.editorViewState = { + group: activeEditorPane.group, + editor: activeEditorPane.input, + state: getIEditor(activeEditorPane.getControl())?.saveViewState() ?? undefined, + }; + } + } - isQuickNavigating: boolean | undefined = undefined; + getFileQueryOptions(input: { filePattern?: string; cacheKey?: string; maxResults?: number }): IFileQueryBuilderOptions { + return { + _reason: 'openFileHandler', // used for telemetry - do not change + extraFileResources: this.instantiationService.invokeFunction(getOutOfWorkspaceEditorResources), + filePattern: input.filePattern || '', + cacheKey: input.cacheKey, + maxResults: input.maxResults || 0, + sortByScore: true + }; + } - constructor(private readonly provider: AnythingQuickAccessProvider, private readonly editorService: IEditorService) { } + async restoreEditorViewState(): Promise { + if (this.editorViewState) { + const options: IEditorOptions = { + viewState: this.editorViewState.state, + preserveFocus: true /* import to not close the picker as a result */ + }; - set(picker: IQuickPick): void { + await this.editorViewState.group.openEditor(this.editorViewState.editor, options); + } + } - // Picker for this run - this.picker = picker; - Event.once(picker.onDispose)(() => { - if (picker === this.picker) { - this.picker = undefined; // clear the picker when disposed to not keep it in memory for too long - } - }); - // Caches - const isQuickNavigating = !!picker.quickNavigate; - if (!isQuickNavigating) { - this.fileQueryCache = this.provider.createFileQueryCache(); - this.scorerCache = Object.create(null); - } + private createFileQueryCache(): FileQueryCacheState { + return new FileQueryCacheState( + cacheKey => this.fileQueryBuilder.file(this.contextService.getWorkspace().folders, this.getFileQueryOptions({ cacheKey })), + query => this.searchService.fileSearch(query), + cacheKey => this.searchService.clearCache(cacheKey), + this.fileQueryCache + ).load(); + } +} - // Other - this.isQuickNavigating = isQuickNavigating; - this.lastOriginalFilter = undefined; - this.lastFilter = undefined; - this.lastRange = undefined; - this.lastGlobalPicks = undefined; - this.editorViewState = undefined; - } +export class AnythingQuickAccessProvider extends PickerQuickAccessProvider { - rememberEditorViewState(): void { - if (this.editorViewState) { - return; // return early if already done - } + static PREFIX = ''; - const activeEditorPane = this.editorService.activeEditorPane; - if (activeEditorPane) { - this.editorViewState = { - group: activeEditorPane.group, - editor: activeEditorPane.input, - state: getIEditor(activeEditorPane.getControl())?.saveViewState() ?? undefined, - }; - } - } + private static readonly NO_RESULTS_PICK: IAnythingQuickPickItem = { + label: localize('noAnythingResults', "No matching results") + }; - async restoreEditorViewState(): Promise { - if (this.editorViewState) { - const options: IEditorOptions = { - viewState: this.editorViewState.state, - preserveFocus: true /* import to not close the picker as a result */ - }; + private static readonly MAX_RESULTS = 512; - await this.editorViewState.group.openEditor(this.editorViewState.editor, options); - } - } - }(this, this.editorService); + private static readonly TYPING_SEARCH_DELAY = 200; // this delay accommodates for the user typing a word and then stops typing to start searching + + private static SYMBOL_PICKS_MERGE_DELAY = 200; // allow some time to merge fast and slow picks to reduce flickering + + private readonly pickState = new PickState( + this.instantiationService, + this.contextService, + this.searchService, + this.editorService + ); get defaultFilterValue(): DefaultQuickAccessFilterValue | undefined { if (this.configuration.preserveInput) { @@ -510,14 +543,6 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider this.fileQueryBuilder.file(this.contextService.getWorkspace().folders, this.getFileQueryOptions({ cacheKey })), - query => this.searchService.fileSearch(query), - cacheKey => this.searchService.clearCache(cacheKey), - this.pickState.fileQueryCache - ).load(); - } private async getFilePicks(query: IPreparedQuery, excludes: ResourceMap, token: CancellationToken): Promise> { if (!query.normalized) { @@ -661,7 +686,7 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider { if (!query.containsPathSeparator) { diff --git a/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts b/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts index 1f248e45437e3..77228cb65c814 100644 --- a/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts @@ -17,7 +17,7 @@ import { ILabelService } from 'vs/platform/label/common/label'; import { WorkbenchCompressibleObjectTree, getSelectionKeyboardEvent } from 'vs/platform/list/browser/listService'; import { FastAndSlowPicks, IPickerQuickAccessItem, PickerQuickAccessProvider, Picks, TriggerAction } from 'vs/platform/quickinput/browser/pickerQuickAccess'; import { DefaultQuickAccessFilterValue, IQuickAccessProviderRunOptions } from 'vs/platform/quickinput/common/quickAccess'; -import { IKeyMods, IQuickPick, IQuickPickItem, IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput'; +import { IKeyMods, IQuickPick, IQuickPickItem, IQuickPickSeparator, QuickInputHideReason } from 'vs/platform/quickinput/common/quickInput'; import { IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { IWorkbenchEditorConfiguration } from 'vs/workbench/common/editor'; import { IViewsService } from 'vs/workbench/services/views/common/viewsService'; @@ -27,7 +27,9 @@ import { SearchView, getEditorSelectionFromMatch } from 'vs/workbench/contrib/se import { IWorkbenchSearchConfiguration, getOutOfWorkspaceEditorResources } from 'vs/workbench/contrib/search/common/search'; import { ACTIVE_GROUP, IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { ITextQueryBuilderOptions, QueryBuilder } from 'vs/workbench/services/search/common/queryBuilder'; -import { IPatternInfo, ITextQuery, VIEW_ID } from 'vs/workbench/services/search/common/search'; +import { IPatternInfo, ISearchService, ITextQuery, VIEW_ID } from 'vs/workbench/services/search/common/search'; +import { PickState } from 'vs/workbench/contrib/search/browser/anythingQuickAccess'; +import { Event } from 'vs/base/common/event'; export const TEXT_SEARCH_QUICK_ACCESS_PREFIX = '%'; @@ -42,9 +44,19 @@ const DEFAULT_TEXT_QUERY_BUILDER_OPTIONS: ITextQueryBuilderOptions = { const MAX_FILES_SHOWN = 30; const MAX_RESULTS_PER_FILE = 10; -export class TextSearchQuickAccess extends PickerQuickAccessProvider { +interface ITextSearchQuickAccessItem extends IPickerQuickAccessItem { + match?: Match; +} +export class TextSearchQuickAccess extends PickerQuickAccessProvider { private queryBuilder: QueryBuilder; private searchModel: SearchModel; + private navigatedAwayUsingPick = false; + private readonly pickState = new PickState( + this._instantiationService, + this._contextService, + this._searchService, + this._editorService + ); private _getTextQueryBuilderOptions(charsPerLine: number): ITextQueryBuilderOptions { return { @@ -69,6 +81,7 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider, token: CancellationToken, runOptions?: IQuickAccessProviderRunOptions): IDisposable { + override provide(picker: IQuickPick, token: CancellationToken, runOptions?: IQuickAccessProviderRunOptions): IDisposable { const disposables = new DisposableStore(); if (TEXT_SEARCH_QUICK_ACCESS_PREFIX.length < picker.value.length) { picker.valueSelection = [TEXT_SEARCH_QUICK_ACCESS_PREFIX.length, picker.value.length]; } picker.customButton = true; picker.customLabel = '$(link-external)'; - picker.onDidCustom(() => { + disposables.add(picker.onDidCustom(() => { this.moveToSearchViewlet(this.searchModel, undefined); picker.hide(); - }); + })); + disposables.add(picker.onDidChangeActive(() => { + const [item] = picker.activeItems; + + if (item.match) { + if (!this.navigatedAwayUsingPick) { + // we must remember our curret view state to be able to restore + this.pickState.rememberEditorViewState(); + this.navigatedAwayUsingPick = true; + } + // open it + this._editorService.openEditor({ + resource: item.match.parent().resource, + options: { preserveFocus: true, revealIfOpened: true, ignoreError: true, selection: item.match.range() } + }); + } + })); + + // Restore view state upon cancellation if we changed it + // but only when the picker was closed via explicit user + // gesture and not e.g. when focus was lost because that + // could mean the user clicked into the editor directly. + disposables.add(Event.once(picker.onDidHide)(({ reason }) => { + if (reason === QuickInputHideReason.Gesture) { + this.pickState.restoreEditorViewState(); + } + })); + disposables.add(super.provide(picker, token, runOptions)); disposables.add(picker.onDidHide(() => this.searchModel.searchResult.toggleHighlights(false))); disposables.add(picker.onDidAccept(() => this.searchModel.searchResult.toggleHighlights(false))); @@ -164,11 +204,11 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider limit ? matches.slice(0, limit) : matches; - const picks: Array = []; + const picks: Array = []; for (let fileIndex = 0; fileIndex < matches.length; fileIndex++) { if (fileIndex === limit) { @@ -245,7 +285,8 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider { this.moveToSearchViewlet(this.searchModel, element); return TriggerAction.CLOSE_PICKER; - } + }, + match: element }); } } From fa466c951141b14e1b314d0618e631e74e647e1d Mon Sep 17 00:00:00 2001 From: andreamah Date: Fri, 12 Jan 2024 10:04:57 -0800 Subject: [PATCH 2/6] reduce diff by only extracting editorViewState --- .../search/browser/anythingQuickAccess.ts | 167 +++++++++--------- .../quickTextSearch/textSearchQuickAccess.ts | 33 ++-- 2 files changed, 97 insertions(+), 103 deletions(-) diff --git a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts index 53907795f0a25..ae510ff4f78f4 100644 --- a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts @@ -71,68 +71,23 @@ function isEditorSymbolQuickPickItem(pick?: IAnythingQuickPickItem): pick is IEd return !!candidate?.range && !!candidate.resource; } -export class PickState { - picker: IQuickPick | undefined = undefined; - - editorViewState: { +export class EditorViewState { + private _editorViewState: { editor: EditorInput; group: IEditorGroup; state: ICodeEditorViewState | IDiffEditorViewState | undefined; } | undefined = undefined; - scorerCache: FuzzyScorerCache = Object.create(null); - fileQueryCache: FileQueryCacheState | undefined = undefined; - - lastOriginalFilter: string | undefined = undefined; - lastFilter: string | undefined = undefined; - lastRange: IRange | undefined = undefined; - - lastGlobalPicks: PicksWithActive | undefined = undefined; - - isQuickNavigating: boolean | undefined = undefined; - - private readonly fileQueryBuilder = this.instantiationService.createInstance(QueryBuilder); - - constructor( - private readonly instantiationService: IInstantiationService, - private readonly contextService: IWorkspaceContextService, - private readonly searchService: ISearchService, - private readonly editorService: IEditorService) { } - - set(picker: IQuickPick): void { - - // Picker for this run - this.picker = picker; - Event.once(picker.onDispose)(() => { - if (picker === this.picker) { - this.picker = undefined; // clear the picker when disposed to not keep it in memory for too long - } - }); - - // Caches - const isQuickNavigating = !!picker.quickNavigate; - if (!isQuickNavigating) { - this.fileQueryCache = this.createFileQueryCache(); - this.scorerCache = Object.create(null); - } - - // Other - this.isQuickNavigating = isQuickNavigating; - this.lastOriginalFilter = undefined; - this.lastFilter = undefined; - this.lastRange = undefined; - this.lastGlobalPicks = undefined; - this.editorViewState = undefined; - } + constructor(private readonly editorService: IEditorService) { } - rememberEditorViewState(): void { - if (this.editorViewState) { + set(): void { + if (this._editorViewState) { return; // return early if already done } const activeEditorPane = this.editorService.activeEditorPane; if (activeEditorPane) { - this.editorViewState = { + this._editorViewState = { group: activeEditorPane.group, editor: activeEditorPane.input, state: getIEditor(activeEditorPane.getControl())?.saveViewState() ?? undefined, @@ -140,36 +95,19 @@ export class PickState { } } - getFileQueryOptions(input: { filePattern?: string; cacheKey?: string; maxResults?: number }): IFileQueryBuilderOptions { - return { - _reason: 'openFileHandler', // used for telemetry - do not change - extraFileResources: this.instantiationService.invokeFunction(getOutOfWorkspaceEditorResources), - filePattern: input.filePattern || '', - cacheKey: input.cacheKey, - maxResults: input.maxResults || 0, - sortByScore: true - }; - } - - async restoreEditorViewState(): Promise { - if (this.editorViewState) { + async restore(): Promise { + if (this._editorViewState) { const options: IEditorOptions = { - viewState: this.editorViewState.state, + viewState: this._editorViewState.state, preserveFocus: true /* import to not close the picker as a result */ }; - await this.editorViewState.group.openEditor(this.editorViewState.editor, options); + await this._editorViewState.group.openEditor(this._editorViewState.editor, options); } } - - private createFileQueryCache(): FileQueryCacheState { - return new FileQueryCacheState( - cacheKey => this.fileQueryBuilder.file(this.contextService.getWorkspace().folders, this.getFileQueryOptions({ cacheKey })), - query => this.searchService.fileSearch(query), - cacheKey => this.searchService.clearCache(cacheKey), - this.fileQueryCache - ).load(); + reset() { + this._editorViewState = undefined; } } @@ -187,12 +125,53 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider | undefined = undefined; + + editorViewState: EditorViewState; + + scorerCache: FuzzyScorerCache = Object.create(null); + fileQueryCache: FileQueryCacheState | undefined = undefined; + + lastOriginalFilter: string | undefined = undefined; + lastFilter: string | undefined = undefined; + lastRange: IRange | undefined = undefined; + + lastGlobalPicks: PicksWithActive | undefined = undefined; + + isQuickNavigating: boolean | undefined = undefined; + + constructor(private readonly provider: AnythingQuickAccessProvider, editorService: IEditorService) { + this.editorViewState = new EditorViewState(editorService); + } + + set(picker: IQuickPick): void { + + // Picker for this run + this.picker = picker; + Event.once(picker.onDispose)(() => { + if (picker === this.picker) { + this.picker = undefined; // clear the picker when disposed to not keep it in memory for too long + } + }); + + // Caches + const isQuickNavigating = !!picker.quickNavigate; + if (!isQuickNavigating) { + this.fileQueryCache = this.provider.createFileQueryCache(); + this.scorerCache = Object.create(null); + } + + // Other + this.isQuickNavigating = isQuickNavigating; + this.lastOriginalFilter = undefined; + this.lastFilter = undefined; + this.lastRange = undefined; + this.lastGlobalPicks = undefined; + this.editorViewState.reset(); + } + }(this, this.editorService); get defaultFilterValue(): DefaultQuickAccessFilterValue | undefined { if (this.configuration.preserveInput) { @@ -270,7 +249,7 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider { if (reason === QuickInputHideReason.Gesture) { - this.pickState.restoreEditorViewState(); + this.pickState.editorViewState.restore(); } })); @@ -292,7 +271,7 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider this.fileQueryBuilder.file(this.contextService.getWorkspace().folders, this.getFileQueryOptions({ cacheKey })), + query => this.searchService.fileSearch(query), + cacheKey => this.searchService.clearCache(cacheKey), + this.pickState.fileQueryCache + ).load(); + } private async getFilePicks(query: IPreparedQuery, excludes: ResourceMap, token: CancellationToken): Promise> { if (!query.normalized) { @@ -686,7 +673,7 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider { if (!query.containsPathSeparator) { @@ -886,7 +883,7 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider { private queryBuilder: QueryBuilder; private searchModel: SearchModel; - private navigatedAwayUsingPick = false; - private readonly pickState = new PickState( - this._instantiationService, - this._contextService, - this._searchService, + private storedOriginalLocation = false; + private readonly editorViewState = new EditorViewState( this._editorService ); @@ -80,8 +77,7 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider { + // Restore view state upon cancellation if we changed it + // but only when the picker was closed via explicit user + // gesture and not e.g. when focus was lost because that + // could mean the user clicked into the editor directly. if (reason === QuickInputHideReason.Gesture) { - this.pickState.restoreEditorViewState(); + this.editorViewState.restore(); } + this.searchModel.searchResult.toggleHighlights(false); })); disposables.add(super.provide(picker, token, runOptions)); - disposables.add(picker.onDidHide(() => this.searchModel.searchResult.toggleHighlights(false))); disposables.add(picker.onDidAccept(() => this.searchModel.searchResult.toggleHighlights(false))); return disposables; } From eb8e7568343701d89aadc633c37b316970a3dae4 Mon Sep 17 00:00:00 2001 From: andreamah Date: Mon, 15 Jan 2024 11:39:40 -0800 Subject: [PATCH 3/6] move EditorViewState to src/vs/workbench/browser/quickaccess.ts --- src/vs/workbench/browser/quickaccess.ts | 45 +++++++++++++++++ .../search/browser/anythingQuickAccess.ts | 48 ++----------------- .../quickTextSearch/textSearchQuickAccess.ts | 2 +- 3 files changed, 49 insertions(+), 46 deletions(-) diff --git a/src/vs/workbench/browser/quickaccess.ts b/src/vs/workbench/browser/quickaccess.ts index afc3f54369b77..a73c3d7072c5c 100644 --- a/src/vs/workbench/browser/quickaccess.ts +++ b/src/vs/workbench/browser/quickaccess.ts @@ -8,6 +8,12 @@ import { ContextKeyExpr, RawContextKey } from 'vs/platform/contextkey/common/con import { ICommandHandler } from 'vs/platform/commands/common/commands'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; +import { getIEditor } from 'vs/editor/browser/editorBrowser'; +import { ICodeEditorViewState, IDiffEditorViewState } from 'vs/editor/common/editorCommon'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; +import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { IEditorOptions } from 'vs/platform/editor/common/editor'; export const inQuickPickContextKeyValue = 'inQuickOpen'; export const InQuickPickContextKey = new RawContextKey(inQuickPickContextKeyValue, false, localize('inQuickOpen', "Whether keyboard focus is inside the quick open control")); @@ -45,3 +51,42 @@ export function getQuickNavigateHandler(id: string, next?: boolean): ICommandHan quickInputService.navigate(!!next, quickNavigate); }; } +export class EditorViewState { + private _editorViewState: { + editor: EditorInput; + group: IEditorGroup; + state: ICodeEditorViewState | IDiffEditorViewState | undefined; + } | undefined = undefined; + + constructor(private readonly editorService: IEditorService) { } + + set(): void { + if (this._editorViewState) { + return; // return early if already done + } + + const activeEditorPane = this.editorService.activeEditorPane; + if (activeEditorPane) { + this._editorViewState = { + group: activeEditorPane.group, + editor: activeEditorPane.input, + state: getIEditor(activeEditorPane.getControl())?.saveViewState() ?? undefined, + }; + } + } + + async restore(): Promise { + if (this._editorViewState) { + const options: IEditorOptions = { + viewState: this._editorViewState.state, + preserveFocus: true /* import to not close the picker as a result */ + }; + + await this._editorViewState.group.openEditor(this._editorViewState.editor, options); + } + } + + reset() { + this._editorViewState = undefined; + } +} diff --git a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts index ae510ff4f78f4..03a37d5384ed7 100644 --- a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts @@ -35,19 +35,17 @@ import { ThrottledDelayer } from 'vs/base/common/async'; import { top } from 'vs/base/common/arrays'; import { FileQueryCacheState } from 'vs/workbench/contrib/search/common/cacheState'; import { IHistoryService } from 'vs/workbench/services/history/common/history'; -import { IEditorOptions, IResourceEditorInput, ITextEditorOptions } from 'vs/platform/editor/common/editor'; +import { IResourceEditorInput, ITextEditorOptions } from 'vs/platform/editor/common/editor'; import { Schemas } from 'vs/base/common/network'; import { IFilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService'; import { ResourceMap } from 'vs/base/common/map'; import { SymbolsQuickAccessProvider } from 'vs/workbench/contrib/search/browser/symbolsQuickAccess'; import { AnythingQuickAccessProviderRunOptions, DefaultQuickAccessFilterValue, Extensions, IQuickAccessRegistry } from 'vs/platform/quickinput/common/quickAccess'; -import { IWorkbenchQuickAccessConfiguration } from 'vs/workbench/browser/quickaccess'; +import { EditorViewState, IWorkbenchQuickAccessConfiguration } from 'vs/workbench/browser/quickaccess'; import { GotoSymbolQuickAccessProvider } from 'vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; -import { ScrollType, IEditor, ICodeEditorViewState, IDiffEditorViewState } from 'vs/editor/common/editorCommon'; +import { ScrollType, IEditor } from 'vs/editor/common/editorCommon'; import { Event } from 'vs/base/common/event'; -import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService'; -import { getIEditor } from 'vs/editor/browser/editorBrowser'; import { Codicon } from 'vs/base/common/codicons'; import { ThemeIcon } from 'vs/base/common/themables'; import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'; @@ -71,46 +69,6 @@ function isEditorSymbolQuickPickItem(pick?: IAnythingQuickPickItem): pick is IEd return !!candidate?.range && !!candidate.resource; } -export class EditorViewState { - private _editorViewState: { - editor: EditorInput; - group: IEditorGroup; - state: ICodeEditorViewState | IDiffEditorViewState | undefined; - } | undefined = undefined; - - constructor(private readonly editorService: IEditorService) { } - - set(): void { - if (this._editorViewState) { - return; // return early if already done - } - - const activeEditorPane = this.editorService.activeEditorPane; - if (activeEditorPane) { - this._editorViewState = { - group: activeEditorPane.group, - editor: activeEditorPane.input, - state: getIEditor(activeEditorPane.getControl())?.saveViewState() ?? undefined, - }; - } - } - - async restore(): Promise { - if (this._editorViewState) { - const options: IEditorOptions = { - viewState: this._editorViewState.state, - preserveFocus: true /* import to not close the picker as a result */ - }; - - await this._editorViewState.group.openEditor(this._editorViewState.editor, options); - } - } - - reset() { - this._editorViewState = undefined; - } -} - export class AnythingQuickAccessProvider extends PickerQuickAccessProvider { static PREFIX = ''; diff --git a/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts b/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts index 83739f75e37b9..4b4c30892bc92 100644 --- a/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts @@ -28,8 +28,8 @@ import { IWorkbenchSearchConfiguration, getOutOfWorkspaceEditorResources } from import { ACTIVE_GROUP, IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { ITextQueryBuilderOptions, QueryBuilder } from 'vs/workbench/services/search/common/queryBuilder'; import { IPatternInfo, ITextQuery, VIEW_ID } from 'vs/workbench/services/search/common/search'; -import { EditorViewState } from 'vs/workbench/contrib/search/browser/anythingQuickAccess'; import { Event } from 'vs/base/common/event'; +import { EditorViewState } from 'vs/workbench/browser/quickaccess'; export const TEXT_SEARCH_QUICK_ACCESS_PREFIX = '%'; From 1c09a050fd28a3ceec4a3174fe67c6acc245a971 Mon Sep 17 00:00:00 2001 From: andreamah Date: Tue, 16 Jan 2024 09:08:17 -0800 Subject: [PATCH 4/6] Fix item undefined error --- .../search/browser/quickTextSearch/textSearchQuickAccess.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts b/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts index 4b4c30892bc92..517a5d2826297 100644 --- a/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts @@ -104,7 +104,7 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider { const [item] = picker.activeItems; - if (item.match) { + if (item && item.match) { // only store location once, or else it will store new state every time we change active pick if (!this.storedOriginalLocation) { // we must remember our curret view state to be able to restore From 142bf289a70bea9fbcd44100e37251344756c91c Mon Sep 17 00:00:00 2001 From: andreamah Date: Tue, 16 Jan 2024 10:43:00 -0800 Subject: [PATCH 5/6] use item?.match --- .../search/browser/quickTextSearch/textSearchQuickAccess.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts b/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts index 517a5d2826297..f51c90d2b6059 100644 --- a/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts @@ -104,7 +104,7 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider { const [item] = picker.activeItems; - if (item && item.match) { + if (item?.match) { // only store location once, or else it will store new state every time we change active pick if (!this.storedOriginalLocation) { // we must remember our curret view state to be able to restore From 96cc606a582e0ed2e762fc400d37d256bd9cb06a Mon Sep 17 00:00:00 2001 From: andreamah Date: Wed, 17 Jan 2024 08:09:52 -0800 Subject: [PATCH 6/6] viewsservice conflict --- .../search/browser/quickTextSearch/textSearchQuickAccess.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts b/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts index 8488bc964cc10..3be24ea6f3434 100644 --- a/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.ts @@ -20,7 +20,6 @@ import { DefaultQuickAccessFilterValue, IQuickAccessProviderRunOptions } from 'v import { IKeyMods, IQuickPick, IQuickPickItem, IQuickPickSeparator, QuickInputHideReason } from 'vs/platform/quickinput/common/quickInput'; import { IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { IWorkbenchEditorConfiguration } from 'vs/workbench/common/editor'; -import { IViewsService } from 'vs/workbench/services/views/common/viewsService'; import { searchDetailsIcon, searchOpenInFileIcon, searchActivityBarIcon } from 'vs/workbench/contrib/search/browser/searchIcons'; import { FileMatch, Match, RenderableMatch, SearchModel, SearchModelLocation, searchComparer } from 'vs/workbench/contrib/search/browser/searchModel'; import { SearchView, getEditorSelectionFromMatch } from 'vs/workbench/contrib/search/browser/searchView'; @@ -30,6 +29,7 @@ import { ITextQueryBuilderOptions, QueryBuilder } from 'vs/workbench/services/se import { IPatternInfo, ISearchComplete, ITextQuery, VIEW_ID } from 'vs/workbench/services/search/common/search'; import { Event } from 'vs/base/common/event'; import { EditorViewState } from 'vs/workbench/browser/quickaccess'; +import { IViewsService } from 'vs/workbench/services/views/common/viewsService'; export const TEXT_SEARCH_QUICK_ACCESS_PREFIX = '%';