@travetto/terminal 4.0.0-rc.6 → 4.0.0-rc.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/terminal.ts +2 -15
- package/src/util.ts +2 -2
- package/src/writer.ts +23 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/terminal",
|
|
3
|
-
"version": "4.0.0-rc.
|
|
3
|
+
"version": "4.0.0-rc.7",
|
|
4
4
|
"description": "General terminal support",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"terminal",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"directory": "module/terminal"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@travetto/base": "^4.0.0-rc.
|
|
27
|
+
"@travetto/base": "^4.0.0-rc.7",
|
|
28
28
|
"chalk": "^4.1.2"
|
|
29
29
|
},
|
|
30
30
|
"travetto": {
|
package/src/terminal.ts
CHANGED
|
@@ -19,7 +19,6 @@ export class Terminal {
|
|
|
19
19
|
|
|
20
20
|
#interactive: boolean;
|
|
21
21
|
#writer: TerminalWriter;
|
|
22
|
-
#cleanExit = 0;
|
|
23
22
|
#width: number;
|
|
24
23
|
#height: number;
|
|
25
24
|
#output: tty.WriteStream;
|
|
@@ -34,14 +33,6 @@ export class Terminal {
|
|
|
34
33
|
}
|
|
35
34
|
}
|
|
36
35
|
|
|
37
|
-
#cleanOnExit(): () => void {
|
|
38
|
-
if (this.#cleanExit === 0) {
|
|
39
|
-
process.on('exit', TerminalWriter.reset);
|
|
40
|
-
}
|
|
41
|
-
this.#cleanExit += 1;
|
|
42
|
-
return () => (this.#cleanExit -= 1) === 0 && process.off('exit', TerminalWriter.reset);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
36
|
constructor(output?: tty.WriteStream, config?: { width?: number, height?: number }) {
|
|
46
37
|
this.#output = output ?? process.stdout;
|
|
47
38
|
this.#interactive = this.#output.isTTY && !Env.TRV_QUIET.isTrue;
|
|
@@ -77,7 +68,6 @@ export class Terminal {
|
|
|
77
68
|
async streamToBottom(source: AsyncIterable<string | undefined>, config: TerminalStreamingConfig = {}): Promise<void> {
|
|
78
69
|
const writePos = { x: 0, y: -1 };
|
|
79
70
|
const minDelay = config.minDelay ?? 0;
|
|
80
|
-
const remove = this.#cleanOnExit();
|
|
81
71
|
|
|
82
72
|
let prev: string | undefined;
|
|
83
73
|
let stop: AbortController | undefined;
|
|
@@ -117,8 +107,7 @@ export class Terminal {
|
|
|
117
107
|
|
|
118
108
|
await this.#writer.setPosition(writePos).clearLine().commit(true);
|
|
119
109
|
} finally {
|
|
120
|
-
await this.#writer.
|
|
121
|
-
remove();
|
|
110
|
+
await this.#writer.reset().commit();
|
|
122
111
|
}
|
|
123
112
|
}
|
|
124
113
|
|
|
@@ -137,7 +126,6 @@ export class Terminal {
|
|
|
137
126
|
return;
|
|
138
127
|
}
|
|
139
128
|
|
|
140
|
-
const remove = this.#cleanOnExit();
|
|
141
129
|
let max = 0;
|
|
142
130
|
try {
|
|
143
131
|
await this.#writer.hideCursor().commit();
|
|
@@ -146,8 +134,7 @@ export class Terminal {
|
|
|
146
134
|
await this.#writer.write('\n'.repeat(idx)).setPosition({ x: 0 }).write(text).clearLine(1).changePosition({ y: -idx }).commit();
|
|
147
135
|
}
|
|
148
136
|
} finally {
|
|
149
|
-
await this.#writer.changePosition({ y: max + 1 }).writeLine('\n').
|
|
150
|
-
remove();
|
|
137
|
+
await this.#writer.changePosition({ y: max + 1 }).writeLine('\n').reset().commit();
|
|
151
138
|
}
|
|
152
139
|
}
|
|
153
140
|
}
|
package/src/util.ts
CHANGED
|
@@ -17,7 +17,7 @@ export class TerminalUtil {
|
|
|
17
17
|
}
|
|
18
18
|
): (ev: ProgressEvent<string>) => string {
|
|
19
19
|
const styleBase = typeof cfg?.style !== 'function' ? {
|
|
20
|
-
complete: StyleUtil.getStyle(cfg?.style?.complete ?? { background: '#
|
|
20
|
+
complete: StyleUtil.getStyle(cfg?.style?.complete ?? { background: '#248613', text: '#ffffff' }),
|
|
21
21
|
incomplete: cfg?.style?.incomplete ? StyleUtil.getStyle(cfg.style.incomplete) : undefined,
|
|
22
22
|
} : undefined;
|
|
23
23
|
|
|
@@ -31,7 +31,7 @@ export class TerminalUtil {
|
|
|
31
31
|
width ??= Math.trunc(Math.ceil(Math.log10(ev.total ?? 10000)));
|
|
32
32
|
}
|
|
33
33
|
const state: Record<string, string> = { total: `${ev.total}`, idx: `${ev.idx}`.padStart(width ?? 0), pct: `${Math.trunc(pct * 100)}` };
|
|
34
|
-
const line = text.replace(/[%](idx|total|pct)/g, (_, k) => state[k])
|
|
34
|
+
const line = ` ${text.replace(/[%](idx|total|pct)/g, (_, k) => state[k])} `;
|
|
35
35
|
const full = term.writer.padToWidth(line, cfg?.withWaiting ? 2 : 0);
|
|
36
36
|
const mid = Math.trunc(pct * term.width);
|
|
37
37
|
const [l, r] = [full.substring(0, mid), full.substring(mid)];
|
package/src/writer.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import tty from 'node:tty';
|
|
2
2
|
|
|
3
|
+
import { ShutdownManager } from '@travetto/base';
|
|
4
|
+
|
|
3
5
|
type State = { output: tty.WriteStream, height: number, width: number };
|
|
4
6
|
type TermCoord = { x: number, y: number };
|
|
5
7
|
|
|
@@ -31,20 +33,31 @@ const Codes = {
|
|
|
31
33
|
* Buffered/batched writer. Meant to be similar to readline.Readline, but with more general writing support and extensibility
|
|
32
34
|
*/
|
|
33
35
|
export class TerminalWriter {
|
|
34
|
-
|
|
35
|
-
static reset(): void {
|
|
36
|
-
process.stdout.isTTY && process.stdout.write(Codes.SOFT_RESET);
|
|
37
|
-
process.stderr.isTTY && process.stderr.write(Codes.SOFT_RESET);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
36
|
#buffer: (string | number)[] = [];
|
|
41
37
|
#restoreOnCommit = false;
|
|
42
38
|
#term: State;
|
|
39
|
+
#cleanup: (() => undefined) | undefined;
|
|
43
40
|
|
|
44
41
|
constructor(state: State) {
|
|
45
42
|
this.#term = state;
|
|
46
43
|
}
|
|
47
44
|
|
|
45
|
+
/** Track dirty state for the stream */
|
|
46
|
+
trackDirty(on: boolean): this {
|
|
47
|
+
const output = this.#term.output;
|
|
48
|
+
if (output.isTTY) {
|
|
49
|
+
if (on && !this.#cleanup) {
|
|
50
|
+
const exit = (): Promise<void> => this.reset().commit(false);
|
|
51
|
+
const free = ShutdownManager.onGracefulShutdown(exit);
|
|
52
|
+
process.on('exit', exit);
|
|
53
|
+
this.#cleanup = (): undefined => { free(); process.off('exit', exit); };
|
|
54
|
+
} else if (!on) {
|
|
55
|
+
this.#cleanup = this.#cleanup?.();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return this;
|
|
59
|
+
}
|
|
60
|
+
|
|
48
61
|
/** Pad to width of terminal */
|
|
49
62
|
padToWidth(text: string, offset = 0, ellipsis = '...'): string {
|
|
50
63
|
if (text.length > (this.#term.width - offset)) {
|
|
@@ -132,12 +145,12 @@ export class TerminalWriter {
|
|
|
132
145
|
|
|
133
146
|
/** Hide cursor */
|
|
134
147
|
hideCursor(): this {
|
|
135
|
-
return this.write(Codes.HIDE_CURSOR);
|
|
148
|
+
return this.trackDirty(true).write(Codes.HIDE_CURSOR);
|
|
136
149
|
}
|
|
137
150
|
|
|
138
151
|
/** Set scrolling range */
|
|
139
152
|
scrollRange({ start = 0, end = -1 }: { start?: number, end?: number }): this {
|
|
140
|
-
return this.write(Codes.SCROLL_RANGE_SET(start, end, this.#term.height));
|
|
153
|
+
return this.trackDirty(true).write(Codes.SCROLL_RANGE_SET(start, end, this.#term.height));
|
|
141
154
|
}
|
|
142
155
|
|
|
143
156
|
/** Clear scrolling range */
|
|
@@ -146,7 +159,7 @@ export class TerminalWriter {
|
|
|
146
159
|
}
|
|
147
160
|
|
|
148
161
|
/** Reset */
|
|
149
|
-
|
|
150
|
-
return this.write(Codes.SOFT_RESET);
|
|
162
|
+
reset(): this {
|
|
163
|
+
return this.trackDirty(false).write(Codes.SOFT_RESET).write(Codes.SHOW_CURSOR);
|
|
151
164
|
}
|
|
152
165
|
}
|