From 6527ca299ef4e7360f1f6d0274219998dd3a0e46 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 23 Apr 2018 11:30:16 -0700 Subject: [PATCH] Fix #48282 - increase size of search history buffer and add "Clear search history" command --- src/vs/base/common/history.ts | 5 ++ src/vs/base/test/common/history.test.ts | 55 +++++++++++-------- .../search/browser/patternInputWidget.ts | 8 ++- .../parts/search/browser/searchActions.ts | 10 +++- .../parts/search/browser/searchView.ts | 21 +++++-- .../parts/search/browser/searchWidget.ts | 7 ++- .../parts/search/common/constants.ts | 1 + .../electron-browser/search.contribution.ts | 15 ++++- 8 files changed, 87 insertions(+), 35 deletions(-) diff --git a/src/vs/base/common/history.ts b/src/vs/base/common/history.ts index bf71cca3ef1..b9993be4f3f 100644 --- a/src/vs/base/common/history.ts +++ b/src/vs/base/common/history.ts @@ -65,6 +65,11 @@ export class HistoryNavigator implements INavigator { return this._navigator.last(); } + public clear(): void { + this._initialize([]); + this._onChange(); + } + private _onChange() { this._reduceToLimit(); this._navigator = new ArrayNavigator(this._elements); diff --git a/src/vs/base/test/common/history.test.ts b/src/vs/base/test/common/history.test.ts index f8f3b388d3b..4cf1324146f 100644 --- a/src/vs/base/test/common/history.test.ts +++ b/src/vs/base/test/common/history.test.ts @@ -9,36 +9,36 @@ import { HistoryNavigator } from 'vs/base/common/history'; suite('History Navigator', () => { - test('create reduces the input to limit', function () { - let testObject = new HistoryNavigator(['1', '2', '3', '4'], 2); + test('create reduces the input to limit', () => { + const testObject = new HistoryNavigator(['1', '2', '3', '4'], 2); assert.deepEqual(['3', '4'], toArray(testObject)); }); - test('create sets the position to last', function () { - let testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); + test('create sets the position to last', () => { + const testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); assert.equal('4', testObject.current()); assert.equal(null, testObject.next()); assert.equal('3', testObject.previous()); }); - test('last returns last element', function () { - let testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); + test('last returns last element', () => { + const testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); testObject.first(); assert.equal('4', testObject.last()); }); - test('first returns first element', function () { - let testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); + test('first returns first element', () => { + const testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); assert.equal('2', testObject.first()); }); - test('next returns next element', function () { - let testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); + test('next returns next element', () => { + const testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); testObject.first(); @@ -47,16 +47,16 @@ suite('History Navigator', () => { assert.equal(null, testObject.next()); }); - test('previous returns previous element', function () { - let testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); + test('previous returns previous element', () => { + const testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); assert.equal('3', testObject.previous()); assert.equal('2', testObject.previous()); assert.equal(null, testObject.previous()); }); - test('next on last element returs null and remains on last', function () { - let testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); + test('next on last element returs null and remains on last', () => { + const testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); testObject.first(); testObject.last(); @@ -65,8 +65,8 @@ suite('History Navigator', () => { assert.equal(null, testObject.next()); }); - test('previous on first element returs null and remains on first', function () { - let testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); + test('previous on first element returs null and remains on first', () => { + const testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); testObject.first(); @@ -74,24 +74,24 @@ suite('History Navigator', () => { assert.equal(null, testObject.previous()); }); - test('add reduces the input to limit', function () { - let testObject = new HistoryNavigator(['1', '2', '3', '4'], 2); + test('add reduces the input to limit', () => { + const testObject = new HistoryNavigator(['1', '2', '3', '4'], 2); testObject.add('5'); assert.deepEqual(['4', '5'], toArray(testObject)); }); - test('adding existing element changes the position', function () { - let testObject = new HistoryNavigator(['1', '2', '3', '4'], 5); + test('adding existing element changes the position', () => { + const testObject = new HistoryNavigator(['1', '2', '3', '4'], 5); testObject.add('2'); assert.deepEqual(['1', '3', '4', '2'], toArray(testObject)); }); - test('add resets the navigator to last', function () { - let testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); + test('add resets the navigator to last', () => { + const testObject = new HistoryNavigator(['1', '2', '3', '4'], 3); testObject.first(); testObject.add('5'); @@ -100,14 +100,21 @@ suite('History Navigator', () => { assert.equal(null, testObject.next()); }); - test('adding an existing item changes the order', function () { - let testObject = new HistoryNavigator(['1', '2', '3']); + test('adding an existing item changes the order', () => { + const testObject = new HistoryNavigator(['1', '2', '3']); testObject.add('1'); assert.deepEqual(['2', '3', '1'], toArray(testObject)); }); + test('clear', () => { + const testObject = new HistoryNavigator(['a', 'b', 'c']); + assert.equal('c', testObject.current()); + testObject.clear(); + assert.equal(undefined, testObject.current()); + }); + function toArray(historyNavigator: HistoryNavigator): string[] { let result = []; historyNavigator.first(); diff --git a/src/vs/workbench/parts/search/browser/patternInputWidget.ts b/src/vs/workbench/parts/search/browser/patternInputWidget.ts index 2b900f9f3c9..d58686be4c2 100644 --- a/src/vs/workbench/parts/search/browser/patternInputWidget.ts +++ b/src/vs/workbench/parts/search/browser/patternInputWidget.ts @@ -21,6 +21,8 @@ export interface IOptions { width?: number; validation?: IInputValidator; ariaLabel?: string; + history?: string[]; + historyLimit?: number; } export class PatternInputWidget extends Widget { @@ -47,7 +49,7 @@ export class PatternInputWidget extends Widget { constructor(parent: HTMLElement, private contextViewProvider: IContextViewProvider, protected themeService: IThemeService, options: IOptions = Object.create(null)) { super(); - this.history = new HistoryNavigator(); + this.history = new HistoryNavigator(options.history || [], options.historyLimit); this.onOptionChange = null; this.width = options.width || 100; this.placeholder = options.placeholder || ''; @@ -123,8 +125,8 @@ export class PatternInputWidget extends Widget { return this.history.getHistory(); } - public setHistory(history: string[]) { - this.history = new HistoryNavigator(history); + public clearHistory(): void { + this.history.clear(); } public onSearchSubmit(): void { diff --git a/src/vs/workbench/parts/search/browser/searchActions.ts b/src/vs/workbench/parts/search/browser/searchActions.ts index 2b42bba2c68..a7ae367a32b 100644 --- a/src/vs/workbench/parts/search/browser/searchActions.ts +++ b/src/vs/workbench/parts/search/browser/searchActions.ts @@ -750,7 +750,7 @@ function allFolderMatchesToString(folderMatches: FolderMatch[], maxMatches: numb return folderResults.join(lineDelimiter + lineDelimiter); } -export const copyAllCommand: ICommandHandler = (accessor) => { +export const copyAllCommand: ICommandHandler = accessor => { const viewletService = accessor.get(IViewletService); const panelService = accessor.get(IPanelService); const clipboardService = accessor.get(IClipboardService); @@ -761,3 +761,11 @@ export const copyAllCommand: ICommandHandler = (accessor) => { const text = allFolderMatchesToString(root.folderMatches(), maxClipboardMatches); clipboardService.writeText(text); }; + +export const clearHistoryCommand: ICommandHandler = accessor => { + const viewletService = accessor.get(IViewletService); + const panelService = accessor.get(IPanelService); + const searchView = getSearchView(viewletService, panelService); + + searchView.clearHistory(); +}; diff --git a/src/vs/workbench/parts/search/browser/searchView.ts b/src/vs/workbench/parts/search/browser/searchView.ts index f367e4aae41..a2aab9a43d0 100644 --- a/src/vs/workbench/parts/search/browser/searchView.ts +++ b/src/vs/workbench/parts/search/browser/searchView.ts @@ -65,6 +65,8 @@ import { IPartService } from 'vs/workbench/services/part/common/partService'; export class SearchView extends Viewlet implements IViewlet, IPanel { + private static readonly MAX_HISTORY_ITEMS = 100; + private static readonly MAX_TEXT_RESULTS = 10000; private static readonly SHOW_REPLACE_STORAGE_KEY = 'vs.search.show.replace'; @@ -240,11 +242,12 @@ export class SearchView extends Viewlet implements IViewlet, IPanel { builder.element('h4', { text: title }); this.inputPatternIncludes = new PatternInputWidget(builder.getContainer(), this.contextViewService, this.themeService, { - ariaLabel: nls.localize('label.includes', 'Search Include Patterns') + ariaLabel: nls.localize('label.includes', 'Search Include Patterns'), + history: patternIncludesHistory, + historyLimit: SearchView.MAX_HISTORY_ITEMS }); this.inputPatternIncludes.setValue(patternIncludes); - this.inputPatternIncludes.setHistory(patternIncludesHistory); this.inputPatternIncludes .on(FindInput.OPTION_CHANGE, (e) => { @@ -262,12 +265,13 @@ export class SearchView extends Viewlet implements IViewlet, IPanel { builder.element('h4', { text: title }); this.inputPatternExcludes = new ExcludePatternInputWidget(builder.getContainer(), this.contextViewService, this.themeService, { - ariaLabel: nls.localize('label.excludes', 'Search Exclude Patterns') + ariaLabel: nls.localize('label.excludes', 'Search Exclude Patterns'), + history: patternExclusionsHistory, + historyLimit: SearchView.MAX_HISTORY_ITEMS }); this.inputPatternExcludes.setValue(patternExclusions); this.inputPatternExcludes.setUseExcludesAndIgnoreFiles(useExcludesAndIgnoreFiles); - this.inputPatternExcludes.setHistory(patternExclusionsHistory); this.inputPatternExcludes .on(FindInput.OPTION_CHANGE, (e) => { @@ -333,7 +337,8 @@ export class SearchView extends Viewlet implements IViewlet, IPanel { isRegex: isRegex, isCaseSensitive: isCaseSensitive, isWholeWords: isWholeWords, - history: searchHistory + history: searchHistory, + historyLimit: SearchView.MAX_HISTORY_ITEMS }); if (this.storageService.getBoolean(SearchView.SHOW_REPLACE_STORAGE_KEY, StorageScope.WORKSPACE, true)) { @@ -1500,6 +1505,12 @@ export class SearchView extends Viewlet implements IViewlet, IPanel { this.updateTitleArea(); } + public clearHistory(): void { + this.searchWidget.clearHistory(); + this.inputPatternExcludes.clearHistory(); + this.inputPatternIncludes.clearHistory(); + } + public shutdown(): void { const isRegex = this.searchWidget.searchInput.getRegex(); const isWholeWords = this.searchWidget.searchInput.getWholeWords(); diff --git a/src/vs/workbench/parts/search/browser/searchWidget.ts b/src/vs/workbench/parts/search/browser/searchWidget.ts index 4c4edcbcd6e..0b79c602d5b 100644 --- a/src/vs/workbench/parts/search/browser/searchWidget.ts +++ b/src/vs/workbench/parts/search/browser/searchWidget.ts @@ -39,6 +39,7 @@ export interface ISearchWidgetOptions { isCaseSensitive?: boolean; isWholeWords?: boolean; history?: string[]; + historyLimit?: number; } class ReplaceAllAction extends Action { @@ -127,7 +128,7 @@ export class SearchWidget extends Widget { @IConfigurationService private configurationService: IConfigurationService ) { super(); - this.searchHistory = new HistoryNavigator(options.history); + this.searchHistory = new HistoryNavigator(options.history, options.historyLimit); this.replaceActive = Constants.ReplaceActiveKey.bindTo(this.keyBindingService); this.searchInputBoxFocused = Constants.SearchInputBoxFocusedKey.bindTo(this.keyBindingService); this.replaceInputBoxFocused = Constants.ReplaceInputBoxFocusedKey.bindTo(this.keyBindingService); @@ -179,6 +180,10 @@ export class SearchWidget extends Widget { return this.searchHistory.getHistory(); } + public clearHistory(): void { + this.searchHistory.clear(); + } + public showNextSearchTerm() { let next = this.searchHistory.next(); if (next) { diff --git a/src/vs/workbench/parts/search/common/constants.ts b/src/vs/workbench/parts/search/common/constants.ts index b8ca4a9aa84..39abb302748 100644 --- a/src/vs/workbench/parts/search/common/constants.ts +++ b/src/vs/workbench/parts/search/common/constants.ts @@ -15,6 +15,7 @@ export const RemoveActionId = 'search.action.remove'; export const CopyPathCommandId = 'search.action.copyPath'; export const CopyMatchCommandId = 'search.action.copyMatch'; export const CopyAllCommandId = 'search.action.copyAll'; +export const ClearSearchHistoryCommandId = 'search.action.clearHistory'; export const ReplaceActionId = 'search.action.replace'; export const ReplaceAllInFileActionId = 'search.action.replaceAllInFile'; export const ReplaceAllInFolderActionId = 'search.action.replaceAllInFolder'; 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 b575b602528..c9c92f4e17a 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 } 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 } 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'; @@ -291,6 +291,19 @@ CommandsRegistry.registerCommand({ handler: copyAllCommand }); +CommandsRegistry.registerCommand({ + id: Constants.ClearSearchHistoryCommandId, + handler: clearHistoryCommand +}); + +const clearSearchHistoryLabel = nls.localize('clearSearchHistoryLabel', "Clear Search History"); +const ClearSearchHistoryCommand: ICommandAction = { + id: Constants.ClearSearchHistoryCommandId, + title: clearSearchHistoryLabel, + category +}; +MenuRegistry.addCommand(ClearSearchHistoryCommand); + CommandsRegistry.registerCommand({ id: Constants.ToggleSearchViewPositionCommandId, handler: (accessor) => { -- GitLab