Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make terminal output readonly #141601

Merged
merged 6 commits into from
Jan 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,11 @@ export class CommandDetectionCapability implements ICommandDetectionCapability {
}

function getOutputForCommand(command: ICurrentPartialCommand, buffer: IBuffer): string | undefined {
const startLine = command.commandStartMarker!.line;
const startLine = command.commandExecutedMarker!.line;
const endLine = command.commandFinishedMarker!.line;

let output = '';
for (let i = startLine; i <= endLine; i++) {
for (let i = startLine; i < endLine; i++) {
output += buffer.getLine(i)?.translateToString() + '\n';
Comment on lines +164 to 169
Copy link
Member

Choose a reason for hiding this comment

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

Makes sense, I was a bit unsure if whether we want the command included or not. To be extra safe we could check getLine as well and skip that line if it's undefined.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If endline is included, it includes the prompt of the next command in the current command's output

}
return output === '' ? undefined : output;
Expand Down
46 changes: 38 additions & 8 deletions src/vs/workbench/contrib/terminal/browser/terminalInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,11 @@ import { IWorkspaceTrustRequestService } from 'vs/platform/workspace/common/work
import { isFirefox } from 'vs/base/browser/browser';
import { TerminalLinkQuickpick } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkQuickpick';
import { fromNow } from 'vs/base/common/date';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { TerminalCapabilityStoreMultiplexer } from 'vs/workbench/contrib/terminal/common/capabilities/terminalCapabilityStore';
import { TerminalCapability } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities';
import { ITextModel } from 'vs/editor/common/model';
import { IModelService } from 'vs/editor/common/services/model';
import { ITextModelContentProvider, ITextModelService } from 'vs/editor/common/services/resolverService';

const enum Constants {
/**
Expand Down Expand Up @@ -113,6 +115,24 @@ interface IGridDimensions {

const scrollbarHeight = 5;

class TerminalOutputProvider implements ITextModelContentProvider {
static scheme = 'TERMINAL_OUTPUT';
constructor(
@ITextModelService textModelResolverService: ITextModelService,
@IModelService private readonly _modelService: IModelService
) {
textModelResolverService.registerTextModelContentProvider(TerminalOutputProvider.scheme, this);
}
async provideTextContent(resource: URI): Promise<ITextModel | null> {
const existing = this._modelService.getModel(resource);
if (existing && !existing.isDisposed()) {
return existing;
}

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

export class TerminalInstance extends Disposable implements ITerminalInstance {
private static _lastKnownCanvasDimensions: ICanvasDimensions | undefined;
private static _lastKnownGridDimensions: IGridDimensions | undefined;
Expand Down Expand Up @@ -330,8 +350,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
@IWorkbenchEnvironmentService workbenchEnvironmentService: IWorkbenchEnvironmentService,
@IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService,
@IEditorService private readonly _editorService: IEditorService,
@IWorkspaceTrustRequestService private readonly _workspaceTrustRequestService: IWorkspaceTrustRequestService,
@ICommandService private readonly _commandService: ICommandService
@IWorkspaceTrustRequestService private readonly _workspaceTrustRequestService: IWorkspaceTrustRequestService
) {
super();

Expand Down Expand Up @@ -764,13 +783,24 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
items.push({ label });
}
}
const outputProvider = this._instantiationService.createInstance(TerminalOutputProvider);
const result = await this._quickInputService.pick(items.reverse(), {
onDidTriggerItemButton: (async e => {
const output = e.item.command?.getOutput();
if (output) {
await this._clipboardService.writeText(output);
await this._commandService.executeCommand('workbench.action.files.newUntitledFile');
await this._commandService.executeCommand('editor.action.clipboardPasteAction');
const selectedCommand = e.item.command;
const output = selectedCommand?.getOutput();
if (output && selectedCommand?.command) {
const textContent = await outputProvider.provideTextContent(URI.from(
{
scheme: TerminalOutputProvider.scheme,
path: `${selectedCommand.command}... ${fromNow(selectedCommand.timestamp, true)}`,
fragment: output,
query: `terminal-output-${selectedCommand.timestamp}-${this.instanceId}`
}));
if (textContent) {
this._editorService.openEditor({
resource: textContent.uri
});
}
}
})
});
Expand Down