diff --git a/src/vs/workbench/contrib/search/browser/patternInputWidget.ts b/src/vs/workbench/contrib/search/browser/patternInputWidget.ts index db21252644c4aa44df59028cb0bf6ffdd8726064..5cd836f67db651b2040008176893363a9d6e13f4 100644 --- a/src/vs/workbench/contrib/search/browser/patternInputWidget.ts +++ b/src/vs/workbench/contrib/search/browser/patternInputWidget.ts @@ -16,6 +16,9 @@ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { attachInputBoxStyler, attachCheckboxStyler } from 'vs/platform/theme/common/styler'; import { ContextScopedHistoryInputBox } from 'vs/platform/browser/contextScopedHistoryWidget'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { ISearchConfigurationProperties } from 'vs/workbench/services/search/common/search'; +import { Delayer } from 'vs/base/common/async'; export interface IOptions { placeholder?: string; @@ -23,6 +26,8 @@ export interface IOptions { validation?: IInputValidator; ariaLabel?: string; history?: string[]; + submitOnType?: boolean; + submitOnTypeDelay?: number; } export class PatternInputWidget extends Widget { @@ -38,14 +43,17 @@ export class PatternInputWidget extends Widget { private domNode!: HTMLElement; protected inputBox!: HistoryInputBox; - private _onSubmit = this._register(new Emitter()); - onSubmit: CommonEvent = this._onSubmit.event; + private _onSubmit = this._register(new Emitter()); + onSubmit: CommonEvent = this._onSubmit.event; - private _onCancel = this._register(new Emitter()); - onCancel: CommonEvent = this._onCancel.event; + private _onCancel = this._register(new Emitter()); + onCancel: CommonEvent = this._onCancel.event; + + private searchOnTypeDelayer: Delayer; constructor(parent: HTMLElement, private contextViewProvider: IContextViewProvider, options: IOptions = Object.create(null), @IThemeService protected themeService: IThemeService, + @IConfigurationService private configurationService: IConfigurationService, @IContextKeyService private readonly contextKeyService: IContextKeyService ) { super(); @@ -53,6 +61,8 @@ export class PatternInputWidget extends Widget { this.placeholder = options.placeholder || ''; this.ariaLabel = options.ariaLabel || nls.localize('defaultLabel', "input"); + this._register(this.searchOnTypeDelayer = new Delayer(this.searchConfig.searchOnTypeDebouncePeriod)); + this.render(options); parent.appendChild(this.domNode); @@ -139,6 +149,12 @@ export class PatternInputWidget extends Widget { this._register(attachInputBoxStyler(this.inputBox, this.themeService)); this.inputFocusTracker = dom.trackFocus(this.inputBox.inputElement); this.onkeyup(this.inputBox.inputElement, (keyboardEvent) => this.onInputKeyUp(keyboardEvent)); + this._register(this.inputBox.onDidChange(() => { + if (this.searchConfig.searchOnType) { + this._onCancel.fire(); + this.searchOnTypeDelayer.trigger(() => this._onSubmit.fire(), this.searchConfig.searchOnTypeDebouncePeriod); + } + })); const controls = document.createElement('div'); controls.className = 'controls'; @@ -154,15 +170,19 @@ export class PatternInputWidget extends Widget { private onInputKeyUp(keyboardEvent: IKeyboardEvent) { switch (keyboardEvent.keyCode) { case KeyCode.Enter: - this._onSubmit.fire(false); + this._onSubmit.fire(); return; case KeyCode.Escape: - this._onCancel.fire(false); + this._onCancel.fire(); return; default: return; } } + + get searchConfig() { + return this.configurationService.getValue('search'); + } } export class ExcludePatternInputWidget extends PatternInputWidget { @@ -172,9 +192,10 @@ export class ExcludePatternInputWidget extends PatternInputWidget { constructor(parent: HTMLElement, contextViewProvider: IContextViewProvider, options: IOptions = Object.create(null), @IThemeService themeService: IThemeService, + @IConfigurationService configurationService: IConfigurationService, @IContextKeyService contextKeyService: IContextKeyService ) { - super(parent, contextViewProvider, options, themeService, contextKeyService); + super(parent, contextViewProvider, options, themeService, configurationService, contextKeyService); } private useExcludesAndIgnoreFilesBox!: Checkbox; diff --git a/src/vs/workbench/contrib/search/browser/searchView.ts b/src/vs/workbench/contrib/search/browser/searchView.ts index d64839689de5b36a0e4bbc10fed7e36f3f9c401c..101fe76326bf71d4134f6947ef96f57877c7a868 100644 --- a/src/vs/workbench/contrib/search/browser/searchView.ts +++ b/src/vs/workbench/contrib/search/browser/searchView.ts @@ -268,7 +268,7 @@ export class SearchView extends ViewletPanel { this.inputPatternIncludes.setValue(patternIncludes); this.inputPatternIncludes.onSubmit(() => this.onQueryChanged(true)); - this.inputPatternIncludes.onCancel(() => this.viewModel.cancelSearch()); // Cancel search without focusing the search widget + this.inputPatternIncludes.onCancel(() => this.cancelSearch(false)); this.trackInputBox(this.inputPatternIncludes.inputFocusTracker, this.inputPatternIncludesFocused); // excludes list @@ -284,7 +284,7 @@ export class SearchView extends ViewletPanel { this.inputPatternExcludes.setUseExcludesAndIgnoreFiles(useExcludesAndIgnoreFiles); this.inputPatternExcludes.onSubmit(() => this.onQueryChanged(true)); - this.inputPatternExcludes.onCancel(() => this.viewModel.cancelSearch()); // Cancel search without focusing the search widget + this.inputPatternExcludes.onCancel(() => this.cancelSearch(false)); this.inputPatternExcludes.onChangeIgnoreBox(() => this.onQueryChanged(true)); this.trackInputBox(this.inputPatternExcludes.inputFocusTracker, this.inputPatternExclusionsFocused); diff --git a/src/vs/workbench/contrib/search/browser/searchWidget.ts b/src/vs/workbench/contrib/search/browser/searchWidget.ts index 485477fdd5edce023741c458ea6242a3610244b5..5aa020a689ecb0eee7dfbbfc8bb3ff0014e379b2 100644 --- a/src/vs/workbench/contrib/search/browser/searchWidget.ts +++ b/src/vs/workbench/contrib/search/browser/searchWidget.ts @@ -448,6 +448,11 @@ export class SearchWidget extends Widget { private onSearchInputChanged(): void { this.searchInput.clearMessage(); this.setReplaceAllActionState(false); + + if (this.searchConfiguration.searchOnType) { + this._onSearchCancel.fire({ focus: false }); + this._searchDelayer.trigger((() => this.submitSearch()), this.searchConfiguration.searchOnTypeDebouncePeriod); + } } private onSearchInputKeyDown(keyboardEvent: IKeyboardEvent) { @@ -482,18 +487,6 @@ export class SearchWidget extends Widget { else if (keyboardEvent.equals(KeyCode.DownArrow)) { stopPropagationForMultiLineDownwards(keyboardEvent, this.searchInput.getValue(), this.searchInput.domNode.querySelector('textarea')); } - - if ((keyboardEvent.browserEvent.key.length === 1 && !(keyboardEvent.ctrlKey || keyboardEvent.metaKey) || - keyboardEvent.equals(KeyCode.Backspace) || - keyboardEvent.equals(KeyCode.UpArrow) || - keyboardEvent.equals(KeyCode.DownArrow)) - && this.searchConfiguration.searchOnType) { - - // Check to see if this input changes the query, being either a printable key (`key` is length 1, and not modified), or backspace, or history scroll - // If so, trigger a new search eventually, and preemptively cancel the old one as it's results will soon be discarded anyways. - this._onSearchCancel.fire({ focus: false }); - this._searchDelayer.trigger((() => this.submitSearch())); - } } private onCaseSensitiveKeyDown(keyboardEvent: IKeyboardEvent) {