module Canis

—————————————————————————– #

       File: actionmanager.rb
Description: a class that manages actions for a widget

     Author: jkepler http://github.com/mare-imbrium/canis/
       Date: 2012-01-4 
    License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
Last update: ,,L

—————————————————————————– #

Maintains actions for a widget

Some methods an application may like to use such as the ability to suspend cooked mode

and go to shell, or run a command and view output without leaving the app.

I am moving the common title and border printing stuff into a separate module.

—————————————————————————– #

       File: canisparser.rb
Description: creates an returns instances of parser objects
     Author: j kepler  http://github.com/mare-imbrium/canis/
       Date: 2014-06-11 - 12:23
    License: MIT
Last update: 2014-06-16 16:56

—————————————————————————– #

canisparser.rb  Copyright (C) 2012-2014 j kepler

———————————————————— #

       File: chunk.rb 
Description: Contains classes that implement the default native format
             we use for colored lines display.
     Author: jkepler http://github.com/mare-imbrium/canis/
       Date: 07.11.11 - 12:31 
Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
Last update: 2017-03-09 23:13

———————————————————— #

Provides the ability to scroll content, typically an array widget that includes may override on_enter_row and on_leave_row Caller should have

row_count()
scrollatrow() typically @height - 2 (unless a header row, then -3)
@current_index (row of current index, starting with 0 usually)
@toprow : set to 0 for starters, top row to be displayed
@pcol (used for horiz scrolling, starts at 0)

File created: 2010-10-29 14:09 Author : jkepler

this is a new, simpler version of listselectable the original gets into models and has complicated operation as well as difficult to remember method names. This attempts to be a simple plugin. Currently being used by rbasiclistbox (rlist) and now tabularwidget. NOTE: pls define @_header_adjustment to 0 if you don't use it or know what it means. TODO: of course we need to fire events so user can do something.

—————————————————————————– #

       File: listbindings.rb
Description: bindings for multi-row widgets such as listbox, table, 
     Author: jkepler http://github.com/mare-imbrium/canis/
       Date: 2011-12-11 - 12:58
    License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
Last update: 2014-09-11 19:09

—————————————————————————– #

Some methods for traversing list like widgets such as tree, listbox and maybe table Different components may bind different keys to these

The DefaultListSelection mixin provides Textpad derived classes with selection methods and bindings.

Example

Inside the constructor of the multiline object use the following line, before the call to `super()`

    self.extend DefaultListSelection

At any other portion, for example after the call to `super()` you may set the default model if the user has not done so in the calling block

@list_selection_model ||= Canis::DefaultListSelectionModel.new self

When clearing data, as in `clear`, selected_indices should also be cleared.

Note

This module does not take care of rendering a selected row. This must still be handled
by the default or custom renderer using `is_row_selected?`.

Note that changing the order of data, or deleting, inserting etc will not correct the selection
indices. Indices are assumed to be stable, and they may be cleared using `clear` on +@selected_indices+
if the data indices change.

Event created when state changed (as in ViewPort)

Event created when state changed (as in ViewPort)

—————————————————————————– #

       File: rhistory.rb
Description: a module that pops up history, and then updates selected value
             This goes with Field.
             e.g.,
             field.extend(FieldHistory)

             The module name History was throwing up errors
     Author: jkepler http://github.com/mare-imbrium/canis/
       Date: 2011-11-27 - 18:10
    License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
Last update: 2014-08-19 00:02

—————————————————————————– #

supply history for this object, at least give an empty array widget would typically be Field,

otherwise it should implement *text()* for getting and setting value
and a *CHANGED* event for when user has modified a value and moved out

You can externally set $history_key to any unused key, otherwise it is M-h

Event created when data modified in Field or TextEdit

2008-12-24 17:54

—————————————————————————– #

       File: textdocument.rb
Description: Abstracts complex text preprocessing and rendering from TextPad
     Author: j kepler  http://github.com/mare-imbrium/canis/
       Date: 2014-06-25 - 12:52
    License: MIT
Last update: 2014-09-11 19:48

—————————————————————————– #

textdocument.rb  Copyright (C) 2012-2014 j kepler

—————————————————————————– #

       File: widgetmenu.rb
Description: a module that displays a menu for customization of a field
             e.g.,
             field.extend(WidgetMenu)

     Author: jkepler http://github.com/mare-imbrium/canis/
       Date: 2011-12-2x
    License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
Last update: 2011-12-26 - 20:25

—————————————————————————– #

Provide a system for us to define a menu for customizing a widget, such that applicatin can also add more menuitems

2014-08-11 - 09:54 There is a limit to the number of color pairs one can make 0 .. COLOR_PAIRS - 1 which i why i get junk colors after 255. In my program, color_pairs is 32767 ???

curses.init_pair(pair_number, fg, bg)

Change the definition of a color-pair. It takes three arguments: the

number of the color-pair to be changed, the foreground color number, and the background color number. The value of pair_number must be between 1 and COLOR_PAIRS - 1 (the 0 color pair is wired to white on black and cannot be changed). The value of fg and bg arguments must be between 0 and COLORS. If the color-pair was previously initialized, the screen is refreshed and all occurrences of that color-pair are changed to the new definition.

- https://docs.python.org/2/library/curses.html

include FFI::NCurses # this pollutes many objects and invalidates method_missing

—————————————————————————– #

       File: colorparser.rb
Description: Default parse for our tmux format
             The aim is to be able to specify parsers so different kinds
             of formatting or documents can be used, such as ANSI formatted
             manpages.
     Author: jkepler http://github.com/mare-imbrium/canis/
       Date: 07.11.11 - 13:17
    License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
Last update: 2013-04-01 13:43

—————————————————————————– #

TODO

- perhaps we can compile the regexp once and reuse

—————————————————————————– #

       File: colorparser.rb
Description: Default parse for our tmux format
             The aim is to be able to specify parsers so different kinds
             of formatting or documents can be used, such as ANSI formatted
             manpages.
     Author: jkepler http://github.com/mare-imbrium/canis/
       Date: 07.11.11 - 13:17
    License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
Last update: 2014-09-01 11:47

—————————————————————————– #

TODO

- perhaps we can compile the regexp once and reuse

CHANGES

- adding style 2014-05-19 - 12:52
The character input routines are from io.rb, however, the user-interface to the input
is copied from the Highline project (James Earl Gray) with permission.

May later use a Label and Field.

NOTE : Pls avoid directly using this class. I am trying to redo this so ask, agree and say
       can create their own window and be done with it. The hurdle in that is that ask calls
       say, so when to close the window is not clear within say. Some shakeup is expected by
       1.4.0 or so.

Allow some objects to take focus when a certain key is pressed. This is for objects like scrollbars and grabbars. We don't want these always getting focus, only sometimes when we want to resize panes. This will not only be included by Form but by containers such as Vimsplit or MasterDetail. Usage: the idea is that when you create grabbars, you would add them to the FocusManager Thus they would remain non-focusable on creation. When hte user presses (say F3) then make_focusable is called, or toggle_focusable. Now user can press TAB and access these bars. When he is done he can toggle again. TODO: we might add a Circular class here so user can traverse only these objects

—————————————————————————– #

       File: helpmanager.rb
Description: manages display of help text and hyperlinking with other files in doc dir.
     Author: j kepler  http://github.com/mare-imbrium/canis/
       Date: 2014-07-08 - 20:59
    License: MIT
Last update: 2014-07-08 21:07

—————————————————————————– #

helpmanager.rb  Copyright (C) 2012-2014 j kepler
TODO
 - the method display_help is huge and a mess. That part needs to be a class.

—————————————————————————– #

       File: promptmenu.rb
Description: a simple 'most' type menu at bottom of screen.
             Moved from io.rb
     Author: j kepler  http://github.com/mare-imbrium/canis/
       Date: 2014-04-25 - 12:32
    License: MIT
Last update: 2014-08-09 18:55

—————————————————————————– #

promptmenu.rb  Copyright (C) 2012-2014 j kepler
Depends on rcommandwindow for display_menu

—————————————————————————– #

       File: textutils.rb
Description: contains some common string or Array<String> utilities
  that may be required by various parts of application.
     Author: j kepler  http://github.com/mare-imbrium/canis/
       Date: 2014-05-22 - 11:11
    License: MIT
Last update: 2014-05-26 19:40

—————————————————————————– #

textutils.rb  Copyright (C) 2012-2014 j kepler

A file or array viewer.

CHANGES

- 2014-04-09 - 00:58 changed textview to textpad

Can be used for print_help_page SUGGESTIONS WELCOME. NOTE: since this is not a proper class / object, it is being hacked to pieces

We need to either make this a proper class, or else make another one with a class,
and use this for simple purposes only.

what is the real purpose of the shortcuts, is it to avoid putting nil for form there if not required. Or is it positioning, such as in a stack. or just a method ?

@example

At a later stage, we will integrate this with lists and tables, so it will happen automatically.

@since 1.4.1 UNTESTED

include Ncurses # FFI 2011-09-8

include Canis

TODO : We can consider making it independent of objects, or allow for a margin so it does not write over the object. Then it will be always visible. TODO: if lists and tables, can without borders actually adjust then putting this independent would make even more sense, since it won't eat an extra line.

@example

lb = list_box ....
rb = Divider.new @form, :parent => lb, :side => :right

At a later stage, we will integrate this with lists and tables, so it will happen automatically.

@since 1.2.0

A listbox based on textpad. Contains a scrollable array of Strings. The list is selectable too. In place editing is not provided, however editing in a separate box has been implemented in various examples. Essentially, the listbox only adds selection to the textpad. TODO


[ ] focussed_color - this could be part of textpad too. row under cursor
[ ] rlist has menu actions that can use prompt menu or popup ?
[ ] nothing has been done about show_selector -- consider whether to knock off

CHANGES


This paints a vertical white bar given row and col, and length. It also calculates and prints a small bar over this based on relaetd objects list.length and current_index. Typically, after setup one would keep updating only current_index from the repaint method of caller or in the traversal event. This would look best if the listbox also has a reverse video border, or none. @example

lb = list_box ....
sb = Scrollbar.new @form, :row => lb.row, :col => lb.col, :length => lb.height, :list_length => lb.row_count, :current_index => 0
 .... later as user traverses
 sb.current_index = lb.current_index
sb = Scrollbar.new @form, :parent => list

At a later stage, we will integrate this with lists and tables, so it will happen automatically.

@since 1.2.0 UNTESTED

The motivation to create yet another table widget is because tabular_widget is based on textview etc which have a lot of complex processing and rendering whereas textpad is quite simple. It is easy to just add one's own renderer making the code base simpler to understand and maintain.

A simple tabular data generator. Given table data in arrays and a column heading row in arrays, it quickely generates tabular data. It only takes left and right alignment of columns into account.

You may specify individual column widths. Else it will take the widths of the column names you supply

in the startup array. You are encouraged to supply column widths.

If no columns are specified, and no widths are given, it take the widths of the first row

as a model to determine column widths.

The motivation to create yet another table widget is because tabular_widget is based on textview etc which have a lot of complex processing and rendering whereas textpad is quite simple. It is easy to just add one's own renderer making the code base simpler to understand and maintain.

Constants

ActionEvent

source - as always is the object whose event has been fired id - event identifier (seems redundant since we bind events often separately. event - is :PRESS action_command - command string associated with event (such as title of button that changed

CANIS_DOCPATH
CMenuItem
 A *simple* way of creating menus that will appear in a single row.
This copies the menu at the bottom of "most" upon pressing ":".
hotkey is the key to invoke an item (a single digit letter)

label is an action name

desc is a description displayed after an item is chosen. Usually, its like:

+ “Folding has been enabled” or “Searches will now be case sensitive”

action may be a Proc or a symbol which will be called if item selected

+ action may be another menu, so recursive menus can be built, but each + should fit in a line, its a simple system.

TreeSelectionEvent

structures {{{

VERSION

Public Class Methods

startup() click to toggle source

unused to my knowledge

# File lib/canis/core/widgets/rwidget.rb, line 3642
def self.startup
  raise "startup seems to be unused. remove this line if used, else remove method by next version"
  Canis::start_ncurses
  path = File.join(ENV["LOGDIR"] || "./" ,"canis14.log")
  file   = File.open(path, File::WRONLY|File::TRUNC|File::CREAT) 
  $log = Logger.new(path)
  $log.level = Logger::DEBUG
end

Public Instance Methods

_new_layout(size) click to toggle source

create a new layout array based on size of data given The layout created is weighted to the bottom, so it is always ending at the second last row The top keeps changing based on height.

# File lib/canis/core/util/rcommandwindow.rb, line 710
def _new_layout size
  ht = size
  #ht = 15
  sh = Ncurses.LINES-1
  sc = Ncurses.COLS-0
  layout = [ ht, sc, sh-ht ,0]
end
_update_default_settings(config={}) click to toggle source

update given hash with layout, close_key and app_header so this is shared across various methods. The layout created is weighted to the bottom, so it is always ending at the second last row

# File lib/canis/core/util/rcommandwindow.rb, line 694
def _update_default_settings config={}
  ht = config[:height] || 15
  sh = Ncurses.LINES-1
  sc = Ncurses.COLS-0
  layout = [ ht, sc, sh-ht ,0]
  config[:layout] = layout
  config[:close_key] = KEY_ENTER
  config[:app_header] = true
  # repeated resetting seems to play with left and other things.
  # let's say we know that my window will always have certain settings, then let me do a check for them in padrefresh
  # in this window the only thing changing is the top (based on rows). all else is same.
  #config[:fixed_bounds] = [nil, 0, sh, sc]
end
choose_file(glob, config={}) click to toggle source

This is a variation of display_list which is more for selecting a file, or dir. It maps some keys to go up to parent dir, and to step into directory under cursor if you are in directory mode. @param [String] (optional) glob is a glob to apply when creating a listing @param [Hash] config options for configuring the listing @option config [Boolean] :recursive Should listing recurse, default true @option config [Boolean] :dirs Should list directories only, default false @option config [String] :startdir Directory to use as current

You may also add other config pairs to be passed to textpad such as title

NOTE: if you pass a glob, then :recursive will not apply. You must specify recursive by prepending “**/” or inserting it in the appropriate place such as “a/b/c/**/*rb”. We would not know where to place the “**/”.

@example list directories recursively

str = choose_file  :title => "Select a file", 
   :recursive => true,
   :dirs => true,
# File lib/canis/core/util/rcommandwindow.rb, line 611
def choose_file glob, config={}
  if glob.is_a? Hash
    config = glob
    glob = nil
  end
  frec = true
  frec = config.delete :recursive if config.key? :recursive
  fdir = config.delete :dirs
  if glob.nil?
    glob = "*"
    if frec
      glob = "**/*"
    end
    if fdir
      glob << "/"
    end
  end
  maxh = 15
  # i am not going through that route, since going up and down a dir will be difficult in a generic
  # case the glob has the dir in it, or i pass directory to the handler.
  # why not Dir.pwd in next line ?? XXX
  #directory = Pathname.new(File.expand_path(File.dirname($0)))
  #_d = config.delete :directory
  #if _d
    #directory = Pathname.new(File.expand_path(_d))
  #end
  directory = config.delete :directory
  # this keeps going up with each invocation if I send ".."
  Dir.chdir(directory) if directory
  command = config.delete(:command)
  text = Dir.glob(glob)
  #text = Dir[File.join(directory.to_s, glob)]
  if !text or text.empty?
    text = ["No entries"]
  end
  if text.size < maxh
    config[:height] = text.size + 1
  end
  # calc window coords
  _update_default_settings config
  default_layout = config[:layout]
  config[:close_key] = 1001
  command_list(text, config) do |t, hash|
    t.suppress_borders true
    t.print_footer false
    #t.fixed_bounds config.delete(:fixed_bounds)
    t.key_handler = ControlPHandler.new(t)
    t.key_handler.maxht = maxh
    t.key_handler.default_layout = default_layout
    t.key_handler.header = hash[:header]
    t.key_handler.recursive_search(glob)
    t.key_handler.directory_key_map
  end
end
command_list(content, config={}) { |textpad| ... } click to toggle source

this is taken from view and replaces the call to view, since we were modifying view a bit too much to fit it into the needs here.

# File lib/canis/core/util/rcommandwindow.rb, line 30
def command_list content, config={}, &block  #:yield: textpad
  wt = 0 # top margin
  wl = 0 # left margin
  wh = Ncurses.LINES-wt # height, goes to bottom of screen
  ww = Ncurses.COLS-wl  # width, goes to right end
  layout = { :height => wh, :width => ww, :top => wt, :left => wl } 
  if config.has_key? :layout
    layout = config[:layout]
    case layout
    when Array
      wh, ww, wt, wl = layout
      layout = { :height => wh, :width => ww, :top => wt, :left => wl } 
    when Hash
      # okay
    end
  end

  fp = config[:title] || ""
  pf = config.fetch(:print_footer, false)
  ta = config.fetch(:title_attrib, 'bold')
  fa = config.fetch(:footer_attrib, 'bold')
  b_ah = config[:app_header]
  type = config[:content_type]

  v_window = Canis::Window.new(layout)
  v_form = Canis::Form.new v_window
  v_window.name = "command-list"
  colors = Ncurses.COLORS
  back = :blue
  back = 235 if colors >= 256
  blue_white = get_color($datacolor, :white, back)

  tprow = 0
  ah = nil
  if b_ah
    ah = ApplicationHeader.new v_form, "", :text_center => fp
    tprow += 1
  end

  textview = TextPad.new v_form do
    name   "CommandList" 
    row  tprow
    col  0
    width ww
    height wh-tprow # earlier 2 but seems to be leaving space.
    title fp
    title_attrib ta
    print_footer pf
    footer_attrib fa
    #border_attrib :reverse
    border_color blue_white
  end

  t = textview
  items = {:header => ah}
  begin
    textview.set_content content, :content_type => type
    if block_given?
      if block.arity > 0
        yield textview, items
      else
        textview.instance_eval(&block)
      end
    end
  v_form.repaint
  v_window.wrefresh
  Ncurses::Panel.update_panels
  retval = ""
  # allow closing using q and Ctrl-q in addition to any key specified
  #  user should not need to specify key, since that becomes inconsistent across usages
  #  NOTE: no longer can we close with just a q since often apps using this trap char keys
  #  NOTE: 2727 is no longer operational, so putting just ESC
    while((ch = v_window.getchar()) != ?\C-q.getbyte(0) )
      # ideally we should be throwing a close rather than this since called will need keys.
      retval = textview.current_value() if ch == config[:close_key] 
      break if ch == config[:close_key] || ch == 3|| ch == 27 # removed double esc 2014-05-04 - 17:30
      # if you've asked for ENTER then i also check for 10 and 13
      retval = textview.current_value() if (ch == 10 || ch == 13) && config[:close_key] == KEY_ENTER
      break if (ch == 10 || ch == 13) && config[:close_key] == KEY_ENTER
      v_form.handle_key ch
      v_form.repaint
    end
  rescue => err
      $log.error " command-list ERROR #{err} "
      $log.debug(err.backtrace.join("\n"))
      alert "#{err}"
      #textdialog ["Error in command-list: #{err} ", *err.backtrace], :title => "Exception"
  ensure
    v_window.destroy if !v_window.nil?
  end
  return retval
end
display_list(text, config={}) click to toggle source

return a blank if user quits list, or the value can we prevent a user from quitting, he must select ?

Display a list of valies given in text and allows user to shrink the list based on keys entered much like control-p.

@param [Array<String>] array of Strings to print @param [ Hash ] config hash passed to Viewer.view

May contain +:command+ which is a Proc that replenishes the list everytime user
enters a key (updates the search string). The proc is supplied user-entered string.
The following example is a proc that matches all the files returned by Dir.glob
with the user entered string.

 Proc.new {|str| Dir.glob("**/*").select do |p| p.index str; end }

@return [ String ] text of line user pressed ENTER on, or “” if user pressed ESC or C-c x show keys entered x shrink the pad based on results x if no results show somethinf like “No entries”. or don't change TODO take left and right arrow key and adjust insert point TODO have some proc so user can keep querying, rather than passing a list. this way if the list is really long, all values don't need to be passed.

# File lib/canis/core/util/rcommandwindow.rb, line 739
def display_list text, config={}
  maxh = 15
  _update_default_settings config
  default_layout = config[:layout].dup
  command = config.delete(:command)
  command_list(text, config) do |t, hash|
    t.suppress_borders true
    t.print_footer false
    #t.fixed_bounds config.delete(:fixed_bounds)
    t.key_handler = ControlPHandler.new(t)
    t.key_handler.maxht = maxh
    t.key_handler.default_layout = default_layout
    t.key_handler.header = hash[:header]
    t.key_handler.command = command if command
  end
end
display_text(text, config={}) click to toggle source

NOTE: moved from bottomline since it used commandwindow but now we;ve moved away from ListObject to view. and i wonder what this really gives ? WARNING: if you actually use this, please copy it to your app, since it may be removed. I don;t see what real purpose it achieves. It is now a wrapper over Canis::Viewer.view

Displays text at the bottom of the screen, close the screen with ENTER. @param text can be file name or Array of Strings. @param config is a Hash. :height which will be from bottom of screen and defaults to 15. All other config elements are passed to view. See viewer.rb.

# File lib/canis/core/util/rcommandwindow.rb, line 679
def display_text text, config={}
  _update_default_settings config
  if text.is_a? String
    if File.exists? text
      text = File.open(text, 'r').read.split("\n")
    end
  end
  command_list(text, config) do |t|
    t.suppress_borders true
    t.print_footer false
  end
end
numbered_menu(list1, config={}) click to toggle source

presents given list in numbered format in a window above last line and accepts input on last line The list is a list of strings. e.g.

%w{ ruby perl python haskell }

Multiple levels can be given as:

list = %w{ ruby perl python haskell }
list[0] = %w{ ruby ruby1.9 ruby 1.8 rubinius jruby }

In this case, “ruby” is the first level option. The others are used in the second level. This might make it clearer. first3 has 2 choices under it.

[ "first1" , "first2", ["first3", "second1", "second2"], "first4"]

Currently, we return an array containing each selected level

@return [Array] selected option/s from list

# File lib/canis/core/util/rcommandwindow.rb, line 549
def numbered_menu list1, config={}
  if list1.nil? || list1.empty?
    #say_with_pause "empty list passed to numbered_menu"  # 2014-04-25
     # remove bottomline
    print_error_message "Empty list passed to numbered_menu"
    return nil
  end
  prompt = config[:prompt] || "Select one: "
  require 'canis/core/util/rcommandwindow'
  layout = { :height => 5, :width => Ncurses.COLS-1, :top => Ncurses.LINES-6, :left => 0 }
  rc = CommandWindow.new nil, :layout => layout, :box => true, :title => config[:title]
  w = rc.window
  # should we yield rc, so user can bind keys or whatever
  # attempt a loop so we do levels.
  retval = []
  begin
    while true
      rc.display_menu list1, :indexing => :number
      #ret = ask(prompt, Integer ) { |q| q.in = 1..list1.size }
      # if class is specifited then update type in Field
      ret = rb_gets(prompt) {|f| f.datatype = 1.class ; f.type :integer; f.valid_range(1..list1.size)}
      val = list1[ret-1]
      if val.is_a? Array
        retval << val[0]
        $log.debug "NL: #{retval} "
        list1 = val[1..-1]
        rc.clear
      else
        retval << val
        $log.debug "NL1: #{retval} "
        break
      end
    end
  ensure
    rc.destroy
    rc = nil
  end
  #list1[ret-1]
  $log.debug "NL2: #{retval} , #{retval.class} "
  retval
end
repaint_old() click to toggle source
# File lib/canis/core/widgets/rprogress.rb, line 115
def repaint_old
end
start_ncurses() click to toggle source

Setup ncurses, nicely documented by the curses manpages

# File lib/canis/core/system/ncurses.rb, line 7
  def start_ncurses
    return if $ncurses_started
    $ncurses_started = true
    # in case we want a blocking getch, you may want to first
    # set wtimeout to -1, and then reset it to this value.
    # Please first check that we are using this.
    $ncurses_timeout = 500 # used by windows for timeout of wgetch

    # The initscr code determines the terminal type and initializes all curses
    # data structures.
    # initscr also causes the first call to refresh to clear the screen.
    # If errors occur, initscr writes an appropriate error message to standard
    # error and exits; otherwise, a pointer is returned to stdscr.
    stdscr = Ncurses.initscr  ## FFI

#    Color.start if Ncurses.has_colors?
      Ncurses.start_color();
      ColorMap.setup # added by RK 2008-11-30 00:48
    # The keypad option enables the keypad of the user's terminal.
    # If enabled (bf is TRUE), the user can press a function key (such as an
    # arrow key) and wgetch returns a single value representing the function
    # key, as in KEY_LEFT.
    # If disabled (bf is FALSE), curses does not treat function keys specially
    # and the program has to interpret the escape sequences itself.
    # If the keypad in the terminal can be turned on (made to transmit) and off
    # (made to work locally), turning on this option causes the terminal keypad
    # to be turned on when wgetch is called.
    # The default value for keypad is false.
    Ncurses.keypad(stdscr.pointer, bf = true) # FFIWINDOW
    #Ncurses.keypad(stdscr, bf = true)
      #Ncurses.stdscr.keypad(true)     # turn on keypad mode FFI
    #Ncurses.keypad(stdscr, bf = 1)

    # The nl and nonl routines control whether the underlying display device
    # translates the return key into newline on input, and whether it
    # translates newline into return and line-feed on output (in either case,
    # the call addch('\n') does the equivalent of return and line feed on the
    # virtual screen).
    # Initially, these translations do occur.
    # If you disable them using nonl, curses will be able to make better use of
    # the line-feed capability, resulting in faster cursor motion.
    # Also, curses will then be able to detect the return key.
    Ncurses.nonl

    # The raw and noraw routines place the terminal into or out of raw mode.
    # Raw mode is similar to cbreak mode, in that characters typed are
    # immediately passed through to the user program.
    # The differences are that in raw mode, the interrupt, quit, suspend, and
    # flow control characters are all passed through uninterpreted, instead of
    # generating a signal.
    # The behavior of the BREAK key depends on other bits in the tty driver
    # that are not set by curses.
    Ncurses.raw

    # Normally, the tty driver buffers typed characters until a newline or
    # carriage return is typed.
    # The cbreak routine disables line buffering and
    # erase/kill character-processing (interrupt and flow control characters
    # are unaffected), making characters typed by the user immediately
    # available to the program.
    #Ncurses.cbreak
    # I have removed cbreak and halfdelay since they were causing C-c
    # to crash if i pressed it in succession

    # The echo and noecho routines control whether characters typed by the user
    # are echoed by getch as they are typed.
    # Echoing by the tty driver is always disabled, but initially getch is in
    # echo mode, so characters typed are echoed.
    Ncurses.noecho

    # The curs_set routine sets the cursor state is set to invisible, normal,
    # or very visible for visibility equal to 0, 1, or 2 respectively.
    # If the terminal supports the visibility requested, the previous cursor
    # state is returned; otherwise, ERR is returned.
    Ncurses.curs_set(1)

    # The halfdelay routine is used for half-delay mode, which is similar to
    # cbreak mode in that characters typed by the user are immediately
    # available to the  program.
    # However, after blocking for tenths tenths of seconds, ERR is returned if
    # nothing has been typed.
    # The value of tenths must be a number between 1 and 255.
    # Use nocbreak to leave half-delay mode.
    #Ncurses::halfdelay(tenths = 10)
    # See above why switched off, halfdelay puts into cbreak mode, in which C-c pressed in quick
    # succession crashes the program.

    # The nodelay option causes getch to be a non-blocking call. If no input is
    # ready, getch returns ERR. If disabled (bf is FALSE), getch waits until a
    # key is pressed.
    # I am using the next line for the window when creating, this does not
    # have any impact on window.
    # For this to have any effect your getch should be Ncurses.getch and not
    # wgetch(@window), For that do this with window.
    # I am disableing this 2011-12-20 since it does not work with combinations
    # such as gg. Any routine that does a getch will just immediatelt return an ERR.
    #Ncurses::nodelay(stdscr.pointer, bf = true)


    # added these 2 so we can do resizing based on original and current size when terminal resized
    #  2012-01-8
    $orig_cols = FFI::NCurses.COLS
    $orig_rows = FFI::NCurses.LINES
    # cache of keycode (int) and string result
    $key_cache ||= {}
  end
stop_ncurses() click to toggle source

this should happen only in outermost program that started ncurses if a called program does this, the calling program can have a display freeze

# File lib/canis/core/system/ncurses.rb, line 116
def stop_ncurses
  Ncurses.echo
  Ncurses.nocbreak
  Ncurses.nl
  Ncurses.endwin
  $ncurses_started = false
  #puts "curses over"
ensure
  return unless error = @last_error

  $stderr.puts ''
  $stderr.puts @last_error_message if @last_error_message
  $stderr.puts @last_error, *@last_error.backtrace
end