Merge pull request #230242 from microsoft/tyriar/230129_history__interface

Simplify terminal contribution interface
This commit is contained in:
Daniel Imms
2024-10-01 08:37:42 -07:00
committed by GitHub
17 changed files with 195 additions and 226 deletions

View File

@@ -52,7 +52,11 @@ export class DetachedTerminal extends Disposable implements IDetachedTerminalIns
let contribution: ITerminalContribution;
try {
contribution = instantiationService.createInstance(desc.ctor, this, options.processInfo, this._widgets);
contribution = instantiationService.createInstance(desc.ctor, {
instance: this,
processManager: options.processInfo,
widgetManager: this._widgets
});
this._contributions.set(desc.id, contribution);
this._register(contribution);
} catch (err) {

View File

@@ -9,10 +9,21 @@ import { IDetachedTerminalInstance, ITerminalContribution, ITerminalInstance } f
import { TerminalWidgetManager } from './widgets/widgetManager.js';
import { ITerminalProcessInfo, ITerminalProcessManager } from '../common/terminal.js';
export interface ITerminalContributionContext {
instance: ITerminalInstance;
processManager: ITerminalProcessManager;
widgetManager: TerminalWidgetManager;
}
export interface IDetachedCompatibleTerminalContributionContext {
instance: IDetachedTerminalInstance;
processManager: ITerminalProcessInfo;
widgetManager: TerminalWidgetManager;
}
/** Constructor compatible with full terminal instances, is assignable to {@link DetachedCompatibleTerminalContributionCtor} */
export type TerminalContributionCtor = IConstructorSignature<ITerminalContribution, [ITerminalInstance, ITerminalProcessManager, TerminalWidgetManager]>;
export type TerminalContributionCtor = IConstructorSignature<ITerminalContribution, [ITerminalContributionContext]>;
/** Constructor compatible with detached terminals */
export type DetachedCompatibleTerminalContributionCtor = IConstructorSignature<ITerminalContribution, [IDetachedTerminalInstance, ITerminalProcessInfo, TerminalWidgetManager]>;
export type DetachedCompatibleTerminalContributionCtor = IConstructorSignature<ITerminalContribution, [IDetachedCompatibleTerminalContributionContext]>;
export type ITerminalContributionDescription = { readonly id: string } & (
| { readonly canRunInDetachedTerminals: false; readonly ctor: TerminalContributionCtor }
@@ -28,10 +39,9 @@ export type ITerminalContributionDescription = { readonly id: string } & (
* @param canRunInDetachedTerminals Whether the terminal contribution should be run in detecthed
* terminals. Defaults to false.
*/
export function registerTerminalContribution<Services extends BrandedService[]>(id: string, ctor: { new(instance: ITerminalInstance, processManager: ITerminalProcessManager, widgetManager: TerminalWidgetManager, ...services: Services): ITerminalContribution }, canRunInDetachedTerminals?: false): void;
export function registerTerminalContribution<Services extends BrandedService[]>(id: string, ctor: { new(instance: ITerminalInstance, processManager: ITerminalProcessInfo, widgetManager: TerminalWidgetManager, ...services: Services): ITerminalContribution }, canRunInDetachedTerminals: true): void;
export function registerTerminalContribution<Services extends BrandedService[]>(id: string, ctor: { new(instance: ITerminalInstance, processManager: ITerminalProcessManager, widgetManager: TerminalWidgetManager, ...services: Services): ITerminalContribution }, canRunInDetachedTerminals = false): void {
// TODO: Pass in a context object containing instance, process manager, widgetmanager
export function registerTerminalContribution<Services extends BrandedService[]>(id: string, ctor: { new(ctx: ITerminalContributionContext, ...services: Services): ITerminalContribution }, canRunInDetachedTerminals?: false): void;
export function registerTerminalContribution<Services extends BrandedService[]>(id: string, ctor: { new(ctx: IDetachedCompatibleTerminalContributionContext, ...services: Services): ITerminalContribution }, canRunInDetachedTerminals: true): void;
export function registerTerminalContribution<Services extends BrandedService[]>(id: string, ctor: { new(ctx: any, ...services: Services): ITerminalContribution }, canRunInDetachedTerminals: boolean = false): void {
TerminalContributionRegistry.INSTANCE.registerTerminalContribution({ id, ctor, canRunInDetachedTerminals } as ITerminalContributionDescription);
}

View File

@@ -582,7 +582,11 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
}
let contribution: ITerminalContribution;
try {
contribution = this._register(this._scopedInstantiationService.createInstance(desc.ctor, this, this._processManager, this._widgetManager));
contribution = this._register(this._scopedInstantiationService.createInstance(desc.ctor, {
instance: this,
processManager: this._processManager,
widgetManager: this._widgetManager
}));
this._contributions.set(desc.id, contribution);
} catch (err) {
onUnexpectedError(err);

View File

@@ -3,38 +3,36 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import type { Terminal } from '@xterm/xterm';
import { Event } from '../../../../../base/common/event.js';
import { KeyCode, KeyMod } from '../../../../../base/common/keyCodes.js';
import { Disposable, DisposableStore, IDisposable, MutableDisposable } from '../../../../../base/common/lifecycle.js';
import { isWindows } from '../../../../../base/common/platform.js';
import { Position } from '../../../../../editor/common/core/position.js';
import { localize2 } from '../../../../../nls.js';
import { AccessibleViewProviderId, IAccessibleViewService, NavigationType } from '../../../../../platform/accessibility/browser/accessibleView.js';
import { CONTEXT_ACCESSIBILITY_MODE_ENABLED } from '../../../../../platform/accessibility/common/accessibility.js';
import { AccessibilitySignal, IAccessibilitySignalService } from '../../../../../platform/accessibilitySignal/browser/accessibilitySignalService.js';
import { Action2, registerAction2 } from '../../../../../platform/actions/common/actions.js';
import { IConfigurationService } from '../../../../../platform/configuration/common/configuration.js';
import { ContextKeyExpr, IContextKeyService } from '../../../../../platform/contextkey/common/contextkey.js';
import { IInstantiationService, ServicesAccessor } from '../../../../../platform/instantiation/common/instantiation.js';
import { KeybindingWeight } from '../../../../../platform/keybinding/common/keybindingsRegistry.js';
import { ITerminalCommand, TerminalCapability } from '../../../../../platform/terminal/common/capabilities/capabilities.js';
import { ICurrentPartialCommand } from '../../../../../platform/terminal/common/capabilities/commandDetection/terminalCommand.js';
import { TerminalSettingId } from '../../../../../platform/terminal/common/terminal.js';
import { accessibleViewCurrentProviderId, accessibleViewIsShown } from '../../../accessibility/browser/accessibilityConfiguration.js';
import { AccessibilityHelpAction, AccessibleViewAction } from '../../../accessibility/browser/accessibleViewActions.js';
import { ITerminalContribution, ITerminalInstance, ITerminalService, IXtermTerminal } from '../../../terminal/browser/terminal.js';
import { registerTerminalAction } from '../../../terminal/browser/terminalActions.js';
import { registerTerminalContribution } from '../../../terminal/browser/terminalExtensions.js';
import { TerminalWidgetManager } from '../../../terminal/browser/widgets/widgetManager.js';
import { ITerminalProcessManager } from '../../../terminal/common/terminal.js';
import { registerTerminalContribution, type ITerminalContributionContext } from '../../../terminal/browser/terminalExtensions.js';
import { TerminalContextKeys } from '../../../terminal/common/terminalContextKey.js';
import { TerminalAccessibilityCommandId } from '../common/terminal.accessibility.js';
import { TerminalAccessibilitySettingId } from '../common/terminalAccessibilityConfiguration.js';
import { BufferContentTracker } from './bufferContentTracker.js';
import { TerminalAccessibilityHelpProvider } from './terminalAccessibilityHelp.js';
import { TextAreaSyncAddon } from './textAreaSyncAddon.js';
import type { Terminal } from '@xterm/xterm';
import { Position } from '../../../../../editor/common/core/position.js';
import { ICommandWithEditorLine, TerminalAccessibleBufferProvider } from './terminalAccessibleBufferProvider.js';
import { IConfigurationService } from '../../../../../platform/configuration/common/configuration.js';
import { TerminalSettingId } from '../../../../../platform/terminal/common/terminal.js';
import { Event } from '../../../../../base/common/event.js';
import { ICurrentPartialCommand } from '../../../../../platform/terminal/common/capabilities/commandDetection/terminalCommand.js';
import { AccessibilitySignal, IAccessibilitySignalService } from '../../../../../platform/accessibilitySignal/browser/accessibilitySignalService.js';
import { TerminalAccessibilitySettingId } from '../common/terminalAccessibilityConfiguration.js';
import { TerminalAccessibilityCommandId } from '../common/terminal.accessibility.js';
import { IAccessibleViewService, AccessibleViewProviderId, NavigationType } from '../../../../../platform/accessibility/browser/accessibleView.js';
import { accessibleViewCurrentProviderId, accessibleViewIsShown } from '../../../accessibility/browser/accessibilityConfiguration.js';
import { isWindows } from '../../../../../base/common/platform.js';
import { TextAreaSyncAddon } from './textAreaSyncAddon.js';
// #region Terminal Contributions
@@ -45,9 +43,7 @@ class TextAreaSyncContribution extends DisposableStore implements ITerminalContr
}
private _addon: TextAreaSyncAddon | undefined;
constructor(
private readonly _instance: ITerminalInstance,
processManager: ITerminalProcessManager,
widgetManager: TerminalWidgetManager,
private readonly _ctx: ITerminalContributionContext,
@IInstantiationService private readonly _instantiationService: IInstantiationService
) {
super();
@@ -56,7 +52,7 @@ class TextAreaSyncContribution extends DisposableStore implements ITerminalContr
if (this._addon) {
return;
}
this._addon = this.add(this._instantiationService.createInstance(TextAreaSyncAddon, this._instance.capabilities));
this._addon = this.add(this._instantiationService.createInstance(TextAreaSyncAddon, this._ctx.instance.capabilities));
xterm.raw.loadAddon(this._addon);
this._addon.activate(xterm.raw);
}
@@ -74,9 +70,7 @@ export class TerminalAccessibleViewContribution extends Disposable implements IT
private readonly _onDidRunCommand: MutableDisposable<IDisposable> = new MutableDisposable();
constructor(
private readonly _instance: ITerminalInstance,
processManager: ITerminalProcessManager,
widgetManager: TerminalWidgetManager,
private readonly _ctx: ITerminalContributionContext,
@IAccessibleViewService private readonly _accessibleViewService: IAccessibleViewService,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@ITerminalService private readonly _terminalService: ITerminalService,
@@ -85,16 +79,16 @@ export class TerminalAccessibleViewContribution extends Disposable implements IT
@IAccessibilitySignalService private readonly _accessibilitySignalService: IAccessibilitySignalService) {
super();
this._register(AccessibleViewAction.addImplementation(90, 'terminal', () => {
if (this._terminalService.activeInstance !== this._instance) {
if (this._terminalService.activeInstance !== this._ctx.instance) {
return false;
}
this.show();
return true;
}, TerminalContextKeys.focus));
this._register(_instance.onDidExecuteText(() => {
this._register(this._ctx.instance.onDidExecuteText(() => {
const focusAfterRun = _configurationService.getValue(TerminalSettingId.FocusAfterRun);
if (focusAfterRun === 'terminal') {
_instance.focus(true);
this._ctx.instance.focus(true);
} else if (focusAfterRun === 'accessible-buffer') {
this.show();
}
@@ -104,7 +98,7 @@ export class TerminalAccessibleViewContribution extends Disposable implements IT
this._updateCommandExecutedListener();
}
}));
this._register(this._instance.capabilities.onDidAddCapability(e => {
this._register(this._ctx.instance.capabilities.onDidAddCapability(e => {
if (e.capability.type === TerminalCapability.CommandDetection) {
this._updateCommandExecutedListener();
}
@@ -112,12 +106,12 @@ export class TerminalAccessibleViewContribution extends Disposable implements IT
}
xtermReady(xterm: IXtermTerminal & { raw: Terminal }): void {
const addon = this._instantiationService.createInstance(TextAreaSyncAddon, this._instance.capabilities);
const addon = this._instantiationService.createInstance(TextAreaSyncAddon, this._ctx.instance.capabilities);
xterm.raw.loadAddon(addon);
addon.activate(xterm.raw);
this._xterm = xterm;
this._register(this._xterm.raw.onWriteParsed(async () => {
if (this._terminalService.activeInstance !== this._instance) {
if (this._terminalService.activeInstance !== this._ctx.instance) {
return;
}
if (this._isTerminalAccessibleViewOpen() && this._xterm!.raw.buffer.active.baseY === 0) {
@@ -127,7 +121,7 @@ export class TerminalAccessibleViewContribution extends Disposable implements IT
const onRequestUpdateEditor = Event.latch(this._xterm.raw.onScroll);
this._register(onRequestUpdateEditor(() => {
if (this._terminalService.activeInstance !== this._instance) {
if (this._terminalService.activeInstance !== this._ctx.instance) {
return;
}
if (this._isTerminalAccessibleViewOpen()) {
@@ -137,7 +131,7 @@ export class TerminalAccessibleViewContribution extends Disposable implements IT
}
private _updateCommandExecutedListener(): void {
if (!this._instance.capabilities.has(TerminalCapability.CommandDetection)) {
if (!this._ctx.instance.capabilities.has(TerminalCapability.CommandDetection)) {
return;
}
if (!this._configurationService.getValue(TerminalAccessibilitySettingId.AccessibleViewFocusOnCommandExecution)) {
@@ -147,9 +141,9 @@ export class TerminalAccessibleViewContribution extends Disposable implements IT
return;
}
const capability = this._instance.capabilities.get(TerminalCapability.CommandDetection)!;
const capability = this._ctx.instance.capabilities.get(TerminalCapability.CommandDetection)!;
this._onDidRunCommand.value = this._register(capability.onCommandExecuted(() => {
if (this._instance.hasFocus) {
if (this._ctx.instance.hasFocus) {
this.show();
}
}));
@@ -167,8 +161,8 @@ export class TerminalAccessibleViewContribution extends Disposable implements IT
this._bufferTracker = this._register(this._instantiationService.createInstance(BufferContentTracker, this._xterm));
}
if (!this._bufferProvider) {
this._bufferProvider = this._register(this._instantiationService.createInstance(TerminalAccessibleBufferProvider, this._instance, this._bufferTracker, () => {
return this._register(this._instantiationService.createInstance(TerminalAccessibilityHelpProvider, this._instance, this._xterm!)).provideContent();
this._bufferProvider = this._register(this._instantiationService.createInstance(TerminalAccessibleBufferProvider, this._ctx.instance, this._bufferTracker, () => {
return this._register(this._instantiationService.createInstance(TerminalAccessibilityHelpProvider, this._ctx.instance, this._xterm!)).provideContent();
}));
}
const position = this._configurationService.getValue(TerminalAccessibilitySettingId.AccessibleViewPreserveCursorPosition) ? this._accessibleViewService.getPosition(AccessibleViewProviderId.Terminal) : undefined;
@@ -202,7 +196,7 @@ export class TerminalAccessibleViewContribution extends Disposable implements IT
}
private _getCommandsWithEditorLine(): ICommandWithEditorLine[] | undefined {
const capability = this._instance.capabilities.get(TerminalCapability.CommandDetection);
const capability = this._ctx.instance.capabilities.get(TerminalCapability.CommandDetection);
const commands = capability?.commands;
const currentCommand = capability?.currentCommand;
if (!commands?.length) {

View File

@@ -2,36 +2,34 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Disposable, DisposableStore, MutableDisposable } from '../../../../../base/common/lifecycle.js';
import { IDetachedTerminalInstance, ITerminalContribution, ITerminalEditorService, ITerminalGroupService, ITerminalInstance, ITerminalService, IXtermTerminal } from '../../../terminal/browser/terminal.js';
import { registerTerminalContribution } from '../../../terminal/browser/terminalExtensions.js';
import type { Terminal as RawXtermTerminal, IDecoration, ITerminalAddon } from '@xterm/xterm';
import { TerminalWidgetManager } from '../../../terminal/browser/widgets/widgetManager.js';
import { ITerminalProcessManager, ITerminalProcessInfo } from '../../../terminal/common/terminal.js';
import { ITerminalCapabilityStore, TerminalCapability } from '../../../../../platform/terminal/common/capabilities/capabilities.js';
import { IKeybindingService } from '../../../../../platform/keybinding/common/keybinding.js';
import { localize } from '../../../../../nls.js';
import { Emitter, Event } from '../../../../../base/common/event.js';
import { OS } from '../../../../../base/common/platform.js';
import { KeybindingLabel } from '../../../../../base/browser/ui/keybindingLabel/keybindingLabel.js';
import { IContentActionHandler, renderFormattedText } from '../../../../../base/browser/formattedTextRenderer.js';
import { WorkbenchActionExecutedClassification, WorkbenchActionExecutedEvent } from '../../../../../base/common/actions.js';
import { AccessibilityVerbositySettingId } from '../../../accessibility/browser/accessibilityConfiguration.js';
import { IConfigurationService } from '../../../../../platform/configuration/common/configuration.js';
import { ICommandService } from '../../../../../platform/commands/common/commands.js';
import { IProductService } from '../../../../../platform/product/common/productService.js';
import { ITelemetryService } from '../../../../../platform/telemetry/common/telemetry.js';
import { status } from '../../../../../base/browser/ui/aria/aria.js';
import type { IDecoration, ITerminalAddon, Terminal as RawXtermTerminal } from '@xterm/xterm';
import * as dom from '../../../../../base/browser/dom.js';
import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js';
import { TerminalChatCommandId } from './terminalChat.js';
import { TerminalInstance } from '../../../terminal/browser/terminalInstance.js';
import './media/terminalInitialHint.css';
import { TerminalInitialHintSettingId } from '../common/terminalInitialHintConfiguration.js';
import { ChatAgentLocation, IChatAgent, IChatAgentService } from '../../../chat/common/chatAgents.js';
import { IStorageService, StorageScope, StorageTarget } from '../../../../../platform/storage/common/storage.js';
import { IContextMenuService } from '../../../../../platform/contextview/browser/contextView.js';
import { IContentActionHandler, renderFormattedText } from '../../../../../base/browser/formattedTextRenderer.js';
import { StandardMouseEvent } from '../../../../../base/browser/mouseEvent.js';
import { status } from '../../../../../base/browser/ui/aria/aria.js';
import { KeybindingLabel } from '../../../../../base/browser/ui/keybindingLabel/keybindingLabel.js';
import { WorkbenchActionExecutedClassification, WorkbenchActionExecutedEvent } from '../../../../../base/common/actions.js';
import { Emitter, Event } from '../../../../../base/common/event.js';
import { Disposable, DisposableStore, MutableDisposable } from '../../../../../base/common/lifecycle.js';
import { OS } from '../../../../../base/common/platform.js';
import { localize } from '../../../../../nls.js';
import { ICommandService } from '../../../../../platform/commands/common/commands.js';
import { IConfigurationService } from '../../../../../platform/configuration/common/configuration.js';
import { IContextMenuService } from '../../../../../platform/contextview/browser/contextView.js';
import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js';
import { IKeybindingService } from '../../../../../platform/keybinding/common/keybinding.js';
import { IProductService } from '../../../../../platform/product/common/productService.js';
import { IStorageService, StorageScope, StorageTarget } from '../../../../../platform/storage/common/storage.js';
import { ITelemetryService } from '../../../../../platform/telemetry/common/telemetry.js';
import { ITerminalCapabilityStore, TerminalCapability } from '../../../../../platform/terminal/common/capabilities/capabilities.js';
import { AccessibilityVerbositySettingId } from '../../../accessibility/browser/accessibilityConfiguration.js';
import { ChatAgentLocation, IChatAgent, IChatAgentService } from '../../../chat/common/chatAgents.js';
import { IDetachedTerminalInstance, ITerminalContribution, ITerminalEditorService, ITerminalGroupService, ITerminalInstance, ITerminalService, IXtermTerminal } from '../../../terminal/browser/terminal.js';
import { registerTerminalContribution, type IDetachedCompatibleTerminalContributionContext, type ITerminalContributionContext } from '../../../terminal/browser/terminalExtensions.js';
import { TerminalInstance } from '../../../terminal/browser/terminalInstance.js';
import { TerminalInitialHintSettingId } from '../common/terminalInitialHintConfiguration.js';
import './media/terminalInitialHint.css';
import { TerminalChatCommandId } from './terminalChat.js';
const $ = dom.$;
@@ -89,9 +87,7 @@ export class TerminalInitialHintContribution extends Disposable implements ITerm
private _xterm: IXtermTerminal & { raw: RawXtermTerminal } | undefined;
constructor(
private readonly _instance: Pick<ITerminalInstance, 'capabilities' | 'shellLaunchConfig'> | IDetachedTerminalInstance,
processManager: ITerminalProcessManager | ITerminalProcessInfo | undefined,
widgetManager: TerminalWidgetManager | undefined,
private readonly _ctx: ITerminalContributionContext | IDetachedCompatibleTerminalContributionContext,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@IConfigurationService private readonly _configurationService: IConfigurationService,
@ITerminalGroupService private readonly _terminalGroupService: ITerminalGroupService,
@@ -111,7 +107,7 @@ export class TerminalInitialHintContribution extends Disposable implements ITerm
xtermOpen(xterm: IXtermTerminal & { raw: RawXtermTerminal }): void {
// Don't show is the terminal was launched by an extension or a feature like debug
if ('shellLaunchConfig' in this._instance && (this._instance.shellLaunchConfig.isExtensionOwnedTerminal || this._instance.shellLaunchConfig.isFeatureTerminal)) {
if ('shellLaunchConfig' in this._ctx.instance && (this._ctx.instance.shellLaunchConfig.isExtensionOwnedTerminal || this._ctx.instance.shellLaunchConfig.isFeatureTerminal)) {
return;
}
// Don't show if disabled
@@ -123,13 +119,13 @@ export class TerminalInitialHintContribution extends Disposable implements ITerm
return;
}
this._xterm = xterm;
this._addon = this._register(this._instantiationService.createInstance(InitialHintAddon, this._instance.capabilities, this._chatAgentService.onDidChangeAgents));
this._addon = this._register(this._instantiationService.createInstance(InitialHintAddon, this._ctx.instance.capabilities, this._chatAgentService.onDidChangeAgents));
this._xterm.raw.loadAddon(this._addon);
this._register(this._addon.onDidRequestCreateHint(() => this._createHint()));
}
private _createHint(): void {
const instance = this._instance instanceof TerminalInstance ? this._instance : undefined;
const instance = this._ctx.instance instanceof TerminalInstance ? this._ctx.instance : undefined;
const commandDetectionCapability = instance?.capabilities.get(TerminalCapability.CommandDetection);
if (!instance || !this._xterm || this._hintWidget || !commandDetectionCapability || commandDetectionCapability.promptInputModel.value || !!instance.shellLaunchConfig.attachPersistentProcess) {
return;

View File

@@ -12,18 +12,17 @@ import { IContextKey, IContextKeyService } from '../../../../../platform/context
import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js';
import { IChatCodeBlockContextProviderService, IChatWidget, showChatView } from '../../../chat/browser/chat.js';
import { IChatProgress, IChatService } from '../../../chat/common/chatService.js';
import { ITerminalContribution, ITerminalInstance, ITerminalService, IXtermTerminal, isDetachedTerminalInstance } from '../../../terminal/browser/terminal.js';
import { TerminalWidgetManager } from '../../../terminal/browser/widgets/widgetManager.js';
import { ITerminalProcessManager } from '../../../terminal/common/terminal.js';
import { isDetachedTerminalInstance, ITerminalContribution, ITerminalInstance, ITerminalService, IXtermTerminal } from '../../../terminal/browser/terminal.js';
import { TerminalChatWidget } from './terminalChatWidget.js';
import { ChatModel, IChatResponseModel } from '../../../chat/common/chatModel.js';
import { TerminalChatContextKeys } from './terminalChat.js';
import { IViewsService } from '../../../../services/views/common/viewsService.js';
import { IStorageService, StorageScope, StorageTarget } from '../../../../../platform/storage/common/storage.js';
import { assertType } from '../../../../../base/common/types.js';
import { CancelablePromise, createCancelablePromise, DeferredPromise } from '../../../../../base/common/async.js';
import { assertType } from '../../../../../base/common/types.js';
import { IStorageService, StorageScope, StorageTarget } from '../../../../../platform/storage/common/storage.js';
import { IViewsService } from '../../../../services/views/common/viewsService.js';
import { ChatAgentLocation } from '../../../chat/common/chatAgents.js';
import { ChatModel, IChatResponseModel } from '../../../chat/common/chatModel.js';
import type { ITerminalContributionContext } from '../../../terminal/browser/terminalExtensions.js';
import { TerminalChatContextKeys } from './terminalChat.js';
const enum Message {
NONE = 0,
@@ -100,9 +99,7 @@ export class TerminalChatController extends Disposable implements ITerminalContr
private _activeRequestCts?: CancellationTokenSource;
constructor(
private readonly _instance: ITerminalInstance,
processManager: ITerminalProcessManager,
widgetManager: TerminalWidgetManager,
private readonly _ctx: ITerminalContributionContext,
@ITerminalService private readonly _terminalService: ITerminalService,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@IContextKeyService private readonly _contextKeyService: IContextKeyService,
@@ -146,18 +143,18 @@ export class TerminalChatController extends Disposable implements ITerminalContr
xtermReady(xterm: IXtermTerminal & { raw: RawXtermTerminal }): void {
this._terminalChatWidget = new Lazy(() => {
const chatWidget = this._register(this._instantiationService.createInstance(TerminalChatWidget, this._instance.domElement!, this._instance, xterm));
const chatWidget = this._register(this._instantiationService.createInstance(TerminalChatWidget, this._ctx.instance.domElement!, this._ctx.instance, xterm));
this._register(chatWidget.focusTracker.onDidFocus(() => {
TerminalChatController.activeChatController = this;
if (!isDetachedTerminalInstance(this._instance)) {
this._terminalService.setActiveInstance(this._instance);
if (!isDetachedTerminalInstance(this._ctx.instance)) {
this._terminalService.setActiveInstance(this._ctx.instance);
}
}));
this._register(chatWidget.focusTracker.onDidBlur(() => {
TerminalChatController.activeChatController = undefined;
this._instance.resetScrollbarVisibility();
this._ctx.instance.resetScrollbarVisibility();
}));
if (!this._instance.domElement) {
if (!this._ctx.instance.domElement) {
throw new Error('FindWidget expected terminal DOM to be initialized');
}
return chatWidget;

View File

@@ -13,9 +13,7 @@ import { listInactiveSelectionBackground } from '../../../../../platform/theme/c
import { registerColor, transparent } from '../../../../../platform/theme/common/colorUtils.js';
import { PANEL_BORDER } from '../../../../common/theme.js';
import { IDetachedTerminalInstance, ITerminalContribution, ITerminalInstance, IXtermTerminal } from '../../../terminal/browser/terminal.js';
import { registerTerminalContribution } from '../../../terminal/browser/terminalExtensions.js';
import { TerminalWidgetManager } from '../../../terminal/browser/widgets/widgetManager.js';
import { ITerminalProcessInfo, ITerminalProcessManager } from '../../../terminal/common/terminal.js';
import { registerTerminalContribution, type IDetachedCompatibleTerminalContributionContext, type ITerminalContributionContext } from '../../../terminal/browser/terminalExtensions.js';
import { terminalCommandGuideConfigSection, TerminalCommandGuideSettingId, type ITerminalCommandGuideConfiguration } from '../common/terminalCommandGuideConfiguration.js';
// #region Terminal Contributions
@@ -31,9 +29,7 @@ class TerminalCommandGuideContribution extends Disposable implements ITerminalCo
private readonly _activeCommandGuide = this._register(new MutableDisposable());
constructor(
private readonly _instance: ITerminalInstance | IDetachedTerminalInstance,
processManager: ITerminalProcessManager | ITerminalProcessInfo,
widgetManager: TerminalWidgetManager,
private readonly _ctx: ITerminalContributionContext | IDetachedCompatibleTerminalContributionContext,
@IConfigurationService private readonly _configurationService: IConfigurationService,
) {
super();
@@ -81,7 +77,7 @@ class TerminalCommandGuideContribution extends Disposable implements ITerminalCo
return;
}
const mouseCursorY = Math.floor((e.clientY - rect.top) / (rect.height / xterm.raw.rows));
const command = this._instance.capabilities.get(TerminalCapability.CommandDetection)?.getCommandForLine(xterm.raw.buffer.active.viewportY + mouseCursorY);
const command = this._ctx.instance.capabilities.get(TerminalCapability.CommandDetection)?.getCommandForLine(xterm.raw.buffer.active.viewportY + mouseCursorY);
if (command && 'getOutput' in command) {
xterm.markTracker.showCommandGuide(command);
} else {

View File

@@ -9,7 +9,6 @@ import { VSBuffer } from '../../../../../base/common/buffer.js';
import { Event } from '../../../../../base/common/event.js';
import { Disposable, DisposableMap, DisposableStore, IDisposable, MutableDisposable, combinedDisposable, dispose } from '../../../../../base/common/lifecycle.js';
import { URI } from '../../../../../base/common/uri.js';
import './media/developer.css';
import { localize, localize2 } from '../../../../../nls.js';
import { Categories } from '../../../../../platform/action/common/actionCommonCategories.js';
import { IClipboardService } from '../../../../../platform/clipboard/common/clipboardService.js';
@@ -22,14 +21,13 @@ import { IQuickInputService } from '../../../../../platform/quickinput/common/qu
import { ITerminalCommand, TerminalCapability, type ICommandDetectionCapability } from '../../../../../platform/terminal/common/capabilities/capabilities.js';
import { ITerminalLogService, TerminalSettingId } from '../../../../../platform/terminal/common/terminal.js';
import { IWorkspaceContextService } from '../../../../../platform/workspace/common/workspace.js';
import { IStatusbarService, StatusbarAlignment, type IStatusbarEntry, type IStatusbarEntryAccessor } from '../../../../services/statusbar/browser/statusbar.js';
import { IInternalXtermTerminal, ITerminalContribution, ITerminalInstance, IXtermTerminal } from '../../../terminal/browser/terminal.js';
import { registerTerminalAction } from '../../../terminal/browser/terminalActions.js';
import { registerTerminalContribution } from '../../../terminal/browser/terminalExtensions.js';
import { TerminalWidgetManager } from '../../../terminal/browser/widgets/widgetManager.js';
import { ITerminalProcessManager } from '../../../terminal/common/terminal.js';
import { registerTerminalContribution, type ITerminalContributionContext } from '../../../terminal/browser/terminalExtensions.js';
import { TerminalContextKeys } from '../../../terminal/common/terminalContextKey.js';
import { TerminalDeveloperCommandId } from '../common/terminal.developer.js';
import { IStatusbarService, StatusbarAlignment, type IStatusbarEntry, type IStatusbarEntryAccessor } from '../../../../services/statusbar/browser/statusbar.js';
import './media/developer.css';
registerTerminalAction({
id: TerminalDeveloperCommandId.ShowTextureAtlas,
@@ -230,9 +228,7 @@ class DevModeContribution extends Disposable implements ITerminalContribution {
private readonly _statusbarEntryAccessor: MutableDisposable<IStatusbarEntryAccessor> = this._register(new MutableDisposable());
constructor(
private readonly _instance: ITerminalInstance,
processManager: ITerminalProcessManager,
widgetManager: TerminalWidgetManager,
private readonly _ctx: ITerminalContributionContext,
@IConfigurationService private readonly _configurationService: IConfigurationService,
@IStatusbarService private readonly _statusbarService: IStatusbarService,
) {
@@ -253,7 +249,7 @@ class DevModeContribution extends Disposable implements ITerminalContribution {
const devMode: boolean = this._isEnabled();
this._xterm?.raw.element?.classList.toggle('dev-mode', devMode);
const commandDetection = this._instance.capabilities.get(TerminalCapability.CommandDetection);
const commandDetection = this._ctx.instance.capabilities.get(TerminalCapability.CommandDetection);
if (devMode) {
if (commandDetection) {
const commandDecorations = new DisposableMap<ITerminalCommand, IDisposable>();
@@ -262,8 +258,8 @@ class DevModeContribution extends Disposable implements ITerminalContribution {
commandDecorations,
otherDisposables,
// Prompt input
this._instance.onDidBlur(() => this._updateDevMode()),
this._instance.onDidFocus(() => this._updateDevMode()),
this._ctx.instance.onDidBlur(() => this._updateDevMode()),
this._ctx.instance.onDidFocus(() => this._updateDevMode()),
commandDetection.promptInputModel.onDidChangeInput(() => this._updateDevMode()),
// Sequence markers
commandDetection.onCommandFinished(command => {
@@ -271,7 +267,7 @@ class DevModeContribution extends Disposable implements ITerminalContribution {
const decorations: IDisposable[] = [];
commandDecorations.set(command, combinedDisposable(...decorations));
if (command.promptStartMarker) {
const d = this._instance.xterm!.raw?.registerDecoration({
const d = this._ctx.instance.xterm!.raw?.registerDecoration({
marker: command.promptStartMarker
});
if (d) {
@@ -283,7 +279,7 @@ class DevModeContribution extends Disposable implements ITerminalContribution {
}
}
if (command.marker) {
const d = this._instance.xterm!.raw?.registerDecoration({
const d = this._ctx.instance.xterm!.raw?.registerDecoration({
marker: command.marker,
x: command.startX
});
@@ -296,7 +292,7 @@ class DevModeContribution extends Disposable implements ITerminalContribution {
}
}
if (command.executedMarker) {
const d = this._instance.xterm!.raw?.registerDecoration({
const d = this._ctx.instance.xterm!.raw?.registerDecoration({
marker: command.executedMarker,
x: command.executedX
});
@@ -309,7 +305,7 @@ class DevModeContribution extends Disposable implements ITerminalContribution {
}
}
if (command.endMarker) {
const d = this._instance.xterm!.raw?.registerDecoration({
const d = this._ctx.instance.xterm!.raw?.registerDecoration({
marker: command.endMarker
});
if (d) {
@@ -335,7 +331,7 @@ class DevModeContribution extends Disposable implements ITerminalContribution {
this._updatePromptInputStatusBar(commandDetection);
} else {
this._activeDevModeDisposables.value = this._instance.capabilities.onDidAddCapabilityType(e => {
this._activeDevModeDisposables.value = this._ctx.instance.capabilities.onDidAddCapabilityType(e => {
if (e === TerminalCapability.CommandDetection) {
this._updateDevMode();
}
@@ -363,11 +359,11 @@ class DevModeContribution extends Disposable implements ITerminalContribution {
kind: 'prominent'
};
if (!this._statusbarEntryAccessor.value) {
this._statusbarEntryAccessor.value = this._statusbarService.addEntry(this._statusbarEntry, `terminal.promptInput.${this._instance.instanceId}`, StatusbarAlignment.LEFT);
this._statusbarEntryAccessor.value = this._statusbarService.addEntry(this._statusbarEntry, `terminal.promptInput.${this._ctx.instance.instanceId}`, StatusbarAlignment.LEFT);
} else {
this._statusbarEntryAccessor.value.update(this._statusbarEntry);
}
this._statusbarService.updateEntryVisibility(`terminal.promptInput.${this._instance.instanceId}`, this._instance.hasFocus);
this._statusbarService.updateEntryVisibility(`terminal.promptInput.${this._ctx.instance.instanceId}`, this._ctx.instance.hasFocus);
}
}
}

View File

@@ -3,6 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import type { Terminal as RawXtermTerminal } from '@xterm/xterm';
import { IDimension } from '../../../../../base/browser/dom.js';
import { KeyCode, KeyMod } from '../../../../../base/common/keyCodes.js';
import { Lazy } from '../../../../../base/common/lazy.js';
@@ -14,14 +15,11 @@ import { KeybindingWeight } from '../../../../../platform/keybinding/common/keyb
import { findInFilesCommand } from '../../../search/browser/searchActionsFind.js';
import { IDetachedTerminalInstance, ITerminalContribution, ITerminalInstance, ITerminalService, IXtermTerminal, isDetachedTerminalInstance } from '../../../terminal/browser/terminal.js';
import { registerActiveInstanceAction, registerActiveXtermAction } from '../../../terminal/browser/terminalActions.js';
import { registerTerminalContribution } from '../../../terminal/browser/terminalExtensions.js';
import { TerminalWidgetManager } from '../../../terminal/browser/widgets/widgetManager.js';
import { ITerminalProcessInfo, ITerminalProcessManager } from '../../../terminal/common/terminal.js';
import { registerTerminalContribution, type IDetachedCompatibleTerminalContributionContext, type ITerminalContributionContext } from '../../../terminal/browser/terminalExtensions.js';
import { TerminalContextKeys } from '../../../terminal/common/terminalContextKey.js';
import { TerminalFindWidget } from './terminalFindWidget.js';
import type { Terminal as RawXtermTerminal } from '@xterm/xterm';
import { TerminalFindCommandId } from '../common/terminal.find.js';
import './media/terminalFind.css';
import { TerminalFindWidget } from './terminalFindWidget.js';
// #region Terminal Contributions
@@ -44,35 +42,33 @@ class TerminalFindContribution extends Disposable implements ITerminalContributi
get findWidget(): TerminalFindWidget { return this._findWidget.value; }
constructor(
private readonly _instance: ITerminalInstance | IDetachedTerminalInstance,
processManager: ITerminalProcessManager | ITerminalProcessInfo,
widgetManager: TerminalWidgetManager,
ctx: ITerminalContributionContext | IDetachedCompatibleTerminalContributionContext,
@IInstantiationService instantiationService: IInstantiationService,
@ITerminalService terminalService: ITerminalService
) {
super();
this._findWidget = new Lazy(() => {
const findWidget = instantiationService.createInstance(TerminalFindWidget, this._instance);
const findWidget = instantiationService.createInstance(TerminalFindWidget, ctx.instance);
// Track focus and set state so we can force the scroll bar to be visible
findWidget.focusTracker.onDidFocus(() => {
TerminalFindContribution.activeFindWidget = this;
this._instance.forceScrollbarVisibility();
if (!isDetachedTerminalInstance(this._instance)) {
terminalService.setActiveInstance(this._instance);
ctx.instance.forceScrollbarVisibility();
if (!isDetachedTerminalInstance(ctx.instance)) {
terminalService.setActiveInstance(ctx.instance);
}
});
findWidget.focusTracker.onDidBlur(() => {
TerminalFindContribution.activeFindWidget = undefined;
this._instance.resetScrollbarVisibility();
ctx.instance.resetScrollbarVisibility();
});
if (!this._instance.domElement) {
if (!ctx.instance.domElement) {
throw new Error('FindWidget expected terminal DOM to be initialized');
}
this._instance.domElement?.appendChild(findWidget.getDomNode());
ctx.instance.domElement?.appendChild(findWidget.getDomNode());
if (this._lastLayoutDimensions) {
findWidget.layout(this._lastLayoutDimensions.width);
}

View File

@@ -16,9 +16,7 @@ import { TerminalLocation } from '../../../../../platform/terminal/common/termin
import { accessibleViewCurrentProviderId, accessibleViewIsShown } from '../../../accessibility/browser/accessibilityConfiguration.js';
import type { ITerminalContribution, ITerminalInstance } from '../../../terminal/browser/terminal.js';
import { registerActiveInstanceAction, registerTerminalAction } from '../../../terminal/browser/terminalActions.js';
import { registerTerminalContribution } from '../../../terminal/browser/terminalExtensions.js';
import type { TerminalWidgetManager } from '../../../terminal/browser/widgets/widgetManager.js';
import { type ITerminalProcessManager } from '../../../terminal/common/terminal.js';
import { registerTerminalContribution, type ITerminalContributionContext } from '../../../terminal/browser/terminalExtensions.js';
import { TerminalContextKeys } from '../../../terminal/common/terminalContextKey.js';
import { clearShellFileHistory, getCommandHistory, getDirectoryHistory } from '../common/history.js';
import { TerminalHistoryCommandId } from '../common/terminal.history.js';
@@ -36,9 +34,7 @@ class TerminalHistoryContribution extends Disposable implements ITerminalContrib
private _terminalInRunCommandPicker: IContextKey<boolean>;
constructor(
private readonly _instance: ITerminalInstance,
processManager: ITerminalProcessManager,
widgetManager: TerminalWidgetManager,
private readonly _ctx: ITerminalContributionContext,
@IContextKeyService private readonly _contextKeyService: IContextKeyService,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
) {
@@ -46,18 +42,18 @@ class TerminalHistoryContribution extends Disposable implements ITerminalContrib
this._terminalInRunCommandPicker = TerminalContextKeys.inTerminalRunCommandPicker.bindTo(this._contextKeyService);
this._register(this._instance.capabilities.onDidAddCapabilityType(e => {
this._register(_ctx.instance.capabilities.onDidAddCapabilityType(e => {
switch (e) {
case TerminalCapability.CwdDetection: {
this._instance.capabilities.get(TerminalCapability.CwdDetection)?.onDidChangeCwd(e => {
this._instantiationService.invokeFunction(getDirectoryHistory)?.add(e, { remoteAuthority: this._instance.remoteAuthority });
_ctx.instance.capabilities.get(TerminalCapability.CwdDetection)?.onDidChangeCwd(e => {
this._instantiationService.invokeFunction(getDirectoryHistory)?.add(e, { remoteAuthority: _ctx.instance.remoteAuthority });
});
break;
}
case TerminalCapability.CommandDetection: {
this._instance.capabilities.get(TerminalCapability.CommandDetection)?.onCommandFinished(e => {
_ctx.instance.capabilities.get(TerminalCapability.CommandDetection)?.onCommandFinished(e => {
if (e.command.trim().length > 0) {
this._instantiationService.invokeFunction(getCommandHistory)?.add(e.command, { shellType: this._instance.shellType });
this._instantiationService.invokeFunction(getCommandHistory)?.add(e.command, { shellType: _ctx.instance.shellType });
}
});
break;
@@ -72,7 +68,7 @@ class TerminalHistoryContribution extends Disposable implements ITerminalContrib
*/
async runRecent(type: 'command' | 'cwd', filterMode?: 'fuzzy' | 'contiguous', value?: string): Promise<void> {
return this._instantiationService.invokeFunction(showRunRecentQuickPick,
this._instance,
this._ctx.instance,
this._terminalInRunCommandPicker,
type,
filterMode,

View File

@@ -3,30 +3,29 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import type { Terminal as RawXtermTerminal } from '@xterm/xterm';
import { Event } from '../../../../../base/common/event.js';
import { KeyCode, KeyMod } from '../../../../../base/common/keyCodes.js';
import { DisposableStore } from '../../../../../base/common/lifecycle.js';
import { localize2 } from '../../../../../nls.js';
import { AccessibleViewProviderId } from '../../../../../platform/accessibility/browser/accessibleView.js';
import { ContextKeyExpr } from '../../../../../platform/contextkey/common/contextkey.js';
import { InstantiationType, registerSingleton } from '../../../../../platform/instantiation/common/extensions.js';
import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js';
import { KeybindingWeight } from '../../../../../platform/keybinding/common/keybindingsRegistry.js';
import { accessibleViewCurrentProviderId, accessibleViewIsShown } from '../../../accessibility/browser/accessibilityConfiguration.js';
import { IDetachedTerminalInstance, ITerminalContribution, ITerminalInstance, IXtermTerminal, isDetachedTerminalInstance } from '../../../terminal/browser/terminal.js';
import { ITerminalContribution, ITerminalInstance, IXtermTerminal, isDetachedTerminalInstance } from '../../../terminal/browser/terminal.js';
import { registerActiveInstanceAction } from '../../../terminal/browser/terminalActions.js';
import { registerTerminalContribution } from '../../../terminal/browser/terminalExtensions.js';
import { TerminalWidgetManager } from '../../../terminal/browser/widgets/widgetManager.js';
import { ITerminalProcessInfo, ITerminalProcessManager, isTerminalProcessManager } from '../../../terminal/common/terminal.js';
import { registerTerminalContribution, type IDetachedCompatibleTerminalContributionContext, type ITerminalContributionContext } from '../../../terminal/browser/terminalExtensions.js';
import { isTerminalProcessManager } from '../../../terminal/common/terminal.js';
import { TerminalContextKeys } from '../../../terminal/common/terminalContextKey.js';
import { terminalStrings } from '../../../terminal/common/terminalStrings.js';
import { TerminalLinksCommandId } from '../common/terminal.links.js';
import { ITerminalLinkProviderService } from './links.js';
import { IDetectedLinks, TerminalLinkManager } from './terminalLinkManager.js';
import { TerminalLinkProviderService } from './terminalLinkProviderService.js';
import { TerminalLinkQuickpick } from './terminalLinkQuickpick.js';
import { TerminalLinkResolver } from './terminalLinkResolver.js';
import type { Terminal as RawXtermTerminal } from '@xterm/xterm';
import { TerminalLinksCommandId } from '../common/terminal.links.js';
import { AccessibleViewProviderId } from '../../../../../platform/accessibility/browser/accessibleView.js';
// #region Services
@@ -48,9 +47,7 @@ class TerminalLinkContribution extends DisposableStore implements ITerminalContr
private _linkResolver: TerminalLinkResolver;
constructor(
private readonly _instance: ITerminalInstance | IDetachedTerminalInstance,
private readonly _processManager: ITerminalProcessManager | ITerminalProcessInfo,
private readonly _widgetManager: TerminalWidgetManager,
private readonly _ctx: ITerminalContributionContext | IDetachedCompatibleTerminalContributionContext,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@ITerminalLinkProviderService private readonly _terminalLinkProviderService: ITerminalLinkProviderService
) {
@@ -59,25 +56,25 @@ class TerminalLinkContribution extends DisposableStore implements ITerminalContr
}
xtermReady(xterm: IXtermTerminal & { raw: RawXtermTerminal }): void {
const linkManager = this._linkManager = this.add(this._instantiationService.createInstance(TerminalLinkManager, xterm.raw, this._processManager, this._instance.capabilities, this._linkResolver));
const linkManager = this._linkManager = this.add(this._instantiationService.createInstance(TerminalLinkManager, xterm.raw, this._ctx.processManager, this._ctx.instance.capabilities, this._linkResolver));
// Set widget manager
if (isTerminalProcessManager(this._processManager)) {
const disposable = linkManager.add(Event.once(this._processManager.onProcessReady)(() => {
linkManager.setWidgetManager(this._widgetManager);
if (isTerminalProcessManager(this._ctx.processManager)) {
const disposable = linkManager.add(Event.once(this._ctx.processManager.onProcessReady)(() => {
linkManager.setWidgetManager(this._ctx.widgetManager);
this.delete(disposable);
}));
} else {
linkManager.setWidgetManager(this._widgetManager);
linkManager.setWidgetManager(this._ctx.widgetManager);
}
// Attach the external link provider to the instance and listen for changes
if (!isDetachedTerminalInstance(this._instance)) {
if (!isDetachedTerminalInstance(this._ctx.instance)) {
for (const linkProvider of this._terminalLinkProviderService.linkProviders) {
linkManager.externalProvideLinksCb = linkProvider.provideLinks.bind(linkProvider, this._instance);
linkManager.externalProvideLinksCb = linkProvider.provideLinks.bind(linkProvider, this._ctx.instance);
}
linkManager.add(this._terminalLinkProviderService.onDidAddLinkProvider(e => {
linkManager.externalProvideLinksCb = e.provideLinks.bind(e, this._instance as ITerminalInstance);
linkManager.externalProvideLinksCb = e.provideLinks.bind(e, this._ctx.instance as ITerminalInstance);
}));
}
linkManager.add(this._terminalLinkProviderService.onDidRemoveLinkProvider(() => linkManager.externalProvideLinksCb = undefined));
@@ -91,7 +88,7 @@ class TerminalLinkContribution extends DisposableStore implements ITerminalContr
});
}
const links = await this._getLinks();
return await this._terminalLinkQuickpick.show(this._instance, links);
return await this._terminalLinkQuickpick.show(this._ctx.instance, links);
}
private async _getLinks(): Promise<{ viewport: IDetectedLinks; all: Promise<IDetectedLinks> }> {

View File

@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import './media/terminalQuickFix.css';
import type { Terminal as RawXtermTerminal } from '@xterm/xterm';
import { KeyCode, KeyMod } from '../../../../../base/common/keyCodes.js';
import { DisposableStore } from '../../../../../base/common/lifecycle.js';
import { localize2 } from '../../../../../nls.js';
@@ -12,15 +12,13 @@ import { IInstantiationService } from '../../../../../platform/instantiation/com
import { KeybindingWeight } from '../../../../../platform/keybinding/common/keybindingsRegistry.js';
import { ITerminalContribution, ITerminalInstance, IXtermTerminal } from '../../../terminal/browser/terminal.js';
import { registerActiveInstanceAction } from '../../../terminal/browser/terminalActions.js';
import { registerTerminalContribution } from '../../../terminal/browser/terminalExtensions.js';
import { TerminalWidgetManager } from '../../../terminal/browser/widgets/widgetManager.js';
import { ITerminalProcessManager } from '../../../terminal/common/terminal.js';
import { registerTerminalContribution, type ITerminalContributionContext } from '../../../terminal/browser/terminalExtensions.js';
import { TerminalContextKeys } from '../../../terminal/common/terminalContextKey.js';
import './media/terminalQuickFix.css';
import { ITerminalQuickFixService } from './quickFix.js';
import { TerminalQuickFixAddon } from './quickFixAddon.js';
import { freePort, gitCreatePr, gitFastForwardPull, gitPushSetUpstream, gitSimilar, gitTwoDashes, pwshGeneralError, pwshUnixCommandNotFoundError } from './terminalQuickFixBuiltinActions.js';
import { TerminalQuickFixService } from './terminalQuickFixService.js';
import type { Terminal as RawXtermTerminal } from '@xterm/xterm';
// #region Services
@@ -41,9 +39,7 @@ class TerminalQuickFixContribution extends DisposableStore implements ITerminalC
get addon(): TerminalQuickFixAddon | undefined { return this._addon; }
constructor(
private readonly _instance: ITerminalInstance,
processManager: ITerminalProcessManager,
widgetManager: TerminalWidgetManager,
private readonly _ctx: ITerminalContributionContext,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
) {
super();
@@ -51,17 +47,17 @@ class TerminalQuickFixContribution extends DisposableStore implements ITerminalC
xtermReady(xterm: IXtermTerminal & { raw: RawXtermTerminal }): void {
// Create addon
this._addon = this._instantiationService.createInstance(TerminalQuickFixAddon, undefined, this._instance.capabilities);
this._addon = this._instantiationService.createInstance(TerminalQuickFixAddon, undefined, this._ctx.instance.capabilities);
xterm.raw.loadAddon(this._addon);
// Hook up listeners
this.add(this._addon.onDidRequestRerunCommand((e) => this._instance.runCommand(e.command, e.shouldExecute || false)));
this.add(this._addon.onDidRequestRerunCommand((e) => this._ctx.instance.runCommand(e.command, e.shouldExecute || false)));
// Register quick fixes
for (const actionOption of [
gitTwoDashes(),
gitFastForwardPull(),
freePort((port: string, command: string) => this._instance.freePortKillProcess(port, command)),
freePort((port: string, command: string) => this._ctx.instance.freePortKillProcess(port, command)),
gitSimilar(),
gitPushSetUpstream(),
gitCreatePr(),

View File

@@ -15,7 +15,7 @@ import { TerminalStickyScrollSettingId } from '../common/terminalStickyScrollCon
// #region Terminal Contributions
registerTerminalContribution(TerminalStickyScrollContribution.ID, TerminalStickyScrollContribution, true);
registerTerminalContribution(TerminalStickyScrollContribution.ID, TerminalStickyScrollContribution);
// #endregion

View File

@@ -6,17 +6,16 @@
import type { Terminal as RawXtermTerminal } from '@xterm/xterm';
import { Event } from '../../../../../base/common/event.js';
import { Disposable, MutableDisposable } from '../../../../../base/common/lifecycle.js';
import './media/stickyScroll.css';
import { IConfigurationService } from '../../../../../platform/configuration/common/configuration.js';
import { IContextKeyService } from '../../../../../platform/contextkey/common/contextkey.js';
import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js';
import { IKeybindingService } from '../../../../../platform/keybinding/common/keybinding.js';
import { TerminalCapability } from '../../../../../platform/terminal/common/capabilities/capabilities.js';
import { ITerminalContribution, ITerminalInstance, IXtermTerminal } from '../../../terminal/browser/terminal.js';
import type { ITerminalContributionContext } from '../../../terminal/browser/terminalExtensions.js';
import { TerminalInstance, TerminalInstanceColorProvider } from '../../../terminal/browser/terminalInstance.js';
import { TerminalWidgetManager } from '../../../terminal/browser/widgets/widgetManager.js';
import { ITerminalProcessInfo, ITerminalProcessManager } from '../../../terminal/common/terminal.js';
import { TerminalStickyScrollSettingId } from '../common/terminalStickyScrollConfiguration.js';
import './media/stickyScroll.css';
import { TerminalStickyScrollOverlay } from './terminalStickyScrollOverlay.js';
export class TerminalStickyScrollContribution extends Disposable implements ITerminalContribution {
@@ -34,9 +33,7 @@ export class TerminalStickyScrollContribution extends Disposable implements ITer
private readonly _disableListeners = this._register(new MutableDisposable());
constructor(
private readonly _instance: ITerminalInstance,
processManager: ITerminalProcessManager | ITerminalProcessInfo,
widgetManager: TerminalWidgetManager,
private readonly _ctx: ITerminalContributionContext,
@IConfigurationService private readonly _configurationService: IConfigurationService,
@IContextKeyService private readonly _contextKeyService: IContextKeyService,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@@ -78,7 +75,7 @@ export class TerminalStickyScrollContribution extends Disposable implements ITer
if (this._overlay.value) {
this._enableListeners.clear();
if (!this._disableListeners.value) {
this._disableListeners.value = this._instance.capabilities.onDidRemoveCapability(e => {
this._disableListeners.value = this._ctx.instance.capabilities.onDidRemoveCapability(e => {
if (e.id === TerminalCapability.CommandDetection) {
this._refreshState();
}
@@ -87,7 +84,7 @@ export class TerminalStickyScrollContribution extends Disposable implements ITer
} else {
this._disableListeners.clear();
if (!this._enableListeners.value) {
this._enableListeners.value = this._instance.capabilities.onDidAddCapability(e => {
this._enableListeners.value = this._ctx.instance.capabilities.onDidAddCapability(e => {
if (e.id === TerminalCapability.CommandDetection) {
this._refreshState();
}
@@ -101,10 +98,10 @@ export class TerminalStickyScrollContribution extends Disposable implements ITer
const xtermCtorEventually = TerminalInstance.getXtermConstructor(this._keybindingService, this._contextKeyService);
this._overlay.value = this._instantiationService.createInstance(
TerminalStickyScrollOverlay,
this._instance,
this._ctx.instance,
this._xterm!,
this._instantiationService.createInstance(TerminalInstanceColorProvider, this._instance.targetRef),
this._instance.capabilities.get(TerminalCapability.CommandDetection)!,
this._instantiationService.createInstance(TerminalInstanceColorProvider, this._ctx.instance.targetRef),
this._ctx.instance.capabilities.get(TerminalCapability.CommandDetection)!,
xtermCtorEventually
);
}
@@ -117,7 +114,7 @@ export class TerminalStickyScrollContribution extends Disposable implements ITer
}
private _shouldBeEnabled(): boolean {
const capability = this._instance.capabilities.get(TerminalCapability.CommandDetection);
const capability = this._ctx.instance.capabilities.get(TerminalCapability.CommandDetection);
return !!(this._configurationService.getValue(TerminalStickyScrollSettingId.Enabled) && capability && this._xterm?.raw?.element);
}
}

View File

@@ -11,6 +11,7 @@ import { KeyCode, KeyMod } from '../../../../../base/common/keyCodes.js';
import { DisposableStore, MutableDisposable, toDisposable } from '../../../../../base/common/lifecycle.js';
import { isWindows } from '../../../../../base/common/platform.js';
import { localize2 } from '../../../../../nls.js';
import { CONTEXT_ACCESSIBILITY_MODE_ENABLED } from '../../../../../platform/accessibility/common/accessibility.js';
import { IConfigurationService } from '../../../../../platform/configuration/common/configuration.js';
import { ContextKeyExpr, IContextKey, IContextKeyService, IReadableSet } from '../../../../../platform/contextkey/common/contextkey.js';
import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js';
@@ -18,18 +19,16 @@ import { KeybindingWeight } from '../../../../../platform/keybinding/common/keyb
import { IStorageService, StorageScope, StorageTarget } from '../../../../../platform/storage/common/storage.js';
import { GeneralShellType, TerminalLocation, TerminalSettingId } from '../../../../../platform/terminal/common/terminal.js';
import { ShellIntegrationOscPs } from '../../../../../platform/terminal/common/xterm/shellIntegrationAddon.js';
import { SimpleCompletionItem } from '../../../../services/suggest/browser/simpleCompletionItem.js';
import { ITerminalContribution, ITerminalInstance, IXtermTerminal } from '../../../terminal/browser/terminal.js';
import { registerActiveInstanceAction } from '../../../terminal/browser/terminalActions.js';
import { registerTerminalContribution } from '../../../terminal/browser/terminalExtensions.js';
import { TerminalWidgetManager } from '../../../terminal/browser/widgets/widgetManager.js';
import { ITerminalProcessManager, TERMINAL_CONFIG_SECTION, type ITerminalConfiguration } from '../../../terminal/common/terminal.js';
import { registerTerminalContribution, type ITerminalContributionContext } from '../../../terminal/browser/terminalExtensions.js';
import { registerSendSequenceKeybinding } from '../../../terminal/browser/terminalKeybindings.js';
import { TERMINAL_CONFIG_SECTION, type ITerminalConfiguration } from '../../../terminal/common/terminal.js';
import { TerminalContextKeys, TerminalContextKeyStrings } from '../../../terminal/common/terminalContextKey.js';
import { parseCompletionsFromShell, SuggestAddon, VSCodeSuggestOscPt, type CompressedPwshCompletion, type PwshCompletion } from './terminalSuggestAddon.js';
import { TerminalSuggestCommandId } from '../common/terminal.suggest.js';
import { terminalSuggestConfigSection, TerminalSuggestSettingId, type ITerminalSuggestConfiguration } from '../common/terminalSuggestConfiguration.js';
import { SimpleCompletionItem } from '../../../../services/suggest/browser/simpleCompletionItem.js';
import { registerSendSequenceKeybinding } from '../../../terminal/browser/terminalKeybindings.js';
import { CONTEXT_ACCESSIBILITY_MODE_ENABLED } from '../../../../../platform/accessibility/common/accessibility.js';
import { parseCompletionsFromShell, SuggestAddon, VSCodeSuggestOscPt, type CompressedPwshCompletion, type PwshCompletion } from './terminalSuggestAddon.js';
const enum Constants {
CachedPwshCommandsStorageKey = 'terminal.suggest.pwshCommands'
@@ -54,9 +53,7 @@ class TerminalSuggestContribution extends DisposableStore implements ITerminalCo
private static readonly _cachedPwshCommands: Set<SimpleCompletionItem> = new Set();
constructor(
private readonly _instance: ITerminalInstance,
processManager: ITerminalProcessManager,
widgetManager: TerminalWidgetManager,
private readonly _ctx: ITerminalContributionContext,
@IContextKeyService private readonly _contextKeyService: IContextKeyService,
@IConfigurationService private readonly _configurationService: IConfigurationService,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@@ -139,7 +136,7 @@ class TerminalSuggestContribution extends DisposableStore implements ITerminalCo
if (!enabled) {
return;
}
this.add(Event.runAndSubscribe(this._instance.onDidChangeShellType, async () => {
this.add(Event.runAndSubscribe(this._ctx.instance.onDidChangeShellType, async () => {
this._loadSuggestAddon(xterm.raw);
}));
this.add(this._contextKeyService.onDidChangeContext(e => {
@@ -156,26 +153,26 @@ class TerminalSuggestContribution extends DisposableStore implements ITerminalCo
private _loadSuggestAddon(xterm: RawXtermTerminal): void {
const sendingKeybindingsToShell = this._configurationService.getValue<ITerminalConfiguration>(TERMINAL_CONFIG_SECTION).sendKeybindingsToShell;
if (sendingKeybindingsToShell || this._instance.shellType !== 'pwsh') {
if (sendingKeybindingsToShell || this._ctx.instance.shellType !== 'pwsh') {
this._addon.clear();
return;
}
if (this._terminalSuggestWidgetVisibleContextKey) {
const addon = this._addon.value = this._instantiationService.createInstance(SuggestAddon, TerminalSuggestContribution._cachedPwshCommands, this._instance.capabilities, this._terminalSuggestWidgetVisibleContextKey);
const addon = this._addon.value = this._instantiationService.createInstance(SuggestAddon, TerminalSuggestContribution._cachedPwshCommands, this._ctx.instance.capabilities, this._terminalSuggestWidgetVisibleContextKey);
xterm.loadAddon(addon);
if (this._instance.target === TerminalLocation.Editor) {
if (this._ctx.instance.target === TerminalLocation.Editor) {
addon.setContainerWithOverflow(xterm.element!);
} else {
addon.setContainerWithOverflow(dom.findParentWithClass(xterm.element!, 'panel')!);
}
addon.setScreen(xterm.element!.querySelector('.xterm-screen')!);
this.add(this._instance.onDidBlur(() => addon.hideSuggestWidget()));
this.add(this._ctx.instance.onDidBlur(() => addon.hideSuggestWidget()));
this.add(addon.onAcceptedCompletion(async text => {
this._instance.focus();
this._instance.sendText(text, false);
this._ctx.instance.focus();
this._ctx.instance.sendText(text, false);
}));
this.add(this._instance.onWillPaste(() => addon.isPasting = true));
this.add(this._instance.onDidPaste(() => {
this.add(this._ctx.instance.onWillPaste(() => addon.isPasting = true));
this.add(this._ctx.instance.onDidPaste(() => {
// Delay this slightly as synchronizing the prompt input is debounced
setTimeout(() => addon.isPasting = false, 100);
}));
@@ -189,7 +186,7 @@ class TerminalSuggestContribution extends DisposableStore implements ITerminalCo
let barrier: AutoOpenBarrier | undefined;
this.add(addon.onDidRequestCompletions(() => {
barrier = new AutoOpenBarrier(2000);
this._instance.pauseInputEvents(barrier);
this._ctx.instance.pauseInputEvents(barrier);
}));
this.add(addon.onDidReceiveCompletions(() => {
barrier?.open();

View File

@@ -3,16 +3,15 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import type { Terminal as RawXtermTerminal } from '@xterm/xterm';
import { DisposableStore, toDisposable } from '../../../../../base/common/lifecycle.js';
import { IConfigurationService } from '../../../../../platform/configuration/common/configuration.js';
import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js';
import { ITerminalContribution, ITerminalInstance, IXtermTerminal } from '../../../terminal/browser/terminal.js';
import { registerTerminalContribution } from '../../../terminal/browser/terminalExtensions.js';
import { TerminalWidgetManager } from '../../../terminal/browser/widgets/widgetManager.js';
import { TypeAheadAddon } from './terminalTypeAheadAddon.js';
import { ITerminalProcessManager, TERMINAL_CONFIG_SECTION } from '../../../terminal/common/terminal.js';
import type { Terminal as RawXtermTerminal } from '@xterm/xterm';
import { registerTerminalContribution, type ITerminalContributionContext } from '../../../terminal/browser/terminalExtensions.js';
import { TERMINAL_CONFIG_SECTION } from '../../../terminal/common/terminal.js';
import { TerminalTypeAheadSettingId, type ITerminalTypeAheadConfiguration } from '../common/terminalTypeAheadConfiguration.js';
import { TypeAheadAddon } from './terminalTypeAheadAddon.js';
class TerminalTypeAheadContribution extends DisposableStore implements ITerminalContribution {
static readonly ID = 'terminal.typeAhead';
@@ -24,9 +23,7 @@ class TerminalTypeAheadContribution extends DisposableStore implements ITerminal
private _addon: TypeAheadAddon | undefined;
constructor(
instance: ITerminalInstance,
private readonly _processManager: ITerminalProcessManager,
widgetManager: TerminalWidgetManager,
private readonly _ctx: ITerminalContributionContext,
@IConfigurationService private readonly _configurationService: IConfigurationService,
@IInstantiationService private readonly _instantiationService: IInstantiationService
) {
@@ -43,14 +40,14 @@ class TerminalTypeAheadContribution extends DisposableStore implements ITerminal
}));
// Reset the addon when the terminal launches or relaunches
this.add(this._processManager.onProcessReady(() => {
this.add(this._ctx.processManager.onProcessReady(() => {
this._addon?.reset();
}));
}
private _loadTypeAheadAddon(xterm: RawXtermTerminal): void {
const enabled = this._configurationService.getValue<ITerminalTypeAheadConfiguration>(TERMINAL_CONFIG_SECTION).localEchoEnabled;
const isRemote = !!this._processManager.remoteAuthority;
const isRemote = !!this._ctx.processManager.remoteAuthority;
if (enabled === 'off' || enabled === 'auto' && !isRemote) {
this._addon?.dispose();
this._addon = undefined;
@@ -60,7 +57,7 @@ class TerminalTypeAheadContribution extends DisposableStore implements ITerminal
return;
}
if (enabled === 'on' || (enabled === 'auto' && isRemote)) {
this._addon = this._instantiationService.createInstance(TypeAheadAddon, this._processManager);
this._addon = this._instantiationService.createInstance(TypeAheadAddon, this._ctx.processManager);
xterm.loadAddon(this._addon);
}
}

View File

@@ -11,10 +11,8 @@ import { Disposable, MutableDisposable, toDisposable } from '../../../../../base
import { isMacintosh } from '../../../../../base/common/platform.js';
import { TerminalSettingId } from '../../../../../platform/terminal/common/terminal.js';
import { IDetachedTerminalInstance, ITerminalContribution, ITerminalInstance, IXtermTerminal } from '../../../terminal/browser/terminal.js';
import { registerTerminalContribution } from '../../../terminal/browser/terminalExtensions.js';
import { registerTerminalContribution, type IDetachedCompatibleTerminalContributionContext, type ITerminalContributionContext } from '../../../terminal/browser/terminalExtensions.js';
import { IConfigurationService } from '../../../../../platform/configuration/common/configuration.js';
import { ITerminalProcessInfo, ITerminalProcessManager } from '../../../terminal/common/terminal.js';
import { TerminalWidgetManager } from '../../../terminal/browser/widgets/widgetManager.js';
import { registerTerminalAction } from '../../../terminal/browser/terminalActions.js';
import { localize2 } from '../../../../../nls.js';
import { isNumber } from '../../../../../base/common/types.js';
@@ -37,9 +35,7 @@ class TerminalMouseWheelZoomContribution extends Disposable implements ITerminal
private readonly _listener = this._register(new MutableDisposable());
constructor(
instance: ITerminalInstance | IDetachedTerminalInstance,
processManager: ITerminalProcessManager | ITerminalProcessInfo,
widgetManager: TerminalWidgetManager,
_ctx: ITerminalContributionContext | IDetachedCompatibleTerminalContributionContext,
@IConfigurationService private readonly _configurationService: IConfigurationService,
) {
super();