commit 1d10420cad79c62f237d5028f376719fe98ce185 Author: Michaƫl Lemaire Date: Tue May 11 23:20:33 2021 +0200 Initial structure diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..83c1115 --- /dev/null +++ b/.editorconfig @@ -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 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d69a4c0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +deno.d.ts +.vscode +.local diff --git a/README.md b/README.md new file mode 100644 index 0000000..c56042c --- /dev/null +++ b/README.md @@ -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) diff --git a/ansi.test.ts b/ansi.test.ts new file mode 100644 index 0000000..8d51b4f --- /dev/null +++ b/ansi.test.ts @@ -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])); + }); +}); diff --git a/ansi.ts b/ansi.ts new file mode 100644 index 0000000..0e66c98 --- /dev/null +++ b/ansi.ts @@ -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 { + return colors; + } + + async clear(): Promise { + await this.writer.write(CLEAR); + } +} + +function escape(sequence: string): Uint8Array { + return new Uint8Array([0x1B, ...new TextEncoder().encode(sequence)]); +} + +const CLEAR = escape("[2J"); diff --git a/common.ts b/common.ts new file mode 100644 index 0000000..6cfe7b1 --- /dev/null +++ b/common.ts @@ -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 { + await this.display.clear(); + } +} diff --git a/demo.ts b/demo.ts new file mode 100755 index 0000000..e18dbca --- /dev/null +++ b/demo.ts @@ -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)); diff --git a/deps.test.ts b/deps.test.ts new file mode 100644 index 0000000..9d35faf --- /dev/null +++ b/deps.test.ts @@ -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"; diff --git a/deps.ts b/deps.ts new file mode 100644 index 0000000..f23b5a8 --- /dev/null +++ b/deps.ts @@ -0,0 +1 @@ +export { Sys } from "https://code.thunderk.net/typescript/devtools/raw/1.2.2/system.ts"; diff --git a/display.ts b/display.ts new file mode 100644 index 0000000..b9cf326 --- /dev/null +++ b/display.ts @@ -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; + + /** + * Clear the whole screen + */ + clear(): Promise; +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..e28737f --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "module": "esnext", + "target": "ESNext", + "strict": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "preserveConstEnums": true + } +}