talc/talc-web/main.js

162 lines
3.2 KiB
JavaScript
Raw Permalink Normal View History

2025-01-06 00:18:13 -05:00
"use strict";
import init, * as talc from "./pkg/talc_web.js";
await init();
/*
* DOM
*/
const $ = (q) => document.querySelector(q);
function newEl(tag, attrs, children) {
const el = document.createElement(tag);
for (const attr in attrs) {
el.setAttribute(attr, attrs[attr]);
}
for (const child of children) {
if (typeof(child) === "string") {
el.appendChild(document.createTextNode(child));
} else {
el.appendChild(child);
}
}
return el;
}
/*
* History
*/
let historyEntries = [""];
let historyIndex = 0;
let currentLine = "";
function prevHistory() {
const inputEl = $("#input");
if (historyIndex === 0) {
currentLine = inputEl.innerText;
}
historyIndex = Math.min(historyIndex+1, historyEntries.length);
const text = historyEntries[historyEntries.length - historyIndex];
inputEl.innerText = text;
document.getSelection().setPosition(inputEl, inputEl.childNodes.length);
}
function nextHistory() {
const inputEl = $("#input");
historyIndex = Math.max(historyIndex-1, 0);
let text;
if (historyIndex === 0) {
text = currentLine;
} else {
text = historyEntries[historyEntries.length - historyIndex];
}
inputEl.innerText = text;
document.getSelection().setPosition(inputEl, inputEl.childNodes.length);
}
/*
* REPL
*/
function nextLine() {
const newPrompt = newEl("div", {"class": "prompt"}, []);
newPrompt.innerHTML = $("#prompt").innerHTML;
const newInput = newEl("div", {}, []);
newInput.innerHTML = $("#input").innerHTML;
$("#history").appendChild(newEl(
"div",
{"class": "input_line"},
[newPrompt, newInput]
));
$("#input").innerHTML = "";
currentLine = "";
historyIndex = 0;
}
function execLine() {
const inputLine = $("#input").innerText;
nextLine();
historyEntries.push(inputLine);
try {
const fixedInput = inputLine.replaceAll("\u00a0", " ");
const out = talc.eval_line(fixedInput);
if (out !== undefined) {
$("#history").appendChild(newEl("div", {}, [out]));
}
} catch (e) {
$("#history").appendChild(newEl("div", {}, [
newEl("span", {"class": "error"}, ["Error: "]),
newEl("pre", {"class": "err_msg"}, [e.toString()])
]));
}
}
/*
* Input
*/
function handleCtrlKey(event) {
switch (event.code) {
case "KeyL":
event.preventDefault();
$("#history").innerHTML = "";
break;
case "KeyC":
event.preventDefault();
nextLine();
break;
}
}
function keyPressed(event) {
2025-01-18 19:06:58 -05:00
if (event.key === "Enter" && !event.shiftKey && !event.altKey) {
2025-01-06 00:18:13 -05:00
event.preventDefault();
execLine()
2025-01-18 19:06:58 -05:00
} else if (event.ctrlKey && !event.altKey) {
2025-01-06 00:18:13 -05:00
handleCtrlKey(event);
2025-01-18 19:06:58 -05:00
} else if (event.key === "ArrowUp" && !event.altKey) {
2025-01-06 00:18:13 -05:00
event.preventDefault();
prevHistory();
2025-01-18 19:06:58 -05:00
} else if (event.key === "ArrowDown" && !event.altKey) {
2025-01-06 00:18:13 -05:00
event.preventDefault();
nextHistory();
}
window.scrollTo(0, document.body.scrollHeight);
}
/*
* Listeners
*/
$("#input").addEventListener("keydown", keyPressed);
$("#input").focus();
$("#terminal").addEventListener("click", (event) => {
if (event.target.id === "terminal" || event.target.id === "input") {
$("#input").focus();
}
})
/*
* Query parameter
*/
const urlParams = new URLSearchParams(window.location.search);
const initialLine = urlParams.get("eval");
if (initialLine !== null) {
$("#input").innerText = initialLine;
execLine();
}