Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions client/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { setupSidebar } from './setupSidebar';
import { setupDecorators } from './setupDecorators';
import { setupPDEFiles } from './setupPDEFiles';
import { EventEmitter } from 'stream';
import setupConsole from './setupConsole';


export interface ProcessingVersion {
Expand Down Expand Up @@ -38,6 +39,7 @@ export async function activate(context: ExtensionContext) {
setupCommands(context);
setupLanguageServer();
setupSidebar(context);
setupConsole(context);
setupDecorators(context);
setupPDEFiles();
}
Expand Down
140 changes: 70 additions & 70 deletions client/src/setupCommands.ts
Original file line number Diff line number Diff line change
@@ -1,77 +1,77 @@
import { basename, dirname, join } from 'path';
import { ExtensionContext, commands, Uri, window, workspace } from 'vscode';
import { state } from './extension';
// import { state } from './extension';

const sketchNumber = 0;
// const sketchNumber = 0;

export function setupCommands(context: ExtensionContext) {
const runSketch = commands.registerCommand('processing.sketch.run', (resource: Uri) => {
// TODO: Use VScode contexts to highlight run button when sketch is running, blocked until we do not run the sketch in a terminal
// https://code.visualstudio.com/api/references/when-clause-contexts

const autosave = workspace
.getConfiguration('processing')
.get<boolean>('autosave');
if (autosave === true) {
// Save all files before running the sketch
commands.executeCommand('workbench.action.files.saveAll');
}
if (resource == undefined) {
const editor = window.activeTextEditor;
if (editor) {
resource = editor.document.uri;
}
}

if (!resource) {
return;
}

// TODO: Give feedback if the sketch is starting

let terminal = state.terminal;
// Create a new terminal
if (terminal === undefined || terminal.exitStatus) {
window.terminals.forEach(t => {
if (t.name === "Sketch") {
t.dispose();
}
});
state.terminal = window.createTerminal("Sketch");
terminal = state.terminal;
// Show the terminal panel the first time
terminal.show(true);
} else {
// Send the command to the terminal
terminal.sendText('\x03', false);
}

// clear the terminal
terminal.sendText("clear", true);

let path = state.selectedVersion.path;
if (process.platform === "win32") {
// on windows we need to escape spaces
path = `& "${path}"`;
}

let cmd = `${path} cli --sketch="${dirname(resource.fsPath)}" --run`;
if (process.platform === "win32") {
// on windows we need to pipe stderr to stdout and convert to string
cmd += ` 2>&1`;
}

terminal.sendText(cmd, true);
});

const stopSketch = commands.registerCommand('processing.sketch.stop', () => {
if (state.terminal === undefined) {
return;
}

// Send the command to the terminal
state.terminal.sendText('\x03', false);
});
// const runSketch = commands.registerCommand('processing.sketch.run', (resource: Uri) => {
// // TODO: Use VScode contexts to highlight run button when sketch is running, blocked until we do not run the sketch in a terminal
// // https://code.visualstudio.com/api/references/when-clause-contexts

// const autosave = workspace
// .getConfiguration('processing')
// .get<boolean>('autosave');
// if (autosave === true) {
// // Save all files before running the sketch
// commands.executeCommand('workbench.action.files.saveAll');
// }
// if (resource == undefined) {
// const editor = window.activeTextEditor;
// if (editor) {
// resource = editor.document.uri;
// }
// }

// if (!resource) {
// return;
// }

// return;

// let terminal = state.terminal;
// // Create a new terminal
// if (terminal === undefined || terminal.exitStatus) {
// window.terminals.forEach(t => {
// if (t.name === "Sketch") {
// t.dispose();
// }
// });
// state.terminal = window.createTerminal("Sketch");
// terminal = state.terminal;
// // Show the terminal panel the first time
// terminal.show(true);
// } else {
// // Send the command to the terminal
// terminal.sendText('\x03', false);
// }

// // clear the terminal
// terminal.sendText("clear", true);

// let path = state.selectedVersion.path;
// if (process.platform === "win32") {
// // on windows we need to escape spaces
// path = `& "${path}"`;
// }

// let cmd = `${path} cli --sketch="${dirname(resource.fsPath)}" --run`;
// if (process.platform === "win32") {
// // on windows we need to pipe stderr to stdout and convert to string
// cmd += ` 2>&1`;
// }

// terminal.sendText(cmd, true);
// });

// const stopSketch = commands.registerCommand('processing.sketch.stop', () => {
// if (state.terminal === undefined) {
// return;
// }

// // Send the command to the terminal
// state.terminal.sendText('\x03', false);
// });

const openSketch = commands.registerCommand('processing.sketch.open', async (folder: string, isReadOnly: boolean) => {
if (!folder) {
Expand Down Expand Up @@ -161,7 +161,7 @@ export function setupCommands(context: ExtensionContext) {

// TODO: Add command to select Processing version and set the setting

context.subscriptions.push(runSketch, stopSketch, openSketch, newSketch);
context.subscriptions.push(openSketch, newSketch);
}

// Helper function to convert a number to alphabetical (e.g., 0 = a, 1 = b, ..., 25 = z, 26 = aa, etc.)
Expand Down
153 changes: 153 additions & 0 deletions client/src/setupConsole.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import { ChildProcess, spawn } from 'child_process';
import { commands, ExtensionContext, Uri, WebviewView, WebviewViewProvider, WebviewViewResolveContext, window, workspace } from 'vscode';
import { state } from './extension';
import { dirname } from 'path';
import * as treeKill from 'tree-kill';

export default function setupConsole(context: ExtensionContext) {
const sketchProcesses: ChildProcess[] = [];

const provider = new ProcessingConsoleViewProvider();

const register = window.registerWebviewViewProvider('processingConsoleView', provider);

const startSketch = commands.registerCommand('processing.sketch.run', (resource: Uri) => {
const autosave = workspace
.getConfiguration('processing')
.get<boolean>('autosave');
if (autosave === true) {
// Save all files before running the sketch
commands.executeCommand('workbench.action.files.saveAll');
}
if (resource == undefined) {
const editor = window.activeTextEditor;
if (editor) {
resource = editor.document.uri;
}
}

if (!resource) {
return;
}
commands.executeCommand('processingConsoleView.focus');
commands.executeCommand('processing.sketch.stop');

const proc = spawn(
state.selectedVersion.path,
['cli', `--sketch=${dirname(resource.fsPath)}`, '--run'],
{
shell: false,
}
);
proc.stdout.on("data", (data) => {
provider.webview?.webview.postMessage({ type: 'stdout', value: data?.toString() });
});
proc.stderr.on("data", (data) => {
provider.webview?.webview.postMessage({ type: 'stderr', value: data?.toString() });
// TODO: Handle and highlight errors in the editor
});
proc.on('close', (code) => {
provider.webview?.webview.postMessage({ type: 'close', value: code?.toString() });
sketchProcesses.splice(sketchProcesses.indexOf(proc), 1);
commands.executeCommand('setContext', 'processing.sketch.running', false);
});
provider.webview?.show?.(true);
provider.webview?.webview.postMessage({ type: 'clear'});
sketchProcesses.push(proc);
commands.executeCommand('setContext', 'processing.sketch.running', true);
});

const restartSketch = commands.registerCommand('processing.sketch.restart', (resource: Uri) => {
commands.executeCommand('processing.sketch.run', resource);
});

const stopSketch = commands.registerCommand('processing.sketch.stop', () => {
for (const proc of sketchProcesses) {
treeKill(proc.pid as number);
}
});

context.subscriptions.push(
register,
startSketch,
restartSketch,
stopSketch
);
}

// TODO: Add setting for timestamps
// TODO: Add setting for collapsing similar messages
// TODO: Add option to enable/disable stdout and stderr
class ProcessingConsoleViewProvider implements WebviewViewProvider {
public webview?: WebviewView;

public resolveWebviewView(webviewView: WebviewView, context: WebviewViewResolveContext): Thenable<void> | void {
webviewView.webview.options = { enableScripts: true };
webviewView.webview.html = `
<!DOCTYPE html>
<html>
<body>
<script>
window.addEventListener('message', event => {

const message = event.data; // The JSON data our extension sent

const isScrolledToBottom = (window.innerHeight + window.scrollY) >= document.body.offsetHeight;

const ts = document.createElement("span");
ts.style.color = "gray";
const now = new Date();
const hours = now.getHours().toString().padStart(2, '0');
const minutes = now.getMinutes().toString().padStart(2, '0');
const seconds = now.getSeconds().toString().padStart(2, '0');
ts.textContent = "[" + hours + ":" + minutes + ":" + seconds + "] ";


switch (message.type) {
case 'clear':
document.body.innerHTML = '';
break;
case 'stdout':
var pre = document.createElement("pre");
pre.style.color = "white";
pre.textContent = message.value;
if (pre.textContent.endsWith("\\n")) {
pre.textContent = pre.textContent.slice(0, -1);
}
pre.prepend(ts);
document.body.appendChild(pre);
break;
case 'stderr':
var pre = document.createElement("pre");
pre.style.color = "red";
pre.textContent = message.value;
if (pre.textContent.endsWith("\\n")) {
pre.textContent = pre.textContent.slice(0, -1);
}
pre.prepend(ts);
document.body.appendChild(pre);
break;
case 'close':
var pre = document.createElement("pre");
pre.style.color = "gray";
pre.textContent = "Process exited with code " + message.value;
pre.prepend(ts);
document.body.appendChild(pre);
break;
}

if (isScrolledToBottom) {
window.scrollTo(0, document.body.scrollHeight);
}
});
</script>
</body>
</html>
`;
webviewView.onDidDispose(() => {
commands.executeCommand("processing.sketch.stop");
});
this.webview = webviewView;
}

}
2 changes: 1 addition & 1 deletion client/tsconfig.tsbuildinfo
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"root":["./src/compareversions.ts","./src/extension.ts","./src/setupcommands.ts","./src/setupdecorators.ts","./src/setuplanguageserver.ts","./src/setuppdefiles.ts","./src/setupselectedversion.ts","./src/setupsidebar.ts"],"version":"5.8.3"}
{"root":["./src/compareversions.ts","./src/extension.ts","./src/setupcommands.ts","./src/setupconsole.ts","./src/setupdecorators.ts","./src/setuplanguageserver.ts","./src/setuppdefiles.ts","./src/setupselectedversion.ts","./src/setupsidebar.ts"],"version":"5.8.3"}
5 changes: 5 additions & 0 deletions media/restart.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 16 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading