Class: OpenHAB::Console::Stdin

Inherits:
Stdio
  • Object
show all
Defined in:
lib/openhab/console/stdio.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Stdio

#inspect, #set_encoding, #tty?, #winsize

Constructor Details

#initialize(terminal) ⇒ Stdin

Returns a new instance of Stdin.



37
38
39
40
41
42
43
# File 'lib/openhab/console/stdio.rb', line 37

def initialize(terminal)
  super

  @byte_stream = terminal.input
  @buffer = StringIO.new.set_encoding(external_encoding)
  @eof = false
end

Instance Attribute Details

#external_encodingObject (readonly)

Returns the value of attribute external_encoding.



35
36
37
# File 'lib/openhab/console/stdio.rb', line 35

def external_encoding
  @external_encoding
end

#internal_encodingObject (readonly)

Returns the value of attribute internal_encoding.



35
36
37
# File 'lib/openhab/console/stdio.rb', line 35

def internal_encoding
  @internal_encoding
end

Instance Method Details

#eof?Boolean

Returns:

  • (Boolean)


45
46
47
# File 'lib/openhab/console/stdio.rb', line 45

def eof?
  @buffer.eof? && @eof
end

#getbyteObject



49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/openhab/console/stdio.rb', line 49

def getbyte
  unless @buffer.eof?
    b = @buffer.getbyte
    @buffer.truncate(0) if @buffer.eof?
    return b
  end
  return nil if eof?

  b = @byte_stream.read
  return nil if b.negative?

  b
end

#getcObject



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/openhab/console/stdio.rb', line 63

def getc
  unless @buffer.eof?
    c = @buffer.getc
    @buffer.truncate(0) if @buffer.eof?
    return c
  end
  return nil if eof?

  bytes = (+"").force_encoding(Encoding::BINARY)
  loop do
    b = getbyte
    return nil if b.nil?

    bytes << b.chr
    c = bytes.encode(external_encoding,
                     internal_encoding || Encoding.default_internal,
                     invalid: :replace,
                     undef: :replace,
                     replace: "")
    return c unless c.empty?
  end
rescue java.io.InterruptedIOException
  raise Interrupt
end

#getsObject



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/openhab/console/stdio.rb', line 96

def gets
  result = +""
  loop do
    c = getc
    if c.nil?
      return nil if result.empty?

      break
    end

    if c == "\x04" && result.empty? # ^D
      return nil
    elsif c == "\x7f"
      result.slice(0...-1)
    else
      result << c
    end
    break if c == "\n"
  end
  result
rescue java.io.InterruptedIOException
  raise Interrupt
end

#raw(min: nil, time: nil, intr: nil) ⇒ Object



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

def raw(min: nil, time: nil, intr: nil)
  previous_attributes = @terminal.attributes
  new_attributes = @terminal.attributes
  new_attributes.set_local_flags(java.util.EnumSet.of(org.jline.terminal.Attributes::LocalFlag::ICANON,
                                                      org.jline.terminal.Attributes::LocalFlag::ECHO,
                                                      org.jline.terminal.Attributes::LocalFlag::IEXTEN),
                                 false)
  new_attributes.set_local_flag(org.jline.terminal.Attributes::LocalFlag::ISIG, !!intr) # rubocop:disable Style/DoubleNegation
  new_attributes.set_input_flags(java.util.EnumSet.of(org.jline.terminal.Attributes::InputFlag::IXON,
                                                      org.jline.terminal.Attributes::InputFlag::ICRNL,
                                                      org.jline.terminal.Attributes::InputFlag::INLCR),
                                 false)
  new_attributes.set_control_char(org.jline.terminal.Attributes::ControlChar::VMIN, min || 1)
  new_attributes.set_control_char(org.jline.terminal.Attributes::ControlChar::VTIME, ((time || 0) * 10).to_i)
  @terminal.attributes = new_attributes
  yield self
ensure
  @terminal.set_attributes(previous_attributes) if previous_attributes
end

#read(bytes) ⇒ Object



120
121
122
123
124
125
126
# File 'lib/openhab/console/stdio.rb', line 120

def read(bytes)
  r = readpartial(bytes) if !eof? || (@buffer.size - @buffer.tell).positive?
  return nil if r.nil?

  r.concat(readpartial(bytes - r.bytesize)) while r.bytesize < bytes
  r
end

#readpartial(bytes) ⇒ Object Also known as: read_nonblock

Raises:

  • (EOFError)


128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/openhab/console/stdio.rb', line 128

def readpartial(bytes)
  available = @buffer.size - @buffer.tell
  if available.positive?
    bytes = available if available < bytes
    r = @buffer.read(bytes)
    @buffer.truncate(0) if @buffer.eof?
    return r
  end

  raise EOFError, "end of file reached" if eof?

  buffer = Java::byte[bytes].new
  read = @byte_stream.read_buffered(buffer)
  buffer = buffer[0..read] if read != bytes
  String.from_java_bytes(buffer)
end

#ungetbyte(byte) ⇒ Object



88
89
90
# File 'lib/openhab/console/stdio.rb', line 88

def ungetbyte(byte)
  @buffer.ungetbyte(byte)
end

#ungetc(char) ⇒ Object



92
93
94
# File 'lib/openhab/console/stdio.rb', line 92

def ungetc(char)
  @buffer.ungetc(char)
end

#wait_readable(timeout = nil) ⇒ Object



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/openhab/console/stdio.rb', line 146

def wait_readable(timeout = nil)
  return true if (@buffer.size - @buffer.tell).positive?

  return @byte_stream.available.positive? ? self : nil if timeout == 0 # rubocop:disable Style/NumericPredicate

  timeout = timeout ? timeout * 1000 : 0
  char = @byte_stream.read(timeout)
  if char == -1
    @eof = true
    # this is not normal behavior for wait_readable, but it seems like when the SSH client
    # disconnects, JLine just "closes" the NonBlockingPumpInputStream, and doesn't trigger
    # any signals. On the other end, Reline just keeps calling this repetitively forever
    # if we're at EOF, with the only way to break out to be check signals. So raise an exception
    # here.
    raise EOFError, "end of file reached"
  end
  return nil if char.negative? # timeout

  ungetc(char.chr(external_encoding))
  self
end