search.contribution.ts 26.5 KB
Newer Older
E
Erich Gamma 已提交
1 2 3 4 5 6 7 8
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

'use strict';

import 'vs/css!./media/search.contribution';
9
import { Registry } from 'vs/platform/registry/common/platform';
S
Sandeep Somavarapu 已提交
10
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
11
import { ViewletRegistry, Extensions as ViewletExtensions, ViewletDescriptor } from 'vs/workbench/browser/viewlet';
S
Sandeep Somavarapu 已提交
12
import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
13
import * as nls from 'vs/nls';
14
import { TPromise } from 'vs/base/common/winjs.base';
I
isidor 已提交
15
import { Action } from 'vs/base/common/actions';
R
Rob Lourens 已提交
16
import * as objects from 'vs/base/common/objects';
17
import * as platform from 'vs/base/common/platform';
I
isidor 已提交
18
import { ExplorerFolderContext, ExplorerRootContext } from 'vs/workbench/parts/files/common/files';
19
import { SyncActionDescriptor, MenuRegistry, MenuId, ICommandAction } from 'vs/platform/actions/common/actions';
B
Benjamin Pasero 已提交
20
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions';
O
Oleg Mihailik 已提交
21
import { QuickOpenHandlerDescriptor, IQuickOpenRegistry, Extensions as QuickOpenExtensions } from 'vs/workbench/browser/quickopen';
22
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
J
Johannes Rieken 已提交
23
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
J
Johannes Rieken 已提交
24
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
25
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
26
import { getSelectionSearchString } from 'vs/editor/contrib/find/findController';
B
Benjamin Pasero 已提交
27
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
J
Johannes Rieken 已提交
28
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
S
Sandeep Somavarapu 已提交
29
import { ITree } from 'vs/base/parts/tree/browser/tree';
30
import * as Constants from 'vs/workbench/parts/search/common/constants';
31 32
import { registerContributions as replaceContributions } from 'vs/workbench/parts/search/browser/replaceContributions';
import { registerContributions as searchWidgetContributions } from 'vs/workbench/parts/search/browser/searchWidget';
33
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
34
import { ToggleCaseSensitiveKeybinding, ToggleRegexKeybinding, ToggleWholeWordKeybinding } from 'vs/editor/contrib/find/findModel';
S
Sandeep Somavarapu 已提交
35
import { ISearchWorkbenchService, SearchWorkbenchService } from 'vs/workbench/parts/search/common/searchModel';
36
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
I
isidor 已提交
37
import { SearchView } from 'vs/workbench/parts/search/browser/searchView';
B
Benjamin Pasero 已提交
38
import { defaultQuickOpenContextKey } from 'vs/workbench/browser/parts/quickopen/quickopen';
39 40
import { OpenSymbolHandler } from 'vs/workbench/parts/search/browser/openSymbolHandler';
import { OpenAnythingHandler } from 'vs/workbench/parts/search/browser/openAnythingHandler';
41
import { registerLanguageCommand } from 'vs/editor/browser/editorExtensions';
42
import { getWorkspaceSymbols } from 'vs/workbench/parts/search/common/search';
I
isidor 已提交
43
import { illegalArgument } from 'vs/base/common/errors';
I
isidor 已提交
44 45 46 47 48
import { WorkbenchListFocusContextKey, IListService } from 'vs/platform/list/browser/listService';
import URI from 'vs/base/common/uri';
import { relative } from 'path';
import { dirname } from 'vs/base/common/resources';
import { ResourceContextKey } from 'vs/workbench/common/resources';
I
isidor 已提交
49
import { IFileService } from 'vs/platform/files/common/files';
50
import { distinct } from 'vs/base/common/arrays';
51
import { getMultiSelectedResources } from 'vs/workbench/parts/files/browser/files';
52
import { Schemas } from 'vs/base/common/network';
I
isidor 已提交
53
import { PanelRegistry, Extensions as PanelExtensions, PanelDescriptor } from 'vs/workbench/browser/panel';
54
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
Y
Yogesh 已提交
55
import { openSearchView, getSearchView, ReplaceAllInFolderAction, ReplaceAllAction, CloseReplaceAction, FocusNextSearchResultAction, FocusPreviousSearchResultAction, ReplaceInFilesAction, FindInFilesAction, toggleCaseSensitiveCommand, toggleRegexCommand, CollapseDeepestExpandedLevelAction, toggleWholeWordCommand, RemoveAction, ReplaceAction, ClearSearchResultsAction, copyPathCommand, copyMatchCommand, copyAllCommand, clearHistoryCommand, FocusNextInputAction, FocusPreviousInputAction, RefreshAction, focusSearchListCommand } from 'vs/workbench/parts/search/browser/searchActions';
56
import { VIEW_ID, ISearchConfigurationProperties } from 'vs/platform/search/common/search';
57 58 59
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { SearchViewLocationUpdater } from 'vs/workbench/parts/search/browser/searchViewLocationUpdater';
60
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
61
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
62

S
Sandeep Somavarapu 已提交
63
registerSingleton(ISearchWorkbenchService, SearchWorkbenchService);
64 65
replaceContributions();
searchWidgetContributions();
E
Erich Gamma 已提交
66

67 68
const category = nls.localize('search', "Search");

A
Alex Dima 已提交
69
KeybindingsRegistry.registerCommandAndKeybindingRule({
E
Erich Gamma 已提交
70
	id: 'workbench.action.search.toggleQueryDetails',
71
	weight: KeybindingWeight.WorkbenchContrib,
I
isidor 已提交
72
	when: Constants.SearchViewVisibleKey,
E
Erich Gamma 已提交
73
	primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_J,
74
	handler: accessor => {
75 76 77 78
		const searchView = getSearchView(accessor.get(IViewletService), accessor.get(IPanelService));
		if (searchView) {
			searchView.toggleQueryDetails();
		}
E
Erich Gamma 已提交
79 80 81
	}
});

S
Sandeep Somavarapu 已提交
82 83
KeybindingsRegistry.registerCommandAndKeybindingRule({
	id: Constants.FocusSearchFromResults,
84
	weight: KeybindingWeight.WorkbenchContrib,
I
isidor 已提交
85
	when: ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.FirstMatchFocusKey),
86
	primary: KeyMod.CtrlCmd | KeyCode.UpArrow,
S
Sandeep Somavarapu 已提交
87
	handler: (accessor, args: any) => {
88
		const searchView = getSearchView(accessor.get(IViewletService), accessor.get(IPanelService));
89
		searchView.focusPreviousInputBox();
S
Sandeep Somavarapu 已提交
90 91 92 93 94
	}
});

KeybindingsRegistry.registerCommandAndKeybindingRule({
	id: Constants.OpenMatchToSide,
95
	weight: KeybindingWeight.WorkbenchContrib,
I
isidor 已提交
96
	when: ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.FileMatchOrMatchFocusKey),
S
Sandeep Somavarapu 已提交
97 98 99 100 101
	primary: KeyMod.CtrlCmd | KeyCode.Enter,
	mac: {
		primary: KeyMod.WinCtrl | KeyCode.Enter
	},
	handler: (accessor, args: any) => {
102
		const searchView = getSearchView(accessor.get(IViewletService), accessor.get(IPanelService));
103 104
		const tree: ITree = searchView.getControl();
		searchView.open(tree.getFocus(), false, true, true);
S
Sandeep Somavarapu 已提交
105 106 107 108 109
	}
});

KeybindingsRegistry.registerCommandAndKeybindingRule({
	id: Constants.CancelActionId,
110
	weight: KeybindingWeight.WorkbenchContrib,
I
isidor 已提交
111
	when: ContextKeyExpr.and(Constants.SearchViewVisibleKey, WorkbenchListFocusContextKey),
S
Sandeep Somavarapu 已提交
112 113
	primary: KeyCode.Escape,
	handler: (accessor, args: any) => {
114
		const searchView = getSearchView(accessor.get(IViewletService), accessor.get(IPanelService));
115
		searchView.cancelSearch();
S
Sandeep Somavarapu 已提交
116 117 118 119 120
	}
});

KeybindingsRegistry.registerCommandAndKeybindingRule({
	id: Constants.RemoveActionId,
121
	weight: KeybindingWeight.WorkbenchContrib,
I
isidor 已提交
122
	when: ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.FileMatchOrMatchFocusKey),
S
Sandeep Somavarapu 已提交
123 124 125 126 127
	primary: KeyCode.Delete,
	mac: {
		primary: KeyMod.CtrlCmd | KeyCode.Backspace,
	},
	handler: (accessor, args: any) => {
128
		const searchView = getSearchView(accessor.get(IViewletService), accessor.get(IPanelService));
129
		const tree: ITree = searchView.getControl();
130
		accessor.get(IInstantiationService).createInstance(RemoveAction, tree, tree.getFocus(), searchView).run();
S
Sandeep Somavarapu 已提交
131 132 133 134 135
	}
});

KeybindingsRegistry.registerCommandAndKeybindingRule({
	id: Constants.ReplaceActionId,
136
	weight: KeybindingWeight.WorkbenchContrib,
I
isidor 已提交
137
	when: ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.ReplaceActiveKey, Constants.MatchFocusKey),
138
	primary: KeyMod.Shift | KeyMod.CtrlCmd | KeyCode.KEY_1,
S
Sandeep Somavarapu 已提交
139
	handler: (accessor, args: any) => {
140
		const searchView = getSearchView(accessor.get(IViewletService), accessor.get(IPanelService));
141
		const tree: ITree = searchView.getControl();
142
		accessor.get(IInstantiationService).createInstance(ReplaceAction, tree, tree.getFocus(), searchView).run();
S
Sandeep Somavarapu 已提交
143 144 145 146 147
	}
});

KeybindingsRegistry.registerCommandAndKeybindingRule({
	id: Constants.ReplaceAllInFileActionId,
148
	weight: KeybindingWeight.WorkbenchContrib,
I
isidor 已提交
149
	when: ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.ReplaceActiveKey, Constants.FileFocusKey),
150 151
	primary: KeyMod.Shift | KeyMod.CtrlCmd | KeyCode.KEY_1,
	secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Enter],
S
Sandeep Somavarapu 已提交
152
	handler: (accessor, args: any) => {
153
		const searchView = getSearchView(accessor.get(IViewletService), accessor.get(IPanelService));
154
		const tree: ITree = searchView.getControl();
155
		accessor.get(IInstantiationService).createInstance(ReplaceAllAction, tree, tree.getFocus(), searchView).run();
S
Sandeep Somavarapu 已提交
156 157 158
	}
});

159 160
KeybindingsRegistry.registerCommandAndKeybindingRule({
	id: Constants.ReplaceAllInFolderActionId,
161
	weight: KeybindingWeight.WorkbenchContrib,
I
isidor 已提交
162
	when: ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.ReplaceActiveKey, Constants.FolderFocusKey),
163 164
	primary: KeyMod.Shift | KeyMod.CtrlCmd | KeyCode.KEY_1,
	secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Enter],
165
	handler: (accessor, args: any) => {
166
		const searchView = getSearchView(accessor.get(IViewletService), accessor.get(IPanelService));
167
		const tree: ITree = searchView.getControl();
168
		accessor.get(IInstantiationService).createInstance(ReplaceAllInFolderAction, tree, tree.getFocus()).run();
169 170 171
	}
});

S
Sandeep Somavarapu 已提交
172 173
KeybindingsRegistry.registerCommandAndKeybindingRule({
	id: Constants.CloseReplaceWidgetActionId,
174
	weight: KeybindingWeight.WorkbenchContrib,
I
isidor 已提交
175
	when: ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.ReplaceInputBoxFocusedKey),
S
Sandeep Somavarapu 已提交
176 177
	primary: KeyCode.Escape,
	handler: (accessor, args: any) => {
178
		accessor.get(IInstantiationService).createInstance(CloseReplaceAction, Constants.CloseReplaceWidgetActionId, '').run();
S
Sandeep Somavarapu 已提交
179 180 181
	}
});

182 183
KeybindingsRegistry.registerCommandAndKeybindingRule({
	id: FocusNextInputAction.ID,
184
	weight: KeybindingWeight.WorkbenchContrib,
185
	when: ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.InputBoxFocusedKey),
186
	primary: KeyMod.CtrlCmd | KeyCode.DownArrow,
187 188 189 190 191 192 193
	handler: (accessor, args: any) => {
		accessor.get(IInstantiationService).createInstance(FocusNextInputAction, FocusNextInputAction.ID, '').run();
	}
});

KeybindingsRegistry.registerCommandAndKeybindingRule({
	id: FocusPreviousInputAction.ID,
194
	weight: KeybindingWeight.WorkbenchContrib,
195
	when: ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.InputBoxFocusedKey, Constants.SearchInputBoxFocusedKey.toNegated()),
196
	primary: KeyMod.CtrlCmd | KeyCode.UpArrow,
197 198 199 200 201
	handler: (accessor, args: any) => {
		accessor.get(IInstantiationService).createInstance(FocusPreviousInputAction, FocusPreviousInputAction.ID, '').run();
	}
});

R
Rob Lourens 已提交
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
MenuRegistry.appendMenuItem(MenuId.SearchContext, {
	command: {
		id: Constants.ReplaceActionId,
		title: ReplaceAction.LABEL
	},
	when: ContextKeyExpr.and(Constants.ReplaceActiveKey, Constants.MatchFocusKey),
	group: 'search',
	order: 1
});

MenuRegistry.appendMenuItem(MenuId.SearchContext, {
	command: {
		id: Constants.ReplaceAllInFolderActionId,
		title: ReplaceAllInFolderAction.LABEL
	},
	when: ContextKeyExpr.and(Constants.ReplaceActiveKey, Constants.FolderFocusKey),
	group: 'search',
	order: 1
});

MenuRegistry.appendMenuItem(MenuId.SearchContext, {
	command: {
		id: Constants.ReplaceAllInFileActionId,
		title: ReplaceAllAction.LABEL
	},
	when: ContextKeyExpr.and(Constants.ReplaceActiveKey, Constants.FileFocusKey),
	group: 'search',
	order: 1
});

MenuRegistry.appendMenuItem(MenuId.SearchContext, {
	command: {
		id: Constants.RemoveActionId,
		title: RemoveAction.LABEL
	},
	when: Constants.FileMatchOrMatchFocusKey,
	group: 'search',
	order: 2
});

R
Rob Lourens 已提交
242 243
KeybindingsRegistry.registerCommandAndKeybindingRule({
	id: Constants.CopyMatchCommandId,
244
	weight: KeybindingWeight.WorkbenchContrib,
R
Rob Lourens 已提交
245 246 247 248 249 250 251 252 253 254 255 256
	when: Constants.FileMatchOrMatchFocusKey,
	primary: KeyMod.CtrlCmd | KeyCode.KEY_C,
	handler: copyMatchCommand
});

MenuRegistry.appendMenuItem(MenuId.SearchContext, {
	command: {
		id: Constants.CopyMatchCommandId,
		title: nls.localize('copyMatchLabel', "Copy")
	},
	when: Constants.FileMatchOrMatchFocusKey,
	group: 'search_2',
R
Rob Lourens 已提交
257
	order: 1
R
Rob Lourens 已提交
258 259
});

260 261
KeybindingsRegistry.registerCommandAndKeybindingRule({
	id: Constants.CopyPathCommandId,
262
	weight: KeybindingWeight.WorkbenchContrib,
263
	when: Constants.FileMatchOrFolderMatchFocusKey,
264 265 266 267 268 269 270 271 272 273 274 275
	primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_C,
	win: {
		primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_C
	},
	handler: copyPathCommand
});

MenuRegistry.appendMenuItem(MenuId.SearchContext, {
	command: {
		id: Constants.CopyPathCommandId,
		title: nls.localize('copyPathLabel', "Copy Path")
	},
276
	when: Constants.FileMatchOrFolderMatchFocusKey,
R
Rob Lourens 已提交
277
	group: 'search_2',
R
Rob Lourens 已提交
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
	order: 2
});

MenuRegistry.appendMenuItem(MenuId.SearchContext, {
	command: {
		id: Constants.CopyAllCommandId,
		title: nls.localize('copyAllLabel', "Copy All")
	},
	when: Constants.HasSearchResults,
	group: 'search_2',
	order: 3
});

CommandsRegistry.registerCommand({
	id: Constants.CopyAllCommandId,
	handler: copyAllCommand
294 295
});

296 297 298 299 300 301 302 303 304 305 306 307 308
CommandsRegistry.registerCommand({
	id: Constants.ClearSearchHistoryCommandId,
	handler: clearHistoryCommand
});

const clearSearchHistoryLabel = nls.localize('clearSearchHistoryLabel', "Clear Search History");
const ClearSearchHistoryCommand: ICommandAction = {
	id: Constants.ClearSearchHistoryCommandId,
	title: clearSearchHistoryLabel,
	category
};
MenuRegistry.addCommand(ClearSearchHistoryCommand);

309 310 311 312 313 314 315 316 317 318 319 320
CommandsRegistry.registerCommand({
	id: Constants.ToggleSearchViewPositionCommandId,
	handler: (accessor) => {
		const configurationService = accessor.get(IConfigurationService);
		const currentValue = configurationService.getValue<ISearchConfigurationProperties>('search').location;
		const toggleValue = currentValue === 'sidebar' ? 'panel' : 'sidebar';

		configurationService.updateValue('search.location', toggleValue);
	}
});

const toggleSearchViewPositionLabel = nls.localize('toggleSearchViewPositionLabel', "Toggle Search View Position");
321 322 323 324 325 326
const ToggleSearchViewPositionCommand: ICommandAction = {
	id: Constants.ToggleSearchViewPositionCommandId,
	title: toggleSearchViewPositionLabel,
	category
};
MenuRegistry.addCommand(ToggleSearchViewPositionCommand);
327
MenuRegistry.appendMenuItem(MenuId.SearchContext, {
328
	command: ToggleSearchViewPositionCommand,
329
	when: Constants.SearchViewVisibleKey,
R
Rob Lourens 已提交
330
	group: 'search_9',
331
	order: 1
332 333
});

Y
Yogesh 已提交
334 335 336 337 338 339 340 341 342 343 344 345 346
CommandsRegistry.registerCommand({
	id: Constants.FocusSearchListCommandID,
	handler: focusSearchListCommand
});

const focusSearchListCommandLabel = nls.localize('focusSearchListCommandLabel', "Focus List");
const FocusSearchListCommand: ICommandAction = {
	id: Constants.FocusSearchListCommandID,
	title: focusSearchListCommandLabel,
	category
};
MenuRegistry.addCommand(FocusSearchListCommand);

I
isidor 已提交
347 348 349 350 351 352
const FIND_IN_FOLDER_ID = 'filesExplorer.findInFolder';
CommandsRegistry.registerCommand({
	id: FIND_IN_FOLDER_ID,
	handler: (accessor, resource?: URI) => {
		const listService = accessor.get(IListService);
		const viewletService = accessor.get(IViewletService);
353
		const panelService = accessor.get(IPanelService);
I
isidor 已提交
354
		const fileService = accessor.get(IFileService);
355
		const resources = getMultiSelectedResources(resource, listService, accessor.get(IEditorService));
I
isidor 已提交
356

357
		return openSearchView(viewletService, panelService, true).then(searchView => {
358 359 360 361 362 363 364 365 366 367
			if (resources && resources.length) {
				return fileService.resolveFiles(resources.map(resource => ({ resource }))).then(results => {
					const folders: URI[] = [];

					results.forEach(result => {
						if (result.success) {
							folders.push(result.stat.isDirectory ? result.stat.resource : dirname(result.stat.resource));
						}
					});

368
					searchView.searchInFolders(distinct(folders, folder => folder.toString()), (from, to) => relative(from, to));
369
				});
370
			}
371 372

			return void 0;
I
isidor 已提交
373
		});
I
isidor 已提交
374 375
	}
});
E
Erich Gamma 已提交
376

R
Rob Lourens 已提交
377 378 379 380 381 382 383
CommandsRegistry.registerCommand({
	id: ClearSearchResultsAction.ID,
	handler: (accessor, args: any) => {
		accessor.get(IInstantiationService).createInstance(ClearSearchResultsAction, ClearSearchResultsAction.ID, '').run();
	}
});

384 385 386 387 388 389 390
CommandsRegistry.registerCommand({
	id: RefreshAction.ID,
	handler: (accessor, args: any) => {
		accessor.get(IInstantiationService).createInstance(RefreshAction, RefreshAction.ID, '').run();
	}
});

I
isidor 已提交
391 392 393
const FIND_IN_WORKSPACE_ID = 'filesExplorer.findInWorkspace';
CommandsRegistry.registerCommand({
	id: FIND_IN_WORKSPACE_ID,
I
isidor 已提交
394
	handler: (accessor) => {
395 396
		return openSearchView(accessor.get(IViewletService), accessor.get(IPanelService), true).then(searchView => {
			searchView.searchInFolders(null, (from, to) => relative(from, to));
I
isidor 已提交
397 398 399
		});
	}
});
E
Erich Gamma 已提交
400

I
isidor 已提交
401
MenuRegistry.appendMenuItem(MenuId.ExplorerContext, {
I
isidor 已提交
402 403
	group: '4_search',
	order: 10,
I
isidor 已提交
404 405 406 407
	command: {
		id: FIND_IN_FOLDER_ID,
		title: nls.localize('findInFolder', "Find in Folder...")
	},
408
	when: ContextKeyExpr.and(ExplorerFolderContext, ResourceContextKey.Scheme.isEqualTo(Schemas.file)) // todo@remote
I
isidor 已提交
409
});
E
Erich Gamma 已提交
410

I
isidor 已提交
411
MenuRegistry.appendMenuItem(MenuId.ExplorerContext, {
I
isidor 已提交
412 413
	group: '4_search',
	order: 10,
I
isidor 已提交
414 415 416 417 418 419
	command: {
		id: FIND_IN_WORKSPACE_ID,
		title: nls.localize('findInWorkspace', "Find in Workspace...")
	},
	when: ContextKeyExpr.and(ExplorerRootContext, ExplorerFolderContext.toNegated())
});
E
Erich Gamma 已提交
420 421


422
class ShowAllSymbolsAction extends Action {
423 424 425
	static readonly ID = 'workbench.action.showAllSymbols';
	static readonly LABEL = nls.localize('showTriggerActions', "Go to Symbol in Workspace...");
	static readonly ALL_SYMBOLS_PREFIX = '#';
E
Erich Gamma 已提交
426

427 428 429 430 431 432 433 434 435 436
	constructor(
		actionId: string, actionLabel: string,
		@IQuickOpenService private quickOpenService: IQuickOpenService,
		@ICodeEditorService private editorService: ICodeEditorService) {
		super(actionId, actionLabel);
		this.enabled = !!this.quickOpenService;
	}

	public run(context?: any): TPromise<void> {

437
		let prefix = ShowAllSymbolsAction.ALL_SYMBOLS_PREFIX;
438
		let inputSelection: { start: number; end: number; } = void 0;
439 440
		let editor = this.editorService.getFocusedCodeEditor();
		const word = editor && getSelectionSearchString(editor);
441 442 443 444
		if (word) {
			prefix = prefix + word;
			inputSelection = { start: 1, end: word.length + 1 };
		}
E
Erich Gamma 已提交
445

446 447 448
		this.quickOpenService.show(prefix, { inputSelection });

		return TPromise.as(null);
E
Erich Gamma 已提交
449 450 451
	}
}

452
// Register View in Viewlet and Panel area
453 454
Registry.as<ViewletRegistry>(ViewletExtensions.Viewlets).registerViewlet(new ViewletDescriptor(
	SearchView,
455
	VIEW_ID,
456 457
	nls.localize('name', "Search"),
	'search',
458
	1
459
));
I
isidor 已提交
460 461

Registry.as<PanelRegistry>(PanelExtensions.Panels).registerPanel(new PanelDescriptor(
462
	SearchView,
463
	VIEW_ID,
E
Erich Gamma 已提交
464 465 466 467 468
	nls.localize('name', "Search"),
	'search',
	10
));

469
// Register view location updater
470
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(SearchViewLocationUpdater, LifecyclePhase.Restoring);
471

S
Sandeep Somavarapu 已提交
472
// Actions
B
Benjamin Pasero 已提交
473
const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
E
Erich Gamma 已提交
474

475 476 477
// Show Search and Find in Files are redundant, but we can't break keybindings by removing one. So it's the same action, same keybinding, registered to different IDs.
// Show Search 'when' is redundant but if the two conflict with exactly the same keybinding and 'when' clause, then they can show up as "unbound" - #51780
registry.registerWorkbenchAction(new SyncActionDescriptor(FindInFilesAction, VIEW_ID, nls.localize('showSearchViewl', "Show Search"), { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_F }, Constants.SearchViewVisibleKey.toNegated()), 'View: Show Search', nls.localize('view', "View"));
478
registry.registerWorkbenchAction(new SyncActionDescriptor(FindInFilesAction, Constants.FindInFilesActionId, nls.localize('findInFiles', "Find in Files"), { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_F }), 'Find in Files', category);
479 480 481 482 483 484 485 486
MenuRegistry.appendMenuItem(MenuId.MenubarEditMenu, {
	group: '4_find_global',
	command: {
		id: Constants.FindInFilesActionId,
		title: nls.localize({ key: 'miFindInFiles', comment: ['&& denotes a mnemonic'] }, "Find &&in Files")
	},
	order: 1
});
487

488 489
registry.registerWorkbenchAction(new SyncActionDescriptor(FocusNextSearchResultAction, FocusNextSearchResultAction.ID, FocusNextSearchResultAction.LABEL, { primary: KeyCode.F4 }, ContextKeyExpr.and(Constants.HasSearchResults)), 'Focus Next Search Result', category);
registry.registerWorkbenchAction(new SyncActionDescriptor(FocusPreviousSearchResultAction, FocusPreviousSearchResultAction.ID, FocusPreviousSearchResultAction.LABEL, { primary: KeyMod.Shift | KeyCode.F4 }, ContextKeyExpr.and(Constants.HasSearchResults)), 'Focus Previous Search Result', category);
490

491
registry.registerWorkbenchAction(new SyncActionDescriptor(ReplaceInFilesAction, ReplaceInFilesAction.ID, ReplaceInFilesAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_H }), 'Replace in Files', category);
492 493 494 495 496 497 498 499
MenuRegistry.appendMenuItem(MenuId.MenubarEditMenu, {
	group: '4_find_global',
	command: {
		id: ReplaceInFilesAction.ID,
		title: nls.localize({ key: 'miReplaceInFiles', comment: ['&& denotes a mnemonic'] }, "Replace &&in Files")
	},
	order: 2
});
S
Sandeep Somavarapu 已提交
500

R
Rob Lourens 已提交
501
KeybindingsRegistry.registerCommandAndKeybindingRule(objects.assign({
R
Rob Lourens 已提交
502
	id: Constants.ToggleCaseSensitiveCommandId,
503
	weight: KeybindingWeight.WorkbenchContrib,
I
isidor 已提交
504
	when: ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.SearchInputBoxFocusedKey),
505
	handler: toggleCaseSensitiveCommand
R
Rob Lourens 已提交
506 507 508
}, ToggleCaseSensitiveKeybinding));

KeybindingsRegistry.registerCommandAndKeybindingRule(objects.assign({
R
Rob Lourens 已提交
509
	id: Constants.ToggleWholeWordCommandId,
510
	weight: KeybindingWeight.WorkbenchContrib,
I
isidor 已提交
511
	when: ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.SearchInputBoxFocusedKey),
512
	handler: toggleWholeWordCommand
R
Rob Lourens 已提交
513 514 515
}, ToggleWholeWordKeybinding));

KeybindingsRegistry.registerCommandAndKeybindingRule(objects.assign({
R
Rob Lourens 已提交
516
	id: Constants.ToggleRegexCommandId,
517
	weight: KeybindingWeight.WorkbenchContrib,
I
isidor 已提交
518
	when: ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.SearchInputBoxFocusedKey),
519
	handler: toggleRegexCommand
R
Rob Lourens 已提交
520
}, ToggleRegexKeybinding));
S
Sandeep Somavarapu 已提交
521

522
registry.registerWorkbenchAction(new SyncActionDescriptor(CollapseDeepestExpandedLevelAction, CollapseDeepestExpandedLevelAction.ID, CollapseDeepestExpandedLevelAction.LABEL), 'Search: Collapse All', category);
523 524
registry.registerWorkbenchAction(new SyncActionDescriptor(ShowAllSymbolsAction, ShowAllSymbolsAction.ID, ShowAllSymbolsAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_T }), 'Go to Symbol in Workspace...');

S
Sandeep Somavarapu 已提交
525

E
Erich Gamma 已提交
526
// Register Quick Open Handler
B
Benjamin Pasero 已提交
527
Registry.as<IQuickOpenRegistry>(QuickOpenExtensions.Quickopen).registerDefaultQuickOpenHandler(
E
Erich Gamma 已提交
528
	new QuickOpenHandlerDescriptor(
529 530
		OpenAnythingHandler,
		OpenAnythingHandler.ID,
E
Erich Gamma 已提交
531
		'',
532
		defaultQuickOpenContextKey,
B
Benjamin Pasero 已提交
533
		nls.localize('openAnythingHandlerDescription', "Go to File")
E
Erich Gamma 已提交
534 535 536
	)
);

B
Benjamin Pasero 已提交
537
Registry.as<IQuickOpenRegistry>(QuickOpenExtensions.Quickopen).registerQuickOpenHandler(
538
	new QuickOpenHandlerDescriptor(
539 540
		OpenSymbolHandler,
		OpenSymbolHandler.ID,
541
		ShowAllSymbolsAction.ALL_SYMBOLS_PREFIX,
542
		'inWorkspaceSymbolsPicker',
543 544
		[
			{
545
				prefix: ShowAllSymbolsAction.ALL_SYMBOLS_PREFIX,
546
				needsEditor: false,
B
Benjamin Pasero 已提交
547
				description: nls.localize('openSymbolDescriptionNormal', "Go to Symbol in Workspace")
548 549 550 551 552
			}
		]
	)
);

E
Erich Gamma 已提交
553
// Configuration
B
Benjamin Pasero 已提交
554
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
E
Erich Gamma 已提交
555
configurationRegistry.registerConfiguration({
556 557 558 559 560
	id: 'search',
	order: 13,
	title: nls.localize('searchConfigurationTitle', "Search"),
	type: 'object',
	properties: {
E
Erich Gamma 已提交
561
		'search.exclude': {
562
			type: 'object',
563
			description: nls.localize('exclude', "Configure glob patterns for excluding files and folders in searches. Inherits all glob patterns from the [`files.exclude`](#files-exclude) setting. Read more about glob patterns [here](https://code.visualstudio.com/docs/editor/codebasics#_advanced-search-options)."),
564 565 566
			default: { '**/node_modules': true, '**/bower_components': true },
			additionalProperties: {
				anyOf: [
E
Erich Gamma 已提交
567
					{
568 569
						type: 'boolean',
						description: nls.localize('exclude.boolean', "The glob pattern to match file paths against. Set to true or false to enable or disable the pattern."),
E
Erich Gamma 已提交
570 571
					},
					{
572 573 574 575 576 577 578
						type: 'object',
						properties: {
							when: {
								type: 'string', // expression ({ "**/*.js": { "when": "$(basename).js" } })
								pattern: '\\w*\\$\\(basename\\)\\w*',
								default: '$(basename).ext',
								description: nls.localize('exclude.when', 'Additional check on the siblings of a matching file. Use $(basename) as variable for the matching file name.')
E
Erich Gamma 已提交
579 580 581 582
							}
						}
					}
				]
S
Sandeep Somavarapu 已提交
583
			},
584
			scope: ConfigurationScope.RESOURCE
585
		},
586
		'search.useRipgrep': {
587 588 589
			type: 'boolean',
			description: nls.localize('useRipgrep', "Controls whether to use ripgrep in text and file search"),
			default: true
590
		},
591
		'search.useIgnoreFiles': {
592 593 594 595
			type: 'boolean',
			description: nls.localize('useIgnoreFiles', "Controls whether to use .gitignore and .ignore files when searching for files."),
			default: true,
			scope: ConfigurationScope.RESOURCE
596
		},
597
		'search.quickOpen.includeSymbols': {
598 599 600
			type: 'boolean',
			description: nls.localize('search.quickOpen.includeSymbols', "Configure to include results from a global symbol search in the file results for Quick Open."),
			default: false
601 602
		},
		'search.followSymlinks': {
603 604 605
			type: 'boolean',
			description: nls.localize('search.followSymlinks', "Controls whether to follow symlinks while searching."),
			default: true
606 607
		},
		'search.smartCase': {
608 609 610
			type: 'boolean',
			description: nls.localize('search.smartCase', "Searches case-insensitively if the pattern is all lowercase, otherwise, searches case-sensitively"),
			default: false
611 612
		},
		'search.globalFindClipboard': {
613 614
			type: 'boolean',
			default: false,
B
Benjamin Pasero 已提交
615
			description: nls.localize('search.globalFindClipboard', "Controls if the search view should read or modify the shared find clipboard on macOS"),
616 617 618
			included: platform.isMacintosh
		},
		'search.location': {
619
			type: 'string',
620 621
			enum: ['sidebar', 'panel'],
			default: 'sidebar',
622
			description: nls.localize('search.location', "Controls if the search will be shown as a view in the sidebar or as a panel in the panel area for more horizontal space."),
623
		}
E
Erich Gamma 已提交
624
	}
J
Johannes Rieken 已提交
625
});
626

627
registerLanguageCommand('_executeWorkspaceSymbolProvider', function (accessor, args: { query: string; }) {
628 629 630 631 632 633
	let { query } = args;
	if (typeof query !== 'string') {
		throw illegalArgument();
	}
	return getWorkspaceSymbols(query);
});
634 635 636 637 638 639 640 641 642 643 644

// View menu

MenuRegistry.appendMenuItem(MenuId.MenubarViewMenu, {
	group: '3_views',
	command: {
		id: VIEW_ID,
		title: nls.localize({ key: 'miViewSearch', comment: ['&& denotes a mnemonic'] }, "&&Search")
	},
	order: 2
});