From 042dd0d69b4d58b4a3e7b05a0ac75a12a1cd7c3a Mon Sep 17 00:00:00 2001 From: Christoph Seitz Date: Mon, 2 Dec 2019 21:19:08 +0100 Subject: [PATCH] fixup! dev. --- src/tasks/execution.ts | 54 +++++++++++++++ src/tasks/taskProvider.ts | 141 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 195 insertions(+) create mode 100644 src/tasks/execution.ts create mode 100644 src/tasks/taskProvider.ts diff --git a/src/tasks/execution.ts b/src/tasks/execution.ts new file mode 100644 index 0000000..9574a4f --- /dev/null +++ b/src/tasks/execution.ts @@ -0,0 +1,54 @@ +import * as vscode from "vscode"; +import {IPty, IBasePtyForkOptions} from "node-pty"; +import * as path from 'path'; + +//@ts-ignore +const requireFunc = typeof __webpack_require__ === "function" ? __non_webpack_require__ : require; +const moduleName = path.join(vscode.env.appRoot, "node_modules.asar", "node-pty"); +const spawn: typeof import('node-pty').spawn = requireFunc(moduleName).spawn; + +import { CMakeClient } from "../cmake/cmake"; + +class CMakeBuildTerminal implements vscode.Pseudoterminal { + private terminal: IPty | undefined; + private closeEmitter: vscode.EventEmitter< + number | void + > = new vscode.EventEmitter(); + private writeEmitter: vscode.EventEmitter = new vscode.EventEmitter(); + + constructor(private client: CMakeClient, private targets?: string[]) {} + + onDidWrite: vscode.Event = this.writeEmitter.event; + onDidClose: vscode.Event = this.closeEmitter.event; + + open(initialDimensions: vscode.TerminalDimensions | undefined): void { + let options: IBasePtyForkOptions = {}; + if (initialDimensions) { + options.cols = initialDimensions.columns; + options.rows = initialDimensions.rows; + } + + this.terminal = spawn( + this.client.cmakeExecutable, + this.client.getBuildArguments(this.targets), + options + ); + + this.terminal.onExit((data) => this.closeEmitter.fire(data.exitCode)); + this.terminal.onData((data) => this.writeEmitter.fire(data)); + } + + close(): void { + if (this.terminal) { + this.terminal.kill(); + } + } + + setDimensions(dim: vscode.TerminalDimensions) { + if (this.terminal) { + this.terminal.resize(dim.columns, dim.rows); + } + } +} + +export { CMakeBuildTerminal }; diff --git a/src/tasks/taskProvider.ts b/src/tasks/taskProvider.ts new file mode 100644 index 0000000..3cebe7c --- /dev/null +++ b/src/tasks/taskProvider.ts @@ -0,0 +1,141 @@ +import * as vscode from "vscode"; +import { CMakeClient } from "../cmake/cmake"; +import { CMakeBuildTerminal } from "./execution"; + +interface CMakeTaskDefinition extends vscode.TaskDefinition { + type: string; + action: "configure" | "build"; + target?: string; +} + +class CMakeTaskProvider implements vscode.TaskProvider { + private clientTasks: Map = new Map(); + private workspaceClients: Map = new Map(); + + static TaskSource: string = "cmake"; + static TaskType: string = "cmake"; + + private static generateClientTasks(client: CMakeClient) { + let tasks: vscode.Task[] = []; + tasks.push( + new vscode.Task( + { + type: CMakeTaskProvider.TaskType, + action: "configure" + } as CMakeTaskDefinition, + client.workspaceFolder, + `configure`, + CMakeTaskProvider.TaskSource, + new vscode.CustomExecution(() => Promise.reject()) + ) + ); + tasks.push( + new vscode.Task( + { + type: "cmake", + action: "build", + target: "clean" + } as CMakeTaskDefinition, + client.workspaceFolder, + `clean`, + "cmake", + new vscode.CustomExecution(() => Promise.resolve( + new CMakeBuildTerminal( + client!, + ["clean"] + ) + )) + ) + ); + client.targets.forEach((target) => { + tasks.push( + new vscode.Task( + { + type: "cmake", + action: "build", + target: target.name + } as CMakeTaskDefinition, + client.workspaceFolder, + `build ${target.name}`, + "cmake", + new vscode.CustomExecution(() => Promise.resolve( + new CMakeBuildTerminal( + client!, + [target.name] + ) + )) + ) + ); + }); + return tasks; + } + + addClient(client: CMakeClient) { + this.clientTasks.set(client, CMakeTaskProvider.generateClientTasks(client)); + this.workspaceClients.set(client.workspaceFolder.uri.toString(), client); + } + + deleteClient(client: CMakeClient) { + this.clientTasks.delete(client); + this.workspaceClients.delete(client.workspaceFolder.uri.toString()); + } + + changeClientModel(client: CMakeClient) { + this.clientTasks.set(client, CMakeTaskProvider.generateClientTasks(client)); + } + + provideTasks( + _token?: vscode.CancellationToken | undefined + ): vscode.ProviderResult { + let tasks: vscode.Task[] = []; + for (const clientTasks of this.clientTasks.values()) { + tasks.push(...clientTasks); + } + return tasks; + } + resolveTask( + task: vscode.Task, + _token?: vscode.CancellationToken | undefined + ): vscode.ProviderResult { + function isWorkspaceFolder( + scope?: vscode.WorkspaceFolder | vscode.TaskScope + ): scope is vscode.WorkspaceFolder { + return typeof scope === "object"; + } + let client: CMakeClient | undefined; + if (task.scope) { + if (isWorkspaceFolder(task.scope)) { + client = this.workspaceClients.get(task.scope.uri.toString()); + } else if (task.scope === vscode.TaskScope.Workspace) { + client = this.workspaceClients.values().next().value; + } + } + if (client) { + let def: CMakeTaskDefinition = task.definition; + let targets = []; + if (def.target) { + targets.push(def.target); + } + return new vscode.Task( + { + type: "cmake", + action: def.action, + target: def.target + } as CMakeTaskDefinition, + client.workspaceFolder, + "Build", + "cmake", + Promise.resolve( + new CMakeBuildTerminal( + client!, + targets + ) + ) + ); + } else { + throw new Error(`Can't resolve client for Task ${task.name}`); + } + } +} + +export { CMakeTaskProvider };