Skip to content

Commit

Permalink
Merge pull request #232740 from microsoft/tyriar/232656__232658
Browse files Browse the repository at this point in the history
Put terminal quick fixes into the SI menu too
  • Loading branch information
Tyriar authored Nov 4, 2024
2 parents d9d4fc8 + d5c34d7 commit e37672f
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 12 deletions.
8 changes: 7 additions & 1 deletion src/vs/platform/terminal/common/terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Event } from '../../../base/common/event.js';
import { IProcessEnvironment, OperatingSystem } from '../../../base/common/platform.js';
import { URI, UriComponents } from '../../../base/common/uri.js';
import { createDecorator } from '../../instantiation/common/instantiation.js';
import { IPtyHostProcessReplayEvent, ISerializedCommandDetectionCapability, ITerminalCapabilityStore } from './capabilities/capabilities.js';
import { IPtyHostProcessReplayEvent, ISerializedCommandDetectionCapability, ITerminalCapabilityStore, type ITerminalCommand } from './capabilities/capabilities.js';
import { IGetTerminalLayoutInfoArgs, IProcessDetails, ISetTerminalLayoutInfoArgs } from './terminalProcess.js';
import { ThemeIcon } from '../../../base/common/themables.js';
import { ISerializableEnvironmentVariableCollections } from './environmentVariable.js';
Expand All @@ -16,6 +16,8 @@ import { IWorkspaceFolder } from '../../workspace/common/workspace.js';
import { Registry } from '../../registry/common/platform.js';
import type * as performance from '../../../base/common/performance.js';
import { ILogService } from '../../log/common/log.js';
import type { IAction } from '../../../base/common/actions.js';
import type { IDisposable } from '../../../base/common/lifecycle.js';

export const terminalTabFocusModeContextKey = new RawContextKey<boolean>('terminalTabFocusMode', false, true);

Expand Down Expand Up @@ -929,6 +931,10 @@ export interface IShellIntegration {
deserialize(serialized: ISerializedCommandDetectionCapability): void;
}

export interface IDecorationAddon {
registerMenuItems(command: ITerminalCommand, items: IAction[]): IDisposable;
}

export interface ITerminalContributions {
profiles?: ITerminalProfileContribution[];
}
Expand Down
4 changes: 3 additions & 1 deletion src/vs/workbench/contrib/terminal/browser/terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { createDecorator } from '../../../../platform/instantiation/common/insta
import { IKeyMods } from '../../../../platform/quickinput/common/quickInput.js';
import { IMarkProperties, ITerminalCapabilityImplMap, ITerminalCapabilityStore, ITerminalCommand, TerminalCapability } from '../../../../platform/terminal/common/capabilities/capabilities.js';
import { IMergedEnvironmentVariableCollection } from '../../../../platform/terminal/common/environmentVariable.js';
import { IExtensionTerminalProfile, IReconnectionProperties, IShellIntegration, IShellLaunchConfig, ITerminalBackend, ITerminalDimensions, ITerminalLaunchError, ITerminalProfile, ITerminalTabLayoutInfoById, TerminalExitReason, TerminalIcon, TerminalLocation, TerminalShellType, TerminalType, TitleEventSource, WaitOnExitValue } from '../../../../platform/terminal/common/terminal.js';
import { IExtensionTerminalProfile, IReconnectionProperties, IShellIntegration, IShellLaunchConfig, ITerminalBackend, ITerminalDimensions, ITerminalLaunchError, ITerminalProfile, ITerminalTabLayoutInfoById, TerminalExitReason, TerminalIcon, TerminalLocation, TerminalShellType, TerminalType, TitleEventSource, WaitOnExitValue, type IDecorationAddon } from '../../../../platform/terminal/common/terminal.js';
import { IColorTheme } from '../../../../platform/theme/common/themeService.js';
import { IWorkspaceFolder } from '../../../../platform/workspace/common/workspace.js';
import { EditorInput } from '../../../common/editor/editorInput.js';
Expand Down Expand Up @@ -1063,6 +1063,8 @@ export interface IXtermTerminal extends IDisposable {
*/
readonly shellIntegration: IShellIntegration;

readonly decorationAddon: IDecorationAddon;

readonly onDidChangeSelection: Event<void>;
readonly onDidChangeFindResults: Event<{ resultIndex: number; resultCount: number }>;
readonly onDidRequestRunCommand: Event<{ command: ITerminalCommand; noNewLine?: boolean }>;
Expand Down
29 changes: 27 additions & 2 deletions src/vs/workbench/contrib/terminal/browser/xterm/decorationAddon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { INotificationService, Severity } from '../../../../../platform/notifica
import { IOpenerService } from '../../../../../platform/opener/common/opener.js';
import { IQuickInputService, IQuickPickItem } from '../../../../../platform/quickinput/common/quickInput.js';
import { CommandInvalidationReason, ICommandDetectionCapability, IMarkProperties, ITerminalCapabilityStore, ITerminalCommand, TerminalCapability } from '../../../../../platform/terminal/common/capabilities/capabilities.js';
import { TerminalSettingId } from '../../../../../platform/terminal/common/terminal.js';
import { TerminalSettingId, type IDecorationAddon } from '../../../../../platform/terminal/common/terminal.js';
import { IThemeService } from '../../../../../platform/theme/common/themeService.js';
import { terminalDecorationError, terminalDecorationIncomplete, terminalDecorationMark, terminalDecorationSuccess } from '../terminalIcons.js';
import { DecorationSelector, getTerminalDecorationHoverContent, updateLayout } from './decorationStyles.js';
Expand All @@ -30,13 +30,14 @@ import { MarkdownString } from '../../../../../base/common/htmlContent.js';

interface IDisposableDecoration { decoration: IDecoration; disposables: IDisposable[]; exitCode?: number; markProperties?: IMarkProperties }

export class DecorationAddon extends Disposable implements ITerminalAddon {
export class DecorationAddon extends Disposable implements ITerminalAddon, IDecorationAddon {
protected _terminal: Terminal | undefined;
private _capabilityDisposables: Map<TerminalCapability, DisposableStore> = new Map();
private _decorations: Map<number, IDisposableDecoration> = new Map();
private _placeholderDecoration: IDecoration | undefined;
private _showGutterDecorations?: boolean;
private _showOverviewRulerDecorations?: boolean;
private readonly _registeredMenuItems: Map<ITerminalCommand, IAction[]> = new Map();

private readonly _onDidRequestRunCommand = this._register(new Emitter<{ command: ITerminalCommand; noNewLine?: boolean }>());
readonly onDidRequestRunCommand = this._onDidRequestRunCommand.event;
Expand Down Expand Up @@ -309,6 +310,26 @@ export class DecorationAddon extends Disposable implements ITerminalAddon {
return decoration;
}

registerMenuItems(command: ITerminalCommand, items: IAction[]): IDisposable {
const existingItems = this._registeredMenuItems.get(command);
if (existingItems) {
existingItems.push(...items);
} else {
this._registeredMenuItems.set(command, [...items]);
}
return toDisposable(() => {
const commandItems = this._registeredMenuItems.get(command);
if (commandItems) {
for (const item of items.values()) {
const index = commandItems.indexOf(item);
if (index !== -1) {
commandItems.splice(index, 1);
}
}
}
});
}

private _createDisposables(element: HTMLElement, command?: ITerminalCommand, markProperties?: IMarkProperties): IDisposable[] {
if (command?.exitCode === undefined && !command?.markProperties) {
return [];
Expand Down Expand Up @@ -387,6 +408,10 @@ export class DecorationAddon extends Disposable implements ITerminalAddon {

private async _getCommandActions(command: ITerminalCommand): Promise<IAction[]> {
const actions: IAction[] = [];
const registeredMenuItems = this._registeredMenuItems.get(command);
if (registeredMenuItems?.length) {
actions.push(...registeredMenuItems, new Separator());
}
if (command.command !== '') {
const labelRun = localize("terminal.rerunCommand", 'Rerun Command');
actions.push({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { IXtermCore } from '../xterm-private.js';
import { IConfigurationService } from '../../../../../platform/configuration/common/configuration.js';
import { Disposable, DisposableStore } from '../../../../../base/common/lifecycle.js';
import { IEditorOptions } from '../../../../../editor/common/config/editorOptions.js';
import { IShellIntegration, ITerminalLogService, TerminalSettingId } from '../../../../../platform/terminal/common/terminal.js';
import { IShellIntegration, ITerminalLogService, TerminalSettingId, type IDecorationAddon } from '../../../../../platform/terminal/common/terminal.js';
import { ITerminalFont, ITerminalConfiguration } from '../../common/terminal.js';
import { IMarkTracker, IInternalXtermTerminal, IXtermTerminal, IXtermColorProvider, XtermTerminalConstants, IXtermAttachToElementOptions, IDetachedXtermTerminal, ITerminalConfigurationService } from '../terminal.js';
import { LogLevel } from '../../../../../platform/log/common/log.js';
Expand Down Expand Up @@ -139,6 +139,7 @@ export class XtermTerminal extends Disposable implements IXtermTerminal, IDetach

get markTracker(): IMarkTracker { return this._markNavigationAddon; }
get shellIntegration(): IShellIntegration { return this._shellIntegrationAddon; }
get decorationAddon(): IDecorationAddon { return this._decorationAddon; }

get textureAtlas(): Promise<ImageBitmap> | undefined {
const canvas = this._webglAddon?.textureAtlas;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ const quickFixClasses = [
];

export interface ITerminalQuickFixAddon {
readonly onDidRequestRerunCommand: Event<{ command: string; shouldExecute?: boolean }>;
readonly onDidUpdateQuickFixes: Event<{ command: ITerminalCommand; actions: ITerminalAction[] | undefined }>;
showMenu(): void;
onDidRequestRerunCommand: Event<{ command: string; shouldExecute?: boolean }>;
/**
* Registers a listener on onCommandFinished scoped to a particular command or regular
* expression and provides a callback to be executed for commands that match.
Expand All @@ -56,8 +57,6 @@ export interface ITerminalQuickFixAddon {
}

export class TerminalQuickFixAddon extends Disposable implements ITerminalAddon, ITerminalQuickFixAddon {
private readonly _onDidRequestRerunCommand = new Emitter<{ command: string; shouldExecute?: boolean }>();
readonly onDidRequestRerunCommand = this._onDidRequestRerunCommand.event;

private _terminal: Terminal | undefined;

Expand All @@ -76,6 +75,11 @@ export class TerminalQuickFixAddon extends Disposable implements ITerminalAddon,

private _didRun: boolean = false;

private readonly _onDidRequestRerunCommand = new Emitter<{ command: string; shouldExecute?: boolean }>();
readonly onDidRequestRerunCommand = this._onDidRequestRerunCommand.event;
private readonly _onDidUpdateQuickFixes = new Emitter<{ command: ITerminalCommand; actions: ITerminalAction[] | undefined }>();
readonly onDidUpdateQuickFixes = this._onDidUpdateQuickFixes.event;

constructor(
private readonly _aliases: string[][] | undefined,
private readonly _capabilities: ITerminalCapabilityStore,
Expand Down Expand Up @@ -186,7 +190,7 @@ export class TerminalQuickFixAddon extends Disposable implements ITerminalAddon,
return;
}
if (command.command !== '' && this._lastQuickFixId) {
this._disposeQuickFix(this._lastQuickFixId);
this._disposeQuickFix(command, this._lastQuickFixId);
}

const resolver = async (selector: ITerminalQuickFixOptions, lines?: string[]) => {
Expand All @@ -212,9 +216,11 @@ export class TerminalQuickFixAddon extends Disposable implements ITerminalAddon,
this._quickFixes = result;
this._lastQuickFixId = this._quickFixes[0].id;
this._registerQuickFixDecoration();
this._onDidUpdateQuickFixes.fire({ command, actions: this._quickFixes });
this._quickFixes = undefined;
}

private _disposeQuickFix(id: string): void {
private _disposeQuickFix(command: ITerminalCommand, id: string): void {
type QuickFixResultTelemetryEvent = {
quickFixId: string;
ranQuickFix: boolean;
Expand All @@ -231,6 +237,7 @@ export class TerminalQuickFixAddon extends Disposable implements ITerminalAddon,
});
this._decoration.clear();
this._decorationDisposables.clear();
this._onDidUpdateQuickFixes.fire({ command, actions: this._quickFixes });
this._quickFixes = undefined;
this._lastQuickFixId = undefined;
this._didRun = false;
Expand Down Expand Up @@ -295,7 +302,6 @@ export class TerminalQuickFixAddon extends Disposable implements ITerminalAddon,
this._register(dom.addDisposableListener(e, dom.EventType.CLICK, () => this.showMenu()));
}));
store.add(decoration.onDispose(() => this._currentRenderContext = undefined));
this._quickFixes = undefined;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import type { Terminal as RawXtermTerminal } from '@xterm/xterm';
import { KeyCode, KeyMod } from '../../../../../base/common/keyCodes.js';
import { DisposableStore } from '../../../../../base/common/lifecycle.js';
import { DisposableStore, MutableDisposable } from '../../../../../base/common/lifecycle.js';
import { localize2 } from '../../../../../nls.js';
import { InstantiationType, registerSingleton } from '../../../../../platform/instantiation/common/extensions.js';
import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js';
Expand Down Expand Up @@ -38,6 +38,8 @@ class TerminalQuickFixContribution extends DisposableStore implements ITerminalC
private _addon?: TerminalQuickFixAddon;
get addon(): TerminalQuickFixAddon | undefined { return this._addon; }

private readonly _quickFixMenuItems = this.add(new MutableDisposable());

constructor(
private readonly _ctx: ITerminalContributionContext,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
Expand All @@ -52,6 +54,10 @@ class TerminalQuickFixContribution extends DisposableStore implements ITerminalC

// Hook up listeners
this.add(this._addon.onDidRequestRerunCommand((e) => this._ctx.instance.runCommand(e.command, e.shouldExecute || false)));
this.add(this._addon.onDidUpdateQuickFixes(e => {
// Only track the latest command's quick fixes
this._quickFixMenuItems.value = e.actions ? xterm.decorationAddon.registerMenuItems(e.command, e.actions) : undefined;
}));

// Register quick fixes
for (const actionOption of [
Expand Down

0 comments on commit e37672f

Please sign in to comment.