class Nuggets::IO::InteractMixin::Interaction

Constants

DEFAULT_MAXLEN

Attributes

maxlen[RW]
readers[R]
timeout[RW]
writers[R]

Public Class Methods

new(input, output, timeout = nil, maxlen = nil) click to toggle source
# File lib/nuggets/io/interact_mixin.rb, line 86
def initialize(input, output, timeout = nil, maxlen = nil)
  @readers, @writers = {}, {}

  output.each { |key, val| @readers[key] =  initialize_reader(val)      }
  input.each  { |key, val| @writers[val] = [initialize_writer(key), ''] }

  @timeout, @maxlen = timeout, maxlen || DEFAULT_MAXLEN
end

Public Instance Methods

interact() click to toggle source
# File lib/nuggets/io/interact_mixin.rb, line 99
def interact
  until readers.empty? && writers.empty?
    handles = select(readers.keys, writers.keys, nil, timeout) or return

    handle_readers(handles[0])
    handle_writers(handles[1])
  end

  []
end

Private Instance Methods

close(container, item, reading = nil) click to toggle source
# File lib/nuggets/io/interact_mixin.rb, line 172
def close(container, item, reading = nil)
  container.delete(item)
  reading ? item.close_read : item.close_write
end
handle_readers(handles) click to toggle source
# File lib/nuggets/io/interact_mixin.rb, line 135
def handle_readers(handles)
  handles.each { |reader| read(reader, readers[reader]) }
end
handle_writers(handles) click to toggle source
# File lib/nuggets/io/interact_mixin.rb, line 139
def handle_writers(handles)
  handles.each { |writer|
    reader, buffer = writers[writer]
    read(reader, buffer, writer) or next if buffer.empty?

    begin
      bytes = writer.write_nonblock(buffer)
    rescue ::Errno::EPIPE
      close(writers, writer)
    end

    buffer.force_encoding('BINARY').slice!(0, bytes) if bytes
  }
end
initialize_reader(reader) click to toggle source
# File lib/nuggets/io/interact_mixin.rb, line 112
def initialize_reader(reader)
  if reader.is_a?(::Proc) && !reader.respond_to?(:<<)
    class << reader; alias_method :<<, :call; end
  end

  reader
end
initialize_writer(writer) click to toggle source
# File lib/nuggets/io/interact_mixin.rb, line 120
def initialize_writer(writer)
  if writer.is_a?(::String)
    require 'stringio'
    writer = ::StringIO.new(writer)
  end

  unless writer.respond_to?(:read_nonblock)
    def writer.read_nonblock(*args)
      read(*args) or raise ::EOFError, 'end of string reached'
    end
  end

  writer
end
read(reader, buffer, writer = nil) click to toggle source
# File lib/nuggets/io/interact_mixin.rb, line 154
def read(reader, buffer, writer = nil)
  container = writer ? writers : readers

  begin
    buffer << reader.read_nonblock(maxlen)
  rescue ::Errno::EAGAIN
  rescue ::EOFError
    buffer.force_encoding(
      reader.internal_encoding  ||
      reader.external_encoding  ||
      Encoding.default_internal ||
      Encoding.default_external
    ) if buffer.respond_to?(:force_encoding)

    close(container, writer || reader, !writer)
  end
end