findController.ts 21.6 KB
Newer Older
1 2 3 4 5 6 7
/*---------------------------------------------------------------------------------------------
 *  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 * as nls from 'vs/nls';
J
Johannes Rieken 已提交
8
import { HistoryNavigator } from 'vs/base/common/history';
9
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
J
Johannes Rieken 已提交
10
import { Disposable } from 'vs/base/common/lifecycle';
11
import { ContextKeyExpr, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
12
import * as strings from 'vs/base/common/strings';
A
Alex Dima 已提交
13
import * as editorCommon from 'vs/editor/common/editorCommon';
14 15
import { registerEditorContribution, registerEditorAction, ServicesAccessor, EditorAction, EditorCommand, registerEditorCommand } from 'vs/editor/browser/editorExtensions';
import { FIND_IDS, FindModelBoundToEditorModel, ToggleCaseSensitiveKeybinding, ToggleRegexKeybinding, ToggleWholeWordKeybinding, ToggleSearchScopeKeybinding, ShowPreviousFindTermKeybinding, ShowNextFindTermKeybinding, CONTEXT_FIND_WIDGET_VISIBLE, CONTEXT_FIND_INPUT_FOCUSED } from 'vs/editor/contrib/find/findModel';
16
import { FindReplaceState, FindReplaceStateChangedEvent, INewFindReplaceState } from 'vs/editor/contrib/find/findState';
17
import { Delayer } from 'vs/base/common/async';
18
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
19
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
20 21 22 23 24 25 26
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { FindWidget, IFindController } from 'vs/editor/contrib/find/findWidget';
import { FindOptionsWidget } from 'vs/editor/contrib/find/findOptionsWidget';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
A
Alex Dima 已提交
27

28
export function getSelectionSearchString(editor: ICodeEditor): string {
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
	let selection = editor.getSelection();

	// if selection spans multiple lines, default search string to empty
	if (selection.startLineNumber === selection.endLineNumber) {
		if (selection.isEmpty()) {
			let wordAtPosition = editor.getModel().getWordAtPosition(selection.getStartPosition());
			if (wordAtPosition) {
				return wordAtPosition.word;
			}
		} else {
			return editor.getModel().getValueInRange(selection);
		}
	}

	return null;
}

A
Alex Dima 已提交
46
export const enum FindStartFocusAction {
47 48 49 50 51 52
	NoFocusChange,
	FocusFindInput,
	FocusReplaceInput
}

export interface IFindStartOptions {
53 54 55 56
	forceRevealReplace: boolean;
	seedSearchStringFromSelection: boolean;
	shouldFocus: FindStartFocusAction;
	shouldAnimate: boolean;
57 58
}

A
Alex Dima 已提交
59
export class CommonFindController extends Disposable implements editorCommon.IEditorContribution {
60

61
	private static ID = 'editor.contrib.findController';
62

63
	private _editor: ICodeEditor;
A
Alex Dima 已提交
64
	private _findWidgetVisible: IContextKey<boolean>;
65
	protected _state: FindReplaceState;
66
	private _currentHistoryNavigator: HistoryNavigator<string>;
S
Sandeep Somavarapu 已提交
67
	protected _updateHistoryDelayer: Delayer<void>;
68
	private _model: FindModelBoundToEditorModel;
69
	private _storageService: IStorageService;
70

71
	public static get(editor: ICodeEditor): CommonFindController {
A
Alex Dima 已提交
72
		return editor.getContribution<CommonFindController>(CommonFindController.ID);
73 74
	}

75
	constructor(editor: ICodeEditor, @IContextKeyService contextKeyService: IContextKeyService, @IStorageService storageService: IStorageService) {
76 77
		super();
		this._editor = editor;
78
		this._findWidgetVisible = CONTEXT_FIND_WIDGET_VISIBLE.bindTo(contextKeyService);
79
		this._storageService = storageService;
80

81 82
		this._updateHistoryDelayer = new Delayer<void>(500);
		this._currentHistoryNavigator = new HistoryNavigator<string>();
83
		this._state = this._register(new FindReplaceState());
84
		this.loadQueryState();
85 86 87 88
		this._register(this._state.addChangeListener((e) => this._onStateChanged(e)));

		this._model = null;

A
Alex Dima 已提交
89
		this._register(this._editor.onDidChangeModel(() => {
90 91 92 93
			let shouldRestartFind = (this._editor.getModel() && this._state.isRevealed);

			this.disposeModel();

94
			this._state.change({
95 96 97 98
				searchScope: null,
				matchCase: this._storageService.getBoolean('editor.matchCase', StorageScope.WORKSPACE, false),
				wholeWord: this._storageService.getBoolean('editor.wholeWord', StorageScope.WORKSPACE, false),
				isRegex: this._storageService.getBoolean('editor.isRegex', StorageScope.WORKSPACE, false)
99 100
			}, false);

101 102 103 104 105
			if (shouldRestartFind) {
				this._start({
					forceRevealReplace: false,
					seedSearchStringFromSelection: false,
					shouldFocus: FindStartFocusAction.NoFocusChange,
106
					shouldAnimate: false,
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
				});
			}
		}));
	}

	public dispose(): void {
		this.disposeModel();
		super.dispose();
	}

	private disposeModel(): void {
		if (this._model) {
			this._model.dispose();
			this._model = null;
		}
	}

	public getId(): string {
		return CommonFindController.ID;
	}

128
	private _onStateChanged(e: FindReplaceStateChangedEvent): void {
129 130
		this.saveQueryState(e);

131 132 133
		if (e.updateHistory && e.searchString) {
			this._delayedUpdateHistory();
		}
134 135 136 137 138 139 140 141 142 143
		if (e.isRevealed) {
			if (this._state.isRevealed) {
				this._findWidgetVisible.set(true);
			} else {
				this._findWidgetVisible.reset();
				this.disposeModel();
			}
		}
	}

144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
	private saveQueryState(e: FindReplaceStateChangedEvent) {
		if (e.isRegex && typeof this._state.isRegex !== 'undefined') {
			this._storageService.store('editor.isRegex', this._state.isRegex, StorageScope.WORKSPACE);
		}
		if (e.wholeWord && typeof this._state.wholeWord !== 'undefined') {
			this._storageService.store('editor.wholeWord', this._state.wholeWord, StorageScope.WORKSPACE);
		}
		if (e.matchCase && typeof this._state.matchCase !== 'undefined') {
			this._storageService.store('editor.matchCase', this._state.matchCase, StorageScope.WORKSPACE);
		}
	}

	private loadQueryState() {
		this._state.change({
			matchCase: this._storageService.getBoolean('editor.matchCase', StorageScope.WORKSPACE, this._state.matchCase),
			wholeWord: this._storageService.getBoolean('editor.wholeWord', StorageScope.WORKSPACE, this._state.wholeWord),
			isRegex: this._storageService.getBoolean('editor.isRegex', StorageScope.WORKSPACE, this._state.isRegex)
		}, false);
	}

164 165 166 167 168 169 170 171 172 173
	protected _delayedUpdateHistory() {
		this._updateHistoryDelayer.trigger(this._updateHistory.bind(this));
	}

	protected _updateHistory() {
		if (this._state.searchString) {
			this._currentHistoryNavigator.add(this._state.searchString);
		}
	}

174 175 176 177
	public getState(): FindReplaceState {
		return this._state;
	}

178 179 180 181
	public getHistory(): HistoryNavigator<string> {
		return this._currentHistoryNavigator;
	}

182
	public closeFindWidget(): void {
183 184 185 186
		this._state.change({
			isRevealed: false,
			searchScope: null
		}, false);
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
		this._editor.focus();
	}

	public toggleCaseSensitive(): void {
		this._state.change({ matchCase: !this._state.matchCase }, false);
	}

	public toggleWholeWords(): void {
		this._state.change({ wholeWord: !this._state.wholeWord }, false);
	}

	public toggleRegex(): void {
		this._state.change({ isRegex: !this._state.isRegex }, false);
	}

202 203 204 205 206 207 208 209 210 211 212 213 214 215
	public toggleSearchScope(): void {
		if (this._state.searchScope) {
			this._state.change({ searchScope: null }, true);
		} else {
			let selection = this._editor.getSelection();
			if (selection.endColumn === 1 && selection.endLineNumber > selection.startLineNumber) {
				selection = selection.setEndPosition(selection.endLineNumber - 1, 1);
			}
			if (!selection.isEmpty()) {
				this._state.change({ searchScope: selection }, true);
			}
		}
	}

216
	public setSearchString(searchString: string): void {
217 218 219
		this._state.change({ searchString: searchString }, false);
	}

220 221 222 223
	public highlightFindOptions(): void {
		// overwritten in subclass
	}

224
	protected _start(opts: IFindStartOptions): void {
225 226 227 228 229 230 231 232 233 234 235 236
		this.disposeModel();

		if (!this._editor.getModel()) {
			// cannot do anything with an editor that doesn't have a model...
			return;
		}

		let stateChanges: INewFindReplaceState = {
			isRevealed: true
		};

		// Consider editor selection and overwrite the state with it
237
		if (opts.seedSearchStringFromSelection && this._editor.getConfiguration().contribInfo.find.seedSearchStringFromSelection) {
238
			let selectionSearchString = getSelectionSearchString(this._editor);
239
			if (selectionSearchString) {
240 241 242 243 244
				if (this._state.isRegex) {
					stateChanges.searchString = strings.escapeRegExpCharacters(selectionSearchString);
				} else {
					stateChanges.searchString = selectionSearchString;
				}
245 246 247 248 249 250
			}
		}

		// Overwrite isReplaceRevealed
		if (opts.forceRevealReplace) {
			stateChanges.isReplaceRevealed = true;
251 252
		} else if (!this._findWidgetVisible.get()) {
			stateChanges.isReplaceRevealed = false;
253 254
		}

255

256 257 258 259 260 261 262
		this._state.change(stateChanges, false);

		if (!this._model) {
			this._model = new FindModelBoundToEditorModel(this._editor, this._state);
		}
	}

263
	public start(opts: IFindStartOptions): void {
264
		this._start(opts);
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
	}

	public moveToNextMatch(): boolean {
		if (this._model) {
			this._model.moveToNextMatch();
			return true;
		}
		return false;
	}

	public moveToPrevMatch(): boolean {
		if (this._model) {
			this._model.moveToPrevMatch();
			return true;
		}
		return false;
	}

	public replace(): boolean {
		if (this._model) {
			this._model.replace();
			return true;
		}
		return false;
	}

	public replaceAll(): boolean {
		if (this._model) {
			this._model.replaceAll();
			return true;
		}
		return false;
	}
I
Inori 已提交
298 299 300

	public selectAllMatches(): boolean {
		if (this._model) {
I
Inori 已提交
301
			this._model.selectAllMatches();
302
			this._editor.focus();
I
Inori 已提交
303 304 305 306
			return true;
		}
		return false;
	}
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322

	public showPreviousFindTerm(): boolean {
		let previousTerm = this._currentHistoryNavigator.previous();
		if (previousTerm) {
			this._state.change({ searchString: previousTerm }, false, false);
		}
		return true;
	}

	public showNextFindTerm(): boolean {
		let nextTerm = this._currentHistoryNavigator.next();
		if (nextTerm) {
			this._state.change({ searchString: nextTerm }, false, false);
		}
		return true;
	}
323 324
}

325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362
export class FindController extends CommonFindController implements IFindController {

	private _widget: FindWidget;
	private _findOptionsWidget: FindOptionsWidget;

	constructor(
		editor: ICodeEditor,
		@IContextViewService contextViewService: IContextViewService,
		@IContextKeyService contextKeyService: IContextKeyService,
		@IKeybindingService keybindingService: IKeybindingService,
		@IThemeService themeService: IThemeService,
		@IStorageService storageService: IStorageService
	) {
		super(editor, contextKeyService, storageService);

		this._widget = this._register(new FindWidget(editor, this, this._state, contextViewService, keybindingService, contextKeyService, themeService));
		this._findOptionsWidget = this._register(new FindOptionsWidget(editor, this._state, keybindingService, themeService));
	}

	protected _start(opts: IFindStartOptions): void {
		super._start(opts);

		if (opts.shouldFocus === FindStartFocusAction.FocusReplaceInput) {
			this._widget.focusReplaceInput();
		} else if (opts.shouldFocus === FindStartFocusAction.FocusFindInput) {
			this._widget.focusFindInput();
		}
	}

	public highlightFindOptions(): void {
		if (this._state.isRevealed) {
			this._widget.highlightFindOptions();
		} else {
			this._findOptionsWidget.highlightFindOptions();
		}
	}
}

A
Alex Dima 已提交
363
export class StartFindAction extends EditorAction {
364

A
Alex Dima 已提交
365
	constructor() {
366 367
		super({
			id: FIND_IDS.StartFindAction,
368
			label: nls.localize('startFindAction', "Find"),
369 370 371 372
			alias: 'Find',
			precondition: null,
			kbOpts: {
				kbExpr: null,
373 374 375 376 377
				primary: KeyMod.CtrlCmd | KeyCode.KEY_F,
				mac: {
					primary: KeyMod.CtrlCmd | KeyCode.KEY_F,
					secondary: [KeyMod.CtrlCmd | KeyCode.KEY_E]
				}
378 379
			}
		});
380 381
	}

382
	public run(accessor: ServicesAccessor, editor: ICodeEditor): void {
A
Alex Dima 已提交
383
		let controller = CommonFindController.get(editor);
384 385 386 387 388 389 390 391
		if (controller) {
			controller.start({
				forceRevealReplace: false,
				seedSearchStringFromSelection: true,
				shouldFocus: FindStartFocusAction.FocusFindInput,
				shouldAnimate: true
			});
		}
392 393 394
	}
}

A
Alex Dima 已提交
395
export abstract class MatchFindAction extends EditorAction {
396
	public run(accessor: ServicesAccessor, editor: ICodeEditor): void {
A
Alex Dima 已提交
397
		let controller = CommonFindController.get(editor);
398
		if (controller && !this._run(controller)) {
399 400 401 402 403 404
			controller.start({
				forceRevealReplace: false,
				seedSearchStringFromSelection: (controller.getState().searchString.length === 0),
				shouldFocus: FindStartFocusAction.NoFocusChange,
				shouldAnimate: true
			});
405
			this._run(controller);
406 407
		}
	}
408

409
	protected abstract _run(controller: CommonFindController): boolean;
410 411
}

412
export class NextMatchFindAction extends MatchFindAction {
A
Alex Dima 已提交
413 414

	constructor() {
415 416 417 418 419 420
		super({
			id: FIND_IDS.NextMatchFindAction,
			label: nls.localize('findNextMatchAction', "Find Next"),
			alias: 'Find Next',
			precondition: null,
			kbOpts: {
421
				kbExpr: EditorContextKeys.focus,
422 423 424 425
				primary: KeyCode.F3,
				mac: { primary: KeyMod.CtrlCmd | KeyCode.KEY_G, secondary: [KeyCode.F3] }
			}
		});
A
Alex Dima 已提交
426 427
	}

428
	protected _run(controller: CommonFindController): boolean {
429 430 431
		return controller.moveToNextMatch();
	}
}
432

433
export class PreviousMatchFindAction extends MatchFindAction {
A
Alex Dima 已提交
434 435

	constructor() {
436 437 438 439 440 441
		super({
			id: FIND_IDS.PreviousMatchFindAction,
			label: nls.localize('findPreviousMatchAction', "Find Previous"),
			alias: 'Find Previous',
			precondition: null,
			kbOpts: {
442
				kbExpr: EditorContextKeys.focus,
443 444 445 446
				primary: KeyMod.Shift | KeyCode.F3,
				mac: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_G, secondary: [KeyMod.Shift | KeyCode.F3] }
			}
		});
A
Alex Dima 已提交
447 448
	}

449
	protected _run(controller: CommonFindController): boolean {
450 451 452 453
		return controller.moveToPrevMatch();
	}
}

A
Alex Dima 已提交
454
export abstract class SelectionMatchFindAction extends EditorAction {
455
	public run(accessor: ServicesAccessor, editor: ICodeEditor): void {
A
Alex Dima 已提交
456
		let controller = CommonFindController.get(editor);
457 458 459
		if (!controller) {
			return;
		}
460
		let selectionSearchString = getSelectionSearchString(editor);
461 462 463 464
		if (selectionSearchString) {
			controller.setSearchString(selectionSearchString);
		}
		if (!this._run(controller)) {
465 466
			controller.start({
				forceRevealReplace: false,
467
				seedSearchStringFromSelection: false,
468 469 470
				shouldFocus: FindStartFocusAction.NoFocusChange,
				shouldAnimate: true
			});
471
			this._run(controller);
472 473
		}
	}
474

475
	protected abstract _run(controller: CommonFindController): boolean;
476 477 478
}

export class NextSelectionMatchFindAction extends SelectionMatchFindAction {
A
Alex Dima 已提交
479 480

	constructor() {
481 482 483 484 485 486
		super({
			id: FIND_IDS.NextSelectionMatchFindAction,
			label: nls.localize('nextSelectionMatchFindAction', "Find Next Selection"),
			alias: 'Find Next Selection',
			precondition: null,
			kbOpts: {
487
				kbExpr: EditorContextKeys.focus,
488 489 490
				primary: KeyMod.CtrlCmd | KeyCode.F3
			}
		});
A
Alex Dima 已提交
491 492
	}

493
	protected _run(controller: CommonFindController): boolean {
494 495 496 497 498
		return controller.moveToNextMatch();
	}
}

export class PreviousSelectionMatchFindAction extends SelectionMatchFindAction {
A
Alex Dima 已提交
499 500

	constructor() {
501 502 503 504 505 506
		super({
			id: FIND_IDS.PreviousSelectionMatchFindAction,
			label: nls.localize('previousSelectionMatchFindAction', "Find Previous Selection"),
			alias: 'Find Previous Selection',
			precondition: null,
			kbOpts: {
507
				kbExpr: EditorContextKeys.focus,
508 509 510
				primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.F3
			}
		});
A
Alex Dima 已提交
511 512
	}

513
	protected _run(controller: CommonFindController): boolean {
514 515
		return controller.moveToPrevMatch();
	}
516 517
}

A
Alex Dima 已提交
518
export class StartFindReplaceAction extends EditorAction {
A
Alex Dima 已提交
519 520

	constructor() {
521 522 523 524 525 526 527 528 529 530 531
		super({
			id: FIND_IDS.StartFindReplaceAction,
			label: nls.localize('startReplace', "Replace"),
			alias: 'Replace',
			precondition: null,
			kbOpts: {
				kbExpr: null,
				primary: KeyMod.CtrlCmd | KeyCode.KEY_H,
				mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_F }
			}
		});
532 533
	}

534
	public run(accessor: ServicesAccessor, editor: ICodeEditor): void {
535 536 537 538
		if (editor.getConfiguration().readOnly) {
			return;
		}

A
Alex Dima 已提交
539
		let controller = CommonFindController.get(editor);
540 541
		let currentSelection = editor.getSelection();
		// we only seed search string from selection when the current selection is single line and not empty.
R
rebornix 已提交
542 543
		let seedSearchStringFromSelection = !currentSelection.isEmpty() &&
			currentSelection.startLineNumber === currentSelection.endLineNumber;
544 545 546
		let oldSearchString = controller.getState().searchString;
		// if the existing search string in find widget is empty and we don't seed search string from selection, it means the Find Input
		// is still empty, so we should focus the Find Input instead of Replace Input.
R
rebornix 已提交
547 548
		let shouldFocus = (!!oldSearchString || seedSearchStringFromSelection) ?
			FindStartFocusAction.FocusReplaceInput : FindStartFocusAction.FocusFindInput;
549

550 551 552
		if (controller) {
			controller.start({
				forceRevealReplace: true,
553 554
				seedSearchStringFromSelection: seedSearchStringFromSelection,
				shouldFocus: shouldFocus,
555 556 557
				shouldAnimate: true
			});
		}
558 559 560
	}
}

S
Sandeep Somavarapu 已提交
561 562 563 564 565 566 567 568 569
export class ShowNextFindTermAction extends MatchFindAction {

	constructor() {
		super({
			id: FIND_IDS.ShowNextFindTermAction,
			label: nls.localize('showNextFindTermAction', "Show Next Find Term"),
			alias: 'Show Next Find Term',
			precondition: CONTEXT_FIND_WIDGET_VISIBLE,
			kbOpts: {
570
				weight: KeybindingsRegistry.WEIGHT.editorContrib(5),
A
Alex Dima 已提交
571
				kbExpr: ContextKeyExpr.and(CONTEXT_FIND_INPUT_FOCUSED, EditorContextKeys.focus),
S
Sandeep Somavarapu 已提交
572 573 574 575 576 577 578 579 580 581 582 583 584
				primary: ShowNextFindTermKeybinding.primary,
				mac: ShowNextFindTermKeybinding.mac,
				win: ShowNextFindTermKeybinding.win,
				linux: ShowNextFindTermKeybinding.linux
			}
		});
	}

	protected _run(controller: CommonFindController): boolean {
		return controller.showNextFindTerm();
	}
}

585
export class ShowPreviousFindTermAction extends MatchFindAction {
S
Sandeep Somavarapu 已提交
586 587 588 589 590 591 592 593

	constructor() {
		super({
			id: FIND_IDS.ShowPreviousFindTermAction,
			label: nls.localize('showPreviousFindTermAction', "Show Previous Find Term"),
			alias: 'Find Show Previous Find Term',
			precondition: CONTEXT_FIND_WIDGET_VISIBLE,
			kbOpts: {
594
				weight: KeybindingsRegistry.WEIGHT.editorContrib(5),
A
Alex Dima 已提交
595
				kbExpr: ContextKeyExpr.and(CONTEXT_FIND_INPUT_FOCUSED, EditorContextKeys.focus),
S
Sandeep Somavarapu 已提交
596 597 598 599 600 601 602 603 604 605 606 607 608
				primary: ShowPreviousFindTermKeybinding.primary,
				mac: ShowPreviousFindTermKeybinding.mac,
				win: ShowPreviousFindTermKeybinding.win,
				linux: ShowPreviousFindTermKeybinding.linux
			}
		});
	}

	protected _run(controller: CommonFindController): boolean {
		return controller.showPreviousFindTerm();
	}
}

609 610
registerEditorContribution(FindController);

611 612 613 614 615 616 617 618
registerEditorAction(StartFindAction);
registerEditorAction(NextMatchFindAction);
registerEditorAction(PreviousMatchFindAction);
registerEditorAction(NextSelectionMatchFindAction);
registerEditorAction(PreviousSelectionMatchFindAction);
registerEditorAction(StartFindReplaceAction);
registerEditorAction(ShowNextFindTermAction);
registerEditorAction(ShowPreviousFindTermAction);
619

A
Alex Dima 已提交
620
const FindCommand = EditorCommand.bindToContribution<CommonFindController>(CommonFindController.get);
A
Alex Dima 已提交
621

622
registerEditorCommand(new FindCommand({
623 624 625 626
	id: FIND_IDS.CloseFindWidgetCommand,
	precondition: CONTEXT_FIND_WIDGET_VISIBLE,
	handler: x => x.closeFindWidget(),
	kbOpts: {
627
		weight: KeybindingsRegistry.WEIGHT.editorContrib(5),
628
		kbExpr: EditorContextKeys.focus,
A
Alex Dima 已提交
629 630 631
		primary: KeyCode.Escape,
		secondary: [KeyMod.Shift | KeyCode.Escape]
	}
632
}));
A
Alex Dima 已提交
633

634
registerEditorCommand(new FindCommand({
635 636 637 638
	id: FIND_IDS.ToggleCaseSensitiveCommand,
	precondition: null,
	handler: x => x.toggleCaseSensitive(),
	kbOpts: {
639
		weight: KeybindingsRegistry.WEIGHT.editorContrib(5),
640
		kbExpr: EditorContextKeys.focus,
S
Sandeep Somavarapu 已提交
641 642 643 644
		primary: ToggleCaseSensitiveKeybinding.primary,
		mac: ToggleCaseSensitiveKeybinding.mac,
		win: ToggleCaseSensitiveKeybinding.win,
		linux: ToggleCaseSensitiveKeybinding.linux
A
Alex Dima 已提交
645
	}
646
}));
A
Alex Dima 已提交
647

648
registerEditorCommand(new FindCommand({
649 650 651 652
	id: FIND_IDS.ToggleWholeWordCommand,
	precondition: null,
	handler: x => x.toggleWholeWords(),
	kbOpts: {
653
		weight: KeybindingsRegistry.WEIGHT.editorContrib(5),
654
		kbExpr: EditorContextKeys.focus,
S
Sandeep Somavarapu 已提交
655 656 657 658
		primary: ToggleWholeWordKeybinding.primary,
		mac: ToggleWholeWordKeybinding.mac,
		win: ToggleWholeWordKeybinding.win,
		linux: ToggleWholeWordKeybinding.linux
A
Alex Dima 已提交
659
	}
660
}));
A
Alex Dima 已提交
661

662
registerEditorCommand(new FindCommand({
663 664 665 666
	id: FIND_IDS.ToggleRegexCommand,
	precondition: null,
	handler: x => x.toggleRegex(),
	kbOpts: {
667
		weight: KeybindingsRegistry.WEIGHT.editorContrib(5),
668
		kbExpr: EditorContextKeys.focus,
S
Sandeep Somavarapu 已提交
669 670 671 672
		primary: ToggleRegexKeybinding.primary,
		mac: ToggleRegexKeybinding.mac,
		win: ToggleRegexKeybinding.win,
		linux: ToggleRegexKeybinding.linux
A
Alex Dima 已提交
673
	}
674
}));
A
Alex Dima 已提交
675

676
registerEditorCommand(new FindCommand({
677 678 679 680
	id: FIND_IDS.ToggleSearchScopeCommand,
	precondition: null,
	handler: x => x.toggleSearchScope(),
	kbOpts: {
681
		weight: KeybindingsRegistry.WEIGHT.editorContrib(5),
682 683 684 685 686 687 688 689
		kbExpr: EditorContextKeys.focus,
		primary: ToggleSearchScopeKeybinding.primary,
		mac: ToggleSearchScopeKeybinding.mac,
		win: ToggleSearchScopeKeybinding.win,
		linux: ToggleSearchScopeKeybinding.linux
	}
}));

690
registerEditorCommand(new FindCommand({
691 692 693 694
	id: FIND_IDS.ReplaceOneAction,
	precondition: CONTEXT_FIND_WIDGET_VISIBLE,
	handler: x => x.replace(),
	kbOpts: {
695
		weight: KeybindingsRegistry.WEIGHT.editorContrib(5),
696
		kbExpr: EditorContextKeys.focus,
A
Alex Dima 已提交
697 698
		primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_1
	}
699
}));
A
Alex Dima 已提交
700

701
registerEditorCommand(new FindCommand({
702 703 704 705
	id: FIND_IDS.ReplaceAllAction,
	precondition: CONTEXT_FIND_WIDGET_VISIBLE,
	handler: x => x.replaceAll(),
	kbOpts: {
706
		weight: KeybindingsRegistry.WEIGHT.editorContrib(5),
707
		kbExpr: EditorContextKeys.focus,
A
Alex Dima 已提交
708 709
		primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.Enter
	}
710
}));
A
Alex Dima 已提交
711

712
registerEditorCommand(new FindCommand({
713 714 715 716
	id: FIND_IDS.SelectAllMatchesAction,
	precondition: CONTEXT_FIND_WIDGET_VISIBLE,
	handler: x => x.selectAllMatches(),
	kbOpts: {
717
		weight: KeybindingsRegistry.WEIGHT.editorContrib(5),
718
		kbExpr: EditorContextKeys.focus,
A
Alex Dima 已提交
719 720
		primary: KeyMod.Alt | KeyCode.Enter
	}
721
}));