class Canis::DefaultKeyReader

created on 2014-04-20 - 00:19 so that user can install own handler

A class that reads keys and handles function, shifted function, control, alt, and other extended keys. THis essentially consists of a method getchar which will be called by the application to get keys in a loop. Application may also call getchar to get one key in some situations.

Originally, rbcurse returned an int, but we are movign to a string, so that user can use the exact control codes he gets on the terminal using C-v and map them here.

Constants

KEY_S_F1

Public Class Methods

new(win) click to toggle source
# File lib/canis/core/system/window.rb, line 784
def initialize win
  @window = win
  #@stack = []
end

Public Instance Methods

_get_int_for_newkey(x) click to toggle source

Generate and return an int for a newkey which user has specified in yml file. We use hash, which won't allow me to derive key string in case loop user can do:

when KEY_ENTER
when 32
when $kh_int["S-F2"]
# File lib/canis/core/system/window.rb, line 1078
def _get_int_for_newkey x
  # FIXME put the declaration somewhere else maybe in window cons ???
  y = $kh_int[x]
  # when i give user the hash, he can get the string back ???
  $kh_int[y] = x unless $kh_int.key? y
  return y
end
getch() click to toggle source

return an int for the key read. this is just a single int, and is not interpreted for control or function keys. it also will return -1 when no action. You may re-implenent it or call the original one.

# File lib/canis/core/system/window.rb, line 793
def getch
  @window.getch
end
getchar() click to toggle source

NOTE: This is a reworked and much simpler version of the original getchar which was taken from manveru's codebase. This also currently returns the keycode as int while placing the char version in a global $key_chr. Until we are ready to return a char, we use this.

FIXME : I have tried very hard to revert to nodelay but it does not seem to have an effect when ESC is pressed. Somewhere, there is a delay when ESC is pressed. I not longer wish to provide the feature of pressing ESC and then a key to be evaluated as Meta-key. This slows down when a user just presses ESC.

Read a char from the window (from user) and returns int code. In some cases, such as codes entered in the $kh hash, we do not yet have a keycode defined so we return 9999 and the user can access $key_chr.

NOTE: Do not convert to string, that is doing two things. Allow user to convert if required using `key_tos`

# File lib/canis/core/system/window.rb, line 844
    def getchar
      $key_chr = nil
        c = nil
        while true
          c = self.getch
          break if c != -1
        end
    
        cn = c
        $key_int = c
        # handle control codes 0 to 127 but not escape
        if cn >= 0 && cn < 128 && cn != 27
          #$key_chr = key_tos(c)
          return c
        end
        
        # if escape then get into a loop and keep checking till -1 or another escape
        #
        if c == 27
          buff=c.chr
          # if there is another escape coming through then 2 keys were pressed so
          # evaluate upon hitting an escape
          # NOTE : i think only if ESc is followed by [ should be keep collectig
          # otherwise the next char should evaluate. cases like F1 are already being sent in as high integer codes
          while true
            #$log.debug " #{Time.now.to_f} inside LOOP before getch "
            # This getch seems to take enough time not to return a -1 for almost a second
            # even if nodelay is true ??? XXX
            FFI::NCurses.set_escdelay(5)
            k = self.getch
            #$log.debug "elapsed #{elapsed} millis  inside LOOP AFTER getch #{k} (#{elapsed1})"
            $log.debug "inside LOOP AFTER getch #{k} "

            if k == 27
              # seems like two Meta keys pressed in quick succession without chance for -1 to kick in
              # but this still does not catch meta char followed by single char. M-za , it does.
              if $esc_esc
                if buff == 27.chr
                  $key_chr = "<ESC-ESC>"
                  return 2727
                else
                  alert "buff is #{buff}"
                end
              end
              $log.debug "  1251 before evaluate "
              x = _evaluate_buff buff
              # return ESC so it can be interpreted again.
              @window.ungetch k
              $key_chr = x if x
              return $key_int if x
              $log.warn "getchar: window.rb 1200 Found no mapping for #{buff} "
              $key_chr = buff
              return $key_int
              #return buff # otherwise caught in loop ???
            elsif k > -1
              # FIXME next lne crashes if M-C-h pressed which gives 263
              if k > 255
                $log.warn "getchar: window.rb 1247 Found no mapping for #{buff} #{k} "
                $key_int = k + 128
                return $key_int
                # this contains ESc followed by a high number
=begin
                ka = key_tos(k)
                if ka
                  $key_chr = "<M-" + ka[1..-1]
                  $key_int = k + 128
                  return $key_int
                else
                  $key_chr = "UNKNOWN: Meta + #{k}"
                  return 9999
                end
=end
              end

              buff += k.chr
              # this is an alt/meta code. All other complex codes seem to have a [ after the escape
              # so we will keep accumulating them.
              # NOTE this still means that user can press Alt-[ and some letter in quick succession
              # and it will accumulate rather than be interpreted as M-[.
              #
              if buff.length == 2 and k == 79
                # this is Alt-O and can be a F key in some terms like xterm-color
              elsif buff.length == 2 and k.chr != '['
                x = _evaluate_buff buff
        
                $key_chr = x
                return $key_int if x
              end
              #$log.debug "XXX:  getchar adding #{k}, #{k.chr} to buff #{buff} "
            else
              #$log.debug "  GOT -1 in escape "
              # it is -1 so evaluate
              x = _evaluate_buff buff
              $key_chr = x if x
              return $key_int if x
              $log.warn "getchar: window.rb 1256 Found no mapping for #{buff} "
              $key_chr = buff
              return $key_int
            end
          end
        end
        
        # what if keyname does not return anything
        if c > 127
          #$log.info "xxxgetchar: window.rb sending #{c} "
=begin
          ch =  FFI::NCurses::keyname(c) 
          # remove those ugly brackets around function keys
          if ch && ch[-1]==')'
            ch = ch.gsub(/[()]/,'')
          end
          if ch && ch.index("KEY_")
            ch = ch.gsub(/KEY_/,'')
          end
          ch = "<#{ch}>" if ch
          #return ch if ch
          $key_chr = ch if ch
          $key_chr = "UNKNOWN:#{c}" unless ch
          $log.warn "getchar: window.rb 1234 Found no mapping for #{c} " unless ch
=end
          #$key_chr = key_tos(ch)
          return c
        end
        if c
          #$key_chr =  c.chr
          return c 
        end
    end
getchar_as_char() click to toggle source
# File lib/canis/core/system/window.rb, line 974
def getchar_as_char
  $key_int = getchar
  $key_chr = key_tos( $key_int )
  return $key_chr
end

Private Instance Methods

_evaluate_buff(buff) click to toggle source

check buffer if some key mapped in global kh for this Otherwise if it is 2 keys then it is a Meta key Can return nil if no mapping @return [String] string code for key (since it is mostly from $kh. Also sets, $key_int

# File lib/canis/core/system/window.rb, line 1090
def _evaluate_buff buff
  if buff == 27.chr
    $key_int = 27
    #$escend = Time.now.to_f
    #elapsed = ($escend - $escstart)*1000
    #$log.debug " #{elapsed} evaluated to ESC"
    $key_chr = "<ESC>"
    return $key_chr
  end
  x=$kh[buff]
  if x
    $key_int = 9999
    $key_int = _get_int_for_newkey(x)
    $key_cache[$key_int] = x unless $key_cache.key? $key_int
    # FIXME currently 9999 signifies unknown key, but since this is derived from a user list
    #   we could have some dummy number being passed or set by user too.
    return "<#{x}>"
  end
  #$log.debug "XXX:  getchar returning with  #{buff}"
  if buff.size == 2
    ## possibly a meta/alt char
    k = buff[-1]
    $key_int = 128 + k.ord
    return key_tos( $key_int )
  end
  $key_int = 99999
  nil
end