Class: Canis::App
- Includes:
- WidgetShortcuts
- Defined in:
- lib/canis/core/util/app.rb
Overview
This is the Application class which does the job of setting up the environment, and closing it at the end.
Instance Attribute Summary collapse
-
#config ⇒ Object
readonly
Returns the value of attribute config.
-
#form ⇒ Object
readonly
Returns the value of attribute form.
-
#quit_key ⇒ Object
writeonly
Sets the attribute quit_key.
-
#window ⇒ Object
readonly
Returns the value of attribute window.
methods to create widgets easily collapse
-
#hline(config = {}) ⇒ Object
displays a horizontal line takes col (column to start from) from current stack take row from app_row.
Instance Method Summary collapse
- #bind_component ⇒ Object
-
#bind_global ⇒ Object
bind a key to a method at global (form) level Note that individual component may be overriding this.
- #close ⇒ Object
-
#field_help_text ⇒ Object
displays help_text associated with field.
- #get_all_commands ⇒ Object
-
#get_binding ⇒ Object
used only by LiveConsole, if enables in an app, usually only during testing.
-
#get_command_from_user(choices = ["quit","help", "suspend", "shell_output"]) ⇒ Object
prompts user for a command.
- #init_vars ⇒ Object
-
#initialize(config = {}, &block) ⇒ App
constructor
TODO: i should be able to pass window coords here in config :title.
-
#keypress(&block) ⇒ Object
returns a symbol of the key pressed e.g.
- #logger ⇒ Object
-
#loop(&block) ⇒ Object
This method is called by run, and thus in most cases this is what is used.
-
#message(text) ⇒ Object
updates a global var with text.
-
#safe_loop(&block) ⇒ Object
if calling loop separately better to call this, since it will shut off ncurses and print error on screen.
-
#suspend(clear = true) ⇒ Object
suspends curses so you can play around on the shell or in cooked mode like Vim does.
Methods included from WidgetShortcuts
#_configure, #_position, #app_header, #blank, #box, #button, #check, def_widget, #dock, #field, #flow, #label, #line, #link, #listbox, #menubar, #menulink, #radio, #stack, #status_line, #table, #textarea, #textpad, #tree, #widget_shortcuts_init
Constructor Details
#initialize(config = {}, &block) ⇒ App
TODO: i should be able to pass window coords here in config :title
83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/canis/core/util/app.rb', line 83 def initialize config={}, &block @config = config @variables = {} # if we are creating child objects then we will not use outer form. this object will manage @current_object = [] @_system_commands = %w{ bind_global bind_component field_help_text } init_vars $log.debug "XXX APP CONFIG: #{@config} " if $log.debug? run &block end |
Instance Attribute Details
#config ⇒ Object (readonly)
Returns the value of attribute config.
74 75 76 |
# File 'lib/canis/core/util/app.rb', line 74 def config @config end |
#form ⇒ Object (readonly)
Returns the value of attribute form.
75 76 77 |
# File 'lib/canis/core/util/app.rb', line 75 def form @form end |
#quit_key=(value) ⇒ Object (writeonly)
Sets the attribute quit_key
77 78 79 |
# File 'lib/canis/core/util/app.rb', line 77 def quit_key=(value) @quit_key = value end |
#window ⇒ Object (readonly)
Returns the value of attribute window.
76 77 78 |
# File 'lib/canis/core/util/app.rb', line 76 def window @window end |
Instance Method Details
#bind_component ⇒ Object
299 300 301 302 303 304 305 306 |
# File 'lib/canis/core/util/app.rb', line 299 def bind_component #rb_puts "Todo. ", :color_pair => get_color($promptcolor, :red, :black) "Todo this. " # the idea here is to get the current component # and bind some keys to some methods. # however, how do we divine the methods we can map to # and also in some cases the components itself has multiple components end |
#bind_global ⇒ Object
bind a key to a method at global (form) level Note that individual component may be overriding this.
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 |
# File 'lib/canis/core/util/app.rb', line 264 def bind_global opts = get_all_commands cmd = rb_gets("Select a command (<tab> for choices) : ", opts) if cmd.nil? || cmd == "" rb_puts "Aborted." return end key = [] str = "" # the next is fine but does not allow user to enter a control or alt or function character # since it uses Field. It is fine if you want to force alphanum input ch = rb_getchar("Enter one or two keys. Finish with <ENTER>. Enter first key:") unless ch rb_puts "Aborted. <Press a key>" return end key << ch str << keycode_tos(ch) ch = rb_getchar "Got #{str}. Enter second key or hit return:" unless ch rb_puts "Aborted. <Press a key>" return end if ch == KEY_ENTER || ch == 13 else key << ch str << keycode_tos(ch) end if !key.empty? rb_puts "Binding #{cmd} to #{str}. " key = key[0] if key.size == 1 #@form.bind_key(key, cmd.to_sym) # not finding it, getting called by that comp @form.bind_key(key){ send(cmd.to_sym) } end end |
#close ⇒ Object
113 114 115 116 117 118 119 120 121 122 |
# File 'lib/canis/core/util/app.rb', line 113 def close $log.debug " INSIDE CLOSE, #{@stop_ncurses_on_close} " @window.destroy if !@window.nil? $log.debug " INSIDE CLOSE, #{@stop_ncurses_on_close} " if @stop_ncurses_on_close Canis::stop_ncurses $log.debug " CLOSING NCURSES" end $log.debug " CLOSING APP" end |
#field_help_text ⇒ Object
displays help_text associated with field. 2011-10-15
308 309 310 311 312 313 314 315 316 317 |
# File 'lib/canis/core/util/app.rb', line 308 def field_help_text f = @form.get_current_field if f.respond_to?('help_text') h = f.help_text h = "No help text defined for this field.\nTry F1, or press '?' for key-bindings." unless h textdialog "#{h}", :title => "Widget Help Text" else alert "Could not get field #{f} or does not respond to helptext. Try F1 or '?'" end end |
#get_all_commands ⇒ Object
255 256 257 258 259 260 261 |
# File 'lib/canis/core/util/app.rb', line 255 def get_all_commands opts = @_system_commands.dup if respond_to? :get_commands opts.push(*get_commands()) end opts end |
#get_binding ⇒ Object
used only by LiveConsole, if enables in an app, usually only during testing.
218 219 220 |
# File 'lib/canis/core/util/app.rb', line 218 def get_binding return binding() end |
#get_command_from_user(choices = ["quit","help", "suspend", "shell_output"]) ⇒ Object
prompts user for a command. we need to get this back to the calling app or have some block stuff TODO Actually, this is naive, you would want to pass some values in like current data value or lines ?? Also may want command completion, or help so all commands can be displayed NOTE: This is gonna change very soon - 2012-01-8
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 |
# File 'lib/canis/core/util/app.rb', line 324 def get_command_from_user choices=["quit","help", "suspend", "shell_output"] @_command_history ||= Array.new str = rb_gets("Cmd: ", choices) { |q| q.default = @_previous_command; q.history = @_command_history } @_command_history << str unless @_command_history.include? str # shell the command if str =~ /^!/ str = str[1..-1] suspend(false) { #system(str); $log.debug "XXX STR #{str} " if $log.debug? output=`#{str}` system("echo ' ' "); $log.debug "XXX output #{output} " if $log.debug? system("echo '#{output}' "); system("echo Press Enter to continue."); system("read"); } return nil # i think else # TODO # here's where we can take internal commands #alert "[#{str}] string did not match :!" str = str.to_s #= str[1..-1] cmdline = str.split cmd = cmdline.shift #.to_sym return unless cmd # added 2011-09-11 FFI f = @form.get_current_field if respond_to?(cmd, true) if cmd == "close" throw :close # other seg faults in del_panel window.destroy executes 2x else res = send cmd, *cmdline end elsif f.respond_to?(cmd, true) res = f.send(cmd, *cmdline) else alert "App: #{self.class} does not respond to #{cmd} " ret = false # what is this execute_this: some kind of general routine for all apps ? ret = execute_this(cmd, *cmdline) if respond_to?(:execute_this, true) rb_puts("#{self.class} does not respond to #{cmd} ", :color_pair => $promptcolor) unless ret # should be able to say in red as error end end end |
#hline(config = {}) ⇒ Object
displays a horizontal line takes col (column to start from) from current stack take row from app_row
requires width to be passed in config, else defaults to 20
391 392 393 394 395 396 397 398 399 400 401 402 |
# File 'lib/canis/core/util/app.rb', line 391 def hline config={} row = config[:row] || @app_row width = config[:width] || 20 _position config col = config[:col] || 1 @color_pair = config[:color_pair] || $datacolor @attrib = config[:attrib] || Ncurses::A_NORMAL @window.attron(Ncurses.COLOR_PAIR(@color_pair) | @attrib) @window.mvwhline( row, col, FFI::NCurses::ACS_HLINE, width) @window.attron(Ncurses.COLOR_PAIR(@color_pair) | @attrib) @app_row += 1 end |
#init_vars ⇒ Object
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/canis/core/util/app.rb', line 97 def init_vars @quit_key ||= FFI::NCurses::KEY_F10 # actually this should be maintained inside ncurses pack, so not loaded 2 times. # this way if we call an app from existing program, App won't start ncurses. unless $ncurses_started init_ncurses end $lastline = Ncurses.LINES - 1 #@message_row = Ncurses.LINES-1 #@prompt_row = @message_row # hope to use for ask etc # 2011-10-17 14:06:27 unless $log logpath=ENV["CANIS_LOG_PATH"] $log = create_logger(logpath || "/dev/null") end end |
#keypress(&block) ⇒ Object
returns a symbol of the key pressed e.g. :C_c for Ctrl-C :Space, :bs, :M_d etc NOTE 2014-08-15 Trying with just string returned by keycode_tos This should allow for simpler apps that want to handle keys perhaps taken from a config file
rather than bind each key manually.
208 209 210 |
# File 'lib/canis/core/util/app.rb', line 208 def keypress &block @keyblock = block end |
#logger ⇒ Object
112 |
# File 'lib/canis/core/util/app.rb', line 112 def logger; return $log; end |
#loop(&block) ⇒ Object
This method is called by run, and thus in most cases this is what is used. run
calls this without a block not sure, but user shuld be able to trap keystrokes if he wants but do i still call handle_key if he does, or give him total control. But loop is already called by framework
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/canis/core/util/app.rb', line 129 def loop &block @form.repaint @window.wrefresh Ncurses::Panel.update_panels @break_key = ?\C-q.getbyte(0) # added this extra loop since from some places we exit using throw :close # amd that was in a much higher place, and was getting us right out, with # no chance of user canceling quit. This extra loop allows us to remain # added on 2011-11-24 while true catch :close do while((ch = @window.getchar()) != 999 ) #break if ch == @break_key if ch == @break_key || ch == @quit_key #stopping = @window.fire_close_handler #break if stopping.nil? || stopping break end # execute a code block so caller program can handle keys from a hash or whatever. # Currently this has the issue that the key is still evaluated again in the next block # - A double evaluation can happen # - these keys will not appear in help # FIXME if @keyblock str = keycode_tos ch # why did we ever want to convert to a symbol. why not just pass it as is. #@keyblock.call(str.gsub(/-/, "_").to_sym) # not used ever ret = @keyblock.call(str) @form.repaint if ret end yield ch if block # <<<---- # this is what the user should have control ove. earlier we would put this in # a try catch block so user could do what he wanted with the error. Now we # need to get it to him somehow, perhaps through a block or on_error event begin @form.handle_key ch rescue => err $log.debug( "handle_key rescue reached ") $log.debug( err.to_s) $log.debug(err.backtrace.join("\n")) textdialog [err.to_s, *err.backtrace], :title => "Exception" end #@form.repaint # was this duplicate ?? handle calls repaint not needed @window.wrefresh end end # catch stopping = @window.fire_close_handler @window.wrefresh break if stopping.nil? || stopping end # while end |
#message(text) ⇒ Object
updates a global var with text. Calling app has to set up a Variable with that name and attach to a label so it can be printed.
213 214 215 |
# File 'lib/canis/core/util/app.rb', line 213 def text $status_message.value = text # trying out 2011-10-9 end |
#safe_loop(&block) ⇒ Object
if calling loop separately better to call this, since it will shut off ncurses and print error on screen.
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
# File 'lib/canis/core/util/app.rb', line 184 def safe_loop &block begin loop &block rescue => ex $log.debug( "APP.rb rescue reached ") $log.debug( ex) if ex $log.debug(ex.backtrace.join("\n")) if ex ensure close # putting it here allows it to be printed on screen, otherwise it was not showing at all. if ex puts "========== EXCEPTION ==========" p ex puts "===============================" puts(ex.backtrace.join("\n")) end end end |
#suspend(clear = true) ⇒ Object
suspends curses so you can play around on the shell or in cooked mode like Vim does. Expects a block to be passed. Purpose: you can print some stuff without creating a window, or just run shell commands without coming out. NOTE: if you pass clear as true, then the screen will be cleared and you can use puts or print to print. You may have to flush. However, with clear as false, the screen will not be cleared. You will have to print using printw, and if you expect user input you must do a “system /bin/stty sane” If you print stuff, you will have to put a getch() or system(“read”) to pause the screen.
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 |
# File 'lib/canis/core/util/app.rb', line 233 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 @window.wrefresh Ncurses::Panel.update_panels end |