Skip to content

Commit dda38ca

Browse files
author
Jackson Kearl
authored
Make pattern inputs also trigger as you type (microsoft#84148)
1 parent 99baecd commit dda38ca

3 files changed

Lines changed: 35 additions & 21 deletions

File tree

src/vs/workbench/contrib/search/browser/patternInputWidget.ts

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,18 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
1616
import { attachInputBoxStyler, attachCheckboxStyler } from 'vs/platform/theme/common/styler';
1717
import { ContextScopedHistoryInputBox } from 'vs/platform/browser/contextScopedHistoryWidget';
1818
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
19+
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
20+
import { ISearchConfigurationProperties } from 'vs/workbench/services/search/common/search';
21+
import { Delayer } from 'vs/base/common/async';
1922

2023
export interface IOptions {
2124
placeholder?: string;
2225
width?: number;
2326
validation?: IInputValidator;
2427
ariaLabel?: string;
2528
history?: string[];
29+
submitOnType?: boolean;
30+
submitOnTypeDelay?: number;
2631
}
2732

2833
export class PatternInputWidget extends Widget {
@@ -38,21 +43,26 @@ export class PatternInputWidget extends Widget {
3843
private domNode!: HTMLElement;
3944
protected inputBox!: HistoryInputBox;
4045

41-
private _onSubmit = this._register(new Emitter<boolean>());
42-
onSubmit: CommonEvent<boolean> = this._onSubmit.event;
46+
private _onSubmit = this._register(new Emitter<void>());
47+
onSubmit: CommonEvent<void> = this._onSubmit.event;
4348

44-
private _onCancel = this._register(new Emitter<boolean>());
45-
onCancel: CommonEvent<boolean> = this._onCancel.event;
49+
private _onCancel = this._register(new Emitter<void>());
50+
onCancel: CommonEvent<void> = this._onCancel.event;
51+
52+
private searchOnTypeDelayer: Delayer<void>;
4653

4754
constructor(parent: HTMLElement, private contextViewProvider: IContextViewProvider, options: IOptions = Object.create(null),
4855
@IThemeService protected themeService: IThemeService,
56+
@IConfigurationService private configurationService: IConfigurationService,
4957
@IContextKeyService private readonly contextKeyService: IContextKeyService
5058
) {
5159
super();
5260
this.width = options.width || 100;
5361
this.placeholder = options.placeholder || '';
5462
this.ariaLabel = options.ariaLabel || nls.localize('defaultLabel', "input");
5563

64+
this._register(this.searchOnTypeDelayer = new Delayer(this.searchConfig.searchOnTypeDebouncePeriod));
65+
5666
this.render(options);
5767

5868
parent.appendChild(this.domNode);
@@ -139,6 +149,12 @@ export class PatternInputWidget extends Widget {
139149
this._register(attachInputBoxStyler(this.inputBox, this.themeService));
140150
this.inputFocusTracker = dom.trackFocus(this.inputBox.inputElement);
141151
this.onkeyup(this.inputBox.inputElement, (keyboardEvent) => this.onInputKeyUp(keyboardEvent));
152+
this._register(this.inputBox.onDidChange(() => {
153+
if (this.searchConfig.searchOnType) {
154+
this._onCancel.fire();
155+
this.searchOnTypeDelayer.trigger(() => this._onSubmit.fire(), this.searchConfig.searchOnTypeDebouncePeriod);
156+
}
157+
}));
142158

143159
const controls = document.createElement('div');
144160
controls.className = 'controls';
@@ -154,15 +170,19 @@ export class PatternInputWidget extends Widget {
154170
private onInputKeyUp(keyboardEvent: IKeyboardEvent) {
155171
switch (keyboardEvent.keyCode) {
156172
case KeyCode.Enter:
157-
this._onSubmit.fire(false);
173+
this._onSubmit.fire();
158174
return;
159175
case KeyCode.Escape:
160-
this._onCancel.fire(false);
176+
this._onCancel.fire();
161177
return;
162178
default:
163179
return;
164180
}
165181
}
182+
183+
get searchConfig() {
184+
return this.configurationService.getValue<ISearchConfigurationProperties>('search');
185+
}
166186
}
167187

168188
export class ExcludePatternInputWidget extends PatternInputWidget {
@@ -172,9 +192,10 @@ export class ExcludePatternInputWidget extends PatternInputWidget {
172192

173193
constructor(parent: HTMLElement, contextViewProvider: IContextViewProvider, options: IOptions = Object.create(null),
174194
@IThemeService themeService: IThemeService,
195+
@IConfigurationService configurationService: IConfigurationService,
175196
@IContextKeyService contextKeyService: IContextKeyService
176197
) {
177-
super(parent, contextViewProvider, options, themeService, contextKeyService);
198+
super(parent, contextViewProvider, options, themeService, configurationService, contextKeyService);
178199
}
179200

180201
private useExcludesAndIgnoreFilesBox!: Checkbox;

src/vs/workbench/contrib/search/browser/searchView.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ export class SearchView extends ViewletPanel {
268268
this.inputPatternIncludes.setValue(patternIncludes);
269269

270270
this.inputPatternIncludes.onSubmit(() => this.onQueryChanged(true));
271-
this.inputPatternIncludes.onCancel(() => this.viewModel.cancelSearch()); // Cancel search without focusing the search widget
271+
this.inputPatternIncludes.onCancel(() => this.cancelSearch(false));
272272
this.trackInputBox(this.inputPatternIncludes.inputFocusTracker, this.inputPatternIncludesFocused);
273273

274274
// excludes list
@@ -284,7 +284,7 @@ export class SearchView extends ViewletPanel {
284284
this.inputPatternExcludes.setUseExcludesAndIgnoreFiles(useExcludesAndIgnoreFiles);
285285

286286
this.inputPatternExcludes.onSubmit(() => this.onQueryChanged(true));
287-
this.inputPatternExcludes.onCancel(() => this.viewModel.cancelSearch()); // Cancel search without focusing the search widget
287+
this.inputPatternExcludes.onCancel(() => this.cancelSearch(false));
288288
this.inputPatternExcludes.onChangeIgnoreBox(() => this.onQueryChanged(true));
289289
this.trackInputBox(this.inputPatternExcludes.inputFocusTracker, this.inputPatternExclusionsFocused);
290290

src/vs/workbench/contrib/search/browser/searchWidget.ts

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,11 @@ export class SearchWidget extends Widget {
448448
private onSearchInputChanged(): void {
449449
this.searchInput.clearMessage();
450450
this.setReplaceAllActionState(false);
451+
452+
if (this.searchConfiguration.searchOnType) {
453+
this._onSearchCancel.fire({ focus: false });
454+
this._searchDelayer.trigger((() => this.submitSearch()), this.searchConfiguration.searchOnTypeDebouncePeriod);
455+
}
451456
}
452457

453458
private onSearchInputKeyDown(keyboardEvent: IKeyboardEvent) {
@@ -482,18 +487,6 @@ export class SearchWidget extends Widget {
482487
else if (keyboardEvent.equals(KeyCode.DownArrow)) {
483488
stopPropagationForMultiLineDownwards(keyboardEvent, this.searchInput.getValue(), this.searchInput.domNode.querySelector('textarea'));
484489
}
485-
486-
if ((keyboardEvent.browserEvent.key.length === 1 && !(keyboardEvent.ctrlKey || keyboardEvent.metaKey) ||
487-
keyboardEvent.equals(KeyCode.Backspace) ||
488-
keyboardEvent.equals(KeyCode.UpArrow) ||
489-
keyboardEvent.equals(KeyCode.DownArrow))
490-
&& this.searchConfiguration.searchOnType) {
491-
492-
// 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
493-
// If so, trigger a new search eventually, and preemptively cancel the old one as it's results will soon be discarded anyways.
494-
this._onSearchCancel.fire({ focus: false });
495-
this._searchDelayer.trigger((() => this.submitSearch()));
496-
}
497490
}
498491

499492
private onCaseSensitiveKeyDown(keyboardEvent: IKeyboardEvent) {

0 commit comments

Comments
 (0)