Skip to content
Merged
1 change: 1 addition & 0 deletions src/vs/workbench/contrib/terminal/common/terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,7 @@ export const enum TerminalCommandId {
OpenWebLink = 'workbench.action.terminal.openUrlLink',
RunRecentCommand = 'workbench.action.terminal.runRecentCommand',
FocusAccessibleBuffer = 'workbench.action.terminal.focusAccessibleBuffer',
GoToCommand = 'workbench.action.terminal.goToCommand',
CopyLastCommandOutput = 'workbench.action.terminal.copyLastCommandOutput',
GoToRecentDirectory = 'workbench.action.terminal.goToRecentDirectory',
CopyAndClearSelection = 'workbench.action.terminal.copyAndClearSelection',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,16 @@ class AccessibleBufferContribution extends DisposableStore implements ITerminalC
}
layout(xterm: IXtermTerminal & { raw: Terminal }): void {
if (!this._accessibleBufferWidget) {
this._accessibleBufferWidget = this._instantiationService.createInstance(AccessibleBufferWidget, this._instance.instanceId, xterm);
this._accessibleBufferWidget = this._instantiationService.createInstance(AccessibleBufferWidget, this._instance.instanceId, xterm, this._instance.capabilities);
}
}
show(): void {
this._accessibleBufferWidget?.show();
}

showCommandQuickPick(): void {
this._accessibleBufferWidget?.showCommandQuickPick();
}
}
registerTerminalContribution(AccessibleBufferContribution.ID, AccessibleBufferContribution);

Expand Down Expand Up @@ -119,6 +123,37 @@ registerAction2(class extends Action2 {
}
});

registerAction2(class extends Action2 {
constructor() {
super({
id: TerminalCommandId.GoToCommand,
title: { value: localize('workbench.action.terminal.goToCommand', 'Go to Command'), original: 'Go to Command' },
f1: true,
category,
precondition: ContextKeyExpr.or(TerminalContextKeys.processSupported, TerminalContextKeys.terminalHasBeenCreated),
keybinding: [
{
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyO,
weight: KeybindingWeight.WorkbenchContrib + 2,
when: ContextKeyExpr.and(CONTEXT_ACCESSIBILITY_MODE_ENABLED, terminalTabFocusContextKey)
}
],
});
}
async run(accessor: ServicesAccessor): Promise<void> {
const terminalService = accessor.get(ITerminalService);
const terminalGroupService = accessor.get(ITerminalGroupService);
const terminalEditorService = accessor.get(ITerminalEditorService);

const instance = await terminalService.getActiveOrCreateInstance();
await revealActiveTerminal(instance, terminalEditorService, terminalGroupService);
if (!instance) {
return;
}
AccessibleBufferContribution.get(instance)?.showCommandQuickPick();
}
});

async function revealActiveTerminal(instance: ITerminalInstance, terminalEditorService: ITerminalEditorService, terminalGroupService: ITerminalGroupService): Promise<void> {
if (instance.target === TerminalLocation.Editor) {
await terminalEditorService.revealActiveEditor();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import { getSimpleEditorOptions } from 'vs/workbench/contrib/codeEditor/browser/
import { ITerminalFont } from 'vs/workbench/contrib/terminal/common/terminal';
import { IXtermTerminal } from 'vs/workbench/contrib/terminal/browser/terminal';
import type { Terminal } from 'xterm';
import { ITerminalCapabilityStore, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities';
import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
import { AudioCue, IAudioCueService } from 'vs/platform/audioCues/browser/audioCueService';

const enum Constants {
Scheme = 'terminal-accessible-buffer',
Expand All @@ -34,14 +37,18 @@ export class AccessibleBufferWidget extends DisposableStore {
private _bufferEditor: CodeEditorWidget;
private _editorContainer: HTMLElement;
private _font: ITerminalFont;
private _inQuickPick = false;
private _xtermElement: HTMLElement;

constructor(
private readonly _instanceId: number,
private readonly _xterm: IXtermTerminal & { raw: Terminal },
private readonly _capabilities: ITerminalCapabilityStore,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@IModelService private readonly _modelService: IModelService,
@IConfigurationService private readonly _configurationService: IConfigurationService
@IConfigurationService private readonly _configurationService: IConfigurationService,
@IQuickInputService private readonly _quickInputService: IQuickInputService,
@IAudioCueService private readonly _audioCueService: IAudioCueService
) {
super();
const codeEditorWidgetOptions: ICodeEditorWidgetOptions = {
Expand Down Expand Up @@ -101,6 +108,9 @@ export class AccessibleBufferWidget extends DisposableStore {
}));
this._updateEditor();
this.add(this._bufferEditor.onDidFocusEditorText(async () => {
if (this._inQuickPick) {
return;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this needed? I wouldn't expect the editor to get focused when the quick pick is up, and if it was, wouldn't it hide?

// if the editor is focused via tab, we need to update the model
// and show it
await this._updateEditor();
Expand Down Expand Up @@ -145,6 +155,48 @@ export class AccessibleBufferWidget extends DisposableStore {
this._bufferEditor.setScrollTop(this._bufferEditor.getScrollHeight());
}

showCommandQuickPick(): void {
const commands = this._capabilities.get(TerminalCapability.CommandDetection)?.commands;
const quickPick = this._quickInputService.createQuickPick<IQuickPickItem>();
const quickPickItems: IQuickPickItem[] = [];
if (!commands?.length) {
return;
}
for (const command of commands) {
const line = command.marker?.line;
if (!line) {
continue;
}
quickPickItems.push(
{
label: localize('terminal.integrated.symbolQuickPick.labelNoExitCode', '{0}', command.command),
meta: JSON.stringify({ line: line + 1, exitCode: command.exitCode })
});
}
quickPick.onDidAccept(() => {
this._inQuickPick = true;
const item = quickPick.activeItems[0];
const model = this._bufferEditor.getModel();
if (!model || !item.meta) {
return;
}
quickPick.hide();
const data: { line: number; exitCode: number } = JSON.parse(item.meta);
this._bufferEditor.setSelection({ startLineNumber: data.line, startColumn: 1, endLineNumber: data.line, endColumn: 1 });
this._bufferEditor.revealLine(data.line);
this._bufferEditor.focus();
this._inQuickPick = false;
return;
});
quickPick.onDidChangeActive(() => {
if (JSON.parse(quickPick.activeItems[0].meta!).exitCode) {
this._audioCueService.playAudioCue(AudioCue.error, true);
}
});
quickPick.items = quickPickItems;
quickPick.show();
}

async show(): Promise<void> {
await this._updateEditor();
this._accessibleBuffer.tabIndex = -1;
Expand All @@ -159,7 +211,6 @@ export class AccessibleBufferWidget extends DisposableStore {
if (existing && !existing.isDisposed()) {
return existing;
}

return this._modelService.createModel(resource.fragment, null, resource, false);
}

Expand Down