mirror of https://github.com/coder/code-server.git
Terminal pasting
This commit is contained in:
parent
bef46391fa
commit
6c4e2f9251
|
@ -2,7 +2,7 @@ import { Event } from "@coder/events";
|
||||||
import { field, logger, time, Time } from "@coder/logger";
|
import { field, logger, time, Time } from "@coder/logger";
|
||||||
import { InitData, ISharedProcessData } from "@coder/protocol";
|
import { InitData, ISharedProcessData } from "@coder/protocol";
|
||||||
import { retry } from "./retry";
|
import { retry } from "./retry";
|
||||||
import { Upload } from "./upload";
|
import { upload } from "./upload";
|
||||||
import { client } from "./fill/client";
|
import { client } from "./fill/client";
|
||||||
import { clipboard } from "./fill/clipboard";
|
import { clipboard } from "./fill/clipboard";
|
||||||
import { INotificationService, NotificationService, IProgressService, ProgressService } from "./fill/notification";
|
import { INotificationService, NotificationService, IProgressService, ProgressService } from "./fill/notification";
|
||||||
|
@ -21,7 +21,8 @@ export abstract class Client {
|
||||||
public readonly retry = retry;
|
public readonly retry = retry;
|
||||||
public readonly clipboard = clipboard;
|
public readonly clipboard = clipboard;
|
||||||
public readonly uriFactory: IURIFactory;
|
public readonly uriFactory: IURIFactory;
|
||||||
public readonly upload = new Upload(new NotificationService(), new ProgressService());
|
public readonly upload = upload;
|
||||||
|
|
||||||
private start: Time | undefined;
|
private start: Time | undefined;
|
||||||
private readonly progressElement: HTMLElement | undefined;
|
private readonly progressElement: HTMLElement | undefined;
|
||||||
private tasks: string[] = [];
|
private tasks: string[] = [];
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
export * from "./client";
|
export * from "./client";
|
||||||
export * from "./fill/uri";
|
export * from "./fill/clipboard";
|
||||||
export * from "./fill/notification";
|
export * from "./fill/notification";
|
||||||
|
export * from "./fill/uri";
|
||||||
|
export * from "./retry";
|
||||||
|
export * from "./upload";
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { promisify } from "util";
|
||||||
import { logger, Logger } from "@coder/logger";
|
import { logger, Logger } from "@coder/logger";
|
||||||
import { escapePath } from "@coder/protocol";
|
import { escapePath } from "@coder/protocol";
|
||||||
import { IURI } from "./fill/uri";
|
import { IURI } from "./fill/uri";
|
||||||
import { INotificationService, IProgressService, IProgress, Severity } from "./fill/notification";
|
import { NotificationService, INotificationService, ProgressService, IProgressService, IProgress, Severity } from "./fill/notification";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an uploadable directory, so we can query for existing files once.
|
* Represents an uploadable directory, so we can query for existing files once.
|
||||||
|
@ -355,3 +355,6 @@ export class Upload {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Global instance.
|
||||||
|
export const upload = new Upload(new NotificationService(), new ProgressService());
|
||||||
|
|
|
@ -4,6 +4,7 @@ import "./fill/storageDatabase";
|
||||||
import "./fill/windowsService";
|
import "./fill/windowsService";
|
||||||
import "./fill/environmentService";
|
import "./fill/environmentService";
|
||||||
import "./fill/vscodeTextmate";
|
import "./fill/vscodeTextmate";
|
||||||
|
import { PasteAction } from "./fill/paste";
|
||||||
import "./fill/dom";
|
import "./fill/dom";
|
||||||
import "./vscode.scss";
|
import "./vscode.scss";
|
||||||
import { Client as IDEClient, IURI, IURIFactory, IProgress, INotificationHandle } from "@coder/ide";
|
import { Client as IDEClient, IURI, IURIFactory, IProgress, INotificationHandle } from "@coder/ide";
|
||||||
|
@ -19,8 +20,6 @@ import { IEditorGroup } from "vs/workbench/services/group/common/editorGroupsSer
|
||||||
import { IWindowsService } from "vs/platform/windows/common/windows";
|
import { IWindowsService } from "vs/platform/windows/common/windows";
|
||||||
import { ServiceCollection } from "vs/platform/instantiation/common/serviceCollection";
|
import { ServiceCollection } from "vs/platform/instantiation/common/serviceCollection";
|
||||||
import { RawContextKey, IContextKeyService } from "vs/platform/contextkey/common/contextkey";
|
import { RawContextKey, IContextKeyService } from "vs/platform/contextkey/common/contextkey";
|
||||||
import { Action } from "vs/base/common/actions";
|
|
||||||
import * as nls from "vs/nls";
|
|
||||||
|
|
||||||
export class Client extends IDEClient {
|
export class Client extends IDEClient {
|
||||||
|
|
||||||
|
@ -78,27 +77,8 @@ export class Client extends IDEClient {
|
||||||
/**
|
/**
|
||||||
* Create a paste action for use in text inputs.
|
* Create a paste action for use in text inputs.
|
||||||
*/
|
*/
|
||||||
public get pasteAction(): Action {
|
public get pasteAction(): PasteAction {
|
||||||
const getLabel = (enabled: boolean): string => {
|
return new PasteAction();
|
||||||
return enabled
|
|
||||||
? nls.localize("paste", "Paste")
|
|
||||||
: nls.localize("pasteWithKeybind", "Paste (must use keybind)");
|
|
||||||
};
|
|
||||||
|
|
||||||
const pasteAction = new Action(
|
|
||||||
"editor.action.clipboardPasteAction",
|
|
||||||
getLabel(this.clipboard.isEnabled),
|
|
||||||
undefined,
|
|
||||||
this.clipboard.isEnabled,
|
|
||||||
async (): Promise<boolean> => this.clipboard.paste(),
|
|
||||||
);
|
|
||||||
|
|
||||||
this.clipboard.onPermissionChange((enabled) => {
|
|
||||||
pasteAction.label = getLabel(enabled);
|
|
||||||
pasteAction.enabled = enabled;
|
|
||||||
});
|
|
||||||
|
|
||||||
return pasteAction;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public get serviceCollection(): ServiceCollection {
|
public get serviceCollection(): ServiceCollection {
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
import * as nls from "vs/nls";
|
||||||
|
import { Action } from "vs/base/common/actions";
|
||||||
|
import { TERMINAL_COMMAND_ID } from "vs/workbench/parts/terminal/common/terminalCommands";
|
||||||
|
import { ITerminalService } from "vs/workbench/parts/terminal/common/terminal";
|
||||||
|
import * as actions from "vs/workbench/parts/terminal/electron-browser/terminalActions";
|
||||||
|
import * as instance from "vs/workbench/parts/terminal/electron-browser/terminalInstance";
|
||||||
|
import { clipboard } from "@coder/ide";
|
||||||
|
|
||||||
|
const getLabel = (key: string, enabled: boolean): string => {
|
||||||
|
return enabled
|
||||||
|
? nls.localize(key, "Paste")
|
||||||
|
: nls.localize(`${key}WithKeybind`, "Paste (must use keybind)");
|
||||||
|
};
|
||||||
|
|
||||||
|
export class PasteAction extends Action {
|
||||||
|
|
||||||
|
private static readonly KEY = "paste";
|
||||||
|
|
||||||
|
public constructor() {
|
||||||
|
super(
|
||||||
|
"editor.action.clipboardPasteAction",
|
||||||
|
getLabel(PasteAction.KEY, clipboard.isEnabled),
|
||||||
|
undefined,
|
||||||
|
clipboard.isEnabled,
|
||||||
|
async (): Promise<boolean> => clipboard.paste(),
|
||||||
|
);
|
||||||
|
|
||||||
|
clipboard.onPermissionChange((enabled) => {
|
||||||
|
this.label = getLabel(PasteAction.KEY, enabled);
|
||||||
|
this.enabled = enabled;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class TerminalPasteAction extends Action {
|
||||||
|
|
||||||
|
private static readonly KEY = "workbench.action.terminal.paste";
|
||||||
|
|
||||||
|
public static readonly ID = TERMINAL_COMMAND_ID.PASTE;
|
||||||
|
public static readonly LABEL = nls.localize("workbench.action.terminal.paste", "Paste into Active Terminal");
|
||||||
|
public static readonly SHORT_LABEL = getLabel(TerminalPasteAction.KEY, clipboard.isEnabled);
|
||||||
|
|
||||||
|
public constructor(
|
||||||
|
id: string, label: string,
|
||||||
|
@ITerminalService private terminalService: ITerminalService,
|
||||||
|
) {
|
||||||
|
super(id, label);
|
||||||
|
clipboard.onPermissionChange((enabled) => {
|
||||||
|
this._setLabel(getLabel(TerminalPasteAction.KEY, enabled));
|
||||||
|
});
|
||||||
|
this._setLabel(getLabel(TerminalPasteAction.KEY, clipboard.isEnabled));
|
||||||
|
}
|
||||||
|
|
||||||
|
public run(): Promise<void> {
|
||||||
|
const instance = this.terminalService.getActiveOrCreateInstance();
|
||||||
|
if (instance) {
|
||||||
|
// tslint:disable-next-line no-any it will return a promise (see below)
|
||||||
|
return (instance as any).paste();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class TerminalInstance extends instance.TerminalInstance {
|
||||||
|
|
||||||
|
public async paste(): Promise<void> {
|
||||||
|
this.focus();
|
||||||
|
if (clipboard.isEnabled) {
|
||||||
|
const text = await clipboard.readText();
|
||||||
|
this.sendText(text, false);
|
||||||
|
} else {
|
||||||
|
document.execCommand("paste");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const actionsTarget = actions as typeof actions;
|
||||||
|
// @ts-ignore TODO: don't ignore it.
|
||||||
|
actionsTarget.TerminalPasteAction = TerminalPasteAction;
|
||||||
|
|
||||||
|
const instanceTarget = instance as typeof instance;
|
||||||
|
instanceTarget.TerminalInstance = TerminalInstance;
|
|
@ -229,6 +229,31 @@ index e600fb2f78..5d65a3124e 100644
|
||||||
const droppedResources = extractResources(originalEvent.browserEvent as DragEvent, true);
|
const droppedResources = extractResources(originalEvent.browserEvent as DragEvent, true);
|
||||||
|
|
||||||
// Check for dropped external files to be folders
|
// Check for dropped external files to be folders
|
||||||
|
diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts b/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts
|
||||||
|
index 2975294e75..73ffb6362d 100644
|
||||||
|
--- a/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts
|
||||||
|
+++ b/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts
|
||||||
|
@@ -38,6 +38,7 @@ import { TerminalPanel } from 'vs/workbench/parts/terminal/electron-browser/term
|
||||||
|
import { TerminalPickerHandler } from 'vs/workbench/parts/terminal/browser/terminalQuickOpen';
|
||||||
|
import { setupTerminalCommands, TERMINAL_COMMAND_ID } from 'vs/workbench/parts/terminal/common/terminalCommands';
|
||||||
|
import { setupTerminalMenu } from 'vs/workbench/parts/terminal/common/terminalMenu';
|
||||||
|
+import { client } from "../../../../../../../../packages/vscode";
|
||||||
|
|
||||||
|
const quickOpenRegistry = (Registry.as<IQuickOpenRegistry>(QuickOpenExtensions.Quickopen));
|
||||||
|
|
||||||
|
@@ -434,9 +435,11 @@ actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusPreviousTer
|
||||||
|
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(TerminalPasteAction, TerminalPasteAction.ID, TerminalPasteAction.LABEL, {
|
||||||
|
primary: KeyMod.CtrlCmd | KeyCode.KEY_V,
|
||||||
|
linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_V },
|
||||||
|
+ win: { primary: KeyMod.CtrlCmd | KeyCode.KEY_V },
|
||||||
|
// Don't apply to Mac since cmd+v works
|
||||||
|
mac: { primary: 0 }
|
||||||
|
-}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Paste into Active Terminal', category);
|
||||||
|
+// }, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Paste into Active Terminal', category);
|
||||||
|
+}, ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_FOCUS, client.clipboardContextKey)), 'Terminal: Paste into Active Terminal', category);
|
||||||
|
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(SelectAllTerminalAction, SelectAllTerminalAction.ID, SelectAllTerminalAction.LABEL, {
|
||||||
|
// Don't use ctrl+a by default as that would override the common go to start
|
||||||
|
// of prompt shell binding
|
||||||
diff --git a/src/vs/workbench/parts/welcome/walkThrough/node/walkThroughContentProvider.ts b/src/vs/workbench/parts/welcome/walkThrough/node/walkThroughContentProvider.ts
|
diff --git a/src/vs/workbench/parts/welcome/walkThrough/node/walkThroughContentProvider.ts b/src/vs/workbench/parts/welcome/walkThrough/node/walkThroughContentProvider.ts
|
||||||
index 7b4e8721ac..8f26dc2f28 100644
|
index 7b4e8721ac..8f26dc2f28 100644
|
||||||
--- a/src/vs/workbench/parts/welcome/walkThrough/node/walkThroughContentProvider.ts
|
--- a/src/vs/workbench/parts/welcome/walkThrough/node/walkThroughContentProvider.ts
|
||||||
|
|
Loading…
Reference in New Issue