terminal-pilot 0.0.5 → 0.0.7

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.
Files changed (86) hide show
  1. package/README.md +40 -0
  2. package/dist/ansi.js +68 -63
  3. package/dist/ansi.js.map +7 -0
  4. package/dist/cli.d.ts +2 -0
  5. package/dist/cli.js +6254 -0
  6. package/dist/cli.js.map +7 -0
  7. package/dist/commands/close-session.d.ts +12 -0
  8. package/dist/commands/close-session.js +1509 -0
  9. package/dist/commands/close-session.js.map +7 -0
  10. package/dist/commands/create-session.d.ts +26 -0
  11. package/dist/commands/create-session.js +1516 -0
  12. package/dist/commands/create-session.js.map +7 -0
  13. package/dist/commands/fill.d.ts +10 -0
  14. package/dist/commands/fill.js +1512 -0
  15. package/dist/commands/fill.js.map +7 -0
  16. package/dist/commands/get-session.d.ts +18 -0
  17. package/dist/commands/get-session.js +1514 -0
  18. package/dist/commands/get-session.js.map +7 -0
  19. package/dist/commands/index.d.ts +242 -0
  20. package/dist/commands/index.js +3973 -0
  21. package/dist/commands/index.js.map +7 -0
  22. package/dist/commands/install.d.ts +20 -0
  23. package/dist/commands/install.js +1480 -0
  24. package/dist/commands/install.js.map +7 -0
  25. package/dist/commands/installer.d.ts +43 -0
  26. package/dist/commands/installer.js +289 -0
  27. package/dist/commands/installer.js.map +7 -0
  28. package/dist/commands/list-sessions.d.ts +16 -0
  29. package/dist/commands/list-sessions.js +1513 -0
  30. package/dist/commands/list-sessions.js.map +7 -0
  31. package/dist/commands/press-key.d.ts +10 -0
  32. package/dist/commands/press-key.js +1512 -0
  33. package/dist/commands/press-key.js.map +7 -0
  34. package/dist/commands/read-history.d.ts +16 -0
  35. package/dist/commands/read-history.js +1511 -0
  36. package/dist/commands/read-history.js.map +7 -0
  37. package/dist/commands/read-screen.d.ts +21 -0
  38. package/dist/commands/read-screen.js +1515 -0
  39. package/dist/commands/read-screen.js.map +7 -0
  40. package/dist/commands/resize.d.ts +12 -0
  41. package/dist/commands/resize.js +1512 -0
  42. package/dist/commands/resize.js.map +7 -0
  43. package/dist/commands/runtime.d.ts +36 -0
  44. package/dist/commands/runtime.js +1262 -0
  45. package/dist/commands/runtime.js.map +7 -0
  46. package/dist/commands/screenshot.d.ts +14 -0
  47. package/dist/commands/screenshot.js +2280 -0
  48. package/dist/commands/screenshot.js.map +7 -0
  49. package/dist/commands/send-signal.d.ts +10 -0
  50. package/dist/commands/send-signal.js +1512 -0
  51. package/dist/commands/send-signal.js.map +7 -0
  52. package/dist/commands/type.d.ts +10 -0
  53. package/dist/commands/type.js +1512 -0
  54. package/dist/commands/type.js.map +7 -0
  55. package/dist/commands/uninstall.d.ts +14 -0
  56. package/dist/commands/uninstall.js +529 -0
  57. package/dist/commands/uninstall.js.map +7 -0
  58. package/dist/commands/wait-for-exit.d.ts +14 -0
  59. package/dist/commands/wait-for-exit.js +1513 -0
  60. package/dist/commands/wait-for-exit.js.map +7 -0
  61. package/dist/commands/wait-for.d.ts +20 -0
  62. package/dist/commands/wait-for.js +1520 -0
  63. package/dist/commands/wait-for.js.map +7 -0
  64. package/dist/exports.compile-check.js +1 -1
  65. package/dist/exports.compile-check.js.map +7 -0
  66. package/dist/index.js +1118 -5
  67. package/dist/index.js.map +7 -0
  68. package/dist/keys.js +58 -49
  69. package/dist/keys.js.map +7 -0
  70. package/dist/templates/terminal-pilot.md +45 -0
  71. package/dist/terminal-buffer.d.ts +9 -1
  72. package/dist/terminal-buffer.js +525 -425
  73. package/dist/terminal-buffer.js.map +7 -0
  74. package/dist/terminal-pilot.js +1105 -35
  75. package/dist/terminal-pilot.js.map +7 -0
  76. package/dist/terminal-screen.js +108 -26
  77. package/dist/terminal-screen.js.map +7 -0
  78. package/dist/terminal-session.js +1020 -292
  79. package/dist/terminal-session.js.map +7 -0
  80. package/dist/testing/cli-repl.d.ts +15 -0
  81. package/dist/testing/cli-repl.js +6359 -0
  82. package/dist/testing/cli-repl.js.map +7 -0
  83. package/dist/testing/qa-cli.d.ts +1 -0
  84. package/dist/testing/qa-cli.js +7276 -0
  85. package/dist/testing/qa-cli.js.map +7 -0
  86. package/package.json +37 -7
@@ -1,445 +1,545 @@
1
- export class TerminalBuffer {
2
- _cols;
3
- _rows;
4
- _screen;
5
- _cursorX = 0;
6
- _cursorY = 0;
7
- _savedCursor = { x: 0, y: 0 };
8
- _scrollTop = 0;
9
- _scrollBottom;
10
- _state = 0 /* State.Normal */;
11
- _csiParams = "";
12
- _csiPrivate = "";
13
- displayBuffer;
14
- constructor(cols, rows) {
15
- this._cols = cols;
16
- this._rows = rows;
17
- this._scrollBottom = rows - 1;
18
- this._screen = this._makeScreen(cols, rows);
19
- this.displayBuffer = Object.defineProperties({}, {
20
- cursorX: { get: () => this._cursorX, enumerable: true },
21
- cursorY: { get: () => this._cursorY, enumerable: true },
22
- data: { get: () => this._screen, enumerable: true },
23
- });
1
+ // src/terminal-buffer.ts
2
+ var RESET_SGR = "\x1B[0m";
3
+ var TerminalBuffer = class {
4
+ _cols;
5
+ _rows;
6
+ _screen;
7
+ _cursorX = 0;
8
+ _cursorY = 0;
9
+ _savedCursor = { x: 0, y: 0 };
10
+ _scrollTop = 0;
11
+ _scrollBottom;
12
+ _state = 0 /* Normal */;
13
+ _csiParams = "";
14
+ _csiPrivate = "";
15
+ _style = createDefaultStyleState();
16
+ _styleSequence = "";
17
+ displayBuffer;
18
+ constructor(cols, rows) {
19
+ this._cols = cols;
20
+ this._rows = rows;
21
+ this._scrollBottom = rows - 1;
22
+ this._screen = this._makeScreen(cols, rows);
23
+ this.displayBuffer = Object.defineProperties(
24
+ {},
25
+ {
26
+ cursorX: { get: () => this._cursorX, enumerable: true },
27
+ cursorY: { get: () => this._cursorY, enumerable: true },
28
+ data: { get: () => this._screen, enumerable: true }
29
+ }
30
+ );
31
+ }
32
+ write(data) {
33
+ for (const ch of data) {
34
+ this._feed(ch);
24
35
  }
25
- write(data) {
26
- for (const ch of data) {
27
- this._feed(ch);
28
- }
36
+ }
37
+ renderLine(row) {
38
+ const cells = this._screen[row] ?? [];
39
+ let lastVisibleCell = -1;
40
+ for (let index = cells.length - 1; index >= 0; index -= 1) {
41
+ if (cells[index] !== null) {
42
+ lastVisibleCell = index;
43
+ break;
44
+ }
29
45
  }
30
- resize(cols, rows) {
31
- // Adjust row count
32
- while (this._screen.length < rows) {
33
- this._screen.push(this._makeRow(cols));
34
- }
35
- this._screen.length = rows;
36
- // Adjust col count for each row
37
- for (let y = 0; y < rows; y++) {
38
- const row = this._screen[y] ?? this._makeRow(cols);
39
- while (row.length < cols)
40
- row.push(null);
41
- row.length = cols;
42
- this._screen[y] = row;
43
- }
44
- this._cols = cols;
45
- this._rows = rows;
46
- this._scrollTop = 0;
47
- this._scrollBottom = rows - 1;
48
- this._cursorX = this._clamp(this._cursorX, 0, cols - 1);
49
- this._cursorY = this._clamp(this._cursorY, 0, rows - 1);
46
+ if (lastVisibleCell === -1) {
47
+ return "";
50
48
  }
51
- _makeScreen(cols, rows) {
52
- return Array.from({ length: rows }, () => this._makeRow(cols));
49
+ let line = "";
50
+ let activeStyle = "";
51
+ for (let index = 0; index <= lastVisibleCell; index += 1) {
52
+ const cell = cells[index];
53
+ const cellStyle = cell?.style ?? "";
54
+ if (cellStyle !== activeStyle) {
55
+ line += cellStyle.length > 0 ? cellStyle : RESET_SGR;
56
+ activeStyle = cellStyle;
57
+ }
58
+ line += cell?.[1] ?? " ";
53
59
  }
54
- _makeRow(cols) {
55
- return Array(cols).fill(null);
60
+ if (activeStyle.length > 0) {
61
+ line += RESET_SGR;
56
62
  }
57
- _clamp(value, min, max) {
58
- return Math.max(min, Math.min(max, value));
63
+ return line;
64
+ }
65
+ resize(cols, rows) {
66
+ while (this._screen.length < rows) {
67
+ this._screen.push(this._makeRow(cols));
59
68
  }
60
- _setChar(y, x, ch) {
61
- const row = this._screen[y];
62
- if (row && x >= 0 && x < this._cols) {
63
- row[x] = [ch.charCodeAt(0), ch];
64
- }
65
- }
66
- _eraseLine(y, fromX, toX) {
67
- const row = this._screen[y];
68
- if (!row)
69
- return;
70
- for (let x = fromX; x <= toX && x < this._cols; x++) {
71
- row[x] = null;
72
- }
69
+ this._screen.length = rows;
70
+ for (let y = 0; y < rows; y++) {
71
+ const row = this._screen[y] ?? this._makeRow(cols);
72
+ while (row.length < cols) row.push(null);
73
+ row.length = cols;
74
+ this._screen[y] = row;
73
75
  }
74
- _scrollUp(count) {
75
- for (let i = 0; i < count; i++) {
76
- this._screen.splice(this._scrollTop, 1);
77
- this._screen.splice(this._scrollBottom, 0, this._makeRow(this._cols));
78
- }
76
+ this._cols = cols;
77
+ this._rows = rows;
78
+ this._scrollTop = 0;
79
+ this._scrollBottom = rows - 1;
80
+ this._cursorX = this._clamp(this._cursorX, 0, cols - 1);
81
+ this._cursorY = this._clamp(this._cursorY, 0, rows - 1);
82
+ }
83
+ _makeScreen(cols, rows) {
84
+ return Array.from({ length: rows }, () => this._makeRow(cols));
85
+ }
86
+ _makeRow(cols) {
87
+ return Array(cols).fill(null);
88
+ }
89
+ _clamp(value, min, max) {
90
+ return Math.max(min, Math.min(max, value));
91
+ }
92
+ _setChar(y, x, ch) {
93
+ const row = this._screen[y];
94
+ if (row && x >= 0 && x < this._cols) {
95
+ const cell = [ch.charCodeAt(0), ch];
96
+ if (this._styleSequence.length > 0) {
97
+ Object.defineProperty(cell, "style", {
98
+ value: this._styleSequence,
99
+ writable: true,
100
+ configurable: true
101
+ });
102
+ }
103
+ row[x] = cell;
79
104
  }
80
- _scrollDown(count) {
81
- for (let i = 0; i < count; i++) {
82
- this._screen.splice(this._scrollBottom, 1);
83
- this._screen.splice(this._scrollTop, 0, this._makeRow(this._cols));
84
- }
105
+ }
106
+ _eraseLine(y, fromX, toX) {
107
+ const row = this._screen[y];
108
+ if (!row) return;
109
+ for (let x = fromX; x <= toX && x < this._cols; x++) {
110
+ row[x] = null;
85
111
  }
86
- _newline() {
87
- if (this._cursorY === this._scrollBottom) {
88
- this._scrollUp(1);
89
- }
90
- else {
91
- this._cursorY = Math.min(this._cursorY + 1, this._rows - 1);
92
- }
112
+ }
113
+ _scrollUp(count) {
114
+ for (let i = 0; i < count; i++) {
115
+ this._screen.splice(this._scrollTop, 1);
116
+ this._screen.splice(this._scrollBottom, 0, this._makeRow(this._cols));
93
117
  }
94
- _parseCsiParams() {
95
- if (!this._csiParams)
96
- return [];
97
- return this._csiParams.split(";").map((s) => (s === "" ? 0 : parseInt(s, 10)));
118
+ }
119
+ _scrollDown(count) {
120
+ for (let i = 0; i < count; i++) {
121
+ this._screen.splice(this._scrollBottom, 1);
122
+ this._screen.splice(this._scrollTop, 0, this._makeRow(this._cols));
98
123
  }
99
- _execCsi(final) {
100
- const params = this._parseCsiParams();
101
- const p0 = params[0] ?? 0;
102
- const p1 = params[1] ?? 0;
103
- if (this._csiPrivate === "?") {
104
- if (final === "h" || final === "l") {
105
- // Only handle alt screen (1049) — ignore everything else
106
- if (params.includes(1049)) {
107
- if (final === "h") {
108
- this._screen = this._makeScreen(this._cols, this._rows);
109
- this._cursorX = 0;
110
- this._cursorY = 0;
111
- }
112
- else {
113
- this._screen = this._makeScreen(this._cols, this._rows);
114
- this._cursorX = 0;
115
- this._cursorY = 0;
116
- }
117
- }
118
- }
119
- return;
120
- }
121
- switch (final) {
122
- case "A": // cursor up
123
- this._cursorY = this._clamp(this._cursorY - Math.max(1, p0), 0, this._rows - 1);
124
- break;
125
- case "B": // cursor down
126
- this._cursorY = this._clamp(this._cursorY + Math.max(1, p0), 0, this._rows - 1);
127
- break;
128
- case "C": // cursor forward
129
- case "a":
130
- this._cursorX = this._clamp(this._cursorX + Math.max(1, p0), 0, this._cols - 1);
131
- break;
132
- case "D": // cursor backward
133
- this._cursorX = this._clamp(this._cursorX - Math.max(1, p0), 0, this._cols - 1);
134
- break;
135
- case "E": // cursor next line
136
- this._cursorY = this._clamp(this._cursorY + Math.max(1, p0), 0, this._rows - 1);
137
- this._cursorX = 0;
138
- break;
139
- case "F": // cursor preceding line
140
- this._cursorY = this._clamp(this._cursorY - Math.max(1, p0), 0, this._rows - 1);
141
- this._cursorX = 0;
142
- break;
143
- case "G": // cursor horizontal absolute
144
- case "`":
145
- this._cursorX = this._clamp(Math.max(1, p0) - 1, 0, this._cols - 1);
146
- break;
147
- case "H": // cursor position
148
- case "f":
149
- this._cursorY = this._clamp(Math.max(1, p0) - 1, 0, this._rows - 1);
150
- this._cursorX = this._clamp(Math.max(1, p1) - 1, 0, this._cols - 1);
151
- break;
152
- case "I": // cursor forward tabulation
153
- for (let i = 0; i < Math.max(1, p0); i++) {
154
- this._cursorX = Math.min(this._cols - 1, (Math.floor(this._cursorX / 8) + 1) * 8);
155
- }
156
- break;
157
- case "J": // erase in display
158
- if (p0 === 0) {
159
- this._eraseLine(this._cursorY, this._cursorX, this._cols - 1);
160
- for (let y = this._cursorY + 1; y < this._rows; y++)
161
- this._eraseLine(y, 0, this._cols - 1);
162
- }
163
- else if (p0 === 1) {
164
- for (let y = 0; y < this._cursorY; y++)
165
- this._eraseLine(y, 0, this._cols - 1);
166
- this._eraseLine(this._cursorY, 0, this._cursorX);
167
- }
168
- else if (p0 === 2 || p0 === 3) {
169
- for (let y = 0; y < this._rows; y++)
170
- this._eraseLine(y, 0, this._cols - 1);
171
- }
172
- break;
173
- case "K": // erase in line
174
- if (p0 === 0)
175
- this._eraseLine(this._cursorY, this._cursorX, this._cols - 1);
176
- else if (p0 === 1)
177
- this._eraseLine(this._cursorY, 0, this._cursorX);
178
- else if (p0 === 2)
179
- this._eraseLine(this._cursorY, 0, this._cols - 1);
180
- break;
181
- case "X": // erase characters (ECH)
182
- this._eraseLine(this._cursorY, this._cursorX, this._cursorX + Math.max(1, p0) - 1);
183
- break;
184
- case "L": { // insert lines
185
- const n = Math.max(1, p0);
186
- for (let i = 0; i < n; i++) {
187
- this._screen.splice(this._scrollBottom, 1);
188
- this._screen.splice(this._cursorY, 0, this._makeRow(this._cols));
189
- }
190
- break;
191
- }
192
- case "M": { // delete lines
193
- const n = Math.max(1, p0);
194
- for (let i = 0; i < n; i++) {
195
- this._screen.splice(this._cursorY, 1);
196
- this._screen.splice(this._scrollBottom, 0, this._makeRow(this._cols));
197
- }
198
- break;
199
- }
200
- case "P": { // delete characters
201
- const row = this._screen[this._cursorY];
202
- if (row) {
203
- const n = Math.max(1, p0);
204
- row.splice(this._cursorX, n);
205
- while (row.length < this._cols)
206
- row.push(null);
207
- }
208
- break;
209
- }
210
- case "@": { // insert blank characters
211
- const row = this._screen[this._cursorY];
212
- if (row) {
213
- const n = Math.max(1, p0);
214
- for (let i = 0; i < n; i++)
215
- row.splice(this._cursorX, 0, null);
216
- row.splice(this._cols);
217
- }
218
- break;
219
- }
220
- case "S": // scroll up
221
- this._scrollUp(Math.max(1, p0));
222
- break;
223
- case "T": // scroll down
224
- if (params.length <= 1)
225
- this._scrollDown(Math.max(1, p0));
226
- break;
227
- case "Z": { // cursor backward tabulation
228
- const n = Math.max(1, p0);
229
- for (let i = 0; i < n; i++) {
230
- this._cursorX = Math.max(0, (Math.ceil(this._cursorX / 8) - 1) * 8);
231
- }
232
- break;
233
- }
234
- case "d": // line position absolute
235
- this._cursorY = this._clamp(Math.max(1, p0) - 1, 0, this._rows - 1);
236
- break;
237
- case "e": // vertical position relative
238
- this._cursorY = this._clamp(this._cursorY + Math.max(1, p0), 0, this._rows - 1);
239
- break;
240
- case "r": { // set scrolling region
241
- const top = this._clamp(Math.max(1, p0) - 1, 0, this._rows - 1);
242
- const bottom = this._clamp((p1 === 0 ? this._rows : p1) - 1, 0, this._rows - 1);
243
- if (top < bottom) {
244
- this._scrollTop = top;
245
- this._scrollBottom = bottom;
246
- }
247
- this._cursorX = 0;
248
- this._cursorY = 0;
249
- break;
250
- }
251
- case "s": // save cursor
252
- this._savedCursor = { x: this._cursorX, y: this._cursorY };
253
- break;
254
- case "u": // restore cursor
255
- this._cursorX = this._clamp(this._savedCursor.x, 0, this._cols - 1);
256
- this._cursorY = this._clamp(this._savedCursor.y, 0, this._rows - 1);
257
- break;
258
- case "m": // SGR — ignore (we don't track attributes)
259
- break;
260
- default:
261
- break;
262
- }
263
- }
264
- _feed(ch) {
265
- const code = ch.charCodeAt(0);
266
- switch (this._state) {
267
- case 0 /* State.Normal */:
268
- this._feedNormal(ch, code);
269
- break;
270
- case 1 /* State.Escape */:
271
- this._feedEscape(ch, code);
272
- break;
273
- case 2 /* State.Csi */:
274
- this._feedCsi(ch, code);
275
- break;
276
- case 3 /* State.Osc */:
277
- // consume until BEL or ESC (ESC \ = ST)
278
- if (code === 0x07 || code === 0x9c) {
279
- this._state = 0 /* State.Normal */;
280
- }
281
- else if (code === 0x1b) {
282
- // next char should be `\` — just return to normal, it will be consumed
283
- this._state = 0 /* State.Normal */;
284
- }
285
- break;
286
- case 4 /* State.Str */:
287
- // consume until ST (0x9c) or BEL
288
- if (code === 0x9c || code === 0x07) {
289
- this._state = 0 /* State.Normal */;
290
- }
291
- else if (code === 0x1b) {
292
- this._state = 0 /* State.Normal */;
293
- }
294
- break;
295
- case 5 /* State.EscCharset */:
296
- // consume one character for charset designation
297
- this._state = 0 /* State.Normal */;
298
- break;
299
- case 6 /* State.EscHash */:
300
- // consume one character for line attributes
301
- this._state = 0 /* State.Normal */;
302
- break;
303
- }
304
- }
305
- _feedNormal(ch, code) {
306
- if (code === 0x1b) {
307
- this._state = 1 /* State.Escape */;
308
- }
309
- else if (code === 0x9b) {
310
- // C1 CSI
311
- this._csiParams = "";
312
- this._csiPrivate = "";
313
- this._state = 2 /* State.Csi */;
314
- }
315
- else if (code === 0x9d) {
316
- // C1 OSC
317
- this._state = 3 /* State.Osc */;
318
- }
319
- else if (code === 0x90 || code === 0x98 || code === 0x9e || code === 0x9f) {
320
- // DCS, SOS, PM, APC
321
- this._state = 4 /* State.Str */;
322
- }
323
- else if (code === 0x07 || code === 0x05 || code === 0x06) {
324
- // BEL, ENQ, ACK — ignore
325
- }
326
- else if (code === 0x08) {
327
- // BS
328
- if (this._cursorX > 0)
329
- this._cursorX--;
330
- }
331
- else if (code === 0x7f) {
332
- // DEL
333
- if (this._cursorX > 0) {
334
- this._cursorX--;
335
- this._setChar(this._cursorY, this._cursorX, " ");
336
- }
337
- }
338
- else if (code === 0x09) {
339
- // HT
340
- this._cursorX = Math.min(this._cols - 1, (Math.floor(this._cursorX / 8) + 1) * 8);
341
- }
342
- else if (code === 0x0a || code === 0x0b || code === 0x0c) {
343
- // LF, VT, FF
344
- this._newline();
345
- }
346
- else if (code === 0x0d) {
347
- // CR
348
- this._cursorX = 0;
349
- }
350
- else if (code === 0x0e || code === 0x0f) {
351
- // SO, SI — charset switch, ignore
352
- }
353
- else if (code >= 0x20 && code !== 0x7f) {
354
- // Printable character (including multi-byte Unicode via code points)
355
- this._setChar(this._cursorY, this._cursorX, ch);
356
- this._cursorX++;
357
- if (this._cursorX >= this._cols) {
358
- // Auto-wrap
359
- this._cursorX = 0;
360
- this._newline();
361
- }
362
- }
124
+ }
125
+ _newline() {
126
+ if (this._cursorY === this._scrollBottom) {
127
+ this._scrollUp(1);
128
+ } else {
129
+ this._cursorY = Math.min(this._cursorY + 1, this._rows - 1);
363
130
  }
364
- _feedEscape(ch, code) {
365
- this._state = 0 /* State.Normal */;
366
- if (code === 0x5b) {
367
- // ESC [ = CSI
368
- this._csiParams = "";
369
- this._csiPrivate = "";
370
- this._state = 2 /* State.Csi */;
371
- }
372
- else if (code === 0x5d) {
373
- // ESC ] = OSC
374
- this._state = 3 /* State.Osc */;
375
- }
376
- else if (code === 0x50 || code === 0x58 || code === 0x5e || code === 0x5f) {
377
- // DCS, SOS, PM, APC
378
- this._state = 4 /* State.Str */;
379
- }
380
- else if (code === 0x28 || code === 0x29 || code === 0x2a || code === 0x2b || code === 0x2d || code === 0x2e) {
381
- // ESC ( ) * + - . = charset designation (consume next char)
382
- this._state = 5 /* State.EscCharset */;
383
- }
384
- else if (code === 0x23) {
385
- // ESC # = line attributes (consume next char)
386
- this._state = 6 /* State.EscHash */;
387
- }
388
- else if (code === 0x37) {
389
- // ESC 7 = save cursor
390
- this._savedCursor = { x: this._cursorX, y: this._cursorY };
391
- }
392
- else if (code === 0x38) {
393
- // ESC 8 = restore cursor
394
- this._cursorX = this._clamp(this._savedCursor.x, 0, this._cols - 1);
395
- this._cursorY = this._clamp(this._savedCursor.y, 0, this._rows - 1);
396
- }
397
- else if (code === 0x44) {
398
- // ESC D = index (LF)
399
- this._newline();
400
- }
401
- else if (code === 0x45) {
402
- // ESC E = next line
131
+ }
132
+ _parseCsiParams() {
133
+ if (!this._csiParams) return [];
134
+ return this._csiParams.split(";").map((s) => s === "" ? 0 : parseInt(s, 10));
135
+ }
136
+ _execCsi(final) {
137
+ const params = this._parseCsiParams();
138
+ const p0 = params[0] ?? 0;
139
+ const p1 = params[1] ?? 0;
140
+ if (this._csiPrivate === "?") {
141
+ if (final === "h" || final === "l") {
142
+ if (params.includes(1049)) {
143
+ if (final === "h") {
144
+ this._screen = this._makeScreen(this._cols, this._rows);
403
145
  this._cursorX = 0;
404
- this._newline();
405
- }
406
- else if (code === 0x4d) {
407
- // ESC M = reverse index
408
- if (this._cursorY === this._scrollTop) {
409
- this._scrollDown(1);
410
- }
411
- else {
412
- this._cursorY = Math.max(0, this._cursorY - 1);
413
- }
414
- }
415
- else if (code === 0x48) {
416
- // ESC H = tab set (ignore)
417
- }
418
- else if (code === 0x63) {
419
- // ESC c = full reset
146
+ this._cursorY = 0;
147
+ } else {
420
148
  this._screen = this._makeScreen(this._cols, this._rows);
421
149
  this._cursorX = 0;
422
150
  this._cursorY = 0;
423
- this._savedCursor = { x: 0, y: 0 };
424
- this._scrollTop = 0;
425
- this._scrollBottom = this._rows - 1;
151
+ }
152
+ this._resetStyle();
426
153
  }
427
- // All other ESC sequences: two-char, already consumed — ignore
154
+ }
155
+ return;
428
156
  }
429
- _feedCsi(ch, code) {
430
- if (code >= 0x40 && code <= 0x7e) {
431
- // Final byte
432
- this._execCsi(ch);
433
- this._state = 0 /* State.Normal */;
434
- }
435
- else if (code === 0x3f || code === 0x21 || code === 0x3e || code === 0x20) {
436
- // Private/intermediate marker (?, !, >, space)
437
- this._csiPrivate = ch;
438
- }
439
- else if ((code >= 0x30 && code <= 0x39) || code === 0x3b) {
440
- // Digit or semicolon — parameter byte
441
- this._csiParams += ch;
442
- }
443
- // Other bytes ignored
157
+ switch (final) {
158
+ case "A":
159
+ this._cursorY = this._clamp(this._cursorY - Math.max(1, p0), 0, this._rows - 1);
160
+ break;
161
+ case "B":
162
+ this._cursorY = this._clamp(this._cursorY + Math.max(1, p0), 0, this._rows - 1);
163
+ break;
164
+ case "C":
165
+ // cursor forward
166
+ case "a":
167
+ this._cursorX = this._clamp(this._cursorX + Math.max(1, p0), 0, this._cols - 1);
168
+ break;
169
+ case "D":
170
+ this._cursorX = this._clamp(this._cursorX - Math.max(1, p0), 0, this._cols - 1);
171
+ break;
172
+ case "E":
173
+ this._cursorY = this._clamp(this._cursorY + Math.max(1, p0), 0, this._rows - 1);
174
+ this._cursorX = 0;
175
+ break;
176
+ case "F":
177
+ this._cursorY = this._clamp(this._cursorY - Math.max(1, p0), 0, this._rows - 1);
178
+ this._cursorX = 0;
179
+ break;
180
+ case "G":
181
+ // cursor horizontal absolute
182
+ case "`":
183
+ this._cursorX = this._clamp(Math.max(1, p0) - 1, 0, this._cols - 1);
184
+ break;
185
+ case "H":
186
+ // cursor position
187
+ case "f":
188
+ this._cursorY = this._clamp(Math.max(1, p0) - 1, 0, this._rows - 1);
189
+ this._cursorX = this._clamp(Math.max(1, p1) - 1, 0, this._cols - 1);
190
+ break;
191
+ case "I":
192
+ for (let i = 0; i < Math.max(1, p0); i++) {
193
+ this._cursorX = Math.min(this._cols - 1, (Math.floor(this._cursorX / 8) + 1) * 8);
194
+ }
195
+ break;
196
+ case "J":
197
+ if (p0 === 0) {
198
+ this._eraseLine(this._cursorY, this._cursorX, this._cols - 1);
199
+ for (let y = this._cursorY + 1; y < this._rows; y++) this._eraseLine(y, 0, this._cols - 1);
200
+ } else if (p0 === 1) {
201
+ for (let y = 0; y < this._cursorY; y++) this._eraseLine(y, 0, this._cols - 1);
202
+ this._eraseLine(this._cursorY, 0, this._cursorX);
203
+ } else if (p0 === 2 || p0 === 3) {
204
+ for (let y = 0; y < this._rows; y++) this._eraseLine(y, 0, this._cols - 1);
205
+ }
206
+ break;
207
+ case "K":
208
+ if (p0 === 0) this._eraseLine(this._cursorY, this._cursorX, this._cols - 1);
209
+ else if (p0 === 1) this._eraseLine(this._cursorY, 0, this._cursorX);
210
+ else if (p0 === 2) this._eraseLine(this._cursorY, 0, this._cols - 1);
211
+ break;
212
+ case "X":
213
+ this._eraseLine(this._cursorY, this._cursorX, this._cursorX + Math.max(1, p0) - 1);
214
+ break;
215
+ case "L": {
216
+ const n = Math.max(1, p0);
217
+ for (let i = 0; i < n; i++) {
218
+ this._screen.splice(this._scrollBottom, 1);
219
+ this._screen.splice(this._cursorY, 0, this._makeRow(this._cols));
220
+ }
221
+ break;
222
+ }
223
+ case "M": {
224
+ const n = Math.max(1, p0);
225
+ for (let i = 0; i < n; i++) {
226
+ this._screen.splice(this._cursorY, 1);
227
+ this._screen.splice(this._scrollBottom, 0, this._makeRow(this._cols));
228
+ }
229
+ break;
230
+ }
231
+ case "P": {
232
+ const row = this._screen[this._cursorY];
233
+ if (row) {
234
+ const n = Math.max(1, p0);
235
+ row.splice(this._cursorX, n);
236
+ while (row.length < this._cols) row.push(null);
237
+ }
238
+ break;
239
+ }
240
+ case "@": {
241
+ const row = this._screen[this._cursorY];
242
+ if (row) {
243
+ const n = Math.max(1, p0);
244
+ for (let i = 0; i < n; i++) row.splice(this._cursorX, 0, null);
245
+ row.splice(this._cols);
246
+ }
247
+ break;
248
+ }
249
+ case "S":
250
+ this._scrollUp(Math.max(1, p0));
251
+ break;
252
+ case "T":
253
+ if (params.length <= 1) this._scrollDown(Math.max(1, p0));
254
+ break;
255
+ case "Z": {
256
+ const n = Math.max(1, p0);
257
+ for (let i = 0; i < n; i++) {
258
+ this._cursorX = Math.max(0, (Math.ceil(this._cursorX / 8) - 1) * 8);
259
+ }
260
+ break;
261
+ }
262
+ case "d":
263
+ this._cursorY = this._clamp(Math.max(1, p0) - 1, 0, this._rows - 1);
264
+ break;
265
+ case "e":
266
+ this._cursorY = this._clamp(this._cursorY + Math.max(1, p0), 0, this._rows - 1);
267
+ break;
268
+ case "r": {
269
+ const top = this._clamp(Math.max(1, p0) - 1, 0, this._rows - 1);
270
+ const bottom = this._clamp((p1 === 0 ? this._rows : p1) - 1, 0, this._rows - 1);
271
+ if (top < bottom) {
272
+ this._scrollTop = top;
273
+ this._scrollBottom = bottom;
274
+ }
275
+ this._cursorX = 0;
276
+ this._cursorY = 0;
277
+ break;
278
+ }
279
+ case "s":
280
+ this._savedCursor = { x: this._cursorX, y: this._cursorY };
281
+ break;
282
+ case "u":
283
+ this._cursorX = this._clamp(this._savedCursor.x, 0, this._cols - 1);
284
+ this._cursorY = this._clamp(this._savedCursor.y, 0, this._rows - 1);
285
+ break;
286
+ case "m":
287
+ this._applySgr(params);
288
+ break;
289
+ default:
290
+ break;
291
+ }
292
+ }
293
+ _feed(ch) {
294
+ const code = ch.charCodeAt(0);
295
+ switch (this._state) {
296
+ case 0 /* Normal */:
297
+ this._feedNormal(ch, code);
298
+ break;
299
+ case 1 /* Escape */:
300
+ this._feedEscape(ch, code);
301
+ break;
302
+ case 2 /* Csi */:
303
+ this._feedCsi(ch, code);
304
+ break;
305
+ case 3 /* Osc */:
306
+ if (code === 7 || code === 156) {
307
+ this._state = 0 /* Normal */;
308
+ } else if (code === 27) {
309
+ this._state = 0 /* Normal */;
310
+ }
311
+ break;
312
+ case 4 /* Str */:
313
+ if (code === 156 || code === 7) {
314
+ this._state = 0 /* Normal */;
315
+ } else if (code === 27) {
316
+ this._state = 0 /* Normal */;
317
+ }
318
+ break;
319
+ case 5 /* EscCharset */:
320
+ this._state = 0 /* Normal */;
321
+ break;
322
+ case 6 /* EscHash */:
323
+ this._state = 0 /* Normal */;
324
+ break;
325
+ }
326
+ }
327
+ _feedNormal(ch, code) {
328
+ if (code === 27) {
329
+ this._state = 1 /* Escape */;
330
+ } else if (code === 155) {
331
+ this._csiParams = "";
332
+ this._csiPrivate = "";
333
+ this._state = 2 /* Csi */;
334
+ } else if (code === 157) {
335
+ this._state = 3 /* Osc */;
336
+ } else if (code === 144 || code === 152 || code === 158 || code === 159) {
337
+ this._state = 4 /* Str */;
338
+ } else if (code === 7 || code === 5 || code === 6) {
339
+ } else if (code === 8) {
340
+ if (this._cursorX > 0) this._cursorX--;
341
+ } else if (code === 127) {
342
+ if (this._cursorX > 0) {
343
+ this._cursorX--;
344
+ this._setChar(this._cursorY, this._cursorX, " ");
345
+ }
346
+ } else if (code === 9) {
347
+ this._cursorX = Math.min(this._cols - 1, (Math.floor(this._cursorX / 8) + 1) * 8);
348
+ } else if (code === 10 || code === 11 || code === 12) {
349
+ this._newline();
350
+ } else if (code === 13) {
351
+ this._cursorX = 0;
352
+ } else if (code === 14 || code === 15) {
353
+ } else if (code >= 32 && code !== 127) {
354
+ this._setChar(this._cursorY, this._cursorX, ch);
355
+ this._cursorX++;
356
+ if (this._cursorX >= this._cols) {
357
+ this._cursorX = 0;
358
+ this._newline();
359
+ }
444
360
  }
361
+ }
362
+ _feedEscape(ch, code) {
363
+ this._state = 0 /* Normal */;
364
+ if (code === 91) {
365
+ this._csiParams = "";
366
+ this._csiPrivate = "";
367
+ this._state = 2 /* Csi */;
368
+ } else if (code === 93) {
369
+ this._state = 3 /* Osc */;
370
+ } else if (code === 80 || code === 88 || code === 94 || code === 95) {
371
+ this._state = 4 /* Str */;
372
+ } else if (code === 40 || code === 41 || code === 42 || code === 43 || code === 45 || code === 46) {
373
+ this._state = 5 /* EscCharset */;
374
+ } else if (code === 35) {
375
+ this._state = 6 /* EscHash */;
376
+ } else if (code === 55) {
377
+ this._savedCursor = { x: this._cursorX, y: this._cursorY };
378
+ } else if (code === 56) {
379
+ this._cursorX = this._clamp(this._savedCursor.x, 0, this._cols - 1);
380
+ this._cursorY = this._clamp(this._savedCursor.y, 0, this._rows - 1);
381
+ } else if (code === 68) {
382
+ this._newline();
383
+ } else if (code === 69) {
384
+ this._cursorX = 0;
385
+ this._newline();
386
+ } else if (code === 77) {
387
+ if (this._cursorY === this._scrollTop) {
388
+ this._scrollDown(1);
389
+ } else {
390
+ this._cursorY = Math.max(0, this._cursorY - 1);
391
+ }
392
+ } else if (code === 72) {
393
+ } else if (code === 99) {
394
+ this._screen = this._makeScreen(this._cols, this._rows);
395
+ this._cursorX = 0;
396
+ this._cursorY = 0;
397
+ this._savedCursor = { x: 0, y: 0 };
398
+ this._scrollTop = 0;
399
+ this._scrollBottom = this._rows - 1;
400
+ this._resetStyle();
401
+ }
402
+ }
403
+ _feedCsi(ch, code) {
404
+ if (code >= 64 && code <= 126) {
405
+ this._execCsi(ch);
406
+ this._state = 0 /* Normal */;
407
+ } else if (code === 63 || code === 33 || code === 62 || code === 32) {
408
+ this._csiPrivate = ch;
409
+ } else if (code >= 48 && code <= 57 || code === 59) {
410
+ this._csiParams += ch;
411
+ }
412
+ }
413
+ _resetStyle() {
414
+ this._style = createDefaultStyleState();
415
+ this._styleSequence = "";
416
+ }
417
+ _applySgr(params) {
418
+ const normalizedParams = params.length === 0 ? [0] : params;
419
+ for (let index = 0; index < normalizedParams.length; index += 1) {
420
+ const value = normalizedParams[index] ?? 0;
421
+ switch (value) {
422
+ case 0:
423
+ this._resetStyle();
424
+ break;
425
+ case 1:
426
+ this._style.bold = true;
427
+ break;
428
+ case 2:
429
+ this._style.dim = true;
430
+ break;
431
+ case 3:
432
+ this._style.italic = true;
433
+ break;
434
+ case 4:
435
+ this._style.underline = true;
436
+ break;
437
+ case 7:
438
+ this._style.inverse = true;
439
+ break;
440
+ case 9:
441
+ this._style.strikethrough = true;
442
+ break;
443
+ case 21:
444
+ case 22:
445
+ this._style.bold = false;
446
+ this._style.dim = false;
447
+ break;
448
+ case 23:
449
+ this._style.italic = false;
450
+ break;
451
+ case 24:
452
+ this._style.underline = false;
453
+ break;
454
+ case 27:
455
+ this._style.inverse = false;
456
+ break;
457
+ case 29:
458
+ this._style.strikethrough = false;
459
+ break;
460
+ case 39:
461
+ this._style.fg = void 0;
462
+ break;
463
+ case 49:
464
+ this._style.bg = void 0;
465
+ break;
466
+ case 38:
467
+ case 48:
468
+ index = this._applyExtendedColor(value, normalizedParams, index);
469
+ break;
470
+ default:
471
+ if (value >= 30 && value <= 37 || value >= 90 && value <= 97) {
472
+ this._style.fg = [value];
473
+ } else if (value >= 40 && value <= 47 || value >= 100 && value <= 107) {
474
+ this._style.bg = [value];
475
+ }
476
+ break;
477
+ }
478
+ }
479
+ this._styleSequence = serializeStyleState(this._style);
480
+ }
481
+ _applyExtendedColor(control, params, index) {
482
+ const mode = params[index + 1];
483
+ const target = control === 38 ? "fg" : "bg";
484
+ if (mode === 5) {
485
+ const paletteIndex = params[index + 2];
486
+ if (paletteIndex !== void 0) {
487
+ this._style[target] = [control, 5, paletteIndex];
488
+ return index + 2;
489
+ }
490
+ return index;
491
+ }
492
+ if (mode === 2) {
493
+ const red = params[index + 2];
494
+ const green = params[index + 3];
495
+ const blue = params[index + 4];
496
+ if (red !== void 0 && green !== void 0 && blue !== void 0) {
497
+ this._style[target] = [control, 2, red, green, blue];
498
+ return index + 4;
499
+ }
500
+ }
501
+ return index;
502
+ }
503
+ };
504
+ function createDefaultStyleState() {
505
+ return {
506
+ bold: false,
507
+ dim: false,
508
+ italic: false,
509
+ underline: false,
510
+ inverse: false,
511
+ strikethrough: false
512
+ };
513
+ }
514
+ function serializeStyleState(state) {
515
+ const codes = [];
516
+ if (state.bold) {
517
+ codes.push(1);
518
+ }
519
+ if (state.dim) {
520
+ codes.push(2);
521
+ }
522
+ if (state.italic) {
523
+ codes.push(3);
524
+ }
525
+ if (state.underline) {
526
+ codes.push(4);
527
+ }
528
+ if (state.inverse) {
529
+ codes.push(7);
530
+ }
531
+ if (state.strikethrough) {
532
+ codes.push(9);
533
+ }
534
+ if (state.fg !== void 0) {
535
+ codes.push(...state.fg);
536
+ }
537
+ if (state.bg !== void 0) {
538
+ codes.push(...state.bg);
539
+ }
540
+ return codes.length === 0 ? "" : `\x1B[${codes.join(";")}m`;
445
541
  }
542
+ export {
543
+ TerminalBuffer
544
+ };
545
+ //# sourceMappingURL=terminal-buffer.js.map