Merge pull request #197668 from microsoft/merogge/quick-fix-api

`addNewLine` -> `shouldExecute`, expose this in quick fix API
This commit is contained in:
Megan Rogge 2023-11-21 10:23:27 -06:00 committed by GitHub
commit 8af169e554
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 60 additions and 56 deletions

View file

@ -78,7 +78,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
}
const lines = outputMatch.regexMatch[1];
const fixes: vscode.TerminalQuickFixExecuteTerminalCommand[] = [];
const fixes: vscode.TerminalQuickFixTerminalCommand[] = [];
for (const line of lines.split('\n')) {
// search from the second char, since the lines might be prefixed with
// "npm ERR!" which comes before the actual command suggestion.

View file

@ -203,9 +203,9 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
(await this._getTerminalInstance(id))?.dispose(TerminalExitReason.Extension);
}
public async $sendText(id: ExtHostTerminalIdentifier, text: string, addNewLine: boolean): Promise<void> {
public async $sendText(id: ExtHostTerminalIdentifier, text: string, shouldExecute: boolean): Promise<void> {
const instance = await this._getTerminalInstance(id);
await instance?.sendText(text, addNewLine);
await instance?.sendText(text, shouldExecute);
}
public $sendProcessExit(terminalId: number, exitCode: number | undefined): void {

View file

@ -1522,7 +1522,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
TaskRevealKind: extHostTypes.TaskRevealKind,
TaskScope: extHostTypes.TaskScope,
TerminalLink: extHostTypes.TerminalLink,
TerminalQuickFixExecuteTerminalCommand: extHostTypes.TerminalQuickFixCommand,
TerminalQuickFixTerminalCommand: extHostTypes.TerminalQuickFixCommand,
TerminalQuickFixOpener: extHostTypes.TerminalQuickFixOpener,
TerminalLocation: extHostTypes.TerminalLocation,
TerminalProfile: extHostTypes.TerminalProfile,

View file

@ -503,7 +503,7 @@ export interface MainThreadTerminalServiceShape extends IDisposable {
$createTerminal(extHostTerminalId: string, config: TerminalLaunchConfig): Promise<void>;
$dispose(id: ExtHostTerminalIdentifier): void;
$hide(id: ExtHostTerminalIdentifier): void;
$sendText(id: ExtHostTerminalIdentifier, text: string, addNewLine: boolean): void;
$sendText(id: ExtHostTerminalIdentifier, text: string, shouldExecute: boolean): void;
$show(id: ExtHostTerminalIdentifier, preserveFocus: boolean): void;
$registerProcessSupport(isSupported: boolean): void;
$registerProfileProvider(id: string, extensionIdentifier: string): void;
@ -2149,15 +2149,16 @@ export interface ITerminalDimensionsDto {
type SingleOrMany<T> = T[] | T;
export interface ITerminalQuickFixExecuteTerminalCommandDto {
export interface ITerminalQuickFixTerminalCommandDto {
terminalCommand: string;
shouldExecute?: boolean;
}
export interface ITerminalQuickFixOpenerDto {
uri: UriComponents;
}
export type TerminalQuickFix = ITerminalQuickFixExecuteTerminalCommandDto | ITerminalQuickFixOpenerDto | ICommandDto;
export type TerminalQuickFix = ITerminalQuickFixTerminalCommandDto | ITerminalQuickFixOpenerDto | ICommandDto;
export interface TerminalCommandMatchResultDto {
commandLine: string;

View file

@ -5,7 +5,7 @@
import type * as vscode from 'vscode';
import { Event, Emitter } from 'vs/base/common/event';
import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, ITerminalDimensionsDto, ITerminalLinkDto, ExtHostTerminalIdentifier, ICommandDto, ITerminalQuickFixOpenerDto, ITerminalQuickFixExecuteTerminalCommandDto, TerminalCommandMatchResultDto, ITerminalCommandDto } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, ITerminalDimensionsDto, ITerminalLinkDto, ExtHostTerminalIdentifier, ICommandDto, ITerminalQuickFixOpenerDto, ITerminalQuickFixTerminalCommandDto, TerminalCommandMatchResultDto, ITerminalCommandDto } from 'vs/workbench/api/common/extHost.protocol';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { URI } from 'vs/base/common/uri';
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
@ -117,9 +117,9 @@ export class ExtHostTerminal {
get selection(): string | undefined {
return that._selection;
},
sendText(text: string, addNewLine: boolean = true): void {
sendText(text: string, shouldExecute: boolean = true): void {
that._checkDisposed();
that._proxy.$sendText(that._id, text, addNewLine);
that._proxy.$sendText(that._id, text, shouldExecute);
},
show(preserveFocus: boolean): void {
that._checkDisposed();
@ -738,7 +738,7 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I
});
}
public async $provideTerminalQuickFixes(id: string, matchResult: TerminalCommandMatchResultDto): Promise<(ITerminalQuickFixExecuteTerminalCommandDto | ITerminalQuickFixOpenerDto | ICommandDto)[] | ITerminalQuickFixExecuteTerminalCommandDto | ITerminalQuickFixOpenerDto | ICommandDto | undefined> {
public async $provideTerminalQuickFixes(id: string, matchResult: TerminalCommandMatchResultDto): Promise<(ITerminalQuickFixTerminalCommandDto | ITerminalQuickFixOpenerDto | ICommandDto)[] | ITerminalQuickFixTerminalCommandDto | ITerminalQuickFixOpenerDto | ICommandDto | undefined> {
const token = new CancellationTokenSource().token;
if (token.isCancellationRequested) {
return;

View file

@ -2356,9 +2356,9 @@ export namespace ChatResponseProgress {
export namespace TerminalQuickFix {
export function from(quickFix: vscode.TerminalQuickFixExecuteTerminalCommand | vscode.TerminalQuickFixOpener | vscode.Command, converter: Command.ICommandsConverter, disposables: DisposableStore): extHostProtocol.ITerminalQuickFixExecuteTerminalCommandDto | extHostProtocol.ITerminalQuickFixOpenerDto | extHostProtocol.ICommandDto | undefined {
export function from(quickFix: vscode.TerminalQuickFixTerminalCommand | vscode.TerminalQuickFixOpener | vscode.Command, converter: Command.ICommandsConverter, disposables: DisposableStore): extHostProtocol.ITerminalQuickFixTerminalCommandDto | extHostProtocol.ITerminalQuickFixOpenerDto | extHostProtocol.ICommandDto | undefined {
if ('terminalCommand' in quickFix) {
return { terminalCommand: quickFix.terminalCommand };
return { terminalCommand: quickFix.terminalCommand, shouldExecute: quickFix.shouldExecute };
}
if ('uri' in quickFix) {
return { uri: quickFix.uri };

View file

@ -846,15 +846,14 @@ export interface ITerminalInstance extends IBaseTerminalInstance {
* process (shell) of the terminal instance.
*
* @param text The text to send.
* @param addNewLine Whether to add a new line to the text being sent, this is normally required
* to run a command in the terminal. The character(s) added are \n or \r\n depending on the
* platform. This defaults to `true`.
* @param shouldExecute Indicates that the text being sent should be executed rather than just inserted in the terminal.
* The character(s) added are \n or \r\n, depending on the platform. This defaults to `true`.
* @param bracketedPasteMode Whether to wrap the text in the bracketed paste mode sequence when
* it's enabled. When true, the shell will treat the text as if it were pasted into the shell,
* this may for example select the text and it will also ensure that the text will not be
* interpreted as a shell keybinding.
*/
sendText(text: string, addNewLine: boolean, bracketedPasteMode?: boolean): Promise<void>;
sendText(text: string, shouldExecute: boolean, bracketedPasteMode?: boolean): Promise<void>;
/**
* Sends a path to the terminal instance, preparing it as needed based on the detected shell
@ -862,13 +861,12 @@ export interface ITerminalInstance extends IBaseTerminalInstance {
* (shell) of the terminal instance.
*
* @param originalPath The path to send.
* @param addNewLine Whether to add a new line to the path being sent, this is normally required
* to run a command in the terminal. The character(s) added are \n or \r\n depending on the
* platform. This defaults to `true`.
* @param shouldExecute Indicates that the text being sent should be executed rather than just inserted in the terminal.
* The character(s) added are \n or \r\n, depending on the platform. This defaults to `true`.
*/
sendPath(originalPath: string | URI, addNewLine: boolean): Promise<void>;
sendPath(originalPath: string | URI, shouldExecute: boolean): Promise<void>;
runCommand(command: string, addNewLine?: boolean): void;
runCommand(command: string, shouldExecute?: boolean): void;
/**
* Takes a path and returns the properly escaped path to send to a given shell. On Windows, this

View file

@ -819,7 +819,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
xterm.raw.loadAddon(this._lineDataEventAddon!);
}
async runCommand(commandLine: string, addNewLine: boolean): Promise<void> {
async runCommand(commandLine: string, shouldExecute: boolean): Promise<void> {
// Determine whether to send ETX (ctrl+c) before running the command. This should always
// happen unless command detection can reliably say that a command is being entered and
// there is no content in the prompt
@ -830,7 +830,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
await timeout(100);
}
// Use bracketed paste mode only when not running the command
await this.sendText(commandLine, addNewLine, !addNewLine);
await this.sendText(commandLine, shouldExecute, !shouldExecute);
}
async runRecent(type: 'command' | 'cwd', filterMode?: 'fuzzy' | 'contiguous', value?: string): Promise<void> {
@ -1249,7 +1249,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
this.xterm.raw.paste(currentText);
}
async sendText(text: string, addNewLine: boolean, bracketedPasteMode?: boolean): Promise<void> {
async sendText(text: string, shouldExecute: boolean, bracketedPasteMode?: boolean): Promise<void> {
// Apply bracketed paste sequences if the terminal has the mode enabled, this will prevent
// the text from triggering keybindings and ensure new lines are handled properly
if (bracketedPasteMode && this.xterm?.raw.modes.bracketedPasteMode) {
@ -1258,7 +1258,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
// Normalize line endings to 'enter' press.
text = text.replace(/\r?\n/g, '\r');
if (addNewLine && !text.endsWith('\r')) {
if (shouldExecute && !text.endsWith('\r')) {
text += '\r';
}
@ -1270,8 +1270,8 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
this._onDidRunText.fire();
}
async sendPath(originalPath: string | URI, addNewLine: boolean): Promise<void> {
return this.sendText(await this.preparePathForShell(originalPath), addNewLine);
async sendPath(originalPath: string | URI, shouldExecute: boolean): Promise<void> {
return this.sendText(await this.preparePathForShell(originalPath), shouldExecute);
}
async preparePathForShell(originalPath: string | URI): Promise<string> {

View file

@ -29,7 +29,7 @@ export interface ITerminalQuickFixProviderSelector {
provider: ITerminalQuickFixProvider;
}
export type TerminalQuickFixActionInternal = IAction | ITerminalQuickFixExecuteTerminalCommandAction | ITerminalQuickFixOpenerAction;
export type TerminalQuickFixActionInternal = IAction | ITerminalQuickFixTerminalCommandAction | ITerminalQuickFixOpenerAction;
export type TerminalQuickFixCallback = (matchResult: ITerminalCommandMatchResult) => TerminalQuickFixActionInternal[] | TerminalQuickFixActionInternal | undefined;
export type TerminalQuickFixCallbackExtension = (terminalCommand: ITerminalCommand, lines: string[] | undefined, option: ITerminalQuickFixOptions, token: CancellationToken) => Promise<ITerminalQuickFix[] | ITerminalQuickFix | undefined>;
@ -65,11 +65,11 @@ export interface ITerminalQuickFix {
source: string;
}
export interface ITerminalQuickFixExecuteTerminalCommandAction extends ITerminalQuickFix {
export interface ITerminalQuickFixTerminalCommandAction extends ITerminalQuickFix {
type: TerminalQuickFixType.TerminalCommand;
terminalCommand: string;
// TODO: Should this depend on whether alt is held?
addNewLine?: boolean;
shouldExecute?: boolean;
}
export interface ITerminalQuickFixOpenerAction extends ITerminalQuickFix {
type: TerminalQuickFixType.Opener;

View file

@ -28,7 +28,7 @@ import { IAnchor } from 'vs/base/browser/ui/contextview/contextview';
import { ILabelService } from 'vs/platform/label/common/label';
import { Schemas } from 'vs/base/common/network';
import { URI } from 'vs/base/common/uri';
import { ITerminalQuickFixInternalOptions, ITerminalQuickFixResolvedExtensionOptions, ITerminalQuickFix, ITerminalQuickFixExecuteTerminalCommandAction, ITerminalQuickFixOpenerAction, ITerminalQuickFixOptions, ITerminalQuickFixProviderSelector, ITerminalQuickFixService, ITerminalQuickFixUnresolvedExtensionOptions, TerminalQuickFixType, ITerminalQuickFixCommandAction } from 'vs/workbench/contrib/terminalContrib/quickFix/browser/quickFix';
import { ITerminalQuickFixInternalOptions, ITerminalQuickFixResolvedExtensionOptions, ITerminalQuickFix, ITerminalQuickFixTerminalCommandAction, ITerminalQuickFixOpenerAction, ITerminalQuickFixOptions, ITerminalQuickFixProviderSelector, ITerminalQuickFixService, ITerminalQuickFixUnresolvedExtensionOptions, TerminalQuickFixType, ITerminalQuickFixCommandAction } from 'vs/workbench/contrib/terminalContrib/quickFix/browser/quickFix';
import { ITerminalCommandSelector } from 'vs/platform/terminal/common/terminal';
import { ActionListItemKind, IActionListItem } from 'vs/platform/actionWidget/browser/actionList';
import { CodeActionKind } from 'vs/editor/contrib/codeAction/common/types';
@ -45,7 +45,7 @@ const quickFixClasses = [
export interface ITerminalQuickFixAddon {
showMenu(): void;
onDidRequestRerunCommand: Event<{ command: string; addNewLine?: boolean }>;
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.
@ -54,7 +54,7 @@ export interface ITerminalQuickFixAddon {
}
export class TerminalQuickFixAddon extends Disposable implements ITerminalAddon, ITerminalQuickFixAddon {
private readonly _onDidRequestRerunCommand = new Emitter<{ command: string; addNewLine?: boolean }>();
private readonly _onDidRequestRerunCommand = new Emitter<{ command: string; shouldExecute?: boolean }>();
readonly onDidRequestRerunCommand = this._onDidRequestRerunCommand.event;
private _terminal: Terminal | undefined;
@ -313,6 +313,7 @@ export interface ITerminalAction extends IAction {
source: string;
uri?: URI;
command?: string;
shouldExecute?: boolean;
}
export async function getQuickFixesForCommand(
@ -323,7 +324,7 @@ export async function getQuickFixesForCommand(
commandService: ICommandService,
openerService: IOpenerService,
labelService: ILabelService,
onDidRequestRerunCommand?: Emitter<{ command: string; addNewLine?: boolean }>,
onDidRequestRerunCommand?: Emitter<{ command: string; shouldExecute?: boolean }>,
getResolvedFixes?: (selector: ITerminalQuickFixOptions, lines?: string[]) => Promise<ITerminalQuickFix | ITerminalQuickFix[] | undefined>
): Promise<ITerminalAction[] | undefined> {
// Prevent duplicates by tracking added entries
@ -368,7 +369,7 @@ export async function getQuickFixesForCommand(
if ('type' in quickFix) {
switch (quickFix.type) {
case TerminalQuickFixType.TerminalCommand: {
const fix = quickFix as ITerminalQuickFixExecuteTerminalCommandAction;
const fix = quickFix as ITerminalQuickFixTerminalCommandAction;
if (commandQuickFixSet.has(fix.terminalCommand)) {
continue;
}
@ -385,11 +386,12 @@ export async function getQuickFixesForCommand(
run: () => {
onDidRequestRerunCommand?.fire({
command: fix.terminalCommand,
addNewLine: fix.addNewLine ?? true
shouldExecute: fix.shouldExecute ?? true
});
},
tooltip: label,
command: fix.terminalCommand
command: fix.terminalCommand,
shouldExecute: fix.shouldExecute
};
break;
}

View file

@ -51,7 +51,7 @@ class TerminalQuickFixContribution extends DisposableStore implements ITerminalC
xterm.raw.loadAddon(this._addon);
// Hook up listeners
this.add(this._addon.onDidRequestRerunCommand((e) => this._instance.runCommand(e.command, e.addNewLine || false)));
this.add(this._addon.onDidRequestRerunCommand((e) => this._instance.runCommand(e.command, e.shouldExecute || false)));
// Register quick fixes
for (const actionOption of [

View file

@ -5,7 +5,7 @@
import { URI } from 'vs/base/common/uri';
import { localize } from 'vs/nls';
import { ITerminalQuickFixInternalOptions, ITerminalCommandMatchResult, ITerminalQuickFixExecuteTerminalCommandAction, TerminalQuickFixActionInternal, TerminalQuickFixType } from 'vs/workbench/contrib/terminalContrib/quickFix/browser/quickFix';
import { ITerminalQuickFixInternalOptions, ITerminalCommandMatchResult, ITerminalQuickFixTerminalCommandAction, TerminalQuickFixActionInternal, TerminalQuickFixType } from 'vs/workbench/contrib/terminalContrib/quickFix/browser/quickFix';
export const GitCommandLineRegex = /git/;
export const GitPushCommandLineRegex = /git\s+push/;
@ -50,7 +50,7 @@ export function gitSimilar(): ITerminalQuickFixInternalOptions {
id: 'Git Similar',
type: TerminalQuickFixType.TerminalCommand,
terminalCommand: matchResult.commandLine.replace(/git\s+[^\s]+/, () => `git ${fixedCommand}`),
addNewLine: true,
shouldExecute: true,
source: QuickFixSource.Builtin
});
}
@ -81,7 +81,7 @@ export function gitTwoDashes(): ITerminalQuickFixInternalOptions {
type: TerminalQuickFixType.TerminalCommand,
id: 'Git Two Dashes',
terminalCommand: matchResult.commandLine.replace(` -${problemArg}`, () => ` --${problemArg}`),
addNewLine: true,
shouldExecute: true,
source: QuickFixSource.Builtin
};
}
@ -175,7 +175,7 @@ export function gitPushSetUpstream(): ITerminalQuickFixInternalOptions {
type: TerminalQuickFixType.TerminalCommand,
id: 'Git Push Set Upstream',
terminalCommand: fixedCommand,
addNewLine: true,
shouldExecute: true,
source: QuickFixSource.Builtin
});
return actions;
@ -265,7 +265,7 @@ export function pwshGeneralError(): ITerminalQuickFixInternalOptions {
if (!suggestions) {
return;
}
const result: ITerminalQuickFixExecuteTerminalCommandAction[] = [];
const result: ITerminalQuickFixTerminalCommandAction[] = [];
for (const suggestion of suggestions) {
result.push({
id: 'Pwsh General Error',
@ -311,7 +311,7 @@ export function pwshUnixCommandNotFoundError(): ITerminalQuickFixInternalOptions
}
// Always remove the first element as it's the "Suggestion [cmd-not-found]"" line
const result: ITerminalQuickFixExecuteTerminalCommandAction[] = [];
const result: ITerminalQuickFixTerminalCommandAction[] = [];
let inSuggestions = false;
for (; i < lines.length; i++) {
const line = lines[i].trim();

View file

@ -7330,11 +7330,10 @@ declare module 'vscode' {
* (shell) of the terminal.
*
* @param text The text to send.
* @param addNewLine Whether to add a new line to the text being sent, this is normally
* required to run a command in the terminal. The character(s) added are \n or \r\n
* depending on the platform. This defaults to `true`.
* @param shouldExecute Indicates that the text being sent should be executed rather than just inserted in the terminal.
* The character(s) added are \n or \r\n, depending on the platform. This defaults to `true`.
*/
sendText(text: string, addNewLine?: boolean): void;
sendText(text: string, shouldExecute?: boolean): void;
/**
* Show the terminal panel and reveal this terminal in the UI.

View file

@ -16,7 +16,7 @@ declare module 'vscode' {
* @param token A cancellation token indicating the result is no longer needed
* @return Terminal quick fix(es) if any
*/
provideTerminalQuickFixes(commandMatchResult: TerminalCommandMatchResult, token: CancellationToken): ProviderResult<SingleOrMany<TerminalQuickFixExecuteTerminalCommand | TerminalQuickFixOpener | Command>>;
provideTerminalQuickFixes(commandMatchResult: TerminalCommandMatchResult, token: CancellationToken): ProviderResult<SingleOrMany<TerminalQuickFixTerminalCommand | TerminalQuickFixOpener | Command>>;
}
@ -31,18 +31,22 @@ declare module 'vscode' {
export namespace window {
/**
* @param provider A terminal quick fix provider
* @return A {@link Disposable} that unregisters the provider when being disposed
*/
* @param provider A terminal quick fix provider
* @return A {@link Disposable} that unregisters the provider when being disposed
*/
export function registerTerminalQuickFixProvider(id: string, provider: TerminalQuickFixProvider): Disposable;
}
export class TerminalQuickFixExecuteTerminalCommand {
export class TerminalQuickFixTerminalCommand {
/**
* The terminal command to run
* The terminal command to insert or run
*/
terminalCommand: string;
constructor(terminalCommand: string);
/**
* Whether the command should be executed or just inserted (default)
*/
shouldExecute?: boolean;
constructor(terminalCommand: string, shouldExecute?: boolean);
}
export class TerminalQuickFixOpener {
/**