mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
cleanup parser rules and docs
This commit is contained in:
+1
-2
@@ -231,8 +231,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
this._parser.setExecuteHandler(C0.SO, () => this.shiftOut());
|
||||
this._parser.setExecuteHandler(C0.SI, () => this.shiftIn());
|
||||
// FIXME: What do to with missing? Old code just added those to print.
|
||||
|
||||
// some C1 control codes - FIXME: should those be enabled by default?
|
||||
|
||||
this._parser.setExecuteHandler(C1.IND, () => this.index());
|
||||
this._parser.setExecuteHandler(C1.NEL, () => this.nextLine());
|
||||
this._parser.setExecuteHandler(C1.HTS, () => this.tabSet());
|
||||
|
||||
@@ -12,7 +12,8 @@ import { PAYLOAD_LIMIT } from 'common/parser/Constants';
|
||||
|
||||
export class DcsParser implements IDcsParser {
|
||||
private _handlers: IHandlerCollection<IDcsHandler> = Object.create(null);
|
||||
private _active: IDcsHandler[] = [];
|
||||
private _empty: IDcsHandler[] = [];
|
||||
private _active: IDcsHandler[] = this._empty;
|
||||
private _ident: number = 0;
|
||||
private _handlerFb: DcsFallbackHandler = () => {};
|
||||
|
||||
@@ -53,13 +54,15 @@ export class DcsParser implements IDcsParser {
|
||||
if (this._active.length) {
|
||||
this.unhook(false);
|
||||
}
|
||||
this._active = [];
|
||||
this._active = this._empty;
|
||||
this._ident = 0;
|
||||
}
|
||||
|
||||
public hook(ident: number, params: IParams): void {
|
||||
// always reset leftover handlers
|
||||
this.reset();
|
||||
this._ident = ident;
|
||||
this._active = this._handlers[ident] || [];
|
||||
this._active = this._handlers[ident] || this._empty;
|
||||
if (!this._active.length) {
|
||||
this._handlerFb(this._ident, 'HOOK', params);
|
||||
} else {
|
||||
@@ -95,7 +98,7 @@ export class DcsParser implements IDcsParser {
|
||||
this._active[j].unhook(false);
|
||||
}
|
||||
}
|
||||
this._active = [];
|
||||
this._active = this._empty;
|
||||
this._ident = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,12 +279,10 @@ describe('EscapeSequenceParser', function (): void {
|
||||
parser.reset();
|
||||
for (state in states) {
|
||||
parser.currentState = state;
|
||||
parser.osc = '#';
|
||||
parser.params = [23];
|
||||
parser.collect = '#';
|
||||
parse(parser, '\x1b');
|
||||
chai.expect(parser.currentState).equal(ParserState.ESCAPE);
|
||||
chai.expect(parser.osc).equal('');
|
||||
chai.expect(parser.params).eql([0]);
|
||||
chai.expect(parser.collect).equal('');
|
||||
parser.reset();
|
||||
@@ -396,24 +394,20 @@ describe('EscapeSequenceParser', function (): void {
|
||||
parser.reset();
|
||||
// C0
|
||||
parser.currentState = ParserState.ESCAPE;
|
||||
parser.osc = '#';
|
||||
parser.params = [123];
|
||||
parser.collect = '#';
|
||||
parse(parser, '[');
|
||||
chai.expect(parser.currentState).equal(ParserState.CSI_ENTRY);
|
||||
chai.expect(parser.osc).equal('');
|
||||
chai.expect(parser.params).eql([0]);
|
||||
chai.expect(parser.collect).equal('');
|
||||
parser.reset();
|
||||
// C1
|
||||
for (state in states) {
|
||||
parser.currentState = state;
|
||||
parser.osc = '#';
|
||||
parser.params = [123];
|
||||
parser.collect = '#';
|
||||
parse(parser, '\x9b');
|
||||
chai.expect(parser.currentState).equal(ParserState.CSI_ENTRY);
|
||||
chai.expect(parser.osc).equal('');
|
||||
chai.expect(parser.params).eql([0]);
|
||||
chai.expect(parser.collect).equal('');
|
||||
parser.reset();
|
||||
|
||||
@@ -334,24 +334,24 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
this._dcsParser.dispose();
|
||||
}
|
||||
|
||||
setPrintHandler(callback: (data: Uint32Array, start: number, end: number) => void): void {
|
||||
public setPrintHandler(callback: (data: Uint32Array, start: number, end: number) => void): void {
|
||||
this._printHandler = callback;
|
||||
}
|
||||
clearPrintHandler(): void {
|
||||
public clearPrintHandler(): void {
|
||||
this._printHandler = this._printHandlerFb;
|
||||
}
|
||||
|
||||
setExecuteHandler(flag: string, callback: () => void): void {
|
||||
public setExecuteHandler(flag: string, callback: () => void): void {
|
||||
this._executeHandlers[flag.charCodeAt(0)] = callback;
|
||||
}
|
||||
clearExecuteHandler(flag: string): void {
|
||||
public clearExecuteHandler(flag: string): void {
|
||||
if (this._executeHandlers[flag.charCodeAt(0)]) delete this._executeHandlers[flag.charCodeAt(0)];
|
||||
}
|
||||
setExecuteHandlerFallback(callback: (code: number) => void): void {
|
||||
public setExecuteHandlerFallback(callback: (code: number) => void): void {
|
||||
this._executeHandlerFb = callback;
|
||||
}
|
||||
|
||||
addCsiHandler(id: IFunctionIdentifier, callback: CsiHandler): IDisposable {
|
||||
public addCsiHandler(id: IFunctionIdentifier, callback: CsiHandler): IDisposable {
|
||||
const ident = this._identifier(id);
|
||||
if (this._csiHandlers[ident] === undefined) {
|
||||
this._csiHandlers[ident] = [];
|
||||
@@ -367,17 +367,17 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
}
|
||||
};
|
||||
}
|
||||
setCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => void): void {
|
||||
public setCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => void): void {
|
||||
this._csiHandlers[this._identifier(id)] = [callback];
|
||||
}
|
||||
clearCsiHandler(id: IFunctionIdentifier): void {
|
||||
public clearCsiHandler(id: IFunctionIdentifier): void {
|
||||
if (this._csiHandlers[this._identifier(id)]) delete this._csiHandlers[this._identifier(id)];
|
||||
}
|
||||
setCsiHandlerFallback(callback: (ident: number, params: IParams) => void): void {
|
||||
public setCsiHandlerFallback(callback: (ident: number, params: IParams) => void): void {
|
||||
this._csiHandlerFb = callback;
|
||||
}
|
||||
|
||||
addEscHandler(id: IFunctionIdentifier, callback: EscHandler): IDisposable {
|
||||
public addEscHandler(id: IFunctionIdentifier, callback: EscHandler): IDisposable {
|
||||
const ident = this._identifier(id, [0x30, 0x7e]);
|
||||
if (this._escHandlers[ident] === undefined) {
|
||||
this._escHandlers[ident] = [];
|
||||
@@ -393,50 +393,50 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
}
|
||||
};
|
||||
}
|
||||
setEscHandler(id: IFunctionIdentifier, callback: () => void): void {
|
||||
public setEscHandler(id: IFunctionIdentifier, callback: () => void): void {
|
||||
this._escHandlers[this._identifier(id, [0x30, 0x7e])] = [callback];
|
||||
}
|
||||
clearEscHandler(id: IFunctionIdentifier): void {
|
||||
public clearEscHandler(id: IFunctionIdentifier): void {
|
||||
if (this._escHandlers[this._identifier(id, [0x30, 0x7e])]) delete this._escHandlers[this._identifier(id, [0x30, 0x7e])];
|
||||
}
|
||||
setEscHandlerFallback(callback: (ident: number) => void): void {
|
||||
public setEscHandlerFallback(callback: (ident: number) => void): void {
|
||||
this._escHandlerFb = callback;
|
||||
}
|
||||
|
||||
addOscHandler(ident: number, handler: IOscHandler): IDisposable {
|
||||
public addOscHandler(ident: number, handler: IOscHandler): IDisposable {
|
||||
return this._oscParser.addOscHandler(ident, handler);
|
||||
}
|
||||
setOscHandler(ident: number, handler: IOscHandler): void {
|
||||
public setOscHandler(ident: number, handler: IOscHandler): void {
|
||||
this._oscParser.setOscHandler(ident, handler);
|
||||
}
|
||||
clearOscHandler(ident: number): void {
|
||||
public clearOscHandler(ident: number): void {
|
||||
this._oscParser.clearOscHandler(ident);
|
||||
}
|
||||
setOscHandlerFallback(handler: OscFallbackHandler): void {
|
||||
public setOscHandlerFallback(handler: OscFallbackHandler): void {
|
||||
this._oscParser.setOscHandlerFallback(handler);
|
||||
}
|
||||
|
||||
addDcsHandler(id: IFunctionIdentifier, handler: IDcsHandler): IDisposable {
|
||||
public addDcsHandler(id: IFunctionIdentifier, handler: IDcsHandler): IDisposable {
|
||||
return this._dcsParser.addDcsHandler(this._identifier(id), handler);
|
||||
}
|
||||
setDcsHandler(id: IFunctionIdentifier, handler: IDcsHandler): void {
|
||||
public setDcsHandler(id: IFunctionIdentifier, handler: IDcsHandler): void {
|
||||
this._dcsParser.setDcsHandler(this._identifier(id), handler);
|
||||
}
|
||||
clearDcsHandler(id: IFunctionIdentifier): void {
|
||||
public clearDcsHandler(id: IFunctionIdentifier): void {
|
||||
this._dcsParser.clearDcsHandler(this._identifier(id));
|
||||
}
|
||||
setDcsHandlerFallback(handler: DcsFallbackHandler): void {
|
||||
public setDcsHandlerFallback(handler: DcsFallbackHandler): void {
|
||||
this._dcsParser.setDcsHandlerFallback(handler);
|
||||
}
|
||||
|
||||
setErrorHandler(callback: (state: IParsingState) => IParsingState): void {
|
||||
public setErrorHandler(callback: (state: IParsingState) => IParsingState): void {
|
||||
this._errorHandler = callback;
|
||||
}
|
||||
clearErrorHandler(): void {
|
||||
public clearErrorHandler(): void {
|
||||
this._errorHandler = this._errorHandlerFb;
|
||||
}
|
||||
|
||||
reset(): void {
|
||||
public reset(): void {
|
||||
this.currentState = this.initialState;
|
||||
this._oscParser.reset();
|
||||
this._dcsParser.reset();
|
||||
@@ -463,7 +463,7 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
* - OSC_STRING:OSC_PUT
|
||||
* - DCS_PASSTHROUGH:DCS_PUT
|
||||
*/
|
||||
parse(data: Uint32Array, length: number): void {
|
||||
public parse(data: Uint32Array, length: number): void {
|
||||
let code = 0;
|
||||
let transition = 0;
|
||||
let currentState = this.currentState;
|
||||
@@ -472,7 +472,6 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
let collect = this._collect;
|
||||
const params = this._params;
|
||||
const table: Uint8Array = this.TRANSITIONS.table;
|
||||
let callback: Function | null = null;
|
||||
|
||||
// process input string
|
||||
for (let i = 0; i < length; ++i) {
|
||||
@@ -508,8 +507,7 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
}
|
||||
break;
|
||||
case ParserAction.EXECUTE:
|
||||
callback = this._executeHandlers[code];
|
||||
if (callback) callback();
|
||||
if (this._executeHandlers[code]) this._executeHandlers[code]();
|
||||
else this._executeHandlerFb(code);
|
||||
this.precedingCodepoint = 0;
|
||||
break;
|
||||
@@ -581,7 +579,6 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
this.precedingCodepoint = 0;
|
||||
break;
|
||||
case ParserAction.CLEAR:
|
||||
osc.reset();
|
||||
params.reset();
|
||||
params.addParam(0); // ZDM
|
||||
collect = 0;
|
||||
@@ -603,7 +600,6 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
case ParserAction.DCS_UNHOOK:
|
||||
dcs.unhook(code !== 0x18 && code !== 0x1a);
|
||||
if (code === 0x1b) transition |= ParserState.ESCAPE;
|
||||
osc.reset();
|
||||
params.reset();
|
||||
params.addParam(0); // ZDM
|
||||
collect = 0;
|
||||
@@ -625,7 +621,6 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
case ParserAction.OSC_END:
|
||||
osc.end(code !== 0x18 && code !== 0x1a);
|
||||
if (code === 0x1b) transition |= ParserState.ESCAPE;
|
||||
osc.reset();
|
||||
params.reset();
|
||||
params.addParam(0); // ZDM
|
||||
collect = 0;
|
||||
@@ -635,7 +630,7 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
currentState = transition & TableAccess.TRANSITION_STATE_MASK;
|
||||
}
|
||||
|
||||
// save non pushable buffers
|
||||
// save collected intermediates
|
||||
this._collect = collect;
|
||||
|
||||
// save state
|
||||
|
||||
@@ -16,7 +16,7 @@ export class OscParser extends Disposable {
|
||||
private _handlers: IHandlerCollection<IOscHandler> = Object.create(null);
|
||||
private _handlerFb: OscFallbackHandler = () => { };
|
||||
|
||||
addOscHandler(ident: number, handler: IOscHandler): IDisposable {
|
||||
public addOscHandler(ident: number, handler: IOscHandler): IDisposable {
|
||||
if (this._handlers[ident] === undefined) {
|
||||
this._handlers[ident] = [];
|
||||
}
|
||||
@@ -31,13 +31,13 @@ export class OscParser extends Disposable {
|
||||
}
|
||||
};
|
||||
}
|
||||
setOscHandler(ident: number, handler: IOscHandler): void {
|
||||
public setOscHandler(ident: number, handler: IOscHandler): void {
|
||||
this._handlers[ident] = [handler];
|
||||
}
|
||||
clearOscHandler(ident: number): void {
|
||||
public clearOscHandler(ident: number): void {
|
||||
if (this._handlers[ident]) delete this._handlers[ident];
|
||||
}
|
||||
setOscHandlerFallback(handler: OscFallbackHandler): void {
|
||||
public setOscHandlerFallback(handler: OscFallbackHandler): void {
|
||||
this._handlerFb = handler;
|
||||
}
|
||||
|
||||
@@ -100,6 +100,8 @@ export class OscParser extends Disposable {
|
||||
}
|
||||
|
||||
public start(): void {
|
||||
// always reset leftover handlers
|
||||
this.reset();
|
||||
this._id = -1;
|
||||
this._state = OscState.ID;
|
||||
}
|
||||
|
||||
Vendored
+61
-33
@@ -502,14 +502,13 @@ declare module 'xterm' {
|
||||
|
||||
/**
|
||||
* Adds a handler for CSI escape sequences.
|
||||
* @param id Specifies the function identifier under which the callback gets registered,
|
||||
* e.g. {final: 'm'} for SGR.
|
||||
* @param callback The function to handle the escape sequence. The callback
|
||||
* is called with the numerical params, as well as the special characters
|
||||
* (e.g. "$" for DECSCPP). If the sequence has subparams the array will
|
||||
* contain subarrays with their numercial values.
|
||||
* Return true if the sequence was handled; false if
|
||||
* we should try a previous handler (set by addCsiHandler or setCsiHandler).
|
||||
* @param id Specifies the function identifier under which the callback
|
||||
* gets registered, e.g. {final: 'm'} for SGR.
|
||||
* @param callback The function to handle the sequence. The callback is
|
||||
* called with the numerical params. If the sequence has subparams the
|
||||
* array will contain subarrays with their numercial values.
|
||||
* Return true if the sequence was handled; false if we should try
|
||||
* a previous handler (set by addCsiHandler or setCsiHandler).
|
||||
* The most recently-added handler is tried first.
|
||||
* @return An IDisposable you can call to remove this handler.
|
||||
*/
|
||||
@@ -517,17 +516,18 @@ declare module 'xterm' {
|
||||
|
||||
/**
|
||||
* Adds a handler for DCS escape sequences.
|
||||
* @param id Specifies the function identifier under which the callback gets registered,
|
||||
* e.g. {intermediates: '$' final: 'q'} for DECRQSS.
|
||||
* @param callback The function to handle the escape sequence. Note that the
|
||||
* @param id Specifies the function identifier under which the callback
|
||||
* gets registered, e.g. {intermediates: '$' final: 'q'} for DECRQSS.
|
||||
* @param callback The function to handle the sequence. Note that the
|
||||
* function will only be called once if the sequence finished sucessfully.
|
||||
* There is currently no way to intercept smaller data chunks, those will be stored up
|
||||
* until the sequence is finished. Since DCS sequences are not limited by the amount
|
||||
* of data this might impose a problem for big payloads. Currently xterm.js limits
|
||||
* DCS payload to 10 MB which should give enough room for most use cases.
|
||||
* The function gets numerical parameter and the data as arguments.
|
||||
* Return true if the sequence was handled; false if
|
||||
* we should try a previous handler (set by addDcsHandler or setDcsHandler).
|
||||
* There is currently no way to intercept smaller data chunks, data chunks
|
||||
* will be stored up until the sequence is finished. Since DCS sequences
|
||||
* are not limited by the amount of data this might impose a problem for
|
||||
* big payloads. Currently xterm.js limits DCS payload to 10 MB
|
||||
* which should give enough room for most use cases.
|
||||
* The function gets the payload and numerical parameters as arguments.
|
||||
* Return true if the sequence was handled; false if we should try
|
||||
* a previous handler (set by addDcsHandler or setDcsHandler).
|
||||
* The most recently-added handler is tried first.
|
||||
* @return An IDisposable you can call to remove this handler.
|
||||
*/
|
||||
@@ -535,11 +535,12 @@ declare module 'xterm' {
|
||||
|
||||
/**
|
||||
* Adds a handler for ESC escape sequences.
|
||||
* @param id Specifies the function identifier under which the callback gets registered,
|
||||
* e.g. {intermediates: '%' final: 'G'} for default charset selection.
|
||||
* @param callback The function to handle the escape sequence.
|
||||
* Return true if the sequence was handled; false if
|
||||
* we should try a previous handler (set by addEscHandler or setEscHandler).
|
||||
* @param id Specifies the function identifier under which the callback
|
||||
* gets registered, e.g. {intermediates: '%' final: 'G'} for
|
||||
* default charset selection.
|
||||
* @param callback The function to handle the sequence.
|
||||
* Return true if the sequence was handled; false if we should try
|
||||
* a previous handler (set by addEscHandler or setEscHandler).
|
||||
* The most recently-added handler is tried first.
|
||||
* @return An IDisposable you can call to remove this handler.
|
||||
*/
|
||||
@@ -548,15 +549,17 @@ declare module 'xterm' {
|
||||
/**
|
||||
* Adds a handler for OSC escape sequences.
|
||||
* @param ident The number (first parameter) of the sequence.
|
||||
* @param callback The function to handle the escape sequence. Note that the
|
||||
* @param callback The function to handle the sequence. Note that the
|
||||
* function will only be called once if the sequence finished sucessfully.
|
||||
* There is currently no way to intercept smaller data chunks, those will be stored up
|
||||
* until the sequence is finished. Since OSC sequences are not limited by the amount
|
||||
* of data this might impose a problem for big payloads. Currently xterm.js limits
|
||||
* OSC payload to 10 MB which should give enough room for most use cases.
|
||||
* The callback is called with OSC data string. Return true if the sequence was handled;
|
||||
* false if we should try a previous handler (set by addOscHandler or
|
||||
* setOscHandler). The most recently-added handler is tried first.
|
||||
* There is currently no way to intercept smaller data chunks, data chunks
|
||||
* will be stored up until the sequence is finished. Since OSC sequences
|
||||
* are not limited by the amount of data this might impose a problem for
|
||||
* big payloads. Currently xterm.js limits OSC payload to 10 MB
|
||||
* which should give enough room for most use cases.
|
||||
* The callback is called with OSC data string.
|
||||
* Return true if the sequence was handled; false if we should try
|
||||
* a previous handler (set by addOscHandler or setOscHandler).
|
||||
* The most recently-added handler is tried first.
|
||||
* @return An IDisposable you can call to remove this handler.
|
||||
*/
|
||||
addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable;
|
||||
@@ -988,19 +991,44 @@ declare module 'xterm' {
|
||||
}
|
||||
|
||||
/**
|
||||
* Data type to register a CSI, DCS or ESC callback in the parser.
|
||||
* Data type to register a CSI, DCS or ESC callback in the parser in the form:
|
||||
* ESC I..I F
|
||||
* CSI Prefix P..P I..I F
|
||||
* DCS Prefix P..P I..I F data_bytes ST
|
||||
*
|
||||
* with these rules/restrictions:
|
||||
* - prefix can only be used with CSI and DCS
|
||||
* - only one leading prefix byte is recognized by the parser
|
||||
* before any other parameter bytes (P..P)
|
||||
* - intermediate bytes are recognized up to 2
|
||||
*
|
||||
* For custom sequences make sure to read ECMA-48 and the resources at
|
||||
* vt100.net to not clash with existing sequences or reserved address space.
|
||||
* General recommendations:
|
||||
* - use private address space (see ECMA-48)
|
||||
* - use max one intermediate byte (technically not limited by the spec,
|
||||
* in practice there are no sequences with more than one intermediate byte,
|
||||
* thus parsers might get confused with more intermediates)
|
||||
* - test against other common emulators to check whether they escape/ignore
|
||||
* the sequence correctly
|
||||
*
|
||||
* Notes: OSC command registration is handled differently (see addOscHandler)
|
||||
* APC, PM or SOS is currently not supported
|
||||
*/
|
||||
export interface IFunctionIdentifier {
|
||||
/**
|
||||
* Optional prefix byte, must be in range \x3c .. \x3f.
|
||||
* Usable in CSI and DCS.
|
||||
*/
|
||||
prefix?: string;
|
||||
/**
|
||||
* Optional intermediate bytes, must be in range \x20 .. \x2f.
|
||||
* Usable in CSI, DCS and ESC.
|
||||
*/
|
||||
intermediates?: string;
|
||||
/**
|
||||
* Final byte, must be in range \x40 .. \x7e (\x30 .. \x7e for ESC).
|
||||
* Final byte, must be in range \x40 .. \x7e for CSI and DCS,
|
||||
* \x30 .. \x7e for ESC.
|
||||
*/
|
||||
final: string;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user