Class: TTYProcessCtl

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/tty-process-ctl.rb

Defined Under Namespace

Classes: Listener

Constant Summary collapse

Timeout =
Class.new(Timeout::Error)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(command, options = {}) ⇒ TTYProcessCtl

Returns a new instance of TTYProcessCtl.



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/tty-process-ctl.rb', line 38

def initialize(command, options = {})
  @backlog_size = options[:backlog_size] || 4000
  @command = command

  @listeners = []
  @out_queue = Queue.new

  @r, @w, @pid = PTY.spawn(@command)
  @w.echo = false # disable echoing of commands
  @thread = Thread.start do
    begin
      abort_on_exception = true
      @r.each_line do |line|
        enqueue_message line.chop
      end
    rescue Errno::EIO
    ensure
      @exit_status = PTY.check(@pid)
      @r.close
      @w.close
      enqueue_end
    end
  end
end

Instance Attribute Details

#exit_statusObject (readonly)

Returns the value of attribute exit_status.



63
64
65
# File 'lib/tty-process-ctl.rb', line 63

def exit_status
  @exit_status
end

Instance Method Details

#alive?Boolean

Returns:



65
66
67
# File 'lib/tty-process-ctl.rb', line 65

def alive?
  @thread.alive?
end

#each(options = {}, &block) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/tty-process-ctl.rb', line 83

def each(options = {}, &block)
  return enum_for(:each, options) unless block
  listener = listener(&block)
  begin
    timeout(options[:timeout]) do
      true while not listener.closed? and poll
    end
    self
  ensure
    # make sure we close the listener when each exits
    listener.close
  end
end

#each_until(pattern, options = {}) ⇒ Object



97
98
99
100
101
102
103
104
# File 'lib/tty-process-ctl.rb', line 97

def each_until(pattern, options = {})
  return enum_for(:each_until, pattern, options) unless block_given?
  each(options) do |message|
    yield message
    break if message =~ pattern
  end
  self
end

#each_until_exclude(pattern, options = {}) ⇒ Object



106
107
108
109
110
111
112
113
# File 'lib/tty-process-ctl.rb', line 106

def each_until_exclude(pattern, options = {})
  return enum_for(:each_until_exclude, pattern, options) unless block_given?
  each(options) do |message|
    break if message =~ pattern
    yield message
  end
  self
end

#flushObject



137
138
139
140
# File 'lib/tty-process-ctl.rb', line 137

def flush
  true while process_message_no_block
  self
end

#on(regexp = nil, &callback) ⇒ Object



75
76
77
78
79
80
81
# File 'lib/tty-process-ctl.rb', line 75

def on(regexp = nil, &callback)
  # return listender to user so he can close it after use
  listener do |message|
    next if regexp and message !~ regexp
    callback.call(message)
  end
end

#poll(options = {}) ⇒ Object



125
126
127
128
129
# File 'lib/tty-process-ctl.rb', line 125

def poll(options = {})
  timeout(options[:timeout]) do
    return process_message
  end
end

#poll!(options = {}) ⇒ Object



131
132
133
134
135
# File 'lib/tty-process-ctl.rb', line 131

def poll!(options = {})
  timeout(options[:timeout]) do
    true while process_message
  end
end

#send_command(command) ⇒ Object



69
70
71
72
73
# File 'lib/tty-process-ctl.rb', line 69

def send_command(command)
  @w.puts command
rescue Errno::EIO
  raise IOError.new("process '#{@command}' (pid: #{@pid}) not accepting input")
end

#wait_exit(options = {}) ⇒ Object



119
120
121
122
123
# File 'lib/tty-process-ctl.rb', line 119

def wait_exit(options = {})
  poll!(options)
  @thread.join
  self
end

#wait_until(pattern, options = {}) ⇒ Object



115
116
117
# File 'lib/tty-process-ctl.rb', line 115

def wait_until(pattern, options = {})
  each_until(pattern, options){}
end