-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcsi.ts
81 lines (78 loc) · 2.23 KB
/
csi.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import { parseSgr, type Sgr } from "./sgr.ts";
export const patternCsi =
// deno-lint-ignore no-control-regex
/\x1b\[([0-9:;<=>?]*[!"#$%&'()*+,-.\/]*[@A-Z\[\]\\^_`a-z{|}~])/;
export type Csi = {
/** Cursor Up */
cuu?: number;
/** Cursor Down */
cud?: number;
/** Cursor Forward */
cuf?: number;
/** Cursor Back */
cub?: number;
/** Cursor Next Line */
cnl?: number;
/** Cursor Previous Line */
cpl?: number;
/** Cursor Horizontal Absolute */
cha?: number;
/** Cursor Position */
cup?: [number, number];
/** Erase in Display */
ed?: number;
/** Erase in Line */
el?: number;
/** Scroll Up */
su?: number;
/** Scroll Down */
sd?: number;
/** Horizontal Vertical Position */
hvp?: [number, number];
/** Select Graphic Rendition */
sgr?: Sgr;
/** Device Status Report */
dsr?: true;
};
/**
* Parse CSI sequence and return `Csi` object
*
* It throws an error when `sequence` is not CSI sequence.
*/
export function parseCsi(sequence: string): Csi {
const m = sequence.match(patternCsi);
if (!m) {
throw new Error(`Failed to parse CSI sequence '${sequence}'`);
}
let expr = m[1];
const csi: Csi = {};
const ps: [RegExp, (m: RegExpMatchArray) => void][] = [
[/(\d*)A/, (m) => csi.cuu = Number(m[1] || 1)],
[/(\d*)B/, (m) => csi.cud = Number(m[1] || 1)],
[/(\d*)C/, (m) => csi.cuf = Number(m[1] || 1)],
[/(\d*)D/, (m) => csi.cub = Number(m[1] || 1)],
[/(\d*)E/, (m) => csi.cnl = Number(m[1] || 1)],
[/(\d*)F/, (m) => csi.cpl = Number(m[1] || 1)],
[/(\d*)G/, (m) => csi.cha = Number(m[1] || 1)],
[/(\d*);(\d*)H/, (m) => csi.cup = [Number(m[1] || 1), Number(m[2] || 1)]],
[/(\d*)J/, (m) => csi.ed = Number(m[1] || 0)],
[/(\d*)K/, (m) => csi.el = Number(m[1] || 0)],
[/(\d*)S/, (m) => csi.su = Number(m[1] || 1)],
[/(\d*)T/, (m) => csi.sd = Number(m[1] || 1)],
[/(\d+);(\d+)f/, (m) => csi.hvp = [Number(m[1]), Number(m[2])]],
[/([\d;]*)m/, (m) => csi.sgr = parseSgr(m[1])],
[/6n/, () => csi.dsr = true],
[/^.*/, () => {}],
];
while (expr) {
for (const [p, handler] of ps) {
const m = expr.match(p);
if (m) {
handler(m);
expr = expr.substring(m[0].length);
break;
}
}
}
return csi;
}