@theia/search-in-workspace 1.45.0 → 1.46.0-next.72

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 (58) hide show
  1. package/README.md +40 -40
  2. package/lib/browser/components/search-in-workspace-input.d.ts +39 -39
  3. package/lib/browser/components/search-in-workspace-input.js +123 -123
  4. package/lib/browser/components/search-in-workspace-textarea.d.ts +39 -39
  5. package/lib/browser/components/search-in-workspace-textarea.js +130 -130
  6. package/lib/browser/search-in-workspace-context-key-service.d.ts +23 -23
  7. package/lib/browser/search-in-workspace-context-key-service.js +90 -90
  8. package/lib/browser/search-in-workspace-factory.d.ts +10 -10
  9. package/lib/browser/search-in-workspace-factory.js +68 -68
  10. package/lib/browser/search-in-workspace-frontend-contribution.d.ts +57 -55
  11. package/lib/browser/search-in-workspace-frontend-contribution.d.ts.map +1 -1
  12. package/lib/browser/search-in-workspace-frontend-contribution.js +516 -482
  13. package/lib/browser/search-in-workspace-frontend-contribution.js.map +1 -1
  14. package/lib/browser/search-in-workspace-frontend-module.d.ts +6 -6
  15. package/lib/browser/search-in-workspace-frontend-module.js +71 -71
  16. package/lib/browser/search-in-workspace-label-provider.d.ts +9 -9
  17. package/lib/browser/search-in-workspace-label-provider.js +57 -57
  18. package/lib/browser/search-in-workspace-preferences.d.ts +17 -17
  19. package/lib/browser/search-in-workspace-preferences.js +87 -87
  20. package/lib/browser/search-in-workspace-result-tree-widget.d.ts +259 -255
  21. package/lib/browser/search-in-workspace-result-tree-widget.d.ts.map +1 -1
  22. package/lib/browser/search-in-workspace-result-tree-widget.js +1172 -1099
  23. package/lib/browser/search-in-workspace-result-tree-widget.js.map +1 -1
  24. package/lib/browser/search-in-workspace-service.d.ts +35 -35
  25. package/lib/browser/search-in-workspace-service.js +158 -158
  26. package/lib/browser/search-in-workspace-widget.d.ts +121 -121
  27. package/lib/browser/search-in-workspace-widget.js +629 -629
  28. package/lib/browser/search-layout-migrations.d.ts +5 -5
  29. package/lib/browser/search-layout-migrations.js +64 -64
  30. package/lib/common/search-in-workspace-interface.d.ts +116 -116
  31. package/lib/common/search-in-workspace-interface.js +35 -35
  32. package/lib/node/ripgrep-search-in-workspace-server.d.ts +94 -94
  33. package/lib/node/ripgrep-search-in-workspace-server.js +430 -430
  34. package/lib/node/ripgrep-search-in-workspace-server.js.map +1 -1
  35. package/lib/node/ripgrep-search-in-workspace-server.slow-spec.d.ts +1 -1
  36. package/lib/node/ripgrep-search-in-workspace-server.slow-spec.js +899 -899
  37. package/lib/node/ripgrep-search-in-workspace-server.slow-spec.js.map +1 -1
  38. package/lib/node/search-in-workspace-backend-module.d.ts +3 -3
  39. package/lib/node/search-in-workspace-backend-module.js +32 -32
  40. package/package.json +9 -9
  41. package/src/browser/components/search-in-workspace-input.tsx +139 -139
  42. package/src/browser/components/search-in-workspace-textarea.tsx +153 -153
  43. package/src/browser/search-in-workspace-context-key-service.ts +93 -93
  44. package/src/browser/search-in-workspace-factory.ts +59 -59
  45. package/src/browser/search-in-workspace-frontend-contribution.ts +510 -474
  46. package/src/browser/search-in-workspace-frontend-module.ts +83 -83
  47. package/src/browser/search-in-workspace-label-provider.ts +48 -48
  48. package/src/browser/search-in-workspace-preferences.ts +96 -96
  49. package/src/browser/search-in-workspace-result-tree-widget.tsx +1318 -1245
  50. package/src/browser/search-in-workspace-service.ts +152 -152
  51. package/src/browser/search-in-workspace-widget.tsx +727 -727
  52. package/src/browser/search-layout-migrations.ts +53 -53
  53. package/src/browser/styles/index.css +400 -400
  54. package/src/browser/styles/search.svg +6 -6
  55. package/src/common/search-in-workspace-interface.ts +153 -153
  56. package/src/node/ripgrep-search-in-workspace-server.slow-spec.ts +1073 -1073
  57. package/src/node/ripgrep-search-in-workspace-server.ts +490 -490
  58. package/src/node/search-in-workspace-backend-module.ts +33 -33
@@ -1,474 +1,510 @@
1
- // *****************************************************************************
2
- // Copyright (C) 2018 TypeFox and others.
3
- //
4
- // This program and the accompanying materials are made available under the
5
- // terms of the Eclipse Public License v. 2.0 which is available at
6
- // http://www.eclipse.org/legal/epl-2.0.
7
- //
8
- // This Source Code may also be made available under the following Secondary
9
- // Licenses when the conditions for such availability set forth in the Eclipse
10
- // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
- // with the GNU Classpath Exception which is available at
12
- // https://www.gnu.org/software/classpath/license.html.
13
- //
14
- // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
- // *****************************************************************************
16
-
17
- import {
18
- AbstractViewContribution, KeybindingRegistry, LabelProvider, CommonMenus, FrontendApplication,
19
- FrontendApplicationContribution, CommonCommands, StylingParticipant, ColorTheme, CssStyleCollector
20
- } from '@theia/core/lib/browser';
21
- import { SearchInWorkspaceWidget } from './search-in-workspace-widget';
22
- import { injectable, inject, postConstruct } from '@theia/core/shared/inversify';
23
- import { CommandRegistry, MenuModelRegistry, SelectionService, Command, isOSX, nls } from '@theia/core';
24
- import { codicon, Widget } from '@theia/core/lib/browser/widgets';
25
- import { FileNavigatorCommands, NavigatorContextMenu } from '@theia/navigator/lib/browser/navigator-contribution';
26
- import { UriCommandHandler, UriAwareCommandHandler } from '@theia/core/lib/common/uri-command-handler';
27
- import URI from '@theia/core/lib/common/uri';
28
- import { WorkspaceService } from '@theia/workspace/lib/browser';
29
- import { SearchInWorkspaceContextKeyService } from './search-in-workspace-context-key-service';
30
- import { TabBarToolbarContribution, TabBarToolbarRegistry } from '@theia/core/lib/browser/shell/tab-bar-toolbar';
31
- import { EditorManager } from '@theia/editor/lib/browser/editor-manager';
32
- import { Range } from '@theia/core/shared/vscode-languageserver-protocol';
33
- import { FileService } from '@theia/filesystem/lib/browser/file-service';
34
- import { SEARCH_VIEW_CONTAINER_ID } from './search-in-workspace-factory';
35
- import { SearchInWorkspaceFileNode, SearchInWorkspaceResultTreeWidget } from './search-in-workspace-result-tree-widget';
36
- import { TreeWidgetSelection } from '@theia/core/lib/browser/tree/tree-widget-selection';
37
- import { ClipboardService } from '@theia/core/lib/browser/clipboard-service';
38
- import { isHighContrast } from '@theia/core/lib/common/theme';
39
-
40
- export namespace SearchInWorkspaceCommands {
41
- const SEARCH_CATEGORY = 'Search';
42
- export const TOGGLE_SIW_WIDGET = {
43
- id: 'search-in-workspace.toggle'
44
- };
45
- export const OPEN_SIW_WIDGET = Command.toDefaultLocalizedCommand({
46
- id: 'search-in-workspace.open',
47
- category: SEARCH_CATEGORY,
48
- label: 'Find in Files'
49
- });
50
- export const REPLACE_IN_FILES = Command.toDefaultLocalizedCommand({
51
- id: 'search-in-workspace.replace',
52
- category: SEARCH_CATEGORY,
53
- label: 'Replace in Files'
54
- });
55
- export const FIND_IN_FOLDER = Command.toDefaultLocalizedCommand({
56
- id: 'search-in-workspace.in-folder',
57
- category: SEARCH_CATEGORY,
58
- label: 'Find in Folder...'
59
- });
60
- export const REFRESH_RESULTS = Command.toDefaultLocalizedCommand({
61
- id: 'search-in-workspace.refresh',
62
- category: SEARCH_CATEGORY,
63
- label: 'Refresh',
64
- iconClass: codicon('refresh')
65
- });
66
- export const CANCEL_SEARCH = Command.toDefaultLocalizedCommand({
67
- id: 'search-in-workspace.cancel',
68
- category: SEARCH_CATEGORY,
69
- label: 'Cancel Search',
70
- iconClass: codicon('search-stop')
71
- });
72
- export const COLLAPSE_ALL = Command.toDefaultLocalizedCommand({
73
- id: 'search-in-workspace.collapse-all',
74
- category: SEARCH_CATEGORY,
75
- label: 'Collapse All',
76
- iconClass: codicon('collapse-all')
77
- });
78
- export const EXPAND_ALL = Command.toDefaultLocalizedCommand({
79
- id: 'search-in-workspace.expand-all',
80
- category: SEARCH_CATEGORY,
81
- label: 'Expand All',
82
- iconClass: codicon('expand-all')
83
- });
84
- export const CLEAR_ALL = Command.toDefaultLocalizedCommand({
85
- id: 'search-in-workspace.clear-all',
86
- category: SEARCH_CATEGORY,
87
- label: 'Clear Search Results',
88
- iconClass: codicon('clear-all')
89
- });
90
- export const COPY_ALL = Command.toDefaultLocalizedCommand({
91
- id: 'search.action.copyAll',
92
- category: SEARCH_CATEGORY,
93
- label: 'Copy All',
94
- });
95
- export const COPY_ONE = Command.toDefaultLocalizedCommand({
96
- id: 'search.action.copyMatch',
97
- category: SEARCH_CATEGORY,
98
- label: 'Copy',
99
- });
100
- export const DISMISS_RESULT = Command.toDefaultLocalizedCommand({
101
- id: 'search.action.remove',
102
- category: SEARCH_CATEGORY,
103
- label: 'Dismiss',
104
- });
105
- export const REPLACE_RESULT = Command.toDefaultLocalizedCommand({
106
- id: 'search.action.replace',
107
- });
108
- export const REPLACE_ALL_RESULTS = Command.toDefaultLocalizedCommand({
109
- id: 'search.action.replaceAll'
110
- });
111
- }
112
-
113
- @injectable()
114
- export class SearchInWorkspaceFrontendContribution extends AbstractViewContribution<SearchInWorkspaceWidget> implements
115
- FrontendApplicationContribution,
116
- TabBarToolbarContribution,
117
- StylingParticipant {
118
-
119
- @inject(SelectionService) protected readonly selectionService: SelectionService;
120
- @inject(LabelProvider) protected readonly labelProvider: LabelProvider;
121
- @inject(WorkspaceService) protected readonly workspaceService: WorkspaceService;
122
- @inject(FileService) protected readonly fileService: FileService;
123
- @inject(EditorManager) protected readonly editorManager: EditorManager;
124
- @inject(ClipboardService) protected readonly clipboardService: ClipboardService;
125
-
126
- @inject(SearchInWorkspaceContextKeyService)
127
- protected readonly contextKeyService: SearchInWorkspaceContextKeyService;
128
-
129
- constructor() {
130
- super({
131
- viewContainerId: SEARCH_VIEW_CONTAINER_ID,
132
- widgetId: SearchInWorkspaceWidget.ID,
133
- widgetName: SearchInWorkspaceWidget.LABEL,
134
- defaultWidgetOptions: {
135
- area: 'left',
136
- rank: 200
137
- },
138
- toggleCommandId: SearchInWorkspaceCommands.TOGGLE_SIW_WIDGET.id
139
- });
140
- }
141
-
142
- @postConstruct()
143
- protected init(): void {
144
- const updateFocusContextKey = () =>
145
- this.contextKeyService.searchViewletFocus.set(this.shell.activeWidget instanceof SearchInWorkspaceWidget);
146
- updateFocusContextKey();
147
- this.shell.onDidChangeActiveWidget(updateFocusContextKey);
148
- }
149
-
150
- async initializeLayout(app: FrontendApplication): Promise<void> {
151
- await this.openView({ activate: false });
152
- }
153
-
154
- override async registerCommands(commands: CommandRegistry): Promise<void> {
155
- super.registerCommands(commands);
156
- commands.registerCommand(SearchInWorkspaceCommands.OPEN_SIW_WIDGET, {
157
- isEnabled: () => this.workspaceService.tryGetRoots().length > 0,
158
- execute: async () => {
159
- const widget = await this.openView({ activate: true });
160
- widget.updateSearchTerm(this.getSearchTerm());
161
- }
162
- });
163
-
164
- commands.registerCommand(SearchInWorkspaceCommands.REPLACE_IN_FILES, {
165
- isEnabled: () => this.workspaceService.tryGetRoots().length > 0,
166
- execute: async () => {
167
- const widget = await this.openView({ activate: true });
168
- widget.updateSearchTerm(this.getSearchTerm(), true);
169
- }
170
- });
171
-
172
- commands.registerCommand(SearchInWorkspaceCommands.FIND_IN_FOLDER, this.newMultiUriAwareCommandHandler({
173
- execute: async uris => {
174
- const resources: string[] = [];
175
- for (const { stat } of await this.fileService.resolveAll(uris.map(resource => ({ resource })))) {
176
- if (stat) {
177
- const uri = stat.resource;
178
- let uriStr = this.labelProvider.getLongName(uri);
179
- if (stat && !stat.isDirectory) {
180
- uriStr = this.labelProvider.getLongName(uri.parent);
181
- }
182
- resources.push(uriStr);
183
- }
184
- }
185
- const widget = await this.openView({ activate: true });
186
- widget.findInFolder(resources);
187
- }
188
- }));
189
-
190
- commands.registerCommand(SearchInWorkspaceCommands.CANCEL_SEARCH, {
191
- execute: w => this.withWidget(w, widget => widget.getCancelIndicator() && widget.getCancelIndicator()!.cancel()),
192
- isEnabled: w => this.withWidget(w, widget => widget.getCancelIndicator() !== undefined),
193
- isVisible: w => this.withWidget(w, widget => widget.getCancelIndicator() !== undefined)
194
- });
195
- commands.registerCommand(SearchInWorkspaceCommands.REFRESH_RESULTS, {
196
- execute: w => this.withWidget(w, widget => widget.refresh()),
197
- isEnabled: w => this.withWidget(w, widget => (widget.hasResultList() || widget.hasSearchTerm()) && this.workspaceService.tryGetRoots().length > 0),
198
- isVisible: w => this.withWidget(w, () => true)
199
- });
200
- commands.registerCommand(SearchInWorkspaceCommands.COLLAPSE_ALL, {
201
- execute: w => this.withWidget(w, widget => widget.collapseAll()),
202
- isEnabled: w => this.withWidget(w, widget => widget.hasResultList()),
203
- isVisible: w => this.withWidget(w, widget => !widget.areResultsCollapsed())
204
- });
205
- commands.registerCommand(SearchInWorkspaceCommands.EXPAND_ALL, {
206
- execute: w => this.withWidget(w, widget => widget.expandAll()),
207
- isEnabled: w => this.withWidget(w, widget => widget.hasResultList()),
208
- isVisible: w => this.withWidget(w, widget => widget.areResultsCollapsed())
209
- });
210
- commands.registerCommand(SearchInWorkspaceCommands.CLEAR_ALL, {
211
- execute: w => this.withWidget(w, widget => widget.clear()),
212
- isEnabled: w => this.withWidget(w, widget => widget.hasResultList()),
213
- isVisible: w => this.withWidget(w, () => true)
214
- });
215
- commands.registerCommand(SearchInWorkspaceCommands.DISMISS_RESULT, {
216
- isEnabled: () => this.withWidget(undefined, widget => {
217
- const { selection } = this.selectionService;
218
- return TreeWidgetSelection.isSource(selection, widget.resultTreeWidget) && selection.length > 0;
219
- }),
220
- isVisible: () => this.withWidget(undefined, widget => {
221
- const { selection } = this.selectionService;
222
- return TreeWidgetSelection.isSource(selection, widget.resultTreeWidget) && selection.length > 0;
223
- }),
224
- execute: () => this.withWidget(undefined, widget => {
225
- const { selection } = this.selectionService;
226
- if (TreeWidgetSelection.is(selection)) {
227
- selection.forEach(n => widget.resultTreeWidget.removeNode(n));
228
- }
229
- })
230
- });
231
- commands.registerCommand(SearchInWorkspaceCommands.REPLACE_RESULT, {
232
- isEnabled: () => this.withWidget(undefined, widget => {
233
- const { selection } = this.selectionService;
234
- return TreeWidgetSelection.isSource(selection, widget.resultTreeWidget) && selection.length > 0 && !SearchInWorkspaceFileNode.is(selection[0]);
235
- }),
236
- isVisible: () => this.withWidget(undefined, widget => {
237
- const { selection } = this.selectionService;
238
- return TreeWidgetSelection.isSource(selection, widget.resultTreeWidget) && selection.length > 0 && !SearchInWorkspaceFileNode.is(selection[0]);
239
- }),
240
- execute: () => this.withWidget(undefined, widget => {
241
- const { selection } = this.selectionService;
242
- if (TreeWidgetSelection.is(selection)) {
243
- selection.forEach(n => widget.resultTreeWidget.replace(n));
244
- }
245
- }),
246
- });
247
- commands.registerCommand(SearchInWorkspaceCommands.REPLACE_ALL_RESULTS, {
248
- isEnabled: () => this.withWidget(undefined, widget => {
249
- const { selection } = this.selectionService;
250
- return TreeWidgetSelection.isSource(selection, widget.resultTreeWidget) && selection.length > 0
251
- && SearchInWorkspaceFileNode.is(selection[0]);
252
- }),
253
- isVisible: () => this.withWidget(undefined, widget => {
254
- const { selection } = this.selectionService;
255
- return TreeWidgetSelection.isSource(selection, widget.resultTreeWidget) && selection.length > 0
256
- && SearchInWorkspaceFileNode.is(selection[0]);
257
- }),
258
- execute: () => this.withWidget(undefined, widget => {
259
- const { selection } = this.selectionService;
260
- if (TreeWidgetSelection.is(selection)) {
261
- selection.forEach(n => widget.resultTreeWidget.replace(n));
262
- }
263
- }),
264
- });
265
- commands.registerCommand(SearchInWorkspaceCommands.COPY_ONE, {
266
- isEnabled: () => this.withWidget(undefined, widget => {
267
- const { selection } = this.selectionService;
268
- return TreeWidgetSelection.isSource(selection, widget.resultTreeWidget) && selection.length > 0;
269
- }),
270
- isVisible: () => this.withWidget(undefined, widget => {
271
- const { selection } = this.selectionService;
272
- return TreeWidgetSelection.isSource(selection, widget.resultTreeWidget) && selection.length > 0;
273
- }),
274
- execute: () => this.withWidget(undefined, widget => {
275
- const { selection } = this.selectionService;
276
- if (TreeWidgetSelection.is(selection)) {
277
- const string = widget.resultTreeWidget.nodeToString(selection[0], true);
278
- if (string.length !== 0) {
279
- this.clipboardService.writeText(string);
280
- }
281
- }
282
- })
283
- });
284
- commands.registerCommand(SearchInWorkspaceCommands.COPY_ALL, {
285
- isEnabled: () => this.withWidget(undefined, widget => {
286
- const { selection } = this.selectionService;
287
- return TreeWidgetSelection.isSource(selection, widget.resultTreeWidget) && selection.length > 0;
288
- }),
289
- isVisible: () => this.withWidget(undefined, widget => {
290
- const { selection } = this.selectionService;
291
- return TreeWidgetSelection.isSource(selection, widget.resultTreeWidget) && selection.length > 0;
292
- }),
293
- execute: () => this.withWidget(undefined, widget => {
294
- const { selection } = this.selectionService;
295
- if (TreeWidgetSelection.is(selection)) {
296
- const string = widget.resultTreeWidget.treeToString();
297
- if (string.length !== 0) {
298
- this.clipboardService.writeText(string);
299
- }
300
- }
301
- })
302
- });
303
- }
304
-
305
- protected withWidget<T>(widget: Widget | undefined = this.tryGetWidget(), fn: (widget: SearchInWorkspaceWidget) => T): T | false {
306
- if (widget instanceof SearchInWorkspaceWidget && widget.id === SearchInWorkspaceWidget.ID) {
307
- return fn(widget);
308
- }
309
- return false;
310
- }
311
-
312
- /**
313
- * Get the search term based on current editor selection.
314
- * @returns the selection if available.
315
- */
316
- protected getSearchTerm(): string {
317
- if (!this.editorManager.currentEditor) {
318
- return '';
319
- }
320
- // Get the current editor selection.
321
- const selection = this.editorManager.currentEditor.editor.selection;
322
- // Compute the selection range.
323
- const selectedRange: Range = Range.create(
324
- selection.start.line,
325
- selection.start.character,
326
- selection.end.line,
327
- selection.end.character
328
- );
329
- // Return the selection text if available, else return empty.
330
- return this.editorManager.currentEditor
331
- ? this.editorManager.currentEditor.editor.document.getText(selectedRange)
332
- : '';
333
- }
334
-
335
- override registerKeybindings(keybindings: KeybindingRegistry): void {
336
- super.registerKeybindings(keybindings);
337
- keybindings.registerKeybinding({
338
- command: SearchInWorkspaceCommands.OPEN_SIW_WIDGET.id,
339
- keybinding: 'ctrlcmd+shift+f'
340
- });
341
- keybindings.registerKeybinding({
342
- command: SearchInWorkspaceCommands.FIND_IN_FOLDER.id,
343
- keybinding: 'shift+alt+f',
344
- when: 'explorerResourceIsFolder'
345
- });
346
- keybindings.registerKeybinding({
347
- command: SearchInWorkspaceCommands.DISMISS_RESULT.id,
348
- keybinding: isOSX ? 'cmd+backspace' : 'del',
349
- when: 'searchViewletFocus && !inputBoxFocus'
350
- });
351
- keybindings.registerKeybinding({
352
- command: SearchInWorkspaceCommands.REPLACE_RESULT.id,
353
- keybinding: 'ctrlcmd+shift+1',
354
- when: 'searchViewletFocus && replaceActive',
355
- });
356
- keybindings.registerKeybinding({
357
- command: SearchInWorkspaceCommands.REPLACE_ALL_RESULTS.id,
358
- keybinding: 'ctrlcmd+shift+1',
359
- when: 'searchViewletFocus && replaceActive',
360
- });
361
- keybindings.registerKeybinding({
362
- command: SearchInWorkspaceCommands.COPY_ONE.id,
363
- keybinding: 'ctrlcmd+c',
364
- when: 'searchViewletFocus && !inputBoxFocus'
365
- });
366
- }
367
-
368
- override registerMenus(menus: MenuModelRegistry): void {
369
- super.registerMenus(menus);
370
- menus.registerMenuAction(NavigatorContextMenu.SEARCH, {
371
- commandId: SearchInWorkspaceCommands.FIND_IN_FOLDER.id,
372
- when: 'explorerResourceIsFolder'
373
- });
374
- menus.registerMenuAction(CommonMenus.EDIT_FIND, {
375
- commandId: SearchInWorkspaceCommands.OPEN_SIW_WIDGET.id,
376
- order: '2'
377
- });
378
- menus.registerMenuAction(CommonMenus.EDIT_FIND, {
379
- commandId: SearchInWorkspaceCommands.REPLACE_IN_FILES.id,
380
- order: '3'
381
- });
382
- menus.registerMenuAction(SearchInWorkspaceResultTreeWidget.Menus.INTERNAL, {
383
- commandId: SearchInWorkspaceCommands.REPLACE_RESULT.id,
384
- label: nls.localizeByDefault('Replace'),
385
- order: '1',
386
- when: 'replaceActive',
387
- });
388
- menus.registerMenuAction(SearchInWorkspaceResultTreeWidget.Menus.INTERNAL, {
389
- commandId: SearchInWorkspaceCommands.REPLACE_ALL_RESULTS.id,
390
- label: nls.localizeByDefault('Replace All'),
391
- order: '1',
392
- when: 'replaceActive',
393
- });
394
- menus.registerMenuAction(SearchInWorkspaceResultTreeWidget.Menus.INTERNAL, {
395
- commandId: SearchInWorkspaceCommands.DISMISS_RESULT.id,
396
- order: '1'
397
- });
398
- menus.registerMenuAction(SearchInWorkspaceResultTreeWidget.Menus.COPY, {
399
- commandId: SearchInWorkspaceCommands.COPY_ONE.id,
400
- order: '1',
401
- });
402
- menus.registerMenuAction(SearchInWorkspaceResultTreeWidget.Menus.COPY, {
403
- commandId: CommonCommands.COPY_PATH.id,
404
- order: '2',
405
- });
406
- menus.registerMenuAction(SearchInWorkspaceResultTreeWidget.Menus.COPY, {
407
- commandId: SearchInWorkspaceCommands.COPY_ALL.id,
408
- order: '3',
409
- });
410
- menus.registerMenuAction(SearchInWorkspaceResultTreeWidget.Menus.EXTERNAL, {
411
- commandId: FileNavigatorCommands.REVEAL_IN_NAVIGATOR.id,
412
- order: '1',
413
- });
414
- }
415
-
416
- async registerToolbarItems(toolbarRegistry: TabBarToolbarRegistry): Promise<void> {
417
- const widget = await this.widget;
418
- const onDidChange = widget.onDidUpdate;
419
- toolbarRegistry.registerItem({
420
- id: SearchInWorkspaceCommands.CANCEL_SEARCH.id,
421
- command: SearchInWorkspaceCommands.CANCEL_SEARCH.id,
422
- tooltip: SearchInWorkspaceCommands.CANCEL_SEARCH.label,
423
- priority: 0,
424
- onDidChange
425
- });
426
- toolbarRegistry.registerItem({
427
- id: SearchInWorkspaceCommands.REFRESH_RESULTS.id,
428
- command: SearchInWorkspaceCommands.REFRESH_RESULTS.id,
429
- tooltip: SearchInWorkspaceCommands.REFRESH_RESULTS.label,
430
- priority: 1,
431
- onDidChange
432
- });
433
- toolbarRegistry.registerItem({
434
- id: SearchInWorkspaceCommands.CLEAR_ALL.id,
435
- command: SearchInWorkspaceCommands.CLEAR_ALL.id,
436
- tooltip: SearchInWorkspaceCommands.CLEAR_ALL.label,
437
- priority: 2,
438
- onDidChange
439
- });
440
- toolbarRegistry.registerItem({
441
- id: SearchInWorkspaceCommands.COLLAPSE_ALL.id,
442
- command: SearchInWorkspaceCommands.COLLAPSE_ALL.id,
443
- tooltip: SearchInWorkspaceCommands.COLLAPSE_ALL.label,
444
- priority: 3,
445
- onDidChange
446
- });
447
- toolbarRegistry.registerItem({
448
- id: SearchInWorkspaceCommands.EXPAND_ALL.id,
449
- command: SearchInWorkspaceCommands.EXPAND_ALL.id,
450
- tooltip: SearchInWorkspaceCommands.EXPAND_ALL.label,
451
- priority: 3,
452
- onDidChange
453
- });
454
- }
455
-
456
- protected newUriAwareCommandHandler(handler: UriCommandHandler<URI>): UriAwareCommandHandler<URI> {
457
- return UriAwareCommandHandler.MonoSelect(this.selectionService, handler);
458
- }
459
-
460
- protected newMultiUriAwareCommandHandler(handler: UriCommandHandler<URI[]>): UriAwareCommandHandler<URI[]> {
461
- return UriAwareCommandHandler.MultiSelect(this.selectionService, handler);
462
- }
463
-
464
- registerThemeStyle(theme: ColorTheme, collector: CssStyleCollector): void {
465
- const contrastBorder = theme.getColor('contrastBorder');
466
- if (contrastBorder && isHighContrast(theme.type)) {
467
- collector.addRule(`
468
- .t-siw-search-container .searchHeader .search-field-container {
469
- border-color: ${contrastBorder};
470
- }
471
- `);
472
- }
473
- }
474
- }
1
+ // *****************************************************************************
2
+ // Copyright (C) 2018 TypeFox and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import {
18
+ AbstractViewContribution, KeybindingRegistry, LabelProvider, CommonMenus, FrontendApplication,
19
+ FrontendApplicationContribution, CommonCommands, StylingParticipant, ColorTheme, CssStyleCollector
20
+ } from '@theia/core/lib/browser';
21
+ import { SearchInWorkspaceWidget } from './search-in-workspace-widget';
22
+ import { injectable, inject, postConstruct } from '@theia/core/shared/inversify';
23
+ import { CommandRegistry, MenuModelRegistry, SelectionService, Command, isOSX, nls } from '@theia/core';
24
+ import { codicon, Widget } from '@theia/core/lib/browser/widgets';
25
+ import { FileNavigatorCommands, NavigatorContextMenu } from '@theia/navigator/lib/browser/navigator-contribution';
26
+ import { UriCommandHandler, UriAwareCommandHandler } from '@theia/core/lib/common/uri-command-handler';
27
+ import URI from '@theia/core/lib/common/uri';
28
+ import { WorkspaceService } from '@theia/workspace/lib/browser';
29
+ import { SearchInWorkspaceContextKeyService } from './search-in-workspace-context-key-service';
30
+ import { TabBarToolbarContribution, TabBarToolbarRegistry } from '@theia/core/lib/browser/shell/tab-bar-toolbar';
31
+ import { EditorManager } from '@theia/editor/lib/browser/editor-manager';
32
+ import { Range } from '@theia/core/shared/vscode-languageserver-protocol';
33
+ import { FileService } from '@theia/filesystem/lib/browser/file-service';
34
+ import { SEARCH_VIEW_CONTAINER_ID } from './search-in-workspace-factory';
35
+ import { SearchInWorkspaceFileNode, SearchInWorkspaceResultTreeWidget } from './search-in-workspace-result-tree-widget';
36
+ import { TreeWidgetSelection } from '@theia/core/lib/browser/tree/tree-widget-selection';
37
+ import { ClipboardService } from '@theia/core/lib/browser/clipboard-service';
38
+ import { isHighContrast } from '@theia/core/lib/common/theme';
39
+
40
+ export namespace SearchInWorkspaceCommands {
41
+ const SEARCH_CATEGORY = 'Search';
42
+ export const TOGGLE_SIW_WIDGET = {
43
+ id: 'search-in-workspace.toggle'
44
+ };
45
+ export const OPEN_SIW_WIDGET = Command.toDefaultLocalizedCommand({
46
+ id: 'search-in-workspace.open',
47
+ category: SEARCH_CATEGORY,
48
+ label: 'Find in Files'
49
+ });
50
+ export const REPLACE_IN_FILES = Command.toDefaultLocalizedCommand({
51
+ id: 'search-in-workspace.replace',
52
+ category: SEARCH_CATEGORY,
53
+ label: 'Replace in Files'
54
+ });
55
+ export const FIND_IN_FOLDER = Command.toDefaultLocalizedCommand({
56
+ id: 'search-in-workspace.in-folder',
57
+ category: SEARCH_CATEGORY,
58
+ label: 'Find in Folder...'
59
+ });
60
+ export const FOCUS_NEXT_RESULT = Command.toDefaultLocalizedCommand({
61
+ id: 'search.action.focusNextSearchResult',
62
+ category: SEARCH_CATEGORY,
63
+ label: 'Focus Next Search Result'
64
+ });
65
+ export const FOCUS_PREV_RESULT = Command.toDefaultLocalizedCommand({
66
+ id: 'search.action.focusPreviousSearchResult',
67
+ category: SEARCH_CATEGORY,
68
+ label: 'Focus Previous Search Result'
69
+ });
70
+ export const REFRESH_RESULTS = Command.toDefaultLocalizedCommand({
71
+ id: 'search-in-workspace.refresh',
72
+ category: SEARCH_CATEGORY,
73
+ label: 'Refresh',
74
+ iconClass: codicon('refresh')
75
+ });
76
+ export const CANCEL_SEARCH = Command.toDefaultLocalizedCommand({
77
+ id: 'search-in-workspace.cancel',
78
+ category: SEARCH_CATEGORY,
79
+ label: 'Cancel Search',
80
+ iconClass: codicon('search-stop')
81
+ });
82
+ export const COLLAPSE_ALL = Command.toDefaultLocalizedCommand({
83
+ id: 'search-in-workspace.collapse-all',
84
+ category: SEARCH_CATEGORY,
85
+ label: 'Collapse All',
86
+ iconClass: codicon('collapse-all')
87
+ });
88
+ export const EXPAND_ALL = Command.toDefaultLocalizedCommand({
89
+ id: 'search-in-workspace.expand-all',
90
+ category: SEARCH_CATEGORY,
91
+ label: 'Expand All',
92
+ iconClass: codicon('expand-all')
93
+ });
94
+ export const CLEAR_ALL = Command.toDefaultLocalizedCommand({
95
+ id: 'search-in-workspace.clear-all',
96
+ category: SEARCH_CATEGORY,
97
+ label: 'Clear Search Results',
98
+ iconClass: codicon('clear-all')
99
+ });
100
+ export const COPY_ALL = Command.toDefaultLocalizedCommand({
101
+ id: 'search.action.copyAll',
102
+ category: SEARCH_CATEGORY,
103
+ label: 'Copy All',
104
+ });
105
+ export const COPY_ONE = Command.toDefaultLocalizedCommand({
106
+ id: 'search.action.copyMatch',
107
+ category: SEARCH_CATEGORY,
108
+ label: 'Copy',
109
+ });
110
+ export const DISMISS_RESULT = Command.toDefaultLocalizedCommand({
111
+ id: 'search.action.remove',
112
+ category: SEARCH_CATEGORY,
113
+ label: 'Dismiss',
114
+ });
115
+ export const REPLACE_RESULT = Command.toDefaultLocalizedCommand({
116
+ id: 'search.action.replace',
117
+ });
118
+ export const REPLACE_ALL_RESULTS = Command.toDefaultLocalizedCommand({
119
+ id: 'search.action.replaceAll'
120
+ });
121
+ }
122
+
123
+ @injectable()
124
+ export class SearchInWorkspaceFrontendContribution extends AbstractViewContribution<SearchInWorkspaceWidget> implements
125
+ FrontendApplicationContribution,
126
+ TabBarToolbarContribution,
127
+ StylingParticipant {
128
+
129
+ @inject(SelectionService) protected readonly selectionService: SelectionService;
130
+ @inject(LabelProvider) protected readonly labelProvider: LabelProvider;
131
+ @inject(WorkspaceService) protected readonly workspaceService: WorkspaceService;
132
+ @inject(FileService) protected readonly fileService: FileService;
133
+ @inject(EditorManager) protected readonly editorManager: EditorManager;
134
+ @inject(ClipboardService) protected readonly clipboardService: ClipboardService;
135
+
136
+ @inject(SearchInWorkspaceContextKeyService)
137
+ protected readonly contextKeyService: SearchInWorkspaceContextKeyService;
138
+
139
+ constructor() {
140
+ super({
141
+ viewContainerId: SEARCH_VIEW_CONTAINER_ID,
142
+ widgetId: SearchInWorkspaceWidget.ID,
143
+ widgetName: SearchInWorkspaceWidget.LABEL,
144
+ defaultWidgetOptions: {
145
+ area: 'left',
146
+ rank: 200
147
+ },
148
+ toggleCommandId: SearchInWorkspaceCommands.TOGGLE_SIW_WIDGET.id
149
+ });
150
+ }
151
+
152
+ @postConstruct()
153
+ protected init(): void {
154
+ const updateFocusContextKey = () =>
155
+ this.contextKeyService.searchViewletFocus.set(this.shell.activeWidget instanceof SearchInWorkspaceWidget);
156
+ updateFocusContextKey();
157
+ this.shell.onDidChangeActiveWidget(updateFocusContextKey);
158
+ }
159
+
160
+ async initializeLayout(app: FrontendApplication): Promise<void> {
161
+ await this.openView({ activate: false });
162
+ }
163
+
164
+ override async registerCommands(commands: CommandRegistry): Promise<void> {
165
+ super.registerCommands(commands);
166
+ commands.registerCommand(SearchInWorkspaceCommands.OPEN_SIW_WIDGET, {
167
+ isEnabled: () => this.workspaceService.tryGetRoots().length > 0,
168
+ execute: async () => {
169
+ const widget = await this.openView({ activate: true });
170
+ widget.updateSearchTerm(this.getSearchTerm());
171
+ }
172
+ });
173
+
174
+ commands.registerCommand(SearchInWorkspaceCommands.REPLACE_IN_FILES, {
175
+ isEnabled: () => this.workspaceService.tryGetRoots().length > 0,
176
+ execute: async () => {
177
+ const widget = await this.openView({ activate: true });
178
+ widget.updateSearchTerm(this.getSearchTerm(), true);
179
+ }
180
+ });
181
+
182
+ commands.registerCommand(SearchInWorkspaceCommands.FOCUS_NEXT_RESULT, {
183
+ isEnabled: () => this.withWidget(undefined, widget => widget.hasResultList()),
184
+ execute: async () => {
185
+ const widget = await this.openView({ reveal: true });
186
+ widget.resultTreeWidget.selectNextResult();
187
+ }
188
+ });
189
+
190
+ commands.registerCommand(SearchInWorkspaceCommands.FOCUS_PREV_RESULT, {
191
+ isEnabled: () => this.withWidget(undefined, widget => widget.hasResultList()),
192
+ execute: async () => {
193
+ const widget = await this.openView({ reveal: true });
194
+ widget.resultTreeWidget.selectPreviousResult();
195
+ }
196
+ });
197
+
198
+ commands.registerCommand(SearchInWorkspaceCommands.FIND_IN_FOLDER, this.newMultiUriAwareCommandHandler({
199
+ execute: async uris => {
200
+ const resources: string[] = [];
201
+ for (const { stat } of await this.fileService.resolveAll(uris.map(resource => ({ resource })))) {
202
+ if (stat) {
203
+ const uri = stat.resource;
204
+ let uriStr = this.labelProvider.getLongName(uri);
205
+ if (stat && !stat.isDirectory) {
206
+ uriStr = this.labelProvider.getLongName(uri.parent);
207
+ }
208
+ resources.push(uriStr);
209
+ }
210
+ }
211
+ const widget = await this.openView({ activate: true });
212
+ widget.findInFolder(resources);
213
+ }
214
+ }));
215
+
216
+ commands.registerCommand(SearchInWorkspaceCommands.CANCEL_SEARCH, {
217
+ execute: w => this.withWidget(w, widget => widget.getCancelIndicator() && widget.getCancelIndicator()!.cancel()),
218
+ isEnabled: w => this.withWidget(w, widget => widget.getCancelIndicator() !== undefined),
219
+ isVisible: w => this.withWidget(w, widget => widget.getCancelIndicator() !== undefined)
220
+ });
221
+ commands.registerCommand(SearchInWorkspaceCommands.REFRESH_RESULTS, {
222
+ execute: w => this.withWidget(w, widget => widget.refresh()),
223
+ isEnabled: w => this.withWidget(w, widget => (widget.hasResultList() || widget.hasSearchTerm()) && this.workspaceService.tryGetRoots().length > 0),
224
+ isVisible: w => this.withWidget(w, () => true)
225
+ });
226
+ commands.registerCommand(SearchInWorkspaceCommands.COLLAPSE_ALL, {
227
+ execute: w => this.withWidget(w, widget => widget.collapseAll()),
228
+ isEnabled: w => this.withWidget(w, widget => widget.hasResultList()),
229
+ isVisible: w => this.withWidget(w, widget => !widget.areResultsCollapsed())
230
+ });
231
+ commands.registerCommand(SearchInWorkspaceCommands.EXPAND_ALL, {
232
+ execute: w => this.withWidget(w, widget => widget.expandAll()),
233
+ isEnabled: w => this.withWidget(w, widget => widget.hasResultList()),
234
+ isVisible: w => this.withWidget(w, widget => widget.areResultsCollapsed())
235
+ });
236
+ commands.registerCommand(SearchInWorkspaceCommands.CLEAR_ALL, {
237
+ execute: w => this.withWidget(w, widget => widget.clear()),
238
+ isEnabled: w => this.withWidget(w, widget => widget.hasResultList()),
239
+ isVisible: w => this.withWidget(w, () => true)
240
+ });
241
+ commands.registerCommand(SearchInWorkspaceCommands.DISMISS_RESULT, {
242
+ isEnabled: () => this.withWidget(undefined, widget => {
243
+ const { selection } = this.selectionService;
244
+ return TreeWidgetSelection.isSource(selection, widget.resultTreeWidget) && selection.length > 0;
245
+ }),
246
+ isVisible: () => this.withWidget(undefined, widget => {
247
+ const { selection } = this.selectionService;
248
+ return TreeWidgetSelection.isSource(selection, widget.resultTreeWidget) && selection.length > 0;
249
+ }),
250
+ execute: () => this.withWidget(undefined, widget => {
251
+ const { selection } = this.selectionService;
252
+ if (TreeWidgetSelection.is(selection)) {
253
+ selection.forEach(n => widget.resultTreeWidget.removeNode(n));
254
+ }
255
+ })
256
+ });
257
+ commands.registerCommand(SearchInWorkspaceCommands.REPLACE_RESULT, {
258
+ isEnabled: () => this.withWidget(undefined, widget => {
259
+ const { selection } = this.selectionService;
260
+ return TreeWidgetSelection.isSource(selection, widget.resultTreeWidget) && selection.length > 0 && !SearchInWorkspaceFileNode.is(selection[0]);
261
+ }),
262
+ isVisible: () => this.withWidget(undefined, widget => {
263
+ const { selection } = this.selectionService;
264
+ return TreeWidgetSelection.isSource(selection, widget.resultTreeWidget) && selection.length > 0 && !SearchInWorkspaceFileNode.is(selection[0]);
265
+ }),
266
+ execute: () => this.withWidget(undefined, widget => {
267
+ const { selection } = this.selectionService;
268
+ if (TreeWidgetSelection.is(selection)) {
269
+ selection.forEach(n => widget.resultTreeWidget.replace(n));
270
+ }
271
+ }),
272
+ });
273
+ commands.registerCommand(SearchInWorkspaceCommands.REPLACE_ALL_RESULTS, {
274
+ isEnabled: () => this.withWidget(undefined, widget => {
275
+ const { selection } = this.selectionService;
276
+ return TreeWidgetSelection.isSource(selection, widget.resultTreeWidget) && selection.length > 0
277
+ && SearchInWorkspaceFileNode.is(selection[0]);
278
+ }),
279
+ isVisible: () => this.withWidget(undefined, widget => {
280
+ const { selection } = this.selectionService;
281
+ return TreeWidgetSelection.isSource(selection, widget.resultTreeWidget) && selection.length > 0
282
+ && SearchInWorkspaceFileNode.is(selection[0]);
283
+ }),
284
+ execute: () => this.withWidget(undefined, widget => {
285
+ const { selection } = this.selectionService;
286
+ if (TreeWidgetSelection.is(selection)) {
287
+ selection.forEach(n => widget.resultTreeWidget.replace(n));
288
+ }
289
+ }),
290
+ });
291
+ commands.registerCommand(SearchInWorkspaceCommands.COPY_ONE, {
292
+ isEnabled: () => this.withWidget(undefined, widget => {
293
+ const { selection } = this.selectionService;
294
+ return TreeWidgetSelection.isSource(selection, widget.resultTreeWidget) && selection.length > 0;
295
+ }),
296
+ isVisible: () => this.withWidget(undefined, widget => {
297
+ const { selection } = this.selectionService;
298
+ return TreeWidgetSelection.isSource(selection, widget.resultTreeWidget) && selection.length > 0;
299
+ }),
300
+ execute: () => this.withWidget(undefined, widget => {
301
+ const { selection } = this.selectionService;
302
+ if (TreeWidgetSelection.is(selection)) {
303
+ const string = widget.resultTreeWidget.nodeToString(selection[0], true);
304
+ if (string.length !== 0) {
305
+ this.clipboardService.writeText(string);
306
+ }
307
+ }
308
+ })
309
+ });
310
+ commands.registerCommand(SearchInWorkspaceCommands.COPY_ALL, {
311
+ isEnabled: () => this.withWidget(undefined, widget => {
312
+ const { selection } = this.selectionService;
313
+ return TreeWidgetSelection.isSource(selection, widget.resultTreeWidget) && selection.length > 0;
314
+ }),
315
+ isVisible: () => this.withWidget(undefined, widget => {
316
+ const { selection } = this.selectionService;
317
+ return TreeWidgetSelection.isSource(selection, widget.resultTreeWidget) && selection.length > 0;
318
+ }),
319
+ execute: () => this.withWidget(undefined, widget => {
320
+ const { selection } = this.selectionService;
321
+ if (TreeWidgetSelection.is(selection)) {
322
+ const string = widget.resultTreeWidget.treeToString();
323
+ if (string.length !== 0) {
324
+ this.clipboardService.writeText(string);
325
+ }
326
+ }
327
+ })
328
+ });
329
+ }
330
+
331
+ protected withWidget<T>(widget: Widget | undefined = this.tryGetWidget(), fn: (widget: SearchInWorkspaceWidget) => T): T | false {
332
+ if (widget instanceof SearchInWorkspaceWidget && widget.id === SearchInWorkspaceWidget.ID) {
333
+ return fn(widget);
334
+ }
335
+ return false;
336
+ }
337
+
338
+ /**
339
+ * Get the search term based on current editor selection.
340
+ * @returns the selection if available.
341
+ */
342
+ protected getSearchTerm(): string {
343
+ if (!this.editorManager.currentEditor) {
344
+ return '';
345
+ }
346
+ // Get the current editor selection.
347
+ const selection = this.editorManager.currentEditor.editor.selection;
348
+ // Compute the selection range.
349
+ const selectedRange: Range = Range.create(
350
+ selection.start.line,
351
+ selection.start.character,
352
+ selection.end.line,
353
+ selection.end.character
354
+ );
355
+ // Return the selection text if available, else return empty.
356
+ return this.editorManager.currentEditor
357
+ ? this.editorManager.currentEditor.editor.document.getText(selectedRange)
358
+ : '';
359
+ }
360
+
361
+ override registerKeybindings(keybindings: KeybindingRegistry): void {
362
+ super.registerKeybindings(keybindings);
363
+ keybindings.registerKeybinding({
364
+ command: SearchInWorkspaceCommands.OPEN_SIW_WIDGET.id,
365
+ keybinding: 'ctrlcmd+shift+f'
366
+ });
367
+ keybindings.registerKeybinding({
368
+ command: SearchInWorkspaceCommands.FIND_IN_FOLDER.id,
369
+ keybinding: 'shift+alt+f',
370
+ when: 'explorerResourceIsFolder'
371
+ });
372
+ keybindings.registerKeybinding({
373
+ command: SearchInWorkspaceCommands.FOCUS_NEXT_RESULT.id,
374
+ keybinding: 'f4',
375
+ when: 'hasSearchResult'
376
+ });
377
+ keybindings.registerKeybinding({
378
+ command: SearchInWorkspaceCommands.FOCUS_PREV_RESULT.id,
379
+ keybinding: 'shift+f4',
380
+ when: 'hasSearchResult'
381
+ });
382
+ keybindings.registerKeybinding({
383
+ command: SearchInWorkspaceCommands.DISMISS_RESULT.id,
384
+ keybinding: isOSX ? 'cmd+backspace' : 'del',
385
+ when: 'searchViewletFocus && !inputBoxFocus'
386
+ });
387
+ keybindings.registerKeybinding({
388
+ command: SearchInWorkspaceCommands.REPLACE_RESULT.id,
389
+ keybinding: 'ctrlcmd+shift+1',
390
+ when: 'searchViewletFocus && replaceActive',
391
+ });
392
+ keybindings.registerKeybinding({
393
+ command: SearchInWorkspaceCommands.REPLACE_ALL_RESULTS.id,
394
+ keybinding: 'ctrlcmd+shift+1',
395
+ when: 'searchViewletFocus && replaceActive',
396
+ });
397
+ keybindings.registerKeybinding({
398
+ command: SearchInWorkspaceCommands.COPY_ONE.id,
399
+ keybinding: 'ctrlcmd+c',
400
+ when: 'searchViewletFocus && !inputBoxFocus'
401
+ });
402
+ }
403
+
404
+ override registerMenus(menus: MenuModelRegistry): void {
405
+ super.registerMenus(menus);
406
+ menus.registerMenuAction(NavigatorContextMenu.SEARCH, {
407
+ commandId: SearchInWorkspaceCommands.FIND_IN_FOLDER.id,
408
+ when: 'explorerResourceIsFolder'
409
+ });
410
+ menus.registerMenuAction(CommonMenus.EDIT_FIND, {
411
+ commandId: SearchInWorkspaceCommands.OPEN_SIW_WIDGET.id,
412
+ order: '2'
413
+ });
414
+ menus.registerMenuAction(CommonMenus.EDIT_FIND, {
415
+ commandId: SearchInWorkspaceCommands.REPLACE_IN_FILES.id,
416
+ order: '3'
417
+ });
418
+ menus.registerMenuAction(SearchInWorkspaceResultTreeWidget.Menus.INTERNAL, {
419
+ commandId: SearchInWorkspaceCommands.REPLACE_RESULT.id,
420
+ label: nls.localizeByDefault('Replace'),
421
+ order: '1',
422
+ when: 'replaceActive',
423
+ });
424
+ menus.registerMenuAction(SearchInWorkspaceResultTreeWidget.Menus.INTERNAL, {
425
+ commandId: SearchInWorkspaceCommands.REPLACE_ALL_RESULTS.id,
426
+ label: nls.localizeByDefault('Replace All'),
427
+ order: '1',
428
+ when: 'replaceActive',
429
+ });
430
+ menus.registerMenuAction(SearchInWorkspaceResultTreeWidget.Menus.INTERNAL, {
431
+ commandId: SearchInWorkspaceCommands.DISMISS_RESULT.id,
432
+ order: '1'
433
+ });
434
+ menus.registerMenuAction(SearchInWorkspaceResultTreeWidget.Menus.COPY, {
435
+ commandId: SearchInWorkspaceCommands.COPY_ONE.id,
436
+ order: '1',
437
+ });
438
+ menus.registerMenuAction(SearchInWorkspaceResultTreeWidget.Menus.COPY, {
439
+ commandId: CommonCommands.COPY_PATH.id,
440
+ order: '2',
441
+ });
442
+ menus.registerMenuAction(SearchInWorkspaceResultTreeWidget.Menus.COPY, {
443
+ commandId: SearchInWorkspaceCommands.COPY_ALL.id,
444
+ order: '3',
445
+ });
446
+ menus.registerMenuAction(SearchInWorkspaceResultTreeWidget.Menus.EXTERNAL, {
447
+ commandId: FileNavigatorCommands.REVEAL_IN_NAVIGATOR.id,
448
+ order: '1',
449
+ });
450
+ }
451
+
452
+ async registerToolbarItems(toolbarRegistry: TabBarToolbarRegistry): Promise<void> {
453
+ const widget = await this.widget;
454
+ const onDidChange = widget.onDidUpdate;
455
+ toolbarRegistry.registerItem({
456
+ id: SearchInWorkspaceCommands.CANCEL_SEARCH.id,
457
+ command: SearchInWorkspaceCommands.CANCEL_SEARCH.id,
458
+ tooltip: SearchInWorkspaceCommands.CANCEL_SEARCH.label,
459
+ priority: 0,
460
+ onDidChange
461
+ });
462
+ toolbarRegistry.registerItem({
463
+ id: SearchInWorkspaceCommands.REFRESH_RESULTS.id,
464
+ command: SearchInWorkspaceCommands.REFRESH_RESULTS.id,
465
+ tooltip: SearchInWorkspaceCommands.REFRESH_RESULTS.label,
466
+ priority: 1,
467
+ onDidChange
468
+ });
469
+ toolbarRegistry.registerItem({
470
+ id: SearchInWorkspaceCommands.CLEAR_ALL.id,
471
+ command: SearchInWorkspaceCommands.CLEAR_ALL.id,
472
+ tooltip: SearchInWorkspaceCommands.CLEAR_ALL.label,
473
+ priority: 2,
474
+ onDidChange
475
+ });
476
+ toolbarRegistry.registerItem({
477
+ id: SearchInWorkspaceCommands.COLLAPSE_ALL.id,
478
+ command: SearchInWorkspaceCommands.COLLAPSE_ALL.id,
479
+ tooltip: SearchInWorkspaceCommands.COLLAPSE_ALL.label,
480
+ priority: 3,
481
+ onDidChange
482
+ });
483
+ toolbarRegistry.registerItem({
484
+ id: SearchInWorkspaceCommands.EXPAND_ALL.id,
485
+ command: SearchInWorkspaceCommands.EXPAND_ALL.id,
486
+ tooltip: SearchInWorkspaceCommands.EXPAND_ALL.label,
487
+ priority: 3,
488
+ onDidChange
489
+ });
490
+ }
491
+
492
+ protected newUriAwareCommandHandler(handler: UriCommandHandler<URI>): UriAwareCommandHandler<URI> {
493
+ return UriAwareCommandHandler.MonoSelect(this.selectionService, handler);
494
+ }
495
+
496
+ protected newMultiUriAwareCommandHandler(handler: UriCommandHandler<URI[]>): UriAwareCommandHandler<URI[]> {
497
+ return UriAwareCommandHandler.MultiSelect(this.selectionService, handler);
498
+ }
499
+
500
+ registerThemeStyle(theme: ColorTheme, collector: CssStyleCollector): void {
501
+ const contrastBorder = theme.getColor('contrastBorder');
502
+ if (contrastBorder && isHighContrast(theme.type)) {
503
+ collector.addRule(`
504
+ .t-siw-search-container .searchHeader .search-field-container {
505
+ border-color: ${contrastBorder};
506
+ }
507
+ `);
508
+ }
509
+ }
510
+ }