typed array support for parser
This commit is contained in:
+158
-136
@@ -50,8 +50,12 @@ const testTerminal: any = {
|
||||
compare: function (value: any): void {
|
||||
chai.expect(this.calls.slice()).eql(value); // weird bug w'o slicing here
|
||||
},
|
||||
print: function (data: string, start: number, end: number): void {
|
||||
this.calls.push(['print', data.substring(start, end)]);
|
||||
print: function (data: Uint16Array, start: number, end: number): void {
|
||||
let s = '';
|
||||
for (let i = start; i < end; ++i) {
|
||||
s += String.fromCharCode(data[i]);
|
||||
}
|
||||
this.calls.push(['print', s]);
|
||||
},
|
||||
actionOSC: function (s: string): void {
|
||||
this.calls.push(['osc', s]);
|
||||
@@ -68,8 +72,12 @@ const testTerminal: any = {
|
||||
actionDCSHook: function (collect: string, params: number[], flag: string): void {
|
||||
this.calls.push(['dcs hook', collect, params, flag]);
|
||||
},
|
||||
actionDCSPrint: function (data: string, start: number, end: number): void {
|
||||
this.calls.push(['dcs put', data.substring(start, end)]);
|
||||
actionDCSPrint: function (data: Uint16Array, start: number, end: number): void {
|
||||
let s = '';
|
||||
for (let i = start; i < end; ++i) {
|
||||
s += String.fromCharCode(data[i]);
|
||||
}
|
||||
this.calls.push(['dcs put', s]);
|
||||
},
|
||||
actionDCSUnhook: function (): void {
|
||||
this.calls.push(['dcs unhook']);
|
||||
@@ -81,7 +89,7 @@ class DcsTest implements IDcsHandler {
|
||||
hook(collect: string, params: number[], flag: number): void {
|
||||
testTerminal.actionDCSHook(collect, params, String.fromCharCode(flag));
|
||||
}
|
||||
put(data: string, start: number, end: number): void {
|
||||
put(data: Uint16Array, start: number, end: number): void {
|
||||
testTerminal.actionDCSPrint(data, start, end);
|
||||
}
|
||||
unhook(): void {
|
||||
@@ -155,6 +163,14 @@ interface IRun {
|
||||
parser: TestEscapeSequenceParser;
|
||||
}
|
||||
|
||||
// translate string based parse calls into typed array based
|
||||
function parse(parser: TestEscapeSequenceParser, data: string): void {
|
||||
const container = new Uint16Array(data.length);
|
||||
for (let i = 0; i < data.length; ++i) {
|
||||
container[i] = data.charCodeAt(i);
|
||||
}
|
||||
parser.parse(container, data.length);
|
||||
}
|
||||
|
||||
describe('EscapeSequenceParser', function (): void {
|
||||
let parser: TestEscapeSequenceParser | null = null;
|
||||
@@ -205,12 +221,12 @@ describe('EscapeSequenceParser', function (): void {
|
||||
it('state GROUND execute action', function (): void {
|
||||
parser.reset();
|
||||
testTerminal.clear();
|
||||
const exes = r(0x00, 0x18);
|
||||
exes.concat(['\x19']);
|
||||
exes.concat(r(0x1c, 0x20));
|
||||
let exes = r(0x00, 0x18);
|
||||
exes = exes.concat(['\x19']);
|
||||
exes = exes.concat(r(0x1c, 0x20));
|
||||
for (let i = 0; i < exes.length; ++i) {
|
||||
parser.currentState = ParserState.GROUND;
|
||||
parser.parse(exes[i]);
|
||||
parse(parser, exes[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.GROUND);
|
||||
testTerminal.compare([['exe', exes[i]]]);
|
||||
parser.reset();
|
||||
@@ -223,7 +239,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
const printables = r(0x20, 0x7f); // NOTE: DEL excluded
|
||||
for (let i = 0; i < printables.length; ++i) {
|
||||
parser.currentState = ParserState.GROUND;
|
||||
parser.parse(printables[i]);
|
||||
parse(parser, printables[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.GROUND);
|
||||
testTerminal.compare([['print', printables[i]]]);
|
||||
parser.reset();
|
||||
@@ -245,13 +261,13 @@ describe('EscapeSequenceParser', function (): void {
|
||||
for (state in states) {
|
||||
for (let i = 0; i < exes.length; ++i) {
|
||||
parser.currentState = state;
|
||||
parser.parse(exes[i]);
|
||||
parse(parser, exes[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.GROUND);
|
||||
testTerminal.compare((state in exceptions ? exceptions[state][exes[i]] : 0) || [['exe', exes[i]]]);
|
||||
parser.reset();
|
||||
testTerminal.clear();
|
||||
}
|
||||
parser.parse('\x9c');
|
||||
parse(parser, '\x9c');
|
||||
chai.expect(parser.currentState).equal(ParserState.GROUND);
|
||||
testTerminal.compare([]);
|
||||
parser.reset();
|
||||
@@ -265,7 +281,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
parser.osc = '#';
|
||||
parser.params = [23];
|
||||
parser.collect = '#';
|
||||
parser.parse('\x1b');
|
||||
parse(parser, '\x1b');
|
||||
chai.expect(parser.currentState).equal(ParserState.ESCAPE);
|
||||
chai.expect(parser.osc).equal('');
|
||||
chai.expect(parser.params).eql([0]);
|
||||
@@ -276,12 +292,12 @@ describe('EscapeSequenceParser', function (): void {
|
||||
it('state ESCAPE execute rules', function (): void {
|
||||
parser.reset();
|
||||
testTerminal.clear();
|
||||
const exes = r(0x00, 0x18);
|
||||
exes.concat(['\x19']);
|
||||
exes.concat(r(0x1c, 0x20));
|
||||
let exes = r(0x00, 0x18);
|
||||
exes = exes.concat(['\x19']);
|
||||
exes = exes.concat(r(0x1c, 0x20));
|
||||
for (let i = 0; i < exes.length; ++i) {
|
||||
parser.currentState = ParserState.ESCAPE;
|
||||
parser.parse(exes[i]);
|
||||
parse(parser, exes[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.ESCAPE);
|
||||
testTerminal.compare([['exe', exes[i]]]);
|
||||
parser.reset();
|
||||
@@ -292,7 +308,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
parser.reset();
|
||||
testTerminal.clear();
|
||||
parser.currentState = ParserState.ESCAPE;
|
||||
parser.parse('\x7f');
|
||||
parse(parser, '\x7f');
|
||||
chai.expect(parser.currentState).equal(ParserState.ESCAPE);
|
||||
testTerminal.compare([]);
|
||||
parser.reset();
|
||||
@@ -301,13 +317,13 @@ describe('EscapeSequenceParser', function (): void {
|
||||
it('trans ESCAPE --> GROUND with ecs_dispatch action', function (): void {
|
||||
parser.reset();
|
||||
testTerminal.clear();
|
||||
const dispatches = r(0x30, 0x50);
|
||||
dispatches.concat(r(0x51, 0x58));
|
||||
dispatches.concat(['\x59', '\x5a', '\x5c']);
|
||||
dispatches.concat(r(0x60, 0x7f));
|
||||
let dispatches = r(0x30, 0x50);
|
||||
dispatches = dispatches.concat(r(0x51, 0x58));
|
||||
dispatches = dispatches.concat(['\x59', '\x5a']); // excluded \x5c
|
||||
dispatches = dispatches.concat(r(0x60, 0x7f));
|
||||
for (let i = 0; i < dispatches.length; ++i) {
|
||||
parser.currentState = ParserState.ESCAPE;
|
||||
parser.parse(dispatches[i]);
|
||||
parse(parser, dispatches[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.GROUND);
|
||||
testTerminal.compare([['esc', '', dispatches[i]]]);
|
||||
parser.reset();
|
||||
@@ -319,7 +335,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
const collect = r(0x20, 0x30);
|
||||
for (let i = 0; i < collect.length; ++i) {
|
||||
parser.currentState = ParserState.ESCAPE;
|
||||
parser.parse(collect[i]);
|
||||
parse(parser, collect[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.ESCAPE_INTERMEDIATE);
|
||||
chai.expect(parser.collect).equal(collect[i]);
|
||||
parser.reset();
|
||||
@@ -328,12 +344,12 @@ describe('EscapeSequenceParser', function (): void {
|
||||
it('state ESCAPE_INTERMEDIATE execute rules', function (): void {
|
||||
parser.reset();
|
||||
testTerminal.clear();
|
||||
const exes = r(0x00, 0x18);
|
||||
exes.concat(['\x19']);
|
||||
exes.concat(r(0x1c, 0x20));
|
||||
let exes = r(0x00, 0x18);
|
||||
exes = exes.concat(['\x19']);
|
||||
exes = exes.concat(r(0x1c, 0x20));
|
||||
for (let i = 0; i < exes.length; ++i) {
|
||||
parser.currentState = ParserState.ESCAPE_INTERMEDIATE;
|
||||
parser.parse(exes[i]);
|
||||
parse(parser, exes[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.ESCAPE_INTERMEDIATE);
|
||||
testTerminal.compare([['exe', exes[i]]]);
|
||||
parser.reset();
|
||||
@@ -344,7 +360,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
parser.reset();
|
||||
testTerminal.clear();
|
||||
parser.currentState = ParserState.ESCAPE_INTERMEDIATE;
|
||||
parser.parse('\x7f');
|
||||
parse(parser, '\x7f');
|
||||
chai.expect(parser.currentState).equal(ParserState.ESCAPE_INTERMEDIATE);
|
||||
testTerminal.compare([]);
|
||||
parser.reset();
|
||||
@@ -355,7 +371,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
const collect = r(0x20, 0x30);
|
||||
for (let i = 0; i < collect.length; ++i) {
|
||||
parser.currentState = ParserState.ESCAPE_INTERMEDIATE;
|
||||
parser.parse(collect[i]);
|
||||
parse(parser, collect[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.ESCAPE_INTERMEDIATE);
|
||||
chai.expect(parser.collect).equal(collect[i]);
|
||||
parser.reset();
|
||||
@@ -367,7 +383,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
const collect = r(0x30, 0x7f);
|
||||
for (let i = 0; i < collect.length; ++i) {
|
||||
parser.currentState = ParserState.ESCAPE_INTERMEDIATE;
|
||||
parser.parse(collect[i]);
|
||||
parse(parser, collect[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.GROUND);
|
||||
// '\x5c' --> ESC + \ (7bit ST) parser does not expose this as it already got handled
|
||||
testTerminal.compare((collect[i] === '\x5c') ? [] : [['esc', '', collect[i]]]);
|
||||
@@ -382,7 +398,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
parser.osc = '#';
|
||||
parser.params = [123];
|
||||
parser.collect = '#';
|
||||
parser.parse('[');
|
||||
parse(parser, '[');
|
||||
chai.expect(parser.currentState).equal(ParserState.CSI_ENTRY);
|
||||
chai.expect(parser.osc).equal('');
|
||||
chai.expect(parser.params).eql([0]);
|
||||
@@ -394,7 +410,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
parser.osc = '#';
|
||||
parser.params = [123];
|
||||
parser.collect = '#';
|
||||
parser.parse('\x9b');
|
||||
parse(parser, '\x9b');
|
||||
chai.expect(parser.currentState).equal(ParserState.CSI_ENTRY);
|
||||
chai.expect(parser.osc).equal('');
|
||||
chai.expect(parser.params).eql([0]);
|
||||
@@ -405,12 +421,12 @@ describe('EscapeSequenceParser', function (): void {
|
||||
it('state CSI_ENTRY execute rules', function (): void {
|
||||
parser.reset();
|
||||
testTerminal.clear();
|
||||
const exes = r(0x00, 0x18);
|
||||
exes.concat(['\x19']);
|
||||
exes.concat(r(0x1c, 0x20));
|
||||
let exes = r(0x00, 0x18);
|
||||
exes = exes.concat(['\x19']);
|
||||
exes = exes.concat(r(0x1c, 0x20));
|
||||
for (let i = 0; i < exes.length; ++i) {
|
||||
parser.currentState = ParserState.CSI_ENTRY;
|
||||
parser.parse(exes[i]);
|
||||
parse(parser, exes[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.CSI_ENTRY);
|
||||
testTerminal.compare([['exe', exes[i]]]);
|
||||
parser.reset();
|
||||
@@ -421,7 +437,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
parser.reset();
|
||||
testTerminal.clear();
|
||||
parser.currentState = ParserState.CSI_ENTRY;
|
||||
parser.parse('\x7f');
|
||||
parse(parser, '\x7f');
|
||||
chai.expect(parser.currentState).equal(ParserState.CSI_ENTRY);
|
||||
testTerminal.compare([]);
|
||||
parser.reset();
|
||||
@@ -432,7 +448,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
const dispatches = r(0x40, 0x7f);
|
||||
for (let i = 0; i < dispatches.length; ++i) {
|
||||
parser.currentState = ParserState.CSI_ENTRY;
|
||||
parser.parse(dispatches[i]);
|
||||
parse(parser, dispatches[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.GROUND);
|
||||
testTerminal.compare([['csi', '', [0], dispatches[i]]]);
|
||||
parser.reset();
|
||||
@@ -445,19 +461,19 @@ describe('EscapeSequenceParser', function (): void {
|
||||
const collect = ['\x3c', '\x3d', '\x3e', '\x3f'];
|
||||
for (let i = 0; i < params.length; ++i) {
|
||||
parser.currentState = ParserState.CSI_ENTRY;
|
||||
parser.parse(params[i]);
|
||||
parse(parser, params[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.CSI_PARAM);
|
||||
chai.expect(parser.params).eql([params[i].charCodeAt(0) - 48]);
|
||||
parser.reset();
|
||||
}
|
||||
parser.currentState = ParserState.CSI_ENTRY;
|
||||
parser.parse('\x3b');
|
||||
parse(parser, '\x3b');
|
||||
chai.expect(parser.currentState).equal(ParserState.CSI_PARAM);
|
||||
chai.expect(parser.params).eql([0, 0]);
|
||||
parser.reset();
|
||||
for (let i = 0; i < collect.length; ++i) {
|
||||
parser.currentState = ParserState.CSI_ENTRY;
|
||||
parser.parse(collect[i]);
|
||||
parse(parser, collect[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.CSI_PARAM);
|
||||
chai.expect(parser.collect).equal(collect[i]);
|
||||
parser.reset();
|
||||
@@ -466,12 +482,12 @@ describe('EscapeSequenceParser', function (): void {
|
||||
it('state CSI_PARAM execute rules', function (): void {
|
||||
parser.reset();
|
||||
testTerminal.clear();
|
||||
const exes = r(0x00, 0x18);
|
||||
exes.concat(['\x19']);
|
||||
exes.concat(r(0x1c, 0x20));
|
||||
let exes = r(0x00, 0x18);
|
||||
exes = exes.concat(['\x19']);
|
||||
exes = exes.concat(r(0x1c, 0x20));
|
||||
for (let i = 0; i < exes.length; ++i) {
|
||||
parser.currentState = ParserState.CSI_PARAM;
|
||||
parser.parse(exes[i]);
|
||||
parse(parser, exes[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.CSI_PARAM);
|
||||
testTerminal.compare([['exe', exes[i]]]);
|
||||
parser.reset();
|
||||
@@ -483,13 +499,13 @@ describe('EscapeSequenceParser', function (): void {
|
||||
const params = ['\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37', '\x38', '\x39'];
|
||||
for (let i = 0; i < params.length; ++i) {
|
||||
parser.currentState = ParserState.CSI_PARAM;
|
||||
parser.parse(params[i]);
|
||||
parse(parser, params[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.CSI_PARAM);
|
||||
chai.expect(parser.params).eql([params[i].charCodeAt(0) - 48]);
|
||||
parser.reset();
|
||||
}
|
||||
parser.currentState = ParserState.CSI_PARAM;
|
||||
parser.parse('\x3b');
|
||||
parse(parser, '\x3b');
|
||||
chai.expect(parser.currentState).equal(ParserState.CSI_PARAM);
|
||||
chai.expect(parser.params).eql([0, 0]);
|
||||
parser.reset();
|
||||
@@ -498,7 +514,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
parser.reset();
|
||||
testTerminal.clear();
|
||||
parser.currentState = ParserState.CSI_PARAM;
|
||||
parser.parse('\x7f');
|
||||
parse(parser, '\x7f');
|
||||
chai.expect(parser.currentState).equal(ParserState.CSI_PARAM);
|
||||
testTerminal.compare([]);
|
||||
parser.reset();
|
||||
@@ -510,7 +526,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
for (let i = 0; i < dispatches.length; ++i) {
|
||||
parser.currentState = ParserState.CSI_PARAM;
|
||||
parser.params = [0, 1];
|
||||
parser.parse(dispatches[i]);
|
||||
parse(parser, dispatches[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.GROUND);
|
||||
testTerminal.compare([['csi', '', [0, 1], dispatches[i]]]);
|
||||
parser.reset();
|
||||
@@ -522,7 +538,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
const collect = r(0x20, 0x30);
|
||||
for (let i = 0; i < collect.length; ++i) {
|
||||
parser.currentState = ParserState.CSI_ENTRY;
|
||||
parser.parse(collect[i]);
|
||||
parse(parser, collect[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.CSI_INTERMEDIATE);
|
||||
chai.expect(parser.collect).equal(collect[i]);
|
||||
parser.reset();
|
||||
@@ -533,7 +549,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
const collect = r(0x20, 0x30);
|
||||
for (let i = 0; i < collect.length; ++i) {
|
||||
parser.currentState = ParserState.CSI_PARAM;
|
||||
parser.parse(collect[i]);
|
||||
parse(parser, collect[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.CSI_INTERMEDIATE);
|
||||
chai.expect(parser.collect).equal(collect[i]);
|
||||
parser.reset();
|
||||
@@ -542,12 +558,12 @@ describe('EscapeSequenceParser', function (): void {
|
||||
it('state CSI_INTERMEDIATE execute rules', function (): void {
|
||||
parser.reset();
|
||||
testTerminal.clear();
|
||||
const exes = r(0x00, 0x18);
|
||||
exes.concat(['\x19']);
|
||||
exes.concat(r(0x1c, 0x20));
|
||||
let exes = r(0x00, 0x18);
|
||||
exes = exes.concat(['\x19']);
|
||||
exes = exes.concat(r(0x1c, 0x20));
|
||||
for (let i = 0; i < exes.length; ++i) {
|
||||
parser.currentState = ParserState.CSI_INTERMEDIATE;
|
||||
parser.parse(exes[i]);
|
||||
parse(parser, exes[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.CSI_INTERMEDIATE);
|
||||
testTerminal.compare([['exe', exes[i]]]);
|
||||
parser.reset();
|
||||
@@ -559,7 +575,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
const collect = r(0x20, 0x30);
|
||||
for (let i = 0; i < collect.length; ++i) {
|
||||
parser.currentState = ParserState.CSI_INTERMEDIATE;
|
||||
parser.parse(collect[i]);
|
||||
parse(parser, collect[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.CSI_INTERMEDIATE);
|
||||
chai.expect(parser.collect).equal(collect[i]);
|
||||
parser.reset();
|
||||
@@ -569,7 +585,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
parser.reset();
|
||||
testTerminal.clear();
|
||||
parser.currentState = ParserState.CSI_INTERMEDIATE;
|
||||
parser.parse('\x7f');
|
||||
parse(parser, '\x7f');
|
||||
chai.expect(parser.currentState).equal(ParserState.CSI_INTERMEDIATE);
|
||||
testTerminal.compare([]);
|
||||
parser.reset();
|
||||
@@ -581,7 +597,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
for (let i = 0; i < dispatches.length; ++i) {
|
||||
parser.currentState = ParserState.CSI_INTERMEDIATE;
|
||||
parser.params = [0, 1];
|
||||
parser.parse(dispatches[i]);
|
||||
parse(parser, dispatches[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.GROUND);
|
||||
testTerminal.compare([['csi', '', [0, 1], dispatches[i]]]);
|
||||
parser.reset();
|
||||
@@ -591,7 +607,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
it('trans CSI_ENTRY --> CSI_IGNORE', function (): void {
|
||||
parser.reset();
|
||||
parser.currentState = ParserState.CSI_ENTRY;
|
||||
parser.parse('\x3a');
|
||||
parse(parser, '\x3a');
|
||||
chai.expect(parser.currentState).equal(ParserState.CSI_IGNORE);
|
||||
parser.reset();
|
||||
});
|
||||
@@ -600,7 +616,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
const chars = ['\x3a', '\x3c', '\x3d', '\x3e', '\x3f'];
|
||||
for (let i = 0; i < chars.length; ++i) {
|
||||
parser.currentState = ParserState.CSI_PARAM;
|
||||
parser.parse('\x3b' + chars[i]);
|
||||
parse(parser, '\x3b' + chars[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.CSI_IGNORE);
|
||||
chai.expect(parser.params).eql([0, 0]);
|
||||
parser.reset();
|
||||
@@ -611,7 +627,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
const chars = r(0x30, 0x40);
|
||||
for (let i = 0; i < chars.length; ++i) {
|
||||
parser.currentState = ParserState.CSI_INTERMEDIATE;
|
||||
parser.parse(chars[i]);
|
||||
parse(parser, chars[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.CSI_IGNORE);
|
||||
chai.expect(parser.params).eql([0]);
|
||||
parser.reset();
|
||||
@@ -620,12 +636,12 @@ describe('EscapeSequenceParser', function (): void {
|
||||
it('state CSI_IGNORE execute rules', function (): void {
|
||||
parser.reset();
|
||||
testTerminal.clear();
|
||||
const exes = r(0x00, 0x18);
|
||||
exes.concat(['\x19']);
|
||||
exes.concat(r(0x1c, 0x20));
|
||||
let exes = r(0x00, 0x18);
|
||||
exes = exes.concat(['\x19']);
|
||||
exes = exes.concat(r(0x1c, 0x20));
|
||||
for (let i = 0; i < exes.length; ++i) {
|
||||
parser.currentState = ParserState.CSI_IGNORE;
|
||||
parser.parse(exes[i]);
|
||||
parse(parser, exes[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.CSI_IGNORE);
|
||||
testTerminal.compare([['exe', exes[i]]]);
|
||||
parser.reset();
|
||||
@@ -635,11 +651,11 @@ describe('EscapeSequenceParser', function (): void {
|
||||
it('state CSI_IGNORE ignore', function (): void {
|
||||
parser.reset();
|
||||
testTerminal.clear();
|
||||
const ignored = r(0x20, 0x40);
|
||||
ignored.concat(['\x7f']);
|
||||
let ignored = r(0x20, 0x40);
|
||||
ignored = ignored.concat(['\x7f']);
|
||||
for (let i = 0; i < ignored.length; ++i) {
|
||||
parser.currentState = ParserState.CSI_IGNORE;
|
||||
parser.parse(ignored[i]);
|
||||
parse(parser, ignored[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.CSI_IGNORE);
|
||||
testTerminal.compare([]);
|
||||
parser.reset();
|
||||
@@ -652,7 +668,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
for (let i = 0; i < dispatches.length; ++i) {
|
||||
parser.currentState = ParserState.CSI_IGNORE;
|
||||
parser.params = [0, 1];
|
||||
parser.parse(dispatches[i]);
|
||||
parse(parser, dispatches[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.GROUND);
|
||||
testTerminal.compare([]);
|
||||
parser.reset();
|
||||
@@ -664,7 +680,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
// C0
|
||||
let initializers = ['\x58', '\x5e', '\x5f'];
|
||||
for (let i = 0; i < initializers.length; ++i) {
|
||||
parser.parse('\x1b' + initializers[i]);
|
||||
parse(parser, '\x1b' + initializers[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.SOS_PM_APC_STRING);
|
||||
parser.reset();
|
||||
}
|
||||
@@ -673,7 +689,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
parser.currentState = state;
|
||||
initializers = ['\x98', '\x9e', '\x9f'];
|
||||
for (let i = 0; i < initializers.length; ++i) {
|
||||
parser.parse(initializers[i]);
|
||||
parse(parser, initializers[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.SOS_PM_APC_STRING);
|
||||
parser.reset();
|
||||
}
|
||||
@@ -681,13 +697,13 @@ describe('EscapeSequenceParser', function (): void {
|
||||
});
|
||||
it('state SOS_PM_APC_STRING ignore rules', function (): void {
|
||||
parser.reset();
|
||||
const ignored = r(0x00, 0x18);
|
||||
ignored.concat(['\x19']);
|
||||
ignored.concat(r(0x1c, 0x20));
|
||||
ignored.concat(r(0x20, 0x80));
|
||||
let ignored = r(0x00, 0x18);
|
||||
ignored = ignored.concat(['\x19']);
|
||||
ignored = ignored.concat(r(0x1c, 0x20));
|
||||
ignored = ignored.concat(r(0x20, 0x80));
|
||||
for (let i = 0; i < ignored.length; ++i) {
|
||||
parser.currentState = ParserState.SOS_PM_APC_STRING;
|
||||
parser.parse(ignored[i]);
|
||||
parse(parser, ignored[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.SOS_PM_APC_STRING);
|
||||
parser.reset();
|
||||
}
|
||||
@@ -695,13 +711,13 @@ describe('EscapeSequenceParser', function (): void {
|
||||
it('trans ANYWHERE/ESCAPE --> OSC_STRING', function (): void {
|
||||
parser.reset();
|
||||
// C0
|
||||
parser.parse('\x1b]');
|
||||
parse(parser, '\x1b]');
|
||||
chai.expect(parser.currentState).equal(ParserState.OSC_STRING);
|
||||
parser.reset();
|
||||
// C1
|
||||
for (state in states) {
|
||||
parser.currentState = state;
|
||||
parser.parse('\x9d');
|
||||
parse(parser, '\x9d');
|
||||
chai.expect(parser.currentState).equal(ParserState.OSC_STRING);
|
||||
parser.reset();
|
||||
}
|
||||
@@ -714,7 +730,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
'\x12', '\x13', '\x14', '\x15', '\x16', '\x17', '\x19', '\x1c', '\x1d', '\x1e', '\x1f'];
|
||||
for (let i = 0; i < ignored.length; ++i) {
|
||||
parser.currentState = ParserState.OSC_STRING;
|
||||
parser.parse(ignored[i]);
|
||||
parse(parser, ignored[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.OSC_STRING);
|
||||
chai.expect(parser.osc).equal('');
|
||||
parser.reset();
|
||||
@@ -725,7 +741,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
const puts = r(0x20, 0x80);
|
||||
for (let i = 0; i < puts.length; ++i) {
|
||||
parser.currentState = ParserState.OSC_STRING;
|
||||
parser.parse(puts[i]);
|
||||
parse(parser, puts[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.OSC_STRING);
|
||||
chai.expect(parser.osc).equal(puts[i]);
|
||||
parser.reset();
|
||||
@@ -734,13 +750,13 @@ describe('EscapeSequenceParser', function (): void {
|
||||
it('state DCS_ENTRY', function (): void {
|
||||
parser.reset();
|
||||
// C0
|
||||
parser.parse('\x1bP');
|
||||
parse(parser, '\x1bP');
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_ENTRY);
|
||||
parser.reset();
|
||||
// C1
|
||||
for (state in states) {
|
||||
parser.currentState = state;
|
||||
parser.parse('\x90');
|
||||
parse(parser, '\x90');
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_ENTRY);
|
||||
parser.reset();
|
||||
}
|
||||
@@ -753,7 +769,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
'\x12', '\x13', '\x14', '\x15', '\x16', '\x17', '\x19', '\x1c', '\x1d', '\x1e', '\x1f', '\x7f'];
|
||||
for (let i = 0; i < ignored.length; ++i) {
|
||||
parser.currentState = ParserState.DCS_ENTRY;
|
||||
parser.parse(ignored[i]);
|
||||
parse(parser, ignored[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_ENTRY);
|
||||
parser.reset();
|
||||
}
|
||||
@@ -764,19 +780,19 @@ describe('EscapeSequenceParser', function (): void {
|
||||
const collect = ['\x3c', '\x3d', '\x3e', '\x3f'];
|
||||
for (let i = 0; i < params.length; ++i) {
|
||||
parser.currentState = ParserState.DCS_ENTRY;
|
||||
parser.parse(params[i]);
|
||||
parse(parser, params[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_PARAM);
|
||||
chai.expect(parser.params).eql([params[i].charCodeAt(0) - 48]);
|
||||
parser.reset();
|
||||
}
|
||||
parser.currentState = ParserState.DCS_ENTRY;
|
||||
parser.parse('\x3b');
|
||||
parse(parser, '\x3b');
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_PARAM);
|
||||
chai.expect(parser.params).eql([0, 0]);
|
||||
parser.reset();
|
||||
for (let i = 0; i < collect.length; ++i) {
|
||||
parser.currentState = ParserState.DCS_ENTRY;
|
||||
parser.parse(collect[i]);
|
||||
parse(parser, collect[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_PARAM);
|
||||
chai.expect(parser.collect).equal(collect[i]);
|
||||
parser.reset();
|
||||
@@ -790,7 +806,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
'\x12', '\x13', '\x14', '\x15', '\x16', '\x17', '\x19', '\x1c', '\x1d', '\x1e', '\x1f', '\x7f'];
|
||||
for (let i = 0; i < ignored.length; ++i) {
|
||||
parser.currentState = ParserState.DCS_PARAM;
|
||||
parser.parse(ignored[i]);
|
||||
parse(parser, ignored[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_PARAM);
|
||||
parser.reset();
|
||||
}
|
||||
@@ -800,13 +816,13 @@ describe('EscapeSequenceParser', function (): void {
|
||||
const params = ['\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37', '\x38', '\x39'];
|
||||
for (let i = 0; i < params.length; ++i) {
|
||||
parser.currentState = ParserState.DCS_PARAM;
|
||||
parser.parse(params[i]);
|
||||
parse(parser, params[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_PARAM);
|
||||
chai.expect(parser.params).eql([params[i].charCodeAt(0) - 48]);
|
||||
parser.reset();
|
||||
}
|
||||
parser.currentState = ParserState.DCS_PARAM;
|
||||
parser.parse('\x3b');
|
||||
parse(parser, '\x3b');
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_PARAM);
|
||||
chai.expect(parser.params).eql([0, 0]);
|
||||
parser.reset();
|
||||
@@ -814,7 +830,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
it('trans DCS_ENTRY --> DCS_IGNORE', function (): void {
|
||||
parser.reset();
|
||||
parser.currentState = ParserState.DCS_ENTRY;
|
||||
parser.parse('\x3a');
|
||||
parse(parser, '\x3a');
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_IGNORE);
|
||||
parser.reset();
|
||||
});
|
||||
@@ -823,7 +839,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
const chars = ['\x3a', '\x3c', '\x3d', '\x3e', '\x3f'];
|
||||
for (let i = 0; i < chars.length; ++i) {
|
||||
parser.currentState = ParserState.DCS_PARAM;
|
||||
parser.parse('\x3b' + chars[i]);
|
||||
parse(parser, '\x3b' + chars[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_IGNORE);
|
||||
chai.expect(parser.params).eql([0, 0]);
|
||||
parser.reset();
|
||||
@@ -834,21 +850,21 @@ describe('EscapeSequenceParser', function (): void {
|
||||
const chars = r(0x30, 0x40);
|
||||
for (let i = 0; i < chars.length; ++i) {
|
||||
parser.currentState = ParserState.DCS_INTERMEDIATE;
|
||||
parser.parse(chars[i]);
|
||||
parse(parser, chars[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_IGNORE);
|
||||
parser.reset();
|
||||
}
|
||||
});
|
||||
it('state DCS_IGNORE ignore rules', function (): void {
|
||||
parser.reset();
|
||||
const ignored = [
|
||||
let ignored = [
|
||||
'\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', '\x08',
|
||||
'\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f', '\x10', '\x11',
|
||||
'\x12', '\x13', '\x14', '\x15', '\x16', '\x17', '\x19', '\x1c', '\x1d', '\x1e', '\x1f', '\x7f'];
|
||||
ignored.concat(r(0x20, 0x80));
|
||||
ignored = ignored.concat(r(0x20, 0x80));
|
||||
for (let i = 0; i < ignored.length; ++i) {
|
||||
parser.currentState = ParserState.DCS_IGNORE;
|
||||
parser.parse(ignored[i]);
|
||||
parse(parser, ignored[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_IGNORE);
|
||||
parser.reset();
|
||||
}
|
||||
@@ -858,7 +874,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
const collect = r(0x20, 0x30);
|
||||
for (let i = 0; i < collect.length; ++i) {
|
||||
parser.currentState = ParserState.DCS_ENTRY;
|
||||
parser.parse(collect[i]);
|
||||
parse(parser, collect[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_INTERMEDIATE);
|
||||
chai.expect(parser.collect).equal(collect[i]);
|
||||
parser.reset();
|
||||
@@ -869,7 +885,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
const collect = r(0x20, 0x30);
|
||||
for (let i = 0; i < collect.length; ++i) {
|
||||
parser.currentState = ParserState.DCS_PARAM;
|
||||
parser.parse(collect[i]);
|
||||
parse(parser, collect[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_INTERMEDIATE);
|
||||
chai.expect(parser.collect).equal(collect[i]);
|
||||
parser.reset();
|
||||
@@ -883,7 +899,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
'\x12', '\x13', '\x14', '\x15', '\x16', '\x17', '\x19', '\x1c', '\x1d', '\x1e', '\x1f', '\x7f'];
|
||||
for (let i = 0; i < ignored.length; ++i) {
|
||||
parser.currentState = ParserState.DCS_INTERMEDIATE;
|
||||
parser.parse(ignored[i]);
|
||||
parse(parser, ignored[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_INTERMEDIATE);
|
||||
parser.reset();
|
||||
}
|
||||
@@ -893,7 +909,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
const collect = r(0x20, 0x30);
|
||||
for (let i = 0; i < collect.length; ++i) {
|
||||
parser.currentState = ParserState.DCS_INTERMEDIATE;
|
||||
parser.parse(collect[i]);
|
||||
parse(parser, collect[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_INTERMEDIATE);
|
||||
chai.expect(parser.collect).equal(collect[i]);
|
||||
parser.reset();
|
||||
@@ -904,7 +920,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
const chars = r(0x30, 0x40);
|
||||
for (let i = 0; i < chars.length; ++i) {
|
||||
parser.currentState = ParserState.DCS_INTERMEDIATE;
|
||||
parser.parse('\x20' + chars[i]);
|
||||
parse(parser, '\x20' + chars[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_IGNORE);
|
||||
chai.expect(parser.collect).equal('\x20');
|
||||
parser.reset();
|
||||
@@ -916,7 +932,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
const collect = r(0x40, 0x7f);
|
||||
for (let i = 0; i < collect.length; ++i) {
|
||||
parser.currentState = ParserState.DCS_ENTRY;
|
||||
parser.parse(collect[i]);
|
||||
parse(parser, collect[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_PASSTHROUGH);
|
||||
testTerminal.compare([['dcs hook', '', [0], collect[i]]]);
|
||||
parser.reset();
|
||||
@@ -929,7 +945,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
const collect = r(0x40, 0x7f);
|
||||
for (let i = 0; i < collect.length; ++i) {
|
||||
parser.currentState = ParserState.DCS_PARAM;
|
||||
parser.parse(collect[i]);
|
||||
parse(parser, collect[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_PASSTHROUGH);
|
||||
testTerminal.compare([['dcs hook', '', [0], collect[i]]]);
|
||||
parser.reset();
|
||||
@@ -942,7 +958,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
const collect = r(0x40, 0x7f);
|
||||
for (let i = 0; i < collect.length; ++i) {
|
||||
parser.currentState = ParserState.DCS_INTERMEDIATE;
|
||||
parser.parse(collect[i]);
|
||||
parse(parser, collect[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_PASSTHROUGH);
|
||||
testTerminal.compare([['dcs hook', '', [0], collect[i]]]);
|
||||
parser.reset();
|
||||
@@ -952,14 +968,14 @@ describe('EscapeSequenceParser', function (): void {
|
||||
it('state DCS_PASSTHROUGH put action', function (): void {
|
||||
parser.reset();
|
||||
testTerminal.clear();
|
||||
const puts = r(0x00, 0x18);
|
||||
puts.concat(['\x19']);
|
||||
puts.concat(r(0x1c, 0x20));
|
||||
puts.concat(r(0x20, 0x7f));
|
||||
let puts = r(0x00, 0x18);
|
||||
puts = puts.concat(['\x19']);
|
||||
puts = puts.concat(r(0x1c, 0x20));
|
||||
puts = puts.concat(r(0x20, 0x7f));
|
||||
for (let i = 0; i < puts.length; ++i) {
|
||||
parser.currentState = ParserState.DCS_PASSTHROUGH;
|
||||
parser.mockActiveDcsHandler();
|
||||
parser.parse(puts[i]);
|
||||
parse(parser, puts[i]);
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_PASSTHROUGH);
|
||||
testTerminal.compare([['dcs put', puts[i]]]);
|
||||
parser.reset();
|
||||
@@ -970,7 +986,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
parser.reset();
|
||||
testTerminal.clear();
|
||||
parser.currentState = ParserState.DCS_PASSTHROUGH;
|
||||
parser.parse('\x7f');
|
||||
parse(parser, '\x7f');
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_PASSTHROUGH);
|
||||
testTerminal.compare([]);
|
||||
parser.reset();
|
||||
@@ -989,7 +1005,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
parser.reset();
|
||||
testTerminal.clear();
|
||||
}
|
||||
parser.parse(s);
|
||||
parse(parser, s);
|
||||
testTerminal.compare(value);
|
||||
};
|
||||
});
|
||||
@@ -1067,7 +1083,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
parser.reset();
|
||||
testTerminal.clear();
|
||||
parser.currentState = ParserState.CSI_IGNORE;
|
||||
parser.parse('€öäü');
|
||||
parse(parser, '€öäü');
|
||||
chai.expect(parser.currentState).equal(ParserState.CSI_IGNORE);
|
||||
testTerminal.compare([]);
|
||||
parser.reset();
|
||||
@@ -1077,7 +1093,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
parser.reset();
|
||||
testTerminal.clear();
|
||||
parser.currentState = ParserState.DCS_IGNORE;
|
||||
parser.parse('€öäü');
|
||||
parse(parser, '€öäü');
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_IGNORE);
|
||||
testTerminal.compare([]);
|
||||
parser.reset();
|
||||
@@ -1087,7 +1103,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
parser.reset();
|
||||
testTerminal.clear();
|
||||
parser.currentState = ParserState.DCS_PASSTHROUGH;
|
||||
parser.parse('\x901;2;3+$a€öäü');
|
||||
parse(parser, '\x901;2;3+$a€öäü');
|
||||
chai.expect(parser.currentState).equal(ParserState.DCS_PASSTHROUGH);
|
||||
testTerminal.compare([['dcs hook', '+$', [1, 2, 3], 'a'], ['dcs put', '€öäü']]);
|
||||
parser.reset();
|
||||
@@ -1097,7 +1113,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
parser.reset();
|
||||
testTerminal.clear();
|
||||
parser.currentState = ParserState.GROUND;
|
||||
parser.parse('\x9c');
|
||||
parse(parser, '\x9c');
|
||||
chai.expect(parser.currentState).equal(ParserState.GROUND);
|
||||
testTerminal.compare([]);
|
||||
parser.reset();
|
||||
@@ -1127,15 +1143,17 @@ describe('EscapeSequenceParser', function (): void {
|
||||
clearAccu();
|
||||
});
|
||||
it('print handler', function (): void {
|
||||
parser2.setPrintHandler(function (data: string, start: number, end: number): void {
|
||||
print += data.substring(start, end);
|
||||
parser2.setPrintHandler(function (data: Uint16Array, start: number, end: number): void {
|
||||
for (let i = start; i < end; ++i) {
|
||||
print += String.fromCharCode(data[i]);
|
||||
}
|
||||
});
|
||||
parser2.parse(INPUT);
|
||||
parse(parser2, INPUT);
|
||||
chai.expect(print).equal('hello world!$>');
|
||||
parser2.clearPrintHandler();
|
||||
parser2.clearPrintHandler(); // should not throw
|
||||
clearAccu();
|
||||
parser2.parse(INPUT);
|
||||
parse(parser2, INPUT);
|
||||
chai.expect(print).equal('');
|
||||
});
|
||||
it('ESC handler', function (): void {
|
||||
@@ -1145,28 +1163,28 @@ describe('EscapeSequenceParser', function (): void {
|
||||
parser2.setEscHandler('E', function (): void {
|
||||
esc.push('E');
|
||||
});
|
||||
parser2.parse(INPUT);
|
||||
parse(parser2, INPUT);
|
||||
chai.expect(esc).eql(['%G', 'E']);
|
||||
parser2.clearEscHandler('%G');
|
||||
parser2.clearEscHandler('%G'); // should not throw
|
||||
clearAccu();
|
||||
parser2.parse(INPUT);
|
||||
parse(parser2, INPUT);
|
||||
chai.expect(esc).eql(['E']);
|
||||
parser2.clearEscHandler('E');
|
||||
clearAccu();
|
||||
parser2.parse(INPUT);
|
||||
parse(parser2, INPUT);
|
||||
chai.expect(esc).eql([]);
|
||||
});
|
||||
it('CSI handler', function (): void {
|
||||
parser2.setCsiHandler('m', function (params: number[], collect: string): void {
|
||||
csi.push(['m', params, collect]);
|
||||
});
|
||||
parser2.parse(INPUT);
|
||||
parse(parser2, INPUT);
|
||||
chai.expect(csi).eql([['m', [1, 31], ''], ['m', [0], '']]);
|
||||
parser2.clearCsiHandler('m');
|
||||
parser2.clearCsiHandler('m'); // should not throw
|
||||
clearAccu();
|
||||
parser2.parse(INPUT);
|
||||
parse(parser2, INPUT);
|
||||
chai.expect(csi).eql([]);
|
||||
});
|
||||
it('EXECUTE handler', function (): void {
|
||||
@@ -1176,24 +1194,24 @@ describe('EscapeSequenceParser', function (): void {
|
||||
parser2.setExecuteHandler('\r', function (): void {
|
||||
exe.push('\r');
|
||||
});
|
||||
parser2.parse(INPUT);
|
||||
parse(parser2, INPUT);
|
||||
chai.expect(exe).eql(['\r', '\n']);
|
||||
parser2.clearExecuteHandler('\r');
|
||||
parser2.clearExecuteHandler('\r'); // should not throw
|
||||
clearAccu();
|
||||
parser2.parse(INPUT);
|
||||
parse(parser2, INPUT);
|
||||
chai.expect(exe).eql(['\n']);
|
||||
});
|
||||
it('OSC handler', function (): void {
|
||||
parser2.setOscHandler(1, function (data: string): void {
|
||||
osc.push([1, data]);
|
||||
});
|
||||
parser2.parse(INPUT);
|
||||
parse(parser2, INPUT);
|
||||
chai.expect(osc).eql([[1, 'foo=bar']]);
|
||||
parser2.clearOscHandler(1);
|
||||
parser2.clearOscHandler(1); // should not throw
|
||||
clearAccu();
|
||||
parser2.parse(INPUT);
|
||||
parse(parser2, INPUT);
|
||||
chai.expect(osc).eql([]);
|
||||
});
|
||||
it('DCS handler', function (): void {
|
||||
@@ -1201,15 +1219,19 @@ describe('EscapeSequenceParser', function (): void {
|
||||
hook: function (collect: string, params: number[], flag: number): void {
|
||||
dcs.push(['hook', collect, params, flag]);
|
||||
},
|
||||
put: function (data: string, start: number, end: number): void {
|
||||
dcs.push(['put', data.substring(start, end)]);
|
||||
put: function (data: Uint16Array, start: number, end: number): void {
|
||||
let s = '';
|
||||
for (let i = start; i < end; ++i) {
|
||||
s += String.fromCharCode(data[i]);
|
||||
}
|
||||
dcs.push(['put', s]);
|
||||
},
|
||||
unhook: function (): void {
|
||||
dcs.push(['unhook']);
|
||||
}
|
||||
});
|
||||
parser2.parse('\x1bP1;2;3+pabc');
|
||||
parser2.parse(';de\x9c');
|
||||
parse(parser2, '\x1bP1;2;3+pabc');
|
||||
parse(parser2, ';de\x9c');
|
||||
chai.expect(dcs).eql([
|
||||
['hook', '+', [1, 2, 3], 'p'.charCodeAt(0)],
|
||||
['put', 'abc'], ['put', ';de'],
|
||||
@@ -1218,8 +1240,8 @@ describe('EscapeSequenceParser', function (): void {
|
||||
parser2.clearDcsHandler('+p');
|
||||
parser2.clearDcsHandler('+p'); // should not throw
|
||||
clearAccu();
|
||||
parser2.parse('\x1bP1;2;3+pabc');
|
||||
parser2.parse(';de\x9c');
|
||||
parse(parser2, '\x1bP1;2;3+pabc');
|
||||
parse(parser2, ';de\x9c');
|
||||
chai.expect(dcs).eql([]);
|
||||
});
|
||||
it('ERROR handler', function (): void {
|
||||
@@ -1228,7 +1250,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
errorState = state;
|
||||
return state;
|
||||
});
|
||||
parser2.parse('\x1b[1;2;€;3m'); // faulty escape sequence
|
||||
parse(parser2, '\x1b[1;2;€;3m'); // faulty escape sequence
|
||||
chai.expect(errorState).eql({
|
||||
position: 6,
|
||||
code: '€'.charCodeAt(0),
|
||||
@@ -1243,7 +1265,7 @@ describe('EscapeSequenceParser', function (): void {
|
||||
parser2.clearErrorHandler();
|
||||
parser2.clearErrorHandler(); // should not throw
|
||||
errorState = null;
|
||||
parser2.parse('\x1b[1;2;a;3m');
|
||||
parse(parser2, '\x1b[1;2;a;3m');
|
||||
chai.expect(errorState).eql(null);
|
||||
});
|
||||
});
|
||||
|
||||
+12
-12
@@ -125,6 +125,7 @@ export const VT500_TRANSITION_TABLE = (function (): TransitionTable {
|
||||
table.addMany(PRINTABLES, ParserState.SOS_PM_APC_STRING, ParserAction.IGNORE, ParserState.SOS_PM_APC_STRING);
|
||||
table.addMany(EXECUTABLES, ParserState.SOS_PM_APC_STRING, ParserAction.IGNORE, ParserState.SOS_PM_APC_STRING);
|
||||
table.add(0x9c, ParserState.SOS_PM_APC_STRING, ParserAction.IGNORE, ParserState.GROUND);
|
||||
table.add(0x7f, ParserState.SOS_PM_APC_STRING, ParserAction.IGNORE, ParserState.SOS_PM_APC_STRING);
|
||||
// csi entries
|
||||
table.add(0x5b, ParserState.ESCAPE, ParserAction.CLEAR, ParserState.CSI_ENTRY);
|
||||
table.addMany(r(0x40, 0x7f), ParserState.CSI_ENTRY, ParserAction.CSI_DISPATCH, ParserState.GROUND);
|
||||
@@ -192,7 +193,7 @@ export const VT500_TRANSITION_TABLE = (function (): TransitionTable {
|
||||
*/
|
||||
class DcsDummy implements IDcsHandler {
|
||||
hook(collect: string, params: number[], flag: number): void { }
|
||||
put(data: string, start: number, end: number): void { }
|
||||
put(data: Uint16Array, start: number, end: number): void { }
|
||||
unhook(): void { }
|
||||
}
|
||||
|
||||
@@ -218,7 +219,7 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
protected _collect: string;
|
||||
|
||||
// handler lookup containers
|
||||
protected _printHandler: (data: string, start: number, end: number) => void;
|
||||
protected _printHandler: (data: Uint16Array, start: number, end: number) => void;
|
||||
protected _executeHandlers: any;
|
||||
protected _csiHandlers: any;
|
||||
protected _escHandlers: any;
|
||||
@@ -228,7 +229,7 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
protected _errorHandler: (state: IParsingState) => IParsingState;
|
||||
|
||||
// fallback handlers
|
||||
protected _printHandlerFb: (data: string, start: number, end: number) => void;
|
||||
protected _printHandlerFb: (data: Uint16Array, start: number, end: number) => void;
|
||||
protected _executeHandlerFb: (code: number) => void;
|
||||
protected _csiHandlerFb: (collect: string, params: number[], flag: number) => void;
|
||||
protected _escHandlerFb: (collect: string, flag: number) => void;
|
||||
@@ -284,7 +285,7 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
this._errorHandler = null;
|
||||
}
|
||||
|
||||
setPrintHandler(callback: (data: string, start: number, end: number) => void): void {
|
||||
setPrintHandler(callback: (data: Uint16Array, start: number, end: number) => void): void {
|
||||
this._printHandler = callback;
|
||||
}
|
||||
clearPrintHandler(): void {
|
||||
@@ -356,7 +357,7 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
this._activeDcsHandler = null;
|
||||
}
|
||||
|
||||
parse(data: string): void {
|
||||
parse(data: Uint16Array, length: number): void {
|
||||
let code = 0;
|
||||
let transition = 0;
|
||||
let error = false;
|
||||
@@ -371,15 +372,14 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
let callback: Function | null = null;
|
||||
|
||||
// process input string
|
||||
const l = data.length;
|
||||
for (let i = 0; i < l; ++i) {
|
||||
code = data.charCodeAt(i);
|
||||
for (let i = 0; i < length; ++i) {
|
||||
code = data[i];
|
||||
|
||||
// shortcut for most chars (print action)
|
||||
if (currentState === ParserState.GROUND && code > 0x1f && code < 0x80) {
|
||||
print = (~print) ? print : i;
|
||||
do i++;
|
||||
while (i < l && data.charCodeAt(i) > 0x1f && data.charCodeAt(i) < 0x80);
|
||||
while (i < length && data[i] > 0x1f && data[i] < 0x80);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
@@ -517,7 +517,7 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
osc = '';
|
||||
break;
|
||||
case ParserAction.OSC_PUT:
|
||||
osc += data.charAt(i);
|
||||
osc += String.fromCharCode(code);
|
||||
break;
|
||||
case ParserAction.OSC_END:
|
||||
if (osc && code !== 0x18 && code !== 0x1a) {
|
||||
@@ -549,9 +549,9 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
||||
|
||||
// push leftover pushable buffers to terminal
|
||||
if (currentState === ParserState.GROUND && ~print) {
|
||||
this._printHandler(data, print, data.length);
|
||||
this._printHandler(data, print, length);
|
||||
} else if (currentState === ParserState.DCS_PASSTHROUGH && ~dcs && dcsHandler) {
|
||||
dcsHandler.put(data, dcs, data.length);
|
||||
dcsHandler.put(data, dcs, length);
|
||||
}
|
||||
|
||||
// save non pushable buffers
|
||||
|
||||
@@ -503,7 +503,9 @@ describe('InputHandler', () => {
|
||||
it('should not cause an infinite loop (regression test)', () => {
|
||||
const term = new Terminal();
|
||||
const inputHandler = new InputHandler(term);
|
||||
inputHandler.print(String.fromCharCode(0x200B), 0, 1);
|
||||
const container = new Uint16Array(10);
|
||||
container[0] = 0x200B;
|
||||
inputHandler.print(container, 0, 1);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
+59
-33
@@ -29,18 +29,26 @@ const GLEVEL: {[key: string]: number} = {'(': 0, ')': 1, '*': 2, '+': 3, '-': 1,
|
||||
* Request Terminfo String
|
||||
* not supported
|
||||
*/
|
||||
class RequestTerminfo implements IDcsHandler {
|
||||
private _data: string;
|
||||
class RequestTerminfo implements IDcsHandler {
|
||||
private _data: Uint16Array = new Uint16Array(0);
|
||||
constructor(private _terminal: any) { }
|
||||
hook(collect: string, params: number[], flag: number): void {
|
||||
this._data = '';
|
||||
}
|
||||
put(data: string, start: number, end: number): void {
|
||||
this._data += data.substring(start, end);
|
||||
put(data: Uint16Array, start: number, end: number): void {
|
||||
const tmp = new Uint16Array(this._data.length + end - start);
|
||||
tmp.set(this._data);
|
||||
tmp.set(data.subarray(start, end), this._data.length);
|
||||
this._data = data;
|
||||
}
|
||||
unhook(): void {
|
||||
let data = '';
|
||||
for (let i = 0; i < this._data.length; ++i) {
|
||||
data += String.fromCharCode(this._data[i]);
|
||||
}
|
||||
this._data = new Uint16Array(0); // dont hold memory longer than needed
|
||||
// invalid: DCS 0 + r Pt ST
|
||||
this._terminal.handler(`${C0.ESC}P0+r${this._data}${C0.ESC}\\`);
|
||||
this._terminal.handler(`${C0.ESC}P0+r${data}${C0.ESC}\\`);
|
||||
this._data = new Uint16Array(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,21 +59,27 @@ class RequestTerminfo implements IDcsHandler {
|
||||
* Response: DECRPSS (https://vt100.net/docs/vt510-rm/DECRPSS.html)
|
||||
*/
|
||||
class DECRQSS implements IDcsHandler {
|
||||
private _data: string;
|
||||
private _data: Uint16Array = new Uint16Array(0);
|
||||
|
||||
constructor(private _terminal: any) { }
|
||||
|
||||
hook(collect: string, params: number[], flag: number): void {
|
||||
// reset data
|
||||
this._data = '';
|
||||
}
|
||||
|
||||
put(data: string, start: number, end: number): void {
|
||||
this._data += data.substring(start, end);
|
||||
put(data: Uint16Array, start: number, end: number): void {
|
||||
const tmp = new Uint16Array(this._data.length + end - start);
|
||||
tmp.set(this._data);
|
||||
tmp.set(data.subarray(start, end), this._data.length);
|
||||
this._data = data;
|
||||
}
|
||||
|
||||
unhook(): void {
|
||||
switch (this._data) {
|
||||
let data = '';
|
||||
for (let i = 0; i < this._data.length; ++i) {
|
||||
data += String.fromCharCode(this._data[i]);
|
||||
}
|
||||
this._data = new Uint16Array(0); // dont hold memory longer than needed
|
||||
switch (data) {
|
||||
// valid: DCS 1 $ r Pt ST (xterm)
|
||||
case '"q': // DECSCA
|
||||
return this._terminal.handler(`${C0.ESC}P1$r0"q${C0.ESC}\\`);
|
||||
@@ -85,8 +99,8 @@ class DECRQSS implements IDcsHandler {
|
||||
return this._terminal.handler(`${C0.ESC}P1$r${style} q${C0.ESC}\\`);
|
||||
default:
|
||||
// invalid: DCS 0 $ r Pt ST (xterm)
|
||||
this._terminal.error('Unknown DCS $q %s', this._data);
|
||||
this._terminal.handler(`${C0.ESC}P0$r${this._data}${C0.ESC}\\`);
|
||||
this._terminal.error('Unknown DCS $q %s', data);
|
||||
this._terminal.handler(`${C0.ESC}P0$r${data}${C0.ESC}\\`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -97,11 +111,11 @@ class DECRQSS implements IDcsHandler {
|
||||
* not supported
|
||||
*/
|
||||
|
||||
/**
|
||||
* DCS + p Pt ST (xterm)
|
||||
* Set Terminfo Data
|
||||
* not supported
|
||||
*/
|
||||
/**
|
||||
* DCS + p Pt ST (xterm)
|
||||
* Set Terminfo Data
|
||||
* not supported
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@@ -114,6 +128,7 @@ class DECRQSS implements IDcsHandler {
|
||||
*/
|
||||
export class InputHandler extends Disposable implements IInputHandler {
|
||||
private _surrogateFirst: string;
|
||||
private _parseBuffer: Uint16Array = new Uint16Array(4096);
|
||||
|
||||
constructor(
|
||||
protected _terminal: IInputHandlingTerminal,
|
||||
@@ -316,7 +331,13 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
this._surrogateFirst = '';
|
||||
}
|
||||
|
||||
this._parser.parse(data);
|
||||
if (this._parseBuffer.length < data.length) {
|
||||
this._parseBuffer = new Uint16Array(data.length);
|
||||
}
|
||||
for (let i = 0; i < data.length; ++i) {
|
||||
this._parseBuffer[i] = data.charCodeAt(i);
|
||||
}
|
||||
this._parser.parse(this._parseBuffer, data.length);
|
||||
|
||||
buffer = this._terminal.buffer;
|
||||
if (buffer.x !== cursorStartX || buffer.y !== cursorStartY) {
|
||||
@@ -324,9 +345,9 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
}
|
||||
}
|
||||
|
||||
public print(data: string, start: number, end: number): void {
|
||||
let char: string;
|
||||
public print(data: Uint16Array, start: number, end: number): void {
|
||||
let code: number;
|
||||
let char: string;
|
||||
let chWidth: number;
|
||||
const buffer: IBuffer = this._terminal.buffer;
|
||||
const charset: ICharset = this._terminal.charset;
|
||||
@@ -338,30 +359,30 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
let bufferRow = buffer.lines.get(buffer.y + buffer.ybase);
|
||||
|
||||
this._terminal.updateRange(buffer.y);
|
||||
for (let stringPosition = start; stringPosition < end; ++stringPosition) {
|
||||
char = data.charAt(stringPosition);
|
||||
code = data.charCodeAt(stringPosition);
|
||||
for (let pos = start; pos < end; ++pos) {
|
||||
code = data[pos];
|
||||
char = String.fromCharCode(code);
|
||||
|
||||
// surrogate pair handling
|
||||
if (0xD800 <= code && code <= 0xDBFF) {
|
||||
if (++stringPosition >= end) {
|
||||
if (++pos >= end) {
|
||||
// end of input:
|
||||
// handle pairs as true UTF-16 and wait for the second part
|
||||
// since we expect the input comming from a stream there is
|
||||
// a small chance that the surrogate pair got split
|
||||
// therefore we dont process the first char here, instead
|
||||
// it gets added as first char to the next processed chunk
|
||||
this._surrogateFirst = char;
|
||||
this._surrogateFirst = String.fromCharCode(code);
|
||||
continue;
|
||||
}
|
||||
const second = data.charCodeAt(stringPosition);
|
||||
const second = data[pos];
|
||||
// if the second part is in surrogate pair range create the high codepoint
|
||||
// otherwise fall back to UCS-2 behavior (handle codepoints independently)
|
||||
if (0xDC00 <= second && second <= 0xDFFF) {
|
||||
code = (code - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
|
||||
char += data.charAt(stringPosition);
|
||||
char += String.fromCharCode(second);
|
||||
} else {
|
||||
stringPosition--;
|
||||
pos--;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,9 +391,14 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
chWidth = wcwidth(code);
|
||||
|
||||
// get charset replacement character
|
||||
if (charset) {
|
||||
char = charset[char] || char;
|
||||
code = char.charCodeAt(0);
|
||||
// charset are only defined for ASCII, therefore we only
|
||||
// search for an replacement char if code < 127
|
||||
if (code < 127 && charset) {
|
||||
const ch = charset[char];
|
||||
if (ch) {
|
||||
code = ch.charCodeAt(0);
|
||||
char = ch;
|
||||
}
|
||||
}
|
||||
|
||||
if (screenReaderMode) {
|
||||
|
||||
+4
-4
@@ -111,7 +111,7 @@ export interface ICompositionHelper {
|
||||
*/
|
||||
export interface IInputHandler {
|
||||
parse(data: string): void;
|
||||
print(data: string, start: number, end: number): void;
|
||||
print(data: Uint16Array, start: number, end: number): void;
|
||||
|
||||
/** C0 BEL */ bell(): void;
|
||||
/** C0 LF */ lineFeed(): void;
|
||||
@@ -463,7 +463,7 @@ export interface IParsingState {
|
||||
*/
|
||||
export interface IDcsHandler {
|
||||
hook(collect: string, params: number[], flag: number): void;
|
||||
put(data: string, start: number, end: number): void;
|
||||
put(data: Uint16Array, start: number, end: number): void;
|
||||
unhook(): void;
|
||||
}
|
||||
|
||||
@@ -480,9 +480,9 @@ export interface IEscapeSequenceParser extends IDisposable {
|
||||
* Parse string `data`.
|
||||
* @param data The data to parse.
|
||||
*/
|
||||
parse(data: string): void;
|
||||
parse(data: Uint16Array, length: number): void;
|
||||
|
||||
setPrintHandler(callback: (data: string, start: number, end: number) => void): void;
|
||||
setPrintHandler(callback: (data: Uint16Array, start: number, end: number) => void): void;
|
||||
clearPrintHandler(): void;
|
||||
|
||||
setExecuteHandler(flag: string, callback: () => void): void;
|
||||
|
||||
Reference in New Issue
Block a user