Class: Menu
- Inherits:
-
Gloo::Core::Obj
- Object
- Gloo::Core::Obj
- Menu
- Defined in:
- lib/menu.rb
Overview
- Author
Eric Crane (mailto:eric.crane@mac.com)
- Copyright
Copyright (c) 2020 Eric Crane. All rights reserved.
A CLI menu. The menu contains a collection of menu items, a prompt and an option to loop until done.
Constant Summary collapse
- KEYWORD =
'menu'.freeze
- KEYWORD_SHORT =
'menu'.freeze
- PROMPT =
'prompt'.freeze
- ITEMS =
'items'.freeze
- LOOP =
'loop'.freeze
- HIDE_ITEMS =
'hide_items'.freeze
- BEFORE_MENU =
'before_menu'.freeze
- DEFAULT =
'default'.freeze
- TITLE =
'title'.freeze
- TITLE_COLOR =
'green'.freeze
- QUIT_ITEM_NAME =
'q'.freeze
[]
Class Method Summary collapse
-
.doc_data ⇒ Object
Get the object's documentation data.
-
.messages ⇒ Object
Get a list of message names that this object receives.
-
.short_typename ⇒ Object
The short name of the object type.
-
.typename ⇒ Object
The name of the object type.
Instance Method Summary collapse
-
#add_children_on_create? ⇒ Boolean
Does this object have children to add when an object is created in interactive mode? This does not apply during obj load, etc.
-
#add_default_children ⇒ Object
Add children to this object.
-
#add_loop_child ⇒ Object
If there is no loop child, add it.
-
#add_quit_item ⇒ Object
Add a Quit menu item.
-
#begin_menu ⇒ Object
Begin the menu execution.
-
#find_cmd(cmd) ⇒ Object
Find the command matching user input.
-
#lazy_add_children ⇒ Object
Add any required children not specified in the source.
-
#loop? ⇒ Boolean
Get the value of the loop child object.
-
#msg_run ⇒ Object
Show the menu options, and prompt for user input.
-
#pop_menu(menu) ⇒ Object
Pop a menu from the stack.
-
#pop_to_top_level_menu ⇒ Object
Quit all menus and drop into gloo.
-
#prompt_value ⇒ Object
Get the value of the prompt child object.
-
#push_menu(obj) ⇒ Object
Add a menu to the stack.
-
#quit_all_menus ⇒ Object
Quit all menus and drop into gloo.
-
#run_before_menu ⇒ Object
If there is a before menu script, run it now.
-
#run_command(cmd) ⇒ Object
Run the selected command.
-
#run_default ⇒ Object
Run the default option.
-
#run_default_title ⇒ Object
There is a title, so show it.
-
#show_menu_stack ⇒ Object
Show the bread-crumbs for the menu stack.
-
#show_options ⇒ Object
Show the list of menu options.
-
#title ⇒ Object
Get the Menu's Title.
-
#title? ⇒ Boolean
Does the menu have a title?.
Class Method Details
.doc_data ⇒ Object
Get the object's documentation data.
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 |
# File 'lib/menu.rb', line 373 def self.doc_data { :name => KEYWORD, :shortcut => KEYWORD_SHORT, :description => 'A CLI menu. This can be used for the main loop ' \ 'of a CLI application. Many of the children are optional; some ' \ 'will be created dynamically if they are not specified in the ' \ 'source file. Note that a Quit menu item will be added ' \ 'dynamically if one is not specified in the source file.', :children => [ "prompt (string) — Default: '> '. Optional; if not provided a default timestamp option is used. The prompt shown for menu item selection.", 'items (container) — The list of menu items.', 'loop (boolean) — Run the menu in a loop? If true, once a menu item has run, the menu prompts again; setting it to false ends the menu. Created dynamically if not specified.', 'title (string) — Optional title to use rather than manually implementing a menu header. With a title, the default and before_menu items are not needed.', 'hide_items (boolean) — Optional, false by default. If false, the menu items are shown each time through the loop; if true, they\'re hidden (can always be shown by typing ? at the prompt).', 'default (script) — Optional. Run if no other option is selected (RETURN pressed). Can be used to clear the screen, for example.', 'before_menu (script) — Optional. Run at the top of each loop through the menu.' ], :messages => [ 'run — Show the options and the prompt, then run the script for the user\'s selection. Optionally repeat as long as the loop child is true.' ], :notes => 'Built-in menu items, always available: q — quit this ' \ 'menu (quits the app if this is the root menu, or goes up to ' \ 'the prior menu if a sub-menu); qq — quit to the top level ' \ 'menu (not shown); q! — quit gloo entirely (not shown); ' \ ': {command} — run a gloo command not part of the running app; ' \ ': (alone) — quit the running app and drop into gloo, keeping ' \ 'loaded app objects in the stack.', :examples => <<~EXAMPLES.strip simple [menu] : on_load [script] : run simple title [string] : Simple Menu items [can] : h [mitem] : Run Hello World do [script] : show 'Hello World!' menu [menu] : on_load [script] : run menu prompt [string] : > loop [bool] : true items [can] : hw [mitem] : shortcut [str] : hw description [str] : Run Hello World do [script] : show 'Hello World!' q [mitem] : shortcut [str] : q description [str] : Quit this menu do [script] : put false into menu.loop EXAMPLES } end |
.messages ⇒ Object
Get a list of message names that this object receives.
217 218 219 |
# File 'lib/menu.rb', line 217 def self. return super + [ 'run' ] end |
.short_typename ⇒ Object
The short name of the object type.
35 36 37 |
# File 'lib/menu.rb', line 35 def self.short_typename return KEYWORD_SHORT end |
.typename ⇒ Object
The name of the object type.
28 29 30 |
# File 'lib/menu.rb', line 28 def self.typename return KEYWORD end |
Instance Method Details
#add_children_on_create? ⇒ Boolean
Does this object have children to add when an object is created in interactive mode? This does not apply during obj load, etc.
130 131 132 |
# File 'lib/menu.rb', line 130 def add_children_on_create? return true end |
#add_default_children ⇒ Object
Add children to this object. This is used by containers to add children needed for default configurations.
139 140 141 142 143 144 145 |
# File 'lib/menu.rb', line 139 def add_default_children fac = @engine.factory fac.create_string PROMPT, '> ', self fac.create_can ITEMS, self fac.create_bool LOOP, true, self fac.create_script DEFAULT, '', self end |
#add_loop_child ⇒ Object
If there is no loop child, add it.
66 67 68 69 70 71 72 73 74 75 |
# File 'lib/menu.rb', line 66 def add_loop_child o = find_child LOOP if o o.set_value true return end fac = @engine.factory fac.create_bool LOOP, true, self end |
#add_quit_item ⇒ Object
Add a Quit menu item
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/menu.rb', line 80 def add_quit_item items = find_child ITEMS q = items.find_child QUIT_ITEM_NAME return if q fac = @engine.factory fac.create_bool LOOP, true, self params = { :name => QUIT_ITEM_NAME, :type => 'mitem', :value => 'Quit', :parent => items } mitem = fac.create params script = "put false into #{self.pn}.loop" fac.create_script 'do', script, mitem end |
#begin_menu ⇒ Object
Begin the menu execution. Run the before menu script if there is one, then show options unless we are hiding them by default.
253 254 255 256 257 258 259 260 261 |
# File 'lib/menu.rb', line 253 def # Check to see if we should show items at all. o = find_child HIDE_ITEMS return if o && o.value == true end |
#find_cmd(cmd) ⇒ Object
Find the command matching user input.
289 290 291 292 293 294 295 296 297 298 299 |
# File 'lib/menu.rb', line 289 def find_cmd( cmd ) o = find_child ITEMS return nil unless o o.children.each do |mitem| mitem = Gloo::Objs::Alias.resolve_alias( @engine, mitem ) return mitem if mitem.shortcut_value.downcase == cmd.downcase end return nil end |
#lazy_add_children ⇒ Object
Add any required children not specified in the source.
100 101 102 103 |
# File 'lib/menu.rb', line 100 def lazy_add_children add_loop_child add_quit_item end |
#loop? ⇒ Boolean
Get the value of the loop child object. Should we keep looping or should we stop?
54 55 56 57 58 59 60 61 |
# File 'lib/menu.rb', line 54 def loop? return false unless @engine.running o = find_child LOOP return false unless o return o.value end |
#msg_run ⇒ Object
Show the menu options, and prompt for user input.
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |
# File 'lib/menu.rb', line 224 def msg_run lazy_add_children self run_default loop do if prompt_value.empty? dt = DateTime.now d = dt.strftime( '%Y.%m.%d' ) t = dt.strftime( '%I:%M:%S' ) cmd = @engine.platform.prompt.ask( "#{d.yellow} #{t.white} >" ) else cmd = @engine.platform.prompt.ask( prompt_value ) end cmd ? run_command( cmd ) : run_default break unless loop? end self end |
#pop_menu(menu) ⇒ Object
Pop a menu from the stack. If the last item isn't the given menu, it won't be popped.
180 181 182 183 184 |
# File 'lib/menu.rb', line 180 def if @@menu_stack[-1] == @@menu_stack.pop end end |
#pop_to_top_level_menu ⇒ Object
Quit all menus and drop into gloo.
189 190 191 192 193 194 195 196 |
# File 'lib/menu.rb', line 189 def @engine.log.debug 'Quitting to top level menu' while @@menu_stack.count > 1 = @@menu_stack.pop o = .find_child LOOP o.set_value( false ) if o end end |
#prompt_value ⇒ Object
Get the value of the prompt child object. Returns nil if there is none.
43 44 45 46 47 48 |
# File 'lib/menu.rb', line 43 def prompt_value o = find_child PROMPT return '' unless o return o.value end |
#push_menu(obj) ⇒ Object
Add a menu to the stack.
171 172 173 |
# File 'lib/menu.rb', line 171 def obj @@menu_stack << obj end |
#quit_all_menus ⇒ Object
Quit all menus and drop into gloo.
201 202 203 204 205 206 207 208 |
# File 'lib/menu.rb', line 201 def @engine.log.debug 'Dropping into Gloo' @@menu_stack.each do || o = .find_child LOOP o.set_value( false ) if o end @engine.loop end |
#run_before_menu ⇒ Object
If there is a before menu script, run it now.
266 267 268 269 270 271 |
# File 'lib/menu.rb', line 266 def o = find_child BEFORE_MENU return unless o Gloo::Exec::Dispatch.( @engine, 'run', o ) end |
#run_command(cmd) ⇒ Object
Run the selected command.
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 |
# File 'lib/menu.rb', line 328 def run_command( cmd ) @engine.log.info "Menu Command: #{cmd}" obj = find_cmd cmd if obj script = obj.do_script return unless script s = Gloo::Exec::Script.new( @engine, script ) s.run else if cmd == '?' @engine.log.debug 'Showing options' elsif cmd == 'q!' @engine.log.debug 'Quitting Gloo' @engine.stop_running elsif cmd == 'qq' @engine.log.debug 'Quitting to top level menu' elsif cmd.starts_with? ':' gloo_cmd = cmd[1..-1].strip if gloo_cmd.blank? @engine.log.debug 'Quitting all menus and dropping into Gloo' else @engine.log.debug "Running Gloo command: #{gloo_cmd}" @engine.process_cmd gloo_cmd end else msg = "#{cmd} is not a valid option" @engine.log.warn msg end return end end |
#run_default ⇒ Object
Run the default option.
304 305 306 307 308 309 310 311 312 |
# File 'lib/menu.rb', line 304 def run_default obj = find_child DEFAULT if obj s = Gloo::Exec::Script.new( @engine, obj ) s.run elsif title? run_default_title end end |
#run_default_title ⇒ Object
There is a title, so show it.
317 318 319 320 321 322 323 |
# File 'lib/menu.rb', line 317 def run_default_title @engine.platform&.clear_screen title_text = @engine.platform.table.box( title ) puts title_text.colorize( :color => :white, :background => :black ) end |
#show_menu_stack ⇒ Object
Show the bread-crumbs for the menu stack.
154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/menu.rb', line 154 def if @@menu_stack.count < 2 puts '...' else msg = '' @@menu_stack[0..-2].each do || msg << ' | ' unless msg.blank? msg << .title end msg << ' | ... ' puts msg end end |
#show_options ⇒ Object
Show the list of menu options.
276 277 278 279 280 281 282 283 284 |
# File 'lib/menu.rb', line 276 def o = find_child ITEMS return unless o o.children.each do |mitem| mitem = Gloo::Objs::Alias.resolve_alias( @engine, mitem ) puts " #{mitem.shortcut_value} - #{mitem.description_value}" end end |
#title ⇒ Object
Get the Menu's Title.
116 117 118 119 |
# File 'lib/menu.rb', line 116 def title obj = find_child TITLE return obj.value end |
#title? ⇒ Boolean
Does the menu have a title?
108 109 110 111 |
# File 'lib/menu.rb', line 108 def title? o = find_child TITLE return o ? true : false end |