From 7a34ec55d9b55e81e300bf5f55d69d0e8fc08445 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 30 Jul 2020 18:29:45 -0700 Subject: [PATCH] fix #102441. --- src/vs/editor/browser/editorExtensions.ts | 43 +++++++++++++++++ src/vs/editor/contrib/find/findController.ts | 12 +++-- .../browser/find/simpleFindReplaceWidget.ts | 30 +++++++++++- .../browser/contrib/find/findController.ts | 48 +++++++++++++++++++ 4 files changed, 127 insertions(+), 6 deletions(-) diff --git a/src/vs/editor/browser/editorExtensions.ts b/src/vs/editor/browser/editorExtensions.ts index 1db05bd2a7c..e4e081bd300 100644 --- a/src/vs/editor/browser/editorExtensions.ts +++ b/src/vs/editor/browser/editorExtensions.ts @@ -337,6 +337,44 @@ export abstract class EditorAction extends EditorCommand { public abstract run(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | Promise; } +export abstract class MultiEditorAction extends EditorAction { + private readonly _implementations: [number, CommandImplementation][] = []; + + constructor(opts: IActionOptions) { + super(opts); + } + + public addImplementation(priority: number, implementation: CommandImplementation): IDisposable { + this._implementations.push([priority, implementation]); + this._implementations.sort((a, b) => b[0] - a[0]); + return { + dispose: () => { + for (let i = 0; i < this._implementations.length; i++) { + if (this._implementations[i][1] === implementation) { + this._implementations.splice(i, 1); + return; + } + } + } + }; + } + + public runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | Promise { + this.reportTelemetry(accessor, editor); + + for (const impl of this._implementations) { + if (impl[1](accessor, args)) { + return; + } + } + + return this.run(accessor, editor, args || {}); + } + + public abstract run(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | Promise; + +} + //#endregion EditorAction //#region EditorAction2 @@ -474,6 +512,11 @@ export function registerEditorAction(ctor: { new(): T; } return action; } +export function registerMultiEditorAction(action: T): T { + EditorContributionRegistry.INSTANCE.registerEditorAction(action); + return action; +} + export function registerInstantiatedEditorAction(editorAction: EditorAction): void { EditorContributionRegistry.INSTANCE.registerEditorAction(editorAction); } diff --git a/src/vs/editor/contrib/find/findController.ts b/src/vs/editor/contrib/find/findController.ts index 712501a3933..2730f6b8040 100644 --- a/src/vs/editor/contrib/find/findController.ts +++ b/src/vs/editor/contrib/find/findController.ts @@ -9,7 +9,7 @@ import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { Disposable } from 'vs/base/common/lifecycle'; import * as strings from 'vs/base/common/strings'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; -import { EditorAction, EditorCommand, ServicesAccessor, registerEditorAction, registerEditorCommand, registerEditorContribution } from 'vs/editor/browser/editorExtensions'; +import { EditorAction, EditorCommand, ServicesAccessor, registerEditorAction, registerEditorCommand, registerEditorContribution, MultiEditorAction, registerMultiEditorAction } from 'vs/editor/browser/editorExtensions'; import { IEditorContribution } from 'vs/editor/common/editorCommon'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { CONTEXT_FIND_INPUT_FOCUSED, CONTEXT_FIND_WIDGET_VISIBLE, FIND_IDS, FindModelBoundToEditorModel, ToggleCaseSensitiveKeybinding, ToggleRegexKeybinding, ToggleSearchScopeKeybinding, ToggleWholeWordKeybinding, CONTEXT_REPLACE_INPUT_FOCUSED } from 'vs/editor/contrib/find/findModel'; @@ -457,7 +457,7 @@ export class FindController extends CommonFindController implements IFindControl } } -export class StartFindAction extends EditorAction { +export class StartFindAction extends MultiEditorAction { constructor() { super({ @@ -706,7 +706,7 @@ export class PreviousSelectionMatchFindAction extends SelectionMatchFindAction { } } -export class StartFindReplaceAction extends EditorAction { +export class StartFindReplaceAction extends MultiEditorAction { constructor() { super({ @@ -769,7 +769,8 @@ export class StartFindReplaceAction extends EditorAction { registerEditorContribution(CommonFindController.ID, FindController); -registerEditorAction(StartFindAction); +export const EditorStartFindAction = new StartFindAction(); +registerMultiEditorAction(EditorStartFindAction); registerEditorAction(StartFindWithSelectionAction); registerEditorAction(NextMatchFindAction); registerEditorAction(NextMatchFindAction2); @@ -777,7 +778,8 @@ registerEditorAction(PreviousMatchFindAction); registerEditorAction(PreviousMatchFindAction2); registerEditorAction(NextSelectionMatchFindAction); registerEditorAction(PreviousSelectionMatchFindAction); -registerEditorAction(StartFindReplaceAction); +export const EditorStartFindReplaceAction = new StartFindReplaceAction(); +registerMultiEditorAction(EditorStartFindReplaceAction); const FindCommand = EditorCommand.bindToContribution(CommonFindController.get); diff --git a/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindReplaceWidget.ts b/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindReplaceWidget.ts index 1d171e60334..088c76bdb4b 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindReplaceWidget.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindReplaceWidget.ts @@ -43,7 +43,7 @@ export abstract class SimpleFindReplaceWidget extends Widget { private readonly prevBtn: SimpleButton; private readonly nextBtn: SimpleButton; - private readonly _replaceInput!: ReplaceInput; + protected readonly _replaceInput!: ReplaceInput; private readonly _innerReplaceDomNode!: HTMLElement; private _toggleReplaceBtn!: SimpleButton; private readonly _replaceInputFocusTracker!: dom.IFocusTracker; @@ -372,6 +372,34 @@ export abstract class SimpleFindReplaceWidget extends Widget { }, 0); } + public showWithReplace(initialInput?: string, replaceInput?: string): void { + if (initialInput && !this._isVisible) { + this._findInput.setValue(initialInput); + } + + if (replaceInput && !this._isVisible) { + this._replaceInput.setValue(replaceInput); + } + + this._isVisible = true; + this._isReplaceVisible = true; + this._state.change({ isReplaceRevealed: this._isReplaceVisible }, false); + if (this._isReplaceVisible) { + this._innerReplaceDomNode.style.display = 'flex'; + } else { + this._innerReplaceDomNode.style.display = 'none'; + } + + setTimeout(() => { + dom.addClass(this._domNode, 'visible'); + dom.addClass(this._domNode, 'visible-transition'); + this._domNode.setAttribute('aria-hidden', 'false'); + this._updateButtons(); + + this._replaceInput.focus(); + }, 0); + } + public hide(): void { if (this._isVisible) { dom.removeClass(this._domNode, 'visible-transition'); diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts b/src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts index e4525a00a52..3661855ef3d 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts @@ -27,6 +27,7 @@ import { getActiveNotebookEditor } from 'vs/workbench/contrib/notebook/browser/c import { FindReplaceState } from 'vs/editor/contrib/find/findState'; import { INotebookSearchOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { EditorStartFindAction, EditorStartFindReplaceAction } from 'vs/editor/contrib/find/findController'; const FIND_HIDE_TRANSITION = 'find-hide-transition'; const FIND_SHOW_TRANSITION = 'find-show-transition'; @@ -285,6 +286,27 @@ export class NotebookFindWidget extends SimpleFindReplaceWidget implements INote } } + replace(initialFindInput?: string, initialReplaceInput?: string) { + super.showWithReplace(initialFindInput, initialReplaceInput); + this._replaceInput.select(); + + if (this._showTimeout === null) { + if (this._hideTimeout !== null) { + window.clearTimeout(this._hideTimeout); + this._hideTimeout = null; + this._notebookEditor.removeClassName(FIND_HIDE_TRANSITION); + } + + this._notebookEditor.addClassName(FIND_SHOW_TRANSITION); + this._showTimeout = window.setTimeout(() => { + this._notebookEditor.removeClassName(FIND_SHOW_TRANSITION); + this._showTimeout = null; + }, 200); + } else { + // no op + } + } + hide() { super.hide(); this.set([], false); @@ -371,3 +393,29 @@ registerAction2(class extends Action2 { controller.show(); } }); + +EditorStartFindAction.addImplementation(100, (accessor: ServicesAccessor, args: any) => { + let editorService = accessor.get(IEditorService); + let editor = getActiveNotebookEditor(editorService); + + if (!editor) { + return false; + } + + const controller = editor.getContribution(NotebookFindWidget.id); + controller.show(); + return true; +}); + +EditorStartFindReplaceAction.addImplementation(100, (accessor: ServicesAccessor, args: any) => { + let editorService = accessor.get(IEditorService); + let editor = getActiveNotebookEditor(editorService); + + if (!editor) { + return false; + } + + const controller = editor.getContribution(NotebookFindWidget.id); + controller.replace(); + return true; +});