lib/em-systemcommand/pipe.rb in em-systemcommand-2.0.0 vs lib/em-systemcommand/pipe.rb in em-systemcommand-2.0.1
- old
+ new
@@ -1,27 +1,36 @@
+# -*- coding: utf-8 -*-
module EventMachine
class SystemCommand
class Pipe < EM::Connection
- def initialize(master, name)
+ def initialize master, name
@master = master
@name = name
@master.pipes[name] = self
begin
- @outputbuffer = StringIO.new()
+ @outputbuffer = StringIO.new
rescue Exception => e
puts "Uninitialized constant StringIO. This may happen when you forgot to use bundler. Use `bundle exec`."
end
end
+ ##
+ # The content of the output buffer as string.
+ #
+ # @return [String] The connections output
def output
@outputbuffer.string
end
##
# Convenience method to create a callback that matches a regular
# expression
+ #
+ # @param [Regexp] regexp The regular expression that should be matched
+ # @option opt [Symbol] :in Match either in `:line` or `:output`
+ # @option opt [Symbol] :match Match either `:first` or `:last`
def match regexp, opt = {}, &block
opt = { in: :line, match: :first }.merge opt
(opt[:in] == :output ? receive_update_callbacks : receive_line_callbacks) << lambda do |data|
matches = data.scan regexp
if matches.length > 0
@@ -33,72 +42,119 @@
end
end
end
end
+ ##
# Invoked when line was received
+ #
+ # @param [String] line The line that´s received
def receive_line line
receive_line_callbacks.each do |callback|
callback.call line.dup
end
end
+ ##
# Adds a callback for `receive_line` events.
+ #
+ # @yield The callback that should be added to callback array for line events
+ # @yieldparam [String] line The line that has been received
def line &block
receive_line_callbacks << block
end
+ ##
# Invoked when a line was written, but `\r` was received without
# a line-break in the end.
+ #
+ # @param [String] buffer The complete buffer content of this connection
def receive_update buffer
receive_update_callbacks.each do |callback|
callback.call buffer.dup
end
end
+ ##
# Adds a callback for `receive_update` events.
+ #
+ # @yield The callback that should be added to callback array for update events
+ # @yieldparam [String] buffer The complete buffer content of this connection
def update &block
receive_update_callbacks << block
end
+ ##
# Invoked when data was received.
+ #
+ # @param [String] data The received data
def receive_data data, recursive = false
+ # if recursive is true we already invoked the receive data callbacks!
unless recursive
receive_data_callbacks.each do |callback|
callback.call data.dup
end
end
@linebuffer ||= []
- @cr_offset = 0
+ @lf_offset ||= 0
parse_crlf data
receive_update @outputbuffer.string unless recursive
end
+ ##
+ # Parses carriage return when data is received.
+ #
+ # @param [String] data The received data
+ # @param [Integer] ix The index of the carriage return
def parse_cr data, ix
ln = (@linebuffer << data[0...ix]).join
@linebuffer.clear
+
receive_line ln
@outputbuffer.print ln
- @outputbuffer.pos = @cr_offset
- parse_crlf data[(ix+1)..-1] # receive rest data
+
+ # jump back to the last line feed
+ @outputbuffer.pos = @lf_offset
+
+ # parse rest of the data
+ parse_crlf data[(ix+1)..-1]
end
+ ##
+ # Parses line feed when data is received.
+ #
+ # @param [String] data The received data
+ # @param [Integer] ix The index of the line feed
def parse_lf data, ix
ln = (@linebuffer << data[0...ix]).join
@linebuffer.clear
ln.chomp!
+
receive_line ln
@outputbuffer.print ln
+
+ # jump to the end of the buffer to keep the characters, that
+ # may already have been written
@outputbuffer.pos = @outputbuffer.length
+ # print the line feed
@outputbuffer.puts
- @cr_offset = @outputbuffer.pos
- parse_crlf data[(ix+1)..-1] # receive rest data
+ # set last line feed to the current cursor position, so we
+ # know where we have to jump back, when a carriage return occurs
+ @lf_offset = @outputbuffer.pos
+
+ # parse rest of the data
+ parse_crlf data[(ix+1)..-1]
end
+ ##
+ # Parse received data for line feeds or carriage returns.
+ #
+ # @param [String] data The received data
def parse_crlf data
+ return if data == ''
if ilf = data.index("\n")
# if we find a LF and that LF is after a CR we first handle
# the CR
if icr = data.index("\r") and ilf != (icr+1) and icr < ilf
parse_cr data, icr
@@ -113,14 +169,19 @@
@outputbuffer.print data
end
end
end
+ ##
# Adds a callback for `receive_data` events.
+ #
+ # @yield The callback that´s to be added to the data callback array
+ # @yieldparam [String] data The data that´s received
def data &block
receive_data_callbacks << block
end
+ ##
# Close the attached IO object.
def close
begin
@io.close unless @io.closed?
detach