"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) { if (event.key === "Enter" && !event.shiftKey && !event.altKey) { event.preventDefault(); execLine() } else if (event.ctrlKey && !event.altKey) { handleCtrlKey(event); } else if (event.key === "ArrowUp" && !event.altKey) { event.preventDefault(); prevHistory(); } else if (event.key === "ArrowDown" && !event.altKey) { 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(); }