improves block functionality
adds cli compatible prompts/logs adds logfile function for debug adds multiselect support new fieldRename adds listFieldNames
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
import { log } from "util/logfile.ts";
|
||||
import { Cursor } from "./cursor.ts";
|
||||
|
||||
export class TerminalLayout {
|
||||
private static ALT_BUFFER_ENABLE = "\x1b[?1049h";
|
||||
private static ALT_BUFFER_DISABLE = "\x1b[?1049l";
|
||||
@@ -12,10 +15,16 @@ export class TerminalLayout {
|
||||
constructor() {
|
||||
Deno.stdout.writeSync(
|
||||
new TextEncoder().encode(
|
||||
TerminalLayout.ALT_BUFFER_ENABLE + TerminalLayout.CURSOR_HIDE,
|
||||
TerminalLayout.ALT_BUFFER_ENABLE,
|
||||
),
|
||||
);
|
||||
Cursor.hide();
|
||||
this.height = Deno.consoleSize().rows;
|
||||
|
||||
Deno.addSignalListener("SIGINT", () => {
|
||||
this.clearAll();
|
||||
Deno.exit(0);
|
||||
});
|
||||
}
|
||||
|
||||
register(name: string, block: TerminalBlock, fixedHeight?: number) {
|
||||
@@ -71,16 +80,25 @@ export class TerminalLayout {
|
||||
}
|
||||
|
||||
clearAll() {
|
||||
log("clearAll");
|
||||
Deno.stdout.writeSync(
|
||||
new TextEncoder().encode(
|
||||
TerminalLayout.ALT_BUFFER_DISABLE + TerminalLayout.CURSOR_SHOW,
|
||||
TerminalLayout.ALT_BUFFER_DISABLE,
|
||||
),
|
||||
);
|
||||
Cursor.show();
|
||||
for (const name of this.layoutOrder) {
|
||||
this.blocks[name].clear();
|
||||
}
|
||||
}
|
||||
|
||||
clear() {
|
||||
log("clear " + this.height);
|
||||
for (let i = 0; i < this.height; i++) {
|
||||
Deno.stdout.writeSync(new TextEncoder().encode("\x1b[2K\x1b[1E"));
|
||||
}
|
||||
}
|
||||
|
||||
get availableHeight() {
|
||||
return this.height;
|
||||
}
|
||||
@@ -96,14 +114,24 @@ export class TerminalBlock {
|
||||
private renderHeight: number = 0;
|
||||
private lastRenderRow = 1;
|
||||
|
||||
private preserveHistory = false;
|
||||
|
||||
constructor(private prepend: string = "") {}
|
||||
|
||||
setPreserveHistory(preserveHistory: boolean) {
|
||||
this.preserveHistory = preserveHistory;
|
||||
}
|
||||
|
||||
setLayout(layout: TerminalLayout) {
|
||||
this.layout = layout;
|
||||
}
|
||||
|
||||
setLines(lines: string[]) {
|
||||
this.lines = lines;
|
||||
setLines(lines: string[], range?: [number, number]) {
|
||||
if (range && this.preserveHistory) {
|
||||
this.lines.splice(range[0], range[1], ...lines);
|
||||
} else {
|
||||
this.lines = this.preserveHistory ? this.lines.concat(lines) : lines;
|
||||
}
|
||||
if (this.scrollOffset > lines.length - 1) {
|
||||
this.scrollOffset = Math.max(0, lines.length - 1);
|
||||
}
|
||||
@@ -115,6 +143,19 @@ export class TerminalBlock {
|
||||
);
|
||||
this.renderInternal();
|
||||
}
|
||||
range = [
|
||||
range?.[0] ?? this.lines.length - lines.length,
|
||||
range ? range[0] + lines.length : this.lines.length,
|
||||
];
|
||||
return range;
|
||||
}
|
||||
|
||||
append(lines: string[]) {
|
||||
this.lines.push(...lines);
|
||||
this.scrollTo(this.lines.length - 1);
|
||||
if (this.layout) {
|
||||
this.layout.requestRender();
|
||||
}
|
||||
}
|
||||
|
||||
scrollTo(offset: number) {
|
||||
@@ -144,15 +185,6 @@ export class TerminalBlock {
|
||||
|
||||
setRenderLines(lines: string[]) {
|
||||
this.renderLines = lines;
|
||||
this.renderedLineCount = lines.reduce(
|
||||
(count, line) =>
|
||||
count +
|
||||
Math.ceil(
|
||||
(this.prepend.length + line.length) /
|
||||
(Deno.consoleSize().columns || 80),
|
||||
),
|
||||
0,
|
||||
);
|
||||
}
|
||||
|
||||
setRenderHeight(height: number) {
|
||||
@@ -165,19 +197,30 @@ export class TerminalBlock {
|
||||
|
||||
renderInternal(startRow?: number) {
|
||||
this.lastRenderRow = startRow ?? this.lastRenderRow;
|
||||
this.clear();
|
||||
let output = this.renderLines.map((line) => `${this.prepend}${line}\x1b[K`)
|
||||
.join("\n");
|
||||
this.clear(); // uses old renderedLineCount
|
||||
|
||||
const outputLines = this.renderLines.map((line) =>
|
||||
`${this.prepend}${line}\x1b[K`
|
||||
);
|
||||
const output = outputLines.join("\n");
|
||||
if (startRow !== undefined) {
|
||||
const moveCursor = `\x1b[${startRow};1H`;
|
||||
output = moveCursor + output;
|
||||
Deno.stdout.writeSync(new TextEncoder().encode(moveCursor + output));
|
||||
} else {
|
||||
Deno.stdout.writeSync(new TextEncoder().encode(output));
|
||||
}
|
||||
Deno.stdout.writeSync(
|
||||
new TextEncoder().encode(output),
|
||||
|
||||
// update rendered line count *after* rendering
|
||||
this.renderedLineCount = outputLines.reduce(
|
||||
(count, line) =>
|
||||
count +
|
||||
Math.ceil((line.length) / (Deno.consoleSize().columns || 80)),
|
||||
0,
|
||||
);
|
||||
}
|
||||
|
||||
clear() {
|
||||
log(this.renderedLineCount);
|
||||
if (this.renderedLineCount === 0) return;
|
||||
const moveCursor = `\x1b[${this.lastRenderRow};1H`;
|
||||
Deno.stdout.writeSync(new TextEncoder().encode(moveCursor));
|
||||
@@ -187,6 +230,11 @@ export class TerminalBlock {
|
||||
this.renderedLineCount = 0;
|
||||
}
|
||||
|
||||
clearAll() {
|
||||
this.clear();
|
||||
this.lines = [];
|
||||
}
|
||||
|
||||
setFixedHeight(height: number) {
|
||||
this.fixedHeight = height;
|
||||
}
|
||||
|
Reference in New Issue
Block a user