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
-
Name : bottomline.rb
-
Description : routines for input at bottom of screen like vim, or anyother line
-
:
-
Author : jkepler
-
Date : 2010-10-25 12:45
-
License : Same as Ruby's License (www.ruby-lang.org/LICENSE.txt)
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
-
removed Array operations to Textpad, some renaming 2014-04-10 - 20:50
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
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
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 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
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
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
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
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
# File lib/canis/core/widgets/rprogress.rb, line 115 def repaint_old end
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
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