Skip to content

Commit

Permalink
Merge pull request #2168 from Tyriar/parser_core
Browse files Browse the repository at this point in the history
Move EscapeSequenceParser to core
  • Loading branch information
Tyriar authored Jun 1, 2019
2 parents 919c53a + 22c6a87 commit 67db588
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 167 deletions.
7 changes: 4 additions & 3 deletions src/InputHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,18 @@
* @license MIT
*/

import { IInputHandler, IDcsHandler, IEscapeSequenceParser, IInputHandlingTerminal } from './Types';
import { IInputHandler, IInputHandlingTerminal } from './Types';
import { C0, C1 } from 'common/data/EscapeSequences';
import { CHARSETS, DEFAULT_CHARSET } from 'core/data/Charsets';
import { wcwidth } from './CharWidth';
import { EscapeSequenceParser } from './EscapeSequenceParser';
import { EscapeSequenceParser } from 'core/parser/EscapeSequenceParser';
import { IDisposable } from 'xterm';
import { Disposable } from 'common/Lifecycle';
import { concat } from 'common/TypedArrayUtils';
import { StringToUtf32, stringFromCodePoint, utf32ToString, Utf8ToUtf32 } from 'core/input/TextDecoder';
import { CellData, Attributes, FgFlags, BgFlags, AttributeData, NULL_CELL_WIDTH, NULL_CELL_CODE, DEFAULT_ATTR_DATA } from 'core/buffer/BufferLine';
import { EventEmitter2, IEvent } from 'common/EventEmitter2';
import { IParsingState, IDcsHandler, IEscapeSequenceParser } from 'core/parser/Types';

/**
* Map collect to glevel. Used in `selectCharset`.
Expand Down Expand Up @@ -277,7 +278,7 @@ export class InputHandler extends Disposable implements IInputHandler {
/**
* error handler
*/
this._parser.setErrorHandler((state) => {
this._parser.setErrorHandler((state: IParsingState) => {
this._terminal.error('Parsing error: ', state);
return state;
});
Expand Down
141 changes: 0 additions & 141 deletions src/Types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -434,147 +434,6 @@ export interface ISoundManager {
playBellSound(): void;
}

/**
* Internal states of EscapeSequenceParser.
*/
export const enum ParserState {
GROUND = 0,
ESCAPE = 1,
ESCAPE_INTERMEDIATE = 2,
CSI_ENTRY = 3,
CSI_PARAM = 4,
CSI_INTERMEDIATE = 5,
CSI_IGNORE = 6,
SOS_PM_APC_STRING = 7,
OSC_STRING = 8,
DCS_ENTRY = 9,
DCS_PARAM = 10,
DCS_IGNORE = 11,
DCS_INTERMEDIATE = 12,
DCS_PASSTHROUGH = 13
}

/**
* Internal actions of EscapeSequenceParser.
*/
export const enum ParserAction {
IGNORE = 0,
ERROR = 1,
PRINT = 2,
EXECUTE = 3,
OSC_START = 4,
OSC_PUT = 5,
OSC_END = 6,
CSI_DISPATCH = 7,
PARAM = 8,
COLLECT = 9,
ESC_DISPATCH = 10,
CLEAR = 11,
DCS_HOOK = 12,
DCS_PUT = 13,
DCS_UNHOOK = 14
}

/**
* Internal state of EscapeSequenceParser.
* Used as argument of the error handler to allow
* introspection at runtime on parse errors.
* Return it with altered values to recover from
* faulty states (not yet supported).
* Set `abort` to `true` to abort the current parsing.
*/
export interface IParsingState {
// position in parse string
position: number;
// actual character code
code: number;
// current parser state
currentState: ParserState;
// print buffer start index (-1 for not set)
print: number;
// dcs buffer start index (-1 for not set)
dcs: number;
// osc string buffer
osc: string;
// collect buffer with intermediate characters
collect: string;
// params buffer
params: number[];
// should abort (default: false)
abort: boolean;
}

/**
* DCS handler signature for EscapeSequenceParser.
* EscapeSequenceParser handles DCS commands via separate
* subparsers that get hook/unhooked and can handle
* arbitrary amount of data.
*
* On entering a DSC sequence `hook` is called by
* `EscapeSequenceParser`. Use it to initialize or reset
* states needed to handle the current DCS sequence.
* Note: A DCS parser is only instantiated once, therefore
* you cannot rely on the ctor to reinitialize state.
*
* EscapeSequenceParser will call `put` several times if the
* parsed data got split, therefore you might have to collect
* `data` until `unhook` is called.
* Note: `data` is borrowed, if you cannot process the data
* in chunks you have to copy it, doing otherwise will lead to
* data losses or corruption.
*
* `unhook` marks the end of the current DCS sequence.
*/
export interface IDcsHandler {
hook(collect: string, params: number[], flag: number): void;
put(data: Uint32Array, start: number, end: number): void;
unhook(): void;
}

/**
* EscapeSequenceParser interface.
*/
export interface IEscapeSequenceParser extends IDisposable {
/**
* Reset the parser to its initial state (handlers are kept).
*/
reset(): void;

/**
* Parse string `data`.
* @param data The data to parse.
*/
parse(data: Uint32Array, length: number): void;

setPrintHandler(callback: (data: Uint32Array, start: number, end: number) => void): void;
clearPrintHandler(): void;

setExecuteHandler(flag: string, callback: () => void): void;
clearExecuteHandler(flag: string): void;
setExecuteHandlerFallback(callback: (code: number) => void): void;

setCsiHandler(flag: string, callback: (params: number[], collect: string) => void): void;
clearCsiHandler(flag: string): void;
setCsiHandlerFallback(callback: (collect: string, params: number[], flag: number) => void): void;
addCsiHandler(flag: string, callback: (params: number[], collect: string) => boolean): IDisposable;
addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable;

setEscHandler(collectAndFlag: string, callback: () => void): void;
clearEscHandler(collectAndFlag: string): void;
setEscHandlerFallback(callback: (collect: string, flag: number) => void): void;

setOscHandler(ident: number, callback: (data: string) => void): void;
clearOscHandler(ident: number): void;
setOscHandlerFallback(callback: (identifier: number, data: string) => void): void;

setDcsHandler(collectAndFlag: string, handler: IDcsHandler): void;
clearDcsHandler(collectAndFlag: string): void;
setDcsHandlerFallback(handler: IDcsHandler): void;

setErrorHandler(callback: (state: IParsingState) => IParsingState): void;
clearErrorHandler(): void;
}

export interface IMouseZoneManager extends IDisposable {
add(zone: IMouseZone): void;
clearAll(start?: number, end?: number): void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
* @license MIT
*/

import { ParserState, IDcsHandler, IParsingState } from './Types';
import { EscapeSequenceParser, TransitionTable, VT500_TRANSITION_TABLE } from './EscapeSequenceParser';
import { ParserState, IDcsHandler, IParsingState } from 'core/parser/Types';
import { EscapeSequenceParser, TransitionTable, VT500_TRANSITION_TABLE } from 'core/parser/EscapeSequenceParser';
import * as chai from 'chai';
import { StringToUtf32, stringFromCodePoint } from 'core/input/TextDecoder';

Expand Down Expand Up @@ -172,7 +172,7 @@ function parse(parser: TestEscapeSequenceParser, data: string): void {
}

describe('EscapeSequenceParser', function (): void {
let parser: TestEscapeSequenceParser | null = null;
let parser: TestEscapeSequenceParser;
const runs: IRun[] = [
{ tableType: 'Uint8Array', parser: parserUint },
{ tableType: 'Array', parser: parserArray }
Expand Down Expand Up @@ -995,7 +995,7 @@ describe('EscapeSequenceParser', function (): void {
});

runs.forEach(function (run: IRun): void {
let test: Function | null = null;
let test: Function;
describe('escape sequence examples / ' + run.tableType, function (): void {
before(function(): void {
parser = run.parser;
Expand Down Expand Up @@ -1122,7 +1122,7 @@ describe('EscapeSequenceParser', function (): void {

describe('set/clear handler', function (): void {
const INPUT = '\x1b[1;31mhello \x1b%Gwor\x1bEld!\x1b[0m\r\n$>\x1b]1;foo=bar\x1b\\';
let parser2: TestEscapeSequenceParser = null;
let parser2: TestEscapeSequenceParser;
let print = '';
const esc: string[] = [];
const csi: [string, number[], string][] = [];
Expand Down Expand Up @@ -1378,7 +1378,7 @@ describe('EscapeSequenceParser', function (): void {
chai.expect(dcs).eql([]);
});
it('ERROR handler', function (): void {
let errorState: IParsingState = null;
let errorState: IParsingState | null = null;
parser2.setErrorHandler(function (state: IParsingState): IParsingState {
errorState = state;
return state;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
* @license MIT
*/

import { ParserState, ParserAction, IParsingState, IDcsHandler, IEscapeSequenceParser } from './Types';
import { IDisposable } from 'xterm';
import { ParserState, ParserAction, IParsingState, IDcsHandler, IEscapeSequenceParser } from 'core/parser/Types';
import { Disposable } from 'common/Lifecycle';
import { utf32ToString } from 'core/input/TextDecoder';
import { IDisposable } from 'common/Types';

interface IHandlerCollection<T> {
[key: string]: T[];
Expand Down Expand Up @@ -50,8 +50,8 @@ export class TransitionTable {
* @param action parser action to be done
* @param next next parser state
*/
add(code: number, state: number, action: number | null, next: number | null): void {
this.table[state << 8 | code] = ((action | 0) << 4) | ((next === undefined) ? state : next);
add(code: number, state: ParserState, action: ParserAction, next: ParserState): void {
this.table[state << 8 | code] = (action << 4) | next;
}

/**
Expand All @@ -61,7 +61,7 @@ export class TransitionTable {
* @param action parser action to be done
* @param next next parser state
*/
addMany(codes: number[], state: number, action: number | null, next: number | null): void {
addMany(codes: number[], state: ParserState, action: ParserAction, next: ParserState): void {
for (let i = 0; i < codes.length; i++) {
this.add(codes[i], state, action, next);
}
Expand Down Expand Up @@ -279,21 +279,10 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
}

public dispose(): void {
this._printHandlerFb = null;
this._executeHandlerFb = null;
this._csiHandlerFb = null;
this._escHandlerFb = null;
this._oscHandlerFb = null;
this._dcsHandlerFb = null;
this._errorHandlerFb = null;
this._printHandler = null;
this._executeHandlers = null;
this._escHandlers = null;
this._csiHandlers = null;
this._oscHandlers = null;
this._dcsHandlers = null;
this._activeDcsHandler = null;
this._errorHandler = null;
}

setPrintHandler(callback: (data: Uint32Array, start: number, end: number) => void): void {
Expand Down Expand Up @@ -453,7 +442,9 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
this._printHandler(data, print, i);
print = -1;
} else if (~dcs) {
dcsHandler.put(data, dcs, i);
if (dcsHandler) {
dcsHandler.put(data, dcs, i);
}
dcs = -1;
}
break;
Expand Down
Loading

0 comments on commit 67db588

Please sign in to comment.