class OTerm::Listener
Attributes
buf[RW]
con[RW]
debug[RW]
executor[RW]
history[RW]
hp[RW]
out[RW]
server[RW]
Public Class Methods
new(server, con, executor)
click to toggle source
# File lib/oterm/listener.rb, line 15 def initialize(server, con, executor) @debug = server.debug() @server = server @con = con @executor = executor @buf = '' @kill_buf = nil @history = [] @hp = 0 @out = Output.new(con) @col = 0 @echo = false @done = false greeting = executor.greeting() @out.pl(greeting) unless greeting.nil? # initiate negotiations for single character mode and no echo @out.p(Telnet.msg(Telnet::DO, Telnet::SGA) + Telnet.msg(Telnet::DO, Telnet::ECHO)) out.prompt() until @done line = con.recv(100) begin len = line.size() break if 0 == len if @debug line.each_byte { |x| print("#{x} ") } plain = line.gsub(/./) { |c| c.ord < 32 || 127 <= c.ord ? '*' : c } puts "[#{line.size()}] #{plain}" end # determine input type (telnet command, char mode, line mode) o0 = line[0].ord() case o0 when 255 # telnet command process_telnet_cmd(line) when 27 # escape, vt100 sequence vt100_cmd(line) when 13 # new line exec_cmd(@buf) when 0..12, 14..26, 28..31, 127 # other control character process_ctrl_cmd(o0) else if 1 == len || (2 == len && "\000" == line[1]) # single char mode @hp = 0 insert(line[0]) else # line mode exec_cmd(line) end end rescue Exception => e puts "#{e.class}: #{e.message}" e.backtrace.each { |bline| puts ' ' + bline } end end end
Public Instance Methods
close()
click to toggle source
# File lib/oterm/listener.rb, line 72 def close() @done = true end
delete_char()
click to toggle source
# File lib/oterm/listener.rb, line 258 def delete_char() return if 0 == @col || 0 == @buf.size if @buf.size <= @col @buf.chop!() @out.p("\x08 \x08") else @buf = @buf[0...@col - 1] + @buf[@col..-1] @out.p("\r") @out.prompt() @out.p(@buf) @out.p(" \r") @out.prompt() @out.p(@buf[0...@col - 1]) end @col -= 1 end
exec_cmd(cmd)
click to toggle source
# File lib/oterm/listener.rb, line 122 def exec_cmd(cmd) @hp = 0 cmd.strip!() if 0 == cmd.size() @out.pl() @out.prompt() @col = 0 return end @buf = "" @out.pl() @history << cmd if 0 < cmd.size() && (0 == @history.size() || @history[-1] != cmd) executor.execute(cmd, self) @out.prompt() @col = 0 end
history_back()
click to toggle source
# File lib/oterm/listener.rb, line 210 def history_back() if @hp < @history.size() @hp += 1 blen = @buf.size() @buf = @history[-@hp] update_cmd(blen) end end
history_forward()
click to toggle source
# File lib/oterm/listener.rb, line 219 def history_forward() if 0 < @hp && @hp <= @history.size() @hp -= 1 blen = @buf.size() if 0 == @hp @buf = '' else @buf = @history[-@hp] end update_cmd(blen) end end
insert(str)
click to toggle source
# File lib/oterm/listener.rb, line 232 def insert(str) # TBD be smarter with vt100 if 0 == @col @buf = str + @buf @out.p("\r") @out.prompt() @out.p(@buf) @out.p("\r") @out.prompt() @out.p(@buf[0...str.size]) elsif @buf.size <= @col @buf << str @out.pc(str) @col = @buf.size else @buf = @buf[0...@col] + str + @buf[@col..-1] @out.p("\r") @out.prompt() @out.p(@buf) @out.p("\r") @out.prompt() @out.p(@buf[0...@col + str.size]) end @col += str.size end
move_col(dif)
click to toggle source
# File lib/oterm/listener.rb, line 193 def move_col(dif) if 0 > dif while 0 > dif && 0 < @col @col -= 1 @out.p("\b") dif += 1 end else max = @buf.size while 0 < dif && @col < max @out.p(@buf[@col]) @col += 1 dif -= 1 end end end
process_ctrl_cmd(o)
click to toggle source
# File lib/oterm/listener.rb, line 139 def process_ctrl_cmd(o) case o when 1 # ^a move_col(-@col) when 2 # ^b move_col(-1) when 4 # ^d @hp = 0 if @col < @buf.size @col += 1 delete_char() end when 5 # ^e move_col(@buf.size() - @col) when 6 # ^f move_col(1) when 8, 127 # backspace or delete @hp = 0 delete_char() when 9 # tab @hp = 0 @executor.tab(@buf, self) when 11 # ^k @hp = 0 if @col < @buf.size() @kill_buf = @buf[@col..-1] blen = @buf.size() @buf = @buf[0...@col] update_cmd(blen) end when 14 # ^n history_forward() when 16 # ^p history_back() when 21 # ^u @hp -= 1 @buf = '' when 25 # ^y insert(@kill_buf) end end
process_telnet_cmd(line)
click to toggle source
# File lib/oterm/listener.rb, line 76 def process_telnet_cmd(line) reply = '' Telnet.parse(line).each do |v,f| case f when Telnet::ECHO case v when Telnet::WILL @echo = false reply += Telnet.msg(Telnet::WONT, f) when Telnet::WONT @echo = true reply += Telnet.msg(Telnet::WILL, f) end when Telnet::SGA case v when Telnet::WILL reply += Telnet.msg(Telnet::WILL, f) when Telnet::WONT reply += Telnet.msg(Telnet::WONT, f) end end end if 0 < reply.size @con.print(reply) else # Done negotiating with telnet. Initiate negotiation for vt100 ANSI support. @out.identify() end end
update_cmd(blen)
click to toggle source
# File lib/oterm/listener.rb, line 181 def update_cmd(blen) @out.cr() @out.prompt() @out.p(@buf) # erase to end of line and come back if @buf.size() < blen dif = blen - @buf.size() @out.p(' ' * dif + "\b" * dif) end @col = @buf.size end
vt100_cmd(line)
click to toggle source
# File lib/oterm/listener.rb, line 106 def vt100_cmd(line) # Possible arrow key. if 3 == line.size() && '[' == line[1] case line[2] when 'A' # up arrow history_back() when 'B' # down arrow history_forward() when 'C' # right arrow move_col(1) when 'D' # left arrow move_col(-1) end end end