diff --git a/src/vs/platform/terminal/common/terminal.ts b/src/vs/platform/terminal/common/terminal.ts index 9dee3d5b41ab2..235d8efdbe8e0 100644 --- a/src/vs/platform/terminal/common/terminal.ts +++ b/src/vs/platform/terminal/common/terminal.ts @@ -966,6 +966,7 @@ export interface ITerminalCommandSelector { outputMatcher?: ITerminalOutputMatcher; exitStatus: boolean; commandExitResult: 'success' | 'error'; + kind?: 'fix' | 'explain'; } export interface ITerminalBackend { diff --git a/src/vs/workbench/contrib/terminal/browser/media/terminal.css b/src/vs/workbench/contrib/terminal/browser/media/terminal.css index 1b240eafdab36..96e52e4816c82 100644 --- a/src/vs/workbench/contrib/terminal/browser/media/terminal.css +++ b/src/vs/workbench/contrib/terminal/browser/media/terminal.css @@ -486,6 +486,11 @@ color: var(--vscode-editorLightBulb-foreground) !important; background-color: var(--vscode-terminal-background, --vscode-panel-background); } +.monaco-workbench .terminal .terminal-command-decoration.quick-fix.explainOnly { + /* Use success background to blend in with the terminal better as it's lower priority. We will + * probably want to add an explicit color for this eventually. */ + color: var(--vscode-terminalCommandDecoration-successBackground) !important; +} .terminal-scroll-highlight { left: 0; diff --git a/src/vs/workbench/contrib/terminalContrib/quickFix/browser/quickFix.ts b/src/vs/workbench/contrib/terminalContrib/quickFix/browser/quickFix.ts index 8a13380b9713a..f576102fe854f 100644 --- a/src/vs/workbench/contrib/terminalContrib/quickFix/browser/quickFix.ts +++ b/src/vs/workbench/contrib/terminalContrib/quickFix/browser/quickFix.ts @@ -56,6 +56,7 @@ export interface ITerminalQuickFixOptions { commandLineMatcher: string | RegExp; outputMatcher?: ITerminalOutputMatcher; commandExitResult: 'success' | 'error'; + kind?: 'fix' | 'explain'; } export interface ITerminalQuickFix { diff --git a/src/vs/workbench/contrib/terminalContrib/quickFix/browser/quickFixAddon.ts b/src/vs/workbench/contrib/terminalContrib/quickFix/browser/quickFixAddon.ts index 0631a1e4e044d..9f1ccc65e8c44 100644 --- a/src/vs/workbench/contrib/terminalContrib/quickFix/browser/quickFixAddon.ts +++ b/src/vs/workbench/contrib/terminalContrib/quickFix/browser/quickFixAddon.ts @@ -36,9 +36,8 @@ import { Codicon } from 'vs/base/common/codicons'; import { ThemeIcon } from 'vs/base/common/themables'; import { ICommandService } from 'vs/platform/commands/common/commands'; -const quickFixSelectors = [ +const quickFixClasses = [ DecorationSelector.QuickFix, - DecorationSelector.LightBulb, DecorationSelector.Codicon, DecorationSelector.CommandDecoration, DecorationSelector.XtermDecoration @@ -116,7 +115,7 @@ export class TerminalQuickFixAddon extends Disposable implements ITerminalAddon, } // TODO: What's documentation do? Need a vscode command? - const actions = this._currentRenderContext.quickFixes.map(f => new TerminalQuickFixItem(f, f.type, f.source, f.label)); + const actions = this._currentRenderContext.quickFixes.map(f => new TerminalQuickFixItem(f, f.type, f.source, f.label, f.kind)); const documentation = this._currentRenderContext.quickFixes.map(f => { return { id: f.source, title: f.label, tooltip: f.source }; }); const actionSet = { // TODO: Documentation and actions are separate? @@ -150,7 +149,8 @@ export class TerminalQuickFixAddon extends Disposable implements ITerminalAddon, type: 'unresolved', commandLineMatcher: selector.commandLineMatcher, outputMatcher: selector.outputMatcher, - commandExitResult: selector.commandExitResult + commandExitResult: selector.commandExitResult, + kind: selector.kind }); this._registeredSelectors.add(selector.id); this._commandListeners.set(matcherKey, currentOptions); @@ -192,7 +192,14 @@ export class TerminalQuickFixAddon extends Disposable implements ITerminalAddon, } const id = selector.id; await this._extensionService.activateByEvent(`onTerminalQuickFixRequest:${id}`); - return this._quickFixService.providers.get(id)?.provideTerminalQuickFixes(command, lines, { type: 'resolved', commandLineMatcher: selector.commandLineMatcher, outputMatcher: selector.outputMatcher, commandExitResult: selector.commandExitResult, id: selector.id }, new CancellationTokenSource().token); + return this._quickFixService.providers.get(id)?.provideTerminalQuickFixes(command, lines, { + type: 'resolved', + commandLineMatcher: selector.commandLineMatcher, + outputMatcher: selector.outputMatcher, + commandExitResult: selector.commandExitResult, + kind: selector.kind, + id: selector.id + }, new CancellationTokenSource().token); }; const result = await getQuickFixesForCommand(aliases, terminal, command, this._commandListeners, this._commandService, this._openerService, this._labelService, this._onDidRequestRerunCommand, resolver); if (!result) { @@ -266,7 +273,13 @@ export class TerminalQuickFixAddon extends Disposable implements ITerminalAddon, return; } - e.classList.add(...quickFixSelectors); + e.classList.add(...quickFixClasses); + const isExplainOnly = fixes.every(e => e.kind === 'explain'); + if (isExplainOnly) { + e.classList.add('explainOnly'); + } + e.classList.add(...ThemeIcon.asClassNameArray(isExplainOnly ? Codicon.sparkle : Codicon.lightBulb)); + updateLayout(this._configurationService, e); this._audioCueService.playAudioCue(AudioCue.terminalQuickFix); @@ -285,6 +298,7 @@ export class TerminalQuickFixAddon extends Disposable implements ITerminalAddon, export interface ITerminalAction extends IAction { type: TerminalQuickFixType; + kind?: 'fix' | 'explain'; source: string; uri?: URI; command?: string; @@ -351,6 +365,7 @@ export async function getQuickFixesForCommand( const label = localize('quickFix.command', 'Run: {0}', fix.terminalCommand); action = { type: TerminalQuickFixType.TerminalCommand, + kind: option.kind, class: undefined, source: quickFix.source, id: quickFix.id, @@ -384,6 +399,7 @@ export async function getQuickFixesForCommand( id: quickFix.id, label, type: TerminalQuickFixType.Opener, + kind: option.kind, class: undefined, enabled: true, run: () => openerService.open(fix.uri), @@ -397,6 +413,7 @@ export async function getQuickFixesForCommand( action = { source: 'builtin', type: fix.type, + kind: option.kind, id: fix.id, label: fix.label, class: fix.class, @@ -413,6 +430,7 @@ export async function getQuickFixesForCommand( action = { source: quickFix.source, type: fix.type, + kind: option.kind, id: fix.id, label: fix.title, class: undefined, @@ -441,22 +459,20 @@ function convertToQuickFixOptions(selectorProvider: ITerminalQuickFixProviderSel commandLineMatcher: selectorProvider.selector.commandLineMatcher, outputMatcher: selectorProvider.selector.outputMatcher, commandExitResult: selectorProvider.selector.commandExitResult, + kind: selectorProvider.selector.kind, getQuickFixes: selectorProvider.provider.provideTerminalQuickFixes }; } class TerminalQuickFixItem { - action: ITerminalAction; - type: TerminalQuickFixType; - disabled?: boolean; - title?: string; - source: string; - constructor(action: ITerminalAction, type: TerminalQuickFixType, source: string, title?: string, disabled?: boolean) { - this.action = action; - this.disabled = disabled; - this.title = title; - this.source = source; - this.type = type; + readonly disabled = false; + constructor( + readonly action: ITerminalAction, + readonly type: TerminalQuickFixType, + readonly source: string, + readonly title: string | undefined, + readonly kind: 'fix' | 'explain' = 'fix' + ) { } } @@ -488,6 +504,9 @@ function toActionWidgetItems(inputQuickFixes: readonly TerminalQuickFixItem[], s } function getQuickFixIcon(quickFix: TerminalQuickFixItem): ThemeIcon { + if (quickFix.kind === 'explain') { + return Codicon.sparkle; + } switch (quickFix.type) { case TerminalQuickFixType.Opener: if ('uri' in quickFix.action && quickFix.action.uri) { diff --git a/src/vs/workbench/contrib/terminalContrib/quickFix/browser/terminalQuickFixService.ts b/src/vs/workbench/contrib/terminalContrib/quickFix/browser/terminalQuickFixService.ts index 4119c99c0472f..61b17085bb663 100644 --- a/src/vs/workbench/contrib/terminalContrib/quickFix/browser/terminalQuickFixService.ts +++ b/src/vs/workbench/contrib/terminalContrib/quickFix/browser/terminalQuickFixService.ts @@ -139,6 +139,14 @@ const quickFixExtensionPoint = ExtensionsRegistry.registerExtensionPoint