@ansi-tools/parser 0.0.0 → 0.0.1

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.
@@ -1,47 +0,0 @@
1
- import { test } from "node:test";
2
- import assert from "node:assert/strict";
3
- import { parseDCS } from "./dcs.ts";
4
- import { CODE_TYPES } from "../constants.ts";
5
-
6
- test("parseDCS simple sequence", () => {
7
- const result = parseDCS(0, "\\eP0;1|name\\e\\\\", "0;1|name");
8
- assert.deepEqual(result, {
9
- type: CODE_TYPES.DCS,
10
- pos: 0,
11
- raw: "\\eP0;1|name\\e\\\\",
12
- params: ["0;1|name"],
13
- command: "",
14
- });
15
- });
16
-
17
- test("parseDCS with missing parameters", () => {
18
- const result = parseDCS(0, "\\eP$q;\\e\\\\", "$q;");
19
- assert.deepEqual(result, {
20
- type: CODE_TYPES.DCS,
21
- pos: 0,
22
- raw: "\\eP$q;\\e\\\\",
23
- params: ["-1", "-1"],
24
- command: "$q",
25
- });
26
- });
27
-
28
- test("parseDCS with known pattern", () => {
29
- const result = parseDCS(0, "\\eP$qm\\e\\\\", "$qm");
30
- assert.deepEqual(result, { type: CODE_TYPES.DCS, pos: 0, raw: "\\eP$qm\\e\\\\", params: ["m"], command: "$q" });
31
- });
32
-
33
- test("parseDCS empty data", () => {
34
- const result = parseDCS(0, "\\eP\\e\\\\", "");
35
- assert.deepEqual(result, { type: CODE_TYPES.DCS, pos: 0, raw: "\\eP\\e\\\\", command: "", params: [] });
36
- });
37
-
38
- test("parseDCS unknown pattern", () => {
39
- const result = parseDCS(0, "\\ePunknown\\e\\\\", "unknown");
40
- assert.deepEqual(result, {
41
- type: CODE_TYPES.DCS,
42
- pos: 0,
43
- raw: "\\ePunknown\\e\\\\",
44
- command: "",
45
- params: ["unknown"],
46
- });
47
- });
@@ -1,36 +0,0 @@
1
- import { CODE_TYPES } from "../constants.ts";
2
- import type { CONTROL_CODE } from "../types.ts";
3
-
4
- const DCS_PATTERNS = new Map([
5
- ["$q", 2],
6
- ["+q", 2],
7
- ["+p", 2],
8
- ["|", 1],
9
- ["{", 1],
10
- ]);
11
-
12
- export function parseDCS(pos: number, raw: string, data: string): CONTROL_CODE {
13
- if (!data) return { type: CODE_TYPES.DCS, pos, raw, command: "", params: [] };
14
-
15
- for (const [pattern, length] of DCS_PATTERNS) {
16
- if (data.startsWith(pattern)) {
17
- const remainder = data.slice(length);
18
- const params = [];
19
- if (remainder) {
20
- let current = "";
21
- for (let i = 0; i < remainder.length; i++) {
22
- if (remainder[i] === ";") {
23
- params.push(current || "-1");
24
- current = "";
25
- } else {
26
- current += remainder[i];
27
- }
28
- }
29
- params.push(current || "-1");
30
- }
31
- return { type: CODE_TYPES.DCS, pos, raw, command: pattern, params };
32
- }
33
- }
34
-
35
- return { type: CODE_TYPES.DCS, pos, raw, command: "", params: [data] };
36
- }
@@ -1,24 +0,0 @@
1
- import { test } from "node:test";
2
- import assert from "node:assert/strict";
3
- import { parseDEC } from "./dec.ts";
4
- import { CODE_TYPES } from "../constants.ts";
5
-
6
- test("parseDEC basic sequence", () => {
7
- const result = parseDEC(0, "\\e[?25h", "?25", "h");
8
- assert.deepEqual(result, { type: CODE_TYPES.DEC, pos: 0, raw: "\\e[?25h", params: ["25"], command: "h" });
9
- });
10
-
11
- test("parseDEC with missing parameters", () => {
12
- const result = parseDEC(0, "\\e[?;h", "?;", "h");
13
- assert.deepEqual(result, { type: CODE_TYPES.DEC, pos: 0, raw: "\\e[?;h", params: ["-1", "-1"], command: "h" });
14
- });
15
-
16
- test("parseDEC with intermediate bytes", () => {
17
- const result = parseDEC(0, "\\e[?1$p", "?1$", "p");
18
- assert.deepEqual(result, { type: CODE_TYPES.DEC, pos: 0, raw: "\\e[?1$p", params: ["1"], command: "$p" });
19
- });
20
-
21
- test("parseDEC multiple parameters with intermediates", () => {
22
- const result = parseDEC(0, "\\e[?1;2$p", "?1;2$", "p");
23
- assert.deepEqual(result, { type: CODE_TYPES.DEC, pos: 0, raw: "\\e[?1;2$p", params: ["1", "2"], command: "$p" });
24
- });
@@ -1,30 +0,0 @@
1
- import { CODE_TYPES } from "../constants.ts";
2
- import type { CONTROL_CODE } from "../types.ts";
3
-
4
- export function parseDEC(pos: number, raw: string, data: string, final: string): CONTROL_CODE {
5
- const withoutPrefix = data.slice(1);
6
- let i = 0;
7
- let paramsRaw = "";
8
- while (
9
- i < withoutPrefix.length &&
10
- ((withoutPrefix.charCodeAt(i) >= 48 && withoutPrefix.charCodeAt(i) <= 57) || withoutPrefix[i] === ";")
11
- ) {
12
- paramsRaw += withoutPrefix[i];
13
- i++;
14
- }
15
- const command = withoutPrefix.slice(i) + final;
16
- const params = [];
17
- if (paramsRaw) {
18
- let current = "";
19
- for (let j = 0; j < paramsRaw.length; j++) {
20
- if (paramsRaw[j] === ";") {
21
- params.push(current || "-1");
22
- current = "";
23
- } else {
24
- current += paramsRaw[j];
25
- }
26
- }
27
- params.push(current || "-1");
28
- }
29
- return { type: CODE_TYPES.DEC, pos, raw, command, params };
30
- }
@@ -1,19 +0,0 @@
1
- import { test } from "node:test";
2
- import assert from "node:assert/strict";
3
- import { parseESC } from "./esc.ts";
4
- import { CODE_TYPES } from "../constants.ts";
5
-
6
- test("parseESC simple command", () => {
7
- const result = parseESC(0, "\\e=", "=");
8
- assert.deepEqual(result, { type: CODE_TYPES.ESC, pos: 0, raw: "\\e=", command: "=", params: [] });
9
- });
10
-
11
- test("parseESC with data", () => {
12
- const result = parseESC(0, "\\e(A", "(", "A");
13
- assert.deepEqual(result, { type: CODE_TYPES.ESC, pos: 0, raw: "\\e(A", command: "(", params: ["A"] });
14
- });
15
-
16
- test("parseESC charset sequence", () => {
17
- const result = parseESC(0, "\\e)A", ")", "A");
18
- assert.deepEqual(result, { type: CODE_TYPES.ESC, pos: 0, raw: "\\e)A", command: ")", params: ["A"] });
19
- });
@@ -1,6 +0,0 @@
1
- import { CODE_TYPES } from "../constants.ts";
2
- import type { CONTROL_CODE } from "../types.ts";
3
-
4
- export function parseESC(pos: number, raw: string, command: string, data?: string): CONTROL_CODE {
5
- return { type: CODE_TYPES.ESC, pos, raw, command, params: data ? [data] : [] };
6
- }
@@ -1,36 +0,0 @@
1
- import { test } from "node:test";
2
- import assert from "node:assert/strict";
3
- import { parseOSC } from "./osc.ts";
4
- import { CODE_TYPES } from "../constants.ts";
5
-
6
- test("parseOSC simple command", () => {
7
- const result = parseOSC(0, "\\e]8;;http://example.com\\a", "8;;http://example.com");
8
- assert.deepEqual(result, {
9
- type: CODE_TYPES.OSC,
10
- pos: 0,
11
- raw: "\\e]8;;http://example.com\\a",
12
- params: ["", "http://example.com"],
13
- command: "8",
14
- });
15
- });
16
-
17
- test("parseOSC no parameters", () => {
18
- const result = parseOSC(0, "\\e]0\\a", "0");
19
- assert.deepEqual(result, { type: CODE_TYPES.OSC, pos: 0, raw: "\\e]0\\a", command: "0", params: [] });
20
- });
21
-
22
- test("parseOSC with trailing semicolon (empty remainder)", () => {
23
- const result = parseOSC(0, "\\e]8;\\a", "8;");
24
- assert.deepEqual(result, { type: CODE_TYPES.OSC, pos: 0, raw: "\\e]8;\\a", command: "8", params: [] });
25
- });
26
-
27
- test("parseOSC real-world example", () => {
28
- const result = parseOSC(0, "\\e]2;Window Title\\a", "2;Window Title");
29
- assert.deepEqual(result, {
30
- type: CODE_TYPES.OSC,
31
- pos: 0,
32
- raw: "\\e]2;Window Title\\a",
33
- command: "2",
34
- params: ["Window Title"],
35
- });
36
- });
@@ -1,29 +0,0 @@
1
- import { CODE_TYPES } from "../constants.ts";
2
- import type { CONTROL_CODE } from "../types.ts";
3
-
4
- export function parseOSC(pos: number, raw: string, data: string): CONTROL_CODE {
5
- const semicolonIndex = data.indexOf(";");
6
- if (semicolonIndex === -1) {
7
- return { type: CODE_TYPES.OSC, pos, raw, command: data, params: [] };
8
- }
9
- const command = data.slice(0, semicolonIndex);
10
- const remainder = data.slice(semicolonIndex + 1);
11
-
12
- if (command === "1337") return { type: CODE_TYPES.OSC, pos, raw, command, params: [remainder] };
13
-
14
- const params = [];
15
- if (remainder) {
16
- let current = "";
17
- for (let i = 0; i < remainder.length; i++) {
18
- if (remainder[i] === ";") {
19
- params.push(current);
20
- current = "";
21
- } else {
22
- current += remainder[i];
23
- }
24
- }
25
- params.push(current);
26
- }
27
-
28
- return { type: CODE_TYPES.OSC, pos, raw, command, params };
29
- }
@@ -1,410 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import { test } from "node:test";
3
- import { tokenizer } from "./tokenize.escaped.ts";
4
- import type { TOKEN } from "./types.ts";
5
-
6
- test("empty", () => {
7
- const input = "";
8
- const tokens: TOKEN[] = [...tokenizer(input)];
9
- assert.deepEqual(tokens, []);
10
- });
11
-
12
- test("text", () => {
13
- const input = "Hello, world!";
14
- const tokens: TOKEN[] = [...tokenizer(input)];
15
- assert.deepEqual(tokens, [{ type: "TEXT", pos: 0, raw: "Hello, world!" }]);
16
- });
17
-
18
- test("CSI", () => {
19
- const input = String.raw`\x1b[31m`;
20
- const tokens: TOKEN[] = [...tokenizer(input)];
21
- assert.deepEqual(tokens, [
22
- { type: "INTRODUCER", pos: 0, raw: "\\x1b[", code: "\x9b" },
23
- { type: "DATA", pos: 5, raw: "31" },
24
- { type: "FINAL", pos: 7, raw: "m" },
25
- ]);
26
- });
27
-
28
- test("OSC", () => {
29
- const input = String.raw`\x1b]0;title\x07`;
30
- const tokens: TOKEN[] = [...tokenizer(input)];
31
- assert.deepEqual(tokens, [
32
- { type: "INTRODUCER", pos: 0, raw: "\\x1b]", code: "\x9d" },
33
- { type: "DATA", pos: 5, raw: "0;title" },
34
- { type: "FINAL", pos: 12, raw: "\\x07" },
35
- ]);
36
- });
37
-
38
- test("multiple", () => {
39
- const input = String.raw`\x1b[31m\x1b]0;title\x07`;
40
- const tokens: TOKEN[] = [...tokenizer(input)];
41
- assert.deepEqual(tokens, [
42
- { type: "INTRODUCER", pos: 0, raw: "\\x1b[", code: "\x9b" },
43
- { type: "DATA", pos: 5, raw: "31" },
44
- { type: "FINAL", pos: 7, raw: "m" },
45
- { type: "INTRODUCER", pos: 8, raw: "\\x1b]", code: "\x9d" },
46
- { type: "DATA", pos: 13, raw: "0;title" },
47
- { type: "FINAL", pos: 20, raw: "\\x07" },
48
- ]);
49
- });
50
-
51
- test("mixed", () => {
52
- const input = String.raw`Hello, \x1b[31mworld\x1b]0;title\x07!`;
53
- const tokens: TOKEN[] = [...tokenizer(input)];
54
- assert.deepEqual(tokens, [
55
- { type: "TEXT", pos: 0, raw: "Hello, " },
56
- { type: "INTRODUCER", pos: 7, raw: "\\x1b[", code: "\x9b" },
57
- { type: "DATA", pos: 12, raw: "31" },
58
- { type: "FINAL", pos: 14, raw: "m" },
59
- { type: "TEXT", pos: 15, raw: "world" },
60
- { type: "INTRODUCER", pos: 20, raw: "\\x1b]", code: "\x9d" },
61
- { type: "DATA", pos: 25, raw: "0;title" },
62
- { type: "FINAL", pos: 32, raw: "\\x07" },
63
- { type: "TEXT", pos: 36, raw: "!" },
64
- ]);
65
- });
66
-
67
- test("colors (rgb)", () => {
68
- const input = String.raw`\x1b[38;2;255;255;0mH\x1b[0;1;3;35me\x1b[95ml\x1b[42ml\x1b[0;41mo\x1b[0m`;
69
- const tokens: TOKEN[] = [...tokenizer(input)];
70
- assert.deepEqual(tokens, [
71
- { type: "INTRODUCER", pos: 0, raw: "\\x1b[", code: "\x9b" },
72
- { type: "DATA", pos: 5, raw: "38;2;255;255;0" },
73
- { type: "FINAL", pos: 19, raw: "m" },
74
- { type: "TEXT", pos: 20, raw: "H" },
75
- { type: "INTRODUCER", pos: 21, raw: "\\x1b[", code: "\x9b" },
76
- { type: "DATA", pos: 26, raw: "0;1;3;35" },
77
- { type: "FINAL", pos: 34, raw: "m" },
78
- { type: "TEXT", pos: 35, raw: "e" },
79
- { type: "INTRODUCER", pos: 36, raw: "\\x1b[", code: "\x9b" },
80
- { type: "DATA", pos: 41, raw: "95" },
81
- { type: "FINAL", pos: 43, raw: "m" },
82
- { type: "TEXT", pos: 44, raw: "l" },
83
- { type: "INTRODUCER", pos: 45, raw: "\\x1b[", code: "\x9b" },
84
- { type: "DATA", pos: 50, raw: "42" },
85
- { type: "FINAL", pos: 52, raw: "m" },
86
- { type: "TEXT", pos: 53, raw: "l" },
87
- { type: "INTRODUCER", pos: 54, raw: "\\x1b[", code: "\x9b" },
88
- { type: "DATA", pos: 59, raw: "0;41" },
89
- { type: "FINAL", pos: 63, raw: "m" },
90
- { type: "TEXT", pos: 64, raw: "o" },
91
- { type: "INTRODUCER", pos: 65, raw: "\\x1b[", code: "\x9b" },
92
- { type: "DATA", pos: 70, raw: "0" },
93
- { type: "FINAL", pos: 71, raw: "m" },
94
- ]);
95
- });
96
-
97
- test("colors", () => {
98
- const input = String.raw`\u001b[31mRed\u001b[39m, \u001b[32mgreen\u001b[39m, and \u001b[44mblue background\u001b[49m.`;
99
- const tokens: TOKEN[] = [...tokenizer(input)];
100
- assert.deepEqual(tokens, [
101
- { type: "INTRODUCER", pos: 0, raw: "\\u001b[", code: "\x9b" },
102
- { type: "DATA", pos: 7, raw: "31" },
103
- { type: "FINAL", pos: 9, raw: "m" },
104
- { type: "TEXT", pos: 10, raw: "Red" },
105
- { type: "INTRODUCER", pos: 13, raw: "\\u001b[", code: "\x9b" },
106
- { type: "DATA", pos: 20, raw: "39" },
107
- { type: "FINAL", pos: 22, raw: "m" },
108
- { type: "TEXT", pos: 23, raw: ", " },
109
- { type: "INTRODUCER", pos: 25, raw: "\\u001b[", code: "\x9b" },
110
- { type: "DATA", pos: 32, raw: "32" },
111
- { type: "FINAL", pos: 34, raw: "m" },
112
- { type: "TEXT", pos: 35, raw: "green" },
113
- { type: "INTRODUCER", pos: 40, raw: "\\u001b[", code: "\x9b" },
114
- { type: "DATA", pos: 47, raw: "39" },
115
- { type: "FINAL", pos: 49, raw: "m" },
116
- { type: "TEXT", pos: 50, raw: ", and " },
117
- { type: "INTRODUCER", pos: 56, raw: "\\u001b[", code: "\x9b" },
118
- { type: "DATA", pos: 63, raw: "44" },
119
- { type: "FINAL", pos: 65, raw: "m" },
120
- { type: "TEXT", pos: 66, raw: "blue background" },
121
- { type: "INTRODUCER", pos: 81, raw: "\\u001b[", code: "\x9b" },
122
- { type: "DATA", pos: 88, raw: "49" },
123
- { type: "FINAL", pos: 90, raw: "m" },
124
- { type: "TEXT", pos: 91, raw: "." },
125
- ]);
126
- });
127
-
128
- test("cursor", () => {
129
- const input = String.raw`\x1b[3A\x1b[4D\x1b[shello\x1b[J\x1b[1;3Hworld\x1b[u\x1b[13T`;
130
- const tokens: TOKEN[] = [...tokenizer(input)];
131
- assert.deepEqual(tokens, [
132
- { type: "INTRODUCER", pos: 0, raw: "\\x1b[", code: "\x9b" },
133
- { type: "DATA", pos: 5, raw: "3" },
134
- { type: "FINAL", pos: 6, raw: "A" },
135
- { type: "INTRODUCER", pos: 7, raw: "\\x1b[", code: "\x9b" },
136
- { type: "DATA", pos: 12, raw: "4" },
137
- { type: "FINAL", pos: 13, raw: "D" },
138
- { type: "INTRODUCER", pos: 14, raw: "\\x1b[", code: "\x9b" },
139
- { type: "FINAL", pos: 19, raw: "s" },
140
- { type: "TEXT", pos: 20, raw: "hello" },
141
- { type: "INTRODUCER", pos: 25, raw: "\\x1b[", code: "\x9b" },
142
- { type: "FINAL", pos: 30, raw: "J" },
143
- { type: "INTRODUCER", pos: 31, raw: "\\x1b[", code: "\x9b" },
144
- { type: "DATA", pos: 36, raw: "1;3" },
145
- { type: "FINAL", pos: 39, raw: "H" },
146
- { type: "TEXT", pos: 40, raw: "world" },
147
- { type: "INTRODUCER", pos: 45, raw: "\\x1b[", code: "\x9b" },
148
- { type: "FINAL", pos: 50, raw: "u" },
149
- { type: "INTRODUCER", pos: 51, raw: "\\x1b[", code: "\x9b" },
150
- { type: "DATA", pos: 56, raw: "13" },
151
- { type: "FINAL", pos: 58, raw: "T" },
152
- ]);
153
- });
154
-
155
- test("mixed", () => {
156
- const input = String.raw`\x1b[A\r\x1b[K\x1b[1;32mOpened \x1b[1;4;34m%s\x1b[0;1;32m in your browser.\x1b[0m\n\n⭐ → ✨\n\n這裡有一些中文文字。\n\nThe End.`;
157
- const tokens: TOKEN[] = [...tokenizer(input)];
158
- assert.deepEqual(tokens, [
159
- { type: "INTRODUCER", pos: 0, raw: "\\x1b[", code: "\x9b" },
160
- { type: "FINAL", pos: 5, raw: "A" },
161
- { type: "TEXT", pos: 6, raw: "\\r" },
162
- { type: "INTRODUCER", pos: 8, raw: "\\x1b[", code: "\x9b" },
163
- { type: "FINAL", pos: 13, raw: "K" },
164
- { type: "INTRODUCER", pos: 14, raw: "\\x1b[", code: "\x9b" },
165
- { type: "DATA", pos: 19, raw: "1;32" },
166
- { type: "FINAL", pos: 23, raw: "m" },
167
- { type: "TEXT", pos: 24, raw: "Opened " },
168
- { type: "INTRODUCER", pos: 31, raw: "\\x1b[", code: "\x9b" },
169
- { type: "DATA", pos: 36, raw: "1;4;34" },
170
- { type: "FINAL", pos: 42, raw: "m" },
171
- { type: "TEXT", pos: 43, raw: "%s" },
172
- { type: "INTRODUCER", pos: 45, raw: "\\x1b[", code: "\x9b" },
173
- { type: "DATA", pos: 50, raw: "0;1;32" },
174
- { type: "FINAL", pos: 56, raw: "m" },
175
- { type: "TEXT", pos: 57, raw: " in your browser." },
176
- { type: "INTRODUCER", pos: 74, raw: "\\x1b[", code: "\x9b" },
177
- { type: "DATA", pos: 79, raw: "0" },
178
- { type: "FINAL", pos: 80, raw: "m" },
179
- { type: "TEXT", pos: 81, raw: "\\n\\n⭐ → ✨\\n\\n這裡有一些中文文字。\\n\\nThe End." },
180
- ]);
181
- });
182
-
183
- test("styles", () => {
184
- const input = String.raw`\u001b[1mBold\u001b[22m, \u001b[3mItalic\u001b[23m, \u001b[4mUnderline\u001b[24m, and \u001b[9mStrikethrough\u001b[29m.`;
185
- const tokens: TOKEN[] = [...tokenizer(input)];
186
- assert.deepEqual(tokens, [
187
- { type: "INTRODUCER", pos: 0, raw: "\\u001b[", code: "\x9b" },
188
- { type: "DATA", pos: 7, raw: "1" },
189
- { type: "FINAL", pos: 8, raw: "m" },
190
- { type: "TEXT", pos: 9, raw: "Bold" },
191
- { type: "INTRODUCER", pos: 13, raw: "\\u001b[", code: "\x9b" },
192
- { type: "DATA", pos: 20, raw: "22" },
193
- { type: "FINAL", pos: 22, raw: "m" },
194
- { type: "TEXT", pos: 23, raw: ", " },
195
- { type: "INTRODUCER", pos: 25, raw: "\\u001b[", code: "\x9b" },
196
- { type: "DATA", pos: 32, raw: "3" },
197
- { type: "FINAL", pos: 33, raw: "m" },
198
- { type: "TEXT", pos: 34, raw: "Italic" },
199
- { type: "INTRODUCER", pos: 40, raw: "\\u001b[", code: "\x9b" },
200
- { type: "DATA", pos: 47, raw: "23" },
201
- { type: "FINAL", pos: 49, raw: "m" },
202
- { type: "TEXT", pos: 50, raw: ", " },
203
- { type: "INTRODUCER", pos: 52, raw: "\\u001b[", code: "\x9b" },
204
- { type: "DATA", pos: 59, raw: "4" },
205
- { type: "FINAL", pos: 60, raw: "m" },
206
- { type: "TEXT", pos: 61, raw: "Underline" },
207
- { type: "INTRODUCER", pos: 70, raw: "\\u001b[", code: "\x9b" },
208
- { type: "DATA", pos: 77, raw: "24" },
209
- { type: "FINAL", pos: 79, raw: "m" },
210
- { type: "TEXT", pos: 80, raw: ", and " },
211
- { type: "INTRODUCER", pos: 86, raw: "\\u001b[", code: "\x9b" },
212
- { type: "DATA", pos: 93, raw: "9" },
213
- { type: "FINAL", pos: 94, raw: "m" },
214
- { type: "TEXT", pos: 95, raw: "Strikethrough" },
215
- { type: "INTRODUCER", pos: 108, raw: "\\u001b[", code: "\x9b" },
216
- { type: "DATA", pos: 115, raw: "29" },
217
- { type: "FINAL", pos: 117, raw: "m" },
218
- { type: "TEXT", pos: 118, raw: "." },
219
- ]);
220
- });
221
-
222
- test("commands", () => {
223
- const input = String.raw`\u001bc\u001b[2J\u001b[3J\u001b[?25l\u001b]0;Set Title\u0007An example of terminal commands.`;
224
- const tokens: TOKEN[] = [...tokenizer(input)];
225
- assert.deepEqual(tokens, [
226
- { type: "INTRODUCER", pos: 0, raw: "\\u001b", code: "\x1b" },
227
- { type: "FINAL", pos: 6, raw: "c" },
228
- { type: "INTRODUCER", pos: 7, raw: "\\u001b[", code: "\x9b" },
229
- { type: "DATA", pos: 14, raw: "2" },
230
- { type: "FINAL", pos: 15, raw: "J" },
231
- { type: "INTRODUCER", pos: 16, raw: "\\u001b[", code: "\x9b" },
232
- { type: "DATA", pos: 23, raw: "3" },
233
- { type: "FINAL", pos: 24, raw: "J" },
234
- { type: "INTRODUCER", pos: 25, raw: "\\u001b[", code: "\x9b" },
235
- { type: "DATA", pos: 32, raw: "?25" },
236
- { type: "FINAL", pos: 35, raw: "l" },
237
- { type: "INTRODUCER", pos: 36, raw: "\\u001b]", code: "\x9d" },
238
- { type: "DATA", pos: 43, raw: "0;Set Title" },
239
- { type: "FINAL", pos: 54, raw: "\\u0007" },
240
- { type: "TEXT", pos: 60, raw: "An example of terminal commands." },
241
- ]);
242
- });
243
-
244
- test("8-bit", () => {
245
- const input = String.raw`\u009b32mGreen text\u009b0m.`;
246
- const tokens: TOKEN[] = [...tokenizer(input)];
247
- assert.deepEqual(tokens, [
248
- { type: "INTRODUCER", pos: 0, raw: "\\u009b", code: "\x9b" },
249
- { type: "DATA", pos: 6, raw: "32" },
250
- { type: "FINAL", pos: 8, raw: "m" },
251
- { type: "TEXT", pos: 9, raw: "Green text" },
252
- { type: "INTRODUCER", pos: 19, raw: "\\u009b", code: "\x9b" },
253
- { type: "DATA", pos: 25, raw: "0" },
254
- { type: "FINAL", pos: 26, raw: "m" },
255
- { type: "TEXT", pos: 27, raw: "." },
256
- ]);
257
- });
258
-
259
- test("OSC terminator", () => {
260
- const input = String.raw`\x1b]0;title\x1b\\`;
261
- const tokens: TOKEN[] = [...tokenizer(input)];
262
- assert.deepEqual(tokens, [
263
- { type: "INTRODUCER", pos: 0, raw: "\\x1b]", code: "\x9d" },
264
- { type: "DATA", pos: 5, raw: "0;title" },
265
- { type: "FINAL", pos: 12, raw: "\\x1b\\\\" },
266
- ]);
267
- });
268
-
269
- test("Set G1 Charset to UK", () => {
270
- const input = String.raw`\x1b(Ab`;
271
- const tokens: TOKEN[] = [...tokenizer(input)];
272
- assert.deepEqual(tokens, [
273
- { type: "INTRODUCER", pos: 0, raw: "\\x1b(", code: "\x9b" },
274
- { type: "FINAL", pos: 5, raw: "A" },
275
- { type: "TEXT", pos: 6, raw: "b" },
276
- ]);
277
- });
278
-
279
- test("Set G1 Charset to UK (no intermediate)", () => {
280
- const input = String.raw`\x1b)B`;
281
- const tokens: TOKEN[] = [...tokenizer(input)];
282
- assert.deepEqual(tokens, [
283
- { type: "INTRODUCER", pos: 0, raw: "\\x1b)", code: "\x9b" },
284
- { type: "FINAL", pos: 5, raw: "B" },
285
- ]);
286
- });
287
-
288
- test("Select UTF-8 character set", () => {
289
- const input = String.raw`\x1b%G`;
290
- const tokens: TOKEN[] = [...tokenizer(input)];
291
- assert.deepEqual(tokens, [
292
- { type: "INTRODUCER", pos: 0, raw: "\\x1b%", code: "\x9b" },
293
- { type: "FINAL", pos: 5, raw: "G" },
294
- ]);
295
- });
296
-
297
- test("DEC Private Mode - Hide Cursor", () => {
298
- const input = String.raw`\x1b[?25l`;
299
- const tokens: TOKEN[] = [...tokenizer(input)];
300
- assert.deepEqual(tokens, [
301
- { type: "INTRODUCER", pos: 0, raw: "\\x1b[", code: "\x9b" },
302
- { type: "DATA", pos: 5, raw: "?25" },
303
- { type: "FINAL", pos: 8, raw: "l" },
304
- ]);
305
- });
306
-
307
- test("Simple ESC", () => {
308
- const input = String.raw`\x1bc`;
309
- const tokens: TOKEN[] = [...tokenizer(input)];
310
- assert.deepEqual(tokens, [
311
- { type: "INTRODUCER", pos: 0, raw: "\\x1b", code: "\x1b" },
312
- { type: "FINAL", pos: 4, raw: "c" },
313
- ]);
314
- });
315
-
316
- test("iTerm2 SetUserVar", () => {
317
- const input = String.raw`\x1b]1337;SetUserVar=foo=YmFy\x07`;
318
- const tokens: TOKEN[] = [...tokenizer(input)];
319
- assert.deepEqual(tokens, [
320
- { type: "INTRODUCER", pos: 0, raw: "\\x1b]", code: "\x9d" },
321
- { type: "DATA", pos: 5, raw: "1337;SetUserVar=foo=YmFy" },
322
- { type: "FINAL", pos: 29, raw: "\\x07" },
323
- ]);
324
- });
325
-
326
- test("DCS with \\e\\\\ terminator", () => {
327
- const input = String.raw`\x1bP0;1|name\e\\`;
328
- const tokens: TOKEN[] = [...tokenizer(input)];
329
- assert.deepEqual(tokens, [
330
- { type: "INTRODUCER", pos: 0, raw: "\\x1bP", code: "P" },
331
- { type: "DATA", pos: 5, raw: "0;1|name" },
332
- { type: "FINAL", pos: 13, raw: "\\e\\\\" },
333
- ]);
334
- });
335
-
336
- test("APC with \\e\\\\ terminator", () => {
337
- const input = String.raw`\x1b_some payload\e\\`;
338
- const tokens: TOKEN[] = [...tokenizer(input)];
339
- assert.deepEqual(tokens, [
340
- { type: "INTRODUCER", pos: 0, raw: "\\x1b_", code: "_" },
341
- { type: "DATA", pos: 5, raw: "some payload" },
342
- { type: "FINAL", pos: 17, raw: "\\e\\\\" },
343
- ]);
344
- });
345
-
346
- test("PM with \\e\\\\ terminator", () => {
347
- const input = String.raw`\x1b^privacy data\e\\`;
348
- const tokens: TOKEN[] = [...tokenizer(input)];
349
- assert.deepEqual(tokens, [
350
- { type: "INTRODUCER", pos: 0, raw: "\\x1b^", code: "^" },
351
- { type: "DATA", pos: 5, raw: "privacy data" },
352
- { type: "FINAL", pos: 17, raw: "\\e\\\\" },
353
- ]);
354
- });
355
-
356
- test("SOS with \\e\\\\ terminator", () => {
357
- const input = String.raw`\x1bXstring data\e\\`;
358
- const tokens: TOKEN[] = [...tokenizer(input)];
359
- assert.deepEqual(tokens, [
360
- { type: "INTRODUCER", pos: 0, raw: "\\x1bX", code: "X" },
361
- { type: "DATA", pos: 5, raw: "string data" },
362
- { type: "FINAL", pos: 16, raw: "\\e\\\\" },
363
- ]);
364
- });
365
-
366
- test("DCS with \\x1b\\\\ terminator", () => {
367
- const input = String.raw`\x1bP0;1|name\x1b\\`;
368
- const tokens: TOKEN[] = [...tokenizer(input)];
369
- assert.deepEqual(tokens, [
370
- { type: "INTRODUCER", pos: 0, raw: "\\x1bP", code: "P" },
371
- { type: "DATA", pos: 5, raw: "0;1|name" },
372
- { type: "FINAL", pos: 13, raw: "\\x1b\\\\" },
373
- ]);
374
- });
375
-
376
- test("APC with \\x1b\\\\ terminator", () => {
377
- const input = String.raw`\x1b_app data\x1b\\`;
378
- const tokens: TOKEN[] = [...tokenizer(input)];
379
- assert.deepEqual(tokens, [
380
- { type: "INTRODUCER", pos: 0, raw: "\\x1b_", code: "_" },
381
- { type: "DATA", pos: 5, raw: "app data" },
382
- { type: "FINAL", pos: 13, raw: "\\x1b\\\\" },
383
- ]);
384
- });
385
-
386
- test("OSC with \\e\\\\ terminator", () => {
387
- const input = String.raw`\x1b]0;window title\e\\`;
388
- const tokens: TOKEN[] = [...tokenizer(input)];
389
- assert.deepEqual(tokens, [
390
- { type: "INTRODUCER", pos: 0, raw: "\\x1b]", code: "\x9d" },
391
- { type: "DATA", pos: 5, raw: "0;window title" },
392
- { type: "FINAL", pos: 19, raw: "\\e\\\\" },
393
- ]);
394
- });
395
-
396
- test("Mixed string sequences with different terminators", () => {
397
- const input = String.raw`\x1b_app\e\\\x1bP0|data\x1b\\\x1b]0;title\x07`;
398
- const tokens: TOKEN[] = [...tokenizer(input)];
399
- assert.deepEqual(tokens, [
400
- { type: "INTRODUCER", pos: 0, raw: "\\x1b_", code: "_" },
401
- { type: "DATA", pos: 5, raw: "app" },
402
- { type: "FINAL", pos: 8, raw: "\\e\\\\" },
403
- { type: "INTRODUCER", pos: 12, raw: "\\x1bP", code: "P" },
404
- { type: "DATA", pos: 17, raw: "0|data" },
405
- { type: "FINAL", pos: 23, raw: "\\x1b\\\\" },
406
- { type: "INTRODUCER", pos: 29, raw: "\\x1b]", code: "\x9d" },
407
- { type: "DATA", pos: 34, raw: "0;title" },
408
- { type: "FINAL", pos: 41, raw: "\\x07" },
409
- ]);
410
- });