@textui/terminal 0.2.0 → 0.3.0
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/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/still.d.ts +71 -0
- package/dist/still.d.ts.map +1 -0
- package/dist/still.js +29 -0
- package/package.json +2 -2
- package/src/index.ts +2 -0
- package/src/still.ts +111 -0
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ export * as ansi from './ansi.js';
|
|
|
2
2
|
export { Writer, createWriter } from './writer.js';
|
|
3
3
|
export { captureBuffer } from './capture.js';
|
|
4
4
|
export type { CaptureOptions } from './capture.js';
|
|
5
|
+
export { renderStill } from './still.js';
|
|
6
|
+
export type { Still, StillOptions } from './still.js';
|
|
5
7
|
export { bufferToSvg } from './svg.js';
|
|
6
8
|
export type { SvgOptions } from './svg.js';
|
|
7
9
|
export { detectCapabilities, detectColorDepth, detectUnicode, applyOverrides, describeEnvironment, } from './capabilities.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EACL,kBAAkB,EAAE,gBAAgB,EAAE,aAAa,EACnD,cAAc,EAAE,mBAAmB,GACpC,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACzD,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AACpE,YAAY,EAAE,kBAAkB,EAAE,aAAa,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACnG,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAC7E,YAAY,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EACL,kBAAkB,EAAE,gBAAgB,EAAE,aAAa,EACnD,cAAc,EAAE,mBAAmB,GACpC,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACzD,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AACpE,YAAY,EAAE,kBAAkB,EAAE,aAAa,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACnG,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAC7E,YAAY,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * as ansi from './ansi.js';
|
|
2
2
|
export { Writer, createWriter } from './writer.js';
|
|
3
3
|
export { captureBuffer } from './capture.js';
|
|
4
|
+
export { renderStill } from './still.js';
|
|
4
5
|
export { bufferToSvg } from './svg.js';
|
|
5
6
|
export { detectCapabilities, detectColorDepth, detectUnicode, applyOverrides, describeEnvironment, } from './capabilities.js';
|
|
6
7
|
export { InputDecoder, createDecoder } from './input.js';
|
package/dist/still.d.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { CapabilityOverrides, CellBuffer, CreateAppOptions, TextUIApp } from '@textui/core';
|
|
2
|
+
import type { CaptureOptions } from './capture.js';
|
|
3
|
+
/**
|
|
4
|
+
* One frame of an application, as text.
|
|
5
|
+
*
|
|
6
|
+
* The same application, not a second rendering path: it is mounted against a
|
|
7
|
+
* terminal that is a size and nothing else, rendered until it stops changing,
|
|
8
|
+
* and every cell it painted is what comes back. Which is what a program does
|
|
9
|
+
* when its output is a pipe rather than a screen - there is no frame after
|
|
10
|
+
* this one to correct it, so it has to be the finished picture.
|
|
11
|
+
*
|
|
12
|
+
* Every example in this repository had written this out by hand, and all of
|
|
13
|
+
* them ended the same way: a sleep loop of four milliseconds times a number
|
|
14
|
+
* somebody had tried until the picture looked right. Eight, mostly - four in
|
|
15
|
+
* one, twelve in another - for the same eight lines of setup either side. The
|
|
16
|
+
* number was the tell. Nobody knew it, a small one silently writes a
|
|
17
|
+
* half-drawn frame, and `TextUIApp.settled` is the answer they were all
|
|
18
|
+
* approximating.
|
|
19
|
+
*/
|
|
20
|
+
export interface StillOptions extends Omit<CreateAppOptions, 'terminal' | 'session'> {
|
|
21
|
+
/** Columns. The terminal is only a size, so this is the whole of it. */
|
|
22
|
+
width?: number;
|
|
23
|
+
height?: number;
|
|
24
|
+
/** What the terminal should claim to be able to do. */
|
|
25
|
+
capabilities?: CapabilityOverrides;
|
|
26
|
+
/**
|
|
27
|
+
* Drive it before the frame is taken.
|
|
28
|
+
*
|
|
29
|
+
* A still of an application in its opening state is the least interesting
|
|
30
|
+
* one. This is where a screen is pushed, a message sent, or a scripted host
|
|
31
|
+
* pumped to the point worth photographing - and it may be async, because
|
|
32
|
+
* most of those are.
|
|
33
|
+
*/
|
|
34
|
+
before?(app: TextUIApp): void | Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* The frame is drawn and the application is still alive.
|
|
37
|
+
*
|
|
38
|
+
* For what a string cannot carry and `stop` would take away: the buffer, to
|
|
39
|
+
* crop it to the rows that were used, and the theme, whose two colours are
|
|
40
|
+
* the honest background for a picture of *this* screen rather than the
|
|
41
|
+
* exporter's guess. It runs before the capture, so a buffer changed here is
|
|
42
|
+
* the buffer that comes back as `text`.
|
|
43
|
+
*/
|
|
44
|
+
after?(app: TextUIApp): void | Promise<void>;
|
|
45
|
+
/** Plain text or SGR, and at what depth. Defaults to what the terminal claims. */
|
|
46
|
+
capture?: CaptureOptions;
|
|
47
|
+
/** Settle passes before giving up. See `TextUIApp.settled`. */
|
|
48
|
+
settleLimit?: number;
|
|
49
|
+
}
|
|
50
|
+
export interface Still {
|
|
51
|
+
/** Every cell it painted, rows separated by newlines. */
|
|
52
|
+
text: string;
|
|
53
|
+
/**
|
|
54
|
+
* The cells themselves, for anything text cannot carry - `bufferToSvg`, a
|
|
55
|
+
* pixel diff, an assertion about one cell's colour. Valid after the
|
|
56
|
+
* application has stopped: nothing writes to it again.
|
|
57
|
+
*/
|
|
58
|
+
buffer: CellBuffer;
|
|
59
|
+
/**
|
|
60
|
+
* Whether it went quiet, or the limit ran out first.
|
|
61
|
+
*
|
|
62
|
+
* An application that animates settles between its frames, so this is
|
|
63
|
+
* `true` for one of those and the picture is a photograph of something
|
|
64
|
+
* moving. `false` means the passes never stopped producing work - a render
|
|
65
|
+
* loop that does not converge - and the frame was taken anyway, because a
|
|
66
|
+
* still is better evidence of that than nothing is.
|
|
67
|
+
*/
|
|
68
|
+
settled: boolean;
|
|
69
|
+
}
|
|
70
|
+
export declare function renderStill(options?: StillOptions): Promise<Still>;
|
|
71
|
+
//# sourceMappingURL=still.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"still.d.ts","sourceRoot":"","sources":["../src/still.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EAAE,UAAU,EAAE,gBAAgB,EAAE,SAAS,EAC7D,MAAM,cAAc,CAAC;AAKtB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,YAAa,SAAQ,IAAI,CAAC,gBAAgB,EAAE,UAAU,GAAG,SAAS,CAAC;IAClF,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,YAAY,CAAC,EAAE,mBAAmB,CAAC;IACnC;;;;;;;OAOG;IACH,MAAM,CAAC,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C;;;;;;;;OAQG;IACH,KAAK,CAAC,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,kFAAkF;IAClF,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,KAAK;IACpB,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,MAAM,EAAE,UAAU,CAAC;IACnB;;;;;;;;OAQG;IACH,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,wBAAsB,WAAW,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,KAAK,CAAC,CAgC5E"}
|
package/dist/still.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { WRITER_KEY, createApp } from '@textui/core';
|
|
2
|
+
import { createVirtualTerminal } from './virtual.js';
|
|
3
|
+
import { createWriter } from './writer.js';
|
|
4
|
+
import { captureBuffer } from './capture.js';
|
|
5
|
+
export async function renderStill(options = {}) {
|
|
6
|
+
const { width = 80, height = 24, capabilities, before, after, capture, settleLimit, ...app } = options;
|
|
7
|
+
const terminal = createVirtualTerminal({
|
|
8
|
+
width,
|
|
9
|
+
height,
|
|
10
|
+
...(capabilities ? { capabilities } : {}),
|
|
11
|
+
});
|
|
12
|
+
const created = createApp({ ...app, terminal });
|
|
13
|
+
// The writer is provided even though the buffer is what is read: a virtual
|
|
14
|
+
// terminal records what was written to it, and a still that quietly stopped
|
|
15
|
+
// producing that would break anything reading the bytes rather than the
|
|
16
|
+
// cells.
|
|
17
|
+
created.services.provide(WRITER_KEY, createWriter(terminal.capabilities()));
|
|
18
|
+
await created.start();
|
|
19
|
+
await before?.(created);
|
|
20
|
+
const settled = await created.settled(settleLimit === undefined ? {} : { limit: settleLimit });
|
|
21
|
+
// Even when it did not settle: the limit means "stop waiting", not "give up
|
|
22
|
+
// on the frame", and a still of a moving thing is still a still.
|
|
23
|
+
created.flush();
|
|
24
|
+
await after?.(created);
|
|
25
|
+
const text = captureBuffer(created.buffer(), terminal.capabilities(), capture ?? {});
|
|
26
|
+
const buffer = created.buffer();
|
|
27
|
+
await created.stop();
|
|
28
|
+
return { text, buffer, settled };
|
|
29
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@textui/terminal",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Terminal adapters, capability detection, ANSI writing and input decoding for TextUI",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"terminal",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"test": "vitest run"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@textui/core": "^0.
|
|
57
|
+
"@textui/core": "^0.3.0"
|
|
58
58
|
},
|
|
59
59
|
"publishConfig": {
|
|
60
60
|
"access": "public"
|
package/src/index.ts
CHANGED
|
@@ -2,6 +2,8 @@ export * as ansi from './ansi.js';
|
|
|
2
2
|
export { Writer, createWriter } from './writer.js';
|
|
3
3
|
export { captureBuffer } from './capture.js';
|
|
4
4
|
export type { CaptureOptions } from './capture.js';
|
|
5
|
+
export { renderStill } from './still.js';
|
|
6
|
+
export type { Still, StillOptions } from './still.js';
|
|
5
7
|
export { bufferToSvg } from './svg.js';
|
|
6
8
|
export type { SvgOptions } from './svg.js';
|
|
7
9
|
export {
|
package/src/still.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CapabilityOverrides, CellBuffer, CreateAppOptions, TextUIApp,
|
|
3
|
+
} from '@textui/core';
|
|
4
|
+
import { WRITER_KEY, createApp } from '@textui/core';
|
|
5
|
+
import { createVirtualTerminal } from './virtual.js';
|
|
6
|
+
import { createWriter } from './writer.js';
|
|
7
|
+
import { captureBuffer } from './capture.js';
|
|
8
|
+
import type { CaptureOptions } from './capture.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* One frame of an application, as text.
|
|
12
|
+
*
|
|
13
|
+
* The same application, not a second rendering path: it is mounted against a
|
|
14
|
+
* terminal that is a size and nothing else, rendered until it stops changing,
|
|
15
|
+
* and every cell it painted is what comes back. Which is what a program does
|
|
16
|
+
* when its output is a pipe rather than a screen - there is no frame after
|
|
17
|
+
* this one to correct it, so it has to be the finished picture.
|
|
18
|
+
*
|
|
19
|
+
* Every example in this repository had written this out by hand, and all of
|
|
20
|
+
* them ended the same way: a sleep loop of four milliseconds times a number
|
|
21
|
+
* somebody had tried until the picture looked right. Eight, mostly - four in
|
|
22
|
+
* one, twelve in another - for the same eight lines of setup either side. The
|
|
23
|
+
* number was the tell. Nobody knew it, a small one silently writes a
|
|
24
|
+
* half-drawn frame, and `TextUIApp.settled` is the answer they were all
|
|
25
|
+
* approximating.
|
|
26
|
+
*/
|
|
27
|
+
export interface StillOptions extends Omit<CreateAppOptions, 'terminal' | 'session'> {
|
|
28
|
+
/** Columns. The terminal is only a size, so this is the whole of it. */
|
|
29
|
+
width?: number;
|
|
30
|
+
height?: number;
|
|
31
|
+
/** What the terminal should claim to be able to do. */
|
|
32
|
+
capabilities?: CapabilityOverrides;
|
|
33
|
+
/**
|
|
34
|
+
* Drive it before the frame is taken.
|
|
35
|
+
*
|
|
36
|
+
* A still of an application in its opening state is the least interesting
|
|
37
|
+
* one. This is where a screen is pushed, a message sent, or a scripted host
|
|
38
|
+
* pumped to the point worth photographing - and it may be async, because
|
|
39
|
+
* most of those are.
|
|
40
|
+
*/
|
|
41
|
+
before?(app: TextUIApp): void | Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* The frame is drawn and the application is still alive.
|
|
44
|
+
*
|
|
45
|
+
* For what a string cannot carry and `stop` would take away: the buffer, to
|
|
46
|
+
* crop it to the rows that were used, and the theme, whose two colours are
|
|
47
|
+
* the honest background for a picture of *this* screen rather than the
|
|
48
|
+
* exporter's guess. It runs before the capture, so a buffer changed here is
|
|
49
|
+
* the buffer that comes back as `text`.
|
|
50
|
+
*/
|
|
51
|
+
after?(app: TextUIApp): void | Promise<void>;
|
|
52
|
+
/** Plain text or SGR, and at what depth. Defaults to what the terminal claims. */
|
|
53
|
+
capture?: CaptureOptions;
|
|
54
|
+
/** Settle passes before giving up. See `TextUIApp.settled`. */
|
|
55
|
+
settleLimit?: number;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface Still {
|
|
59
|
+
/** Every cell it painted, rows separated by newlines. */
|
|
60
|
+
text: string;
|
|
61
|
+
/**
|
|
62
|
+
* The cells themselves, for anything text cannot carry - `bufferToSvg`, a
|
|
63
|
+
* pixel diff, an assertion about one cell's colour. Valid after the
|
|
64
|
+
* application has stopped: nothing writes to it again.
|
|
65
|
+
*/
|
|
66
|
+
buffer: CellBuffer;
|
|
67
|
+
/**
|
|
68
|
+
* Whether it went quiet, or the limit ran out first.
|
|
69
|
+
*
|
|
70
|
+
* An application that animates settles between its frames, so this is
|
|
71
|
+
* `true` for one of those and the picture is a photograph of something
|
|
72
|
+
* moving. `false` means the passes never stopped producing work - a render
|
|
73
|
+
* loop that does not converge - and the frame was taken anyway, because a
|
|
74
|
+
* still is better evidence of that than nothing is.
|
|
75
|
+
*/
|
|
76
|
+
settled: boolean;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export async function renderStill(options: StillOptions = {}): Promise<Still> {
|
|
80
|
+
const {
|
|
81
|
+
width = 80, height = 24, capabilities, before, after, capture, settleLimit, ...app
|
|
82
|
+
} = options;
|
|
83
|
+
|
|
84
|
+
const terminal = createVirtualTerminal({
|
|
85
|
+
width,
|
|
86
|
+
height,
|
|
87
|
+
...(capabilities ? { capabilities } : {}),
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const created = createApp({ ...app, terminal });
|
|
91
|
+
// The writer is provided even though the buffer is what is read: a virtual
|
|
92
|
+
// terminal records what was written to it, and a still that quietly stopped
|
|
93
|
+
// producing that would break anything reading the bytes rather than the
|
|
94
|
+
// cells.
|
|
95
|
+
created.services.provide(WRITER_KEY, createWriter(terminal.capabilities()));
|
|
96
|
+
|
|
97
|
+
await created.start();
|
|
98
|
+
await before?.(created);
|
|
99
|
+
|
|
100
|
+
const settled = await created.settled(settleLimit === undefined ? {} : { limit: settleLimit });
|
|
101
|
+
// Even when it did not settle: the limit means "stop waiting", not "give up
|
|
102
|
+
// on the frame", and a still of a moving thing is still a still.
|
|
103
|
+
created.flush();
|
|
104
|
+
await after?.(created);
|
|
105
|
+
|
|
106
|
+
const text = captureBuffer(created.buffer(), terminal.capabilities(), capture ?? {});
|
|
107
|
+
const buffer = created.buffer();
|
|
108
|
+
await created.stop();
|
|
109
|
+
|
|
110
|
+
return { text, buffer, settled };
|
|
111
|
+
}
|