@mudah-cli/terminal 0.1.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/capabilities.d.ts +5 -0
- package/dist/capabilities.js +1 -0
- package/dist/capabilities.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/keys.js +24 -2
- package/dist/keys.js.map +1 -1
- package/dist/mouse.d.ts +66 -0
- package/dist/mouse.js +111 -0
- package/dist/mouse.js.map +1 -0
- package/dist/theme-query.d.ts +71 -0
- package/dist/theme-query.js +142 -0
- package/dist/theme-query.js.map +1 -0
- package/package.json +1 -1
package/dist/capabilities.d.ts
CHANGED
|
@@ -18,6 +18,11 @@ export interface TerminalCapabilities {
|
|
|
18
18
|
readonly osc9: boolean;
|
|
19
19
|
/** OSC 133 semantic prompt markers (Kitty, WezTerm, iTerm2, VS Code, foot). */
|
|
20
20
|
readonly osc133: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* The terminal answers OSC 10/11 color queries, so its theme can be read
|
|
23
|
+
* at runtime. Everything modern does; dumb terminals and CI do not.
|
|
24
|
+
*/
|
|
25
|
+
readonly themeQuery: boolean;
|
|
21
26
|
/** Cursor show/hide is safe. */
|
|
22
27
|
readonly cursorControl: boolean;
|
|
23
28
|
/** Best-guess terminal theme. */
|
package/dist/capabilities.js
CHANGED
|
@@ -19,6 +19,7 @@ export function detectCapabilities(options = {}) {
|
|
|
19
19
|
reducedMotion,
|
|
20
20
|
osc9: brand === 'ghostty' || brand === 'wezterm',
|
|
21
21
|
osc133: brand === 'kitty' || brand === 'wezterm' || brand === 'iterm' || brand === 'vscode' || brand === 'foot',
|
|
22
|
+
themeQuery: isTty && brand !== 'apple-terminal' && env['TERM'] !== 'dumb',
|
|
22
23
|
cursorControl: isTty,
|
|
23
24
|
theme: overrides.theme ?? 'unknown',
|
|
24
25
|
width: options.width ?? process.stdout.columns ?? 80,
|
package/dist/capabilities.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { ansi } from './ansi.js';
|
|
2
2
|
export { detectCapabilities, type CapabilityOverrides, type ColorLevel, type DetectCapabilitiesOptions, type TerminalBrand, type TerminalCapabilities, } from './capabilities.js';
|
|
3
3
|
export { guardedOsc, osc, type OscWriter } from './osc.js';
|
|
4
|
+
export { parseOscColor, parseThemeResponses, queryTerminalTheme, relativeLuminance, themeFromBackground, type Rgb, type TerminalTheme, type ThemeQueryFailure, type ThemeQueryInput, type ThemeQueryOptions, type ThemeQueryResult, } from './theme-query.js';
|
|
4
5
|
export { enterRawMode, KeyParser, parseKeys, type KeyEvent, type KeyName } from './keys.js';
|
|
6
|
+
export { disableMouse, enableMouse, isMouseEvent, parseMouseEvents, type MouseButtons, type MouseEvent, type MouseModeOptions, } from './mouse.js';
|
|
5
7
|
export { Ticker, type TickerOptions } from './ticker.js';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export { ansi } from './ansi.js';
|
|
2
2
|
export { detectCapabilities, } from './capabilities.js';
|
|
3
3
|
export { guardedOsc, osc } from './osc.js';
|
|
4
|
+
export { parseOscColor, parseThemeResponses, queryTerminalTheme, relativeLuminance, themeFromBackground, } from './theme-query.js';
|
|
4
5
|
export { enterRawMode, KeyParser, parseKeys } from './keys.js';
|
|
6
|
+
export { disableMouse, enableMouse, isMouseEvent, parseMouseEvents, } from './mouse.js';
|
|
5
7
|
export { Ticker } from './ticker.js';
|
|
6
8
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EACL,kBAAkB,GAMnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,GAAG,EAAkB,MAAM,UAAU,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAA+B,MAAM,WAAW,CAAC;AAC5F,OAAO,EAAE,MAAM,EAAsB,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EACL,kBAAkB,GAMnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,GAAG,EAAkB,MAAM,UAAU,CAAC;AAC3D,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,GAOpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAA+B,MAAM,WAAW,CAAC;AAC5F,OAAO,EACL,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,gBAAgB,GAIjB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,MAAM,EAAsB,MAAM,aAAa,CAAC"}
|
package/dist/keys.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isMouseEvent } from './mouse.js';
|
|
1
2
|
/**
|
|
2
3
|
* Parse a raw input buffer into key events. Pure and synchronous.
|
|
3
4
|
* Handles CSI sequences (arrows, home/end, paging, delete), bare escape,
|
|
@@ -5,6 +6,8 @@
|
|
|
5
6
|
*/
|
|
6
7
|
export function parseKeys(buffer) {
|
|
7
8
|
const events = [];
|
|
9
|
+
if (isMouseEvent(buffer))
|
|
10
|
+
return events;
|
|
8
11
|
let i = 0;
|
|
9
12
|
while (i < buffer.length) {
|
|
10
13
|
const char = buffer[i];
|
|
@@ -118,6 +121,10 @@ export class KeyParser {
|
|
|
118
121
|
return [];
|
|
119
122
|
const ready = this.pending.slice(0, safe);
|
|
120
123
|
this.pending = this.pending.slice(safe);
|
|
124
|
+
// A complete mouse report produces no key events but must not linger:
|
|
125
|
+
// leaving it in `pending` would corrupt the next chunk's parse.
|
|
126
|
+
if (isMouseEvent(ready))
|
|
127
|
+
return [];
|
|
121
128
|
return parseKeys(ready);
|
|
122
129
|
}
|
|
123
130
|
/** Index up to which the buffer can be split without cutting a sequence. */
|
|
@@ -126,8 +133,23 @@ export class KeyParser {
|
|
|
126
133
|
if (esc < 0)
|
|
127
134
|
return text.length;
|
|
128
135
|
const rest = text.slice(esc + 1);
|
|
129
|
-
|
|
130
|
-
|
|
136
|
+
// Mouse reports carry their own terminator; wait for it rather than
|
|
137
|
+
// leaking half a click as a stray escape key. SGR is itself a CSI
|
|
138
|
+
// sequence, so it must be checked before the generic CSI branch below.
|
|
139
|
+
if (rest.startsWith('[<')) {
|
|
140
|
+
return /^\[<\d+;\d+;\d+[Mm]$/.test(rest) ? text.length : -1;
|
|
141
|
+
}
|
|
142
|
+
if (rest.startsWith('[') && /\d+;\d+;\d+M$/.test(rest)) {
|
|
143
|
+
return text.length; // urxvt 1015
|
|
144
|
+
}
|
|
145
|
+
if (rest.startsWith('M')) {
|
|
146
|
+
return /^M[\x20-\x7f]{3}$/.test(rest) ? text.length : -1;
|
|
147
|
+
}
|
|
148
|
+
if (rest.length === 0) {
|
|
149
|
+
// Trailing lone ESC at a chunk boundary: terminals deliver CSI
|
|
150
|
+
// sequences as single reads, so a bare ESC here IS the escape key.
|
|
151
|
+
return esc + 1;
|
|
152
|
+
}
|
|
131
153
|
if (rest[0] === '[') {
|
|
132
154
|
// Complete only when a final byte (0x40–0x7e) terminates the sequence.
|
|
133
155
|
return /^\[[0-9;?]*[\x40-\x7e]$/.test(rest) ? text.length : -1;
|
package/dist/keys.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keys.js","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"keys.js","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"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"}
|
package/dist/mouse.d.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mouse input parsing for modern terminals.
|
|
3
|
+
*
|
|
4
|
+
* Terminals report clicks as CSI sequences. Three encodings are in use:
|
|
5
|
+
*
|
|
6
|
+
* - **X10** (`\x1b[Mbxy`) — press only, coordinates capped at 223.
|
|
7
|
+
* - **SGR 1006** (`\x1b[<b;x;yM/m`) — unlimited coordinates, press *and*
|
|
8
|
+
* release. Every terminal worth supporting speaks this.
|
|
9
|
+
* - **Urxvt 1015** (`\x1b[b;x;yM`) — rare; handled for completeness.
|
|
10
|
+
*
|
|
11
|
+
* Programs enable reporting by writing the corresponding mode (see
|
|
12
|
+
* {@link enableMouse} / {@link disableMouse}) and feed raw stdin through
|
|
13
|
+
* {@link parseMouseEvents}. Coordinates arrive 1-based and are normalized
|
|
14
|
+
* to 0-based here, matching how renderers address cells.
|
|
15
|
+
*/
|
|
16
|
+
/** Which buttons are held. */
|
|
17
|
+
export interface MouseButtons {
|
|
18
|
+
readonly left: boolean;
|
|
19
|
+
readonly middle: boolean;
|
|
20
|
+
readonly right: boolean;
|
|
21
|
+
/** Fourth button, or wheel-up in some encodings. */
|
|
22
|
+
readonly extra: boolean;
|
|
23
|
+
}
|
|
24
|
+
/** A single mouse event on a cell. */
|
|
25
|
+
export interface MouseEvent {
|
|
26
|
+
/** 0-based column. */
|
|
27
|
+
readonly x: number;
|
|
28
|
+
/** 0-based row. */
|
|
29
|
+
readonly y: number;
|
|
30
|
+
readonly buttons: MouseButtons;
|
|
31
|
+
/** True when no button is pressed (a move or a release). */
|
|
32
|
+
readonly hover: boolean;
|
|
33
|
+
/** True for a button release rather than a press. */
|
|
34
|
+
readonly release: boolean;
|
|
35
|
+
readonly drag: boolean;
|
|
36
|
+
/** Mouse wheel direction, when this event came from a wheel. */
|
|
37
|
+
readonly wheel?: 'up' | 'down';
|
|
38
|
+
/** Set of modifiers held during the event. */
|
|
39
|
+
readonly shift: boolean;
|
|
40
|
+
readonly alt: boolean;
|
|
41
|
+
readonly ctrl: boolean;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Decode a raw input chunk into mouse events. Terminals that don't report
|
|
45
|
+
* the mouse simply never match, so this is safe to run on every keystroke.
|
|
46
|
+
*
|
|
47
|
+
* A terminal speaks one encoding at a time. SGR is tried first, and when it
|
|
48
|
+
* matches the chunk, the older encodings are skipped — otherwise an SGR
|
|
49
|
+
* report can also look like a stray X10 one.
|
|
50
|
+
*/
|
|
51
|
+
export declare function parseMouseEvents(buffer: string): MouseEvent[];
|
|
52
|
+
/** True when the buffer looks like a mouse report. */
|
|
53
|
+
export declare function isMouseEvent(buffer: string): boolean;
|
|
54
|
+
export interface MouseModeOptions {
|
|
55
|
+
/** Report motion only while a button is held. */
|
|
56
|
+
drag?: boolean;
|
|
57
|
+
/** Report all motion, even with no button held. */
|
|
58
|
+
motion?: boolean;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* The escape sequence that turns mouse reporting on. `1006` (SGR) is always
|
|
62
|
+
* included: it's the only encoding that survives large terminals.
|
|
63
|
+
*/
|
|
64
|
+
export declare function enableMouse(options?: MouseModeOptions): string;
|
|
65
|
+
/** The escape sequence that turns mouse reporting off. */
|
|
66
|
+
export declare function disableMouse(options?: MouseModeOptions): string;
|
package/dist/mouse.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mouse input parsing for modern terminals.
|
|
3
|
+
*
|
|
4
|
+
* Terminals report clicks as CSI sequences. Three encodings are in use:
|
|
5
|
+
*
|
|
6
|
+
* - **X10** (`\x1b[Mbxy`) — press only, coordinates capped at 223.
|
|
7
|
+
* - **SGR 1006** (`\x1b[<b;x;yM/m`) — unlimited coordinates, press *and*
|
|
8
|
+
* release. Every terminal worth supporting speaks this.
|
|
9
|
+
* - **Urxvt 1015** (`\x1b[b;x;yM`) — rare; handled for completeness.
|
|
10
|
+
*
|
|
11
|
+
* Programs enable reporting by writing the corresponding mode (see
|
|
12
|
+
* {@link enableMouse} / {@link disableMouse}) and feed raw stdin through
|
|
13
|
+
* {@link parseMouseEvents}. Coordinates arrive 1-based and are normalized
|
|
14
|
+
* to 0-based here, matching how renderers address cells.
|
|
15
|
+
*/
|
|
16
|
+
const NO_BUTTONS = { left: false, middle: false, right: false, extra: false };
|
|
17
|
+
// \x1b[M<b><x><y> — X10 / 1000 mode, coordinates offset by 32.
|
|
18
|
+
const X10 = /\x1b\[M([\x20-\x7f])([\x20-\x7f])([\x20-\x7f])/g;
|
|
19
|
+
// \x1b[<0;1;2M — SGR 1006: params then a final M (press) or m (release).
|
|
20
|
+
const SGR = /\x1b\[<(\d+);(\d+);(\d+)([Mm])/g;
|
|
21
|
+
// \x1b[0;1;2M — urxvt 1015.
|
|
22
|
+
const URXVT = /\x1b\[(\d+);(\d+);(\d+)M/g;
|
|
23
|
+
/**
|
|
24
|
+
* Decode a raw input chunk into mouse events. Terminals that don't report
|
|
25
|
+
* the mouse simply never match, so this is safe to run on every keystroke.
|
|
26
|
+
*
|
|
27
|
+
* A terminal speaks one encoding at a time. SGR is tried first, and when it
|
|
28
|
+
* matches the chunk, the older encodings are skipped — otherwise an SGR
|
|
29
|
+
* report can also look like a stray X10 one.
|
|
30
|
+
*/
|
|
31
|
+
export function parseMouseEvents(buffer) {
|
|
32
|
+
const sgr = [...buffer.matchAll(SGR)];
|
|
33
|
+
if (sgr.length > 0) {
|
|
34
|
+
return sgr.map((match) => decode(Number(match[1]), Number(match[2]) - 1, Number(match[3]) - 1, match[4] === 'm'));
|
|
35
|
+
}
|
|
36
|
+
const x10 = [...buffer.matchAll(X10)];
|
|
37
|
+
if (x10.length > 0) {
|
|
38
|
+
return x10.map((match) => decode(match[1].charCodeAt(0) - 32, match[2].charCodeAt(0) - 33, match[3].charCodeAt(0) - 33, false));
|
|
39
|
+
}
|
|
40
|
+
return [...buffer.matchAll(URXVT)].map((match) => decode(Number(match[1]) - 32, Number(match[2]) - 1, Number(match[3]) - 1, false));
|
|
41
|
+
}
|
|
42
|
+
/** True when the buffer looks like a mouse report. */
|
|
43
|
+
export function isMouseEvent(buffer) {
|
|
44
|
+
return /\x1b\[(M[\x20-\x7f]{3}|<\d+;\d+;\d+[Mm]|\d+;\d+;\d+M)/.test(buffer);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Turn a protocol button code into an event.
|
|
48
|
+
*
|
|
49
|
+
* Layout of the low bits: `0b11` is the button (0 left, 1 middle, 2 right,
|
|
50
|
+
* 3 none), `0b100000` marks motion, `0b100`/`0b1000`/`0b10000` are the
|
|
51
|
+
* shift/alt/ctrl modifiers, and 64/65 are the wheel.
|
|
52
|
+
*/
|
|
53
|
+
function decode(code, x, y, release) {
|
|
54
|
+
const wheel = wheelDirection(code);
|
|
55
|
+
const button = code & 0b11;
|
|
56
|
+
const motion = (code & 0b100000) !== 0;
|
|
57
|
+
return {
|
|
58
|
+
x,
|
|
59
|
+
y,
|
|
60
|
+
buttons: wheel === undefined ? buttonsFrom(button, release) : NO_BUTTONS,
|
|
61
|
+
// "No button reported" covers both hover and release; SGR distinguishes
|
|
62
|
+
// them by its final byte, which is what `release` carries.
|
|
63
|
+
hover: wheel === undefined && button === 3 && motion,
|
|
64
|
+
release: wheel === undefined && (release || (button === 3 && !motion)),
|
|
65
|
+
drag: wheel === undefined && motion && button !== 3,
|
|
66
|
+
...(wheel === undefined ? {} : { wheel }),
|
|
67
|
+
shift: (code & 0b100) !== 0,
|
|
68
|
+
alt: (code & 0b1000) !== 0,
|
|
69
|
+
ctrl: (code & 0b10000) !== 0,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function wheelDirection(code) {
|
|
73
|
+
// 64 = wheel up, 65 = wheel down (button codes 4 and 5).
|
|
74
|
+
if (code === 64)
|
|
75
|
+
return 'up';
|
|
76
|
+
if (code === 65)
|
|
77
|
+
return 'down';
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
function buttonsFrom(button, release) {
|
|
81
|
+
if (release || button === 3)
|
|
82
|
+
return NO_BUTTONS;
|
|
83
|
+
return {
|
|
84
|
+
left: button === 0,
|
|
85
|
+
middle: button === 1,
|
|
86
|
+
right: button === 2,
|
|
87
|
+
extra: false,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* The escape sequence that turns mouse reporting on. `1006` (SGR) is always
|
|
92
|
+
* included: it's the only encoding that survives large terminals.
|
|
93
|
+
*/
|
|
94
|
+
export function enableMouse(options = {}) {
|
|
95
|
+
const modes = ['1000', '1006'];
|
|
96
|
+
if (options.drag === true)
|
|
97
|
+
modes.unshift('1002');
|
|
98
|
+
if (options.motion === true)
|
|
99
|
+
modes.unshift('1003');
|
|
100
|
+
return modes.map((mode) => `\x1b[?${mode}h`).join('');
|
|
101
|
+
}
|
|
102
|
+
/** The escape sequence that turns mouse reporting off. */
|
|
103
|
+
export function disableMouse(options = {}) {
|
|
104
|
+
const modes = ['1000', '1006'];
|
|
105
|
+
if (options.drag === true)
|
|
106
|
+
modes.unshift('1002');
|
|
107
|
+
if (options.motion === true)
|
|
108
|
+
modes.unshift('1003');
|
|
109
|
+
return modes.map((mode) => `\x1b[?${mode}l`).join('');
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=mouse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mouse.js","sourceRoot":"","sources":["../src/mouse.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { OscWriter } from './osc.js';
|
|
2
|
+
/** An 8-bit-per-channel sRGB color. */
|
|
3
|
+
export interface Rgb {
|
|
4
|
+
readonly r: number;
|
|
5
|
+
readonly g: number;
|
|
6
|
+
readonly b: number;
|
|
7
|
+
}
|
|
8
|
+
export type TerminalTheme = 'dark' | 'light';
|
|
9
|
+
export type ThemeQueryFailure = 'not-a-tty' | 'timeout' | 'unsupported';
|
|
10
|
+
export interface ThemeQueryResult {
|
|
11
|
+
/** True when at least one color came back from the terminal. */
|
|
12
|
+
readonly ok: boolean;
|
|
13
|
+
/** Reported background (OSC 11), when the terminal answered. */
|
|
14
|
+
readonly background?: Rgb;
|
|
15
|
+
/** Reported foreground (OSC 10), when the terminal answered. */
|
|
16
|
+
readonly foreground?: Rgb;
|
|
17
|
+
/** Theme inferred from the reported colors. */
|
|
18
|
+
readonly theme: TerminalTheme | 'unknown';
|
|
19
|
+
/** Why nothing came back, when `ok` is false. */
|
|
20
|
+
readonly reason?: ThemeQueryFailure;
|
|
21
|
+
}
|
|
22
|
+
/** The subset of a readable stream the query needs. `process.stdin` fits. */
|
|
23
|
+
export interface ThemeQueryInput {
|
|
24
|
+
readonly isTTY?: boolean;
|
|
25
|
+
readonly isRaw?: boolean;
|
|
26
|
+
setRawMode?(enabled: boolean): unknown;
|
|
27
|
+
resume?(): unknown;
|
|
28
|
+
pause?(): unknown;
|
|
29
|
+
on(event: string, listener: (chunk: Buffer | string) => void): unknown;
|
|
30
|
+
off(event: string, listener: (chunk: Buffer | string) => void): unknown;
|
|
31
|
+
}
|
|
32
|
+
export interface ThemeQueryOptions {
|
|
33
|
+
/** Stream the query is written to (default `process.stdout`). */
|
|
34
|
+
stdout?: OscWriter;
|
|
35
|
+
/** Stream the answer is read from (default `process.stdin`). */
|
|
36
|
+
stdin?: ThemeQueryInput;
|
|
37
|
+
/** How long to wait for an answer before giving up. */
|
|
38
|
+
timeoutMs?: number;
|
|
39
|
+
/** Also ask for the foreground color (OSC 10). Default true. */
|
|
40
|
+
includeForeground?: boolean;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Parse a single OSC color payload. Accepts the X11 `rgb:rr/gg/bb` form
|
|
44
|
+
* (1–4 hex digits per channel, scaled to 8 bits) and plain `#rrggbb`.
|
|
45
|
+
* Returns null for anything else.
|
|
46
|
+
*/
|
|
47
|
+
export declare function parseOscColor(value: string): Rgb | null;
|
|
48
|
+
/**
|
|
49
|
+
* Pull every OSC 10/11 answer out of a raw input buffer. Input that arrives
|
|
50
|
+
* mid-response is kept by the caller, so this is safe to re-run per chunk.
|
|
51
|
+
*/
|
|
52
|
+
export declare function parseThemeResponses(buffer: string): {
|
|
53
|
+
background?: Rgb;
|
|
54
|
+
foreground?: Rgb;
|
|
55
|
+
};
|
|
56
|
+
/** WCAG relative luminance, 0 (black) to 1 (white). */
|
|
57
|
+
export declare function relativeLuminance(color: Rgb): number;
|
|
58
|
+
/**
|
|
59
|
+
* Classify a background as light or dark. `threshold` is the relative
|
|
60
|
+
* luminance that separates the two (default 0.5).
|
|
61
|
+
*/
|
|
62
|
+
export declare function themeFromBackground(background: Rgb, threshold?: number): TerminalTheme;
|
|
63
|
+
/**
|
|
64
|
+
* Ask the terminal for its colors with OSC 10 (foreground) and OSC 11
|
|
65
|
+
* (background), then infer light/dark from the answer.
|
|
66
|
+
*
|
|
67
|
+
* Resolves fast on the paths that can't work: no TTY, or a terminal that
|
|
68
|
+
* never answers (timeout). Terminal state (raw mode, flow, listeners) is
|
|
69
|
+
* always restored before this returns.
|
|
70
|
+
*/
|
|
71
|
+
export declare function queryTerminalTheme(options?: ThemeQueryOptions): Promise<ThemeQueryResult>;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
const DEFAULT_TIMEOUT_MS = 150;
|
|
2
|
+
// Terminals answer with either `\x1b]11;rgb:…\x1b\\` (ST) or `\x1b]11;rgb:…\x07` (BEL).
|
|
3
|
+
const RESPONSE = /\x1b\](10|11);([^\x07\x1b]*)(?:\x07|\x1b\\)/g;
|
|
4
|
+
const RGB_FORM = /^rgb:([0-9a-f]{1,4})\/([0-9a-f]{1,4})\/([0-9a-f]{1,4})$/i;
|
|
5
|
+
const HEX_FORM = /^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i;
|
|
6
|
+
/**
|
|
7
|
+
* Parse a single OSC color payload. Accepts the X11 `rgb:rr/gg/bb` form
|
|
8
|
+
* (1–4 hex digits per channel, scaled to 8 bits) and plain `#rrggbb`.
|
|
9
|
+
* Returns null for anything else.
|
|
10
|
+
*/
|
|
11
|
+
export function parseOscColor(value) {
|
|
12
|
+
const text = value.trim();
|
|
13
|
+
const rgb = RGB_FORM.exec(text);
|
|
14
|
+
if (rgb) {
|
|
15
|
+
return {
|
|
16
|
+
r: scaleChannel(rgb[1]),
|
|
17
|
+
g: scaleChannel(rgb[2]),
|
|
18
|
+
b: scaleChannel(rgb[3]),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
const hex = HEX_FORM.exec(text);
|
|
22
|
+
if (hex) {
|
|
23
|
+
return {
|
|
24
|
+
r: parseInt(hex[1], 16),
|
|
25
|
+
g: parseInt(hex[2], 16),
|
|
26
|
+
b: parseInt(hex[3], 16),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
/** Scale a 1–4 digit hex channel up to the 0–255 range. */
|
|
32
|
+
function scaleChannel(hex) {
|
|
33
|
+
const max = 2 ** (hex.length * 4) - 1;
|
|
34
|
+
return Math.round((parseInt(hex, 16) / max) * 255);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Pull every OSC 10/11 answer out of a raw input buffer. Input that arrives
|
|
38
|
+
* mid-response is kept by the caller, so this is safe to re-run per chunk.
|
|
39
|
+
*/
|
|
40
|
+
export function parseThemeResponses(buffer) {
|
|
41
|
+
const found = {};
|
|
42
|
+
for (const match of buffer.matchAll(RESPONSE)) {
|
|
43
|
+
const code = match[1];
|
|
44
|
+
const color = parseOscColor(match[2] ?? '');
|
|
45
|
+
if (color === null)
|
|
46
|
+
continue;
|
|
47
|
+
if (code === '11')
|
|
48
|
+
found.background = color;
|
|
49
|
+
if (code === '10')
|
|
50
|
+
found.foreground = color;
|
|
51
|
+
}
|
|
52
|
+
return found;
|
|
53
|
+
}
|
|
54
|
+
/** WCAG relative luminance, 0 (black) to 1 (white). */
|
|
55
|
+
export function relativeLuminance(color) {
|
|
56
|
+
const channel = (raw) => {
|
|
57
|
+
const c = raw / 255;
|
|
58
|
+
return c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;
|
|
59
|
+
};
|
|
60
|
+
return (0.2126 * channel(color.r) + 0.7152 * channel(color.g) + 0.0722 * channel(color.b));
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Classify a background as light or dark. `threshold` is the relative
|
|
64
|
+
* luminance that separates the two (default 0.5).
|
|
65
|
+
*/
|
|
66
|
+
export function themeFromBackground(background, threshold = 0.5) {
|
|
67
|
+
return relativeLuminance(background) >= threshold ? 'light' : 'dark';
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Ask the terminal for its colors with OSC 10 (foreground) and OSC 11
|
|
71
|
+
* (background), then infer light/dark from the answer.
|
|
72
|
+
*
|
|
73
|
+
* Resolves fast on the paths that can't work: no TTY, or a terminal that
|
|
74
|
+
* never answers (timeout). Terminal state (raw mode, flow, listeners) is
|
|
75
|
+
* always restored before this returns.
|
|
76
|
+
*/
|
|
77
|
+
export async function queryTerminalTheme(options = {}) {
|
|
78
|
+
const stdout = options.stdout ?? process.stdout;
|
|
79
|
+
const stdin = options.stdin ?? process.stdin;
|
|
80
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
81
|
+
const includeForeground = options.includeForeground ?? true;
|
|
82
|
+
if (stdin.isTTY !== true) {
|
|
83
|
+
return { ok: false, theme: 'unknown', reason: 'not-a-tty' };
|
|
84
|
+
}
|
|
85
|
+
let buffer = '';
|
|
86
|
+
let found = {};
|
|
87
|
+
const isSettled = () => found.background !== undefined &&
|
|
88
|
+
(!includeForeground || found.foreground !== undefined);
|
|
89
|
+
let done;
|
|
90
|
+
const finished = new Promise((resolve) => {
|
|
91
|
+
done = resolve;
|
|
92
|
+
});
|
|
93
|
+
const settle = () => {
|
|
94
|
+
clearTimeout(timer);
|
|
95
|
+
stdin.off?.('data', listener);
|
|
96
|
+
if (canRaw && stdin.isRaw !== wasRaw)
|
|
97
|
+
stdin.setRawMode?.(wasRaw);
|
|
98
|
+
if (didResume)
|
|
99
|
+
stdin.pause?.();
|
|
100
|
+
if (found.background === undefined && found.foreground === undefined) {
|
|
101
|
+
done({ ok: false, theme: 'unknown', reason: 'timeout' });
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
done({
|
|
105
|
+
ok: true,
|
|
106
|
+
background: found.background,
|
|
107
|
+
foreground: found.foreground,
|
|
108
|
+
theme: inferTheme(found),
|
|
109
|
+
});
|
|
110
|
+
};
|
|
111
|
+
const listener = (chunk) => {
|
|
112
|
+
buffer += typeof chunk === 'string' ? chunk : chunk.toString('utf8');
|
|
113
|
+
found = parseThemeResponses(buffer);
|
|
114
|
+
if (isSettled())
|
|
115
|
+
settle();
|
|
116
|
+
};
|
|
117
|
+
const canRaw = stdin.setRawMode !== undefined;
|
|
118
|
+
const wasRaw = stdin.isRaw === true;
|
|
119
|
+
const didResume = stdin.resume !== undefined;
|
|
120
|
+
const timer = setTimeout(settle, timeoutMs);
|
|
121
|
+
stdin.on('data', listener);
|
|
122
|
+
if (canRaw && !wasRaw)
|
|
123
|
+
stdin.setRawMode?.(true);
|
|
124
|
+
stdin.resume?.();
|
|
125
|
+
if (includeForeground)
|
|
126
|
+
stdout.write('\x1b]10;?\x1b\\');
|
|
127
|
+
stdout.write('\x1b]11;?\x1b\\');
|
|
128
|
+
return finished;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Background drives the guess. With only a foreground we invert it, which
|
|
132
|
+
* is a weak signal — bright text usually sits on a dark terminal.
|
|
133
|
+
*/
|
|
134
|
+
function inferTheme(found) {
|
|
135
|
+
if (found.background !== undefined)
|
|
136
|
+
return themeFromBackground(found.background);
|
|
137
|
+
if (found.foreground !== undefined) {
|
|
138
|
+
return relativeLuminance(found.foreground) >= 0.5 ? 'dark' : 'light';
|
|
139
|
+
}
|
|
140
|
+
return 'unknown';
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=theme-query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme-query.js","sourceRoot":"","sources":["../src/theme-query.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED