Files
newt/playground/src/main.ts
2024-11-05 20:20:20 -08:00

101 lines
2.8 KiB
TypeScript

import { newtConfig, newtTokens } from "./monarch.ts";
import * as monaco from "monaco-editor";
monaco.languages.register({ id: "newt" });
monaco.languages.setMonarchTokensProvider("newt", newtTokens);
monaco.languages.setLanguageConfiguration("newt", newtConfig);
const newtWorker = new Worker("worker.js")//new URL("worker.js", import.meta.url))
self.MonacoEnvironment = {
getWorkerUrl(moduleId, label) {
console.log("Get worker", moduleId);
return moduleId;
},
};
// I keep pressing this.
document.addEventListener('keydown', (ev) => {
if (ev.metaKey && ev.code == 'KeyS') ev.preventDefault();
})
let value = localStorage.code || "module Main\n";
let container = document.getElementById("editor")!;
let result = document.getElementById("result")!;
const editor = monaco.editor.create(container, {
value,
language: "newt",
theme: "vs",
automaticLayout: true,
minimap: { enabled: false },
});
let timeout: number | undefined;
function run(src: string) {
newtWorker.postMessage({src})
}
newtWorker.onmessage = (ev) => {
console.log('worker sent', ev.data)
let {output, javascript} = ev.data
processOutput(output);
}
// Adapted from the vscode extension, but types are slightly different
// and positions are 1-based.
const processOutput = (output: string) => {
result.innerText = output
let model = editor.getModel()!
let markers: monaco.editor.IMarkerData[] = []
let lines = output.split('\n')
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
const match = line.match(/(INFO|ERROR) at \((\d+), (\d+)\):\s*(.*)/);
if (match) {
let [_full, kind, line, col, message] = match;
let lineNumber = +line+1
let column = +col+1;
let start = {column, lineNumber};
// we don't have the full range, so grab the surrounding word
let endColumn = column + 1
let word = model.getWordAtPosition(start)
if (word) endColumn = word.endColumn
// heuristics to grab the entire message:
// anything indented
// Context:, or Goal: are part of PRINTME
// unexpected / expecting appear in parse errors
while (
lines[i + 1]?.match(/^( )/)
) {
message += "\n" + lines[++i];
}
const severity = kind === 'ERROR' ? monaco.MarkerSeverity.Error : monaco.MarkerSeverity.Info
markers.push({
severity,
message,
startLineNumber: lineNumber,
endLineNumber: lineNumber,
startColumn: column,
endColumn,
})
}
}
console.log('setMarkers', markers)
monaco.editor.setModelMarkers(model, 'newt', markers)
}
editor.onDidChangeModelContent((ev) => {
console.log("mc", ev);
let value = editor.getValue();
clearTimeout(timeout);
timeout = setTimeout(() => run(value), 1000);
localStorage.code = value;
});
run(value);