@sagmans/dsh-tui 0.4.0 → 0.5.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/LICENSE +1 -1
- package/README.md +270 -68
- package/lib/agent/present.js +1 -1
- package/lib/agent/present.js.map +1 -1
- package/lib/agent/prompt-history.d.ts.map +1 -1
- package/lib/agent/prompt-history.js +5 -3
- package/lib/agent/prompt-history.js.map +1 -1
- package/lib/agent/status.d.ts +1 -1
- package/lib/cards.d.ts +83 -13
- package/lib/cards.d.ts.map +1 -1
- package/lib/cards.js +96 -28
- package/lib/cards.js.map +1 -1
- package/lib/export.d.ts +3 -3
- package/lib/export.d.ts.map +1 -1
- package/lib/export.js +23 -13
- package/lib/export.js.map +1 -1
- package/lib/fold-cursor.d.ts +12 -5
- package/lib/fold-cursor.d.ts.map +1 -1
- package/lib/fold-cursor.js +16 -5
- package/lib/fold-cursor.js.map +1 -1
- package/lib/gates.d.ts.map +1 -1
- package/lib/gates.js +42 -9
- package/lib/gates.js.map +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +459 -72
- package/lib/index.js.map +1 -1
- package/lib/injection.d.ts +9 -0
- package/lib/injection.d.ts.map +1 -0
- package/lib/injection.js +128 -0
- package/lib/injection.js.map +1 -0
- package/lib/input/actions.d.ts +19 -2
- package/lib/input/actions.d.ts.map +1 -1
- package/lib/input/actions.js +57 -11
- package/lib/input/actions.js.map +1 -1
- package/lib/input/cancel.d.ts +55 -0
- package/lib/input/cancel.d.ts.map +1 -0
- package/lib/input/cancel.js +47 -0
- package/lib/input/cancel.js.map +1 -0
- package/lib/input/completion.d.ts +5 -2
- package/lib/input/completion.d.ts.map +1 -1
- package/lib/input/completion.js +79 -4
- package/lib/input/completion.js.map +1 -1
- package/lib/input/file-search.d.ts +105 -0
- package/lib/input/file-search.d.ts.map +1 -0
- package/lib/input/file-search.js +665 -0
- package/lib/input/file-search.js.map +1 -0
- package/lib/input/fuzzy.d.ts +42 -0
- package/lib/input/fuzzy.d.ts.map +1 -0
- package/lib/input/fuzzy.js +289 -0
- package/lib/input/fuzzy.js.map +1 -0
- package/lib/input/keymap.d.ts +3 -1
- package/lib/input/keymap.d.ts.map +1 -1
- package/lib/input/keymap.js +14 -3
- package/lib/input/keymap.js.map +1 -1
- package/lib/input/match.d.ts +12 -4
- package/lib/input/match.d.ts.map +1 -1
- package/lib/input/match.js +50 -51
- package/lib/input/match.js.map +1 -1
- package/lib/input/submission.d.ts +10 -0
- package/lib/input/submission.d.ts.map +1 -1
- package/lib/input/submission.js +7 -6
- package/lib/input/submission.js.map +1 -1
- package/lib/keys-command.d.ts +19 -3
- package/lib/keys-command.d.ts.map +1 -1
- package/lib/keys-command.js +34 -31
- package/lib/keys-command.js.map +1 -1
- package/lib/settings-notice.d.ts +5 -0
- package/lib/settings-notice.d.ts.map +1 -1
- package/lib/settings-notice.js +9 -7
- package/lib/settings-notice.js.map +1 -1
- package/lib/stash/paths.d.ts +8 -8
- package/lib/stash/paths.d.ts.map +1 -1
- package/lib/stash/paths.js +19 -18
- package/lib/stash/paths.js.map +1 -1
- package/lib/stash/schema.d.ts +11 -12
- package/lib/stash/schema.d.ts.map +1 -1
- package/lib/stash/schema.js +10 -29
- package/lib/stash/schema.js.map +1 -1
- package/lib/stash/store.js +10 -10
- package/lib/stash/store.js.map +1 -1
- package/lib/stash.d.ts +37 -6
- package/lib/stash.d.ts.map +1 -1
- package/lib/stash.js +93 -36
- package/lib/stash.js.map +1 -1
- package/lib/terminal/external-editor.d.ts +93 -0
- package/lib/terminal/external-editor.d.ts.map +1 -0
- package/lib/terminal/external-editor.js +263 -0
- package/lib/terminal/external-editor.js.map +1 -0
- package/lib/terminal/host-writes.d.ts +39 -0
- package/lib/terminal/host-writes.d.ts.map +1 -0
- package/lib/terminal/host-writes.js +136 -0
- package/lib/terminal/host-writes.js.map +1 -0
- package/lib/terminal/signals.d.ts +25 -0
- package/lib/terminal/signals.d.ts.map +1 -0
- package/lib/terminal/signals.js +39 -0
- package/lib/terminal/signals.js.map +1 -0
- package/lib/terminal/warning-screen.d.ts +19 -1
- package/lib/terminal/warning-screen.d.ts.map +1 -1
- package/lib/terminal/warning-screen.js +37 -1
- package/lib/terminal/warning-screen.js.map +1 -1
- package/lib/terminal-text.d.ts +72 -0
- package/lib/terminal-text.d.ts.map +1 -0
- package/lib/terminal-text.js +603 -0
- package/lib/terminal-text.js.map +1 -0
- package/lib/text.d.ts +45 -6
- package/lib/text.d.ts.map +1 -1
- package/lib/text.js +106 -46
- package/lib/text.js.map +1 -1
- package/lib/theme-command.d.ts +7 -4
- package/lib/theme-command.d.ts.map +1 -1
- package/lib/theme-command.js +32 -12
- package/lib/theme-command.js.map +1 -1
- package/lib/theme-files.d.ts +110 -0
- package/lib/theme-files.d.ts.map +1 -0
- package/lib/theme-files.js +352 -0
- package/lib/theme-files.js.map +1 -0
- package/lib/theme-schema.d.ts +121 -0
- package/lib/theme-schema.d.ts.map +1 -0
- package/lib/theme-schema.js +87 -0
- package/lib/theme-schema.js.map +1 -0
- package/lib/theme-settings.d.ts +43 -10
- package/lib/theme-settings.d.ts.map +1 -1
- package/lib/theme-settings.js +103 -43
- package/lib/theme-settings.js.map +1 -1
- package/lib/theme-tokens.d.ts +39 -7
- package/lib/theme-tokens.d.ts.map +1 -1
- package/lib/theme-tokens.js +96 -13
- package/lib/theme-tokens.js.map +1 -1
- package/lib/theme.d.ts +24 -2
- package/lib/theme.d.ts.map +1 -1
- package/lib/theme.js +49 -6
- package/lib/theme.js.map +1 -1
- package/lib/tool-display.d.ts +57 -0
- package/lib/tool-display.d.ts.map +1 -0
- package/lib/tool-display.js +51 -0
- package/lib/tool-display.js.map +1 -0
- package/lib/transcript.d.ts +28 -0
- package/lib/transcript.d.ts.map +1 -1
- package/lib/transcript.js +126 -37
- package/lib/transcript.js.map +1 -1
- package/lib/ui/diff.d.ts +49 -0
- package/lib/ui/diff.d.ts.map +1 -0
- package/lib/ui/diff.js +208 -0
- package/lib/ui/diff.js.map +1 -0
- package/lib/ui/dock.d.ts.map +1 -1
- package/lib/ui/dock.js +9 -6
- package/lib/ui/dock.js.map +1 -1
- package/lib/ui/editor.d.ts.map +1 -1
- package/lib/ui/editor.js +4 -2
- package/lib/ui/editor.js.map +1 -1
- package/lib/ui/frame.d.ts +16 -5
- package/lib/ui/frame.d.ts.map +1 -1
- package/lib/ui/frame.js +32 -13
- package/lib/ui/frame.js.map +1 -1
- package/lib/ui/keymap-picker.d.ts +16 -0
- package/lib/ui/keymap-picker.d.ts.map +1 -0
- package/lib/ui/keymap-picker.js +41 -0
- package/lib/ui/keymap-picker.js.map +1 -0
- package/lib/ui/layout.d.ts +33 -0
- package/lib/ui/layout.d.ts.map +1 -0
- package/lib/ui/layout.js +33 -0
- package/lib/ui/layout.js.map +1 -0
- package/lib/ui/markdown.d.ts +25 -3
- package/lib/ui/markdown.d.ts.map +1 -1
- package/lib/ui/markdown.js +12 -8
- package/lib/ui/markdown.js.map +1 -1
- package/lib/ui/picker-card.d.ts +42 -0
- package/lib/ui/picker-card.d.ts.map +1 -0
- package/lib/ui/picker-card.js +148 -0
- package/lib/ui/picker-card.js.map +1 -0
- package/lib/ui/picker.d.ts +40 -2
- package/lib/ui/picker.d.ts.map +1 -1
- package/lib/ui/picker.js +50 -6
- package/lib/ui/picker.js.map +1 -1
- package/lib/ui/prompt.d.ts +10 -2
- package/lib/ui/prompt.d.ts.map +1 -1
- package/lib/ui/prompt.js +21 -2
- package/lib/ui/prompt.js.map +1 -1
- package/lib/ui/rows.d.ts +8 -6
- package/lib/ui/rows.d.ts.map +1 -1
- package/lib/ui/rows.js +10 -18
- package/lib/ui/rows.js.map +1 -1
- package/lib/ui/stash-picker.d.ts +2 -2
- package/lib/ui/stash-picker.d.ts.map +1 -1
- package/lib/ui/stash-picker.js +4 -4
- package/lib/ui/stash-picker.js.map +1 -1
- package/lib/ui/status.d.ts.map +1 -1
- package/lib/ui/status.js +18 -16
- package/lib/ui/status.js.map +1 -1
- package/lib/ui/theme-picker.d.ts +18 -0
- package/lib/ui/theme-picker.d.ts.map +1 -0
- package/lib/ui/theme-picker.js +68 -0
- package/lib/ui/theme-picker.js.map +1 -0
- package/lib/ui/view.d.ts +146 -22
- package/lib/ui/view.d.ts.map +1 -1
- package/lib/ui/view.js +461 -154
- package/lib/ui/view.js.map +1 -1
- package/package.json +3 -1
- package/themes/deepseek-blue.yaml +183 -0
- package/themes/violet-orbit.yaml +178 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Restore the terminal when the process is asked to end from outside.
|
|
3
|
+
*
|
|
4
|
+
* The surface owns the alternate screen and nothing else puts it back: a SIGTERM
|
|
5
|
+
* from a supervisor, a SIGHUP when a window closes, or a SIGQUIT all end a
|
|
6
|
+
* process by default, leaving the reader on a screen no shell prompt is drawn
|
|
7
|
+
* in. These handlers run the same shutdown a quit key runs, then leave with the
|
|
8
|
+
* status a shell reports for the signal.
|
|
9
|
+
*/
|
|
10
|
+
/** Signals whose default action ends the process without unwinding the surface. */
|
|
11
|
+
export const TERMINATING_SIGNALS = ['SIGINT', 'SIGTERM', 'SIGHUP', 'SIGQUIT'];
|
|
12
|
+
/** The status a shell reports for a process ended by one of those signals. */
|
|
13
|
+
const SIGNAL_EXIT = { SIGINT: 130, SIGTERM: 143, SIGHUP: 129, SIGQUIT: 131 };
|
|
14
|
+
/**
|
|
15
|
+
* Run a shutdown once for the first terminating signal, then leave.
|
|
16
|
+
*
|
|
17
|
+
* The listener removes itself before the shutdown runs, so a slow shutdown
|
|
18
|
+
* cannot be re-entered by a second signal; the status is the one a shell expects
|
|
19
|
+
* for the signal, so whatever was supervising the process sees an interrupted
|
|
20
|
+
* run rather than a clean one.
|
|
21
|
+
*/
|
|
22
|
+
export function installSignalRestore(options) {
|
|
23
|
+
const handlers = new Map();
|
|
24
|
+
const remove = () => {
|
|
25
|
+
for (const [signal, handler] of handlers)
|
|
26
|
+
process.removeListener(signal, handler);
|
|
27
|
+
handlers.clear();
|
|
28
|
+
};
|
|
29
|
+
for (const signal of options.signals ?? TERMINATING_SIGNALS) {
|
|
30
|
+
const handler = () => {
|
|
31
|
+
remove();
|
|
32
|
+
options.shutdown(SIGNAL_EXIT[signal], signal);
|
|
33
|
+
};
|
|
34
|
+
process.on(signal, handler);
|
|
35
|
+
handlers.set(signal, handler);
|
|
36
|
+
}
|
|
37
|
+
return remove;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=signals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signals.js","sourceRoot":"","sources":["../../src/terminal/signals.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,mFAAmF;AACnF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAU,CAAA;AAItF,8EAA8E;AAC9E,MAAM,WAAW,GAAsC,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,CAAA;AAE/G;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAGpC;IACC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAiC,CAAA;IACzD,MAAM,MAAM,GAAG,GAAS,EAAE;QACxB,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,QAAQ;YAAE,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QACjF,QAAQ,CAAC,KAAK,EAAE,CAAA;IAClB,CAAC,CAAA;IACD,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,OAAO,IAAI,mBAAmB,EAAE,CAAC;QAC5D,MAAM,OAAO,GAAG,GAAS,EAAE;YACzB,MAAM,EAAE,CAAA;YACR,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAA;QAC/C,CAAC,CAAA;QACD,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAC3B,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC/B,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC"}
|
|
@@ -1,8 +1,26 @@
|
|
|
1
1
|
import { TuiAltScreen, type TuiStopOptions } from '@earendil-works/pi-tui';
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* Terminal safety follows screen ownership, including partial startup and
|
|
4
|
+
* repeated disposal: warnings wait for the shell, the host's own writing waits
|
|
5
|
+
* with them, and a frame that cannot be drawn keeps the last good screen.
|
|
6
|
+
*/
|
|
3
7
|
export declare class WarningSafeTui extends TuiAltScreen {
|
|
4
8
|
private releaseWarnings;
|
|
9
|
+
private hostWrites;
|
|
10
|
+
private frameFailed;
|
|
11
|
+
/** Told once when a frame could not be drawn, so the surface can report it. */
|
|
12
|
+
onFrameError: ((error: unknown) => void) | undefined;
|
|
5
13
|
start(): void;
|
|
14
|
+
/**
|
|
15
|
+
* Draw a frame, keeping the last good one when drawing fails.
|
|
16
|
+
*
|
|
17
|
+
* A frame is composed before it is written, so a component that throws leaves
|
|
18
|
+
* the previous screen intact; without this the throw would reach the timer that
|
|
19
|
+
* asked for the frame, end the process, and take the terminal down with it.
|
|
20
|
+
* The first failure is reported and later ones stay silent: a repaint a broken
|
|
21
|
+
* component fails again is the same news, and repeating it would only loop.
|
|
22
|
+
*/
|
|
23
|
+
doRender(): void;
|
|
6
24
|
stop(options?: TuiStopOptions): void;
|
|
7
25
|
}
|
|
8
26
|
//# sourceMappingURL=warning-screen.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"warning-screen.d.ts","sourceRoot":"","sources":["../../src/terminal/warning-screen.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"warning-screen.d.ts","sourceRoot":"","sources":["../../src/terminal/warning-screen.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAoC1E;;;;GAIG;AACH,qBAAa,cAAe,SAAQ,YAAY;IAC9C,OAAO,CAAC,eAAe,CAA0B;IACjD,OAAO,CAAC,UAAU,CAA4B;IAC9C,OAAO,CAAC,WAAW,CAAQ;IAE3B,+EAA+E;IAC/E,YAAY,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IAE3C,KAAK,IAAI,IAAI;IAWtB;;;;;;;;OAQG;IACM,QAAQ,IAAI,IAAI;IAUhB,IAAI,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,IAAI;CAmB9C"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { TuiAltScreen } from '@earendil-works/pi-tui';
|
|
2
|
+
import { holdHostWrites, HOST_WRITE_TARGETS } from "./host-writes.js";
|
|
2
3
|
const WARNING_EVENT = 'warning';
|
|
3
4
|
const RESTORE_SHELL = '\x1b[?1049l\x1b[0m\x1b[?7h\x1b[?25h';
|
|
4
5
|
/** Node's default warning listener writes outside the renderer, so delivery must wait for the shell. */
|
|
@@ -34,11 +35,20 @@ function deferWarnings() {
|
|
|
34
35
|
throw failures[0];
|
|
35
36
|
};
|
|
36
37
|
}
|
|
37
|
-
/**
|
|
38
|
+
/**
|
|
39
|
+
* Terminal safety follows screen ownership, including partial startup and
|
|
40
|
+
* repeated disposal: warnings wait for the shell, the host's own writing waits
|
|
41
|
+
* with them, and a frame that cannot be drawn keeps the last good screen.
|
|
42
|
+
*/
|
|
38
43
|
export class WarningSafeTui extends TuiAltScreen {
|
|
39
44
|
releaseWarnings;
|
|
45
|
+
hostWrites;
|
|
46
|
+
frameFailed = false;
|
|
47
|
+
/** Told once when a frame could not be drawn, so the surface can report it. */
|
|
48
|
+
onFrameError;
|
|
40
49
|
start() {
|
|
41
50
|
this.releaseWarnings ??= deferWarnings();
|
|
51
|
+
this.hostWrites ??= holdHostWrites({ terminal: this.terminal, targets: HOST_WRITE_TARGETS });
|
|
42
52
|
try {
|
|
43
53
|
super.start();
|
|
44
54
|
}
|
|
@@ -47,6 +57,26 @@ export class WarningSafeTui extends TuiAltScreen {
|
|
|
47
57
|
throw error;
|
|
48
58
|
}
|
|
49
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Draw a frame, keeping the last good one when drawing fails.
|
|
62
|
+
*
|
|
63
|
+
* A frame is composed before it is written, so a component that throws leaves
|
|
64
|
+
* the previous screen intact; without this the throw would reach the timer that
|
|
65
|
+
* asked for the frame, end the process, and take the terminal down with it.
|
|
66
|
+
* The first failure is reported and later ones stay silent: a repaint a broken
|
|
67
|
+
* component fails again is the same news, and repeating it would only loop.
|
|
68
|
+
*/
|
|
69
|
+
doRender() {
|
|
70
|
+
try {
|
|
71
|
+
super.doRender();
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
if (this.frameFailed)
|
|
75
|
+
return;
|
|
76
|
+
this.frameFailed = true;
|
|
77
|
+
this.onFrameError?.(error);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
50
80
|
stop(options) {
|
|
51
81
|
try {
|
|
52
82
|
super.stop(options);
|
|
@@ -57,9 +87,15 @@ export class WarningSafeTui extends TuiAltScreen {
|
|
|
57
87
|
throw error;
|
|
58
88
|
}
|
|
59
89
|
finally {
|
|
90
|
+
// Warnings go first, while the hold is still in place, so what they print
|
|
91
|
+
// joins the host text in the order it arrived; the release then writes it
|
|
92
|
+
// all out behind the exit sequence this call already wrote.
|
|
60
93
|
const release = this.releaseWarnings;
|
|
61
94
|
this.releaseWarnings = undefined;
|
|
62
95
|
release?.();
|
|
96
|
+
const writes = this.hostWrites;
|
|
97
|
+
this.hostWrites = undefined;
|
|
98
|
+
writes?.release();
|
|
63
99
|
}
|
|
64
100
|
}
|
|
65
101
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"warning-screen.js","sourceRoot":"","sources":["../../src/terminal/warning-screen.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAuB,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"warning-screen.js","sourceRoot":"","sources":["../../src/terminal/warning-screen.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal text, read the way a terminal would read it.
|
|
3
|
+
*
|
|
4
|
+
* Tool output, file content, and model text all reach the screen, and this
|
|
5
|
+
* module is the only place that decides what a control byte means. It offers
|
|
6
|
+
* two policies over one token stream, so they can never disagree about where a
|
|
7
|
+
* sequence ends:
|
|
8
|
+
*
|
|
9
|
+
* - {@link renderTerminalText} draws what the terminal would have drawn: a
|
|
10
|
+
* whitelisted SGR subset becomes real colour at the session's colour budget,
|
|
11
|
+
* a tab lands on its stop, a carriage return repaints the row it sits on, and
|
|
12
|
+
* every sequence a terminal would *act* on is consumed, so it acts on
|
|
13
|
+
* nothing. Bytes that are not a sequence are still spelled out rather than
|
|
14
|
+
* dropped, because silently swallowing text would hide what a tool said.
|
|
15
|
+
* - {@link escapeTerminalText} is for text a buffer or a file will hold: every
|
|
16
|
+
* control character is spelled out, because an editor cannot draw an escape
|
|
17
|
+
* and must not execute one.
|
|
18
|
+
*
|
|
19
|
+
* Sharing one scanner matters for more than agreement: pi-tui's own escape
|
|
20
|
+
* scanner recognises less than a terminal does (a `\x1b[?25l` left in a drawn
|
|
21
|
+
* string would make its width arithmetic swallow the text after it), so a
|
|
22
|
+
* sequence that is not SGR must be gone before any width is measured.
|
|
23
|
+
*/
|
|
24
|
+
import { type ColourMode } from './theme-capability.ts';
|
|
25
|
+
/** Columns between tab stops: the POSIX default, and what every terminal still uses. */
|
|
26
|
+
export declare const TAB_STOP = 8;
|
|
27
|
+
/** Whether a tab is drawn on its stop, or kept for a buffer that will hold it. */
|
|
28
|
+
export type TabPolicy = 'expand' | 'keep';
|
|
29
|
+
export interface EscapeTextOptions {
|
|
30
|
+
/** The column the text starts at, so its first tab lands on the terminal's next stop. */
|
|
31
|
+
readonly column?: number | undefined;
|
|
32
|
+
readonly tab?: TabPolicy | undefined;
|
|
33
|
+
}
|
|
34
|
+
export interface RenderTextOptions {
|
|
35
|
+
/** The colour budget the session has; `none` drops tool styling entirely. */
|
|
36
|
+
readonly color: ColourMode;
|
|
37
|
+
/** SGR already in effect — an element's own colour, which a foreign reset returns to. */
|
|
38
|
+
readonly base?: string | undefined;
|
|
39
|
+
readonly column?: number | undefined;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Spell every control character, expanding a tab to the stop the terminal would
|
|
43
|
+
* have used.
|
|
44
|
+
*
|
|
45
|
+
* The column is what makes a tab land where it landed for the tool that wrote
|
|
46
|
+
* it: a row indented by four columns reaches its stop four columns later than
|
|
47
|
+
* the same row at the left edge.
|
|
48
|
+
*/
|
|
49
|
+
export declare function escapeTerminalText(raw: string, options?: EscapeTextOptions): string;
|
|
50
|
+
/**
|
|
51
|
+
* Draw text as the terminal that produced it would have drawn it.
|
|
52
|
+
*
|
|
53
|
+
* A carriage return repaints the row from the column the fragment starts at
|
|
54
|
+
* and a backspace moves one column left, so a progress bar collapses to the
|
|
55
|
+
* state it settled on instead of showing every repaint in a row. That starting
|
|
56
|
+
* column is also a left margin: a row indented by the layout cannot be repainted
|
|
57
|
+
* by the text it holds, which is the one thing a carriage return could
|
|
58
|
+
* otherwise do to the frame. Styling is kept per cell, so what survives a
|
|
59
|
+
* repaint keeps the colour it was written with.
|
|
60
|
+
*/
|
|
61
|
+
export declare function renderTerminalText(raw: string, options: RenderTextOptions): string;
|
|
62
|
+
/**
|
|
63
|
+
* Cut text to a budget of the characters a reader sees.
|
|
64
|
+
*
|
|
65
|
+
* Sequences are not content: counting them would let a coloured row lose its
|
|
66
|
+
* words sooner than a plain one, and cutting through one would leave a half
|
|
67
|
+
* sequence for a renderer to guess at. The cut falls between grapheme clusters
|
|
68
|
+
* for the same reason every other cut in the surface does — half a joined emoji
|
|
69
|
+
* is the same glitch as half a colour code.
|
|
70
|
+
*/
|
|
71
|
+
export declare function clipVisibleGraphemes(raw: string, limit: number): string;
|
|
72
|
+
//# sourceMappingURL=terminal-text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-text.d.ts","sourceRoot":"","sources":["../src/terminal-text.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,OAAO,EAAkC,KAAK,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAEvF,wFAAwF;AACxF,eAAO,MAAM,QAAQ,IAAI,CAAA;AAEzB,kFAAkF;AAClF,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAA;AAEzC,MAAM,WAAW,iBAAiB;IAChC,yFAAyF;IACzF,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACpC,QAAQ,CAAC,GAAG,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;CACrC;AAED,MAAM,WAAW,iBAAiB;IAChC,6EAA6E;IAC7E,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;IAC1B,yFAAyF;IACzF,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACrC;AAuRD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,GAAG,MAAM,CAkCvF;AAsJD;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,MAAM,CA2ElF;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAwBvE"}
|