@codingame/monaco-vscode-search-service-override 4.1.0 → 4.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/external/rollup-plugin-styles/dist/runtime/inject-css.js +3 -0
  2. package/external/tslib/tslib.es6.js +11 -0
  3. package/override/vs/platform/dialogs/common/dialogs.js +10 -0
  4. package/package.json +2 -2
  5. package/search.js +4 -4
  6. package/vscode/src/vs/workbench/contrib/search/browser/anythingQuickAccess.js +796 -0
  7. package/vscode/src/vs/workbench/contrib/search/browser/media/anythingQuickAccess.css.js +6 -0
  8. package/vscode/src/vs/workbench/contrib/search/browser/media/searchview.css.js +6 -0
  9. package/vscode/src/vs/workbench/contrib/search/browser/patternInputWidget.js +234 -0
  10. package/vscode/src/vs/workbench/contrib/search/browser/quickTextSearch/textSearchQuickAccess.js +341 -0
  11. package/vscode/src/vs/workbench/contrib/search/browser/replaceContributions.js +9 -0
  12. package/vscode/src/vs/workbench/contrib/search/browser/replaceService.js +232 -0
  13. package/vscode/src/vs/workbench/contrib/search/browser/search.contribution.js +647 -0
  14. package/vscode/src/vs/workbench/contrib/search/browser/searchActionsCopy.js +209 -0
  15. package/vscode/src/vs/workbench/contrib/search/browser/searchActionsNav.js +511 -0
  16. package/vscode/src/vs/workbench/contrib/search/browser/searchActionsRemoveReplace.js +374 -0
  17. package/vscode/src/vs/workbench/contrib/search/browser/searchActionsSymbol.js +43 -0
  18. package/vscode/src/vs/workbench/contrib/search/browser/searchActionsTextQuickAccess.js +44 -0
  19. package/vscode/src/vs/workbench/contrib/search/browser/searchActionsTopBar.js +323 -0
  20. package/vscode/src/vs/workbench/contrib/search/browser/searchFindInput.js +103 -0
  21. package/vscode/src/vs/workbench/contrib/search/browser/searchIcons.js +106 -0
  22. package/vscode/src/vs/workbench/contrib/search/browser/searchMessage.js +66 -0
  23. package/vscode/src/vs/workbench/contrib/search/browser/searchResultsView.js +437 -0
  24. package/vscode/src/vs/workbench/contrib/search/browser/searchView.js +2177 -0
  25. package/vscode/src/vs/workbench/contrib/search/browser/searchWidget.js +674 -0
  26. package/vscode/src/vs/workbench/contrib/search/browser/symbolsQuickAccess.js +234 -0
  27. package/vscode/src/vs/workbench/contrib/search/common/cacheState.js +87 -0
  28. package/vscode/src/vs/workbench/contrib/searchEditor/browser/media/searchEditor.css.js +6 -0
  29. package/vscode/src/vs/workbench/contrib/searchEditor/browser/searchEditor.contribution.js +586 -0
  30. package/vscode/src/vs/workbench/contrib/searchEditor/browser/searchEditor.js +760 -0
  31. package/vscode/src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.js +189 -0
  32. package/vscode/src/vs/workbench/contrib/searchEditor/browser/searchEditorInput.js +320 -0
  33. package/vscode/src/vs/workbench/contrib/searchEditor/browser/searchEditorModel.js +138 -0
  34. package/vscode/src/vs/workbench/contrib/searchEditor/browser/searchEditorSerialization.js +293 -0
  35. package/vscode/src/vs/workbench/services/search/common/searchService.js +416 -0
@@ -0,0 +1,2177 @@
1
+ import { __decorate, __param } from '../../../../../../../external/tslib/tslib.es6.js';
2
+ import { $ as $$1, hide, append, addDisposableListener, EventType, EventHelper, clearNode, show, getActiveWindow, getTotalHeight, Dimension, isAncestorOfActiveElement } from 'vscode/vscode/vs/base/browser/dom';
3
+ import { StandardKeyboardEvent } from 'vscode/vscode/vs/base/browser/keyboardEvent';
4
+ import { status } from 'vscode/vscode/vs/base/browser/ui/aria/aria';
5
+ import { ObjectTreeElementCollapseState } from 'vscode/vscode/vs/base/browser/ui/tree/tree';
6
+ import { Delayer, RunOnceScheduler } from 'vscode/vscode/vs/base/common/async';
7
+ import { isCancellationError, onUnexpectedError } from 'vscode/vscode/vs/base/common/errors';
8
+ import { Event } from 'vscode/vscode/vs/base/common/event';
9
+ import { Iterable } from 'vscode/vscode/vs/base/common/iterator';
10
+ import { DisposableStore, Disposable } from 'vscode/vscode/vs/base/common/lifecycle';
11
+ import { isMacintosh, isNative } from 'vscode/vscode/vs/base/common/platform';
12
+ import { escapeRegExpCharacters } from 'vscode/vscode/vs/base/common/strings';
13
+ import { URI } from 'vscode/vscode/vs/base/common/uri';
14
+ import { Schemas } from 'vscode/vscode/vs/base/common/network';
15
+ import './media/searchview.css.js';
16
+ import { isCodeEditor, getCodeEditor, isDiffEditor } from 'vscode/vscode/vs/editor/browser/editorBrowser';
17
+ import { ICodeEditorService } from 'vscode/vscode/vs/editor/browser/services/codeEditorService';
18
+ import { EmbeddedCodeEditorWidget } from 'vscode/vscode/vs/editor/browser/widget/codeEditor/embeddedCodeEditorWidget';
19
+ import { Selection } from 'vscode/vscode/vs/editor/common/core/selection';
20
+ import { CommonFindController } from 'vscode/vscode/vs/editor/contrib/find/browser/findController';
21
+ import { MultiCursorSelectionController } from 'vscode/vscode/vs/editor/contrib/multicursor/browser/multicursor';
22
+ import { localizeWithPath } from 'vscode/vscode/vs/nls';
23
+ import { IAccessibilityService } from 'vscode/vscode/vs/platform/accessibility/common/accessibility';
24
+ import { MenuId } from 'vscode/vscode/vs/platform/actions/common/actions';
25
+ import { ICommandService } from 'vscode/vscode/vs/platform/commands/common/commands';
26
+ import { IConfigurationService } from 'vscode/vscode/vs/platform/configuration/common/configuration';
27
+ import { IContextKeyService } from 'vscode/vscode/vs/platform/contextkey/common/contextkey';
28
+ import { IContextViewService, IContextMenuService } from 'vscode/vscode/vs/platform/contextview/browser/contextView';
29
+ import '../../../../../../../override/vs/platform/dialogs/common/dialogs.js';
30
+ import { IFileService } from 'vscode/vscode/vs/platform/files/common/files';
31
+ import { IInstantiationService } from 'vscode/vscode/vs/platform/instantiation/common/instantiation';
32
+ import { ServiceCollection } from 'vscode/vscode/vs/platform/instantiation/common/serviceCollection';
33
+ import { IKeybindingService } from 'vscode/vscode/vs/platform/keybinding/common/keybinding';
34
+ import { WorkbenchCompressibleObjectTree, getSelectionKeyboardEvent } from 'vscode/vscode/vs/platform/list/browser/listService';
35
+ import { INotificationService } from 'vscode/vscode/vs/platform/notification/common/notification';
36
+ import { withSelection, IOpenerService } from 'vscode/vscode/vs/platform/opener/common/opener';
37
+ import { IProgressService } from 'vscode/vscode/vs/platform/progress/common/progress';
38
+ import { IStorageService } from 'vscode/vscode/vs/platform/storage/common/storage';
39
+ import { ITelemetryService } from 'vscode/vscode/vs/platform/telemetry/common/telemetry';
40
+ import { defaultInputBoxStyles, defaultToggleStyles } from 'vscode/vscode/vs/platform/theme/browser/defaultStyles';
41
+ import { IThemeService } from 'vscode/vscode/vs/platform/theme/common/themeService';
42
+ import { ThemeIcon } from 'vscode/vscode/vs/base/common/themables';
43
+ import { IWorkspaceContextService } from 'vscode/vscode/vs/platform/workspace/common/workspace';
44
+ import { OpenFileFolderAction, OpenFolderAction } from 'vscode/vscode/vs/workbench/browser/actions/workspaceActions';
45
+ import { ResourceListDnDHandler } from 'vscode/vscode/vs/workbench/browser/dnd';
46
+ import { ResourceLabels } from 'vscode/vscode/vs/workbench/browser/labels';
47
+ import { ViewPane } from 'vscode/vscode/vs/workbench/browser/parts/views/viewPane';
48
+ import { Memento } from 'vscode/vscode/vs/workbench/common/memento';
49
+ import { IViewDescriptorService } from 'vscode/vscode/vs/workbench/common/views';
50
+ import { NotebookEditor } from 'vscode/vscode/vs/workbench/contrib/notebook/browser/notebookEditor';
51
+ import { IncludePatternInputWidget, ExcludePatternInputWidget } from './patternInputWidget.js';
52
+ import { appendKeyBindingLabel } from 'vscode/vscode/vs/workbench/contrib/search/browser/searchActionsBase';
53
+ import { searchDetailsIcon } from './searchIcons.js';
54
+ import { renderSearchMessage } from './searchMessage.js';
55
+ import { SearchAccessibilityProvider, SearchDelegate, FolderMatchRenderer, FileMatchRenderer, MatchRenderer } from './searchResultsView.js';
56
+ import { SearchWidget } from './searchWidget.js';
57
+ import { SearchContext } from 'vscode/vscode/vs/workbench/contrib/search/common/constants';
58
+ import { IReplaceService } from 'vscode/vscode/vs/workbench/contrib/search/browser/replace';
59
+ import { SearchStateKey, SearchUIState, getOutOfWorkspaceEditorResources } from 'vscode/vscode/vs/workbench/contrib/search/common/search';
60
+ import { SearchHistoryService, ISearchHistoryService } from 'vscode/vscode/vs/workbench/contrib/search/common/searchHistoryService';
61
+ import { SearchModelLocation, searchMatchComparer, FileMatch, SearchResult, FolderMatch, Match, FolderMatchWithResource, MatchInNotebook, ISearchViewModelWorkbenchService } from 'vscode/vscode/vs/workbench/contrib/search/browser/searchModel';
62
+ import { createEditorFromSearchResult } from '../../searchEditor/browser/searchEditorActions.js';
63
+ import { SIDE_GROUP, ACTIVE_GROUP, IEditorService } from 'vscode/vscode/vs/workbench/services/editor/common/editorService';
64
+ import { IPreferencesService } from 'vscode/vscode/vs/workbench/services/preferences/common/preferences';
65
+ import { QueryBuilder } from 'vscode/vscode/vs/workbench/services/search/common/queryBuilder';
66
+ import 'vscode/vscode/vs/workbench/services/search/common/search';
67
+ import { ITextFileService } from 'vscode/vscode/vs/workbench/services/textfile/common/textfiles';
68
+ import { INotebookService } from 'vscode/vscode/vs/workbench/contrib/notebook/common/notebookService';
69
+ import { ILogService } from 'vscode/vscode/vs/platform/log/common/log';
70
+ import { AccessibilitySignal, IAccessibilitySignalService } from 'vscode/vscode/vs/platform/accessibilitySignal/browser/accessibilitySignalService';
71
+ import { setupCustomHover } from 'vscode/vscode/vs/base/browser/ui/hover/updatableHoverWidget';
72
+ import { getDefaultHoverDelegate } from 'vscode/vscode/vs/base/browser/ui/hover/hoverDelegateFactory';
73
+ import { TextSearchCompleteMessageType } from 'vscode/vscode/vs/workbench/services/search/common/searchExtTypes';
74
+ import { IDialogService } from 'vscode/vscode/vs/platform/dialogs/common/dialogs';
75
+
76
+ var SearchView_1;
77
+ const $ = $$1;
78
+ const SEARCH_CANCELLED_MESSAGE = ( localizeWithPath(
79
+ 'vs/workbench/contrib/search/browser/searchView',
80
+ 'searchCanceled',
81
+ "Search was canceled before any results could be found - "
82
+ ));
83
+ const DEBOUNCE_DELAY = 75;
84
+ let SearchView = class SearchView extends ViewPane {
85
+ static { SearchView_1 = this; }
86
+ static { this.ACTIONS_RIGHT_CLASS_NAME = 'actions-right'; }
87
+ constructor(options, fileService, editorService, codeEditorService, progressService, notificationService, dialogService, commandService, contextViewService, instantiationService, viewDescriptorService, configurationService, contextService, searchViewModelWorkbenchService, contextKeyService, replaceService, textFileService, preferencesService, themeService, searchHistoryService, contextMenuService, accessibilityService, keybindingService, storageService, openerService, telemetryService, notebookService, logService, accessibilitySignalService) {
88
+ super(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService);
89
+ this.fileService = fileService;
90
+ this.editorService = editorService;
91
+ this.codeEditorService = codeEditorService;
92
+ this.progressService = progressService;
93
+ this.notificationService = notificationService;
94
+ this.dialogService = dialogService;
95
+ this.commandService = commandService;
96
+ this.contextViewService = contextViewService;
97
+ this.contextService = contextService;
98
+ this.searchViewModelWorkbenchService = searchViewModelWorkbenchService;
99
+ this.replaceService = replaceService;
100
+ this.textFileService = textFileService;
101
+ this.preferencesService = preferencesService;
102
+ this.searchHistoryService = searchHistoryService;
103
+ this.accessibilityService = accessibilityService;
104
+ this.storageService = storageService;
105
+ this.notebookService = notebookService;
106
+ this.logService = logService;
107
+ this.accessibilitySignalService = accessibilitySignalService;
108
+ this.isDisposed = false;
109
+ this.lastFocusState = 'input';
110
+ this.messageDisposables = ( new DisposableStore());
111
+ this.changedWhileHidden = false;
112
+ this.currentSearchQ = Promise.resolve();
113
+ this.pauseSearching = false;
114
+ this._visibleMatches = 0;
115
+ this.container = $$1('.search-view');
116
+ this.viewletVisible = SearchContext.SearchViewVisibleKey.bindTo(this.contextKeyService);
117
+ this.firstMatchFocused = SearchContext.FirstMatchFocusKey.bindTo(this.contextKeyService);
118
+ this.fileMatchOrMatchFocused = SearchContext.FileMatchOrMatchFocusKey.bindTo(this.contextKeyService);
119
+ this.fileMatchOrFolderMatchFocus = SearchContext.FileMatchOrFolderMatchFocusKey.bindTo(this.contextKeyService);
120
+ this.fileMatchOrFolderMatchWithResourceFocus = SearchContext.FileMatchOrFolderMatchWithResourceFocusKey.bindTo(this.contextKeyService);
121
+ this.fileMatchFocused = SearchContext.FileFocusKey.bindTo(this.contextKeyService);
122
+ this.folderMatchFocused = SearchContext.FolderFocusKey.bindTo(this.contextKeyService);
123
+ this.folderMatchWithResourceFocused = SearchContext.ResourceFolderFocusKey.bindTo(this.contextKeyService);
124
+ this.hasSearchResultsKey = SearchContext.HasSearchResults.bindTo(this.contextKeyService);
125
+ this.matchFocused = SearchContext.MatchFocusKey.bindTo(this.contextKeyService);
126
+ this.searchStateKey = SearchStateKey.bindTo(this.contextKeyService);
127
+ this.hasSearchPatternKey = SearchContext.ViewHasSearchPatternKey.bindTo(this.contextKeyService);
128
+ this.hasReplacePatternKey = SearchContext.ViewHasReplacePatternKey.bindTo(this.contextKeyService);
129
+ this.hasFilePatternKey = SearchContext.ViewHasFilePatternKey.bindTo(this.contextKeyService);
130
+ this.hasSomeCollapsibleResultKey = SearchContext.ViewHasSomeCollapsibleKey.bindTo(this.contextKeyService);
131
+ this.treeViewKey = SearchContext.InTreeViewKey.bindTo(this.contextKeyService);
132
+ this.aiResultsVisibleKey = SearchContext.AIResultsVisibleKey.bindTo(this.contextKeyService);
133
+ this._register(this.contextKeyService.onDidChangeContext(e => {
134
+ const keys = ( SearchContext.hasAIResultProvider.keys());
135
+ if (e.affectsSome(( new Set(keys)))) {
136
+ this.refreshHasAISetting();
137
+ }
138
+ }));
139
+ this.contextKeyService = this._register(this.contextKeyService.createScoped(this.container));
140
+ SearchContext.SearchViewFocusedKey.bindTo(this.contextKeyService).set(true);
141
+ this.inputBoxFocused = SearchContext.InputBoxFocusedKey.bindTo(this.contextKeyService);
142
+ this.inputPatternIncludesFocused = SearchContext.PatternIncludesFocusedKey.bindTo(this.contextKeyService);
143
+ this.inputPatternExclusionsFocused = SearchContext.PatternExcludesFocusedKey.bindTo(this.contextKeyService);
144
+ this.isEditableItem = SearchContext.IsEditableItemKey.bindTo(this.contextKeyService);
145
+ this.instantiationService = this.instantiationService.createChild(( new ServiceCollection([IContextKeyService, this.contextKeyService])));
146
+ this._register(this.configurationService.onDidChangeConfiguration(e => {
147
+ if (e.affectsConfiguration('search.sortOrder')) {
148
+ if (this.searchConfig.sortOrder === "modified" ) {
149
+ this.removeFileStats();
150
+ }
151
+ this.refreshTree();
152
+ }
153
+ else if (e.affectsConfiguration('search.aiResults')) {
154
+ this.refreshHasAISetting();
155
+ }
156
+ }));
157
+ this.viewModel = this._register(this.searchViewModelWorkbenchService.searchModel);
158
+ this.queryBuilder = this.instantiationService.createInstance(QueryBuilder);
159
+ this.memento = ( new Memento(this.id, storageService));
160
+ this.viewletState = this.memento.getMemento(1 , 1 );
161
+ this._register(this.fileService.onDidFilesChange(e => this.onFilesChanged(e)));
162
+ this._register(this.textFileService.untitled.onWillDispose(model => this.onUntitledDidDispose(model.resource)));
163
+ this._register(this.contextService.onDidChangeWorkbenchState(() => this.onDidChangeWorkbenchState()));
164
+ this._register(this.searchHistoryService.onDidClearHistory(() => this.clearHistory()));
165
+ this._register(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated(e)));
166
+ this.delayedRefresh = this._register(( new Delayer(250)));
167
+ this.addToSearchHistoryDelayer = this._register(( new Delayer(2000)));
168
+ this.toggleCollapseStateDelayer = this._register(( new Delayer(100)));
169
+ this.triggerQueryDelayer = this._register(( new Delayer(0)));
170
+ this.treeAccessibilityProvider = this.instantiationService.createInstance(SearchAccessibilityProvider, this);
171
+ this.isTreeLayoutViewVisible = this.viewletState['view.treeLayout'] ?? ((this.searchConfig.defaultViewMode === "tree") );
172
+ this._refreshResultsScheduler = this._register(( new RunOnceScheduler(this._updateResults.bind(this), 80)));
173
+ this._register(this.storageService.onWillSaveState(() => {
174
+ this._saveSearchHistoryService();
175
+ }));
176
+ this._register(this.storageService.onDidChangeValue(1 , SearchHistoryService.SEARCH_HISTORY_KEY, this._register(( new DisposableStore())))(() => {
177
+ const restoredHistory = this.searchHistoryService.load();
178
+ if (restoredHistory.include) {
179
+ this.inputPatternIncludes.prependHistory(restoredHistory.include);
180
+ }
181
+ if (restoredHistory.exclude) {
182
+ this.inputPatternExcludes.prependHistory(restoredHistory.exclude);
183
+ }
184
+ if (restoredHistory.search) {
185
+ this.searchWidget.prependSearchHistory(restoredHistory.search);
186
+ }
187
+ if (restoredHistory.replace) {
188
+ this.searchWidget.prependReplaceHistory(restoredHistory.replace);
189
+ }
190
+ }));
191
+ }
192
+ get isTreeLayoutViewVisible() {
193
+ return this.treeViewKey.get() ?? false;
194
+ }
195
+ set isTreeLayoutViewVisible(visible) {
196
+ this.treeViewKey.set(visible);
197
+ }
198
+ get aiResultsVisible() {
199
+ return this.aiResultsVisibleKey.get() ?? false;
200
+ }
201
+ set aiResultsVisible(visible) {
202
+ this.aiResultsVisibleKey.set(visible);
203
+ }
204
+ setTreeView(visible) {
205
+ if (visible === this.isTreeLayoutViewVisible) {
206
+ return;
207
+ }
208
+ this.isTreeLayoutViewVisible = visible;
209
+ this.updateIndentStyles(this.themeService.getFileIconTheme());
210
+ this.refreshTree();
211
+ }
212
+ async setAIResultsVisible(visible) {
213
+ if (visible === this.aiResultsVisible) {
214
+ return;
215
+ }
216
+ this.aiResultsVisible = visible;
217
+ if (this.viewModel.searchResult.isEmpty()) {
218
+ return;
219
+ }
220
+ this.model.cancelAISearch();
221
+ if (visible) {
222
+ await this.model.addAIResults();
223
+ }
224
+ else {
225
+ this.searchWidget.toggleReplace(false);
226
+ }
227
+ this.onSearchResultsChanged();
228
+ this.onSearchComplete(() => { }, undefined, undefined, this.viewModel.searchResult.getCachedSearchComplete(visible));
229
+ }
230
+ get state() {
231
+ return this.searchStateKey.get() ?? SearchUIState.Idle;
232
+ }
233
+ set state(v) {
234
+ this.searchStateKey.set(v);
235
+ }
236
+ getContainer() {
237
+ return this.container;
238
+ }
239
+ get searchResult() {
240
+ return this.viewModel && this.viewModel.searchResult;
241
+ }
242
+ get model() {
243
+ return this.viewModel;
244
+ }
245
+ refreshHasAISetting() {
246
+ const val = this.shouldShowAIButton();
247
+ if (val && this.searchWidget.searchInput) {
248
+ this.searchWidget.searchInput.shouldShowAIButton = val;
249
+ }
250
+ }
251
+ onDidChangeWorkbenchState() {
252
+ if (this.contextService.getWorkbenchState() !== 1 && this.searchWithoutFolderMessageElement) {
253
+ hide(this.searchWithoutFolderMessageElement);
254
+ }
255
+ }
256
+ refreshInputs() {
257
+ this.pauseSearching = true;
258
+ this.searchWidget.setValue(this.viewModel.searchResult.query?.contentPattern.pattern ?? '');
259
+ this.searchWidget.setReplaceAllActionState(false);
260
+ this.searchWidget.toggleReplace(true);
261
+ this.inputPatternIncludes.setOnlySearchInOpenEditors(this.viewModel.searchResult.query?.onlyOpenEditors || false);
262
+ this.inputPatternExcludes.setUseExcludesAndIgnoreFiles(!this.viewModel.searchResult.query?.userDisabledExcludesAndIgnoreFiles || true);
263
+ this.searchIncludePattern.setValue('');
264
+ this.searchExcludePattern.setValue('');
265
+ this.pauseSearching = false;
266
+ }
267
+ async replaceSearchModel(searchModel, asyncResults) {
268
+ let progressComplete;
269
+ this.progressService.withProgress({ location: this.getProgressLocation(), delay: 0 }, _progress => {
270
+ return ( new Promise(resolve => progressComplete = resolve));
271
+ });
272
+ const slowTimer = setTimeout(() => {
273
+ this.state = SearchUIState.SlowSearch;
274
+ }, 2000);
275
+ this._refreshResultsScheduler.schedule();
276
+ searchModel.location = SearchModelLocation.PANEL;
277
+ searchModel.replaceActive = this.viewModel.isReplaceActive();
278
+ searchModel.replaceString = this.searchWidget.getReplaceValue();
279
+ this._onSearchResultChangedDisposable?.dispose();
280
+ this._onSearchResultChangedDisposable = this._register(searchModel.onSearchResultChanged((event) => this.onSearchResultsChanged(event)));
281
+ this.searchViewModelWorkbenchService.searchModel = searchModel;
282
+ this.viewModel = searchModel;
283
+ this.onSearchResultsChanged();
284
+ this.refreshInputs();
285
+ asyncResults.then((complete) => {
286
+ clearTimeout(slowTimer);
287
+ this.onSearchComplete(progressComplete, undefined, undefined, complete);
288
+ }, (e) => {
289
+ clearTimeout(slowTimer);
290
+ this.onSearchError(e, progressComplete, undefined, undefined);
291
+ });
292
+ const collapseResults = this.searchConfig.collapseResults;
293
+ if (collapseResults !== 'alwaysCollapse' && this.viewModel.searchResult.matches(this.aiResultsVisible).length === 1) {
294
+ const onlyMatch = this.viewModel.searchResult.matches(this.aiResultsVisible)[0];
295
+ if (onlyMatch.count() < 50) {
296
+ this.tree.expand(onlyMatch);
297
+ }
298
+ }
299
+ }
300
+ renderBody(parent) {
301
+ super.renderBody(parent);
302
+ this.container = append(parent, $$1('.search-view'));
303
+ this.searchWidgetsContainerElement = append(this.container, $('.search-widgets-container'));
304
+ this.createSearchWidget(this.searchWidgetsContainerElement);
305
+ this.refreshHasAISetting();
306
+ const history = this.searchHistoryService.load();
307
+ const filePatterns = this.viewletState['query.filePatterns'] || '';
308
+ const patternExclusions = this.viewletState['query.folderExclusions'] || '';
309
+ const patternExclusionsHistory = history.exclude || [];
310
+ const patternIncludes = this.viewletState['query.folderIncludes'] || '';
311
+ const patternIncludesHistory = history.include || [];
312
+ const onlyOpenEditors = this.viewletState['query.onlyOpenEditors'] || false;
313
+ const queryDetailsExpanded = this.viewletState['query.queryDetailsExpanded'] || '';
314
+ const useExcludesAndIgnoreFiles = typeof this.viewletState['query.useExcludesAndIgnoreFiles'] === 'boolean' ?
315
+ this.viewletState['query.useExcludesAndIgnoreFiles'] : true;
316
+ this.queryDetails = append(this.searchWidgetsContainerElement, $('.query-details'));
317
+ this.toggleQueryDetailsButton = append(this.queryDetails, $('.more' + ThemeIcon.asCSSSelector(searchDetailsIcon), { tabindex: 0, role: 'button' }));
318
+ this._register(setupCustomHover(getDefaultHoverDelegate('element'), this.toggleQueryDetailsButton, ( localizeWithPath(
319
+ 'vs/workbench/contrib/search/browser/searchView',
320
+ 'moreSearch',
321
+ "Toggle Search Details"
322
+ ))));
323
+ this._register(addDisposableListener(this.toggleQueryDetailsButton, EventType.CLICK, e => {
324
+ EventHelper.stop(e);
325
+ this.toggleQueryDetails(!this.accessibilityService.isScreenReaderOptimized());
326
+ }));
327
+ this._register(addDisposableListener(this.toggleQueryDetailsButton, EventType.KEY_UP, (e) => {
328
+ const event = ( new StandardKeyboardEvent(e));
329
+ if (event.equals(3 ) || event.equals(10 )) {
330
+ EventHelper.stop(e);
331
+ this.toggleQueryDetails(false);
332
+ }
333
+ }));
334
+ this._register(addDisposableListener(this.toggleQueryDetailsButton, EventType.KEY_DOWN, (e) => {
335
+ const event = ( new StandardKeyboardEvent(e));
336
+ if (event.equals(1024 | 2 )) {
337
+ if (this.searchWidget.isReplaceActive()) {
338
+ this.searchWidget.focusReplaceAllAction();
339
+ }
340
+ else {
341
+ this.searchWidget.isReplaceShown() ? this.searchWidget.replaceInput?.focusOnPreserve() : this.searchWidget.focusRegexAction();
342
+ }
343
+ EventHelper.stop(e);
344
+ }
345
+ }));
346
+ const folderIncludesList = append(this.queryDetails, $('.file-types.includes'));
347
+ const filesToIncludeTitle = ( localizeWithPath(
348
+ 'vs/workbench/contrib/search/browser/searchView',
349
+ 'searchScope.includes',
350
+ "files to include"
351
+ ));
352
+ append(folderIncludesList, $('h4', undefined, filesToIncludeTitle));
353
+ this.inputPatternIncludes = this._register(this.instantiationService.createInstance(IncludePatternInputWidget, folderIncludesList, this.contextViewService, {
354
+ ariaLabel: filesToIncludeTitle,
355
+ placeholder: ( localizeWithPath(
356
+ 'vs/workbench/contrib/search/browser/searchView',
357
+ 'placeholder.includes',
358
+ "e.g. *.ts, src/**/include"
359
+ )),
360
+ showPlaceholderOnFocus: true,
361
+ history: patternIncludesHistory,
362
+ inputBoxStyles: defaultInputBoxStyles
363
+ }));
364
+ this.inputPatternIncludes.setValue(patternIncludes);
365
+ this.inputPatternIncludes.setOnlySearchInOpenEditors(onlyOpenEditors);
366
+ this._register(this.inputPatternIncludes.onCancel(() => this.cancelSearch(false)));
367
+ this._register(this.inputPatternIncludes.onChangeSearchInEditorsBox(() => this.triggerQueryChange()));
368
+ this.trackInputBox(this.inputPatternIncludes.inputFocusTracker, this.inputPatternIncludesFocused);
369
+ const excludesList = append(this.queryDetails, $('.file-types.excludes'));
370
+ const excludesTitle = ( localizeWithPath(
371
+ 'vs/workbench/contrib/search/browser/searchView',
372
+ 'searchScope.excludes',
373
+ "files to exclude"
374
+ ));
375
+ append(excludesList, $('h4', undefined, excludesTitle));
376
+ this.inputPatternExcludes = this._register(this.instantiationService.createInstance(ExcludePatternInputWidget, excludesList, this.contextViewService, {
377
+ ariaLabel: excludesTitle,
378
+ placeholder: ( localizeWithPath(
379
+ 'vs/workbench/contrib/search/browser/searchView',
380
+ 'placeholder.excludes',
381
+ "e.g. *.ts, src/**/exclude"
382
+ )),
383
+ showPlaceholderOnFocus: true,
384
+ history: patternExclusionsHistory,
385
+ inputBoxStyles: defaultInputBoxStyles
386
+ }));
387
+ this.inputPatternExcludes.setValue(patternExclusions);
388
+ this.inputPatternExcludes.setUseExcludesAndIgnoreFiles(useExcludesAndIgnoreFiles);
389
+ this._register(this.inputPatternExcludes.onCancel(() => this.cancelSearch(false)));
390
+ this._register(this.inputPatternExcludes.onChangeIgnoreBox(() => this.triggerQueryChange()));
391
+ this.trackInputBox(this.inputPatternExcludes.inputFocusTracker, this.inputPatternExclusionsFocused);
392
+ const updateHasFilePatternKey = () => this.hasFilePatternKey.set(this.inputPatternIncludes.getValue().length > 0 || this.inputPatternExcludes.getValue().length > 0);
393
+ updateHasFilePatternKey();
394
+ const onFilePatternSubmit = (triggeredOnType) => {
395
+ this.triggerQueryChange({ triggeredOnType, delay: this.searchConfig.searchOnTypeDebouncePeriod });
396
+ if (triggeredOnType) {
397
+ updateHasFilePatternKey();
398
+ }
399
+ };
400
+ this._register(this.inputPatternIncludes.onSubmit(onFilePatternSubmit));
401
+ this._register(this.inputPatternExcludes.onSubmit(onFilePatternSubmit));
402
+ this.messagesElement = append(this.container, $('.messages.text-search-provider-messages'));
403
+ if (this.contextService.getWorkbenchState() === 1 ) {
404
+ this.showSearchWithoutFolderMessage();
405
+ }
406
+ this.createSearchResultsView(this.container);
407
+ if (filePatterns !== '' || patternExclusions !== '' || patternIncludes !== '' || queryDetailsExpanded !== '' || !useExcludesAndIgnoreFiles) {
408
+ this.toggleQueryDetails(true, true, true);
409
+ }
410
+ this._onSearchResultChangedDisposable = this._register(this.viewModel.onSearchResultChanged((event) => this.onSearchResultsChanged(event)));
411
+ this._register(this.onDidChangeBodyVisibility(visible => this.onVisibilityChanged(visible)));
412
+ this.updateIndentStyles(this.themeService.getFileIconTheme());
413
+ this._register(this.themeService.onDidFileIconThemeChange(this.updateIndentStyles, this));
414
+ }
415
+ updateIndentStyles(theme) {
416
+ this.resultsElement.classList.toggle('hide-arrows', this.isTreeLayoutViewVisible && theme.hidesExplorerArrows);
417
+ }
418
+ onVisibilityChanged(visible) {
419
+ this.viewletVisible.set(visible);
420
+ if (visible) {
421
+ if (this.changedWhileHidden) {
422
+ this.refreshAndUpdateCount();
423
+ this.changedWhileHidden = false;
424
+ }
425
+ }
426
+ else {
427
+ this.lastFocusState = 'input';
428
+ }
429
+ this.viewModel?.searchResult.toggleHighlights(visible);
430
+ }
431
+ get searchAndReplaceWidget() {
432
+ return this.searchWidget;
433
+ }
434
+ get searchIncludePattern() {
435
+ return this.inputPatternIncludes;
436
+ }
437
+ get searchExcludePattern() {
438
+ return this.inputPatternExcludes;
439
+ }
440
+ createSearchWidget(container) {
441
+ const contentPattern = this.viewletState['query.contentPattern'] || '';
442
+ const replaceText = this.viewletState['query.replaceText'] || '';
443
+ const isRegex = this.viewletState['query.regex'] === true;
444
+ const isWholeWords = this.viewletState['query.wholeWords'] === true;
445
+ const isCaseSensitive = this.viewletState['query.caseSensitive'] === true;
446
+ const history = this.searchHistoryService.load();
447
+ const searchHistory = history.search || this.viewletState['query.searchHistory'] || [];
448
+ const replaceHistory = history.replace || this.viewletState['query.replaceHistory'] || [];
449
+ const showReplace = typeof this.viewletState['view.showReplace'] === 'boolean' ? this.viewletState['view.showReplace'] : true;
450
+ const preserveCase = this.viewletState['query.preserveCase'] === true;
451
+ const isInNotebookMarkdownInput = this.viewletState['query.isInNotebookMarkdownInput'] ?? true;
452
+ const isInNotebookMarkdownPreview = this.viewletState['query.isInNotebookMarkdownPreview'] ?? true;
453
+ const isInNotebookCellInput = this.viewletState['query.isInNotebookCellInput'] ?? true;
454
+ const isInNotebookCellOutput = this.viewletState['query.isInNotebookCellOutput'] ?? true;
455
+ this.searchWidget = this._register(this.instantiationService.createInstance(SearchWidget, container, {
456
+ value: contentPattern,
457
+ replaceValue: replaceText,
458
+ isRegex: isRegex,
459
+ isCaseSensitive: isCaseSensitive,
460
+ isWholeWords: isWholeWords,
461
+ searchHistory: searchHistory,
462
+ replaceHistory: replaceHistory,
463
+ preserveCase: preserveCase,
464
+ inputBoxStyles: defaultInputBoxStyles,
465
+ toggleStyles: defaultToggleStyles,
466
+ notebookOptions: {
467
+ isInNotebookMarkdownInput,
468
+ isInNotebookMarkdownPreview,
469
+ isInNotebookCellInput,
470
+ isInNotebookCellOutput,
471
+ },
472
+ initialAIButtonVisibility: this.shouldShowAIButton()
473
+ }));
474
+ if (!this.searchWidget.searchInput || !this.searchWidget.replaceInput) {
475
+ this.logService.warn(`Cannot fully create search widget. Search or replace input undefined. SearchInput: ${this.searchWidget.searchInput}, ReplaceInput: ${this.searchWidget.replaceInput}`);
476
+ return;
477
+ }
478
+ if (showReplace) {
479
+ this.searchWidget.toggleReplace(true);
480
+ }
481
+ this._register(this.searchWidget.onSearchSubmit(options => this.triggerQueryChange(options)));
482
+ this._register(this.searchWidget.onSearchCancel(({ focus }) => this.cancelSearch(focus)));
483
+ this._register(this.searchWidget.searchInput.onDidOptionChange(() => {
484
+ if (this.searchWidget.searchInput && this.searchWidget.searchInput.isAIEnabled !== this.aiResultsVisible) {
485
+ this.setAIResultsVisible(this.searchWidget.searchInput.isAIEnabled);
486
+ }
487
+ else {
488
+ this.triggerQueryChange();
489
+ }
490
+ }));
491
+ this._register(this.searchWidget.getNotebookFilters().onDidChange(() => this.triggerQueryChange()));
492
+ const updateHasPatternKey = () => this.hasSearchPatternKey.set(this.searchWidget.searchInput ? (this.searchWidget.searchInput.getValue().length > 0) : false);
493
+ updateHasPatternKey();
494
+ this._register(this.searchWidget.searchInput.onDidChange(() => updateHasPatternKey()));
495
+ const updateHasReplacePatternKey = () => this.hasReplacePatternKey.set(this.searchWidget.getReplaceValue().length > 0);
496
+ updateHasReplacePatternKey();
497
+ this._register(this.searchWidget.replaceInput.inputBox.onDidChange(() => updateHasReplacePatternKey()));
498
+ this._register(this.searchWidget.onDidHeightChange(() => this.reLayout()));
499
+ this._register(this.searchWidget.onReplaceToggled(() => this.reLayout()));
500
+ this._register(this.searchWidget.onReplaceStateChange((state) => {
501
+ this.viewModel.replaceActive = state;
502
+ this.refreshTree();
503
+ }));
504
+ this._register(this.searchWidget.onPreserveCaseChange((state) => {
505
+ this.viewModel.preserveCase = state;
506
+ this.refreshTree();
507
+ }));
508
+ this._register(this.searchWidget.onReplaceValueChanged(() => {
509
+ this.viewModel.replaceString = this.searchWidget.getReplaceValue();
510
+ this.delayedRefresh.trigger(() => this.refreshTree());
511
+ }));
512
+ this._register(this.searchWidget.onBlur(() => {
513
+ this.toggleQueryDetailsButton.focus();
514
+ }));
515
+ this._register(this.searchWidget.onReplaceAll(() => this.replaceAll()));
516
+ this.trackInputBox(this.searchWidget.searchInputFocusTracker);
517
+ this.trackInputBox(this.searchWidget.replaceInputFocusTracker);
518
+ }
519
+ shouldShowAIButton() {
520
+ const hasProvider = SearchContext.hasAIResultProvider.getValue(this.contextKeyService);
521
+ return !!(this.configurationService.getValue('search.aiResults') && hasProvider);
522
+ }
523
+ onConfigurationUpdated(event) {
524
+ if (event && (event.affectsConfiguration('search.decorations.colors') || event.affectsConfiguration('search.decorations.badges'))) {
525
+ this.refreshTree();
526
+ }
527
+ }
528
+ trackInputBox(inputFocusTracker, contextKey) {
529
+ if (!inputFocusTracker) {
530
+ return;
531
+ }
532
+ this._register(inputFocusTracker.onDidFocus(() => {
533
+ this.lastFocusState = 'input';
534
+ this.inputBoxFocused.set(true);
535
+ contextKey?.set(true);
536
+ }));
537
+ this._register(inputFocusTracker.onDidBlur(() => {
538
+ this.inputBoxFocused.set(this.searchWidget.searchInputHasFocus()
539
+ || this.searchWidget.replaceInputHasFocus()
540
+ || this.inputPatternIncludes.inputHasFocus()
541
+ || this.inputPatternExcludes.inputHasFocus());
542
+ contextKey?.set(false);
543
+ }));
544
+ }
545
+ onSearchResultsChanged(event) {
546
+ if (this.isVisible()) {
547
+ return this.refreshAndUpdateCount(event);
548
+ }
549
+ else {
550
+ this.changedWhileHidden = true;
551
+ }
552
+ }
553
+ refreshAndUpdateCount(event) {
554
+ this.searchWidget.setReplaceAllActionState(!this.viewModel.searchResult.isEmpty(this.aiResultsVisible));
555
+ this.updateSearchResultCount(this.viewModel.searchResult.query.userDisabledExcludesAndIgnoreFiles, this.viewModel.searchResult.query?.onlyOpenEditors, event?.clearingAll);
556
+ return this.refreshTree(event);
557
+ }
558
+ refreshTree(event) {
559
+ const collapseResults = this.searchConfig.collapseResults;
560
+ if (!event || event.added || event.removed) {
561
+ if (this.searchConfig.sortOrder === "modified" ) {
562
+ this.retrieveFileStats()
563
+ .then(() => this.tree.setChildren(null, this.createResultIterator(collapseResults)));
564
+ }
565
+ else {
566
+ this.tree.setChildren(null, this.createResultIterator(collapseResults));
567
+ }
568
+ }
569
+ else {
570
+ if (this.searchConfig.sortOrder === "countAscending" ||
571
+ this.searchConfig.sortOrder === "countDescending" ) {
572
+ this.tree.setChildren(null, this.createResultIterator(collapseResults));
573
+ }
574
+ else {
575
+ event.elements.forEach(element => {
576
+ this.tree.setChildren(element, this.createIterator(element, collapseResults));
577
+ this.tree.rerender(element);
578
+ });
579
+ }
580
+ }
581
+ }
582
+ createResultIterator(collapseResults) {
583
+ const folderMatches = this.searchResult.folderMatches(this.aiResultsVisible)
584
+ .filter(fm => !fm.isEmpty())
585
+ .sort(searchMatchComparer);
586
+ if (folderMatches.length === 1) {
587
+ return this.createFolderIterator(folderMatches[0], collapseResults, true);
588
+ }
589
+ return ( Iterable.map(folderMatches, folderMatch => {
590
+ const children = this.createFolderIterator(folderMatch, collapseResults, true);
591
+ return { element: folderMatch, children, incompressible: true };
592
+ }));
593
+ }
594
+ createFolderIterator(folderMatch, collapseResults, childFolderIncompressible) {
595
+ const sortOrder = this.searchConfig.sortOrder;
596
+ const matchArray = this.isTreeLayoutViewVisible ? folderMatch.matches() : folderMatch.allDownstreamFileMatches();
597
+ const matches = matchArray.sort((a, b) => searchMatchComparer(a, b, sortOrder));
598
+ return ( Iterable.map(matches, match => {
599
+ let children;
600
+ if (match instanceof FileMatch) {
601
+ children = this.createFileIterator(match);
602
+ }
603
+ else {
604
+ children = this.createFolderIterator(match, collapseResults, false);
605
+ }
606
+ const collapsed = (collapseResults === 'alwaysCollapse' || (match.count() > 10 && collapseResults !== 'alwaysExpand')) ? ObjectTreeElementCollapseState.PreserveOrCollapsed : ObjectTreeElementCollapseState.PreserveOrExpanded;
607
+ return { element: match, children, collapsed, incompressible: (match instanceof FileMatch) ? true : childFolderIncompressible };
608
+ }));
609
+ }
610
+ createFileIterator(fileMatch) {
611
+ let matches = fileMatch.matches().sort(searchMatchComparer);
612
+ if (!this.aiResultsVisible) {
613
+ matches = matches.filter(e => !e.aiContributed);
614
+ }
615
+ return ( Iterable.map(matches, r => ({ element: r, incompressible: true })));
616
+ }
617
+ createIterator(match, collapseResults) {
618
+ return match instanceof SearchResult ? this.createResultIterator(collapseResults) :
619
+ match instanceof FolderMatch ? this.createFolderIterator(match, collapseResults, false) :
620
+ this.createFileIterator(match);
621
+ }
622
+ replaceAll() {
623
+ if (this.viewModel.searchResult.count() === 0) {
624
+ return;
625
+ }
626
+ const occurrences = this.viewModel.searchResult.count();
627
+ const fileCount = this.viewModel.searchResult.fileCount();
628
+ const replaceValue = this.searchWidget.getReplaceValue() || '';
629
+ const afterReplaceAllMessage = this.buildAfterReplaceAllMessage(occurrences, fileCount, replaceValue);
630
+ let progressComplete;
631
+ let progressReporter;
632
+ this.progressService.withProgress({ location: this.getProgressLocation(), delay: 100, total: occurrences }, p => {
633
+ progressReporter = p;
634
+ return ( new Promise(resolve => progressComplete = resolve));
635
+ });
636
+ const confirmation = {
637
+ title: ( localizeWithPath(
638
+ 'vs/workbench/contrib/search/browser/searchView',
639
+ 'replaceAll.confirmation.title',
640
+ "Replace All"
641
+ )),
642
+ message: this.buildReplaceAllConfirmationMessage(occurrences, fileCount, replaceValue),
643
+ primaryButton: ( localizeWithPath(
644
+ 'vs/workbench/contrib/search/browser/searchView',
645
+ { key: 'replaceAll.confirm.button', comment: ['&& denotes a mnemonic'] },
646
+ "&&Replace"
647
+ ))
648
+ };
649
+ this.dialogService.confirm(confirmation).then(res => {
650
+ if (res.confirmed) {
651
+ this.searchWidget.setReplaceAllActionState(false);
652
+ this.viewModel.searchResult.replaceAll(progressReporter).then(() => {
653
+ progressComplete();
654
+ const messageEl = this.clearMessage();
655
+ append(messageEl, afterReplaceAllMessage);
656
+ this.reLayout();
657
+ }, (error) => {
658
+ progressComplete();
659
+ this.notificationService.error(error);
660
+ });
661
+ }
662
+ else {
663
+ progressComplete();
664
+ }
665
+ });
666
+ }
667
+ buildAfterReplaceAllMessage(occurrences, fileCount, replaceValue) {
668
+ if (occurrences === 1) {
669
+ if (fileCount === 1) {
670
+ if (replaceValue) {
671
+ return ( localizeWithPath(
672
+ 'vs/workbench/contrib/search/browser/searchView',
673
+ 'replaceAll.occurrence.file.message',
674
+ "Replaced {0} occurrence across {1} file with '{2}'.",
675
+ occurrences,
676
+ fileCount,
677
+ replaceValue
678
+ ));
679
+ }
680
+ return ( localizeWithPath(
681
+ 'vs/workbench/contrib/search/browser/searchView',
682
+ 'removeAll.occurrence.file.message',
683
+ "Replaced {0} occurrence across {1} file.",
684
+ occurrences,
685
+ fileCount
686
+ ));
687
+ }
688
+ if (replaceValue) {
689
+ return ( localizeWithPath(
690
+ 'vs/workbench/contrib/search/browser/searchView',
691
+ 'replaceAll.occurrence.files.message',
692
+ "Replaced {0} occurrence across {1} files with '{2}'.",
693
+ occurrences,
694
+ fileCount,
695
+ replaceValue
696
+ ));
697
+ }
698
+ return ( localizeWithPath(
699
+ 'vs/workbench/contrib/search/browser/searchView',
700
+ 'removeAll.occurrence.files.message',
701
+ "Replaced {0} occurrence across {1} files.",
702
+ occurrences,
703
+ fileCount
704
+ ));
705
+ }
706
+ if (fileCount === 1) {
707
+ if (replaceValue) {
708
+ return ( localizeWithPath(
709
+ 'vs/workbench/contrib/search/browser/searchView',
710
+ 'replaceAll.occurrences.file.message',
711
+ "Replaced {0} occurrences across {1} file with '{2}'.",
712
+ occurrences,
713
+ fileCount,
714
+ replaceValue
715
+ ));
716
+ }
717
+ return ( localizeWithPath(
718
+ 'vs/workbench/contrib/search/browser/searchView',
719
+ 'removeAll.occurrences.file.message',
720
+ "Replaced {0} occurrences across {1} file.",
721
+ occurrences,
722
+ fileCount
723
+ ));
724
+ }
725
+ if (replaceValue) {
726
+ return ( localizeWithPath(
727
+ 'vs/workbench/contrib/search/browser/searchView',
728
+ 'replaceAll.occurrences.files.message',
729
+ "Replaced {0} occurrences across {1} files with '{2}'.",
730
+ occurrences,
731
+ fileCount,
732
+ replaceValue
733
+ ));
734
+ }
735
+ return ( localizeWithPath(
736
+ 'vs/workbench/contrib/search/browser/searchView',
737
+ 'removeAll.occurrences.files.message',
738
+ "Replaced {0} occurrences across {1} files.",
739
+ occurrences,
740
+ fileCount
741
+ ));
742
+ }
743
+ buildReplaceAllConfirmationMessage(occurrences, fileCount, replaceValue) {
744
+ if (occurrences === 1) {
745
+ if (fileCount === 1) {
746
+ if (replaceValue) {
747
+ return ( localizeWithPath(
748
+ 'vs/workbench/contrib/search/browser/searchView',
749
+ 'removeAll.occurrence.file.confirmation.message',
750
+ "Replace {0} occurrence across {1} file with '{2}'?",
751
+ occurrences,
752
+ fileCount,
753
+ replaceValue
754
+ ));
755
+ }
756
+ return ( localizeWithPath(
757
+ 'vs/workbench/contrib/search/browser/searchView',
758
+ 'replaceAll.occurrence.file.confirmation.message',
759
+ "Replace {0} occurrence across {1} file?",
760
+ occurrences,
761
+ fileCount
762
+ ));
763
+ }
764
+ if (replaceValue) {
765
+ return ( localizeWithPath(
766
+ 'vs/workbench/contrib/search/browser/searchView',
767
+ 'removeAll.occurrence.files.confirmation.message',
768
+ "Replace {0} occurrence across {1} files with '{2}'?",
769
+ occurrences,
770
+ fileCount,
771
+ replaceValue
772
+ ));
773
+ }
774
+ return ( localizeWithPath(
775
+ 'vs/workbench/contrib/search/browser/searchView',
776
+ 'replaceAll.occurrence.files.confirmation.message',
777
+ "Replace {0} occurrence across {1} files?",
778
+ occurrences,
779
+ fileCount
780
+ ));
781
+ }
782
+ if (fileCount === 1) {
783
+ if (replaceValue) {
784
+ return ( localizeWithPath(
785
+ 'vs/workbench/contrib/search/browser/searchView',
786
+ 'removeAll.occurrences.file.confirmation.message',
787
+ "Replace {0} occurrences across {1} file with '{2}'?",
788
+ occurrences,
789
+ fileCount,
790
+ replaceValue
791
+ ));
792
+ }
793
+ return ( localizeWithPath(
794
+ 'vs/workbench/contrib/search/browser/searchView',
795
+ 'replaceAll.occurrences.file.confirmation.message',
796
+ "Replace {0} occurrences across {1} file?",
797
+ occurrences,
798
+ fileCount
799
+ ));
800
+ }
801
+ if (replaceValue) {
802
+ return ( localizeWithPath(
803
+ 'vs/workbench/contrib/search/browser/searchView',
804
+ 'removeAll.occurrences.files.confirmation.message',
805
+ "Replace {0} occurrences across {1} files with '{2}'?",
806
+ occurrences,
807
+ fileCount,
808
+ replaceValue
809
+ ));
810
+ }
811
+ return ( localizeWithPath(
812
+ 'vs/workbench/contrib/search/browser/searchView',
813
+ 'replaceAll.occurrences.files.confirmation.message',
814
+ "Replace {0} occurrences across {1} files?",
815
+ occurrences,
816
+ fileCount
817
+ ));
818
+ }
819
+ clearMessage() {
820
+ this.searchWithoutFolderMessageElement = undefined;
821
+ const wasHidden = this.messagesElement.style.display === 'none';
822
+ clearNode(this.messagesElement);
823
+ show(this.messagesElement);
824
+ this.messageDisposables.clear();
825
+ const newMessage = append(this.messagesElement, $('.message'));
826
+ if (wasHidden) {
827
+ this.reLayout();
828
+ }
829
+ return newMessage;
830
+ }
831
+ createSearchResultsView(container) {
832
+ this.resultsElement = append(container, $('.results.show-file-icons.file-icon-themable-tree'));
833
+ const delegate = this.instantiationService.createInstance(SearchDelegate);
834
+ const identityProvider = {
835
+ getId(element) {
836
+ return element.id();
837
+ }
838
+ };
839
+ this.treeLabels = this._register(this.instantiationService.createInstance(ResourceLabels, { onDidChangeVisibility: this.onDidChangeBodyVisibility }));
840
+ this.tree = this._register(this.instantiationService.createInstance(WorkbenchCompressibleObjectTree, 'SearchView', this.resultsElement, delegate, [
841
+ this._register(this.instantiationService.createInstance(FolderMatchRenderer, this, this.treeLabels)),
842
+ this._register(this.instantiationService.createInstance(FileMatchRenderer, this, this.treeLabels)),
843
+ this._register(this.instantiationService.createInstance(MatchRenderer, this)),
844
+ ], {
845
+ identityProvider,
846
+ accessibilityProvider: this.treeAccessibilityProvider,
847
+ dnd: this.instantiationService.createInstance(ResourceListDnDHandler, element => {
848
+ if (element instanceof FileMatch) {
849
+ return element.resource;
850
+ }
851
+ if (element instanceof Match) {
852
+ return withSelection(element.parent().resource, element.range());
853
+ }
854
+ return null;
855
+ }),
856
+ multipleSelectionSupport: true,
857
+ selectionNavigation: true,
858
+ overrideStyles: {
859
+ listBackground: this.getBackgroundColor()
860
+ },
861
+ paddingBottom: SearchDelegate.ITEM_HEIGHT
862
+ }));
863
+ this._register(this.tree.onContextMenu(e => this.onContextMenu(e)));
864
+ const updateHasSomeCollapsible = () => this.toggleCollapseStateDelayer.trigger(() => this.hasSomeCollapsibleResultKey.set(this.hasSomeCollapsible()));
865
+ updateHasSomeCollapsible();
866
+ this._register(this.tree.onDidChangeCollapseState(() => updateHasSomeCollapsible()));
867
+ this._register(this.tree.onDidChangeModel(() => updateHasSomeCollapsible()));
868
+ this._register(Event.debounce(this.tree.onDidOpen, (last, event) => event, DEBOUNCE_DELAY, true)(options => {
869
+ if (options.element instanceof Match) {
870
+ const selectedMatch = options.element;
871
+ this.currentSelectedFileMatch?.setSelectedMatch(null);
872
+ this.currentSelectedFileMatch = selectedMatch.parent();
873
+ this.currentSelectedFileMatch.setSelectedMatch(selectedMatch);
874
+ this.onFocus(selectedMatch, options.editorOptions.preserveFocus, options.sideBySide, options.editorOptions.pinned);
875
+ }
876
+ }));
877
+ this._register(Event.debounce(this.tree.onDidChangeFocus, (last, event) => event, DEBOUNCE_DELAY, true)(() => {
878
+ const selection = this.tree.getSelection();
879
+ const focus = this.tree.getFocus()[0];
880
+ if (selection.length > 1 && focus instanceof Match) {
881
+ this.onFocus(focus, true);
882
+ }
883
+ }));
884
+ this._register(Event.any(this.tree.onDidFocus, this.tree.onDidChangeFocus)(() => {
885
+ const focus = this.tree.getFocus()[0];
886
+ if (this.tree.isDOMFocused()) {
887
+ this.firstMatchFocused.set(this.tree.navigate().first() === focus);
888
+ this.fileMatchOrMatchFocused.set(!!focus);
889
+ this.fileMatchFocused.set(focus instanceof FileMatch);
890
+ this.folderMatchFocused.set(focus instanceof FolderMatch);
891
+ this.matchFocused.set(focus instanceof Match);
892
+ this.fileMatchOrFolderMatchFocus.set(focus instanceof FileMatch || focus instanceof FolderMatch);
893
+ this.fileMatchOrFolderMatchWithResourceFocus.set(focus instanceof FileMatch || focus instanceof FolderMatchWithResource);
894
+ this.folderMatchWithResourceFocused.set(focus instanceof FolderMatchWithResource);
895
+ this.lastFocusState = 'tree';
896
+ }
897
+ let editable = false;
898
+ if (focus instanceof Match) {
899
+ editable = (focus instanceof MatchInNotebook) ? !focus.isReadonly() : true;
900
+ }
901
+ else if (focus instanceof FileMatch) {
902
+ editable = !focus.hasOnlyReadOnlyMatches();
903
+ }
904
+ else if (focus instanceof FolderMatch) {
905
+ editable = !focus.hasOnlyReadOnlyMatches();
906
+ }
907
+ this.isEditableItem.set(editable);
908
+ }));
909
+ this._register(this.tree.onDidBlur(() => {
910
+ this.firstMatchFocused.reset();
911
+ this.fileMatchOrMatchFocused.reset();
912
+ this.fileMatchFocused.reset();
913
+ this.folderMatchFocused.reset();
914
+ this.matchFocused.reset();
915
+ this.fileMatchOrFolderMatchFocus.reset();
916
+ this.fileMatchOrFolderMatchWithResourceFocus.reset();
917
+ this.folderMatchWithResourceFocused.reset();
918
+ this.isEditableItem.reset();
919
+ }));
920
+ }
921
+ onContextMenu(e) {
922
+ e.browserEvent.preventDefault();
923
+ e.browserEvent.stopPropagation();
924
+ this.contextMenuService.showContextMenu({
925
+ menuId: MenuId.SearchContext,
926
+ menuActionOptions: { shouldForwardArgs: true },
927
+ contextKeyService: this.contextKeyService,
928
+ getAnchor: () => e.anchor,
929
+ getActionsContext: () => e.element,
930
+ });
931
+ }
932
+ hasSomeCollapsible() {
933
+ const viewer = this.getControl();
934
+ const navigator = viewer.navigate();
935
+ let node = navigator.first();
936
+ do {
937
+ if (!viewer.isCollapsed(node)) {
938
+ return true;
939
+ }
940
+ } while (node = navigator.next());
941
+ return false;
942
+ }
943
+ selectNextMatch() {
944
+ if (!this.hasSearchResults()) {
945
+ return;
946
+ }
947
+ const [selected] = this.tree.getSelection();
948
+ if (selected && !(selected instanceof Match)) {
949
+ if (this.tree.isCollapsed(selected)) {
950
+ this.tree.expand(selected);
951
+ }
952
+ }
953
+ const navigator = this.tree.navigate(selected);
954
+ let next = navigator.next();
955
+ if (!next) {
956
+ next = navigator.first();
957
+ }
958
+ while (next && !(next instanceof Match)) {
959
+ if (this.tree.isCollapsed(next)) {
960
+ this.tree.expand(next);
961
+ }
962
+ next = navigator.next();
963
+ }
964
+ if (next) {
965
+ if (next === selected) {
966
+ this.tree.setFocus([]);
967
+ }
968
+ const event = getSelectionKeyboardEvent(undefined, false, false);
969
+ this.tree.setFocus([next], event);
970
+ this.tree.setSelection([next], event);
971
+ this.tree.reveal(next);
972
+ const ariaLabel = this.treeAccessibilityProvider.getAriaLabel(next);
973
+ if (ariaLabel) {
974
+ status(ariaLabel);
975
+ }
976
+ }
977
+ }
978
+ selectPreviousMatch() {
979
+ if (!this.hasSearchResults()) {
980
+ return;
981
+ }
982
+ const [selected] = this.tree.getSelection();
983
+ let navigator = this.tree.navigate(selected);
984
+ let prev = navigator.previous();
985
+ while (!prev || (!(prev instanceof Match) && !this.tree.isCollapsed(prev))) {
986
+ const nextPrev = prev ? navigator.previous() : navigator.last();
987
+ if (!prev && !nextPrev) {
988
+ return;
989
+ }
990
+ prev = nextPrev;
991
+ }
992
+ while (!(prev instanceof Match)) {
993
+ const nextItem = navigator.next();
994
+ this.tree.expand(prev);
995
+ navigator = this.tree.navigate(nextItem);
996
+ prev = nextItem ? navigator.previous() : navigator.last();
997
+ }
998
+ if (prev) {
999
+ if (prev === selected) {
1000
+ this.tree.setFocus([]);
1001
+ }
1002
+ const event = getSelectionKeyboardEvent(undefined, false, false);
1003
+ this.tree.setFocus([prev], event);
1004
+ this.tree.setSelection([prev], event);
1005
+ this.tree.reveal(prev);
1006
+ const ariaLabel = this.treeAccessibilityProvider.getAriaLabel(prev);
1007
+ if (ariaLabel) {
1008
+ status(ariaLabel);
1009
+ }
1010
+ }
1011
+ }
1012
+ moveFocusToResults() {
1013
+ this.tree.domFocus();
1014
+ }
1015
+ focus() {
1016
+ super.focus();
1017
+ if (this.lastFocusState === 'input' || !this.hasSearchResults()) {
1018
+ const updatedText = this.searchConfig.seedOnFocus ? this.updateTextFromSelection({ allowSearchOnType: false }) : false;
1019
+ this.searchWidget.focus(undefined, undefined, updatedText);
1020
+ }
1021
+ else {
1022
+ this.tree.domFocus();
1023
+ }
1024
+ }
1025
+ updateTextFromFindWidgetOrSelection({ allowUnselectedWord = true, allowSearchOnType = true }) {
1026
+ let activeEditor = this.editorService.activeTextEditorControl;
1027
+ if (isCodeEditor(activeEditor) && !activeEditor?.hasTextFocus()) {
1028
+ const controller = CommonFindController.get(activeEditor);
1029
+ if (controller && controller.isFindInputFocused()) {
1030
+ return this.updateTextFromFindWidget(controller, { allowSearchOnType });
1031
+ }
1032
+ const editors = this.codeEditorService.listCodeEditors();
1033
+ activeEditor = editors.find(editor => editor instanceof EmbeddedCodeEditorWidget && editor.getParentEditor() === activeEditor && editor.hasTextFocus())
1034
+ ?? activeEditor;
1035
+ }
1036
+ return this.updateTextFromSelection({ allowUnselectedWord, allowSearchOnType }, activeEditor);
1037
+ }
1038
+ updateTextFromFindWidget(controller, { allowSearchOnType = true }) {
1039
+ if (!this.searchConfig.seedWithNearestWord && (getActiveWindow().getSelection()?.toString() ?? '') === '') {
1040
+ return false;
1041
+ }
1042
+ const searchString = controller.getState().searchString;
1043
+ if (searchString === '') {
1044
+ return false;
1045
+ }
1046
+ this.searchWidget.searchInput?.setCaseSensitive(controller.getState().matchCase);
1047
+ this.searchWidget.searchInput?.setWholeWords(controller.getState().wholeWord);
1048
+ this.searchWidget.searchInput?.setRegex(controller.getState().isRegex);
1049
+ this.updateText(searchString, allowSearchOnType);
1050
+ return true;
1051
+ }
1052
+ updateTextFromSelection({ allowUnselectedWord = true, allowSearchOnType = true }, editor) {
1053
+ const seedSearchStringFromSelection = this.configurationService.getValue('editor').find.seedSearchStringFromSelection;
1054
+ if (!seedSearchStringFromSelection || seedSearchStringFromSelection === 'never') {
1055
+ return false;
1056
+ }
1057
+ let selectedText = this.getSearchTextFromEditor(allowUnselectedWord, editor);
1058
+ if (selectedText === null) {
1059
+ return false;
1060
+ }
1061
+ if (this.searchWidget.searchInput?.getRegex()) {
1062
+ selectedText = escapeRegExpCharacters(selectedText);
1063
+ }
1064
+ this.updateText(selectedText, allowSearchOnType);
1065
+ return true;
1066
+ }
1067
+ updateText(text, allowSearchOnType = true) {
1068
+ if (allowSearchOnType && !this.viewModel.searchResult.isDirty) {
1069
+ this.searchWidget.setValue(text);
1070
+ }
1071
+ else {
1072
+ this.pauseSearching = true;
1073
+ this.searchWidget.setValue(text);
1074
+ this.pauseSearching = false;
1075
+ }
1076
+ }
1077
+ focusNextInputBox() {
1078
+ if (this.searchWidget.searchInputHasFocus()) {
1079
+ if (this.searchWidget.isReplaceShown()) {
1080
+ this.searchWidget.focus(true, true);
1081
+ }
1082
+ else {
1083
+ this.moveFocusFromSearchOrReplace();
1084
+ }
1085
+ return;
1086
+ }
1087
+ if (this.searchWidget.replaceInputHasFocus()) {
1088
+ this.moveFocusFromSearchOrReplace();
1089
+ return;
1090
+ }
1091
+ if (this.inputPatternIncludes.inputHasFocus()) {
1092
+ this.inputPatternExcludes.focus();
1093
+ this.inputPatternExcludes.select();
1094
+ return;
1095
+ }
1096
+ if (this.inputPatternExcludes.inputHasFocus()) {
1097
+ this.selectTreeIfNotSelected();
1098
+ return;
1099
+ }
1100
+ }
1101
+ moveFocusFromSearchOrReplace() {
1102
+ if (this.showsFileTypes()) {
1103
+ this.toggleQueryDetails(true, this.showsFileTypes());
1104
+ }
1105
+ else {
1106
+ this.selectTreeIfNotSelected();
1107
+ }
1108
+ }
1109
+ focusPreviousInputBox() {
1110
+ if (this.searchWidget.searchInputHasFocus()) {
1111
+ return;
1112
+ }
1113
+ if (this.searchWidget.replaceInputHasFocus()) {
1114
+ this.searchWidget.focus(true);
1115
+ return;
1116
+ }
1117
+ if (this.inputPatternIncludes.inputHasFocus()) {
1118
+ this.searchWidget.focus(true, true);
1119
+ return;
1120
+ }
1121
+ if (this.inputPatternExcludes.inputHasFocus()) {
1122
+ this.inputPatternIncludes.focus();
1123
+ this.inputPatternIncludes.select();
1124
+ return;
1125
+ }
1126
+ if (this.tree.isDOMFocused()) {
1127
+ this.moveFocusFromResults();
1128
+ return;
1129
+ }
1130
+ }
1131
+ moveFocusFromResults() {
1132
+ if (this.showsFileTypes()) {
1133
+ this.toggleQueryDetails(true, true, false, true);
1134
+ }
1135
+ else {
1136
+ this.searchWidget.focus(true, true);
1137
+ }
1138
+ }
1139
+ reLayout() {
1140
+ if (this.isDisposed || !this.size) {
1141
+ return;
1142
+ }
1143
+ const actionsPosition = this.searchConfig.actionsPosition;
1144
+ this.getContainer().classList.toggle(SearchView_1.ACTIONS_RIGHT_CLASS_NAME, actionsPosition === 'right');
1145
+ this.searchWidget.setWidth(this.size.width - 28 );
1146
+ this.inputPatternExcludes.setWidth(this.size.width - 28 );
1147
+ this.inputPatternIncludes.setWidth(this.size.width - 28 );
1148
+ const widgetHeight = getTotalHeight(this.searchWidgetsContainerElement);
1149
+ const messagesHeight = getTotalHeight(this.messagesElement);
1150
+ this.tree.layout(this.size.height - widgetHeight - messagesHeight, this.size.width - 28);
1151
+ }
1152
+ layoutBody(height, width) {
1153
+ super.layoutBody(height, width);
1154
+ this.size = new Dimension(width, height);
1155
+ this.reLayout();
1156
+ }
1157
+ getControl() {
1158
+ return this.tree;
1159
+ }
1160
+ allSearchFieldsClear() {
1161
+ return this.searchWidget.getReplaceValue() === '' &&
1162
+ (!this.searchWidget.searchInput || this.searchWidget.searchInput.getValue() === '');
1163
+ }
1164
+ allFilePatternFieldsClear() {
1165
+ return this.searchExcludePattern.getValue() === '' &&
1166
+ this.searchIncludePattern.getValue() === '';
1167
+ }
1168
+ hasSearchResults() {
1169
+ return !this.viewModel.searchResult.isEmpty(this.aiResultsVisible);
1170
+ }
1171
+ clearSearchResults(clearInput = true) {
1172
+ this.viewModel.searchResult.clear();
1173
+ this.showEmptyStage(true);
1174
+ if (this.contextService.getWorkbenchState() === 1 ) {
1175
+ this.showSearchWithoutFolderMessage();
1176
+ }
1177
+ if (clearInput) {
1178
+ if (this.allSearchFieldsClear()) {
1179
+ this.clearFilePatternFields();
1180
+ }
1181
+ this.searchWidget.clear();
1182
+ }
1183
+ this.viewModel.cancelSearch();
1184
+ this.tree.ariaLabel = ( localizeWithPath(
1185
+ 'vs/workbench/contrib/search/browser/searchView',
1186
+ 'emptySearch',
1187
+ "Empty Search"
1188
+ ));
1189
+ this.accessibilitySignalService.playSignal(AccessibilitySignal.clear);
1190
+ this.reLayout();
1191
+ }
1192
+ clearFilePatternFields() {
1193
+ this.searchExcludePattern.clear();
1194
+ this.searchIncludePattern.clear();
1195
+ }
1196
+ cancelSearch(focus = true) {
1197
+ if (this.viewModel.cancelSearch()) {
1198
+ if (focus) {
1199
+ this.searchWidget.focus();
1200
+ }
1201
+ return true;
1202
+ }
1203
+ return false;
1204
+ }
1205
+ selectTreeIfNotSelected() {
1206
+ if (this.tree.getNode(null)) {
1207
+ this.tree.domFocus();
1208
+ const selection = this.tree.getSelection();
1209
+ if (selection.length === 0) {
1210
+ const event = getSelectionKeyboardEvent();
1211
+ this.tree.focusNext(undefined, undefined, event);
1212
+ this.tree.setSelection(this.tree.getFocus(), event);
1213
+ }
1214
+ }
1215
+ }
1216
+ getSearchTextFromEditor(allowUnselectedWord, editor) {
1217
+ if (isAncestorOfActiveElement(this.getContainer())) {
1218
+ return null;
1219
+ }
1220
+ editor = editor ?? this.editorService.activeTextEditorControl;
1221
+ if (!editor) {
1222
+ return null;
1223
+ }
1224
+ const allowUnselected = this.searchConfig.seedWithNearestWord && allowUnselectedWord;
1225
+ return getSelectionTextFromEditor(allowUnselected, editor);
1226
+ }
1227
+ showsFileTypes() {
1228
+ return this.queryDetails.classList.contains('more');
1229
+ }
1230
+ toggleCaseSensitive() {
1231
+ this.searchWidget.searchInput?.setCaseSensitive(!this.searchWidget.searchInput.getCaseSensitive());
1232
+ this.triggerQueryChange();
1233
+ }
1234
+ toggleWholeWords() {
1235
+ this.searchWidget.searchInput?.setWholeWords(!this.searchWidget.searchInput.getWholeWords());
1236
+ this.triggerQueryChange();
1237
+ }
1238
+ toggleRegex() {
1239
+ this.searchWidget.searchInput?.setRegex(!this.searchWidget.searchInput.getRegex());
1240
+ this.triggerQueryChange();
1241
+ }
1242
+ togglePreserveCase() {
1243
+ this.searchWidget.replaceInput?.setPreserveCase(!this.searchWidget.replaceInput.getPreserveCase());
1244
+ this.triggerQueryChange();
1245
+ }
1246
+ setSearchParameters(args = {}) {
1247
+ if (typeof args.isCaseSensitive === 'boolean') {
1248
+ this.searchWidget.searchInput?.setCaseSensitive(args.isCaseSensitive);
1249
+ }
1250
+ if (typeof args.matchWholeWord === 'boolean') {
1251
+ this.searchWidget.searchInput?.setWholeWords(args.matchWholeWord);
1252
+ }
1253
+ if (typeof args.isRegex === 'boolean') {
1254
+ this.searchWidget.searchInput?.setRegex(args.isRegex);
1255
+ }
1256
+ if (typeof args.filesToInclude === 'string') {
1257
+ this.searchIncludePattern.setValue(String(args.filesToInclude));
1258
+ }
1259
+ if (typeof args.filesToExclude === 'string') {
1260
+ this.searchExcludePattern.setValue(String(args.filesToExclude));
1261
+ }
1262
+ if (typeof args.query === 'string') {
1263
+ this.searchWidget.searchInput?.setValue(args.query);
1264
+ }
1265
+ if (typeof args.replace === 'string') {
1266
+ this.searchWidget.replaceInput?.setValue(args.replace);
1267
+ }
1268
+ else {
1269
+ if (this.searchWidget.replaceInput && this.searchWidget.replaceInput.getValue() !== '') {
1270
+ this.searchWidget.replaceInput.setValue('');
1271
+ }
1272
+ }
1273
+ if (typeof args.triggerSearch === 'boolean' && args.triggerSearch) {
1274
+ this.triggerQueryChange();
1275
+ }
1276
+ if (typeof args.preserveCase === 'boolean') {
1277
+ this.searchWidget.replaceInput?.setPreserveCase(args.preserveCase);
1278
+ }
1279
+ if (typeof args.useExcludeSettingsAndIgnoreFiles === 'boolean') {
1280
+ this.inputPatternExcludes.setUseExcludesAndIgnoreFiles(args.useExcludeSettingsAndIgnoreFiles);
1281
+ }
1282
+ if (typeof args.onlyOpenEditors === 'boolean') {
1283
+ this.searchIncludePattern.setOnlySearchInOpenEditors(args.onlyOpenEditors);
1284
+ }
1285
+ }
1286
+ toggleQueryDetails(moveFocus = true, show, skipLayout, reverse) {
1287
+ const cls = 'more';
1288
+ show = typeof show === 'undefined' ? !this.queryDetails.classList.contains(cls) : Boolean(show);
1289
+ this.viewletState['query.queryDetailsExpanded'] = show;
1290
+ skipLayout = Boolean(skipLayout);
1291
+ if (show) {
1292
+ this.toggleQueryDetailsButton.setAttribute('aria-expanded', 'true');
1293
+ this.queryDetails.classList.add(cls);
1294
+ if (moveFocus) {
1295
+ if (reverse) {
1296
+ this.inputPatternExcludes.focus();
1297
+ this.inputPatternExcludes.select();
1298
+ }
1299
+ else {
1300
+ this.inputPatternIncludes.focus();
1301
+ this.inputPatternIncludes.select();
1302
+ }
1303
+ }
1304
+ }
1305
+ else {
1306
+ this.toggleQueryDetailsButton.setAttribute('aria-expanded', 'false');
1307
+ this.queryDetails.classList.remove(cls);
1308
+ if (moveFocus) {
1309
+ this.searchWidget.focus();
1310
+ }
1311
+ }
1312
+ if (!skipLayout && this.size) {
1313
+ this.reLayout();
1314
+ }
1315
+ }
1316
+ searchInFolders(folderPaths = []) {
1317
+ this._searchWithIncludeOrExclude(true, folderPaths);
1318
+ }
1319
+ searchOutsideOfFolders(folderPaths = []) {
1320
+ this._searchWithIncludeOrExclude(false, folderPaths);
1321
+ }
1322
+ _searchWithIncludeOrExclude(include, folderPaths) {
1323
+ if (!folderPaths.length || ( folderPaths.some(folderPath => folderPath === '.'))) {
1324
+ this.inputPatternIncludes.setValue('');
1325
+ this.searchWidget.focus();
1326
+ return;
1327
+ }
1328
+ if (!this.showsFileTypes()) {
1329
+ this.toggleQueryDetails(true, true);
1330
+ }
1331
+ (include ? this.inputPatternIncludes : this.inputPatternExcludes).setValue(folderPaths.join(', '));
1332
+ this.searchWidget.focus(false);
1333
+ }
1334
+ triggerQueryChange(_options) {
1335
+ const options = { preserveFocus: true, triggeredOnType: false, delay: 0, ..._options };
1336
+ if (options.triggeredOnType && !this.searchConfig.searchOnType) {
1337
+ return;
1338
+ }
1339
+ if (!this.pauseSearching) {
1340
+ const delay = options.triggeredOnType ? options.delay : 0;
1341
+ this.triggerQueryDelayer.trigger(() => {
1342
+ this._onQueryChanged(options.preserveFocus, options.triggeredOnType);
1343
+ }, delay);
1344
+ }
1345
+ }
1346
+ _onQueryChanged(preserveFocus, triggeredOnType = false) {
1347
+ if (!(this.searchWidget.searchInput?.inputBox.isInputValid())) {
1348
+ return;
1349
+ }
1350
+ const isRegex = this.searchWidget.searchInput.getRegex();
1351
+ const isInNotebookMarkdownInput = this.searchWidget.getNotebookFilters().markupInput;
1352
+ const isInNotebookMarkdownPreview = this.searchWidget.getNotebookFilters().markupPreview;
1353
+ const isInNotebookCellInput = this.searchWidget.getNotebookFilters().codeInput;
1354
+ const isInNotebookCellOutput = this.searchWidget.getNotebookFilters().codeOutput;
1355
+ const isWholeWords = this.searchWidget.searchInput.getWholeWords();
1356
+ const isCaseSensitive = this.searchWidget.searchInput.getCaseSensitive();
1357
+ const contentPattern = this.searchWidget.searchInput.getValue();
1358
+ const excludePatternText = this.inputPatternExcludes.getValue().trim();
1359
+ const includePatternText = this.inputPatternIncludes.getValue().trim();
1360
+ const useExcludesAndIgnoreFiles = this.inputPatternExcludes.useExcludesAndIgnoreFiles();
1361
+ const onlySearchInOpenEditors = this.inputPatternIncludes.onlySearchInOpenEditors();
1362
+ if (contentPattern.length === 0) {
1363
+ this.clearSearchResults(false);
1364
+ this.clearMessage();
1365
+ return;
1366
+ }
1367
+ const content = {
1368
+ pattern: contentPattern,
1369
+ isRegExp: isRegex,
1370
+ isCaseSensitive: isCaseSensitive,
1371
+ isWordMatch: isWholeWords,
1372
+ notebookInfo: {
1373
+ isInNotebookMarkdownInput,
1374
+ isInNotebookMarkdownPreview,
1375
+ isInNotebookCellInput,
1376
+ isInNotebookCellOutput
1377
+ }
1378
+ };
1379
+ const excludePattern = this.inputPatternExcludes.getValue();
1380
+ const includePattern = this.inputPatternIncludes.getValue();
1381
+ const charsPerLine = content.isRegExp ? 10000 : 1000;
1382
+ const options = {
1383
+ _reason: 'searchView',
1384
+ extraFileResources: this.instantiationService.invokeFunction(getOutOfWorkspaceEditorResources),
1385
+ maxResults: this.searchConfig.maxResults ?? undefined,
1386
+ disregardIgnoreFiles: !useExcludesAndIgnoreFiles || undefined,
1387
+ disregardExcludeSettings: !useExcludesAndIgnoreFiles || undefined,
1388
+ onlyOpenEditors: onlySearchInOpenEditors,
1389
+ excludePattern,
1390
+ includePattern,
1391
+ previewOptions: {
1392
+ matchLines: 1,
1393
+ charsPerLine
1394
+ },
1395
+ isSmartCase: this.searchConfig.smartCase,
1396
+ expandPatterns: true
1397
+ };
1398
+ const folderResources = this.contextService.getWorkspace().folders;
1399
+ const onQueryValidationError = (err) => {
1400
+ this.searchWidget.searchInput?.showMessage({ content: err.message, type: 3 });
1401
+ this.viewModel.searchResult.clear();
1402
+ };
1403
+ let query;
1404
+ try {
1405
+ query = this.queryBuilder.text(content, ( folderResources.map(folder => folder.uri)), options);
1406
+ }
1407
+ catch (err) {
1408
+ onQueryValidationError(err);
1409
+ return;
1410
+ }
1411
+ this.validateQuery(query).then(() => {
1412
+ this.onQueryTriggered(query, options, excludePatternText, includePatternText, triggeredOnType);
1413
+ if (!preserveFocus) {
1414
+ this.searchWidget.focus(false, undefined, true);
1415
+ }
1416
+ }, onQueryValidationError);
1417
+ }
1418
+ validateQuery(query) {
1419
+ const folderQueriesExistP = ( query.folderQueries.map(fq => {
1420
+ return this.fileService.exists(fq.folder).catch(() => false);
1421
+ }));
1422
+ return Promise.all(folderQueriesExistP).then(existResults => {
1423
+ const existingFolderQueries = query.folderQueries.filter((folderQuery, i) => existResults[i]);
1424
+ if (!query.folderQueries.length || existingFolderQueries.length) {
1425
+ query.folderQueries = existingFolderQueries;
1426
+ }
1427
+ else {
1428
+ const nonExistantPath = query.folderQueries[0].folder.fsPath;
1429
+ const searchPathNotFoundError = ( localizeWithPath(
1430
+ 'vs/workbench/contrib/search/browser/searchView',
1431
+ 'searchPathNotFoundError',
1432
+ "Search path not found: {0}",
1433
+ nonExistantPath
1434
+ ));
1435
+ return Promise.reject(( new Error(searchPathNotFoundError)));
1436
+ }
1437
+ return undefined;
1438
+ });
1439
+ }
1440
+ onQueryTriggered(query, options, excludePatternText, includePatternText, triggeredOnType) {
1441
+ this.addToSearchHistoryDelayer.trigger(() => {
1442
+ this.searchWidget.searchInput?.onSearchSubmit();
1443
+ this.inputPatternExcludes.onSearchSubmit();
1444
+ this.inputPatternIncludes.onSearchSubmit();
1445
+ });
1446
+ this.viewModel.cancelSearch(true);
1447
+ this.viewModel.cancelAISearch(true);
1448
+ this.currentSearchQ = this.currentSearchQ
1449
+ .then(() => this.doSearch(query, excludePatternText, includePatternText, triggeredOnType))
1450
+ .then(() => undefined, () => undefined);
1451
+ }
1452
+ _updateResults() {
1453
+ if (this.state === SearchUIState.Idle) {
1454
+ return;
1455
+ }
1456
+ try {
1457
+ const fileCount = this.viewModel.searchResult.fileCount(this.aiResultsVisible);
1458
+ if (this._visibleMatches !== fileCount) {
1459
+ this._visibleMatches = fileCount;
1460
+ this.refreshAndUpdateCount();
1461
+ }
1462
+ }
1463
+ finally {
1464
+ this._refreshResultsScheduler.schedule();
1465
+ }
1466
+ }
1467
+ onSearchComplete(progressComplete, excludePatternText, includePatternText, completed) {
1468
+ this.state = SearchUIState.Idle;
1469
+ progressComplete();
1470
+ this.onSearchResultsChanged();
1471
+ const collapseResults = this.searchConfig.collapseResults;
1472
+ if (collapseResults !== 'alwaysCollapse' && this.viewModel.searchResult.matches(this.aiResultsVisible).length === 1) {
1473
+ const onlyMatch = this.viewModel.searchResult.matches(this.aiResultsVisible)[0];
1474
+ if (onlyMatch.count() < 50) {
1475
+ this.tree.expand(onlyMatch);
1476
+ }
1477
+ }
1478
+ const hasResults = !this.viewModel.searchResult.isEmpty(this.aiResultsVisible);
1479
+ if (completed?.exit === 1 ) {
1480
+ return;
1481
+ }
1482
+ if (!hasResults) {
1483
+ const hasExcludes = !!excludePatternText;
1484
+ const hasIncludes = !!includePatternText;
1485
+ let message;
1486
+ if (!completed) {
1487
+ message = SEARCH_CANCELLED_MESSAGE;
1488
+ }
1489
+ else if (this.inputPatternIncludes.onlySearchInOpenEditors()) {
1490
+ if (hasIncludes && hasExcludes) {
1491
+ message = ( localizeWithPath(
1492
+ 'vs/workbench/contrib/search/browser/searchView',
1493
+ 'noOpenEditorResultsIncludesExcludes',
1494
+ "No results found in open editors matching '{0}' excluding '{1}' - ",
1495
+ includePatternText,
1496
+ excludePatternText
1497
+ ));
1498
+ }
1499
+ else if (hasIncludes) {
1500
+ message = ( localizeWithPath(
1501
+ 'vs/workbench/contrib/search/browser/searchView',
1502
+ 'noOpenEditorResultsIncludes',
1503
+ "No results found in open editors matching '{0}' - ",
1504
+ includePatternText
1505
+ ));
1506
+ }
1507
+ else if (hasExcludes) {
1508
+ message = ( localizeWithPath(
1509
+ 'vs/workbench/contrib/search/browser/searchView',
1510
+ 'noOpenEditorResultsExcludes',
1511
+ "No results found in open editors excluding '{0}' - ",
1512
+ excludePatternText
1513
+ ));
1514
+ }
1515
+ else {
1516
+ message = ( localizeWithPath(
1517
+ 'vs/workbench/contrib/search/browser/searchView',
1518
+ 'noOpenEditorResultsFound',
1519
+ "No results found in open editors. Review your settings for configured exclusions and check your gitignore files - "
1520
+ ));
1521
+ }
1522
+ }
1523
+ else {
1524
+ if (hasIncludes && hasExcludes) {
1525
+ message = ( localizeWithPath(
1526
+ 'vs/workbench/contrib/search/browser/searchView',
1527
+ 'noResultsIncludesExcludes',
1528
+ "No results found in '{0}' excluding '{1}' - ",
1529
+ includePatternText,
1530
+ excludePatternText
1531
+ ));
1532
+ }
1533
+ else if (hasIncludes) {
1534
+ message = ( localizeWithPath(
1535
+ 'vs/workbench/contrib/search/browser/searchView',
1536
+ 'noResultsIncludes',
1537
+ "No results found in '{0}' - ",
1538
+ includePatternText
1539
+ ));
1540
+ }
1541
+ else if (hasExcludes) {
1542
+ message = ( localizeWithPath(
1543
+ 'vs/workbench/contrib/search/browser/searchView',
1544
+ 'noResultsExcludes',
1545
+ "No results found excluding '{0}' - ",
1546
+ excludePatternText
1547
+ ));
1548
+ }
1549
+ else {
1550
+ message = ( localizeWithPath(
1551
+ 'vs/workbench/contrib/search/browser/searchView',
1552
+ 'noResultsFound',
1553
+ "No results found. Review your settings for configured exclusions and check your gitignore files - "
1554
+ ));
1555
+ }
1556
+ }
1557
+ status(message);
1558
+ const messageEl = this.clearMessage();
1559
+ append(messageEl, message);
1560
+ if (!completed) {
1561
+ const searchAgainButton = this.messageDisposables.add(( new SearchLinkButton(( localizeWithPath(
1562
+ 'vs/workbench/contrib/search/browser/searchView',
1563
+ 'rerunSearch.message',
1564
+ "Search again"
1565
+ )), () => this.triggerQueryChange({ preserveFocus: false }))));
1566
+ append(messageEl, searchAgainButton.element);
1567
+ }
1568
+ else if (hasIncludes || hasExcludes) {
1569
+ const searchAgainButton = this.messageDisposables.add(( new SearchLinkButton(( localizeWithPath(
1570
+ 'vs/workbench/contrib/search/browser/searchView',
1571
+ 'rerunSearchInAll.message',
1572
+ "Search again in all files"
1573
+ )), this.onSearchAgain.bind(this))));
1574
+ append(messageEl, searchAgainButton.element);
1575
+ }
1576
+ else {
1577
+ const openSettingsButton = this.messageDisposables.add(( new SearchLinkButton(( localizeWithPath(
1578
+ 'vs/workbench/contrib/search/browser/searchView',
1579
+ 'openSettings.message',
1580
+ "Open Settings"
1581
+ )), this.onOpenSettings.bind(this))));
1582
+ append(messageEl, openSettingsButton.element);
1583
+ }
1584
+ if (completed) {
1585
+ append(messageEl, $('span', undefined, ' - '));
1586
+ const learnMoreButton = this.messageDisposables.add(( new SearchLinkButton(( localizeWithPath(
1587
+ 'vs/workbench/contrib/search/browser/searchView',
1588
+ 'openSettings.learnMore',
1589
+ "Learn More"
1590
+ )), this.onLearnMore.bind(this))));
1591
+ append(messageEl, learnMoreButton.element);
1592
+ }
1593
+ if (this.contextService.getWorkbenchState() === 1 ) {
1594
+ this.showSearchWithoutFolderMessage();
1595
+ }
1596
+ this.reLayout();
1597
+ }
1598
+ else {
1599
+ this.viewModel.searchResult.toggleHighlights(this.isVisible());
1600
+ status(( localizeWithPath(
1601
+ 'vs/workbench/contrib/search/browser/searchView',
1602
+ 'ariaSearchResultsStatus',
1603
+ "Search returned {0} results in {1} files",
1604
+ this.viewModel.searchResult.count(this.aiResultsVisible),
1605
+ this.viewModel.searchResult.fileCount()
1606
+ )));
1607
+ }
1608
+ if (completed && completed.limitHit) {
1609
+ completed.messages.push({ type: TextSearchCompleteMessageType.Warning, text: ( localizeWithPath(
1610
+ 'vs/workbench/contrib/search/browser/searchView',
1611
+ 'searchMaxResultsWarning',
1612
+ "The result set only contains a subset of all matches. Be more specific in your search to narrow down the results."
1613
+ )) });
1614
+ }
1615
+ if (completed && completed.messages) {
1616
+ for (const message of completed.messages) {
1617
+ this.addMessage(message);
1618
+ }
1619
+ }
1620
+ this.reLayout();
1621
+ }
1622
+ onSearchError(e, progressComplete, excludePatternText, includePatternText, completed) {
1623
+ this.state = SearchUIState.Idle;
1624
+ if (isCancellationError(e)) {
1625
+ return this.onSearchComplete(progressComplete, excludePatternText, includePatternText, completed);
1626
+ }
1627
+ else {
1628
+ progressComplete();
1629
+ this.searchWidget.searchInput?.showMessage({ content: e.message, type: 3 });
1630
+ this.viewModel.searchResult.clear();
1631
+ return Promise.resolve();
1632
+ }
1633
+ }
1634
+ doSearch(query, excludePatternText, includePatternText, triggeredOnType) {
1635
+ let progressComplete;
1636
+ this.progressService.withProgress({ location: this.getProgressLocation(), delay: triggeredOnType ? 300 : 0 }, _progress => {
1637
+ return ( new Promise(resolve => progressComplete = resolve));
1638
+ });
1639
+ this.searchWidget.searchInput?.clearMessage();
1640
+ this.state = SearchUIState.Searching;
1641
+ this.showEmptyStage();
1642
+ const slowTimer = setTimeout(() => {
1643
+ this.state = SearchUIState.SlowSearch;
1644
+ }, 2000);
1645
+ this._visibleMatches = 0;
1646
+ this._refreshResultsScheduler.schedule();
1647
+ this.searchWidget.setReplaceAllActionState(false);
1648
+ this.tree.setSelection([]);
1649
+ this.tree.setFocus([]);
1650
+ this.viewModel.replaceString = this.searchWidget.getReplaceValue();
1651
+ const result = this.viewModel.search(query);
1652
+ if (this.aiResultsVisible) {
1653
+ const aiResult = this.viewModel.aiSearch({ ...query, contentPattern: query.contentPattern.pattern, type: 3 });
1654
+ return result.asyncResults.then(() => aiResult.then((complete) => {
1655
+ clearTimeout(slowTimer);
1656
+ this.onSearchComplete(progressComplete, excludePatternText, includePatternText, complete);
1657
+ }, (e) => {
1658
+ clearTimeout(slowTimer);
1659
+ this.onSearchError(e, progressComplete, excludePatternText, includePatternText);
1660
+ }));
1661
+ }
1662
+ return result.asyncResults.then((complete) => {
1663
+ clearTimeout(slowTimer);
1664
+ this.onSearchComplete(progressComplete, excludePatternText, includePatternText, complete);
1665
+ }, (e) => {
1666
+ clearTimeout(slowTimer);
1667
+ this.onSearchError(e, progressComplete, excludePatternText, includePatternText);
1668
+ });
1669
+ }
1670
+ onOpenSettings(e) {
1671
+ EventHelper.stop(e, false);
1672
+ this.openSettings('@id:files.exclude,search.exclude,search.useParentIgnoreFiles,search.useGlobalIgnoreFiles,search.useIgnoreFiles');
1673
+ }
1674
+ openSettings(query) {
1675
+ const options = { query };
1676
+ return this.contextService.getWorkbenchState() !== 1 ?
1677
+ this.preferencesService.openWorkspaceSettings(options) :
1678
+ this.preferencesService.openUserSettings(options);
1679
+ }
1680
+ onLearnMore() {
1681
+ this.openerService.open(( URI.parse('https://go.microsoft.com/fwlink/?linkid=853977')));
1682
+ }
1683
+ onSearchAgain() {
1684
+ this.inputPatternExcludes.setValue('');
1685
+ this.inputPatternIncludes.setValue('');
1686
+ this.inputPatternIncludes.setOnlySearchInOpenEditors(false);
1687
+ this.triggerQueryChange({ preserveFocus: false });
1688
+ }
1689
+ onEnableExcludes() {
1690
+ this.toggleQueryDetails(false, true);
1691
+ this.searchExcludePattern.setUseExcludesAndIgnoreFiles(true);
1692
+ }
1693
+ onDisableSearchInOpenEditors() {
1694
+ this.toggleQueryDetails(false, true);
1695
+ this.inputPatternIncludes.setOnlySearchInOpenEditors(false);
1696
+ }
1697
+ updateSearchResultCount(disregardExcludesAndIgnores, onlyOpenEditors, clear = false) {
1698
+ const fileCount = this.viewModel.searchResult.fileCount(this.aiResultsVisible);
1699
+ const resultCount = this.viewModel.searchResult.count(this.aiResultsVisible);
1700
+ this.hasSearchResultsKey.set(fileCount > 0);
1701
+ const msgWasHidden = this.messagesElement.style.display === 'none';
1702
+ const messageEl = this.clearMessage();
1703
+ const resultMsg = clear ? '' : this.buildResultCountMessage(resultCount, fileCount);
1704
+ this.tree.ariaLabel = resultMsg + ( localizeWithPath(
1705
+ 'vs/workbench/contrib/search/browser/searchView',
1706
+ 'forTerm',
1707
+ " - Search: {0}",
1708
+ this.searchResult.query?.contentPattern.pattern ?? ''
1709
+ ));
1710
+ append(messageEl, resultMsg);
1711
+ if (fileCount > 0) {
1712
+ if (disregardExcludesAndIgnores) {
1713
+ const excludesDisabledMessage = ' - ' + ( localizeWithPath(
1714
+ 'vs/workbench/contrib/search/browser/searchView',
1715
+ 'useIgnoresAndExcludesDisabled',
1716
+ "exclude settings and ignore files are disabled"
1717
+ )) + ' ';
1718
+ const enableExcludesButton = this.messageDisposables.add(( new SearchLinkButton(( localizeWithPath(
1719
+ 'vs/workbench/contrib/search/browser/searchView',
1720
+ 'excludes.enable',
1721
+ "enable"
1722
+ )), this.onEnableExcludes.bind(this), ( localizeWithPath(
1723
+ 'vs/workbench/contrib/search/browser/searchView',
1724
+ 'useExcludesAndIgnoreFilesDescription',
1725
+ "Use Exclude Settings and Ignore Files"
1726
+ )))));
1727
+ append(messageEl, $('span', undefined, excludesDisabledMessage, '(', enableExcludesButton.element, ')'));
1728
+ }
1729
+ if (onlyOpenEditors) {
1730
+ const searchingInOpenMessage = ' - ' + ( localizeWithPath(
1731
+ 'vs/workbench/contrib/search/browser/searchView',
1732
+ 'onlyOpenEditors',
1733
+ "searching only in open files"
1734
+ )) + ' ';
1735
+ const disableOpenEditorsButton = this.messageDisposables.add(( new SearchLinkButton(( localizeWithPath(
1736
+ 'vs/workbench/contrib/search/browser/searchView',
1737
+ 'openEditors.disable',
1738
+ "disable"
1739
+ )), this.onDisableSearchInOpenEditors.bind(this), ( localizeWithPath(
1740
+ 'vs/workbench/contrib/search/browser/searchView',
1741
+ 'disableOpenEditors',
1742
+ "Search in entire workspace"
1743
+ )))));
1744
+ append(messageEl, $('span', undefined, searchingInOpenMessage, '(', disableOpenEditorsButton.element, ')'));
1745
+ }
1746
+ append(messageEl, ' - ');
1747
+ const openInEditorTooltip = appendKeyBindingLabel(( localizeWithPath(
1748
+ 'vs/workbench/contrib/search/browser/searchView',
1749
+ 'openInEditor.tooltip',
1750
+ "Copy current search results to an editor"
1751
+ )), this.keybindingService.lookupKeybinding("search.action.openInEditor" ));
1752
+ const openInEditorButton = this.messageDisposables.add(( new SearchLinkButton(( localizeWithPath(
1753
+ 'vs/workbench/contrib/search/browser/searchView',
1754
+ 'openInEditor.message',
1755
+ "Open in editor"
1756
+ )), () => this.instantiationService.invokeFunction(createEditorFromSearchResult, this.searchResult, this.searchIncludePattern.getValue(), this.searchExcludePattern.getValue(), this.searchIncludePattern.onlySearchInOpenEditors()), openInEditorTooltip)));
1757
+ append(messageEl, openInEditorButton.element);
1758
+ this.reLayout();
1759
+ }
1760
+ else if (!msgWasHidden) {
1761
+ hide(this.messagesElement);
1762
+ }
1763
+ }
1764
+ addMessage(message) {
1765
+ const messageBox = this.messagesElement.firstChild;
1766
+ if (!messageBox) {
1767
+ return;
1768
+ }
1769
+ append(messageBox, renderSearchMessage(message, this.instantiationService, this.notificationService, this.openerService, this.commandService, this.messageDisposables, () => this.triggerQueryChange()));
1770
+ }
1771
+ buildResultCountMessage(resultCount, fileCount) {
1772
+ if (resultCount === 1 && fileCount === 1) {
1773
+ return ( localizeWithPath(
1774
+ 'vs/workbench/contrib/search/browser/searchView',
1775
+ 'search.file.result',
1776
+ "{0} result in {1} file",
1777
+ resultCount,
1778
+ fileCount
1779
+ ));
1780
+ }
1781
+ else if (resultCount === 1) {
1782
+ return ( localizeWithPath(
1783
+ 'vs/workbench/contrib/search/browser/searchView',
1784
+ 'search.files.result',
1785
+ "{0} result in {1} files",
1786
+ resultCount,
1787
+ fileCount
1788
+ ));
1789
+ }
1790
+ else if (fileCount === 1) {
1791
+ return ( localizeWithPath(
1792
+ 'vs/workbench/contrib/search/browser/searchView',
1793
+ 'search.file.results',
1794
+ "{0} results in {1} file",
1795
+ resultCount,
1796
+ fileCount
1797
+ ));
1798
+ }
1799
+ else {
1800
+ return ( localizeWithPath(
1801
+ 'vs/workbench/contrib/search/browser/searchView',
1802
+ 'search.files.results',
1803
+ "{0} results in {1} files",
1804
+ resultCount,
1805
+ fileCount
1806
+ ));
1807
+ }
1808
+ }
1809
+ showSearchWithoutFolderMessage() {
1810
+ this.searchWithoutFolderMessageElement = this.clearMessage();
1811
+ const textEl = append(this.searchWithoutFolderMessageElement, $('p', undefined, ( localizeWithPath(
1812
+ 'vs/workbench/contrib/search/browser/searchView',
1813
+ 'searchWithoutFolder',
1814
+ "You have not opened or specified a folder. Only open files are currently searched - "
1815
+ ))));
1816
+ const openFolderButton = this.messageDisposables.add(( new SearchLinkButton(( localizeWithPath(
1817
+ 'vs/workbench/contrib/search/browser/searchView',
1818
+ 'openFolder',
1819
+ "Open Folder"
1820
+ )), () => {
1821
+ this.commandService.executeCommand(isMacintosh && isNative ? OpenFileFolderAction.ID : OpenFolderAction.ID).catch(err => onUnexpectedError(err));
1822
+ })));
1823
+ append(textEl, openFolderButton.element);
1824
+ }
1825
+ showEmptyStage(forceHideMessages = false) {
1826
+ const showingCancelled = (this.messagesElement.firstChild?.textContent?.indexOf(SEARCH_CANCELLED_MESSAGE) ?? -1) > -1;
1827
+ if (showingCancelled || forceHideMessages || !this.configurationService.getValue().search.searchOnType) {
1828
+ hide(this.messagesElement);
1829
+ }
1830
+ show(this.resultsElement);
1831
+ this.currentSelectedFileMatch = undefined;
1832
+ }
1833
+ shouldOpenInNotebookEditor(match, uri) {
1834
+ return match instanceof MatchInNotebook || (uri.scheme !== Schemas.untitled && this.notebookService.getContributedNotebookTypes(uri).length > 0);
1835
+ }
1836
+ onFocus(lineMatch, preserveFocus, sideBySide, pinned) {
1837
+ const useReplacePreview = this.configurationService.getValue().search.useReplacePreview;
1838
+ const resource = lineMatch instanceof Match ? lineMatch.parent().resource : lineMatch.resource;
1839
+ return (useReplacePreview && this.viewModel.isReplaceActive() && !!this.viewModel.replaceString && !(this.shouldOpenInNotebookEditor(lineMatch, resource))) ?
1840
+ this.replaceService.openReplacePreview(lineMatch, preserveFocus, sideBySide, pinned) :
1841
+ this.open(lineMatch, preserveFocus, sideBySide, pinned, resource);
1842
+ }
1843
+ async open(element, preserveFocus, sideBySide, pinned, resourceInput) {
1844
+ const selection = getEditorSelectionFromMatch(element, this.viewModel);
1845
+ const oldParentMatches = element instanceof Match ? element.parent().matches() : [];
1846
+ const resource = resourceInput ?? (element instanceof Match ? element.parent().resource : element.resource);
1847
+ let editor;
1848
+ const options = {
1849
+ preserveFocus,
1850
+ pinned,
1851
+ selection,
1852
+ revealIfVisible: true,
1853
+ };
1854
+ try {
1855
+ editor = await this.editorService.openEditor({
1856
+ resource: resource,
1857
+ options,
1858
+ }, sideBySide ? SIDE_GROUP : ACTIVE_GROUP);
1859
+ const editorControl = editor?.getControl();
1860
+ if (element instanceof Match && preserveFocus && isCodeEditor(editorControl)) {
1861
+ this.viewModel.searchResult.rangeHighlightDecorations.highlightRange(editorControl.getModel(), element.range());
1862
+ }
1863
+ else {
1864
+ this.viewModel.searchResult.rangeHighlightDecorations.removeHighlightRange();
1865
+ }
1866
+ }
1867
+ catch (err) {
1868
+ onUnexpectedError(err);
1869
+ return;
1870
+ }
1871
+ if (editor instanceof NotebookEditor) {
1872
+ const elemParent = element.parent();
1873
+ if (element instanceof Match) {
1874
+ if (element instanceof MatchInNotebook) {
1875
+ element.parent().showMatch(element);
1876
+ }
1877
+ else {
1878
+ const editorWidget = editor.getControl();
1879
+ if (editorWidget) {
1880
+ elemParent.bindNotebookEditorWidget(editorWidget);
1881
+ await elemParent.updateMatchesForEditorWidget();
1882
+ const matchIndex = oldParentMatches.findIndex(e => e.id() === element.id());
1883
+ const matches = elemParent.matches();
1884
+ const match = matchIndex >= matches.length ? matches[matches.length - 1] : matches[matchIndex];
1885
+ if (match instanceof MatchInNotebook) {
1886
+ elemParent.showMatch(match);
1887
+ if (!this.tree.getFocus().includes(match) || !this.tree.getSelection().includes(match)) {
1888
+ this.tree.setSelection([match], getSelectionKeyboardEvent());
1889
+ this.tree.setFocus([match]);
1890
+ }
1891
+ }
1892
+ }
1893
+ }
1894
+ }
1895
+ }
1896
+ }
1897
+ openEditorWithMultiCursor(element) {
1898
+ const resource = element instanceof Match ? element.parent().resource : element.resource;
1899
+ return this.editorService.openEditor({
1900
+ resource: resource,
1901
+ options: {
1902
+ preserveFocus: false,
1903
+ pinned: true,
1904
+ revealIfVisible: true
1905
+ }
1906
+ }).then(editor => {
1907
+ if (editor) {
1908
+ let fileMatch = null;
1909
+ if (element instanceof FileMatch) {
1910
+ fileMatch = element;
1911
+ }
1912
+ else if (element instanceof Match) {
1913
+ fileMatch = element.parent();
1914
+ }
1915
+ if (fileMatch) {
1916
+ const selections = ( fileMatch.matches().map(m => ( new Selection(
1917
+ m.range().startLineNumber,
1918
+ m.range().startColumn,
1919
+ m.range().endLineNumber,
1920
+ m.range().endColumn
1921
+ ))));
1922
+ const codeEditor = getCodeEditor(editor.getControl());
1923
+ if (codeEditor) {
1924
+ const multiCursorController = MultiCursorSelectionController.get(codeEditor);
1925
+ multiCursorController?.selectAllUsingSelections(selections);
1926
+ }
1927
+ }
1928
+ }
1929
+ this.viewModel.searchResult.rangeHighlightDecorations.removeHighlightRange();
1930
+ }, onUnexpectedError);
1931
+ }
1932
+ onUntitledDidDispose(resource) {
1933
+ if (!this.viewModel) {
1934
+ return;
1935
+ }
1936
+ let matches = this.viewModel.searchResult.matches();
1937
+ for (let i = 0, len = matches.length; i < len; i++) {
1938
+ if (( resource.toString()) === ( matches[i].resource.toString())) {
1939
+ this.viewModel.searchResult.remove(matches[i]);
1940
+ }
1941
+ }
1942
+ matches = this.viewModel.searchResult.matches(true);
1943
+ for (let i = 0, len = matches.length; i < len; i++) {
1944
+ if (( resource.toString()) === ( matches[i].resource.toString())) {
1945
+ this.viewModel.searchResult.remove(matches[i]);
1946
+ }
1947
+ }
1948
+ }
1949
+ onFilesChanged(e) {
1950
+ if (!this.viewModel || (this.searchConfig.sortOrder !== "modified" && !e.gotDeleted())) {
1951
+ return;
1952
+ }
1953
+ const matches = this.viewModel.searchResult.matches();
1954
+ if (e.gotDeleted()) {
1955
+ const deletedMatches = matches.filter(m => e.contains(m.resource, 2 ));
1956
+ this.viewModel.searchResult.remove(deletedMatches);
1957
+ }
1958
+ else {
1959
+ const changedMatches = matches.filter(m => e.contains(m.resource));
1960
+ if (changedMatches.length && this.searchConfig.sortOrder === "modified" ) {
1961
+ this.updateFileStats(changedMatches).then(() => this.refreshTree());
1962
+ }
1963
+ }
1964
+ }
1965
+ get searchConfig() {
1966
+ return this.configurationService.getValue('search');
1967
+ }
1968
+ clearHistory() {
1969
+ this.searchWidget.clearHistory();
1970
+ this.inputPatternExcludes.clearHistory();
1971
+ this.inputPatternIncludes.clearHistory();
1972
+ }
1973
+ saveState() {
1974
+ if (!this.searchWidget) {
1975
+ return;
1976
+ }
1977
+ const patternExcludes = this.inputPatternExcludes?.getValue().trim() ?? '';
1978
+ const patternIncludes = this.inputPatternIncludes?.getValue().trim() ?? '';
1979
+ const onlyOpenEditors = this.inputPatternIncludes?.onlySearchInOpenEditors() ?? false;
1980
+ const useExcludesAndIgnoreFiles = this.inputPatternExcludes?.useExcludesAndIgnoreFiles() ?? true;
1981
+ const preserveCase = this.viewModel.preserveCase;
1982
+ if (this.searchWidget.searchInput) {
1983
+ const isRegex = this.searchWidget.searchInput.getRegex();
1984
+ const isWholeWords = this.searchWidget.searchInput.getWholeWords();
1985
+ const isCaseSensitive = this.searchWidget.searchInput.getCaseSensitive();
1986
+ const contentPattern = this.searchWidget.searchInput.getValue();
1987
+ const isInNotebookCellInput = this.searchWidget.getNotebookFilters().codeInput;
1988
+ const isInNotebookCellOutput = this.searchWidget.getNotebookFilters().codeOutput;
1989
+ const isInNotebookMarkdownInput = this.searchWidget.getNotebookFilters().markupInput;
1990
+ const isInNotebookMarkdownPreview = this.searchWidget.getNotebookFilters().markupPreview;
1991
+ this.viewletState['query.contentPattern'] = contentPattern;
1992
+ this.viewletState['query.regex'] = isRegex;
1993
+ this.viewletState['query.wholeWords'] = isWholeWords;
1994
+ this.viewletState['query.caseSensitive'] = isCaseSensitive;
1995
+ this.viewletState['query.isInNotebookMarkdownInput'] = isInNotebookMarkdownInput;
1996
+ this.viewletState['query.isInNotebookMarkdownPreview'] = isInNotebookMarkdownPreview;
1997
+ this.viewletState['query.isInNotebookCellInput'] = isInNotebookCellInput;
1998
+ this.viewletState['query.isInNotebookCellOutput'] = isInNotebookCellOutput;
1999
+ }
2000
+ this.viewletState['query.folderExclusions'] = patternExcludes;
2001
+ this.viewletState['query.folderIncludes'] = patternIncludes;
2002
+ this.viewletState['query.useExcludesAndIgnoreFiles'] = useExcludesAndIgnoreFiles;
2003
+ this.viewletState['query.preserveCase'] = preserveCase;
2004
+ this.viewletState['query.onlyOpenEditors'] = onlyOpenEditors;
2005
+ const isReplaceShown = this.searchAndReplaceWidget.isReplaceShown();
2006
+ this.viewletState['view.showReplace'] = isReplaceShown;
2007
+ this.viewletState['view.treeLayout'] = this.isTreeLayoutViewVisible;
2008
+ this.viewletState['query.replaceText'] = isReplaceShown && this.searchWidget.getReplaceValue();
2009
+ this._saveSearchHistoryService();
2010
+ this.memento.saveMemento();
2011
+ super.saveState();
2012
+ }
2013
+ _saveSearchHistoryService() {
2014
+ if (this.searchWidget === undefined) {
2015
+ return;
2016
+ }
2017
+ const history = Object.create(null);
2018
+ const searchHistory = this.searchWidget.getSearchHistory();
2019
+ if (searchHistory && searchHistory.length) {
2020
+ history.search = searchHistory;
2021
+ }
2022
+ const replaceHistory = this.searchWidget.getReplaceHistory();
2023
+ if (replaceHistory && replaceHistory.length) {
2024
+ history.replace = replaceHistory;
2025
+ }
2026
+ const patternExcludesHistory = this.inputPatternExcludes.getHistory();
2027
+ if (patternExcludesHistory && patternExcludesHistory.length) {
2028
+ history.exclude = patternExcludesHistory;
2029
+ }
2030
+ const patternIncludesHistory = this.inputPatternIncludes.getHistory();
2031
+ if (patternIncludesHistory && patternIncludesHistory.length) {
2032
+ history.include = patternIncludesHistory;
2033
+ }
2034
+ this.searchHistoryService.save(history);
2035
+ }
2036
+ async retrieveFileStats() {
2037
+ const files = ( this.searchResult.matches(this.aiResultsVisible).filter(f => !f.fileStat).map(f => f.resolveFileStat(this.fileService)));
2038
+ await Promise.all(files);
2039
+ }
2040
+ async updateFileStats(elements) {
2041
+ const files = ( elements.map(f => f.resolveFileStat(this.fileService)));
2042
+ await Promise.all(files);
2043
+ }
2044
+ removeFileStats() {
2045
+ for (const fileMatch of this.searchResult.matches()) {
2046
+ fileMatch.fileStat = undefined;
2047
+ }
2048
+ for (const fileMatch of this.searchResult.matches(true)) {
2049
+ fileMatch.fileStat = undefined;
2050
+ }
2051
+ }
2052
+ dispose() {
2053
+ this.isDisposed = true;
2054
+ this.saveState();
2055
+ super.dispose();
2056
+ }
2057
+ };
2058
+ SearchView = SearchView_1 = ( __decorate([
2059
+ ( __param(1, IFileService)),
2060
+ ( __param(2, IEditorService)),
2061
+ ( __param(3, ICodeEditorService)),
2062
+ ( __param(4, IProgressService)),
2063
+ ( __param(5, INotificationService)),
2064
+ ( __param(6, IDialogService)),
2065
+ ( __param(7, ICommandService)),
2066
+ ( __param(8, IContextViewService)),
2067
+ ( __param(9, IInstantiationService)),
2068
+ ( __param(10, IViewDescriptorService)),
2069
+ ( __param(11, IConfigurationService)),
2070
+ ( __param(12, IWorkspaceContextService)),
2071
+ ( __param(13, ISearchViewModelWorkbenchService)),
2072
+ ( __param(14, IContextKeyService)),
2073
+ ( __param(15, IReplaceService)),
2074
+ ( __param(16, ITextFileService)),
2075
+ ( __param(17, IPreferencesService)),
2076
+ ( __param(18, IThemeService)),
2077
+ ( __param(19, ISearchHistoryService)),
2078
+ ( __param(20, IContextMenuService)),
2079
+ ( __param(21, IAccessibilityService)),
2080
+ ( __param(22, IKeybindingService)),
2081
+ ( __param(23, IStorageService)),
2082
+ ( __param(24, IOpenerService)),
2083
+ ( __param(25, ITelemetryService)),
2084
+ ( __param(26, INotebookService)),
2085
+ ( __param(27, ILogService)),
2086
+ ( __param(28, IAccessibilitySignalService))
2087
+ ], SearchView));
2088
+ class SearchLinkButton extends Disposable {
2089
+ constructor(label, handler, tooltip) {
2090
+ super();
2091
+ this.element = $('a.pointer', { tabindex: 0 }, label);
2092
+ this._register(setupCustomHover(getDefaultHoverDelegate('mouse'), this.element, tooltip));
2093
+ this.addEventHandlers(handler);
2094
+ }
2095
+ addEventHandlers(handler) {
2096
+ const wrappedHandler = (e) => {
2097
+ EventHelper.stop(e, false);
2098
+ handler(e);
2099
+ };
2100
+ this._register(addDisposableListener(this.element, EventType.CLICK, wrappedHandler));
2101
+ this._register(addDisposableListener(this.element, EventType.KEY_DOWN, e => {
2102
+ const event = ( new StandardKeyboardEvent(e));
2103
+ if (event.equals(10 ) || event.equals(3 )) {
2104
+ wrappedHandler(e);
2105
+ event.preventDefault();
2106
+ event.stopPropagation();
2107
+ }
2108
+ }));
2109
+ }
2110
+ }
2111
+ function getEditorSelectionFromMatch(element, viewModel) {
2112
+ let match = null;
2113
+ if (element instanceof Match) {
2114
+ match = element;
2115
+ }
2116
+ if (element instanceof FileMatch && element.count() > 0) {
2117
+ match = element.matches()[element.matches().length - 1];
2118
+ }
2119
+ if (match) {
2120
+ const range = match.range();
2121
+ if (viewModel.isReplaceActive() && !!viewModel.replaceString) {
2122
+ const replaceString = match.replaceString;
2123
+ return {
2124
+ startLineNumber: range.startLineNumber,
2125
+ startColumn: range.startColumn,
2126
+ endLineNumber: range.startLineNumber,
2127
+ endColumn: range.startColumn + replaceString.length
2128
+ };
2129
+ }
2130
+ return range;
2131
+ }
2132
+ return undefined;
2133
+ }
2134
+ function getSelectionTextFromEditor(allowUnselectedWord, activeEditor) {
2135
+ let editor = activeEditor;
2136
+ if (isDiffEditor(editor)) {
2137
+ if (editor.getOriginalEditor().hasTextFocus()) {
2138
+ editor = editor.getOriginalEditor();
2139
+ }
2140
+ else {
2141
+ editor = editor.getModifiedEditor();
2142
+ }
2143
+ }
2144
+ if (!isCodeEditor(editor) || !editor.hasModel()) {
2145
+ return null;
2146
+ }
2147
+ const range = editor.getSelection();
2148
+ if (!range) {
2149
+ return null;
2150
+ }
2151
+ if (range.isEmpty()) {
2152
+ if (allowUnselectedWord) {
2153
+ const wordAtPosition = editor.getModel().getWordAtPosition(range.getStartPosition());
2154
+ return wordAtPosition?.word ?? null;
2155
+ }
2156
+ else {
2157
+ return null;
2158
+ }
2159
+ }
2160
+ let searchText = '';
2161
+ for (let i = range.startLineNumber; i <= range.endLineNumber; i++) {
2162
+ let lineText = editor.getModel().getLineContent(i);
2163
+ if (i === range.endLineNumber) {
2164
+ lineText = lineText.substring(0, range.endColumn - 1);
2165
+ }
2166
+ if (i === range.startLineNumber) {
2167
+ lineText = lineText.substring(range.startColumn - 1);
2168
+ }
2169
+ if (i !== range.startLineNumber) {
2170
+ lineText = '\n' + lineText;
2171
+ }
2172
+ searchText += lineText;
2173
+ }
2174
+ return searchText;
2175
+ }
2176
+
2177
+ export { SearchView, getEditorSelectionFromMatch, getSelectionTextFromEditor };