diff --git a/README.md b/README.md index 3db23c9..1f6e605 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,6 @@ Format mma code. -Very slow, but works. - Need to have installed first. Make sure you have `wolframscript` in your `PATH`. diff --git a/extension.js b/extension.js index d1b29d8..3e22553 100644 --- a/extension.js +++ b/extension.js @@ -1,7 +1,9 @@ // The module 'vscode' contains the VS Code extensibility API // Import the module and reference it with the alias vscode in your code below const vscode = require("vscode"); -const { spawnSync } = require("child_process"); +const path = require("path"); +const http = require("http"); +const { spawn, exec, fork, execSync } = require("child_process"); // This method is called when your extension is activated // Your extension is activated the very first time the command is executed @@ -10,32 +12,55 @@ const { spawnSync } = require("child_process"); */ function activate(context) { context.subscriptions.push( - vscode.languages.registerDocumentFormattingEditProvider("wolfram", { - provideDocumentFormattingEdits(document) { - const cellContent = []; - for (let i = 0; i < document.lineCount; i++) { - cellContent.push(document.lineAt(i).text); - } - const cellContentString = cellContent.join("\n"); - - return [ - vscode.TextEdit.replace( - new vscode.Range( - new vscode.Position(0, 0), - new vscode.Position( - document.lineCount - 1, - document.lineAt(document.lineCount - 1).text.length - ) + vscode.languages.registerDocumentFormattingEditProvider( + { language: "wolfram" }, + { + async provideDocumentFormattingEdits(document) { + try { + spawn("wolframscript", ["-f", path.join(__dirname, "server.wls")]); + } catch (e) { + console.debug(e.message); + } + const cellContent = []; + for (let i = 0; i < document.lineCount; i++) { + cellContent.push(document.lineAt(i).text); + } + const cellContentString = cellContent.join("\n"); + return [ + vscode.TextEdit.replace( + new vscode.Range( + new vscode.Position(0, 0), + new vscode.Position( + document.lineCount - 1, + document.lineAt(document.lineCount - 1).text.length + ) + ), + await new Promise((resolve) => { + const req = http.request( + { + hostname: "127.0.0.1", + port: 5858, + path: "/", + method: "POST", + headers: { + "Content-Type": "application/json", + "Content-Length": cellContentString.length, + }, + }, + (res) => { + res.on("data", (d) => { + console.debug(d.toString()); + resolve(d.toString()); + }); + } + ); + req.write(cellContentString); + }) ), - - spawnSync(`wolframscript`, ["-f", "./fmt.wls", cellContentString], { - timeout: 30000, - stdio: "pipe", - }).stdout.toString() - ), - ]; - }, - }) + ]; + }, + } + ) ); } // This method is called when your extension is deactivated diff --git a/fmt.wls b/fmt.wls deleted file mode 100644 index a656177..0000000 --- a/fmt.wls +++ /dev/null @@ -1,6 +0,0 @@ -Needs["CodeFormatter`"]; - -$ScriptCommandLine // -Last // -CodeFormatter`CodeFormat // -Print diff --git a/package.json b/package.json index b3df19f..0c9345d 100644 --- a/package.json +++ b/package.json @@ -2,12 +2,13 @@ "name": "mmafmt", "displayName": "mmafmt", "description": "fmt code", - "version": "0.0.1", + "version": "0.0.2", "repository": { "url": "whatever" }, "activationEvents": [ - "onLanguage:wolfram" + "onLanguage:wolfram", + "onStartupFinished" ], "engines": { "vscode": "^1.75.0" diff --git a/server.wls b/server.wls new file mode 100644 index 0000000..27fe43d --- /dev/null +++ b/server.wls @@ -0,0 +1,47 @@ +#!/usr/bin/env wolframscript +Print @ "Wolfram Expression Server 0.0.1 (alpha)"; +Print @ "Usage: wolframserver.wls [port]\n"; + +Needs["CodeFormatter`"]; + +If[ Length[$ScriptCommandLine] == 2, port = ToExpression @ Part[$ScriptCommandLine,2], port = 5858 ]; + +Print["Port: ", port]; +Print["$ProcessID: ", $ProcessID]; + +ApacheDateString[] := With[{tz = StringReplace[DateString["ISOTimeZone"], ":" -> ""]}, + DateString[{"[", "Day", "/", "Month", "/", "Year", ":", "Hour", ":", "Minute", ":", "Second", " ", tz, "]"}]]; + +ApacheLog[ str_String ] := Module[{}, Print[ "127.0.0.1 - - " <> ApacheDateString[] <> " \"POST / HTTP/1.1\" 200 " <> StringTrim[str] ] ]; + +listener = SocketListen[ + port, + Function[{assoc}, + With[{ + client = assoc["SourceSocket"], + data = assoc["Data"] + }, + request = ImportString[data, "HTTPRequest"]; + origin = Association[ request["Headers"] ]["origin"]; + If[ Head[origin]===Missing, origin="" ]; + result = CodeFormatter`CodeFormat[request["Body"]]; + response = ExportString[ + HTTPResponse[ result, <| + "StatusCode" -> 200, + "ContentType" -> "application/json", + "Headers" -> { "Access-Control-Allow-Origin" -> origin } + |>], "HTTPResponse"]; + WriteString[client, response]; + ApacheLog[ request["Body"] ]; + Close[client] + ] + ] + ]; + +url = URLBuild[<|"Scheme" -> "http", "Domain" -> First[listener["Socket"]["DestinationIPAddress"]], "Port" -> listener["Socket"]["DestinationPort"]|>]; + +Print["Listening: ", url, "\n"]; + +task = ZeroMQLink`Private`$AsyncState["Task"]; +WaitAsynchronousTask[task]; +Print["Exiting..."]; \ No newline at end of file