This repository was archived by the owner on Jan 8, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlinestream.coffee
More file actions
86 lines (76 loc) · 2.61 KB
/
linestream.coffee
File metadata and controls
86 lines (76 loc) · 2.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
###
@author Tobias Kopelke <nox@demoncode.de>
The Linestream class will take any stream that emits a 'data'
and an 'end' event and converts the content that is streamed
into a string, splits it by '\n' and emits a 'line' event for
each line found.
The class ensures that the line events will be emitted in order
and have the line-number as a second parameter.
When the 'end' event is emitted the class will not accept
anymore content.
@TODO find a way to offset a stream
@TODO pause & resume handles
###
Stream = require 'stream'
class Linestream extends Stream
constructor: (stream) ->
# A buffer that contains the remainder of a line
# to prevent emitting 2 lines where only is one
buffer = null
# buffer array to emit
lines = []
# line index
line = 0
# Flag if we are waiting for the process emitting
# the current line. Only after it is emitted we
# allow the emitting of the next line
emitting = false
# Flag if the end event was emitted
ended = false
# Flag to stop emitting anything
# true when ended and lines.length = 0
done = false
# emit-handler
emit = =>
# do not emit while waiting or we are done
return if emitting or done or not lines.length
emitting = true
# get the current line and emit it
current = lines.shift()
@emit 'line', current, line++ if current isnt null
# emit the 'end' event if there are no more lines and
# we have handled the 'end' event from the stream
if ended and not lines.length
@emit 'end'
@on 'line', =>
# on-line handler, emit more or wait for more content
emitting = false
return done = ended or done if not lines.length or done
process.nextTick emit
stream.on 'data', (data) ->
# done do anything if we are done
return if ended
# convert to string and add the old buffer
str = (buffer or '') + data.toString()
# split by '\n'
splitted = str.split "\n"
# take the last element and put it in the buffer
buffer = splitted.pop()
# append all new found lines to the lines array
lines.push.apply lines, splitted
# and start the emitter
emit()
stream.on 'end', ->
# done do anything if we are done
return if ended
# set the ended flag
ended = true
# put the buffer into the lines array
lines.push buffer
# and start the emitter
emit()
stream.on 'error', (err) =>
@emit 'error', err
Linestream.create = (stream) ->
new Linestream stream
module.exports = Linestream