提交 6527ca29 编写于 作者: R Rob Lourens

Fix #48282 - increase size of search history buffer and add "Clear search history" command

上级 e0a44567
......@@ -65,6 +65,11 @@ export class HistoryNavigator<T> implements INavigator<T> {
return this._navigator.last();
}
public clear(): void {
this._initialize([]);
this._onChange();
}
private _onChange() {
this._reduceToLimit();
this._navigator = new ArrayNavigator(this._elements);
......
......@@ -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>): string[] {
let result = [];
historyNavigator.first();
......
......@@ -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<string>();
this.history = new HistoryNavigator<string>(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<string>(history);
public clearHistory(): void {
this.history.clear();
}
public onSearchSubmit(): void {
......
......@@ -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();
};
......@@ -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();
......
......@@ -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<string>(options.history);
this.searchHistory = new HistoryNavigator<string>(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) {
......
......@@ -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';
......
......@@ -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) => {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册