From 7fea1340b1d13e64a985262d4ed751fa6c929cfe Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Thu, 28 Sep 2023 16:20:06 -0700 Subject: [PATCH] Use async processing, displays immediate feedback Still seems not to be able to recreate the window when closed once. --- arduino-littlefs-upload-0.0.2.vsix | Bin 196866 -> 196919 bytes src/extension.ts | 66 +++++++++++++++++------------ 2 files changed, 39 insertions(+), 27 deletions(-) diff --git a/arduino-littlefs-upload-0.0.2.vsix b/arduino-littlefs-upload-0.0.2.vsix index 20e412981f5b3a51c73f5b37f366652f036f4a21..5ab87119f0f450491e10af98af74a97899d90027 100644 GIT binary patch delta 5805 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 Kz8t+7)BPXW4Febe delta 5744 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 diff --git a/src/extension.ts b/src/extension.ts index a197e48..e7e3b8b 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -2,16 +2,10 @@ import * as vscode from 'vscode'; import * as fs from 'fs'; import type { ArduinoContext } from 'vscode-arduino-api'; import { platform } from 'node:os'; -import { spawn, spawnSync } from 'child_process'; - - -import { exec as cpExec } from "child_process"; -import { promisify } from "util"; - -// promisified Node executable (Node 10+) -const exec = promisify(cpExec); +import { spawn } from 'child_process'; const writeEmitter = new vscode.EventEmitter(); +let writerReady : boolean = false; function makeTerminal(title : string) { // If it exists, move it to the front @@ -24,8 +18,8 @@ function makeTerminal(title : string) { // Not found, make a new terminal const pty = { onDidWrite: writeEmitter.event, - open: () => {}, - close: () => {}, + open: () => { writerReady = true; }, + close: () => { writerReady = false; }, handleInput: () => {} }; let terminal = (vscode.window).createTerminal({name: title, pty}); @@ -46,6 +40,8 @@ function findTool(ctx: ArduinoContext, match : string) : string | undefined { return ret; } + + export function activate(context: vscode.ExtensionContext) { // Get the Arduino info extension loaded const arduinoContext: ArduinoContext = vscode.extensions.getExtension('dankeboy36.vscode-arduino-api')?.exports; @@ -58,7 +54,7 @@ export function activate(context: vscode.ExtensionContext) { makeTerminal("LittleFS Upload"); // Register the command - let disposable = vscode.commands.registerCommand('arduino-littlefs-upload.uploadLittleFS', () => { + const disposable = vscode.commands.registerCommand('arduino-littlefs-upload.uploadLittleFS', async () => { //let str = JSON.stringify(arduinoContext, null, 4); //console.log(str); @@ -68,6 +64,11 @@ export function activate(context: vscode.ExtensionContext) { return; } + // Wait for the terminal to become active. + while (!writerReady) { + await new Promise( resolve => setTimeout(resolve, 100) ); + } + // Clear the terminal writeEmitter.fire('\x1b[2J\x1b[3J\x1b[;H'); @@ -185,14 +186,20 @@ export function activate(context: vscode.ExtensionContext) { writeEmitter.fire("Building LittleFS filesystem\r\n"); writeEmitter.fire(mklittlefs + " " + buildOpts.join(" ") + "\r\n"); - let mkfs = spawnSync(mklittlefs, buildOpts); - writeEmitter.fire(String(mkfs.stdout).replace(/\n/g, "\r\n")); - if (mkfs.stderr) { - writeEmitter.fire(String(mkfs.stderr).replace(/\n/g, "\r\n")); + const mkfs = spawn(mklittlefs, buildOpts); + for await (const chunk of mkfs.stdout) { + writeEmitter.fire(String(chunk).replace(/\n/g, "\r\n")); } - writeEmitter.fire("\r\n\r\n"); - if (mkfs.status) { - writeEmitter.fire("ERROR: Mklittlefs failed, error code: " + String(mkfs.status) + "\r\n\r\n"); + for await (const chunk of mkfs.stderr) { + writeEmitter.fire(String(chunk).replace(/\n/g, "\r\n")); + } + // Wait until the executable finishes + let exitCode = await new Promise( (resolve, reject) => { + mkfs.on('close', resolve); + }); + + if (exitCode) { + writeEmitter.fire("ERROR: Mklittlefs failed, error code: " + String(exitCode) + "\r\n\r\n"); return; } @@ -214,17 +221,22 @@ export function activate(context: vscode.ExtensionContext) { uploadOpts = [upload, "--chip", "esp8266", "--port", serialPort, "--baud", String(uploadSpeed), "write_flash", String(fsStart), imageFile]; } - writeEmitter.fire("Uploading LittleFS filesystem\r\n"); + writeEmitter.fire("\r\n\r\nUploading LittleFS filesystem\r\n"); writeEmitter.fire(python3 + " " + uploadOpts.join(" ") + "\r\n"); - let upld = spawnSync(python3, uploadOpts); - - writeEmitter.fire(String(upld.stdout).replace(/\n/g, "\r\n")); - if (upld.stderr) { - writeEmitter.fire(String(upld.stderr).replace(/\n/g, "\r\n")); + const upld = spawn(python3, uploadOpts); + for await (const chunk of upld.stdout) { + writeEmitter.fire(String(chunk).replace(/\n/g, "\r\n")); } - writeEmitter.fire("\r\n\r\n"); - if (upld.status) { - writeEmitter.fire("ERROR: Upload failed, error code: " + String(upld.status) + "\r\n\r\n"); + for await (const chunk of upld.stderr) { + writeEmitter.fire(String(chunk).replace(/\n/g, "\r\n")); + } + // Wait until the executable finishes + exitCode = await new Promise( (resolve, reject) => { + upld.on('close', resolve); + }); + + if (exitCode) { + writeEmitter.fire("ERROR: Upload failed, error code: " + String(exitCode) + "\r\n\r\n"); return; }