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
# File lib/canis/core/system/window.rb, line 784 def initialize win @window = win #@stack = [] end
Public Instance Methods
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
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
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
# 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
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