Class: EventMachine::SystemCommand::Pipe

Inherits:
EM::Connection
  • Object
show all
Defined in:
lib/em-systemcommand/pipe.rb

Instance Method Summary collapse

Constructor Details

#initialize(master, name) ⇒ Pipe

Returns a new instance of Pipe.



6
7
8
9
10
11
12
13
14
15
# File 'lib/em-systemcommand/pipe.rb', line 6

def initialize master, name
  @master             = master
  @name               = name
  @master.pipes[name] = self
  begin
    @outputbuffer     = StringIO.new
  rescue Exception => e
    puts "Uninitialized constant StringIO. This may happen when you forgot to use bundler. Use `bundle exec`."
  end
end

Instance Method Details

#closeObject

Close the attached IO object.



199
200
201
202
203
204
205
206
207
# File 'lib/em-systemcommand/pipe.rb', line 199

def close
  begin
    @io.close unless @io.closed?
    close_connection
  rescue Exception => e
    # ignore errors for instance when the connection has already
    # been closed.
  end
end

#data {|data| ... } ⇒ Object

Adds a callback for ‘receive_data` events.

Yields:

  • The callback that´s to be added to the data callback array

Yield Parameters:

  • data (String)

    The data that´s received



193
194
195
# File 'lib/em-systemcommand/pipe.rb', line 193

def data &block
  receive_data_callbacks << block
end

#line {|line| ... } ⇒ Object

Adds a callback for ‘receive_line` events.

Yields:

  • The callback that should be added to callback array for line events

Yield Parameters:

  • line (String)

    The line that has been received



68
69
70
# File 'lib/em-systemcommand/pipe.rb', line 68

def line &block
  receive_line_callbacks << block
end

#match(regexp, opt = {}, &block) ⇒ Object

Convenience method to create a callback that matches a regular expression

Parameters:

  • regexp (Regexp)

    The regular expression that should be matched

  • opt (Hash) (defaults to: {})

    a customizable set of options

Options Hash (opt):

  • :in (Symbol)

    Match either in ‘:line` or `:output`

  • :match (Symbol)

    Match either ‘:first` or `:last`



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/em-systemcommand/pipe.rb', line 32

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
      case opt[:match]
      when :first
        EM.next_tick do
          block.call *matches[0]
        end
      when :last
        EM.next_tick do
          block.call *matches[matches.length-1]
        end
      end
    end
  end
end

#outputString

The content of the output buffer as string.

Returns:

  • (String)

    The connections output



21
22
23
# File 'lib/em-systemcommand/pipe.rb', line 21

def output
  @outputbuffer.string
end

#parse_cr(data, ix) ⇒ Object

Parses carriage return when data is received.

Parameters:

  • data (String)

    The received data

  • ix (Integer)

    The index of the carriage return



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/em-systemcommand/pipe.rb', line 120

def parse_cr data, ix
  ln = (@linebuffer << data[0...ix]).join
  @linebuffer.clear

  ln.force_encoding("UTF-8")

  receive_line ln
  @outputbuffer.print ln

  # jump back to the last line feed
  @outputbuffer.pos = @lf_offset

  # parse rest of the data
  parse_crlf data[(ix+1)..-1]
end

#parse_crlf(data) ⇒ Object

Parse received data for line feeds or carriage returns.

Parameters:

  • data (String)

    The received data



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/em-systemcommand/pipe.rb', line 168

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
    else
      parse_lf data, ilf
    end
  else
    if icr = data.index("\r")
      parse_cr data, icr
    else
      @linebuffer << data
      @outputbuffer.print data
    end
  end
end

#parse_lf(data, ix) ⇒ Object

Parses line feed when data is received.

Parameters:

  • data (String)

    The received data

  • ix (Integer)

    The index of the line feed



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/em-systemcommand/pipe.rb', line 141

def parse_lf data, ix
  ln = (@linebuffer << data[0...ix]).join
  @linebuffer.clear
  ln.chomp!

  ln.force_encoding("UTF-8")

  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
  # 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

#receive_data(data, recursive = false) ⇒ Object

Invoked when data was received.

Parameters:

  • data (String)

    The received data



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/em-systemcommand/pipe.rb', line 98

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|
      EM.next_tick do
        callback.call data.dup
      end
    end
  end
  @linebuffer ||= []
  @lf_offset  ||= 0

  parse_crlf data

  receive_update @outputbuffer.string unless recursive
end

#receive_line(line) ⇒ Object

Invoked when line was received

Parameters:

  • line (String)

    The line that´s received



55
56
57
58
59
60
61
# File 'lib/em-systemcommand/pipe.rb', line 55

def receive_line line
  receive_line_callbacks.each do |callback|
    EM.next_tick do
      callback.call line.dup
    end
  end
end

#receive_update(buffer) ⇒ Object

Invoked when a line was written, but ‘r` was received without a line-break in the end.

Parameters:

  • buffer (String)

    The complete buffer content of this connection



77
78
79
80
81
82
83
# File 'lib/em-systemcommand/pipe.rb', line 77

def receive_update buffer
  receive_update_callbacks.each do |callback|
    EM.next_tick do
      callback.call buffer.dup
    end
  end
end

#unbindObject

Invoked when the connection is terminated. Calls ‘unbind(@name)` on master.



212
213
214
215
# File 'lib/em-systemcommand/pipe.rb', line 212

def unbind
  self.close
  @master.unbind(@name)
end

#update {|buffer| ... } ⇒ Object

Adds a callback for ‘receive_update` events.

Yields:

  • The callback that should be added to callback array for update events

Yield Parameters:

  • buffer (String)

    The complete buffer content of this connection



90
91
92
# File 'lib/em-systemcommand/pipe.rb', line 90

def update &block
  receive_update_callbacks << block
end