mirror of
https://github.com/coder/code-server.git
synced 2026-05-06 12:31:58 +02:00
210 lines
8.0 KiB
TypeScript
210 lines
8.0 KiB
TypeScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
import { URI, UriComponents } from 'vs/base/common/uri';
|
|
import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
|
import { CommandsRegistry, ICommandService, ICommandHandler } from 'vs/platform/commands/common/commands';
|
|
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
|
import { IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows';
|
|
import { IWorkspacesService, IRecent } from 'vs/platform/workspaces/common/workspaces';
|
|
import { ILogService } from 'vs/platform/log/common/log';
|
|
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
|
import { IViewDescriptorService, IViewsService, ViewVisibilityState } from 'vs/workbench/common/views';
|
|
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
|
|
|
// -----------------------------------------------------------------
|
|
// The following commands are registered on both sides separately.
|
|
//
|
|
// We are trying to maintain backwards compatibility for cases where
|
|
// API commands are encoded as markdown links, for example.
|
|
// -----------------------------------------------------------------
|
|
|
|
export interface ICommandsExecutor {
|
|
executeCommand<T>(id: string, ...args: any[]): Promise<T | undefined>;
|
|
}
|
|
|
|
function adjustHandler(handler: (executor: ICommandsExecutor, ...args: any[]) => any): ICommandHandler {
|
|
return (accessor, ...args: any[]) => {
|
|
return handler(accessor.get(ICommandService), ...args);
|
|
};
|
|
}
|
|
|
|
interface INewWindowAPICommandOptions {
|
|
reuseWindow?: boolean;
|
|
remoteAuthority?: string;
|
|
}
|
|
|
|
export class NewWindowAPICommand {
|
|
public static readonly ID = 'vscode.newWindow';
|
|
public static execute(executor: ICommandsExecutor, options?: INewWindowAPICommandOptions): Promise<any> {
|
|
const commandOptions: IOpenEmptyWindowOptions = {
|
|
forceReuseWindow: options && options.reuseWindow,
|
|
remoteAuthority: options && options.remoteAuthority
|
|
};
|
|
|
|
return executor.executeCommand('_files.newWindow', commandOptions);
|
|
}
|
|
}
|
|
CommandsRegistry.registerCommand({
|
|
id: NewWindowAPICommand.ID,
|
|
handler: adjustHandler(NewWindowAPICommand.execute),
|
|
description: {
|
|
description: 'Opens an new window',
|
|
args: [
|
|
]
|
|
}
|
|
});
|
|
|
|
CommandsRegistry.registerCommand('_workbench.removeFromRecentlyOpened', function (accessor: ServicesAccessor, uri: URI) {
|
|
const workspacesService = accessor.get(IWorkspacesService);
|
|
return workspacesService.removeRecentlyOpened([uri]);
|
|
});
|
|
|
|
export class RemoveFromRecentlyOpenedAPICommand {
|
|
public static readonly ID = 'vscode.removeFromRecentlyOpened';
|
|
public static execute(executor: ICommandsExecutor, path: string | URI): Promise<any> {
|
|
if (typeof path === 'string') {
|
|
path = path.match(/^[^:/?#]+:\/\//) ? URI.parse(path) : URI.file(path);
|
|
} else {
|
|
path = URI.revive(path); // called from extension host
|
|
}
|
|
return executor.executeCommand('_workbench.removeFromRecentlyOpened', path);
|
|
}
|
|
}
|
|
CommandsRegistry.registerCommand(RemoveFromRecentlyOpenedAPICommand.ID, adjustHandler(RemoveFromRecentlyOpenedAPICommand.execute));
|
|
|
|
export interface OpenIssueReporterArgs {
|
|
readonly extensionId: string;
|
|
readonly issueTitle?: string;
|
|
readonly issueBody?: string;
|
|
}
|
|
|
|
export class OpenIssueReporter {
|
|
public static readonly ID = 'vscode.openIssueReporter';
|
|
|
|
public static execute(executor: ICommandsExecutor, args: string | OpenIssueReporterArgs): Promise<void> {
|
|
const commandArgs = typeof args === 'string'
|
|
? { extensionId: args }
|
|
: args;
|
|
return executor.executeCommand('workbench.action.openIssueReporter', commandArgs);
|
|
}
|
|
}
|
|
|
|
interface RecentEntry {
|
|
uri: URI;
|
|
type: 'workspace' | 'folder' | 'file';
|
|
label?: string;
|
|
}
|
|
|
|
CommandsRegistry.registerCommand('_workbench.addToRecentlyOpened', async function (accessor: ServicesAccessor, recentEntry: RecentEntry) {
|
|
const workspacesService = accessor.get(IWorkspacesService);
|
|
let recent: IRecent | undefined = undefined;
|
|
const uri = recentEntry.uri;
|
|
const label = recentEntry.label;
|
|
if (recentEntry.type === 'workspace') {
|
|
const workspace = await workspacesService.getWorkspaceIdentifier(uri);
|
|
recent = { workspace, label };
|
|
} else if (recentEntry.type === 'folder') {
|
|
recent = { folderUri: uri, label };
|
|
} else {
|
|
recent = { fileUri: uri, label };
|
|
}
|
|
return workspacesService.addRecentlyOpened([recent]);
|
|
});
|
|
|
|
CommandsRegistry.registerCommand('_workbench.getRecentlyOpened', async function (accessor: ServicesAccessor) {
|
|
const workspacesService = accessor.get(IWorkspacesService);
|
|
return workspacesService.getRecentlyOpened();
|
|
});
|
|
|
|
CommandsRegistry.registerCommand('_extensionTests.setLogLevel', function (accessor: ServicesAccessor, level: number) {
|
|
const logService = accessor.get(ILogService);
|
|
const environmentService = accessor.get(IEnvironmentService);
|
|
|
|
if (environmentService.isExtensionDevelopment && !!environmentService.extensionTestsLocationURI) {
|
|
logService.setLevel(level);
|
|
}
|
|
});
|
|
|
|
CommandsRegistry.registerCommand('_workbench.openExternal', function (accessor: ServicesAccessor, uri: UriComponents, options: { allowTunneling?: boolean }) {
|
|
// TODO: discuss martin, ben where to put this
|
|
const openerService = accessor.get(IOpenerService);
|
|
openerService.open(URI.revive(uri), options);
|
|
});
|
|
|
|
|
|
CommandsRegistry.registerCommand('_extensionTests.getLogLevel', function (accessor: ServicesAccessor) {
|
|
const logService = accessor.get(ILogService);
|
|
|
|
return logService.getLevel();
|
|
});
|
|
|
|
|
|
CommandsRegistry.registerCommand('_workbench.action.moveViews', async function (accessor: ServicesAccessor, options: { viewIds: string[], destinationId: string }) {
|
|
const viewDescriptorService = accessor.get(IViewDescriptorService);
|
|
|
|
const destination = viewDescriptorService.getViewContainerById(options.destinationId);
|
|
if (!destination) {
|
|
return;
|
|
}
|
|
|
|
// FYI, don't use `moveViewsToContainer` in 1 shot, because it expects all views to have the same current location
|
|
for (const viewId of options.viewIds) {
|
|
const viewDescriptor = viewDescriptorService.getViewDescriptorById(viewId);
|
|
if (viewDescriptor?.canMoveView) {
|
|
viewDescriptorService.moveViewsToContainer([viewDescriptor], destination, ViewVisibilityState.Default);
|
|
}
|
|
}
|
|
|
|
await accessor.get(IViewsService).openViewContainer(destination.id, true);
|
|
});
|
|
|
|
export class MoveViewsAPICommand {
|
|
public static readonly ID = 'vscode.moveViews';
|
|
public static execute(executor: ICommandsExecutor, options: { viewIds: string[], destinationId: string }): Promise<any> {
|
|
if (!Array.isArray(options?.viewIds) || typeof options?.destinationId !== 'string') {
|
|
return Promise.reject('Invalid arguments');
|
|
}
|
|
|
|
return executor.executeCommand('_workbench.action.moveViews', options);
|
|
}
|
|
}
|
|
CommandsRegistry.registerCommand({
|
|
id: MoveViewsAPICommand.ID,
|
|
handler: adjustHandler(MoveViewsAPICommand.execute),
|
|
description: {
|
|
description: 'Move Views',
|
|
args: []
|
|
}
|
|
});
|
|
|
|
|
|
// -----------------------------------------------------------------
|
|
// The following commands are registered on the renderer but as API
|
|
// command. DO NOT USE this unless you have understood what this
|
|
// means
|
|
// -----------------------------------------------------------------
|
|
|
|
|
|
class OpenAPICommand {
|
|
public static readonly ID = 'vscode.open';
|
|
public static execute(executor: ICommandsExecutor, resource: URI): Promise<any> {
|
|
|
|
return executor.executeCommand('_workbench.open', resource);
|
|
}
|
|
}
|
|
CommandsRegistry.registerCommand(OpenAPICommand.ID, adjustHandler(OpenAPICommand.execute));
|
|
|
|
class DiffAPICommand {
|
|
public static readonly ID = 'vscode.diff';
|
|
public static execute(executor: ICommandsExecutor, left: URI, right: URI, label: string, options?: typeConverters.TextEditorOpenOptions): Promise<any> {
|
|
return executor.executeCommand('_workbench.diff', [
|
|
left, right,
|
|
label,
|
|
]);
|
|
}
|
|
}
|
|
CommandsRegistry.registerCommand(DiffAPICommand.ID, adjustHandler(DiffAPICommand.execute));
|