em-systemcommand 2.0.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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(master, name)
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
- @cr_offset = 0
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
- @outputbuffer.pos = @cr_offset
84
- parse_crlf data[(ix+1)..-1] # receive rest data
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
- @cr_offset = @outputbuffer.pos
96
- parse_crlf data[(ix+1)..-1] # receive rest data
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
@@ -1,5 +1,5 @@
1
1
  module Em
2
2
  module Systemcommand
3
- VERSION = "2.0.0"
3
+ VERSION = "2.0.1"
4
4
  end
5
5
  end
@@ -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.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: 1829514624315752226
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: 1829514624315752226
175
+ hash: -2179568276682517415
176
176
  requirements: []
177
177
  rubyforge_project:
178
178
  rubygems_version: 1.8.24