Skip to content

Commit

Permalink
fix #20813
Browse files Browse the repository at this point in the history
  • Loading branch information
meganrogge committed Mar 9, 2022
1 parent 2434468 commit befa521
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 6 deletions.
4 changes: 2 additions & 2 deletions src/vs/workbench/contrib/terminal/browser/terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -647,9 +647,9 @@ export interface ITerminalInstance {
hasSelection(): boolean;

/**
* Copies the terminal selection to the clipboard.
* Copies the terminal selection to the clipboard as HTML if specified.
*/
copySelection(): Promise<void>;
copySelection(asHTML?: boolean): Promise<void>;

/**
* Current selection in the terminal.
Expand Down
14 changes: 14 additions & 0 deletions src/vs/workbench/contrib/terminal/browser/terminalActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2113,6 +2113,20 @@ export function registerTerminalActions() {
await accessor.get(ITerminalService).activeInstance?.copySelection();
}
});
registerAction2(class extends Action2 {
constructor() {
super({
id: TerminalCommandId.CopySelectionAsHtml,
title: { value: localize('workbench.action.terminal.copySelectionAsHtml', "Copy Selection as HTML"), original: 'Copy Selection as HTML' },
f1: true,
category,
precondition: ContextKeyExpr.and(ContextKeyExpr.or(TerminalContextKeys.processSupported, TerminalContextKeys.terminalHasBeenCreated), TerminalContextKeys.textSelected)
});
}
async run(accessor: ServicesAccessor) {
await accessor.get(ITerminalService).activeInstance?.copySelection(true);
}
});
}

if (BrowserFeatures.clipboard.readText) {
Expand Down
4 changes: 2 additions & 2 deletions src/vs/workbench/contrib/terminal/browser/terminalInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1126,10 +1126,10 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
return this.xterm ? this.xterm.raw.hasSelection() : false;
}

async copySelection(): Promise<void> {
async copySelection(asHTML?: boolean): Promise<void> {
const xterm = await this._xtermReadyPromise;
if (this.hasSelection()) {
await this._clipboardService.writeText(xterm.raw.getSelection());
asHTML ? xterm.copyAsHtml() : await this._clipboardService.writeText(xterm.raw.getSelection());
} else {
this._notificationService.warn(nls.localize('terminal.integrated.copySelection.noSelection', 'The terminal has no selection to copy'));
}
Expand Down
26 changes: 24 additions & 2 deletions src/vs/workbench/contrib/terminal/browser/terminalMenus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,17 @@ export function setupTerminalMenus(): void {
order: 1
}
},
{
id: MenuId.TerminalInstanceContext,
item: {
command: {
id: TerminalCommandId.CopySelectionAsHtml,
title: localize('workbench.action.terminal.copySelectionAsHtml', "Copy as HTML")
},
group: ContextMenuGroup.Edit,
order: 2
}
},
{
id: MenuId.TerminalInstanceContext,
item: {
Expand All @@ -145,7 +156,7 @@ export function setupTerminalMenus(): void {
title: localize('workbench.action.terminal.paste.short', "Paste")
},
group: ContextMenuGroup.Edit,
order: 2
order: 3
}
},
{
Expand Down Expand Up @@ -237,6 +248,17 @@ export function setupTerminalMenus(): void {
order: 1
}
},
{
id: MenuId.TerminalEditorInstanceContext,
item: {
command: {
id: TerminalCommandId.CopySelectionAsHtml,
title: localize('workbench.action.terminal.copySelectionAsHtml', "Copy as HTML")
},
group: ContextMenuGroup.Edit,
order: 2
}
},
{
id: MenuId.TerminalEditorInstanceContext,
item: {
Expand All @@ -245,7 +267,7 @@ export function setupTerminalMenus(): void {
title: localize('workbench.action.terminal.paste.short', "Paste")
},
group: ContextMenuGroup.Edit,
order: 2
order: 3
}
},
{
Expand Down
17 changes: 17 additions & 0 deletions src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { DecorationAddon } from 'vs/workbench/contrib/terminal/browser/xterm/decorationAddon';
import { ITerminalCapabilityStore } from 'vs/workbench/contrib/terminal/common/capabilities/capabilities';
import { Emitter } from 'vs/base/common/event';
import { SerializeAddon } from 'xterm-addon-serialize';

// How long in milliseconds should an average frame take to render for a notification to appear
// which suggests the fallback DOM-based renderer
Expand Down Expand Up @@ -64,6 +65,7 @@ export class XtermTerminal extends DisposableStore implements IXtermTerminal {
private _searchAddon?: SearchAddonType;
private _unicode11Addon?: Unicode11AddonType;
private _webglAddon?: WebglAddonType;
private _serializeAddon?: SerializeAddon;

private readonly _onDidRequestRunCommand = new Emitter<string>();
readonly onDidRequestRunCommand = this._onDidRequestRunCommand.event;
Expand Down Expand Up @@ -167,6 +169,21 @@ export class XtermTerminal extends DisposableStore implements IXtermTerminal {
this.raw.loadAddon(this._decorationAddon);
}

copyAsHtml(): void {
if (!this._serializeAddon) {
this._serializeAddon = this._instantiationService.createInstance(SerializeAddon);
this.raw.loadAddon(this._serializeAddon);
}
const selectionAsHtml = this._serializeAddon.serializeAsHTML({ onlySelection: true });
function listener(e: any) {
e.clipboardData.setData('text/html', selectionAsHtml);
e.preventDefault();
}
document.addEventListener('copy', listener);
document.execCommand('copy');
document.removeEventListener('copy', listener);
}

attachToElement(container: HTMLElement): HTMLElement {
// Update the theme when attaching as the terminal location could have changed
this._updateTheme();
Expand Down
2 changes: 2 additions & 0 deletions src/vs/workbench/contrib/terminal/common/terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ export const enum TerminalCommandId {
RunRecentCommand = 'workbench.action.terminal.runRecentCommand',
GoToRecentDirectory = 'workbench.action.terminal.goToRecentDirectory',
CopySelection = 'workbench.action.terminal.copySelection',
CopySelectionAsHtml = 'workbench.action.terminal.copySelectionAsHtml',
SelectAll = 'workbench.action.terminal.selectAll',
DeleteWordLeft = 'workbench.action.terminal.deleteWordLeft',
DeleteWordRight = 'workbench.action.terminal.deleteWordRight',
Expand Down Expand Up @@ -566,6 +567,7 @@ export const DEFAULT_COMMANDS_TO_SKIP_SHELL: string[] = [
TerminalCommandId.ClearSelection,
TerminalCommandId.Clear,
TerminalCommandId.CopySelection,
TerminalCommandId.CopySelectionAsHtml,
TerminalCommandId.DeleteToLineStart,
TerminalCommandId.DeleteWordLeft,
TerminalCommandId.DeleteWordRight,
Expand Down

0 comments on commit befa521

Please sign in to comment.