Optimize ansi character writing

This commit is contained in:
Michaël Lemaire 2021-06-25 01:09:05 +02:00
parent b0a8e2b5b7
commit 65a06d40d4
3 changed files with 38 additions and 12 deletions

36
ansi.ts
View file

@ -7,6 +7,8 @@ import { Display } from "./display.ts";
export class AnsiTerminalDisplay implements Display {
private palette_bg: readonly Uint8Array[] = [];
private palette_fg: readonly Uint8Array[] = [];
private width = 1;
private state = { x: -1, y: -1, f: -1, b: -1 }; // current location and color
constructor(
private writer: Deno.Writer = Deno.stdout,
@ -16,6 +18,7 @@ export class AnsiTerminalDisplay implements Display {
async getSize(): Promise<BufferSize> {
const size = Deno.consoleSize(Deno.stdout.rid);
this.width = size.columns;
return {
w: size.columns,
h: size.rows,
@ -39,13 +42,32 @@ export class AnsiTerminalDisplay implements Display {
}
async setChar(at: BufferLocation, char: Char): Promise<void> {
// TODO do not move the cursor if already at good location
// TODO do not change the color if already good
const fg = this.palette_fg[char.fg];
const bg = this.palette_bg[char.bg];
await this.writer.write(fg);
await this.writer.write(bg);
await this.writer.write(escape(`[${at.y};${at.x}H${char.ch}`));
let { x, y, f, b } = this.state;
if (f != char.fg) {
f = char.fg;
await this.writer.write(this.palette_fg[f]);
}
if (b != char.bg) {
b = char.bg;
await this.writer.write(this.palette_bg[b]);
}
if (x != at.x || y != at.y) {
x = at.x;
y = at.y;
await this.writer.write(escape(`[${at.y};${at.x}H`));
}
await this.writer.write(new TextEncoder().encode(char.ch));
x += 1;
if (x > this.width) {
x = 0;
y += 1;
}
this.state = { x, y, f, b };
}
}

10
mod.ts
View file

@ -1,11 +1,15 @@
import { AnsiTerminalDisplay } from "./ansi.ts";
import { TextUI } from "./ui.ts";
import { TextUI, UIPalette } from "./ui.ts";
export { TextUI } from "./ui.ts";
export async function createTextUI(): Promise<TextUI> {
export type UIConfig = {
palette: UIPalette;
};
export async function createTextUI(config: UIConfig): Promise<TextUI> {
// TODO detect platform
var display = new AnsiTerminalDisplay();
var ui = new TextUI(display);
await ui.init();
await ui.init(config.palette);
return ui;
}

4
ui.ts
View file

@ -44,8 +44,8 @@ export class TextUI {
async flush(): Promise<void> {
// TODO only dirty chars
const { w, h } = this.screen.getSize();
for (let x = 0; x < w; x++) {
for (let y = 0; y < h; y++) {
for (let y = 0; y < h; y++) {
for (let x = 0; x < w; x++) {
await this.display.setChar({ x, y }, this.screen.get({ x, y }));
}
}