module Canis::Utils

Public Instance Methods

ORIG_process_key(keycode, object, window) click to toggle source

e.g. process_key ch, self returns UNHANDLED if no block for it after form handles basic keys, it gives unhandled key to current field, if current field returns unhandled, then it checks this map. added 2009-01-06 19:13 since widgets need to handle keys properly added 2009-01-18 12:58 returns ret val of blk.call so that if block does not handle, the key can still be handled e.g. table last row, last col does not handle, so it will auto go to next field

2010-02-24 13:45 handles 2 key combinations, copied from Form, must be identical in logic
except maybe for window pointer. TODO not tested
# File lib/canis/core/widgets/rwidget.rb, line 855
def ORIG_process_key keycode, object, window
  return :UNHANDLED if @_key_map.nil?
  blk = @_key_map[keycode]
  $log.debug "XXX:  _process key keycode #{keycode} #{blk.class}, #{self.class} "
  return :UNHANDLED if blk.nil?
  if blk.is_a? OrderedHash 
    #Ncurses::nodelay(window.get_window, bf = false)
    # if you set nodelay in ncurses.rb then this will not
    # wait for second key press, so you then must either make it blocking
    # here, or set a wtimeout here.
    #
    # This is since i have removed timeout globally since resize was happeing
    # after a keypress. maybe we can revert to timeout and not worry about resize so much
    Ncurses::wtimeout(window.get_window, 500) # will wait a second on wgetch so we can get gg and qq
    ch = window.getch
    # we should not reset here, resetting should happen in getch itself so it is consistent
    #Ncurses::nowtimeout(window.get_window, true)

    $log.debug " process_key: got #{keycode} , #{ch} "
    # next line ignores function keys etc. C-x F1, thus commented 255 2012-01-11
    if ch < 0 #|| ch > 255
      return nil
    end
    #yn = ch.chr
    blk1 = blk[ch]
    # FIXME we are only returning the second key, what if form
    # has mapped first and second combo. We should unget keycode and ch. 2011-12-23
    # check this out first.
    window.ungetch(ch) if blk1.nil? # trying  2011-09-27
    return :UNHANDLED if blk1.nil? # changed nil to unhandled 2011-09-27
    $log.debug " process_key: found block for #{keycode} , #{ch} "
    blk = blk1
  end
  if blk.is_a? Symbol
    if respond_to? blk
      return send(blk, *@_key_args[keycode])
    else
      ## 2013-03-05 - 19:50 why the hell is there an alert here, nowhere else
      alert "This ( #{self.class} ) does not respond to #{blk.to_s} [PROCESS-KEY]"
      # added 2013-03-05 - 19:50 so called can know
      return :UNHANDLED 
    end
  else
    $log.debug "rwidget BLOCK called _process_key " if $log.debug? 
    return blk.call object,  *@_key_args[keycode]
  end
  #0
end
ORIGbind_key(keycode, *args, &blk) click to toggle source

this is the bindkey that has been working all along. now i am trying a new approach that does not use a hash inside but keeps on key. so it can be manip easily be user

# File lib/canis/core/widgets/rwidget.rb, line 396
def ORIGbind_key keycode, *args, &blk # -- {{{
  #$log.debug " #{@name} bind_key received #{keycode} "
  @_key_map ||= {}
  #
  # added on 2011-12-4 so we can pass a description for a key and print it
  # The first argument may be a string, it will not be removed
  # so existing programs will remain as is.
  @key_label ||= {}
  if args[0].is_a?(String) || args[0].is_a?(Symbol)
    @key_label[keycode] = args[0] 
  else
    @key_label[keycode] = :unknown
  end

  if !block_given?
    blk = args.pop
    raise "If block not passed, last arg should be a method symbol" if !blk.is_a? Symbol
    #$log.debug " #{@name} bind_key received a symbol #{blk} "
  end
  case keycode
  when String
    # single assignment
    keycode = keycode.getbyte(0) #if keycode.class==String ##    1.9 2009-10-05 19:40
    #$log.debug " #{name} Widg String called bind_key BIND #{keycode}, #{keycode_tos(keycode)}  "
    #$log.debug " assigning #{keycode}  " if $log.debug?
    @_key_map[keycode] = blk
  when Array
    # double assignment
    # for starters lets try with 2 keys only
    raise "A one key array will not work. Pass without array" if keycode.size == 1
    a0 = keycode[0]
    a0 = keycode[0].getbyte(0) if keycode[0].class == String
    a1 = keycode[1]
    a1 = keycode[1].getbyte(0) if keycode[1].class == String
    @_key_map[a0] ||= OrderedHash.new
    #$log.debug " assigning #{keycode} , A0 #{a0} , A1 #{a1} " if $log.debug?
    @_key_map[a0][a1] = blk
    #$log.debug " XX assigning #{keycode} to  _key_map " if $log.debug?
  else
    #$log.debug " assigning #{keycode} to  _key_map " if $log.debug?
    @_key_map[keycode] = blk
  end
  @_key_args ||= {}
  @_key_args[keycode] = args

end
ORIGkeycode_tos(keycode) click to toggle source

needs to move to a keystroke class please use these only for printing or debugging, not comparing I could soon return symbols instead 2010-09-07 14:14 @deprecated Please move to window.key_tos

# File lib/canis/core/widgets/rwidget.rb, line 250
def ORIGkeycode_tos keycode # {{{
  $log.warn "XXX:  keycode_tos please move to window.key_tos"
  case keycode
  when 33..126
    return keycode.chr
  when ?\C-a.getbyte(0) .. ?\C-z.getbyte(0)
    return "C-" + (keycode + ?a.getbyte(0) -1).chr 
  when ?\M-A.getbyte(0)..?\M-z.getbyte(0)
    return "M-"+ (keycode - 128).chr
  when ?\M-\C-A.getbyte(0)..?\M-\C-Z.getbyte(0)
    return "M-C-"+ (keycode - 32).chr
  when ?\M-0.getbyte(0)..?\M-9.getbyte(0)
    return "M-"+ (keycode-?\M-0.getbyte(0)).to_s
  when 32
    return "space" # changed to lowercase so consistent
  when 27
    return "esc" # changed to lowercase so consistent
  when ?\C-].getbyte(0)
    return "C-]"
  when 258
    return "down"
  when 259
    return "up"
  when 260
    return "left"
  when 261
    return "right"
  when FFI::NCurses::KEY_F1..FFI::NCurses::KEY_F12
    return "F"+ (keycode-264).to_s
  when 330
    return "delete"
  when 127
    return "bs"
  when 353
    return "btab"
  when 481
    return "M-S-tab"
  when 393..402
    return "M-F"+ (keycode-392).to_s
  when 0
    return "C-space" 
  when 160
    return "M-space" # at least on OSX Leopard now (don't remember this working on PPC)
  when C_LEFT
    return "C-left"
  when C_RIGHT
    return "C-right"
  when S_F9
    return "S_F9"
  else
    others=[?\M--,?\M-+,?\M-=,?\M-',?\M-",?\M-;,?\M-:,?\M-\,, ?\M-.,?\M-<,?\M->,?\M-?,?\M-/,?\M-!]
    others.collect! {|x| x.getbyte(0)  }  ## added 2009-10-04 14:25 for 1.9
    s_others=%w[M-- M-+ M-= M-' M-"   M-;   M-:   M-, M-. M-< M-> M-? M-/ M-!]
    if others.include? keycode
      index = others.index keycode
      return s_others[index]
    end
    # all else failed
    return keycode.to_s
  end
end
_process_key(keycode, object, window) click to toggle source

This the new one which does not use orderedhash, it uses an array for multiple assignments and falls back to a single assignment if multiple fails. e.g. process_key ch, self returns UNHANDLED if no block for it after form handles basic keys, it gives unhandled key to current field, if current field returns unhandled, then it checks this map. added 2009-01-06 19:13 since widgets need to handle keys properly added 2009-01-18 12:58 returns ret val of blk.call so that if block does not handle, the key can still be handled e.g. table last row, last col does not handle, so it will auto go to next field

2010-02-24 13:45 handles 2 key combinations, copied from Form, must be identical in logic
except maybe for window pointer.
# File lib/canis/core/widgets/rwidget.rb, line 772
        def _process_key keycode, object, window
          return :UNHANDLED if @_key_map.nil?
          chr = nil
          ch = keycode
          if ch > 0 and ch < 256
            chr = ch.chr
          end
          blk = @_key_map[keycode]
          # i am scrappaing this since i am once again complicating too much
=begin
          # if blk then we found an exact match which supercedes any ranges, arrays and regexes
          unless blk
            @_key_map.each_pair do |k,p|
              $log.debug "KKK:  processing key #{ch}  #{chr} "
              if (k == ch || k == chr)
                $log.debug "KKK:  checking match == #{k}: #{ch}  #{chr} "
                # compare both int key and chr
                $log.debug "KKK:  found match 1 #{ch}  #{chr} "
                #p.call(self, ch)
                #return 0
                blk = p
                break
              elsif k.respond_to? :include?
                $log.debug "KKK:  checking match include #{k}: #{ch}  #{chr} "
                # this bombs if its a String and we check for include of a ch.
                if !k.is_a?( String ) && (k.include?( ch ) || k.include?(chr))
                  $log.debug "KKK:  found match include #{ch}  #{chr} "
                  #p.call(self, ch)
                  #return 0
                  blk = p
                  break
                end
              elsif k.is_a? Regexp
                if k.match(chr)
                  $log.debug "KKK:  found match regex #{ch}  #{chr} "
                  #p.call(self, ch)
                  #return 0
                  blk = p
                  break
                end
              end
            end
          end
=end
          # blk either has a proc or is nil
          # we still need to check for a complex map.  if none, then execute simple map.
          ret = check_composite_mapping(ch, window)
          $log.debug "  composite returned (#{ret}) for #{ch} "
          if !ret
            return execute_mapping(blk, ch, object) if blk
          end
          return execute_mapping(ret, ch, object) if ret
          return :UNHANDLED
        end
bind_composite_mapping(key, *args, action) click to toggle source
# File lib/canis/core/widgets/rwidget.rb, line 528
def bind_composite_mapping key, *args, action
  @_key_composite_map ||= Hash.new {|hash, key| hash[key] = MapNode.new }
  if key.is_a? String
    n = @_key_composite_map[key]
    n.action = action
  else
    mp = @_key_composite_map
    n = nil
    key.each do |e|
      n = mp[e]
      mp = n.map
    end
    n.action = action
  end
  val = @_key_composite_map.fetch(key[0], nil)
  $log.debug " composite contains #{key} : #{val} "
end
bind_key(keycode, *args, &blk) click to toggle source

A new attempt at a flat hash 2014-05-06 - 00:16 bind an action to a key, required if you create a button which has a hotkey or a field to be focussed on a key, or any other user defined action based on key e.g. bind_key ?C-x, object, block added 2009-01-06 19:13 since widgets need to handle keys properly

2010-02-24 12:43 trying to take in multiple key bindings, TODO unbind
TODO add symbol so easy to map from config file or mapping file

Ideally i want to also allow a regex and array/range to be used as a key 
However, then how do i do multiple assignments which use an array.

Currently the only difference is that there is no hash inside the value,
key can be an int, or array of ints (for multiple keycode like qq or gg).
# File lib/canis/core/widgets/rwidget.rb, line 457
def bind_key keycode, *args, &blk
  #$log.debug " #{@name} bind_key received #{keycode} "
  @_key_map ||= {}
  #
  # added on 2011-12-4 so we can pass a description for a key and print it
  # The first argument may be a string, it will not be removed
  # so existing programs will remain as is.
  @key_label ||= {}
  if args[0].is_a?(String) || args[0].is_a?(Symbol)
    @key_label[keycode] = args[0] 
  else
    @key_label[keycode] = :unknown
  end

  if !block_given?
    blk = args.pop
    raise "If block not passed, last arg should be a method symbol" if !blk.is_a? Symbol
    #$log.debug " #{@name} bind_key received a symbol #{blk} "
  end
  case keycode
  when String
    # single assignment
    keycode = keycode.getbyte(0) 
  when Array
    # double assignment
    # this means that all these keys have to be pressed in succession for this block, like "gg" or "C-x C-c"
    raise "A one key array will not work. Pass without array" if keycode.size == 1
    ee = []
    keycode.each do |e| 
      e = e.getbyte(0) if e.is_a? String
      ee << e
    end
    bind_composite_mapping ee, args, blk
    return self
    #@_key_map[a0] ||= OrderedHash.new
    #@_key_map[a0][a1] = blk
    #$log.debug " XX assigning #{keycode} to  _key_map " if $log.debug?
  else
    $log.debug " assigning #{keycode} to  _key_map for #{self.class}, #{@name}" if $log.debug? 
  end
  @_key_map[keycode] = blk
  @_key_args ||= {}
  @_key_args[keycode] = args
  self
end
bind_keys(keycodes, *args, &blk) click to toggle source
# File lib/canis/core/widgets/rwidget.rb, line 754
def bind_keys keycodes, *args, &blk
  keycodes.each { |k| bind_key k, *args, &blk }
end
check_composite_mapping(key, window) click to toggle source
# File lib/canis/core/widgets/rwidget.rb, line 545
def check_composite_mapping key, window
  #$log.debug  "inside check with #{key} "
  return nil if !@_key_composite_map
  return nil if !@_key_composite_map.key? key
  $log.debug "  composite has #{key} "

  # we have a match and need to loop
  mp = @_key_composite_map
  n = nil
  actions = []
  unconsumed = []
  e = key
  while true

    # we traverse each key and get action of final.
    # However, if at any level there is a failure, we need to go back to previous action
    # and push the other keys back so they can be again processed.
    if e.nil? or e == -1
      #puts "e is nil TODO "
      # TODO
      #$log.debug "  -1  push #{unconsumed} returning: #{actions.last}"
      $log.debug "  -1  returning: #{actions.last}" 
      # is there a reason we are pushing here ?
      #unconsumed.each {|e| window.ungetch(e)}
      return actions.last 
    else
      $log.debug  " in loop with #{e} "
      unconsumed << e
      n = mp.fetch(e, nil)
      $log.debug  " got node #{n} with #{e} "
      # instead of just nil, we need to go back up, but since not recursive ...
      #return nil unless n
      unless n
        # testing shift otherwise it seems current key evaluated twice 2014-08-17
        unconsumed.shift
        $log.debug  "push unconsumed:#{unconsumed} " unless n
        unconsumed.each {|e| window.ungetch(e)} unless n
        return actions.last unless n
      end
      mp = n.map
      # there are no more keys, only an action
      if mp.nil? or mp.empty?
        $log.debug "  mp is nil or empty returning action: #{n.action}"
        #puts "mp is nil or empty"
        return n.action
      end
      # we could have consumed keys at this point
      actions << n.action if n.action
      unconsumed.clear if n.action
      #e = window.getchar
      Ncurses::wtimeout(window.get_window, 500) # will wait a second on wgetch so we can get gg and qq
      e = window.getch
      Ncurses::nowtimeout(window.get_window, true)
      # e can return -1 if timedout
      $log.debug "  getch got #{e}"
    end
  end
end
create_logger(path) click to toggle source

create a logger giving a path.

# File lib/canis/core/widgets/rwidget.rb, line 909
def create_logger path
  #path = File.join(ENV["LOGDIR"] || "./" ,"canis14.log")
  _path   = File.open(path, File::WRONLY|File::TRUNC|File::CREAT) 
  logg = Logger.new(_path)
  raise "Could not create logger: #{path}" unless logg
  # if not set, will default to 0 which is debug. Other values are 1 - info, 2 - warn
  logg.level = ENV["CANIS_LOG_LEVEL"].to_i
  colors = Ncurses.COLORS
  logg.info "START #{colors} colors  -- #{$0} win: #{@window} : log level: #{logg.level}. To change log level, increase CANIS_LOG_LEVEL in your environment to 1 or 2 or 3."
  return logg
end
define_key(_symbol, _keycode, *args, &blk) click to toggle source

Define a key for a prefix command. @see define_prefix_command

Example:

@form.define_key(:csmap, "s", 'specification') { specification }
@form.define_key(:csmap, "r", 'refresh', :refresh )

@param _symbol prefix command symbol (already created using define_prefix_command @param keycode key within the prefix command for given block or action @param args arguments to be passed to block. The first is a description.

The second may be a symbol for a method to be executed (if block not given).

@param block action to be executed on pressing keycode

# File lib/canis/core/widgets/rwidget.rb, line 686
def define_key _symbol, _keycode, *args, &blk
  #_symbol = @symbol
  h = $rb_prefix_map[_symbol]
  raise ArgumentError, "No such keymap #{_symbol} defined. Use define_prefix_command." unless h
  _keycode = _keycode[0].getbyte(0) if _keycode[0].class == String
  arg = args.shift
  if arg.is_a? String
    desc = arg
    arg = args.shift
  elsif arg.is_a? Symbol
    # its a symbol
    desc = arg.to_s
  elsif arg.nil?
    desc = "unknown"
  else
    raise ArgumentError, "Don't know how to handle #{arg.class} in PrefixManager"
  end
  # 2013-03-20 - 18:45 187compat gave error in 187 cannot convert string to int
  #@descriptions ||= []
  @descriptions ||= {}
  @descriptions[_keycode] = desc

  if !block_given?
    blk = arg
  end
  h[_keycode] = blk
end
define_prefix_command(_name, config={}) click to toggle source

define a key with sub-keys to which commands are attached. e.g. to attach commands to C-x a , C-x b, C-x x etc.

Example

We create a map named :csmap and attach various commands to it on different keys. At this point, there is no main key that triggers it. Any key can be made the prefix command later. In this case, C-s was bound to the map. This is more organized that creating separate maps for C-s r, C-s s etc which then cannot be changed or customized by user.

@form.define_prefix_command :csmap, :scope => self
@form.define_key(:csmap, "r", 'refresh', :refresh )
@form.define_key(:csmap, "s", 'specification') { specification }
@form.bind_key ?\C-s, :csmap
# File lib/canis/core/widgets/rwidget.rb, line 631
def define_prefix_command _name, config={} #_mapvar=nil, _prompt=nil
  $rb_prefix_map ||= {}
  _name = _name.to_sym unless _name.is_a? Symbol
  $rb_prefix_map[_name] ||= {}
  scope = config[:scope] || self
  $rb_prefix_map[_name][:scope] = scope


  # create a variable by name _name
  # create a method by same name to use
  # Don;t let this happen more than once
  instance_eval %{
def #{_name.to_s} *args
  #$log.debug "XXX:  came inside #{_name} "
   h = $rb_prefix_map["#{_name}".to_sym]
   raise "No prefix_map named #{_name}, #{$rb_prefix_map.keys} " unless h
   ch = @window.getchar
   if ch
    if ch == KEY_F1
      text =  ["Options are: "]
      h.keys.each { |e| c = keycode_tos(e); text << c + " " + @descriptions[e]  }
      textdialog text, :title => "#{_name} key bindings"
      return
    end
      res =  h[ch]
      if res.is_a? Proc
        res.call
      elsif res.is_a? Symbol
         scope = h[:scope]
         scope.send(res)
      elsif res.nil?
        Ncurses.beep
         return :UNHANDLED
      end
   else
         :UNHANDLED
   end
end
  }
  return _name
end
execute_mapping(blk, keycode, object) click to toggle source
# File lib/canis/core/widgets/rwidget.rb, line 827
def execute_mapping blk, keycode, object

  if blk.is_a? Symbol
    if respond_to? blk
      $log.debug "  RESPONDING TO BLCK #{keycode}"
      return send(blk, *@_key_args[keycode])
    else
      ## 2013-03-05 - 19:50 why the hell is there an alert here, nowhere else
      alert "This ( #{self.class} ) does not respond to #{blk.to_s} [PROCESS-KEY]"
      # added 2013-03-05 - 19:50 so called can know
      return :UNHANDLED 
    end
  else
    $log.debug "rwidget BLOCK called _process_key #{keycode} " if $log.debug? 
    return blk.call object,  *@_key_args[keycode]
  end
end
get_attrib(str) click to toggle source

convert a string to integer attribute FIXME: what if user wishes to OR two attribs, this will give error @param [String] e.g. reverse bold normal underline

if a Integer is passed, it is returned as is assuming to be 
an attrib
# File lib/canis/core/widgets/rwidget.rb, line 334
def get_attrib str
  return FFI::NCurses::A_NORMAL unless str
  # next line allows us to do a one time conversion and keep the value
  #  in the same variable
  if str.is_a? Integer
    if [
      FFI::NCurses::A_BOLD,
      FFI::NCurses::A_REVERSE,    
      FFI::NCurses::A_NORMAL,
      FFI::NCurses::A_UNDERLINE,
      FFI::NCurses::A_STANDOUT,    
      FFI::NCurses::A_DIM,    
      FFI::NCurses::A_BOLD | FFI::NCurses::A_REVERSE,    
      FFI::NCurses::A_BOLD | FFI::NCurses::A_UNDERLINE,    
      FFI::NCurses::A_REVERSE | FFI::NCurses::A_UNDERLINE,    
      FFI::NCurses::A_BLINK
    ].include? str
    return str
    else
      raise ArgumentError, "get_attrib got a wrong value: #{str} "
    end
  end


  att = nil
  str = str.downcase.to_sym if str.is_a? String
  case str #.to_s.downcase
  when :bold
    att = FFI::NCurses::A_BOLD
  when :reverse
    att = FFI::NCurses::A_REVERSE    
  when :normal
    att = FFI::NCurses::A_NORMAL
  when :underline
    att = FFI::NCurses::A_UNDERLINE
  when :standout
    att = FFI::NCurses::A_STANDOUT
  when :bold_reverse
    att = FFI::NCurses::A_BOLD | FFI::NCurses::A_REVERSE
  when :bold_underline
    att = FFI::NCurses::A_BOLD | FFI::NCurses::A_UNDERLINE
  when :dim
    att = FFI::NCurses::A_DIM    
  when :blink
    att = FFI::NCurses::A_BLINK    # unlikely to work
  else
    att = FFI::NCurses::A_NORMAL
  end
  return att
end
get_color(default=$datacolor, color=color(), bgcolor=bgcolor()) click to toggle source

if passed a string in second or third param, will create a color and return, else it will return default color Use this in order to create a color pair with the colors provided, however, if user has not provided, use supplied default. @param [Integer] color_pair created by ncurses @param [Symbol] color name such as white black cyan magenta red green yellow @param [Symbol] bgcolor name such as white black cyan magenta red green yellow @example get_color $promptcolor, :white, :cyan

# File lib/canis/core/widgets/rwidget.rb, line 321
def get_color default=$datacolor, color=color(), bgcolor=bgcolor()
  return default if color.nil? || bgcolor.nil?
  #raise ArgumentError, "Color not valid: #{color}: #{ColorMap.colors} " if !ColorMap.is_color? color
  #raise ArgumentError, "Bgolor not valid: #{bgcolor} : #{ColorMap.colors} " if !ColorMap.is_color? bgcolor
  acolor = ColorMap.get_color(color, bgcolor)
  return acolor
end
key(ch) click to toggle source

convenience func to get int value of a key added 2014-05-05 instead of ?C-a.getbyte(0) use key(?C-a) or key(?a) or key(?M-x)

# File lib/canis/core/widgets/rwidget.rb, line 175
def key ch
  ch.getbyte(0)
end
key_tos(ch) click to toggle source

returns a string representation of a given int keycode @param [Integer] keycode read by window

In some case, such as Meta/Alt codes, the window reads two ints, but still we are using the param
as the value returned by ?\M-a.getbyte(0) and such, which is typically 128 + key

@return [String] a string representation which is what is to be used when binding a key to an

action or Proc. This is close to what vimrc recognizes such as <CR> <C-a> a-zA-z0-9 <SPACE>
Hopefully it should be identical to what vim recognizes in the map command.
If the key is not known to this program it returns "UNKNOWN:key" which means this program
needs to take care of that combination. FIXME some numbers are missing in between.

NOTE do we really need to cache everything ? Only the computed ones should be cached ?

# File lib/canis/core/widgets/rwidget.rb, line 188
def key_tos ch # -- {{{
  x = $key_cache[ch]
  return x if x
  chr = case ch
        when 10,13 , KEY_ENTER
          "<CR>"
        when 9 
          "<TAB>"
        when 0 
          "<C-@>"
        when 27
          "<ESC>"
        when 31
          "<C-/>"
        when 1..30
          x= ch + 96
          "<C-#{x.chr}>"
        when 32 
          "<SPACE>"
        when 41
          "<M-CR>"
        when 33..126
          ch.chr
        when 127,263 
          "<BACKSPACE>"
        when 128..154
          x = ch - 128
          #"<M-C-#{x.chr}>"
          xx = key_tos(x).gsub(/[<>]/,"")
          "<M-#{xx}>"
        when 160..255
          x = ch - 128
          xx = key_tos(x).gsub(/[<>]/,"")
          "<M-#{xx}>"
        when 255
          "<M-BACKSPACE>"
        when 2727
          "<ESC-ESC>"
        else

          chs =  FFI::NCurses::keyname(ch) 
          # remove those ugly brackets around function keys
          if chs && chs[-1]==')'
            chs = chs.gsub(/[()]/,'')
          end
          if chs
            chs = chs.gsub("KEY_","")
            "<#{chs}>"
          else
            "UNKNOWN:#{ch}"
          end
        end
  $key_cache[ch] = chr
  return chr
end
Also aliased as: keycode_tos
keycode_tos(ch)

only for a short while till we weed it out.

Alias for: key_tos
print_key_bindings(*args) click to toggle source

Display key bindings for current widget and form in dialog

repeatm() { || ... } click to toggle source
repeats the given action based on how value of universal numerica argument

+ set using the C-u key. Or in vim-mode using numeric keys

# File lib/canis/core/widgets/rwidget.rb, line 387
def repeatm
  $inside_multiplier_action = true
  _multiplier = ( ($multiplier.nil? || $multiplier == 0) ? 1 : $multiplier )
  _multiplier.times { yield }
  $multiplier = 0
  $inside_multiplier_action = false
end
run_command(cmd) click to toggle source

executes given command and displays in viewer @param [String] unix command, e.g., git -st

# File lib/canis/core/include/appmethods.rb, line 65
def run_command cmd
  # http://whynotwiki.com/Ruby_/_Process_management#What_happens_to_standard_error_.28stderr.29.3F
  require 'canis/core/util/viewer'
  begin
    res = `#{cmd} 2>&1`
  rescue => ex
    res = ex.to_s
    res << ex.backtrace.join("\n") 
  end
  res.gsub!("\t","   ")
  # Earlier close key was ENTER but we need that to execute or fire
  Canis::Viewer.view(res.split("\n"), :close_key => 'q', :title => "<q> to close, M-l M-h to scroll")
end
shell_out(command=nil) click to toggle source

takes a unix command (system) and executes the same. No output @return return value of system command

# File lib/canis/core/include/appmethods.rb, line 82
def shell_out command=nil
  $shell_history ||= []
  command ||= get_string("Enter system command:", :maxlen => 50) do |f|
    require 'canis/core/include/rhistory'
    f.extend(FieldHistory)
    f.history($shell_history)
  end
  ##w = @window || @form.window
  #w.hide
  Ncurses.endwin
  ret = system command
  Ncurses.refresh
  #Ncurses.curs_set 0  # why ?
  #w.show
  return ret
end
shell_output() click to toggle source

prompts user for unix command and displays output in viewer

# File lib/canis/core/include/appmethods.rb, line 49
def shell_output
  $shell_history ||= []
  cmd = get_string("Enter shell command:", :maxlen => 50) do |f|
    require 'canis/core/include/rhistory'
    f.extend(FieldHistory)
    f.history($shell_history)
  end
  if cmd && !cmd.empty?
    run_command cmd
    $shell_history.push(cmd) unless $shell_history.include? cmd
  end
end
suspend() click to toggle source

suspends current program and puts user on unix prompt

# File lib/canis/core/include/appmethods.rb, line 36
def suspend
  _suspend(false) do
    system("tput cup 26 0")
    system("tput ed")
    system("echo Enter C-d to return to application")
    system (ENV['PS1']='\s-\v\$ ') if ENV['SHELL']== '/bin/bash'
    system(ENV['SHELL']);
  end
end
view(what, config={}) { |textview for further configuration| ... } click to toggle source

view a file or array of strings

# File lib/canis/core/widgets/rwidget.rb, line 904
def view what, config={}, &block # :yields: textview for further configuration
  require 'canis/core/util/viewer'
  Canis::Viewer.view what, config, &block
end
xxxbind_composite_mapping(keycode, *args, &blk) click to toggle source
# File lib/canis/core/widgets/rwidget.rb, line 604
def xxxbind_composite_mapping keycode, *args, &blk
  @_key_composite_map ||= {}
  str = ""
  keycode.each do |e| 
    s = key_tos(e)
    str << s
  end
  $log.debug "  composite map #{keycode} bound as #{str} "
  @_key_composite_map[str] = blk
end

Private Instance Methods

_suspend(clear=true) { || ... } click to toggle source
# File lib/canis/core/include/appmethods.rb, line 6
def _suspend clear=true
  return unless block_given?
  Ncurses.def_prog_mode
  if clear
    Ncurses.endwin 
    # NOTE: avoid false since screen remains half off
    # too many issues
  else
    system "/bin/stty sane"
  end
  yield if block_given?
  Ncurses.reset_prog_mode
  if !clear
    # Hope we don't screw your terminal up with this constantly.
    Canis::stop_ncurses
    Canis::start_ncurses  
    #@form.reset_all # not required
  end
  @form.repaint if @form
  @window.wrefresh if @window
  Ncurses::Panel.update_panels
end