em-systemcommand 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/em-systemcommand/pipe.rb +68 -7
- data/lib/em-systemcommand/version.rb +1 -1
- data/spec/em-systemcommand/pipe_spec.rb +21 -0
- metadata +3 -3
@@ -1,18 +1,23 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
1
2
|
module EventMachine
|
2
3
|
class SystemCommand
|
3
4
|
class Pipe < EM::Connection
|
4
5
|
|
5
|
-
def initialize
|
6
|
+
def initialize master, name
|
6
7
|
@master = master
|
7
8
|
@name = name
|
8
9
|
@master.pipes[name] = self
|
9
10
|
begin
|
10
|
-
@outputbuffer = StringIO.new
|
11
|
+
@outputbuffer = StringIO.new
|
11
12
|
rescue Exception => e
|
12
13
|
puts "Uninitialized constant StringIO. This may happen when you forgot to use bundler. Use `bundle exec`."
|
13
14
|
end
|
14
15
|
end
|
15
16
|
|
17
|
+
##
|
18
|
+
# The content of the output buffer as string.
|
19
|
+
#
|
20
|
+
# @return [String] The connections output
|
16
21
|
def output
|
17
22
|
@outputbuffer.string
|
18
23
|
end
|
@@ -20,6 +25,10 @@ module EventMachine
|
|
20
25
|
##
|
21
26
|
# Convenience method to create a callback that matches a regular
|
22
27
|
# expression
|
28
|
+
#
|
29
|
+
# @param [Regexp] regexp The regular expression that should be matched
|
30
|
+
# @option opt [Symbol] :in Match either in `:line` or `:output`
|
31
|
+
# @option opt [Symbol] :match Match either `:first` or `:last`
|
23
32
|
def match regexp, opt = {}, &block
|
24
33
|
opt = { in: :line, match: :first }.merge opt
|
25
34
|
(opt[:in] == :output ? receive_update_callbacks : receive_line_callbacks) << lambda do |data|
|
@@ -35,68 +44,115 @@ module EventMachine
|
|
35
44
|
end
|
36
45
|
end
|
37
46
|
|
47
|
+
##
|
38
48
|
# Invoked when line was received
|
49
|
+
#
|
50
|
+
# @param [String] line The line that´s received
|
39
51
|
def receive_line line
|
40
52
|
receive_line_callbacks.each do |callback|
|
41
53
|
callback.call line.dup
|
42
54
|
end
|
43
55
|
end
|
44
56
|
|
57
|
+
##
|
45
58
|
# Adds a callback for `receive_line` events.
|
59
|
+
#
|
60
|
+
# @yield The callback that should be added to callback array for line events
|
61
|
+
# @yieldparam [String] line The line that has been received
|
46
62
|
def line &block
|
47
63
|
receive_line_callbacks << block
|
48
64
|
end
|
49
65
|
|
66
|
+
##
|
50
67
|
# Invoked when a line was written, but `\r` was received without
|
51
68
|
# a line-break in the end.
|
69
|
+
#
|
70
|
+
# @param [String] buffer The complete buffer content of this connection
|
52
71
|
def receive_update buffer
|
53
72
|
receive_update_callbacks.each do |callback|
|
54
73
|
callback.call buffer.dup
|
55
74
|
end
|
56
75
|
end
|
57
76
|
|
77
|
+
##
|
58
78
|
# Adds a callback for `receive_update` events.
|
79
|
+
#
|
80
|
+
# @yield The callback that should be added to callback array for update events
|
81
|
+
# @yieldparam [String] buffer The complete buffer content of this connection
|
59
82
|
def update &block
|
60
83
|
receive_update_callbacks << block
|
61
84
|
end
|
62
85
|
|
86
|
+
##
|
63
87
|
# Invoked when data was received.
|
88
|
+
#
|
89
|
+
# @param [String] data The received data
|
64
90
|
def receive_data data, recursive = false
|
91
|
+
# if recursive is true we already invoked the receive data callbacks!
|
65
92
|
unless recursive
|
66
93
|
receive_data_callbacks.each do |callback|
|
67
94
|
callback.call data.dup
|
68
95
|
end
|
69
96
|
end
|
70
97
|
@linebuffer ||= []
|
71
|
-
@
|
98
|
+
@lf_offset ||= 0
|
72
99
|
|
73
100
|
parse_crlf data
|
74
101
|
|
75
102
|
receive_update @outputbuffer.string unless recursive
|
76
103
|
end
|
77
104
|
|
105
|
+
##
|
106
|
+
# Parses carriage return when data is received.
|
107
|
+
#
|
108
|
+
# @param [String] data The received data
|
109
|
+
# @param [Integer] ix The index of the carriage return
|
78
110
|
def parse_cr data, ix
|
79
111
|
ln = (@linebuffer << data[0...ix]).join
|
80
112
|
@linebuffer.clear
|
113
|
+
|
81
114
|
receive_line ln
|
82
115
|
@outputbuffer.print ln
|
83
|
-
|
84
|
-
|
116
|
+
|
117
|
+
# jump back to the last line feed
|
118
|
+
@outputbuffer.pos = @lf_offset
|
119
|
+
|
120
|
+
# parse rest of the data
|
121
|
+
parse_crlf data[(ix+1)..-1]
|
85
122
|
end
|
86
123
|
|
124
|
+
##
|
125
|
+
# Parses line feed when data is received.
|
126
|
+
#
|
127
|
+
# @param [String] data The received data
|
128
|
+
# @param [Integer] ix The index of the line feed
|
87
129
|
def parse_lf data, ix
|
88
130
|
ln = (@linebuffer << data[0...ix]).join
|
89
131
|
@linebuffer.clear
|
90
132
|
ln.chomp!
|
133
|
+
|
91
134
|
receive_line ln
|
92
135
|
@outputbuffer.print ln
|
136
|
+
|
137
|
+
# jump to the end of the buffer to keep the characters, that
|
138
|
+
# may already have been written
|
93
139
|
@outputbuffer.pos = @outputbuffer.length
|
140
|
+
# print the line feed
|
94
141
|
@outputbuffer.puts
|
95
|
-
|
96
|
-
|
142
|
+
# set last line feed to the current cursor position, so we
|
143
|
+
# know where we have to jump back, when a carriage return occurs
|
144
|
+
@lf_offset = @outputbuffer.pos
|
145
|
+
|
146
|
+
# parse rest of the data
|
147
|
+
parse_crlf data[(ix+1)..-1]
|
97
148
|
end
|
98
149
|
|
150
|
+
##
|
151
|
+
# Parse received data for line feeds or carriage returns.
|
152
|
+
#
|
153
|
+
# @param [String] data The received data
|
99
154
|
def parse_crlf data
|
155
|
+
return if data == ''
|
100
156
|
if ilf = data.index("\n")
|
101
157
|
# if we find a LF and that LF is after a CR we first handle
|
102
158
|
# the CR
|
@@ -115,11 +171,16 @@ module EventMachine
|
|
115
171
|
end
|
116
172
|
end
|
117
173
|
|
174
|
+
##
|
118
175
|
# Adds a callback for `receive_data` events.
|
176
|
+
#
|
177
|
+
# @yield The callback that´s to be added to the data callback array
|
178
|
+
# @yieldparam [String] data The data that´s received
|
119
179
|
def data &block
|
120
180
|
receive_data_callbacks << block
|
121
181
|
end
|
122
182
|
|
183
|
+
##
|
123
184
|
# Close the attached IO object.
|
124
185
|
def close
|
125
186
|
begin
|
@@ -2,6 +2,27 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe 'Pipe' do
|
4
4
|
|
5
|
+
context 'parsing' do
|
6
|
+
|
7
|
+
it 'should handle carriage returns' do
|
8
|
+
cmd = EM::SystemCommand.new 'exit 0;'
|
9
|
+
pipe = EM::SystemCommand::Pipe.new(nil, cmd, :stdout)
|
10
|
+
pipe.receive_data "test\n"
|
11
|
+
pipe.receive_data " 32768 0% 0.00kB/s 0:00:00\r"
|
12
|
+
pipe.receive_data " 131235840 12% 125.12MB/s 0:00:06\r"
|
13
|
+
pipe.receive_data " 261619712 25% 124.80MB/s 0:00:05\r"
|
14
|
+
pipe.receive_data " 391544832 38% 124.54MB/s 0:00:04\r"
|
15
|
+
pipe.receive_data " 522616832 51% 124.69MB/s 0:00:03\r"
|
16
|
+
pipe.receive_data " 652738560 63% 124.43MB/s 0:00:02\r"
|
17
|
+
pipe.receive_data " 783056896 76% 124.41MB/s 0:00:01\r"
|
18
|
+
pipe.receive_data " 906657792 88% 122.90MB/s 0:00:00\r"
|
19
|
+
pipe.receive_data " 1024000000 100% 123.67MB/s 0:00:07 (xfer#1, to-check=0/1)\n"
|
20
|
+
pipe.receive_data "\n"
|
21
|
+
pipe.receive_data "sent 1024125065 bytes received 31 bytes 120485305.41 bytes/sec\ntotal size is 1024000000 speedup is 1.00\n"
|
22
|
+
pipe.output.should == "test\n 1024000000 100% 123.67MB/s 0:00:07 (xfer#1, to-check=0/1)\n\nsent 1024125065 bytes received 31 bytes 120485305.41 bytes/sec\ntotal size is 1024000000 speedup is 1.00\n"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
5
26
|
context '#receive_data' do
|
6
27
|
it 'should correctly do a carriage return in the output buffer' do
|
7
28
|
EM.run do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: em-systemcommand
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -163,7 +163,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
163
163
|
version: '0'
|
164
164
|
segments:
|
165
165
|
- 0
|
166
|
-
hash:
|
166
|
+
hash: -2179568276682517415
|
167
167
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
168
168
|
none: false
|
169
169
|
requirements:
|
@@ -172,7 +172,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
172
172
|
version: '0'
|
173
173
|
segments:
|
174
174
|
- 0
|
175
|
-
hash:
|
175
|
+
hash: -2179568276682517415
|
176
176
|
requirements: []
|
177
177
|
rubyforge_project:
|
178
178
|
rubygems_version: 1.8.24
|