generated from stellartux/last-call-bbs-server-template
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.js
157 lines (131 loc) · 4.34 KB
/
server.js
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
// Config constants
const SCROLLBACK_INPUT_COLOR = 10;
const SCROLLBACK_OUTPUT_COLOR = 16;
const SCROLLBACK_ERROR_COLOR = 8;
const MAX_BUFFER_LENGTH = 49;
// Environment
const SCREEN_WIDTH = 56;
const SCREEN_HEIGHT = 20; // In characters
const SCROLLBACK_HEIGHT = 19;
const FIRST_PRINTABLE_CHARACTER = 32;
const SPACE = 32; // First printable ASCII character
// Control characters
const BACKSPACE = 8;
const TAB = 9;
const ENTER = 10;
const UP = 17;
const DOWN = 18;
const LEFT = 19;
const RIGHT = 20;
const ESCAPE = 27;
const DEL = 127;
const Mode = {
EDIT: 0,
SCROLL: 1,
};
// Global variables (blech)
let lastKey = ''; // The last key that was pressed
let keyBuffer = ''; // The current line
let _ = null; // Similar to the Python convention
let currentMode = Mode.EDIT;
let scrollback = [{ text: "JavaScript REPL", color: SCROLLBACK_OUTPUT_COLOR }];
let history = [];
let scrollOffsetFromEnd = 0;
function getName() {
return 'REPL';
}
function onConnect() {
render();
}
function onUpdate() {
}
function onInput(key) {
// Remember the last key pressed:
lastKey = key.toString();
switch (key) {
case BACKSPACE:
if (keyBuffer.length > 0) {
keyBuffer = keyBuffer.substring(0, keyBuffer.length - 1);
}
break;
case ENTER:
if (keyBuffer.length > 0) {
try {
scrollback.push({ text: keyBuffer, color: SCROLLBACK_INPUT_COLOR });
history.push(keyBuffer);
_ = eval(keyBuffer);
if (_ === null) {
scrollback.push({ text: "null", color: SCROLLBACK_OUTPUT_COLOR });
}
else if (_ === undefined) {
scrollback.push({ text: "undefined", color: SCROLLBACK_OUTPUT_COLOR });
}
else {
const result = _.toString();
output(result, SCROLLBACK_OUTPUT_COLOR);
}
}
catch (error) {
output(error.toString(), SCROLLBACK_ERROR_COLOR);
}
}
keyBuffer = '';
scrollOffsetFromEnd = 0;
break;
case TAB:
case ESCAPE:
case DEL:
// noop
break;
case UP: {
const unseenLinesFromStart = Math.max(scrollback.length - SCROLLBACK_HEIGHT, 0);
if (scrollOffsetFromEnd < unseenLinesFromStart) {
scrollOffsetFromEnd += 1;
}
break;
}
case DOWN: {
if (scrollOffsetFromEnd > 0) {
scrollOffsetFromEnd -= 1;
}
}
default:
// Add text
if (key >= FIRST_PRINTABLE_CHARACTER && keyBuffer.length < MAX_BUFFER_LENGTH) {
keyBuffer = keyBuffer + String.fromCharCode(key);
}
}
render();
}
// Some characters aren't available in the display font,
// so I replace them with reasonable-looking substitutes.
function sanitize(input) {
input = input.replace(/=/g, "═");
input = input.replace(/\|/g, "║");
input = input.replace(/~/g, "™");
input = input.replace(/@/g, "☺");
input = input.replace(/\$/g, "♣");
input = input.replace(/_/g, "▄");
input = input.replace(/\{/g, "╣");
input = input.replace(/\}/g, "╠");
return input;
}
// Output text, wrapping it across multiple lines if necessary
function output(text, color) {
const result = text.toString();
for (let s = 0; s < (result.length / SCREEN_WIDTH); s++) { // Break the output into chunks the size of the screen's width
const segment = result.slice(s * SCREEN_WIDTH, (s + 1) * SCREEN_WIDTH);
scrollback.push({ text: segment, color: color });
}
}
function render() {
// It is safe to completely redraw the screen during every update:
clearScreen();
const displayHeight = Math.min(scrollback.length, SCROLLBACK_HEIGHT);
const unseenLinesFromStart = Math.max(scrollback.length - SCROLLBACK_HEIGHT, 0);
for (let i = 0; i < displayHeight; i++) {
const entry = scrollback[i + unseenLinesFromStart - scrollOffsetFromEnd];
drawText(sanitize(entry.text), entry.color, 0, i)
}
drawText("> " + sanitize(keyBuffer) + "█", 17, 0, SCREEN_HEIGHT - 1);
}