@mudah-cli/terminal 0.2.0 → 0.4.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 +15 -0
- package/dist/capabilities.js +3 -0
- package/dist/capabilities.js.map +1 -1
- package/dist/graphics.d.ts +64 -0
- package/dist/graphics.js +135 -0
- package/dist/graphics.js.map +1 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/keys.d.ts +35 -2
- package/dist/keys.js +152 -32
- 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 +2 -2
package/dist/capabilities.d.ts
CHANGED
|
@@ -18,6 +18,21 @@ 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;
|
|
26
|
+
/**
|
|
27
|
+
* Kitty graphics protocol (APC `_G`): pixel images in the terminal.
|
|
28
|
+
* Ghostty, Kitty, and WezTerm.
|
|
29
|
+
*/
|
|
30
|
+
readonly kittyGraphics: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Kitty keyboard protocol (CSI u), including key-up when enabled.
|
|
33
|
+
* Ghostty, Kitty, and WezTerm.
|
|
34
|
+
*/
|
|
35
|
+
readonly kittyKeyboard: boolean;
|
|
21
36
|
/** Cursor show/hide is safe. */
|
|
22
37
|
readonly cursorControl: boolean;
|
|
23
38
|
/** Best-guess terminal theme. */
|
package/dist/capabilities.js
CHANGED
|
@@ -19,6 +19,9 @@ 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',
|
|
23
|
+
kittyGraphics: isTty && (brand === 'ghostty' || brand === 'kitty' || brand === 'wezterm'),
|
|
24
|
+
kittyKeyboard: isTty && (brand === 'ghostty' || brand === 'kitty' || brand === 'wezterm'),
|
|
22
25
|
cursorControl: isTty,
|
|
23
26
|
theme: overrides.theme ?? 'unknown',
|
|
24
27
|
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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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { OscWriter } from './osc.js';
|
|
2
|
+
/**
|
|
3
|
+
* Kitty graphics protocol (APC `_G`): transmit raw pixels and place them
|
|
4
|
+
* in the terminal. Ghostty, Kitty, and WezTerm speak this. Other terminals
|
|
5
|
+
* ignore APC, so a write is safe anywhere.
|
|
6
|
+
*
|
|
7
|
+
* Quiet mode (`q=2`) is always on: the terminal must not reply, so the
|
|
8
|
+
* key parser never sees an APC acknowledgement.
|
|
9
|
+
*/
|
|
10
|
+
export type PixelFormat = 'rgb' | 'rgba';
|
|
11
|
+
export interface KittyImageOptions {
|
|
12
|
+
/** Pixel bytes, tightly packed, row-major, top-left origin. */
|
|
13
|
+
readonly pixels: Uint8Array;
|
|
14
|
+
readonly width: number;
|
|
15
|
+
readonly height: number;
|
|
16
|
+
/** Default `rgba`. */
|
|
17
|
+
readonly format?: PixelFormat;
|
|
18
|
+
/** Image id (1–4294967295). Reusing an id replaces the previous image. */
|
|
19
|
+
readonly id?: number;
|
|
20
|
+
/** Placement id. Pair with `id` so a later frame replaces this one. */
|
|
21
|
+
readonly placementId?: number;
|
|
22
|
+
/** Compress with zlib before base64. Default true. */
|
|
23
|
+
readonly compress?: boolean;
|
|
24
|
+
/** Scale to this many columns. Kitty preserves aspect if `rows` is omitted. */
|
|
25
|
+
readonly columns?: number;
|
|
26
|
+
/** Scale to this many rows. */
|
|
27
|
+
readonly rows?: number;
|
|
28
|
+
/** Do not move the cursor after placing the image. Default true. */
|
|
29
|
+
readonly stay?: boolean;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Encode a framebuffer as one or more Kitty graphics sequences.
|
|
33
|
+
* Chunks stay at most 4096 base64 bytes, as the protocol requires.
|
|
34
|
+
*/
|
|
35
|
+
export declare function encodeKittyImage(options: KittyImageOptions): string;
|
|
36
|
+
/**
|
|
37
|
+
* Delete images. `all` wipes every placement. A numeric `id` deletes that
|
|
38
|
+
* image and its placements.
|
|
39
|
+
*/
|
|
40
|
+
export declare function encodeKittyDelete(target?: 'all' | {
|
|
41
|
+
id: number;
|
|
42
|
+
}): string;
|
|
43
|
+
/**
|
|
44
|
+
* Place a framebuffer through the Kitty protocol. Reuses `id`/`placementId`
|
|
45
|
+
* so the next call replaces the frame without flicker.
|
|
46
|
+
*/
|
|
47
|
+
export declare class KittyGraphics {
|
|
48
|
+
private readonly writer;
|
|
49
|
+
readonly id: number;
|
|
50
|
+
readonly placementId: number;
|
|
51
|
+
constructor(writer: OscWriter, options?: {
|
|
52
|
+
id?: number;
|
|
53
|
+
placementId?: number;
|
|
54
|
+
});
|
|
55
|
+
draw(pixels: Uint8Array, width: number, height: number, options?: Omit<KittyImageOptions, 'pixels' | 'width' | 'height' | 'id' | 'placementId'>): void;
|
|
56
|
+
/** Remove this image (or every image, when `all` is true). */
|
|
57
|
+
delete(all?: boolean): void;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Encode an RGBA/RGB framebuffer as unicode half-blocks (`▀`). Each cell
|
|
61
|
+
* holds two vertical pixels (foreground = top, background = bottom).
|
|
62
|
+
* Works in any truecolor terminal, including those without Kitty graphics.
|
|
63
|
+
*/
|
|
64
|
+
export declare function encodeHalfBlocks(pixels: Uint8Array, width: number, height: number, format?: PixelFormat): string[];
|
package/dist/graphics.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { deflateSync } from 'node:zlib';
|
|
2
|
+
const CHUNK = 4096;
|
|
3
|
+
const ST = '\x1b\\';
|
|
4
|
+
function bytesPerPixel(format) {
|
|
5
|
+
return format === 'rgb' ? 3 : 4;
|
|
6
|
+
}
|
|
7
|
+
/** APC wrapper: `ESC _ G <control> ; <payload> ESC \`. */
|
|
8
|
+
function apc(control, payload = '') {
|
|
9
|
+
return `\x1b_G${control};${payload}${ST}`;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Encode a framebuffer as one or more Kitty graphics sequences.
|
|
13
|
+
* Chunks stay at most 4096 base64 bytes, as the protocol requires.
|
|
14
|
+
*/
|
|
15
|
+
export function encodeKittyImage(options) {
|
|
16
|
+
const format = options.format ?? 'rgba';
|
|
17
|
+
const bpp = bytesPerPixel(format);
|
|
18
|
+
const expected = options.width * options.height * bpp;
|
|
19
|
+
if (options.pixels.byteLength < expected) {
|
|
20
|
+
throw new Error(`[terminal] Kitty image payload is ${options.pixels.byteLength} bytes, need ${expected} for ${options.width}x${options.height} ${format}.`);
|
|
21
|
+
}
|
|
22
|
+
const raw = options.pixels.subarray(0, expected);
|
|
23
|
+
const compress = options.compress !== false;
|
|
24
|
+
const body = compress ? deflateSync(raw) : Buffer.from(raw);
|
|
25
|
+
const encoded = body.toString('base64');
|
|
26
|
+
const keys = [
|
|
27
|
+
'a=T',
|
|
28
|
+
`f=${format === 'rgb' ? 24 : 32}`,
|
|
29
|
+
`s=${options.width}`,
|
|
30
|
+
`v=${options.height}`,
|
|
31
|
+
'q=2',
|
|
32
|
+
];
|
|
33
|
+
if (compress)
|
|
34
|
+
keys.push('o=z');
|
|
35
|
+
if (options.id !== undefined && options.id > 0)
|
|
36
|
+
keys.push(`i=${options.id}`);
|
|
37
|
+
if (options.placementId !== undefined && options.placementId > 0) {
|
|
38
|
+
keys.push(`p=${options.placementId}`);
|
|
39
|
+
}
|
|
40
|
+
if (options.columns !== undefined)
|
|
41
|
+
keys.push(`c=${options.columns}`);
|
|
42
|
+
if (options.rows !== undefined)
|
|
43
|
+
keys.push(`r=${options.rows}`);
|
|
44
|
+
if (options.stay !== false)
|
|
45
|
+
keys.push('C=1');
|
|
46
|
+
if (encoded.length <= CHUNK) {
|
|
47
|
+
return apc(keys.join(','), encoded);
|
|
48
|
+
}
|
|
49
|
+
const chunks = [];
|
|
50
|
+
for (let offset = 0; offset < encoded.length; offset += CHUNK) {
|
|
51
|
+
const slice = encoded.slice(offset, offset + CHUNK);
|
|
52
|
+
const last = offset + CHUNK >= encoded.length;
|
|
53
|
+
if (offset === 0) {
|
|
54
|
+
chunks.push(apc(`${keys.join(',')},m=1`, slice));
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
chunks.push(apc(`m=${last ? 0 : 1}`, slice));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// The loop always emits m=1 on the first chunk. If the payload spanned
|
|
61
|
+
// more than two chunks, the last iteration already set m=0. If it spanned
|
|
62
|
+
// exactly two, the second iteration is last and also sets m=0.
|
|
63
|
+
return chunks.join('');
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Delete images. `all` wipes every placement. A numeric `id` deletes that
|
|
67
|
+
* image and its placements.
|
|
68
|
+
*/
|
|
69
|
+
export function encodeKittyDelete(target = 'all') {
|
|
70
|
+
if (target === 'all')
|
|
71
|
+
return apc('a=d,d=A,q=2');
|
|
72
|
+
return apc(`a=d,d=i,i=${target.id},q=2`);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Place a framebuffer through the Kitty protocol. Reuses `id`/`placementId`
|
|
76
|
+
* so the next call replaces the frame without flicker.
|
|
77
|
+
*/
|
|
78
|
+
export class KittyGraphics {
|
|
79
|
+
writer;
|
|
80
|
+
id;
|
|
81
|
+
placementId;
|
|
82
|
+
constructor(writer, options = {}) {
|
|
83
|
+
this.writer = writer;
|
|
84
|
+
this.id = options.id ?? 1;
|
|
85
|
+
this.placementId = options.placementId ?? 1;
|
|
86
|
+
}
|
|
87
|
+
draw(pixels, width, height, options = {}) {
|
|
88
|
+
this.writer.write(encodeKittyImage({
|
|
89
|
+
pixels,
|
|
90
|
+
width,
|
|
91
|
+
height,
|
|
92
|
+
id: this.id,
|
|
93
|
+
placementId: this.placementId,
|
|
94
|
+
...options,
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
/** Remove this image (or every image, when `all` is true). */
|
|
98
|
+
delete(all = false) {
|
|
99
|
+
this.writer.write(encodeKittyDelete(all ? 'all' : { id: this.id }));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Encode an RGBA/RGB framebuffer as unicode half-blocks (`▀`). Each cell
|
|
104
|
+
* holds two vertical pixels (foreground = top, background = bottom).
|
|
105
|
+
* Works in any truecolor terminal, including those without Kitty graphics.
|
|
106
|
+
*/
|
|
107
|
+
export function encodeHalfBlocks(pixels, width, height, format = 'rgba') {
|
|
108
|
+
const bpp = bytesPerPixel(format);
|
|
109
|
+
const lines = [];
|
|
110
|
+
const rows = Math.ceil(height / 2);
|
|
111
|
+
for (let cy = 0; cy < rows; cy++) {
|
|
112
|
+
let line = '';
|
|
113
|
+
const yTop = cy * 2;
|
|
114
|
+
const yBot = yTop + 1;
|
|
115
|
+
for (let x = 0; x < width; x++) {
|
|
116
|
+
const top = sample(pixels, width, height, x, yTop, bpp);
|
|
117
|
+
const bot = yBot < height ? sample(pixels, width, height, x, yBot, bpp) : top;
|
|
118
|
+
line += `\x1b[38;2;${top.r};${top.g};${top.b}m\x1b[48;2;${bot.r};${bot.g};${bot.b}m▀`;
|
|
119
|
+
}
|
|
120
|
+
line += '\x1b[0m';
|
|
121
|
+
lines.push(line);
|
|
122
|
+
}
|
|
123
|
+
return lines;
|
|
124
|
+
}
|
|
125
|
+
function sample(pixels, width, height, x, y, bpp) {
|
|
126
|
+
if (y >= height)
|
|
127
|
+
y = height - 1;
|
|
128
|
+
const i = (y * width + x) * bpp;
|
|
129
|
+
return {
|
|
130
|
+
r: pixels[i] ?? 0,
|
|
131
|
+
g: pixels[i + 1] ?? 0,
|
|
132
|
+
b: pixels[i + 2] ?? 0,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=graphics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphics.js","sourceRoot":"","sources":["../src/graphics.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
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 {
|
|
4
|
+
export { parseOscColor, parseThemeResponses, queryTerminalTheme, relativeLuminance, themeFromBackground, type Rgb, type TerminalTheme, type ThemeQueryFailure, type ThemeQueryInput, type ThemeQueryOptions, type ThemeQueryResult, } from './theme-query.js';
|
|
5
|
+
export { enterRawMode, KeyParser, parseKeys, enableKittyKeyboard, disableKittyKeyboard, KITTY_KEYBOARD, KITTY_KEYBOARD_KEYUP, type KeyEvent, type KeyKind, type KeyName } from './keys.js';
|
|
6
|
+
export { KittyGraphics, encodeHalfBlocks, encodeKittyDelete, encodeKittyImage, type KittyImageOptions, type PixelFormat, } from './graphics.js';
|
|
7
|
+
export { disableMouse, enableMouse, isMouseEvent, parseMouseEvents, type MouseButtons, type MouseEvent, type MouseModeOptions, } from './mouse.js';
|
|
5
8
|
export { Ticker, type TickerOptions } from './ticker.js';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
export { ansi } from './ansi.js';
|
|
2
2
|
export { detectCapabilities, } from './capabilities.js';
|
|
3
3
|
export { guardedOsc, osc } from './osc.js';
|
|
4
|
-
export {
|
|
4
|
+
export { parseOscColor, parseThemeResponses, queryTerminalTheme, relativeLuminance, themeFromBackground, } from './theme-query.js';
|
|
5
|
+
export { enterRawMode, KeyParser, parseKeys, enableKittyKeyboard, disableKittyKeyboard, KITTY_KEYBOARD, KITTY_KEYBOARD_KEYUP } from './keys.js';
|
|
6
|
+
export { KittyGraphics, encodeHalfBlocks, encodeKittyDelete, encodeKittyImage, } from './graphics.js';
|
|
7
|
+
export { disableMouse, enableMouse, isMouseEvent, parseMouseEvents, } from './mouse.js';
|
|
5
8
|
export { Ticker } from './ticker.js';
|
|
6
9
|
//# 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,
|
|
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,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,cAAc,EAAE,oBAAoB,EAA6C,MAAM,WAAW,CAAC;AAC3L,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,GAGjB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,gBAAgB,GAIjB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,MAAM,EAAsB,MAAM,aAAa,CAAC"}
|
package/dist/keys.d.ts
CHANGED
|
@@ -1,14 +1,47 @@
|
|
|
1
1
|
import type { ReadStream } from 'node:tty';
|
|
2
2
|
export type KeyName = 'up' | 'down' | 'left' | 'right' | 'home' | 'end' | 'page-up' | 'page-down' | 'enter' | 'escape' | 'backspace' | 'delete' | 'tab' | 'shift-tab' | 'space' | `ctrl+${string}` | `alt+${string}` | string;
|
|
3
|
+
export type KeyKind = 'press' | 'repeat' | 'release';
|
|
3
4
|
export interface KeyEvent {
|
|
4
5
|
name: KeyName;
|
|
5
6
|
/** Raw character for printable keys. */
|
|
6
7
|
ch?: string;
|
|
8
|
+
/**
|
|
9
|
+
* How the key moved. Legacy terminals only ever send `press` (and treat
|
|
10
|
+
* auto-repeat as another press). Kitty's keyboard protocol can also send
|
|
11
|
+
* `repeat` and `release`. Omitted means `press`.
|
|
12
|
+
*/
|
|
13
|
+
kind?: KeyKind;
|
|
14
|
+
readonly shift?: boolean;
|
|
15
|
+
readonly alt?: boolean;
|
|
16
|
+
readonly ctrl?: boolean;
|
|
7
17
|
}
|
|
18
|
+
/** Progressive-enhancement bits for the Kitty keyboard protocol. */
|
|
19
|
+
export declare const KITTY_KEYBOARD: {
|
|
20
|
+
/** Disambiguate Esc / alt / ctrl so they never collide with CSI. */
|
|
21
|
+
readonly disambiguate: 1;
|
|
22
|
+
/** Report press, repeat, and release as separate events. */
|
|
23
|
+
readonly eventTypes: 2;
|
|
24
|
+
/** Report shifted / base-layout alternate key codes. */
|
|
25
|
+
readonly alternateKeys: 4;
|
|
26
|
+
/** Send every key (including letters) as a CSI u event. Needed for key-up. */
|
|
27
|
+
readonly allKeys: 8;
|
|
28
|
+
/** Embed associated text in the CSI u sequence. */
|
|
29
|
+
readonly associatedText: 16;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Flags that give games real key-up: disambiguate + event types + all keys.
|
|
33
|
+
* Letter keys otherwise never produce a release event.
|
|
34
|
+
*/
|
|
35
|
+
export declare const KITTY_KEYBOARD_KEYUP: number;
|
|
36
|
+
/** Push the Kitty keyboard protocol with `flags`. Default enables key-up. */
|
|
37
|
+
export declare function enableKittyKeyboard(flags?: number): string;
|
|
38
|
+
/** Pop the Kitty keyboard protocol (restore whatever was in force before). */
|
|
39
|
+
export declare function disableKittyKeyboard(): string;
|
|
8
40
|
/**
|
|
9
41
|
* Parse a raw input buffer into key events. Pure and synchronous.
|
|
10
|
-
* Handles CSI sequences (arrows, home/end, paging, delete
|
|
11
|
-
* alt+char, control characters, and
|
|
42
|
+
* Handles CSI sequences (arrows, home/end, paging, delete, CSI u), Kitty
|
|
43
|
+
* keyboard releases, bare escape, alt+char, control characters, and
|
|
44
|
+
* printable text. APC (Kitty graphics replies) is skipped.
|
|
12
45
|
*/
|
|
13
46
|
export declare function parseKeys(buffer: string): KeyEvent[];
|
|
14
47
|
/**
|
package/dist/keys.js
CHANGED
|
@@ -1,17 +1,55 @@
|
|
|
1
|
+
import { isMouseEvent } from './mouse.js';
|
|
2
|
+
/** Progressive-enhancement bits for the Kitty keyboard protocol. */
|
|
3
|
+
export const KITTY_KEYBOARD = {
|
|
4
|
+
/** Disambiguate Esc / alt / ctrl so they never collide with CSI. */
|
|
5
|
+
disambiguate: 1,
|
|
6
|
+
/** Report press, repeat, and release as separate events. */
|
|
7
|
+
eventTypes: 2,
|
|
8
|
+
/** Report shifted / base-layout alternate key codes. */
|
|
9
|
+
alternateKeys: 4,
|
|
10
|
+
/** Send every key (including letters) as a CSI u event. Needed for key-up. */
|
|
11
|
+
allKeys: 8,
|
|
12
|
+
/** Embed associated text in the CSI u sequence. */
|
|
13
|
+
associatedText: 16,
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Flags that give games real key-up: disambiguate + event types + all keys.
|
|
17
|
+
* Letter keys otherwise never produce a release event.
|
|
18
|
+
*/
|
|
19
|
+
export const KITTY_KEYBOARD_KEYUP = KITTY_KEYBOARD.disambiguate | KITTY_KEYBOARD.eventTypes | KITTY_KEYBOARD.allKeys;
|
|
20
|
+
/** Push the Kitty keyboard protocol with `flags`. Default enables key-up. */
|
|
21
|
+
export function enableKittyKeyboard(flags = KITTY_KEYBOARD_KEYUP) {
|
|
22
|
+
return `\x1b[>${flags}u`;
|
|
23
|
+
}
|
|
24
|
+
/** Pop the Kitty keyboard protocol (restore whatever was in force before). */
|
|
25
|
+
export function disableKittyKeyboard() {
|
|
26
|
+
return '\x1b[<u';
|
|
27
|
+
}
|
|
1
28
|
/**
|
|
2
29
|
* Parse a raw input buffer into key events. Pure and synchronous.
|
|
3
|
-
* Handles CSI sequences (arrows, home/end, paging, delete
|
|
4
|
-
* alt+char, control characters, and
|
|
30
|
+
* Handles CSI sequences (arrows, home/end, paging, delete, CSI u), Kitty
|
|
31
|
+
* keyboard releases, bare escape, alt+char, control characters, and
|
|
32
|
+
* printable text. APC (Kitty graphics replies) is skipped.
|
|
5
33
|
*/
|
|
6
34
|
export function parseKeys(buffer) {
|
|
7
35
|
const events = [];
|
|
36
|
+
if (isMouseEvent(buffer))
|
|
37
|
+
return events;
|
|
8
38
|
let i = 0;
|
|
9
39
|
while (i < buffer.length) {
|
|
10
40
|
const char = buffer[i];
|
|
11
41
|
if (char === '\x1b') {
|
|
12
42
|
const rest = buffer.slice(i + 1);
|
|
43
|
+
// APC (Kitty graphics): ESC _ ... ST (ESC \). Skip, never a key.
|
|
44
|
+
if (rest.startsWith('_')) {
|
|
45
|
+
const st = rest.indexOf('\x1b\\');
|
|
46
|
+
if (st < 0)
|
|
47
|
+
break;
|
|
48
|
+
i += 1 + st + 2;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
13
51
|
if (rest.startsWith('[') || rest.startsWith('O')) {
|
|
14
|
-
const matcher = /^\[([0-9
|
|
52
|
+
const matcher = /^\[([0-9;:?]*)([\x40-\x7e])/.exec(rest) ?? /^O([\x40-\x7e])/.exec(rest);
|
|
15
53
|
if (matcher) {
|
|
16
54
|
const event = escapeSequence(matcher[1] ?? '', (matcher[2] ?? matcher[1]));
|
|
17
55
|
if (event)
|
|
@@ -19,38 +57,36 @@ export function parseKeys(buffer) {
|
|
|
19
57
|
i += 1 + matcher[0].length;
|
|
20
58
|
continue;
|
|
21
59
|
}
|
|
22
|
-
// Incomplete sequence (should not happen for complete buffers).
|
|
23
60
|
break;
|
|
24
61
|
}
|
|
25
62
|
if (rest.startsWith(' ')) {
|
|
26
63
|
const ch = rest.slice(1, 2);
|
|
27
|
-
events.push({ name: `alt+${ch}`, ch });
|
|
64
|
+
events.push({ name: `alt+${ch}`, ch, alt: true, kind: 'press' });
|
|
28
65
|
i += 2;
|
|
29
66
|
continue;
|
|
30
67
|
}
|
|
31
|
-
events.push({ name: 'escape' });
|
|
68
|
+
events.push({ name: 'escape', kind: 'press' });
|
|
32
69
|
i += 1;
|
|
33
70
|
continue;
|
|
34
71
|
}
|
|
35
72
|
if (char === '\r' || char === '\n') {
|
|
36
|
-
events.push({ name: 'enter', ch: '\r' });
|
|
73
|
+
events.push({ name: 'enter', ch: '\r', kind: 'press' });
|
|
37
74
|
i += 1;
|
|
38
75
|
continue;
|
|
39
76
|
}
|
|
40
77
|
if (char === '\x7f' || char === '\x08') {
|
|
41
|
-
events.push({ name: 'backspace' });
|
|
78
|
+
events.push({ name: 'backspace', kind: 'press' });
|
|
42
79
|
i += 1;
|
|
43
80
|
continue;
|
|
44
81
|
}
|
|
45
82
|
if (char === '\t') {
|
|
46
|
-
events.push({ name: 'tab' });
|
|
83
|
+
events.push({ name: 'tab', kind: 'press' });
|
|
47
84
|
i += 1;
|
|
48
85
|
continue;
|
|
49
86
|
}
|
|
50
87
|
if (char >= '\x01' && char <= '\x1a') {
|
|
51
|
-
// ctrl+a .. ctrl+z
|
|
52
88
|
const letter = String.fromCharCode(char.charCodeAt(0) + 96);
|
|
53
|
-
events.push({ name: `ctrl+${letter}
|
|
89
|
+
events.push({ name: `ctrl+${letter}`, ctrl: true, kind: 'press' });
|
|
54
90
|
i += 1;
|
|
55
91
|
continue;
|
|
56
92
|
}
|
|
@@ -59,48 +95,119 @@ export function parseKeys(buffer) {
|
|
|
59
95
|
continue;
|
|
60
96
|
}
|
|
61
97
|
if (char === ' ') {
|
|
62
|
-
events.push({ name: 'space', ch: ' ' });
|
|
98
|
+
events.push({ name: 'space', ch: ' ', kind: 'press' });
|
|
63
99
|
i += 1;
|
|
64
100
|
continue;
|
|
65
101
|
}
|
|
66
|
-
events.push({ name: char, ch: char });
|
|
102
|
+
events.push({ name: char, ch: char, kind: 'press' });
|
|
67
103
|
i += 1;
|
|
68
104
|
}
|
|
69
105
|
return events;
|
|
70
106
|
}
|
|
107
|
+
function parseModField(field) {
|
|
108
|
+
const [modRaw, typeRaw] = (field ?? '1').split(':');
|
|
109
|
+
const mod = Math.max(0, Number(modRaw ?? '1') - 1);
|
|
110
|
+
const typeNum = typeRaw === undefined || typeRaw === '' ? 1 : Number(typeRaw);
|
|
111
|
+
const kind = typeNum === 3 ? 'release' : typeNum === 2 ? 'repeat' : 'press';
|
|
112
|
+
return {
|
|
113
|
+
shift: (mod & 1) !== 0,
|
|
114
|
+
alt: (mod & 2) !== 0,
|
|
115
|
+
ctrl: (mod & 4) !== 0,
|
|
116
|
+
kind,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function namedKey(base, mods, ch) {
|
|
120
|
+
let name = base;
|
|
121
|
+
if (mods.ctrl && mods.alt)
|
|
122
|
+
name = `ctrl+alt+${base}`;
|
|
123
|
+
else if (mods.ctrl)
|
|
124
|
+
name = `ctrl+${base}`;
|
|
125
|
+
else if (mods.alt)
|
|
126
|
+
name = `alt+${base}`;
|
|
127
|
+
return { name, ch, kind: mods.kind, shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl };
|
|
128
|
+
}
|
|
129
|
+
/** CSI u / functional-key mapping for the Kitty keyboard protocol. */
|
|
130
|
+
function fromKeyCode(code, mods) {
|
|
131
|
+
switch (code) {
|
|
132
|
+
case 27:
|
|
133
|
+
return { name: 'escape', kind: mods.kind, shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl };
|
|
134
|
+
case 13:
|
|
135
|
+
return { name: 'enter', ch: '\r', kind: mods.kind, shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl };
|
|
136
|
+
case 9:
|
|
137
|
+
return mods.shift
|
|
138
|
+
? { name: 'shift-tab', kind: mods.kind, shift: true, alt: mods.alt, ctrl: mods.ctrl }
|
|
139
|
+
: { name: 'tab', kind: mods.kind, shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl };
|
|
140
|
+
case 127:
|
|
141
|
+
case 8:
|
|
142
|
+
return { name: 'backspace', kind: mods.kind, shift: mods.shift, alt: mods.alt, ctrl: mods.ctrl };
|
|
143
|
+
case 32:
|
|
144
|
+
return namedKey('space', mods, ' ');
|
|
145
|
+
default:
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
if (code >= 32 && code <= 126) {
|
|
149
|
+
const ch = String.fromCharCode(code);
|
|
150
|
+
const base = ch === ' ' ? 'space' : ch;
|
|
151
|
+
return namedKey(base, mods, ch);
|
|
152
|
+
}
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
71
155
|
function escapeSequence(code, letter) {
|
|
72
|
-
const
|
|
156
|
+
const fields = code.split(';');
|
|
157
|
+
const first = fields[0] ?? '';
|
|
158
|
+
const mods = parseModField(fields[1]);
|
|
159
|
+
if (letter === 'u') {
|
|
160
|
+
// CSI ? flags u is a keyboard-flags query reply, not a key.
|
|
161
|
+
if (first.startsWith('?'))
|
|
162
|
+
return null;
|
|
163
|
+
const keyCode = Number((first.split(':')[0] ?? '').replace('?', ''));
|
|
164
|
+
if (!Number.isFinite(keyCode))
|
|
165
|
+
return null;
|
|
166
|
+
return fromKeyCode(keyCode, mods);
|
|
167
|
+
}
|
|
168
|
+
const nav = (name) => ({
|
|
169
|
+
name,
|
|
170
|
+
kind: mods.kind,
|
|
171
|
+
shift: mods.shift,
|
|
172
|
+
alt: mods.alt,
|
|
173
|
+
ctrl: mods.ctrl,
|
|
174
|
+
});
|
|
73
175
|
switch (letter) {
|
|
74
176
|
case 'A':
|
|
75
|
-
return
|
|
177
|
+
return nav('up');
|
|
76
178
|
case 'B':
|
|
77
|
-
return
|
|
179
|
+
return nav('down');
|
|
78
180
|
case 'C':
|
|
79
|
-
return
|
|
181
|
+
return nav('right');
|
|
80
182
|
case 'D':
|
|
81
|
-
return
|
|
183
|
+
return nav('left');
|
|
82
184
|
case 'H':
|
|
83
|
-
return
|
|
185
|
+
return nav('home');
|
|
84
186
|
case 'F':
|
|
85
|
-
return
|
|
187
|
+
return nav('end');
|
|
86
188
|
case 'Z':
|
|
87
|
-
return { name: 'shift-tab' };
|
|
88
|
-
case '~':
|
|
189
|
+
return { name: 'shift-tab', kind: mods.kind, shift: true, alt: mods.alt, ctrl: mods.ctrl };
|
|
190
|
+
case '~': {
|
|
191
|
+
const param = first.split(':')[0] ?? '';
|
|
89
192
|
switch (param) {
|
|
90
193
|
case '1':
|
|
91
|
-
|
|
194
|
+
case '7':
|
|
195
|
+
return nav('home');
|
|
92
196
|
case '2':
|
|
197
|
+
return nav('delete');
|
|
93
198
|
case '3':
|
|
94
|
-
return
|
|
199
|
+
return nav('delete');
|
|
95
200
|
case '4':
|
|
96
|
-
|
|
201
|
+
case '8':
|
|
202
|
+
return nav('end');
|
|
97
203
|
case '5':
|
|
98
|
-
return
|
|
204
|
+
return nav('page-up');
|
|
99
205
|
case '6':
|
|
100
|
-
return
|
|
206
|
+
return nav('page-down');
|
|
101
207
|
default:
|
|
102
208
|
return null;
|
|
103
209
|
}
|
|
210
|
+
}
|
|
104
211
|
default:
|
|
105
212
|
return null;
|
|
106
213
|
}
|
|
@@ -118,6 +225,8 @@ export class KeyParser {
|
|
|
118
225
|
return [];
|
|
119
226
|
const ready = this.pending.slice(0, safe);
|
|
120
227
|
this.pending = this.pending.slice(safe);
|
|
228
|
+
if (isMouseEvent(ready))
|
|
229
|
+
return [];
|
|
121
230
|
return parseKeys(ready);
|
|
122
231
|
}
|
|
123
232
|
/** Index up to which the buffer can be split without cutting a sequence. */
|
|
@@ -126,14 +235,26 @@ export class KeyParser {
|
|
|
126
235
|
if (esc < 0)
|
|
127
236
|
return text.length;
|
|
128
237
|
const rest = text.slice(esc + 1);
|
|
238
|
+
// ST (ESC \): terminator of an APC. The sequence ends two bytes later.
|
|
239
|
+
if (rest.startsWith('\\'))
|
|
240
|
+
return esc + 2;
|
|
241
|
+
if (rest.startsWith('_')) {
|
|
242
|
+
return rest.includes('\x1b\\') ? text.length : -1;
|
|
243
|
+
}
|
|
244
|
+
if (rest.startsWith('[<')) {
|
|
245
|
+
return /^\[<\d+;\d+;\d+[Mm]$/.test(rest) ? text.length : -1;
|
|
246
|
+
}
|
|
247
|
+
if (rest.startsWith('[') && /\d+;\d+;\d+M$/.test(rest)) {
|
|
248
|
+
return text.length;
|
|
249
|
+
}
|
|
250
|
+
if (rest.startsWith('M')) {
|
|
251
|
+
return /^M[\x20-\x7f]{3}$/.test(rest) ? text.length : -1;
|
|
252
|
+
}
|
|
129
253
|
if (rest.length === 0) {
|
|
130
|
-
// Trailing lone ESC at a chunk boundary: terminals deliver CSI
|
|
131
|
-
// sequences as single reads, so a bare ESC here IS the escape key.
|
|
132
254
|
return esc + 1;
|
|
133
255
|
}
|
|
134
256
|
if (rest[0] === '[') {
|
|
135
|
-
|
|
136
|
-
return /^\[[0-9;?]*[\x40-\x7e]$/.test(rest) ? text.length : -1;
|
|
257
|
+
return /^\[[0-9;:?]*[\x40-\x7e]$/.test(rest) ? text.length : -1;
|
|
137
258
|
}
|
|
138
259
|
if (rest[0] === 'O') {
|
|
139
260
|
return /^O[\x40-\x7e]$/.test(rest) ? text.length : -1;
|
|
@@ -141,7 +262,6 @@ export class KeyParser {
|
|
|
141
262
|
if (rest[0] === ' ') {
|
|
142
263
|
return rest.length >= 2 ? text.length : -1;
|
|
143
264
|
}
|
|
144
|
-
// Bare escape followed by other data: the escape itself is complete.
|
|
145
265
|
return esc + 1;
|
|
146
266
|
}
|
|
147
267
|
}
|
package/dist/keys.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keys.js","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"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"}
|
|
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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mudah-cli/terminal",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Terminal capability detection, OSC
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "Terminal capability detection, OSC emitters, Kitty graphics, Kitty keyboard (key-up), and key/mouse parsing.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"engines": {
|