Module: Clack::Core::OptionsHelper
- Included in:
- Prompts::Autocomplete, Prompts::AutocompleteMultiselect, Prompts::Multiselect, Prompts::Path, Prompts::Select
- Defined in:
- lib/clack/core/options_helper.rb
Overview
Shared functionality for option-based prompts (Select, Multiselect, Autocomplete, etc.). Handles option normalization, cursor navigation, and scrolling.
Including classes must define:
-
@max_items [Integer, nil] maximum visible items (nil = show all)
-
@option_index [Integer] current selection index
-
@scroll_offset [Integer] current scroll position
Including classes must implement:
-
navigable_items[Array] returns the current list to navigate
Class Method Summary collapse
-
.normalize_option(opt) ⇒ Option
Normalize a single option to an Option value object.
Instance Method Summary collapse
-
#find_initial_cursor(initial_value) ⇒ Integer
Find initial cursor position based on initial value or first enabled option.
-
#find_next_enabled(from, delta) ⇒ Integer
Find the next enabled option in the given direction.
-
#first_enabled_index ⇒ Integer
Index of the first enabled option.
-
#move_cursor(delta) ⇒ Object
Move option_index in the given direction, skipping disabled options.
-
#move_selection(delta) ⇒ Object
Move the selection index by delta, wrapping around.
-
#navigable_items ⇒ Array
The list of items to navigate.
-
#normalize_options(options) ⇒ Array<Hash>
Normalize options to a consistent hash format.
-
#update_scroll ⇒ Object
Update scroll offset to keep option_index visible within the window.
-
#visible_options ⇒ Array<Hash>
Get the currently visible options based on scroll offset and max_items.
Class Method Details
.normalize_option(opt) ⇒ Option
Normalize a single option to an Option value object.
56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/clack/core/options_helper.rb', line 56 def self.normalize_option(opt) case opt when Hash Option.new( value: opt[:value], label: opt[:label] || opt[:value].to_s, hint: opt[:hint], disabled: opt[:disabled] || false ) else Option.new(value: opt, label: opt.to_s, hint: nil, disabled: false) end end |
Instance Method Details
#find_initial_cursor(initial_value) ⇒ Integer
Find initial cursor position based on initial value or first enabled option.
142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/clack/core/options_helper.rb', line 142 def find_initial_cursor(initial_value) items = navigable_items return 0 if items.empty? if initial_value.nil? # Start at first enabled option return items[0].disabled ? first_enabled_index : 0 end idx = items.find_index { |o| o.value == initial_value } (idx && !items[idx].disabled) ? idx : first_enabled_index end |
#find_next_enabled(from, delta) ⇒ Integer
Find the next enabled option in the given direction. Wraps around the list if necessary.
76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/clack/core/options_helper.rb', line 76 def find_next_enabled(from, delta) items = navigable_items max = items.length idx = (from + delta) % max max.times do return idx unless items[idx].disabled idx = (idx + delta) % max end from end |
#first_enabled_index ⇒ Integer
Index of the first enabled option.
92 93 94 |
# File 'lib/clack/core/options_helper.rb', line 92 def first_enabled_index find_next_enabled(-1, 1) end |
#move_cursor(delta) ⇒ Object
Move option_index in the given direction, skipping disabled options.
99 100 101 102 |
# File 'lib/clack/core/options_helper.rb', line 99 def move_cursor(delta) @option_index = find_next_enabled(@option_index, delta) update_scroll end |
#move_selection(delta) ⇒ Object
Move the selection index by delta, wrapping around. Unlike move_cursor, does not skip disabled items.
108 109 110 111 112 113 114 |
# File 'lib/clack/core/options_helper.rb', line 108 def move_selection(delta) items = navigable_items return if items.empty? @option_index = (@option_index + delta) % items.length update_scroll end |
#navigable_items ⇒ Array
The list of items to navigate. Override in subclasses that use a filtered or dynamic list (e.g., Autocomplete uses @filtered).
158 159 160 |
# File 'lib/clack/core/options_helper.rb', line 158 def navigable_items @options end |
#normalize_options(options) ⇒ Array<Hash>
Normalize options to a consistent hash format. Accepts strings, symbols, or hashes with value/label/hint/disabled keys.
47 48 49 50 51 |
# File 'lib/clack/core/options_helper.rb', line 47 def () raise ArgumentError, "options cannot be empty" if .nil? || .empty? .map { |opt| OptionsHelper.normalize_option(opt) } end |
#update_scroll ⇒ Object
Update scroll offset to keep option_index visible within the window.
127 128 129 130 131 132 133 134 135 136 |
# File 'lib/clack/core/options_helper.rb', line 127 def update_scroll items = navigable_items return unless @max_items && items.length > @max_items if @option_index < @scroll_offset @scroll_offset = @option_index elsif @option_index >= @scroll_offset + @max_items @scroll_offset = @option_index - @max_items + 1 end end |
#visible_options ⇒ Array<Hash>
Get the currently visible options based on scroll offset and max_items.
119 120 121 122 123 124 |
# File 'lib/clack/core/options_helper.rb', line 119 def items = navigable_items return items unless @max_items && items.length > @max_items items[@scroll_offset, @max_items] end |