Class: Menu

Inherits:
Gloo::Core::Obj
  • Object
show all
Defined in:
lib/menu.rb

Overview

Author

Eric Crane ([email protected])

Copyright

Copyright © 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

Instance Method Summary collapse

Class Method Details

.messagesObject

Get a list of message names that this object receives.



217
218
219
# File 'lib/menu.rb', line 217

def self.messages
  return super + [ 'run' ]
end

.short_typenameObject

The short name of the object type.



35
36
37
# File 'lib/menu.rb', line 35

def self.short_typename
  return KEYWORD_SHORT
end

.typenameObject

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.

Returns:

  • (Boolean)


130
131
132
# File 'lib/menu.rb', line 130

def add_children_on_create?
  return true
end

#add_default_childrenObject

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_childObject

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_itemObject

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_menuObject

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 begin_menu
  run_before_menu

  # Check to see if we should show items at all.
  o = find_child HIDE_ITEMS
  return if o && o.value == true

  show_options
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_childrenObject

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?

Returns:

  • (Boolean)


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_runObject

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
  push_menu self
  run_default
  loop do
    begin_menu
    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
  pop_menu 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 pop_menu menu
  if @@menu_stack[-1] == menu
    @@menu_stack.pop
  end
end

#pop_to_top_level_menuObject

Quit all menus and drop into gloo.



189
190
191
192
193
194
195
196
# File 'lib/menu.rb', line 189

def pop_to_top_level_menu
  @engine.log.debug 'Quitting to top level menu'
  while @@menu_stack.count > 1
    menu = @@menu_stack.pop
    o = menu.find_child LOOP
    o.set_value( false ) if o
  end
end

#prompt_valueObject

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 push_menu obj
  @@menu_stack << obj
end

#quit_all_menusObject

Quit all menus and drop into gloo.



201
202
203
204
205
206
207
208
# File 'lib/menu.rb', line 201

def quit_all_menus
  @engine.log.debug 'Dropping into Gloo'
  @@menu_stack.each do |menu|
    o = menu.find_child LOOP
    o.set_value( false ) if o
  end
  @engine.loop
end

#run_before_menuObject

If there is a before menu script, run it now.



266
267
268
269
270
271
# File 'lib/menu.rb', line 266

def run_before_menu
  o = find_child BEFORE_MENU
  return unless o

  Gloo::Exec::Dispatch.message( @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'
      show_options
    elsif cmd == 'q!'
      @engine.log.debug 'Quitting Gloo'
      @engine.stop_running
    elsif cmd == 'qq'
      @engine.log.debug 'Quitting to top level menu'
      pop_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'
        quit_all_menus
      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_defaultObject

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_titleObject

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
  show_menu_stack

  title_text = @engine.platform.table.box( title )
  puts title_text.colorize( :color => :white, :background => :black )
end

#show_menu_stackObject

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 show_menu_stack
  if @@menu_stack.count < 2
    puts '...'
  else
    msg = ''
    @@menu_stack[0..-2].each do |menu|
      msg << ' | ' unless msg.blank?
      msg << menu.title
    end
    msg << ' | ... '
    puts msg
  end
end

#show_optionsObject

Show the list of menu options.



276
277
278
279
280
281
282
283
284
# File 'lib/menu.rb', line 276

def show_options
  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

#titleObject

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?

Returns:

  • (Boolean)


108
109
110
111
# File 'lib/menu.rb', line 108

def title?
  o = find_child TITLE
  return o ? true : false
end