-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtl.html
117 lines (105 loc) · 2.58 KB
/
tl.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
<!DOCTYPE html>
<html>
<head>
<title>TinyLISP</title>
<meta charset="utf8"/>
<script type="text/javascript">
var worker, output;
var classes = {
stdout: "output",
stdin: "input",
stderr: "error",
system: "system",
};
function addout(txt, kind) {
var lc = output.lastChild;
if(lc && lc.nodeType == document.ELEMENT_NODE && lc.classList.contains(kind)) {
lc.textContent += txt;
return;
}
var spn = document.createElement("span");
spn.textContent = txt;
spn.classList.add(kind);
output.appendChild(spn);
spn.scrollIntoView();
}
function backspace() {
while(output.lastChild.textContent.length == 0) {
output.removeChild(output.lastChild);
}
var tc = output.lastChild.textContent;
if(tc.length == 1) {
output.removeChild(output.lastChild);
} else {
output.lastChild.textContent = tc.substr(0, tc.length - 1);
}
}
function recv(e) {
switch(e.data.type) {
case "stdout": case "stderr": case "stdin": case "system":
if(e.data.text == "\b") {
backspace();
} else {
addout(e.data.text, classes[e.data.type]);
}
break;
default:
console.log("Unknown message:", e.data);
break;
}
}
function onkey(e) {
if(!worker) return;
if(e.ctrlKey) return;
if(e.target instanceof HTMLInputElement) return;
worker.postMessage({type: "keydown", key: e.key});
e.preventDefault();
}
function onpaste(e) {
if(!worker) return;
var data = e.clipboardData.getData("text/plain");
if(data.length > 0) {
worker.postMessage({type: "paste", text: data});
}
}
function init() {
output = document.querySelector("#output");
worker = new Worker("worker.js?" + Math.random());
worker.onmessage = recv;
}
function load_file(fn) {
if(!worker) return;
fetch(fn).then(resp => resp.text()).then(source =>
worker.postMessage({type: "paste", text: source})
);
}
document.addEventListener("DOMContentLoaded", init);
document.addEventListener("keydown", onkey);
document.addEventListener("paste", onpaste);
</script>
<style type="text/css">
:root {
--input-color: #00a;
}
#output {
width: 100%;
height: 512px;
font-family: monospace;
white-space: pre-wrap;
}
#output *:last-child::after {
content: "█";
color: var(--input-color);
}
.error { color: #a00; }
.input { color: var(--input-color); }
.system { color: #707; }
</style>
</head>
<body>
<button onclick="load_file('../std.tl?' + Math.random());">Load Standard Library</button>
<input id="filename" type="text" placeholder="file.tl"/>
<button onclick="var ip = document.querySelector('#filename'); load_file('../' + ip.value + '?' + Math.random()); ip.value = '';">Load</button>
<div id="output"></div>
</body>
</html>