stuff
This commit is contained in:
parent
e8e9bfd6ec
commit
5d8a047949
4 changed files with 155 additions and 7 deletions
14
README.md
14
README.md
|
@ -1,12 +1,12 @@
|
|||
# hundred
|
||||
|
||||
a coding challenge i made for myself; how much
|
||||
can i fit in one hundred lines or less?
|
||||
a coding challenge i made for myself; how much can i fit in one hundred
|
||||
lines or less?
|
||||
|
||||
i'll try to keep these understandable and not
|
||||
mangle/minify them. if you want to use them,
|
||||
you probrably should edit them to your liking
|
||||
first.
|
||||
i'll try to keep these understandable and not mangle/minify them. if
|
||||
you want to use them, you probrably should edit them to your liking
|
||||
first. **note: many of these are buggy. please double check before
|
||||
using them**
|
||||
|
||||
- `server.js` basic http server based off of express
|
||||
- `templater.js` pre-render your webpages server side
|
||||
|
@ -19,3 +19,5 @@ first.
|
|||
- `tictactoe.js` (deno) two player tic-tac-toe game
|
||||
- `xml.js` xml/html parser
|
||||
- `p2p.js` sample p2p protocol implementation
|
||||
- `canvas.js` a terminal canvas emulator with many, many known bugs
|
||||
- `input.js` simple terminal raw input
|
||||
|
|
99
canvas.js
Normal file
99
canvas.js
Normal file
|
@ -0,0 +1,99 @@
|
|||
const block = "\u2580"
|
||||
const nl = s => s.str.replace(/\n/g, `\n\x1b[${s.x + 1}G`)
|
||||
const fmt = s => `\x1b[${Math.floor(s.y / 2) + 1};${s.x + 1}H${nl(s)}`;
|
||||
class Color {
|
||||
static black = 0;
|
||||
static red = 1;
|
||||
static green = 2;
|
||||
static yellow = 3;
|
||||
static blue = 4;
|
||||
static purple = 5;
|
||||
static cyan = 6;
|
||||
static white = 7;
|
||||
}
|
||||
|
||||
class Canvas {
|
||||
constructor(w, h) {
|
||||
if(h) this.rw = w, this.rh = h;
|
||||
this.strs = [];
|
||||
this.buffer = [];
|
||||
for(let i = 0; i < this.height; i++) this.buffer.push([]);
|
||||
this.clear();
|
||||
this.color = Color.black;
|
||||
}
|
||||
|
||||
flush(clear = true) {
|
||||
let curtop = -1, curbot = -1;
|
||||
let runtop = true, runbot = true;
|
||||
let str = "\x1b[0;0H";
|
||||
for(let i = 0; i < this.height; i += 2) {
|
||||
for(let j = 0; j < this.width; j++) {
|
||||
const top = this.buffer[i][j], bottom = this.buffer[i + 1][j];
|
||||
const resumed = !(runtop || runbot);
|
||||
runtop = top !== -1, runbot = bottom !== -1;
|
||||
if(!(runtop || runbot)) continue;
|
||||
if(resumed) str += `\x1b[${i / 2 + 1};${j + 1}H`;
|
||||
if(top !== curtop) {
|
||||
str += `\x1b[3${top === -1 ? 0 : top}m`;
|
||||
curtop = top;
|
||||
}
|
||||
if(bottom !== curbot) {
|
||||
str += `\x1b[4${bottom === -1 ? 0 : bottom}m`;
|
||||
curbot = bottom;
|
||||
}
|
||||
str += block;
|
||||
}
|
||||
}
|
||||
if(curtop !== -1 || curbot !== -1) str += "\x1b[0m";
|
||||
for(let i of this.strs) str += fmt(i);
|
||||
process.stdout.write(str);
|
||||
if(clear) this.clear();
|
||||
}
|
||||
|
||||
clear() {
|
||||
for(let i = 0; i < this.height; i++) {
|
||||
for(let j = 0; j < this.width; j++) {
|
||||
this.buffer[i][j] = -1;
|
||||
}
|
||||
}
|
||||
while(this.strs.length) this.strs.pop();
|
||||
}
|
||||
|
||||
pixel(x, y) {
|
||||
this.buffer[y][x] = this.color;
|
||||
}
|
||||
|
||||
rect(x, y, w, h) {
|
||||
for(let i = y; i < y + h; i++) {
|
||||
for(let j = x; j < x + w; j++) {
|
||||
this.buffer[i][j] = this.color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
text(str, x, y) {
|
||||
this.strs.push({ str, x, y });
|
||||
}
|
||||
|
||||
canvas(c, x, y, flush = true) {
|
||||
for(let i = 0; i < c.height; i++) {
|
||||
for(let j = 0; j < c.width; j++) {
|
||||
if(c.buffer[i][j] !== -1) this.buffer[i + y][j + x] = c.buffer[i][j];
|
||||
}
|
||||
}
|
||||
for(let i of c.strs) this.strs.push({ str: i.str, x: i.x + x, y: i.y + y });
|
||||
if(flush) c.clear();
|
||||
}
|
||||
|
||||
get width() {
|
||||
return this.rw ? this.rw : process.stdout.columns;
|
||||
}
|
||||
|
||||
get height() {
|
||||
return this.rh ? this.rh : process.stdout.rows * 2;
|
||||
}
|
||||
|
||||
static color = Color;
|
||||
}
|
||||
|
||||
module.exports = Canvas;
|
47
input.js
Normal file
47
input.js
Normal file
|
@ -0,0 +1,47 @@
|
|||
const EventEmitter = require("events");
|
||||
const Keys = {
|
||||
up: Buffer.from([0x1B, 0x5B, 0x41]),
|
||||
down: Buffer.from([0x1B, 0x5B, 0x42]),
|
||||
right: Buffer.from([0x1B, 0x5B, 0x43]),
|
||||
left: Buffer.from([0x1B, 0x5B, 0x44]),
|
||||
left: Buffer.from([0x1B, 0x5B, 0x44]),
|
||||
tab: Buffer.from([0x07]),
|
||||
enter: Buffer.from([0x0A]),
|
||||
space: Buffer.from([0x20]),
|
||||
};
|
||||
|
||||
function isPrint(char) {
|
||||
if(char >= 'a' && char <= 'z') return true;
|
||||
if(char >= 'A' && char <= 'Z') return true;
|
||||
if(char >= '0' && char <= '9') return true;
|
||||
if(char >= '[' && char <= '_') return true;
|
||||
if(char >= '{' && char <= '~') return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
class Input extends EventEmitter {
|
||||
constructor(stream) {
|
||||
super();
|
||||
stream.on("data", this.handle.bind(this));
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
handle(data) {
|
||||
for(let i in Keys) {
|
||||
if(data.equals(Keys[i])) this.emit(i);
|
||||
}
|
||||
const key = data.toString();
|
||||
if(isPrint(key)) this.emit(key);
|
||||
this.emit("data", data);
|
||||
}
|
||||
|
||||
hijack() {
|
||||
this.stream.setRawMode(true);
|
||||
}
|
||||
|
||||
close() {
|
||||
this.stream?.setRawMode(false);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Input;
|
|
@ -34,6 +34,7 @@ function parse(route, url) {
|
|||
url = url.slice(i.length);
|
||||
} else return null;
|
||||
}
|
||||
if(url.length) return null;
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -91,7 +92,6 @@ class Server extends http.Server {
|
|||
js: "text/javascript",
|
||||
json: "application/json",
|
||||
png: "image/png",
|
||||
jpg: "image/jpeg",
|
||||
jpeg: "image/jpeg",
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue