From cf4ce3868197574a48d36439235b3200460089f1 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 9 May 2018 00:11:35 -0700 Subject: [PATCH] Fixes #18233: Added replace history for Find view --- .../parts/search/browser/searchActions.ts | 41 +++++++++++++++++++ .../parts/search/browser/searchView.ts | 8 +++- .../parts/search/browser/searchWidget.ts | 39 ++++++++++++++++-- .../electron-browser/search.contribution.ts | 5 ++- 4 files changed, 87 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/parts/search/browser/searchActions.ts b/src/vs/workbench/parts/search/browser/searchActions.ts index 17a6209022f..30ad61a997a 100644 --- a/src/vs/workbench/parts/search/browser/searchActions.ts +++ b/src/vs/workbench/parts/search/browser/searchActions.ts @@ -209,6 +209,47 @@ export class ShowPreviousSearchTermAction extends Action { return TPromise.as(null); } } +export class ShowNextReplaceTermAction extends Action { + + public static readonly ID = 'search.replaceHistory.showNext'; + public static readonly LABEL = nls.localize('nextReplaceTerm', "Show Next Search Replace Term"); + + constructor(id: string, label: string, + @IViewletService private viewletService: IViewletService, + @IContextKeyService private contextKeyService: IContextKeyService, + @IPanelService private panelService: IPanelService + ) { + super(id, label); + this.enabled = this.contextKeyService.contextMatchesRules(Constants.SearchViewVisibleKey); + } + + public run(): TPromise { + const searchView = getSearchView(this.viewletService, this.panelService); + searchView.searchAndReplaceWidget.showNextReplaceTerm(); + return TPromise.as(null); + } +} + +export class ShowPreviousReplaceTermAction extends Action { + + public static readonly ID = 'search.replaceHistory.showPrevious'; + public static readonly LABEL = nls.localize('previousReplaceTerm', "Show Previous Search Replace Term"); + + constructor(id: string, label: string, + @IViewletService private viewletService: IViewletService, + @IContextKeyService private contextKeyService: IContextKeyService, + @IPanelService private panelService: IPanelService + ) { + super(id, label); + this.enabled = this.contextKeyService.contextMatchesRules(Constants.SearchViewVisibleKey); + } + + public run(): TPromise { + const searchView = getSearchView(this.viewletService, this.panelService); + searchView.searchAndReplaceWidget.showPreviousReplaceTerm(); + return TPromise.as(null); + } +} export class FocusNextInputAction extends Action { diff --git a/src/vs/workbench/parts/search/browser/searchView.ts b/src/vs/workbench/parts/search/browser/searchView.ts index 9de89c56f91..5c763261753 100644 --- a/src/vs/workbench/parts/search/browser/searchView.ts +++ b/src/vs/workbench/parts/search/browser/searchView.ts @@ -331,13 +331,15 @@ export class SearchView extends Viewlet implements IViewlet, IPanel { let isWholeWords = this.viewletSettings['query.wholeWords'] === true; let isCaseSensitive = this.viewletSettings['query.caseSensitive'] === true; let searchHistory = this.viewletSettings['query.searchHistory'] || []; + let replaceHistory = this.viewletSettings['query.replaceHistory'] || []; this.searchWidget = this.instantiationService.createInstance(SearchWidget, builder, { value: contentPattern, isRegex: isRegex, isCaseSensitive: isCaseSensitive, isWholeWords: isWholeWords, - history: searchHistory, + searchHistory: searchHistory, + replaceHistory: replaceHistory, historyLimit: SearchView.MAX_HISTORY_ITEMS }); @@ -1519,13 +1521,15 @@ export class SearchView extends Viewlet implements IViewlet, IPanel { const patternExcludes = this.inputPatternExcludes.getValue().trim(); const patternIncludes = this.inputPatternIncludes.getValue().trim(); const useExcludesAndIgnoreFiles = this.inputPatternExcludes.useExcludesAndIgnoreFiles(); - const searchHistory = this.searchWidget.getHistory(); + const searchHistory = this.searchWidget.getSearchHistory(); + const replaceHistory = this.searchWidget.getReplaceHistory(); const patternExcludesHistory = this.inputPatternExcludes.getHistory(); const patternIncludesHistory = this.inputPatternIncludes.getHistory(); // store memento this.viewletSettings['query.contentPattern'] = contentPattern; this.viewletSettings['query.searchHistory'] = searchHistory; + this.viewletSettings['query.replaceHistory'] = replaceHistory; this.viewletSettings['query.regex'] = isRegex; this.viewletSettings['query.wholeWords'] = isWholeWords; this.viewletSettings['query.caseSensitive'] = isCaseSensitive; diff --git a/src/vs/workbench/parts/search/browser/searchWidget.ts b/src/vs/workbench/parts/search/browser/searchWidget.ts index 0b79c602d5b..c2ae258908a 100644 --- a/src/vs/workbench/parts/search/browser/searchWidget.ts +++ b/src/vs/workbench/parts/search/browser/searchWidget.ts @@ -38,8 +38,9 @@ export interface ISearchWidgetOptions { isRegex?: boolean; isCaseSensitive?: boolean; isWholeWords?: boolean; - history?: string[]; + searchHistory?: string[]; historyLimit?: number; + replaceHistory?: string[]; } class ReplaceAllAction extends Action { @@ -96,6 +97,7 @@ export class SearchWidget extends Widget { private replaceActionBar: ActionBar; private searchHistory: HistoryNavigator; + private replaceHistory: HistoryNavigator; private ignoreGlobalFindBufferOnNextFocus = false; private previousGlobalFindBufferValue: string; @@ -128,7 +130,8 @@ export class SearchWidget extends Widget { @IConfigurationService private configurationService: IConfigurationService ) { super(); - this.searchHistory = new HistoryNavigator(options.history, options.historyLimit); + this.searchHistory = new HistoryNavigator(options.searchHistory, options.historyLimit); + this.replaceHistory = new HistoryNavigator(options.replaceHistory, options.historyLimit); this.replaceActive = Constants.ReplaceActiveKey.bindTo(this.keyBindingService); this.searchInputBoxFocused = Constants.SearchInputBoxFocusedKey.bindTo(this.keyBindingService); this.replaceInputBoxFocused = Constants.ReplaceInputBoxFocusedKey.bindTo(this.keyBindingService); @@ -176,10 +179,14 @@ export class SearchWidget extends Widget { } } - public getHistory(): string[] { + public getSearchHistory(): string[] { return this.searchHistory.getHistory(); } + public getReplaceHistory(): string[] { + return this.replaceHistory.getHistory(); + } + public clearHistory(): void { this.searchHistory.clear(); } @@ -204,6 +211,26 @@ export class SearchWidget extends Widget { } } + public showNextReplaceTerm() { + let next = this.replaceHistory.next(); + if (next) { + this.replaceInput.value = next; + } + } + + public showPreviousReplaceTerm() { + let previous; + if (this.replaceInput.value.length === 0) { + previous = this.replaceHistory.current(); + } else { + this.replaceHistory.addIfNotPresent(this.replaceInput.value); + previous = this.replaceHistory.previous(); + } + if (previous) { + this.replaceInput.value = previous; + } + } + public searchInputHasFocus(): boolean { return this.searchInputBoxFocused.get(); } @@ -256,6 +283,12 @@ export class SearchWidget extends Widget { this.searchHistory.add(this.searchInput.getValue()); })); + this._register(this.onReplaceValueChanged(() => { + if ((this.replaceHistory.current() !== this.replaceInput.value) && (this.replaceInput.value)) { + this.replaceHistory.add(this.replaceInput.value); + } + })); + this.searchInputFocusTracker = this._register(dom.trackFocus(this.searchInput.inputBox.inputElement)); this._register(this.searchInputFocusTracker.onDidFocus(() => { this.searchInputBoxFocused.set(true); diff --git a/src/vs/workbench/parts/search/electron-browser/search.contribution.ts b/src/vs/workbench/parts/search/electron-browser/search.contribution.ts index 6f1d4ed9b57..a14b8b8df43 100644 --- a/src/vs/workbench/parts/search/electron-browser/search.contribution.ts +++ b/src/vs/workbench/parts/search/electron-browser/search.contribution.ts @@ -53,7 +53,7 @@ import { getMultiSelectedResources } from 'vs/workbench/parts/files/browser/file import { Schemas } from 'vs/base/common/network'; import { PanelRegistry, Extensions as PanelExtensions, PanelDescriptor } from 'vs/workbench/browser/panel'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; -import { openSearchView, getSearchView, ReplaceAllInFolderAction, ReplaceAllAction, CloseReplaceAction, FocusNextInputAction, FocusPreviousInputAction, FocusNextSearchResultAction, FocusPreviousSearchResultAction, ReplaceInFilesAction, FindInFilesAction, FocusActiveEditorCommand, toggleCaseSensitiveCommand, ShowNextSearchTermAction, ShowPreviousSearchTermAction, toggleRegexCommand, ShowPreviousSearchIncludeAction, ShowNextSearchIncludeAction, CollapseDeepestExpandedLevelAction, toggleWholeWordCommand, RemoveAction, ReplaceAction, ClearSearchResultsAction, copyPathCommand, copyMatchCommand, copyAllCommand, ShowNextSearchExcludeAction, ShowPreviousSearchExcludeAction, clearHistoryCommand } from 'vs/workbench/parts/search/browser/searchActions'; +import { openSearchView, getSearchView, ReplaceAllInFolderAction, ReplaceAllAction, CloseReplaceAction, FocusNextInputAction, FocusPreviousInputAction, FocusNextSearchResultAction, FocusPreviousSearchResultAction, ReplaceInFilesAction, FindInFilesAction, FocusActiveEditorCommand, toggleCaseSensitiveCommand, ShowNextSearchTermAction, ShowPreviousSearchTermAction, toggleRegexCommand, ShowPreviousSearchIncludeAction, ShowNextSearchIncludeAction, CollapseDeepestExpandedLevelAction, toggleWholeWordCommand, RemoveAction, ReplaceAction, ClearSearchResultsAction, copyPathCommand, copyMatchCommand, copyAllCommand, ShowNextSearchExcludeAction, ShowPreviousSearchExcludeAction, clearHistoryCommand, ShowNextReplaceTermAction, ShowPreviousReplaceTermAction } from 'vs/workbench/parts/search/browser/searchActions'; import { VIEW_ID, ISearchConfigurationProperties } from 'vs/platform/search/common/search'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; @@ -493,6 +493,9 @@ KeybindingsRegistry.registerCommandAndKeybindingRule(objects.assign({ registry.registerWorkbenchAction(new SyncActionDescriptor(ShowNextSearchTermAction, ShowNextSearchTermAction.ID, ShowNextSearchTermAction.LABEL, ShowNextFindTermKeybinding, ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.SearchInputBoxFocusedKey)), 'Search: Show Next Search Term', category); registry.registerWorkbenchAction(new SyncActionDescriptor(ShowPreviousSearchTermAction, ShowPreviousSearchTermAction.ID, ShowPreviousSearchTermAction.LABEL, ShowPreviousFindTermKeybinding, ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.SearchInputBoxFocusedKey)), 'Search: Show Previous Search Term', category); +registry.registerWorkbenchAction(new SyncActionDescriptor(ShowNextReplaceTermAction, ShowNextReplaceTermAction.ID, ShowNextReplaceTermAction.LABEL, ShowNextFindTermKeybinding, ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.ReplaceInputBoxFocusedKey)), 'Search: Show Next Search Replace Term', category); +registry.registerWorkbenchAction(new SyncActionDescriptor(ShowPreviousReplaceTermAction, ShowPreviousReplaceTermAction.ID, ShowPreviousReplaceTermAction.LABEL, ShowPreviousFindTermKeybinding, ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.ReplaceInputBoxFocusedKey)), 'Search: Show Previous Search Replace Term', category); + registry.registerWorkbenchAction(new SyncActionDescriptor(ShowNextSearchIncludeAction, ShowNextSearchIncludeAction.ID, ShowNextSearchIncludeAction.LABEL, ShowNextFindTermKeybinding, ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.PatternIncludesFocusedKey)), 'Search: Show Next Search Include Pattern', category); registry.registerWorkbenchAction(new SyncActionDescriptor(ShowPreviousSearchIncludeAction, ShowPreviousSearchIncludeAction.ID, ShowPreviousSearchIncludeAction.LABEL, ShowPreviousFindTermKeybinding, ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.PatternIncludesFocusedKey)), 'Search: Show Previous Search Include Pattern', category); -- GitLab