]> git.proxmox.com Git - mirror_xterm.js.git/blame - src/Parser.ts
Add character sets for most languages
[mirror_xterm.js.git] / src / Parser.ts
CommitLineData
ef60e50e
DI
1/**
2 * @license MIT
3 */
4
659fb90c
DI
5import { C0 } from './EscapeSequences';
6import { IInputHandler } from './Interfaces';
1848fff4 7import { CHARSETS } from './Charsets';
659fb90c 8
fa3484cd
DI
9const normalStateHandler: {[key: string]: (parser: Parser, handler: IInputHandler) => void} = {};
10normalStateHandler[C0.BEL] = (parser, handler) => handler.bell();
11normalStateHandler[C0.LF] = (parser, handler) => handler.lineFeed();
659fb90c
DI
12normalStateHandler[C0.VT] = normalStateHandler[C0.LF];
13normalStateHandler[C0.FF] = normalStateHandler[C0.LF];
fa3484cd
DI
14normalStateHandler[C0.CR] = (parser, handler) => handler.carriageReturn();
15normalStateHandler[C0.BS] = (parser, handler) => handler.backspace();
16normalStateHandler[C0.HT] = (parser, handler) => handler.tab();
17normalStateHandler[C0.SO] = (parser, handler) => handler.shiftOut();
18normalStateHandler[C0.SI] = (parser, handler) => handler.shiftIn();
19normalStateHandler[C0.ESC] = (parser, handler) => parser.setState(ParserState.ESCAPED);
672dc1a2 20
ecd7e69f
DI
21// TODO: Remove terminal when parser owns params and currentParam
22const escapedStateHandler: {[key: string]: (parser: Parser, terminal: any) => void} = {};
23escapedStateHandler['['] = (parser, terminal) => {
24 // ESC [ Control Sequence Introducer (CSI is 0x9b)
25 terminal.params = [];
26 terminal.currentParam = 0;
27 parser.setState(ParserState.CSI_PARAM);
28};
29escapedStateHandler[']'] = (parser, terminal) => {
30 // ESC ] Operating System Command (OSC is 0x9d)
31 terminal.params = [];
32 terminal.currentParam = 0;
33 parser.setState(ParserState.OSC);
34};
35escapedStateHandler['P'] = (parser, terminal) => {
36 // ESC P Device Control String (DCS is 0x90)
37 terminal.params = [];
38 terminal.currentParam = 0;
39 parser.setState(ParserState.DCS);
40};
41escapedStateHandler['_'] = (parser, terminal) => {
42 // ESC _ Application Program Command ( APC is 0x9f).
43 parser.setState(ParserState.IGNORE);
4448ebe3 44};
ecd7e69f
DI
45escapedStateHandler['^'] = (parser, terminal) => {
46 // ESC ^ Privacy Message ( PM is 0x9e).
47 parser.setState(ParserState.IGNORE);
4448ebe3 48};
ecd7e69f
DI
49escapedStateHandler['c'] = (parser, terminal) => {
50 // ESC c Full Reset (RIS).
51 terminal.reset();
4448ebe3 52};
ecd7e69f
DI
53escapedStateHandler['E'] = (parser, terminal) => {
54 // ESC E Next Line ( NEL is 0x85).
55 terminal.x = 0;
56 terminal.index();
57 parser.setState(ParserState.NORMAL);
4448ebe3 58};
ecd7e69f
DI
59escapedStateHandler['D'] = (parser, terminal) => {
60 // ESC D Index ( IND is 0x84).
61 terminal.index();
62 parser.setState(ParserState.NORMAL);
63};
64escapedStateHandler['M'] = (parser, terminal) => {
65 // ESC M Reverse Index ( RI is 0x8d).
66 terminal.reverseIndex();
67 parser.setState(ParserState.NORMAL);
68};
69escapedStateHandler['%'] = (parser, terminal) => {
70 // ESC % Select default/utf-8 character set.
71 // @ = default, G = utf-8
72 terminal.setgLevel(0);
73 terminal.setgCharset(0, CHARSETS.US);
74 parser.setState(ParserState.NORMAL);
75 parser.skipNextChar();
76};
77
7572dd5f
DI
78const csiParamStateHandler: {[key: string]: (parser: Parser) => void} = {};
79csiParamStateHandler['?'] = (parser) => parser.setPrefix('?');
80csiParamStateHandler['>'] = (parser) => parser.setPrefix('>');
81csiParamStateHandler['!'] = (parser) => parser.setPrefix('!');
82csiParamStateHandler['0'] = (parser) => parser.setParam(parser.getParam() * 10);
83csiParamStateHandler['1'] = (parser) => parser.setParam(parser.getParam() * 10 + 1);
84csiParamStateHandler['2'] = (parser) => parser.setParam(parser.getParam() * 10 + 2);
85csiParamStateHandler['3'] = (parser) => parser.setParam(parser.getParam() * 10 + 3);
86csiParamStateHandler['4'] = (parser) => parser.setParam(parser.getParam() * 10 + 4);
87csiParamStateHandler['5'] = (parser) => parser.setParam(parser.getParam() * 10 + 5);
88csiParamStateHandler['6'] = (parser) => parser.setParam(parser.getParam() * 10 + 6);
89csiParamStateHandler['7'] = (parser) => parser.setParam(parser.getParam() * 10 + 7);
90csiParamStateHandler['8'] = (parser) => parser.setParam(parser.getParam() * 10 + 8);
91csiParamStateHandler['9'] = (parser) => parser.setParam(parser.getParam() * 10 + 9);
92csiParamStateHandler['$'] = (parser) => parser.setPostfix('$');
93csiParamStateHandler['"'] = (parser) => parser.setPostfix('"');
94csiParamStateHandler[' '] = (parser) => parser.setPostfix(' ');
95csiParamStateHandler['\''] = (parser) => parser.setPostfix('\'');
c7fa2d55 96csiParamStateHandler[';'] = (parser) => parser.finalizeParam();
9942477b 97
0bd469f5 98const csiStateHandler: {[key: string]: (handler: IInputHandler, params: number[], prefix: string, postfix: string) => void} = {};
f4846aa1
DI
99csiStateHandler['@'] = (handler, params, prefix) => handler.insertChars(params);
100csiStateHandler['A'] = (handler, params, prefix) => handler.cursorUp(params);
101csiStateHandler['B'] = (handler, params, prefix) => handler.cursorDown(params);
102csiStateHandler['C'] = (handler, params, prefix) => handler.cursorForward(params);
103csiStateHandler['D'] = (handler, params, prefix) => handler.cursorBackward(params);
104csiStateHandler['E'] = (handler, params, prefix) => handler.cursorNextLine(params);
105csiStateHandler['F'] = (handler, params, prefix) => handler.cursorPrecedingLine(params);
106csiStateHandler['G'] = (handler, params, prefix) => handler.cursorCharAbsolute(params);
107csiStateHandler['H'] = (handler, params, prefix) => handler.cursorPosition(params);
108csiStateHandler['I'] = (handler, params, prefix) => handler.cursorForwardTab(params);
109csiStateHandler['J'] = (handler, params, prefix) => handler.eraseInDisplay(params);
110csiStateHandler['K'] = (handler, params, prefix) => handler.eraseInLine(params);
111csiStateHandler['L'] = (handler, params, prefix) => handler.insertLines(params);
112csiStateHandler['M'] = (handler, params, prefix) => handler.deleteLines(params);
113csiStateHandler['P'] = (handler, params, prefix) => handler.deleteChars(params);
114csiStateHandler['S'] = (handler, params, prefix) => handler.scrollUp(params);
115csiStateHandler['T'] = (handler, params, prefix) => {
116 if (params.length < 2 && !prefix) {
117 handler.scrollDown(params);
118 }
119};
120csiStateHandler['X'] = (handler, params, prefix) => handler.eraseChars(params);
121csiStateHandler['Z'] = (handler, params, prefix) => handler.cursorBackwardTab(params);
122csiStateHandler['`'] = (handler, params, prefix) => handler.charPosAbsolute(params);
123csiStateHandler['a'] = (handler, params, prefix) => handler.HPositionRelative(params);
124csiStateHandler['b'] = (handler, params, prefix) => handler.repeatPrecedingCharacter(params);
125csiStateHandler['c'] = (handler, params, prefix) => handler.sendDeviceAttributes(params);
126csiStateHandler['d'] = (handler, params, prefix) => handler.linePosAbsolute(params);
127csiStateHandler['e'] = (handler, params, prefix) => handler.VPositionRelative(params);
128csiStateHandler['f'] = (handler, params, prefix) => handler.HVPosition(params);
129csiStateHandler['g'] = (handler, params, prefix) => handler.tabClear(params);
130csiStateHandler['h'] = (handler, params, prefix) => handler.setMode(params);
131csiStateHandler['l'] = (handler, params, prefix) => handler.resetMode(params);
132csiStateHandler['m'] = (handler, params, prefix) => handler.charAttributes(params);
133csiStateHandler['n'] = (handler, params, prefix) => handler.deviceStatus(params);
134csiStateHandler['p'] = (handler, params, prefix) => {
135 switch (prefix) {
136 case '!': handler.softReset(params); break;
137 }
138};
0bd469f5
DI
139csiStateHandler['q'] = (handler, params, prefix, postfix) => {
140 if (postfix === ' ') {
141 handler.setCursorStyle(params);
142 }
143};
9b662080
DI
144csiStateHandler['r'] = (handler, params) => handler.setScrollRegion(params);
145csiStateHandler['s'] = (handler, params) => handler.saveCursor(params);
146csiStateHandler['u'] = (handler, params) => handler.restoreCursor(params);
a31921ae 147
4448ebe3
DI
148// TODO: Many codes/charsets appear to not be supported
149// See: http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
150const charsetMap = {
151 '0': CHARSETS.SCLD,
152 'A': CHARSETS.UK, // United Kingdom
153 'B': CHARSETS.US, // United States (USASCII)
154 '4': CHARSETS.Dutch,
155 'C': CHARSETS.Finnish,
156 '5': CHARSETS.Finnish,
157 'f': CHARSETS.French,
158 'Q': CHARSETS.FrenchCanadian,
159 'K': CHARSETS.German,
160 'Y': CHARSETS.Italian,
161 'E': CHARSETS.NorwegianDanish,
162 '6': CHARSETS.NorwegianDanish,
163 'Z': CHARSETS.Spanish,
164 'H': CHARSETS.Swedish,
165 '7': CHARSETS.Swedish,
166 '=': CHARSETS.Swiss,
167 '/': CHARSETS.ISOLatin // ISOLatin is actually /A
168};
169
a31921ae
DI
170enum ParserState {
171 NORMAL = 0,
172 ESCAPED = 1,
c7fa2d55
DI
173 CSI_PARAM = 2,
174 CSI = 3,
175 OSC = 4,
176 CHARSET = 5,
177 DCS = 6,
178 IGNORE = 7
a31921ae
DI
179}
180
ef60e50e
DI
181/**
182 * The terminal's parser, all input into the terminal goes through the parser
183 * which parses and defers the actual input handling the the IInputHandler
184 * specified in the constructor.
185 */
a31921ae 186export class Parser {
ecd7e69f
DI
187 private _state: ParserState;
188 private _position: number;
a31921ae
DI
189
190 // TODO: Remove terminal when handler can do everything
191 constructor(
192 private _inputHandler: IInputHandler,
193 private _terminal: any
194 ) {
ecd7e69f 195 this._state = ParserState.NORMAL;
a31921ae
DI
196 }
197
ef60e50e
DI
198 /**
199 * Parse and handle data.
200 *
201 * @param data The data to parse.
202 */
a31921ae 203 public parse(data: string) {
ecd7e69f 204 let l = data.length, j, cs, ch, code, low;
a31921ae 205
ecd7e69f 206 this._position = 0;
a31921ae
DI
207 // apply leftover surrogate high from last write
208 if (this._terminal.surrogate_high) {
209 data = this._terminal.surrogate_high + data;
210 this._terminal.surrogate_high = '';
211 }
212
ecd7e69f
DI
213 for (; this._position < l; this._position++) {
214 ch = data[this._position];
a31921ae
DI
215
216 // FIXME: higher chars than 0xa0 are not allowed in escape sequences
217 // --> maybe move to default
ecd7e69f 218 code = data.charCodeAt(this._position);
a31921ae
DI
219 if (0xD800 <= code && code <= 0xDBFF) {
220 // we got a surrogate high
221 // get surrogate low (next 2 bytes)
ecd7e69f 222 low = data.charCodeAt(this._position + 1);
a31921ae
DI
223 if (isNaN(low)) {
224 // end of data stream, save surrogate high
225 this._terminal.surrogate_high = ch;
226 continue;
227 }
228 code = ((code - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;
ecd7e69f 229 ch += data.charAt(this._position + 1);
a31921ae
DI
230 }
231 // surrogate low - already handled above
232 if (0xDC00 <= code && code <= 0xDFFF)
233 continue;
234
ecd7e69f 235 switch (this._state) {
a31921ae 236 case ParserState.NORMAL:
fa3484cd
DI
237 if (ch in normalStateHandler) {
238 normalStateHandler[ch](this, this._inputHandler);
239 } else {
240 this._inputHandler.addChar(ch, code);
a31921ae
DI
241 }
242 break;
243 case ParserState.ESCAPED:
ecd7e69f
DI
244 if (ch in escapedStateHandler) {
245 escapedStateHandler[ch](this, this._terminal);
246 // Skip switch as it was just handled
247 break;
248 }
a31921ae 249 switch (ch) {
a31921ae
DI
250
251 // ESC (,),*,+,-,. Designate G0-G2 Character Set.
252 case '(': // <-- this seems to get all the attention
253 case ')':
254 case '*':
255 case '+':
256 case '-':
257 case '.':
258 switch (ch) {
259 case '(':
991b2843 260 this._terminal.gcharset = 0;
a31921ae
DI
261 break;
262 case ')':
991b2843 263 this._terminal.gcharset = 1;
a31921ae
DI
264 break;
265 case '*':
991b2843 266 this._terminal.gcharset = 2;
a31921ae
DI
267 break;
268 case '+':
991b2843 269 this._terminal.gcharset = 3;
a31921ae
DI
270 break;
271 case '-':
991b2843 272 this._terminal.gcharset = 1;
a31921ae
DI
273 break;
274 case '.':
991b2843 275 this._terminal.gcharset = 2;
a31921ae
DI
276 break;
277 }
ecd7e69f 278 this._state = ParserState.CHARSET;
a31921ae
DI
279 break;
280
281 // Designate G3 Character Set (VT300).
282 // A = ISO Latin-1 Supplemental.
283 // Not implemented.
284 case '/':
991b2843 285 this._terminal.gcharset = 3;
ecd7e69f
DI
286 this._state = ParserState.CHARSET;
287 this._position--;
a31921ae
DI
288 break;
289
290 // ESC N
291 // Single Shift Select of G2 Character Set
292 // ( SS2 is 0x8e). This affects next character only.
293 case 'N':
294 break;
295 // ESC O
296 // Single Shift Select of G3 Character Set
297 // ( SS3 is 0x8f). This affects next character only.
298 case 'O':
299 break;
300 // ESC n
301 // Invoke the G2 Character Set as GL (LS2).
302 case 'n':
991b2843 303 this._terminal.setgLevel(2);
a31921ae
DI
304 break;
305 // ESC o
306 // Invoke the G3 Character Set as GL (LS3).
307 case 'o':
991b2843 308 this._terminal.setgLevel(3);
a31921ae
DI
309 break;
310 // ESC |
311 // Invoke the G3 Character Set as GR (LS3R).
312 case '|':
991b2843 313 this._terminal.setgLevel(3);
a31921ae
DI
314 break;
315 // ESC }
316 // Invoke the G2 Character Set as GR (LS2R).
317 case '}':
991b2843 318 this._terminal.setgLevel(2);
a31921ae
DI
319 break;
320 // ESC ~
321 // Invoke the G1 Character Set as GR (LS1R).
322 case '~':
991b2843 323 this._terminal.setgLevel(1);
a31921ae
DI
324 break;
325
326 // ESC 7 Save Cursor (DECSC).
327 case '7':
f4846aa1 328 this._inputHandler.saveCursor();
ecd7e69f 329 this._state = ParserState.NORMAL;
a31921ae
DI
330 break;
331
332 // ESC 8 Restore Cursor (DECRC).
333 case '8':
f4846aa1 334 this._inputHandler.restoreCursor();
ecd7e69f 335 this._state = ParserState.NORMAL;
a31921ae
DI
336 break;
337
338 // ESC # 3 DEC line height/width
339 case '#':
ecd7e69f
DI
340 this._state = ParserState.NORMAL;
341 this._position++;
a31921ae
DI
342 break;
343
344 // ESC H Tab Set (HTS is 0x88).
345 case 'H':
991b2843 346 this._terminal.tabSet();
ecd7e69f 347 this._state = ParserState.NORMAL;
a31921ae
DI
348 break;
349
350 // ESC = Application Keypad (DECKPAM).
351 case '=':
991b2843
DI
352 this._terminal.log('Serial port requested application keypad.');
353 this._terminal.applicationKeypad = true;
354 this._terminal.viewport.syncScrollArea();
ecd7e69f 355 this._state = ParserState.NORMAL;
a31921ae
DI
356 break;
357
358 // ESC > Normal Keypad (DECKPNM).
359 case '>':
991b2843
DI
360 this._terminal.log('Switching back to normal keypad.');
361 this._terminal.applicationKeypad = false;
362 this._terminal.viewport.syncScrollArea();
ecd7e69f 363 this._state = ParserState.NORMAL;
a31921ae
DI
364 break;
365
366 default:
ecd7e69f 367 this._state = ParserState.NORMAL;
991b2843 368 this._terminal.error('Unknown ESC control: %s.', ch);
a31921ae
DI
369 break;
370 }
371 break;
372
373 case ParserState.CHARSET:
4448ebe3
DI
374 if (ch in charsetMap) {
375 cs = charsetMap[ch];
376 if (ch === '/') { // ISOLatin is actually /A
377 this.skipNextChar();
378 }
379 } else {
380 cs = CHARSETS.US; // Default
a31921ae 381 }
991b2843
DI
382 this._terminal.setgCharset(this._terminal.gcharset, cs);
383 this._terminal.gcharset = null;
ecd7e69f 384 this._state = ParserState.NORMAL;
a31921ae
DI
385 break;
386
387 case ParserState.OSC:
388 // OSC Ps ; Pt ST
389 // OSC Ps ; Pt BEL
390 // Set Text Parameters.
391 if (ch === C0.ESC || ch === C0.BEL) {
ecd7e69f 392 if (ch === C0.ESC) this._position++;
a31921ae 393
991b2843 394 this._terminal.params.push(this._terminal.currentParam);
a31921ae 395
991b2843 396 switch (this._terminal.params[0]) {
a31921ae
DI
397 case 0:
398 case 1:
399 case 2:
991b2843
DI
400 if (this._terminal.params[1]) {
401 this._terminal.title = this._terminal.params[1];
402 this._terminal.handleTitle(this._terminal.title);
a31921ae
DI
403 }
404 break;
405 case 3:
406 // set X property
407 break;
408 case 4:
409 case 5:
410 // change dynamic colors
411 break;
412 case 10:
413 case 11:
414 case 12:
415 case 13:
416 case 14:
417 case 15:
418 case 16:
419 case 17:
420 case 18:
421 case 19:
422 // change dynamic ui colors
423 break;
424 case 46:
425 // change log file
426 break;
427 case 50:
428 // dynamic font
429 break;
430 case 51:
431 // emacs shell
432 break;
433 case 52:
434 // manipulate selection data
435 break;
436 case 104:
437 case 105:
438 case 110:
439 case 111:
440 case 112:
441 case 113:
442 case 114:
443 case 115:
444 case 116:
445 case 117:
446 case 118:
447 // reset colors
448 break;
449 }
450
991b2843
DI
451 this._terminal.params = [];
452 this._terminal.currentParam = 0;
ecd7e69f 453 this._state = ParserState.NORMAL;
a31921ae 454 } else {
991b2843 455 if (!this._terminal.params.length) {
a31921ae 456 if (ch >= '0' && ch <= '9') {
991b2843
DI
457 this._terminal.currentParam =
458 this._terminal.currentParam * 10 + ch.charCodeAt(0) - 48;
a31921ae 459 } else if (ch === ';') {
991b2843
DI
460 this._terminal.params.push(this._terminal.currentParam);
461 this._terminal.currentParam = '';
a31921ae
DI
462 }
463 } else {
991b2843 464 this._terminal.currentParam += ch;
a31921ae
DI
465 }
466 }
467 break;
468
c7fa2d55 469 case ParserState.CSI_PARAM:
9942477b 470 if (ch in csiParamStateHandler) {
7572dd5f 471 csiParamStateHandler[ch](this);
a31921ae
DI
472 break;
473 }
c7fa2d55
DI
474 this.finalizeParam();
475 // Fall through the CSI as this character should be the CSI code.
ecd7e69f 476 this._state = ParserState.CSI;
a31921ae 477
c7fa2d55 478 case ParserState.CSI:
9942477b 479 if (ch in csiStateHandler) {
0bd469f5 480 csiStateHandler[ch](this._inputHandler, this._terminal.params, this._terminal.prefix, this._terminal.postfix);
f4846aa1
DI
481 } else {
482 this._terminal.error('Unknown CSI code: %s.', ch);
a31921ae
DI
483 }
484
ecd7e69f 485 this._state = ParserState.NORMAL;
991b2843
DI
486 this._terminal.prefix = '';
487 this._terminal.postfix = '';
a31921ae
DI
488 break;
489
490 case ParserState.DCS:
491 if (ch === C0.ESC || ch === C0.BEL) {
ecd7e69f 492 if (ch === C0.ESC) this._position++;
a31921ae 493
991b2843 494 switch (this._terminal.prefix) {
a31921ae
DI
495 // User-Defined Keys (DECUDK).
496 case '':
497 break;
498
499 // Request Status String (DECRQSS).
500 // test: echo -e '\eP$q"p\e\\'
501 case '$q':
991b2843 502 let pt = this._terminal.currentParam
a31921ae
DI
503 , valid = false;
504
505 switch (pt) {
506 // DECSCA
507 case '"q':
508 pt = '0"q';
509 break;
510
511 // DECSCL
512 case '"p':
513 pt = '61"p';
514 break;
515
516 // DECSTBM
517 case 'r':
518 pt = ''
991b2843 519 + (this._terminal.scrollTop + 1)
a31921ae 520 + ';'
991b2843 521 + (this._terminal.scrollBottom + 1)
a31921ae
DI
522 + 'r';
523 break;
524
525 // SGR
526 case 'm':
527 pt = '0m';
528 break;
529
530 default:
991b2843 531 this._terminal.error('Unknown DCS Pt: %s.', pt);
a31921ae
DI
532 pt = '';
533 break;
534 }
535
991b2843 536 this._terminal.send(C0.ESC + 'P' + +valid + '$r' + pt + C0.ESC + '\\');
a31921ae
DI
537 break;
538
539 // Set Termcap/Terminfo Data (xterm, experimental).
540 case '+p':
541 break;
542
543 // Request Termcap/Terminfo String (xterm, experimental)
544 // Regular xterm does not even respond to this sequence.
545 // This can cause a small glitch in vim.
546 // test: echo -ne '\eP+q6b64\e\\'
547 case '+q':
991b2843
DI
548 // TODO: Don't declare pt twice
549 /*let*/ pt = this._terminal.currentParam
a31921ae
DI
550 , valid = false;
551
991b2843 552 this._terminal.send(C0.ESC + 'P' + +valid + '+r' + pt + C0.ESC + '\\');
a31921ae
DI
553 break;
554
555 default:
991b2843 556 this._terminal.error('Unknown DCS prefix: %s.', this._terminal.prefix);
a31921ae
DI
557 break;
558 }
559
991b2843
DI
560 this._terminal.currentParam = 0;
561 this._terminal.prefix = '';
ecd7e69f 562 this._state = ParserState.NORMAL;
991b2843
DI
563 } else if (!this._terminal.currentParam) {
564 if (!this._terminal.prefix && ch !== '$' && ch !== '+') {
565 this._terminal.currentParam = ch;
566 } else if (this._terminal.prefix.length === 2) {
567 this._terminal.currentParam = ch;
a31921ae 568 } else {
991b2843 569 this._terminal.prefix += ch;
a31921ae
DI
570 }
571 } else {
991b2843 572 this._terminal.currentParam += ch;
a31921ae
DI
573 }
574 break;
575
576 case ParserState.IGNORE:
577 // For PM and APC.
578 if (ch === C0.ESC || ch === C0.BEL) {
ecd7e69f
DI
579 if (ch === C0.ESC) this._position++;
580 this._state = ParserState.NORMAL;
a31921ae
DI
581 }
582 break;
583 }
584 }
585 }
672dc1a2 586
ef60e50e
DI
587 /**
588 * Set the parser's current parsing state.
589 *
590 * @param state The new state.
591 */
fa3484cd 592 public setState(state: ParserState): void {
ecd7e69f 593 this._state = state;
fa3484cd
DI
594 }
595
ef60e50e
DI
596 /**
597 * Sets the parsier's current prefix. CSI codes can have prefixes of '?', '>'
598 * or '!'.
599 *
600 * @param prefix The prefix.
601 */
635a4d76 602 public setPrefix(prefix: string): void {
672dc1a2
DI
603 this._terminal.prefix = prefix;
604 }
605
ef60e50e
DI
606 /**
607 * Sets the parsier's current prefix. CSI codes can have postfixes of '$',
608 * '"', ' ', '\''.
609 *
610 * @param postfix The postfix.
611 */
612 public setPostfix(postfix: string): void {
613 this._terminal.postfix = postfix;
614 }
615
616 /**
617 * Sets the parser's current parameter.
618 *
619 * @param param the parameter.
620 */
672dc1a2
DI
621 public setParam(param: number) {
622 this._terminal.currentParam = param;
623 }
624
ef60e50e
DI
625 /**
626 * Gets the parser's current parameter.
627 */
672dc1a2
DI
628 public getParam(): number {
629 return this._terminal.currentParam;
630 }
635a4d76 631
ef60e50e
DI
632 /**
633 * Finalizes the parser's current parameter, adding it to the list of
634 * parameters and setting the new current parameter to 0.
635 */
c7fa2d55
DI
636 public finalizeParam(): void {
637 this._terminal.params.push(this._terminal.currentParam);
638 this._terminal.currentParam = 0;
639 }
640
ef60e50e
DI
641 /**
642 * Tell the parser to skip the next character.
643 */
ecd7e69f
DI
644 public skipNextChar(): void {
645 this._position++;
646 }
647
ef60e50e
DI
648 /**
649 * Tell the parser to repeat parsing the current character (for example if it
650 * needs parsing using a different state.
651 */
ecd7e69f
DI
652 // public repeatChar(): void {
653 // this._position--;
654 // }
a31921ae 655}