1 | 'use strict';
|
2 |
|
3 | var _ = require('lodash');
|
4 |
|
5 | var eventCodes = {
|
6 | 0: 'clear-screen',
|
7 | 1: 'cursor-home',
|
8 | 2: {
|
9 | type: 'cursor-position',
|
10 | args: 2
|
11 | },
|
12 | 3: 'cursor-left',
|
13 | 4: 'cursor-right',
|
14 | 5: 'cursor-up',
|
15 | 6: 'cursor-down',
|
16 | 7: 'speaker-beep',
|
17 | 8: 'backspace',
|
18 | 9: 'tab',
|
19 | 10: 'linefeed',
|
20 | 11: 'clear-eol',
|
21 | 12: 'clear-below',
|
22 | 13: 'linefeed',
|
23 | 14: {
|
24 | type: 'cursor-position-x',
|
25 | args: 1
|
26 | },
|
27 | 15: {
|
28 | type: 'cursor-position-y',
|
29 | args: 1
|
30 | },
|
31 | 16: 'clear-screen'
|
32 | };
|
33 |
|
34 | function addTextEvent(eventList, text) {
|
35 | if(text.length > 0){
|
36 | eventList.push({
|
37 | type: 'text',
|
38 | data: text
|
39 | });
|
40 | }
|
41 | }
|
42 |
|
43 | function addEvent(eventList, type, data) {
|
44 | eventList.push({
|
45 | type: type,
|
46 | data: data
|
47 | });
|
48 | }
|
49 |
|
50 | function combineLinefeed(lastCode, code){
|
51 | return (lastCode === 10 && code === 13) || (lastCode === 13 && code === 10);
|
52 | }
|
53 |
|
54 | function StreamParser(){
|
55 | this.partial = null;
|
56 | this.lastCode = null;
|
57 | this.ignoreBytes = [];
|
58 | }
|
59 |
|
60 | StreamParser.prototype.parseStreamChunk = function(chunk){
|
61 | var events = [];
|
62 | var str = '';
|
63 | for(var idx = 0; idx < chunk.length; idx++){
|
64 | var char = chunk[idx];
|
65 | if(this.partial != null){
|
66 | this.partial.data.push(char);
|
67 | if(this.partial.data.length >= this.partial.args){
|
68 | events.push(this.partial);
|
69 | this.partial = null;
|
70 | }
|
71 | }else if(combineLinefeed(this.lastCode, char)){
|
72 |
|
73 |
|
74 |
|
75 | this.lastCode = null;
|
76 | continue;
|
77 | }else if(this.ignoreBytes.length > 0 && char === this.ignoreBytes[0]){
|
78 |
|
79 | this.ignoreBytes.shift();
|
80 | }else if(eventCodes[char] != null){
|
81 |
|
82 | addTextEvent(events, str);
|
83 | str = '';
|
84 | this.handleEvent(events, eventCodes[char]);
|
85 | } else {
|
86 | str += String.fromCharCode(char);
|
87 | }
|
88 | this.lastCode = char;
|
89 | }
|
90 |
|
91 | addTextEvent(events, str);
|
92 | return events;
|
93 | };
|
94 |
|
95 | StreamParser.prototype.handleEvent = function(eventList, evt){
|
96 | if(typeof evt === 'string'){
|
97 | addEvent(eventList, evt);
|
98 | }else{
|
99 | this.partial = {
|
100 | type: evt.type,
|
101 | data: [],
|
102 | args: evt.args
|
103 | };
|
104 | }
|
105 | };
|
106 |
|
107 | StreamParser.prototype.clearIgnore = function(data){
|
108 | this.ignoreBytes = [];
|
109 | };
|
110 |
|
111 | StreamParser.prototype.ignore = function(data){
|
112 | if(_.isNumber(data)){
|
113 | this.ignoreBytes.push(data);
|
114 | }else{
|
115 | this.ignoreBytes = this.ignoreBytes.concat(_.toArray(data));
|
116 | }
|
117 | };
|
118 |
|
119 |
|
120 | module.exports = StreamParser;
|