diff --git a/src/vs/editor/contrib/find/findController.ts b/src/vs/editor/contrib/find/findController.ts index 2ad8187c49d042fee77a0582165c22f646872413..9002c412bcfc5b37cda75ac2b311184dc56629a6 100644 --- a/src/vs/editor/contrib/find/findController.ts +++ b/src/vs/editor/contrib/find/findController.ts @@ -11,7 +11,7 @@ import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/c import * as strings from 'vs/base/common/strings'; import * as editorCommon from 'vs/editor/common/editorCommon'; import { registerEditorContribution, registerEditorAction, ServicesAccessor, EditorAction, EditorCommand, registerEditorCommand } from 'vs/editor/browser/editorExtensions'; -import { FIND_IDS, FindModelBoundToEditorModel, ToggleCaseSensitiveKeybinding, ToggleRegexKeybinding, ToggleWholeWordKeybinding, ToggleSearchScopeKeybinding, CONTEXT_FIND_WIDGET_VISIBLE } from 'vs/editor/contrib/find/findModel'; +import { FIND_IDS, FindModelBoundToEditorModel, ToggleCaseSensitiveKeybinding, ToggleRegexKeybinding, ToggleWholeWordKeybinding, ToggleSearchScopeKeybinding, CONTEXT_FIND_WIDGET_VISIBLE, CONTEXT_FIND_INPUT_FOCUSED } from 'vs/editor/contrib/find/findModel'; import { FindReplaceState, FindReplaceStateChangedEvent, INewFindReplaceState } from 'vs/editor/contrib/find/findState'; import { Delayer } from 'vs/base/common/async'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; @@ -75,6 +75,7 @@ export class CommonFindController extends Disposable implements editorCommon.IEd private _model: FindModelBoundToEditorModel; protected _storageService: IStorageService; private _clipboardService: IClipboardService; + protected readonly _contextKeyService: IContextKeyService; public static get(editor: ICodeEditor): CommonFindController { return editor.getContribution(CommonFindController.ID); @@ -89,6 +90,7 @@ export class CommonFindController extends Disposable implements editorCommon.IEd super(); this._editor = editor; this._findWidgetVisible = CONTEXT_FIND_WIDGET_VISIBLE.bindTo(contextKeyService); + this._contextKeyService = contextKeyService; this._storageService = storageService; this._clipboardService = clipboardService; @@ -176,6 +178,10 @@ export class CommonFindController extends Disposable implements editorCommon.IEd }, false); } + public isFindInputFocused(): boolean { + return CONTEXT_FIND_INPUT_FOCUSED.getValue(this._contextKeyService); + } + public getState(): FindReplaceState { return this._state; } @@ -352,7 +358,7 @@ export class FindController extends CommonFindController implements IFindControl constructor( editor: ICodeEditor, @IContextViewService private readonly _contextViewService: IContextViewService, - @IContextKeyService private readonly _contextKeyService: IContextKeyService, + @IContextKeyService _contextKeyService: IContextKeyService, @IKeybindingService private readonly _keybindingService: IKeybindingService, @IThemeService private readonly _themeService: IThemeService, @IStorageService storageService: IStorageService, @@ -630,14 +636,23 @@ export class StartFindReplaceAction extends EditorAction { let controller = CommonFindController.get(editor); let currentSelection = editor.getSelection(); - // we only seed search string from selection when the current selection is single line and not empty. - let seedSearchStringFromSelection = !currentSelection.isEmpty() && - currentSelection.startLineNumber === currentSelection.endLineNumber && editor.getConfiguration().contribInfo.find.seedSearchStringFromSelection; - // 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. - let shouldFocus = seedSearchStringFromSelection ? + let findInputFocused = controller.isFindInputFocused(); + // we only seed search string from selection when the current selection is single line and not empty, + // + the find input is not focused + let seedSearchStringFromSelection = !currentSelection.isEmpty() + && currentSelection.startLineNumber === currentSelection.endLineNumber && editor.getConfiguration().contribInfo.find.seedSearchStringFromSelection + && !findInputFocused; + /* + * 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. + + * findInputFocused true -> seedSearchStringFromSelection false, FocusReplaceInput + * findInputFocused false, seedSearchStringFromSelection true FocusReplaceInput + * findInputFocused false seedSearchStringFromSelection false FocusFindInput + */ + let shouldFocus = (findInputFocused || seedSearchStringFromSelection) ? FindStartFocusAction.FocusReplaceInput : FindStartFocusAction.FocusFindInput; + if (controller) { controller.start({ forceRevealReplace: true, diff --git a/src/vs/editor/contrib/find/test/findController.test.ts b/src/vs/editor/contrib/find/test/findController.test.ts index f3733fdf704cdd11329a186c0e4fe5cc5af0599d..4be84bd72bdc3da5e0f7feb50d091d849bf71fb4 100644 --- a/src/vs/editor/contrib/find/test/findController.test.ts +++ b/src/vs/editor/contrib/find/test/findController.test.ts @@ -11,9 +11,10 @@ import { Position } from 'vs/editor/common/core/position'; import { Selection } from 'vs/editor/common/core/selection'; import { Range } from 'vs/editor/common/core/range'; import * as platform from 'vs/base/common/platform'; -import { CommonFindController, FindStartFocusAction, IFindStartOptions, NextMatchFindAction, StartFindAction, NextSelectionMatchFindAction } from 'vs/editor/contrib/find/findController'; +import { CommonFindController, FindStartFocusAction, IFindStartOptions, NextMatchFindAction, StartFindAction, NextSelectionMatchFindAction, StartFindReplaceAction } from 'vs/editor/contrib/find/findController'; +import { CONTEXT_FIND_INPUT_FOCUSED } from 'vs/editor/contrib/find/findModel'; import { withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; @@ -26,6 +27,8 @@ export class TestFindController extends CommonFindController { public delayUpdateHistory: boolean = false; public delayedUpdateHistoryPromise: TPromise; + private _findInputFocused: IContextKey; + constructor( editor: ICodeEditor, @IContextKeyService contextKeyService: IContextKeyService, @@ -33,6 +36,7 @@ export class TestFindController extends CommonFindController { @IClipboardService clipboardService: IClipboardService ) { super(editor, contextKeyService, storageService, clipboardService); + this._findInputFocused = CONTEXT_FIND_INPUT_FOCUSED.bindTo(contextKeyService); this._updateHistoryDelayer = new Delayer(50); } @@ -42,6 +46,9 @@ export class TestFindController extends CommonFindController { if (opts.shouldFocus !== FindStartFocusAction.NoFocusChange) { this.hasFocus = true; } + + let inputFocused = opts.shouldFocus === FindStartFocusAction.FocusFindInput; + this._findInputFocused.set(inputFocused); } } @@ -248,6 +255,34 @@ suite('FindController', () => { }); }); + test('issue #41027: Don\'t replace find input value on replace action if find input is active', () => { + withTestCodeEditor([ + 'test', + ], { serviceCollection: serviceCollection }, (editor, cursor) => { + let testRegexString = 'tes.'; + let findController = editor.registerAndInstantiateContribution(TestFindController); + let nextMatchFindAction = new NextMatchFindAction(); + let startFindReplaceAction = new StartFindReplaceAction(); + + findController.toggleRegex(); + findController.setSearchString(testRegexString); + findController.start({ + forceRevealReplace: false, + seedSearchStringFromSelection: false, + seedSearchStringFromGlobalClipboard: false, + shouldFocus: FindStartFocusAction.FocusFindInput, + shouldAnimate: false, + updateSearchScope: false + }); + nextMatchFindAction.run(null, editor); + startFindReplaceAction.run(null, editor); + + assert.equal(findController.getState().searchString, testRegexString); + + findController.dispose(); + }); + }); + test('issue #9043: Clear search scope when find widget is hidden', () => { withTestCodeEditor([ 'var x = (3 * 5)',