def handle_stdin
    @escapes ||= 0
    @ebuff ||= ''
    
    $stdin.read_nonblock(1024).each_char do |chr|
    
      if @escapes == 0
        if chr == "\e"
          @escapes = 1
        elsif chr == "\t"
          cycle_controls
        elsif chr == "\177"
          route_key :backspace
        else
          route_key chr
        end
        
      elsif @escapes == 1 && chr == '['
        @escapes = 2
      elsif @escapes == 1 && chr == 'O'
        @escapes = 5
        
      elsif @escapes == 2
        if chr == 'A'
          route_key :up
        elsif chr == 'B'
          route_key :down
        elsif chr == 'C'
          route_key :right
        elsif chr == 'D'
          route_key :left
        elsif chr == 'E'
          route_key :center
        elsif chr == 'Z'
          cycle_controls_back
        else
          @ebuff = chr
          @escapes = 3
        end
        @escapes = 0 if @escapes == 2
        
      elsif @escapes == 3
        if chr == '~' && @ebuff.to_i.to_s == @ebuff
          route_key case @ebuff.to_i
            when 2; :insert
            when 3; :delete
            when 5; :pageup
            when 6; :pagedown
            when 15; :f5
            when 17; :f6
            when 18; :f7
            when 19; :f8
            when 20; :f9
            when 24; :f12
            else; raise @ebuff.inspect
          end
        elsif @ebuff[0,1] == 'M' && @ebuff.size == 3
          @ebuff += chr
          info, x, y = @ebuff.unpack('xCCC').map{|i| i - 32}
          modifiers = []
          modifiers << :shift if info & 4 == 4
          modifiers << :meta if info & 8 == 8
          modifiers << :control if info & 16 == 16
          pane = pane_at(x, y)
          
          unless modal && modal != pane
            pane.handle_click BUTTONS[info & 71], modifiers, x, y if pane
          end
        elsif @ebuff.size > 10
          raise "long ebuff #{@ebuff.inspect} - #{chr.inspect}"
        else
          @ebuff += chr
          @escapes = 4
        end
        @escapes = 0 if @escapes == 3
        @escapes = 3 if @escapes == 4
        @ebuff = '' if @escapes == 0
        
      elsif @escapes == 5
        if chr == 'H'
          route_key :home
        elsif chr == 'F'
          route_key :end
        elsif chr == 'Q'
          route_key :f2
        elsif chr == 'R'
          route_key :f3
        elsif chr == 'S'
          route_key :f4
        else
          raise "escape 5 #{chr.inspect}"
        end
        @escapes = 0
        
      else
        @escapes = 0
      end
    end
    
    @driver.flush
    
  rescue Errno::EAGAIN
  rescue EOFError
  end
def handle_stdin
    @escapes ||= 0
    @ebuff ||= ''
    
    $stdin.read_nonblock(1024).each_char do |chr|
    
      if @escapes == 0
        if chr == "\e"
          @escapes = 1
        elsif chr == "\t"
          cycle_controls
        elsif chr == "\177"
          route_key :backspace
        else
          route_key chr
        end
        
      elsif @escapes == 1 && chr == '['
        @escapes = 2
      elsif @escapes == 1 && chr == 'O'
        @escapes = 5
        
      elsif @escapes == 2
        if chr == 'A'
          route_key :up
        elsif chr == 'B'
          route_key :down
        elsif chr == 'C'
          route_key :right
        elsif chr == 'D'
          route_key :left
        elsif chr == 'E'
          route_key :center
        elsif chr == 'Z'
          cycle_controls_back
        else
          @ebuff = chr
          @escapes = 3
        end
        @escapes = 0 if @escapes == 2
        
      elsif @escapes == 3
        if chr == '~' && @ebuff.to_i.to_s == @ebuff
          route_key case @ebuff.to_i
            when 2; :insert
            when 3; :delete
            when 5; :pageup
            when 6; :pagedown
            when 15; :f5
            when 17; :f6
            when 18; :f7
            when 19; :f8
            when 20; :f9
            when 24; :f12
            else; raise @ebuff.inspect
          end
        elsif @ebuff[0,1] == 'M' && @ebuff.size == 3
          @ebuff += chr
          info, x, y = @ebuff.unpack('xCCC').map{|i| i - 32}
          modifiers = []
          modifiers << :shift if info & 4 == 4
          modifiers << :meta if info & 8 == 8
          modifiers << :control if info & 16 == 16
          pane = pane_at(x, y)
          
          unless modal && modal != pane
            pane.handle_click BUTTONS[info & 71], modifiers, x, y if pane
          end
        elsif @ebuff.size > 10
          raise "long ebuff 
        else
          @ebuff += chr
          @escapes = 4
        end
        @escapes = 0 if @escapes == 3
        @escapes = 3 if @escapes == 4
        @ebuff = '' if @escapes == 0
        
      elsif @escapes == 5
        if chr == 'H'
          route_key :home
        elsif chr == 'F'
          route_key :end
        elsif chr == 'Q'
          route_key :f2
        elsif chr == 'R'
          route_key :f3
        elsif chr == 'S'
          route_key :f4
        else
          raise "escape 5 
        end
        @escapes = 0
        
      else
        @escapes = 0
      end
    end
    
    @driver.flush
    
  rescue Errno::EAGAIN
  rescue EOFError
  end
def handle_stdin @escapes ||= 0 @ebuff ||= '' $stdin . read_nonblock ( 1024 ) . each_char do | chr | if @escapes == 0 if chr == "\e" @escapes = 1 elsif chr == "\t" cycle_controls elsif chr == "\177" route_key :backspace else route_key chr end elsif @escapes == 1 && chr == '[' @escapes = 2 elsif @escapes == 1 && chr == 'O' @escapes = 5 elsif @escapes == 2 if chr == 'A' route_key :up elsif chr == 'B' route_key :down elsif chr == 'C' route_key :right elsif chr == 'D' route_key :left elsif chr == 'E' route_key :center elsif chr == 'Z' cycle_controls_back else @ebuff = chr @escapes = 3 end @escapes = 0 if @escapes == 2 elsif @escapes == 3 if chr == '~' && @ebuff . to_i . to_s == @ebuff route_key case @ebuff . to_i when 2 ; :insert when 3 ; :delete when 5 ; :pageup when 6 ; :pagedown when 15 ; :f5 when 17 ; :f6 when 18 ; :f7 when 19 ; :f8 when 20 ; :f9 when 24 ; :f12 else ; raise @ebuff . inspect end elsif @ebuff [ 0 , 1 ] == 'M' && @ebuff . size == 3 @ebuff += chr info , x , y = @ebuff . unpack ( 'xCCC' ) . map { | i | i - 32 } modifiers = [ ] modifiers << :shift if info & 4 == 4 modifiers << :meta if info & 8 == 8 modifiers << :control if info & 16 == 16 pane = pane_at ( x , y ) unless modal && modal != pane pane . handle_click BUTTONS [ info & 71 ] , modifiers , x , y if pane end elsif @ebuff . size > 10 raise "long ebuff #{@ebuff.inspect} - #{chr.inspect}" else @ebuff += chr @escapes = 4 end @escapes = 0 if @escapes == 3 @escapes = 3 if @escapes == 4 @ebuff = '' if @escapes == 0 elsif @escapes == 5 if chr == 'H' route_key :home elsif chr == 'F' route_key :end elsif chr == 'Q' route_key :f2 elsif chr == 'R' route_key :f3 elsif chr == 'S' route_key :f4 else raise "escape 5 #{chr.inspect}" end @escapes = 0 else @escapes = 0 end end @driver . flush rescue Errno :: EAGAIN rescue EOFError end
alt-anything => \e*KEY* (same as Esc, key)
 alt-[ would become \e[ which is an ANSI escape

 ctrl-stuff becomes weird stuff, i.e. ctrl-space = \x00, ctrl-a = \x01, ctrl-b = \x02

 super is not sent?
alt - anything = > \ e * KEY * ( same as Esc key ) alt - [ would become \ e [ which is an ANSI escape