mirror of
https://github.com/microsoft/vscode.git
synced 2026-08-28 22:59:22 +01:00
add action to copy output text
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ServicesAccessor } from 'vs/editor/browser/editorExtensions';
|
||||
import { localize } from 'vs/nls';
|
||||
import { MenuId, registerAction2 } from 'vs/platform/actions/common/actions';
|
||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||
import { CELL_TITLE_OUTPUT_GROUP_ID, INotebookOutputActionContext, NotebookAction } from 'vs/workbench/contrib/notebook/browser/controller/coreActions';
|
||||
import { NOTEBOOK_CELL_HAS_OUTPUTS } from 'vs/workbench/contrib/notebook/common/notebookContextKeys';
|
||||
import * as icons from 'vs/workbench/contrib/notebook/browser/notebookIcons';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
|
||||
registerAction2(class CopyCellOutputAction extends NotebookAction {
|
||||
constructor() {
|
||||
super(
|
||||
{
|
||||
id: 'CopyCellOutput',
|
||||
title: localize('notebookActions.copyOutput', "Copy Output to Clipboard"),
|
||||
menu: {
|
||||
id: MenuId.NotebookOutputToolbar,
|
||||
when: NOTEBOOK_CELL_HAS_OUTPUTS,
|
||||
group: CELL_TITLE_OUTPUT_GROUP_ID
|
||||
},
|
||||
icon: icons.copyIcon,
|
||||
});
|
||||
}
|
||||
|
||||
async runWithContext(accessor: ServicesAccessor, context: INotebookOutputActionContext): Promise<void> {
|
||||
const clipboardService = accessor.get(IClipboardService);
|
||||
const logService = accessor.get(ILogService);
|
||||
|
||||
const outputViewModel = context.outputViewModel;
|
||||
const outputTextModel = outputViewModel.model;
|
||||
const mimeType = outputViewModel.pickedMimeType?.mimeType;
|
||||
const buffer = outputTextModel.outputs.find(output => output.mime === mimeType);
|
||||
|
||||
if (!buffer || !mimeType) {
|
||||
return;
|
||||
}
|
||||
|
||||
const charLimit = 100_000;
|
||||
const decoder = new TextDecoder();
|
||||
let text = decoder.decode(buffer.data.slice(0, charLimit).buffer);
|
||||
|
||||
if (buffer.data.byteLength > charLimit) {
|
||||
text = text + '...(truncated)';
|
||||
}
|
||||
|
||||
if (mimeType.endsWith('error')) {
|
||||
text = text.replace(/\\u001b\[[0-9;]*m/gi, '').replaceAll('\\n', '\n');
|
||||
}
|
||||
|
||||
try {
|
||||
await clipboardService.writeText(text);
|
||||
|
||||
} catch (e) {
|
||||
logService.error(`Failed to copy content: ${e}`);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
@@ -9,7 +9,7 @@ import { Action2, IAction2Options, MenuId, MenuRegistry } from 'vs/platform/acti
|
||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { getNotebookEditorFromEditorPane, IActiveNotebookEditor, ICellViewModel, cellRangeToViewCells } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { getNotebookEditorFromEditorPane, IActiveNotebookEditor, ICellViewModel, cellRangeToViewCells, ICellOutputViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { INTERACTIVE_WINDOW_IS_ACTIVE_EDITOR, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_KERNEL_COUNT, NOTEBOOK_KERNEL_SOURCE_COUNT } from 'vs/workbench/contrib/notebook/common/notebookContextKeys';
|
||||
import { ICellRange, isICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
@@ -70,6 +70,10 @@ export interface INotebookCellActionContext extends INotebookActionContext {
|
||||
cell: ICellViewModel;
|
||||
}
|
||||
|
||||
export interface INotebookOutputActionContext extends INotebookCellActionContext {
|
||||
outputViewModel: ICellOutputViewModel;
|
||||
}
|
||||
|
||||
export function getContextFromActiveEditor(editorService: IEditorService): INotebookActionContext | undefined {
|
||||
const editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane);
|
||||
if (!editor || !editor.hasModel()) {
|
||||
|
||||
@@ -64,6 +64,7 @@ import 'vs/workbench/contrib/notebook/browser/controller/insertCellActions';
|
||||
import 'vs/workbench/contrib/notebook/browser/controller/executeActions';
|
||||
import 'vs/workbench/contrib/notebook/browser/controller/layoutActions';
|
||||
import 'vs/workbench/contrib/notebook/browser/controller/editActions';
|
||||
import 'vs/workbench/contrib/notebook/browser/controller/copyOutputAction';
|
||||
import 'vs/workbench/contrib/notebook/browser/controller/apiActions';
|
||||
import 'vs/workbench/contrib/notebook/browser/controller/foldingController';
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ export const openAsTextIcon = registerIcon('notebook-open-as-text', Codicon.file
|
||||
export const revertIcon = registerIcon('notebook-revert', Codicon.discard, localize('revertIcon', 'Icon to revert in notebook editors.'));
|
||||
export const renderOutputIcon = registerIcon('notebook-render-output', Codicon.preview, localize('renderOutputIcon', 'Icon to render output in diff editor.'));
|
||||
export const mimetypeIcon = registerIcon('notebook-mimetype', Codicon.code, localize('mimetypeIcon', 'Icon for a mime type in notebook editors.'));
|
||||
export const copyIcon = registerIcon('notebook-copy', Codicon.copy, localize('copyIcon', 'Icon to copy content to clipboard'));
|
||||
|
||||
export const previousChangeIcon = registerIcon('notebook-diff-editor-previous-change', Codicon.arrowUp, localize('previousChangeIcon', 'Icon for the previous change action in the diff editor.'));
|
||||
export const nextChangeIcon = registerIcon('notebook-diff-editor-next-change', Codicon.arrowDown, localize('nextChangeIcon', 'Icon for the next change action in the diff editor.'));
|
||||
|
||||
@@ -21,7 +21,7 @@ import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/commo
|
||||
import { ThemeIcon } from 'vs/base/common/themables';
|
||||
import { ViewContainerLocation } from 'vs/workbench/common/views';
|
||||
import { IExtensionsViewPaneContainer, VIEWLET_ID as EXTENSION_VIEWLET_ID } from 'vs/workbench/contrib/extensions/common/extensions';
|
||||
import { INotebookCellActionContext } from 'vs/workbench/contrib/notebook/browser/controller/coreActions';
|
||||
import { INotebookOutputActionContext } from 'vs/workbench/contrib/notebook/browser/controller/coreActions';
|
||||
import { ICellOutputViewModel, ICellViewModel, IInsetRenderOutput, INotebookEditorDelegate, JUPYTER_EXTENSION_ID, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { mimetypeIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons';
|
||||
import { CellContentPart } from 'vs/workbench/contrib/notebook/browser/view/cellPart';
|
||||
@@ -254,8 +254,8 @@ class CellOutputElement extends Disposable {
|
||||
}
|
||||
|
||||
private async _attachToolbar(outputItemDiv: HTMLElement, notebookTextModel: NotebookTextModel, kernel: INotebookKernel | undefined, index: number, mimeTypes: readonly IOrderedMimeType[]) {
|
||||
const hasMultipleMimeTypes = mimeTypes.filter(mimeType => mimeType.isTrusted).length <= 1;
|
||||
if (index > 0 && hasMultipleMimeTypes) {
|
||||
const hasMultipleMimeTypes = mimeTypes.filter(mimeType => mimeType.isTrusted).length > 1;
|
||||
if (index > 0 && !hasMultipleMimeTypes) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -273,9 +273,10 @@ class CellOutputElement extends Disposable {
|
||||
const toolbar = this._renderDisposableStore.add(this.instantiationService.createInstance(WorkbenchToolBar, mimeTypePicker, {
|
||||
renderDropdownAsChildElement: false
|
||||
}));
|
||||
toolbar.context = <INotebookCellActionContext>{
|
||||
toolbar.context = <INotebookOutputActionContext>{
|
||||
ui: true,
|
||||
cell: this.output.cellViewModel as ICellViewModel,
|
||||
outputViewModel: this.output,
|
||||
notebookEditor: this.notebookEditor,
|
||||
$mid: MarshalledId.NotebookCellActionContext
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user