Initial structure

This commit is contained in:
Michaël Lemaire 2021-05-11 23:20:33 +02:00
commit 1d10420cad
11 changed files with 121 additions and 0 deletions

9
.editorconfig Normal file
View file

@ -0,0 +1,9 @@
root = true
[*.{ts,json}]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 2
trim_trailing_whitespace = true

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
deno.d.ts
.vscode
.local

3
README.md Normal file
View file

@ -0,0 +1,3 @@
# typescript/textui
[![Build Status](https://thunderk.visualstudio.com/typescript/_apis/build/status/textui?branchName=master)](https://dev.azure.com/thunderk/typescript/_build?pipelineNameFilter=textui)

11
ansi.test.ts Normal file
View file

@ -0,0 +1,11 @@
import { AnsiTerminalDisplay } from "./ansi.ts";
import { Buffer, describe, expect, it } from "./deps.test.ts";
describe(AnsiTerminalDisplay, () => {
it("clears the screen", async () => {
const stdout = new Buffer();
const display = new AnsiTerminalDisplay(stdout);
await display.clear();
expect(stdout.bytes()).toEqual(new Uint8Array([27, 91, 50, 74]));
});
});

23
ansi.ts Normal file
View file

@ -0,0 +1,23 @@
import { Color, Display } from "./display.ts";
/**
* ANSI terminal display
*/
export class AnsiTerminalDisplay implements Display {
constructor(private writer: Deno.Writer = Deno.stdout) {
}
async setupPalette(colors: readonly Color[]): Promise<readonly Color[]> {
return colors;
}
async clear(): Promise<void> {
await this.writer.write(CLEAR);
}
}
function escape(sequence: string): Uint8Array {
return new Uint8Array([0x1B, ...new TextEncoder().encode(sequence)]);
}
const CLEAR = escape("[2J");

13
common.ts Normal file
View file

@ -0,0 +1,13 @@
import { Display } from "./display.ts";
/**
* Common abstraction for a textual UI
*/
export class TextUI {
constructor(private display: Display) {
}
async init(): Promise<void> {
await this.display.clear();
}
}

9
demo.ts Executable file
View file

@ -0,0 +1,9 @@
#!/usr/bin/env -S deno run
import { AnsiTerminalDisplay } from "./ansi.ts";
import { TextUI } from "./common.ts";
const display = new AnsiTerminalDisplay();
const ui = new TextUI(display);
await ui.init();
await new Promise((resolve) => setTimeout(resolve, 3000));

2
deps.test.ts Normal file
View file

@ -0,0 +1,2 @@
export * from "https://code.thunderk.net/typescript/devtools/raw/1.2.2/testing.ts";
export { Buffer } from "https://deno.land/std@0.96.0/io/buffer.ts";

1
deps.ts Normal file
View file

@ -0,0 +1 @@
export { Sys } from "https://code.thunderk.net/typescript/devtools/raw/1.2.2/system.ts";

37
display.ts Normal file
View file

@ -0,0 +1,37 @@
/**
* Color represented by RGB (0.0-1.0) components
*/
export type Color = {
r: number;
g: number;
b: number;
};
/**
* Displayable character, with background and foreground color taken from the palette
*/
export type Char = {
ch: string;
bg: number;
fg: number;
};
/**
* Display protocol, to allow the UI to draw things on "screen"
*/
export interface Display {
/**
* Setup the palette for color display
*
* If the display supports the whole RGB range, it may return the array as-is.
* If the display only supports a limited palette, it may return only supported colors.
*
* From this call forward, colors will be received by numbered index in the returned array.
*/
setupPalette(colors: readonly Color[]): Promise<readonly Color[]>;
/**
* Clear the whole screen
*/
clear(): Promise<void>;
}

10
tsconfig.json Normal file
View file

@ -0,0 +1,10 @@
{
"compilerOptions": {
"module": "esnext",
"target": "ESNext",
"strict": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"preserveConstEnums": true
}
}