diff --git a/src/vs/workbench/contrib/terminal/browser/detachedTerminal.ts b/src/vs/workbench/contrib/terminal/browser/detachedTerminal.ts index 9902a5483e5..d8b53f3989f 100644 --- a/src/vs/workbench/contrib/terminal/browser/detachedTerminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/detachedTerminal.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import * as dom from 'vs/base/browser/dom'; import { Delayer } from 'vs/base/common/async'; import { onUnexpectedError } from 'vs/base/common/errors'; import { Disposable } from 'vs/base/common/lifecycle'; @@ -19,11 +20,13 @@ import { XtermTerminal } from 'vs/workbench/contrib/terminal/browser/xterm/xterm import { IEnvironmentVariableInfo } from 'vs/workbench/contrib/terminal/common/environmentVariable'; import { ITerminalProcessInfo, ProcessState } from 'vs/workbench/contrib/terminal/common/terminal'; -export class DeatachedTerminal extends Disposable implements IDetachedTerminalInstance { +export class DetachedTerminal extends Disposable implements IDetachedTerminalInstance { private readonly _widgets = this._register(new TerminalWidgetManager()); public readonly capabilities = new TerminalCapabilityStore(); private readonly _contributions: Map = new Map(); + public domElement?: HTMLElement; + public get xterm(): IDetachedXtermTerminal { return this._xterm; } @@ -66,10 +69,41 @@ export class DeatachedTerminal extends Disposable implements IDetachedTerminalIn }); } + get selection(): string | undefined { + return this._xterm && this.hasSelection() ? this._xterm.raw.getSelection() : undefined; + } + + hasSelection(): boolean { + return this._xterm.hasSelection(); + } + + clearSelection(): void { + this._xterm.clearSelection(); + } + + focus(force?: boolean): void { + if (force || !dom.getActiveWindow().getSelection()?.toString()) { + this.xterm.focus(); + } + } + attachToElement(container: HTMLElement, options?: Partial | undefined): void { + this.domElement = container; const screenElement = this._xterm.attachToElement(container, options); this._widgets.attachToElement(screenElement); } + + forceScrollbarVisibility(): void { + this.domElement?.classList.add('force-scrollbar'); + } + + resetScrollbarVisibility(): void { + this.domElement?.classList.remove('force-scrollbar'); + } + + getContribution(id: string): T | null { + return this._contributions.get(id) as T | null; + } } /** diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.ts b/src/vs/workbench/contrib/terminal/browser/terminal.ts index ce5c9213f6f..658c6208989 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.ts @@ -149,15 +149,66 @@ export interface IDetachedXTermOptions { processInfo: ITerminalProcessInfo; } +/** + * A generic interface implemented in both the {@link ITerminalInstance} (an + * interface used for terminals attached to the terminal panel or editor) and + * {@link IDetachedTerminalInstance} (a terminal used elsewhere in VS Code UI). + */ +export interface IBaseTerminalInstance { + readonly capabilities: ITerminalCapabilityStore; + + /** + * DOM element the terminal is mounted in. + */ + readonly domElement?: HTMLElement; + + /** + * Current selection in the terminal. + */ + readonly selection: string | undefined; + + /** + * Check if anything is selected in terminal. + */ + hasSelection(): boolean; + + /** + * Clear current selection. + */ + clearSelection(): void; + + /** + * Focuses the terminal instance if it's able to (the xterm.js instance must exist). + * + * @param force Force focus even if there is a selection. + */ + focus(force?: boolean): void; + + /** + * Force the scroll bar to be visible until {@link resetScrollbarVisibility} is called. + */ + forceScrollbarVisibility(): void; + + /** + * Resets the scroll bar to only be visible when needed, this does nothing unless + * {@link forceScrollbarVisibility} was called. + */ + resetScrollbarVisibility(): void; + + /** + * Gets a terminal contribution by its ID. + */ + getContribution(id: string): T | null; +} + /** * A {@link ITerminalInstance}-like object that emulates a subset of * capabilities. This instance is returned from {@link ITerminalService.createDetachedTerminal} * to represent terminals that appear in other parts of the VS Code UI outside * of the "Terminal" view or editors. */ -export interface IDetachedTerminalInstance extends IDisposable { +export interface IDetachedTerminalInstance extends IDisposable, IBaseTerminalInstance { readonly xterm: IDetachedXtermTerminal; - readonly capabilities: ITerminalCapabilityStore; /** * Attached the terminal to the given element. This should be preferred over @@ -178,7 +229,7 @@ export interface ITerminalService extends ITerminalInstanceHost { /** Gets all terminal instances, including editor and terminal view (group) instances. */ readonly instances: readonly ITerminalInstance[]; /** Gets detached terminal instances created via {@link createDetachedXterm}. */ - readonly detachedXterms: Iterable; + readonly detachedInstances: Iterable; readonly configHelper: ITerminalConfigHelper; readonly defaultLocation: TerminalLocation; @@ -478,7 +529,7 @@ export interface ISearchOptions { incremental?: boolean; } -export interface ITerminalInstance { +export interface ITerminalInstance extends IBaseTerminalInstance { /** * The ID of the terminal instance, this is an arbitrary number only used to uniquely identify * terminal instances within a window. @@ -510,7 +561,6 @@ export interface ITerminalInstance { readonly cwd?: string; readonly initialCwd?: string; readonly os?: OperatingSystem; - readonly capabilities: ITerminalCapabilityStore; readonly usedShellIntegrationInjection: boolean; readonly injectedArgs: string[] | undefined; readonly extEnvironmentVariableCollection: IMergedEnvironmentVariableCollection | undefined; @@ -749,39 +799,17 @@ export interface ITerminalInstance { */ detachProcessAndDispose(reason: TerminalExitReason): Promise; - /** - * Check if anything is selected in terminal. - */ - hasSelection(): boolean; - /** * Copies the terminal selection to the clipboard. */ copySelection(asHtml?: boolean, command?: ITerminalCommand): Promise; - /** - * Current selection in the terminal. - */ - readonly selection: string | undefined; - - /** - * Clear current selection. - */ - clearSelection(): void; - /** * When the panel is hidden or a terminal in the editor area becomes inactive, reset the focus context key * to avoid issues like #147180. */ resetFocusContextKey(): void; - /** - * Focuses the terminal instance if it's able to (the xterm.js instance must exist). - * - * @param force Force focus even if there is a selection. - */ - focus(force?: boolean): void; - /** * Focuses the terminal instance when it's ready (the xterm.js instance much exist). This is the * best focus call when the terminal is being shown for example. @@ -977,22 +1005,6 @@ export interface ITerminalInstance { * Hides the suggest widget. */ hideSuggestWidget(): void; - - /** - * Force the scroll bar to be visible until {@link resetScrollbarVisibility} is called. - */ - forceScrollbarVisibility(): void; - - /** - * Resets the scroll bar to only be visible when needed, this does nothing unless - * {@link forceScrollbarVisibility} was called. - */ - resetScrollbarVisibility(): void; - - /** - * Gets a terminal contribution by its ID. - */ - getContribution(id: string): T | null; } export const enum XtermTerminalConstants { diff --git a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts index 9d5896ce8f6..987db2379d3 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts @@ -32,7 +32,7 @@ import { IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspac import { PICK_WORKSPACE_FOLDER_COMMAND_ID } from 'vs/workbench/browser/actions/workspaceCommands'; import { CLOSE_EDITOR_COMMAND_ID } from 'vs/workbench/browser/parts/editor/editorCommands'; import { ResourceContextKey } from 'vs/workbench/common/contextkeys'; -import { Direction, ICreateTerminalOptions, ITerminalEditorService, ITerminalGroupService, ITerminalInstance, ITerminalInstanceService, ITerminalService, IXtermTerminal } from 'vs/workbench/contrib/terminal/browser/terminal'; +import { Direction, ICreateTerminalOptions, IDetachedTerminalInstance, ITerminalEditorService, ITerminalGroupService, ITerminalInstance, ITerminalInstanceService, ITerminalService, IXtermTerminal } from 'vs/workbench/contrib/terminal/browser/terminal'; import { TerminalQuickAccessProvider } from 'vs/workbench/contrib/terminal/browser/terminalQuickAccess'; import { IRemoteTerminalAttachTarget, ITerminalConfigHelper, ITerminalProfileResolverService, ITerminalProfileService, TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal'; import { TerminalContextKeys } from 'vs/workbench/contrib/terminal/common/terminalContextKey'; @@ -251,15 +251,15 @@ export function registerActiveInstanceAction( * This includes detached xterm terminals that are not managed by an {@link ITerminalInstance}. */ export function registerActiveXtermAction( - options: IAction2Options & { run: (activeTerminal: IXtermTerminal, accessor: ServicesAccessor, instance?: ITerminalInstance, args?: unknown) => void | Promise } + options: IAction2Options & { run: (activeTerminal: IXtermTerminal, accessor: ServicesAccessor, instance: ITerminalInstance | IDetachedTerminalInstance, args?: unknown) => void | Promise } ): IDisposable { const originalRun = options.run; return registerTerminalAction({ ...options, run: (c, accessor, args) => { - const activeDetached = Iterable.find(c.service.detachedXterms, d => d.isFocused); + const activeDetached = Iterable.find(c.service.detachedInstances, d => d.xterm.isFocused); if (activeDetached) { - return originalRun(activeDetached, accessor, undefined, args); + return originalRun(activeDetached.xterm, accessor, activeDetached, args); } const activeInstance = c.service.activeInstance; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index 15b4f2728bc..a9d162ce81c 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -88,7 +88,6 @@ import { ISimpleSelectedSuggestion } from 'vs/workbench/services/suggest/browser import type { IMarker, Terminal as XTermTerminal } from '@xterm/xterm'; import { AccessibilityCommandId } from 'vs/workbench/contrib/accessibility/common/accessibilityCommands'; import { terminalStrings } from 'vs/workbench/contrib/terminal/common/terminalStrings'; -import { $window } from 'vs/base/browser/window'; const enum Constants { /** @@ -1211,7 +1210,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { if (!this.xterm) { return; } - if (force || !$window.getSelection()?.toString()) { + if (force || !dom.getActiveWindow().getSelection()?.toString()) { this.xterm.raw.focus(); this._onDidRequestFocus.fire(); } diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index 4686df0178b..a7a00159d71 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -29,7 +29,7 @@ import { ThemeIcon } from 'vs/base/common/themables'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { VirtualWorkspaceContext } from 'vs/workbench/common/contextkeys'; import { IEditableData, IViewsService } from 'vs/workbench/common/views'; -import { ICreateTerminalOptions, IDetachedTerminalInstance, IDetachedXTermOptions, IRequestAddInstanceToGroupEvent, ITerminalEditorService, ITerminalGroup, ITerminalGroupService, ITerminalInstance, ITerminalInstanceHost, ITerminalInstanceService, ITerminalLocationOptions, ITerminalService, ITerminalServiceNativeDelegate, IXtermTerminal, TerminalConnectionState, TerminalEditorLocation } from 'vs/workbench/contrib/terminal/browser/terminal'; +import { ICreateTerminalOptions, IDetachedTerminalInstance, IDetachedXTermOptions, IRequestAddInstanceToGroupEvent, ITerminalEditorService, ITerminalGroup, ITerminalGroupService, ITerminalInstance, ITerminalInstanceHost, ITerminalInstanceService, ITerminalLocationOptions, ITerminalService, ITerminalServiceNativeDelegate, TerminalConnectionState, TerminalEditorLocation } from 'vs/workbench/contrib/terminal/browser/terminal'; import { getCwdForSplit } from 'vs/workbench/contrib/terminal/browser/terminalActions'; import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper'; import { TerminalEditorInput } from 'vs/workbench/contrib/terminal/browser/terminalEditorInput'; @@ -52,7 +52,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore'; import { ITimerService } from 'vs/workbench/services/timer/browser/timerService'; import { mark } from 'vs/base/common/performance'; -import { DeatachedTerminal } from 'vs/workbench/contrib/terminal/browser/detachedTerminal'; +import { DetachedTerminal } from 'vs/workbench/contrib/terminal/browser/detachedTerminal'; import { ITerminalCapabilityImplMap, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; import { createInstanceCapabilityEventMultiplexer } from 'vs/workbench/contrib/terminal/browser/terminalEvents'; import { mainWindow } from 'vs/base/browser/window'; @@ -62,7 +62,7 @@ export class TerminalService extends Disposable implements ITerminalService { private _hostActiveTerminals: Map = new Map(); - private _detachedXterms = new Set(); + private _detachedXterms = new Set(); private _terminalEditorActive: IContextKey; private readonly _terminalShellTypeContextKey: IContextKey; @@ -95,7 +95,7 @@ export class TerminalService extends Disposable implements ITerminalService { get instances(): ITerminalInstance[] { return this._terminalGroupService.instances.concat(this._terminalEditorService.instances); } - get detachedXterms(): Iterable { + get detachedInstances(): Iterable { return this._detachedXterms; } @@ -1023,13 +1023,14 @@ export class TerminalService extends Disposable implements ITerminalService { xterm.raw.attachCustomKeyEventHandler(() => false); } - this._detachedXterms.add(xterm); + const instance = new DetachedTerminal(xterm, options, this._instantiationService); + this._detachedXterms.add(instance); const l = xterm.onDidDispose(() => { - this._detachedXterms.delete(xterm); + this._detachedXterms.delete(instance); l.dispose(); }); - return new DeatachedTerminal(xterm, options, this._instantiationService); + return instance; } private async _resolveCwd(shellLaunchConfig: IShellLaunchConfig, splitActiveTerminal: boolean, options?: ICreateTerminalOptions): Promise { diff --git a/src/vs/workbench/contrib/terminalContrib/find/browser/terminal.find.contribution.ts b/src/vs/workbench/contrib/terminalContrib/find/browser/terminal.find.contribution.ts index 83404f7cb1e..cf9c16b27f6 100644 --- a/src/vs/workbench/contrib/terminalContrib/find/browser/terminal.find.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/find/browser/terminal.find.contribution.ts @@ -12,11 +12,11 @@ import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { findInFilesCommand } from 'vs/workbench/contrib/search/browser/searchActionsFind'; -import { ITerminalContribution, ITerminalInstance, ITerminalService, IXtermTerminal } from 'vs/workbench/contrib/terminal/browser/terminal'; -import { registerActiveInstanceAction } from 'vs/workbench/contrib/terminal/browser/terminalActions'; +import { IDetachedTerminalInstance, ITerminalContribution, ITerminalInstance, ITerminalService, IXtermTerminal, isDetachedTerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminal'; +import { registerActiveInstanceAction, registerActiveXtermAction } from 'vs/workbench/contrib/terminal/browser/terminalActions'; import { registerTerminalContribution } from 'vs/workbench/contrib/terminal/browser/terminalExtensions'; import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/widgets/widgetManager'; -import { ITerminalProcessManager, TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalProcessInfo, ITerminalProcessManager, TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal'; import { TerminalContextKeys } from 'vs/workbench/contrib/terminal/common/terminalContextKey'; import { TerminalFindWidget } from 'vs/workbench/contrib/terminalContrib/find/browser/terminalFindWidget'; import type { Terminal as RawXtermTerminal } from '@xterm/xterm'; @@ -24,7 +24,13 @@ import type { Terminal as RawXtermTerminal } from '@xterm/xterm'; class TerminalFindContribution extends Disposable implements ITerminalContribution { static readonly ID = 'terminal.find'; - static get(instance: ITerminalInstance): TerminalFindContribution | null { + /** + * Currently focused find widget. This is used to track action context since + * 'active terminals' are only tracked for non-detached terminal instanecs. + */ + static activeFindWidget?: TerminalFindContribution; + + static get(instance: ITerminalInstance | IDetachedTerminalInstance): TerminalFindContribution | null { return instance.getContribution(TerminalFindContribution.ID); } @@ -34,8 +40,8 @@ class TerminalFindContribution extends Disposable implements ITerminalContributi get findWidget(): TerminalFindWidget { return this._findWidget.value; } constructor( - private readonly _instance: ITerminalInstance, - processManager: ITerminalProcessManager, + private readonly _instance: ITerminalInstance | IDetachedTerminalInstance, + processManager: ITerminalProcessManager | ITerminalProcessInfo, widgetManager: TerminalWidgetManager, @IInstantiationService instantiationService: IInstantiationService, @ITerminalService terminalService: ITerminalService @@ -47,14 +53,22 @@ class TerminalFindContribution extends Disposable implements ITerminalContributi // Track focus and set state so we can force the scroll bar to be visible findWidget.focusTracker.onDidFocus(() => { + TerminalFindContribution.activeFindWidget = this; this._instance.forceScrollbarVisibility(); - terminalService.setActiveInstance(this._instance); + if (!isDetachedTerminalInstance(this._instance)) { + terminalService.setActiveInstance(this._instance); + } }); findWidget.focusTracker.onDidBlur(() => { + TerminalFindContribution.activeFindWidget = undefined; this._instance.resetScrollbarVisibility(); }); - this._instance.domElement.appendChild(findWidget.getDomNode()); + if (!this._instance.domElement) { + throw new Error('FindWidget expected terminal DOM to be initialized'); + } + + this._instance.domElement?.appendChild(findWidget.getDomNode()); if (this._lastLayoutDimensions) { findWidget.layout(this._lastLayoutDimensions.width); } @@ -63,7 +77,7 @@ class TerminalFindContribution extends Disposable implements ITerminalContributi }); } - layout(xterm: IXtermTerminal & { raw: RawXtermTerminal }, dimension: IDimension): void { + layout(_xterm: IXtermTerminal & { raw: RawXtermTerminal }, dimension: IDimension): void { this._lastLayoutDimensions = dimension; this._findWidget.rawValue?.layout(dimension.width); } @@ -73,98 +87,106 @@ class TerminalFindContribution extends Disposable implements ITerminalContributi } override dispose() { + if (TerminalFindContribution.activeFindWidget === this) { + TerminalFindContribution.activeFindWidget = undefined; + } super.dispose(); this._findWidget.rawValue?.dispose(); } } -registerTerminalContribution(TerminalFindContribution.ID, TerminalFindContribution); +registerTerminalContribution(TerminalFindContribution.ID, TerminalFindContribution, true); -registerActiveInstanceAction({ +registerActiveXtermAction({ id: TerminalCommandId.FindFocus, title: { value: localize('workbench.action.terminal.focusFind', "Focus Find"), original: 'Focus Find' }, keybinding: { primary: KeyMod.CtrlCmd | KeyCode.KeyF, - when: ContextKeyExpr.or(TerminalContextKeys.findFocus, TerminalContextKeys.focus), + when: ContextKeyExpr.or(TerminalContextKeys.findFocus, TerminalContextKeys.focusInAny), weight: KeybindingWeight.WorkbenchContrib }, precondition: ContextKeyExpr.or(TerminalContextKeys.processSupported, TerminalContextKeys.terminalHasBeenCreated), - run: (activeInstance) => { - TerminalFindContribution.get(activeInstance)?.findWidget.reveal(); + run: (_xterm, _accessor, activeInstance) => { + const contr = TerminalFindContribution.activeFindWidget || TerminalFindContribution.get(activeInstance); + contr?.findWidget.reveal(); } }); -registerActiveInstanceAction({ +registerActiveXtermAction({ id: TerminalCommandId.FindHide, title: { value: localize('workbench.action.terminal.hideFind', "Hide Find"), original: 'Hide Find' }, keybinding: { primary: KeyCode.Escape, secondary: [KeyMod.Shift | KeyCode.Escape], - when: ContextKeyExpr.and(TerminalContextKeys.focus, TerminalContextKeys.findVisible), + when: ContextKeyExpr.and(TerminalContextKeys.focusInAny, TerminalContextKeys.findVisible), weight: KeybindingWeight.WorkbenchContrib }, precondition: ContextKeyExpr.or(TerminalContextKeys.processSupported, TerminalContextKeys.terminalHasBeenCreated), - run: (activeInstance) => { - TerminalFindContribution.get(activeInstance)?.findWidget.hide(); + run: (_xterm, _accessor, activeInstance) => { + const contr = TerminalFindContribution.activeFindWidget || TerminalFindContribution.get(activeInstance); + contr?.findWidget.hide(); } }); -registerActiveInstanceAction({ +registerActiveXtermAction({ id: TerminalCommandId.ToggleFindRegex, title: { value: localize('workbench.action.terminal.toggleFindRegex', "Toggle Find Using Regex"), original: 'Toggle Find Using Regex' }, keybinding: { primary: KeyMod.Alt | KeyCode.KeyR, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KeyR }, - when: ContextKeyExpr.or(TerminalContextKeys.focus, TerminalContextKeys.findFocus), + when: ContextKeyExpr.or(TerminalContextKeys.focusInAny, TerminalContextKeys.findFocus), weight: KeybindingWeight.WorkbenchContrib }, precondition: ContextKeyExpr.or(TerminalContextKeys.processSupported, TerminalContextKeys.terminalHasBeenCreated), - run: (activeInstance) => { - const state = TerminalFindContribution.get(activeInstance)?.findWidget.state; + run: (_xterm, _accessor, activeInstance) => { + const contr = TerminalFindContribution.activeFindWidget || TerminalFindContribution.get(activeInstance); + const state = contr?.findWidget.state; state?.change({ isRegex: !state.isRegex }, false); } }); -registerActiveInstanceAction({ +registerActiveXtermAction({ id: TerminalCommandId.ToggleFindWholeWord, title: { value: localize('workbench.action.terminal.toggleFindWholeWord', "Toggle Find Using Whole Word"), original: 'Toggle Find Using Whole Word' }, keybinding: { primary: KeyMod.Alt | KeyCode.KeyW, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KeyW }, - when: ContextKeyExpr.or(TerminalContextKeys.focus, TerminalContextKeys.findFocus), + when: ContextKeyExpr.or(TerminalContextKeys.focusInAny, TerminalContextKeys.findFocus), weight: KeybindingWeight.WorkbenchContrib }, precondition: ContextKeyExpr.or(TerminalContextKeys.processSupported, TerminalContextKeys.terminalHasBeenCreated), - run: (activeInstance) => { - const state = TerminalFindContribution.get(activeInstance)?.findWidget.state; + run: (_xterm, _accessor, activeInstance) => { + const contr = TerminalFindContribution.activeFindWidget || TerminalFindContribution.get(activeInstance); + const state = contr?.findWidget.state; state?.change({ wholeWord: !state.wholeWord }, false); } }); -registerActiveInstanceAction({ +registerActiveXtermAction({ id: TerminalCommandId.ToggleFindCaseSensitive, title: { value: localize('workbench.action.terminal.toggleFindCaseSensitive', "Toggle Find Using Case Sensitive"), original: 'Toggle Find Using Case Sensitive' }, keybinding: { primary: KeyMod.Alt | KeyCode.KeyC, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KeyC }, - when: ContextKeyExpr.or(TerminalContextKeys.focus, TerminalContextKeys.findFocus), + when: ContextKeyExpr.or(TerminalContextKeys.focusInAny, TerminalContextKeys.findFocus), weight: KeybindingWeight.WorkbenchContrib }, precondition: ContextKeyExpr.or(TerminalContextKeys.processSupported, TerminalContextKeys.terminalHasBeenCreated), - run: (activeInstance) => { - const state = TerminalFindContribution.get(activeInstance)?.findWidget.state; + run: (_xterm, _accessor, activeInstance) => { + const contr = TerminalFindContribution.activeFindWidget || TerminalFindContribution.get(activeInstance); + const state = contr?.findWidget.state; state?.change({ matchCase: !state.matchCase }, false); } }); -registerActiveInstanceAction({ +registerActiveXtermAction({ id: TerminalCommandId.FindNext, title: { value: localize('workbench.action.terminal.findNext', "Find Next"), original: 'Find Next' }, keybinding: [ { primary: KeyCode.F3, mac: { primary: KeyMod.CtrlCmd | KeyCode.KeyG, secondary: [KeyCode.F3] }, - when: ContextKeyExpr.or(TerminalContextKeys.focus, TerminalContextKeys.findFocus), + when: ContextKeyExpr.or(TerminalContextKeys.focusInAny, TerminalContextKeys.findFocus), weight: KeybindingWeight.WorkbenchContrib }, { @@ -174,8 +196,9 @@ registerActiveInstanceAction({ } ], precondition: ContextKeyExpr.or(TerminalContextKeys.processSupported, TerminalContextKeys.terminalHasBeenCreated), - run: (activeInstance) => { - const widget = TerminalFindContribution.get(activeInstance)?.findWidget; + run: (_xterm, _accessor, activeInstance) => { + const contr = TerminalFindContribution.activeFindWidget || TerminalFindContribution.get(activeInstance); + const widget = contr?.findWidget; if (widget) { widget.show(); widget.find(false); @@ -183,14 +206,14 @@ registerActiveInstanceAction({ } }); -registerActiveInstanceAction({ +registerActiveXtermAction({ id: TerminalCommandId.FindPrevious, title: { value: localize('workbench.action.terminal.findPrevious', "Find Previous"), original: 'Find Previous' }, keybinding: [ { primary: KeyMod.Shift | KeyCode.F3, mac: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyG, secondary: [KeyMod.Shift | KeyCode.F3] }, - when: ContextKeyExpr.or(TerminalContextKeys.focus, TerminalContextKeys.findFocus), + when: ContextKeyExpr.or(TerminalContextKeys.focusInAny, TerminalContextKeys.findFocus), weight: KeybindingWeight.WorkbenchContrib }, { @@ -200,8 +223,9 @@ registerActiveInstanceAction({ } ], precondition: ContextKeyExpr.or(TerminalContextKeys.processSupported, TerminalContextKeys.terminalHasBeenCreated), - run: (activeInstance) => { - const widget = TerminalFindContribution.get(activeInstance)?.findWidget; + run: (_xterm, _accessor, activeInstance) => { + const contr = TerminalFindContribution.activeFindWidget || TerminalFindContribution.get(activeInstance); + const widget = contr?.findWidget; if (widget) { widget.show(); widget.find(true); diff --git a/src/vs/workbench/contrib/terminalContrib/find/browser/terminalFindWidget.ts b/src/vs/workbench/contrib/terminalContrib/find/browser/terminalFindWidget.ts index dbdc049730b..545ab13ac95 100644 --- a/src/vs/workbench/contrib/terminalContrib/find/browser/terminalFindWidget.ts +++ b/src/vs/workbench/contrib/terminalContrib/find/browser/terminalFindWidget.ts @@ -6,7 +6,7 @@ import { SimpleFindWidget } from 'vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; -import { ITerminalInstance, IXtermTerminal, XtermTerminalConstants } from 'vs/workbench/contrib/terminal/browser/terminal'; +import { IDetachedTerminalInstance, ITerminalInstance, IXtermTerminal, XtermTerminalConstants } from 'vs/workbench/contrib/terminal/browser/terminal'; import { TerminalContextKeys } from 'vs/workbench/contrib/terminal/common/terminalContextKey'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -23,7 +23,7 @@ export class TerminalFindWidget extends SimpleFindWidget { private _findWidgetVisible: IContextKey; constructor( - private _instance: ITerminalInstance, + private _instance: ITerminalInstance | IDetachedTerminalInstance, @IContextViewService _contextViewService: IContextViewService, @IKeybindingService keybindingService: IKeybindingService, @IContextKeyService private readonly _contextKeyService: IContextKeyService,