Class: RobotLab::Cyborg::Channel::Terminal

Inherits:
Channel
  • Object
show all
Defined in:
lib/robot_lab/cyborg/channel.rb

Overview

Terminal-backed channel: the human is at a keyboard. This is the only place +$stdin+/+$stdout+ are assumed; inject StringIO in tests.

Instance Method Summary collapse

Constructor Details

#initialize(input: $stdin, output: $stdout, name: "cyborg") ⇒ Terminal

Returns a new instance of Terminal.

Parameters:

  • input (IO) (defaults to: $stdin)

    stream to read the human's messages from

  • output (IO) (defaults to: $stdout)

    stream to write messages to the human on

  • name (String) (defaults to: "cyborg")

    label shown when a message has no explicit sender



85
86
87
88
89
90
91
# File 'lib/robot_lab/cyborg/channel.rb', line 85

def initialize(input: $stdin, output: $stdout, name: "cyborg")
  @input = input
  @output = output
  @name = name
  @write_mutex = Mutex.new
  super()
end

Instance Method Details

#deliver(message) ⇒ Object

Print the message. A :question is followed by a "> " prompt; other kinds (inbound peer messages, notices) are not, so unsolicited traffic does not spam the input cursor. Synchronized so concurrent deliveries (a question and an inbound peer message) never interleave on screen.



97
98
99
100
101
102
103
104
# File 'lib/robot_lab/cyborg/channel.rb', line 97

def deliver(message)
  @write_mutex.synchronize do
    @output.puts "\n[#{message.sender || @name}] #{message.content}"
    @output.print "> " if message.question?
    @output.flush
  end
  message
end

#receive(timeout: nil) ⇒ Object

Read a line, honoring timeout so the consumer can poll for shutdown and expiry. Uses IO.select on a real IO; a non-selectable stream (StringIO in tests) returns immediately from #gets, which is equally responsive. A nil line means EOF. A bare terminal carries no correlation, so in_reply_to stays nil.



111
112
113
114
115
116
117
118
# File 'lib/robot_lab/cyborg/channel.rb', line 111

def receive(timeout: nil)
  return nil if timeout && selectable? && !@input.wait_readable(timeout)
  return nil unless (line = @input.gets)

  ChannelMessage.new(content: line.chomp, kind: :answer)
rescue IOError
  nil
end