Class: InputSequencer

Inherits:
Object show all
Defined in:
lib/input_sequencer.rb

Overview

InputSequencer manages the sequence of menu interactions and block executions based on user input.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(document_filename, initial_blocks = nil) ⇒ InputSequencer

Returns a new instance of InputSequencer.



18
19
20
21
22
23
# File 'lib/input_sequencer.rb', line 18

def initialize(document_filename, initial_blocks = nil)
  @document_filename = document_filename
  @current_block = nil
  @block_queue = initial_blocks
  @debug = Env::env_bool('INPUT_SEQUENCER_DEBUG', default: false) ### false e
end

Instance Attribute Details

#block_queueObject (readonly)

self.prepend InstanceMethodWrapper # traps initialize as well



16
17
18
# File 'lib/input_sequencer.rb', line 16

def block_queue
  @block_queue
end

#current_blockObject (readonly)

self.prepend InstanceMethodWrapper # traps initialize as well



16
17
18
# File 'lib/input_sequencer.rb', line 16

def current_block
  @current_block
end

#document_filenameObject (readonly)

self.prepend InstanceMethodWrapper # traps initialize as well



16
17
18
# File 'lib/input_sequencer.rb', line 16

def document_filename
  @document_filename
end

Class Method Details

Merges the current menu state with the next, prioritizing the next state’s values.



26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/input_sequencer.rb', line 26

def self.merge_link_state(current, next_state)
  MarkdownExec::LinkState.new(
    block_name: next_state.block_name,
    display_menu: next_state.display_menu.nil? ? current.display_menu : next_state.display_menu,
    document_filename: next_state.document_filename || current.document_filename,
    inherited_block_names: next_state.inherited_block_names,
    inherited_dependencies: next_state.inherited_dependencies,
    inherited_lines: next_state.inherited_lines,
    prior_block_was_link: next_state.prior_block_was_link.nil? ? current.prior_block_was_link : next_state.prior_block_was_link
  )
rescue
  pp backtrace
  binding.irb
end

Generates the next menu state based on provided attributes.



43
44
45
46
47
48
49
50
# File 'lib/input_sequencer.rb', line 43

def self.next_link_state(block_name: nil, display_menu: nil, document_filename: nil, prior_block_was_link: false)
  MarkdownExec::LinkState.new(
    block_name: block_name,
    display_menu: display_menu,
    document_filename: document_filename,
    prior_block_was_link: prior_block_was_link
  )
end

Instance Method Details

#bq_is_empty?Boolean

Returns:

  • (Boolean)


57
58
59
# File 'lib/input_sequencer.rb', line 57

def bq_is_empty?
  !@block_queue || @block_queue.empty?
end

#run(&block) ⇒ Object

Orchestrates the flow of menu states and user interactions.



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/input_sequencer.rb', line 62

def run(&block)
  now_menu = InputSequencer.next_link_state(
    display_menu: bq_is_empty?,
    document_filename: @document_filename,
    prior_block_was_link: false # true bypass_exit when last block was a link (from cli)
  )
  exit_when_bq_empty = !bq_is_empty? # true when running blocks from cli; unless "stay" is used
  loop do
    break if run_yield(:parse_document, now_menu.document_filename, &block) == :break

    pp [__LINE__, 'exit_when_bq_empty', exit_when_bq_empty, '@block_queue', @block_queue, 'now_menu', now_menu] if @debug
    # self.imw_ins now_menu, 'now_menu'

    break if exit_when_bq_empty && bq_is_empty? && !now_menu.prior_block_was_link

    if now_menu.display_menu
      exit_when_bq_empty = false
      run_yield :display_menu, &block

      choice = run_yield :user_choice, &block

      if choice.nil?
        raise "Block not recognized."
        break
      end
      break if run_yield(:exit?, choice&.downcase, &block) # Exit loop and method to terminate the app

      next_state = run_yield :execute_block, choice, &block
      # imw_ins next_state, 'next_state'
      pp [__LINE__, 'next_state', next_state] if @debug
      return :break if next_state == :break

      next_menu = next_state

    else
      if now_menu.block_name && !now_menu.block_name.empty?
        block_name = now_menu.block_name
      else
        break if bq_is_empty? # Exit loop if no more blocks to process

        block_name = @block_queue.shift
      end
      # self.imw_ins block_name, 'block_name'
      pp [__LINE__, 'block_name', block_name] if @debug

      next_menu = if block_name == '.'
                    exit_when_bq_empty = false
                    InputSequencer.next_link_state(display_menu: true)
                  else
                    state = run_yield :execute_block, block_name, &block
                    state.display_menu = bq_is_empty?
                    state
                  end
      pp [__LINE__, 'next_menu', next_menu] if @debug
      next_menu
      # imw_ins next_menu, 'next_menu'
    end
    now_menu = InputSequencer.merge_link_state(now_menu, next_menu)
  end
rescue
  pp backtrace
  binding.irb
end

#run_yield(sym, *args, &block) ⇒ Object

Orchestrates the flow of menu states and user interactions.



53
54
55
# File 'lib/input_sequencer.rb', line 53

def run_yield(sym, *args, &block)
  block.call sym, *args
end