UNPKG

2.68 kBJavaScriptView Raw
1'use strict';
2
3var _ = require('lodash');
4
5var 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
34function addTextEvent(eventList, text) {
35 if(text.length > 0){
36 eventList.push({
37 type: 'text',
38 data: text
39 });
40 }
41}
42
43function addEvent(eventList, type, data) {
44 eventList.push({
45 type: type,
46 data: data
47 });
48}
49
50function combineLinefeed(lastCode, code){
51 return (lastCode === 10 && code === 13) || (lastCode === 13 && code === 10);
52}
53
54function StreamParser(){
55 this.partial = null;
56 this.lastCode = null;
57 this.ignoreBytes = [];
58}
59
60StreamParser.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 //do nothing, allow previous linefeed event to handle this
73 //set lastCode to nothing so it won't accidentally filter repeating cases:
74 // LF, CR, LF, CR
75 this.lastCode = null;
76 continue;
77 }else if(this.ignoreBytes.length > 0 && char === this.ignoreBytes[0]){
78 //ignore character, remove from ignore buffer
79 this.ignoreBytes.shift();
80 }else if(eventCodes[char] != null){
81 // finalize the current text event before we create the special event
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 // finalize any trailing text into an event
91 addTextEvent(events, str);
92 return events;
93};
94
95StreamParser.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
107StreamParser.prototype.clearIgnore = function(data){
108 this.ignoreBytes = [];
109};
110
111StreamParser.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
120module.exports = StreamParser;