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_list(options) ⇒ Array<Option>
Normalize a list of raw options without the empty check.
-
.normalize_option(opt) ⇒ Option
Normalize a single option to an Option value object.
-
.option_entries(options) ⇒ Array
Expand the Hash shorthand (value => label, or value => spec Hash) into the Array-of-entries shape that OptionsHelper.normalize_option understands.
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<Option>
Normalize options to a consistent list of Option value objects.
-
#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_list(options) ⇒ Array<Option>
Normalize a list of raw options without the empty check. Used by prompts that build their own list (e.g. GroupMultiselect groups).
60 61 62 |
# File 'lib/clack/core/options_helper.rb', line 60 def self.normalize_list() option_entries().map { |opt| normalize_option(opt) } end |
.normalize_option(opt) ⇒ Option
Normalize a single option to an Option value object.
93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/clack/core/options_helper.rb', line 93 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 |
.option_entries(options) ⇒ Array
Expand the Hash shorthand (value => label, or value => spec Hash) into the Array-of-entries shape that normalize_option understands. Anything that is not a Hash is returned unchanged.
71 72 73 74 75 |
# File 'lib/clack/core/options_helper.rb', line 71 def self.option_entries() return unless .is_a?(Hash) .map { |value, spec| hash_entry(value, spec) } end |
Instance Method Details
#find_initial_cursor(initial_value) ⇒ Integer
Find initial cursor position based on initial value or first enabled option.
179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/clack/core/options_helper.rb', line 179 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.
113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/clack/core/options_helper.rb', line 113 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.
129 130 131 |
# File 'lib/clack/core/options_helper.rb', line 129 def first_enabled_index find_next_enabled(-1, 1) end |
#move_cursor(delta) ⇒ Object
Move option_index in the given direction, skipping disabled options.
136 137 138 139 |
# File 'lib/clack/core/options_helper.rb', line 136 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.
145 146 147 148 149 150 151 |
# File 'lib/clack/core/options_helper.rb', line 145 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).
195 196 197 |
# File 'lib/clack/core/options_helper.rb', line 195 def navigable_items @options end |
#normalize_options(options) ⇒ Array<Option>
Normalize options to a consistent list of Clack::Core::Option value objects.
Accepts an Array of strings, symbols, or hashes with value/label/hint/disabled keys, or a Hash of value => label (or value => hint:, disabled:).
49 50 51 52 53 |
# File 'lib/clack/core/options_helper.rb', line 49 def () raise ArgumentError, "options cannot be empty" if .nil? || .empty? OptionsHelper.normalize_list() end |
#update_scroll ⇒ Object
Update scroll offset to keep option_index visible within the window.
164 165 166 167 168 169 170 171 172 173 |
# File 'lib/clack/core/options_helper.rb', line 164 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.
156 157 158 159 160 161 |
# File 'lib/clack/core/options_helper.rb', line 156 def items = navigable_items return items unless @max_items && items.length > @max_items items[@scroll_offset, @max_items] end |