class TTY::Prompt::MultiList
A class responsible for rendering multi select list menu. Used by {Prompt} to display interactive choice menu.
@api private
Public Class Methods
Create instance of TTY::Prompt::MultiList menu.
@param [Prompt] :prompt @param [Hash] options
@api public
# File lib/tty/prompt/multi_list.rb, line 18 def initialize(prompt, **options) super @selected = SelectedChoices.new @help = options[:help] @echo = options.fetch(:echo, true) @min = options[:min] @max = options[:max] end
Public Instance Methods
Selects all choices when Ctrl+A is pressed
@api private
# File lib/tty/prompt/multi_list.rb, line 70 def keyctrl_a(*) return if @max && @max < choices.size @selected = SelectedChoices.new(choices.enabled, choices.enabled_indexes) end
Revert currently selected choices when Ctrl+I is pressed
@api private
# File lib/tty/prompt/multi_list.rb, line 79 def keyctrl_r(*) return if @max && @max < choices.size indexes = choices.each_with_index.reduce([]) do |acc, (choice, idx)| acc << idx if !choice.disabled? && !@selected.include?(choice) acc end @selected = SelectedChoices.new(choices.enabled - @selected.to_a, indexes) end
Callback fired when enter/return key is pressed
@api private
# File lib/tty/prompt/multi_list.rb, line 44 def keyenter(*) valid = true valid = @min <= @selected.size if @min valid = @selected.size <= @max if @max super if valid end
Callback fired when space key is pressed
@api private
# File lib/tty/prompt/multi_list.rb, line 56 def keyspace(*) active_choice = choices[@active - 1] if @selected.include?(active_choice) @selected.delete_at(@active - 1) else return if @max && @selected.size >= @max @selected.insert(@active - 1, active_choice) end end
Set a maximum number of choices
@api public
# File lib/tty/prompt/multi_list.rb, line 37 def max(value) @max = value end
Set a minimum number of choices
@api public
# File lib/tty/prompt/multi_list.rb, line 30 def min(value) @min = value end
Private Instance Methods
All values for the choices selected
@return [Array]
@api private
# File lib/tty/prompt/multi_list.rb, line 188 def answer @selected.map(&:value) end
Build a default help text
@return [String]
@api private
# File lib/tty/prompt/multi_list.rb, line 143 def default_help str = [] str << "(Press " str << "#{arrows_help} arrow" str << " or 1-#{choices.size} number" if enumerate? str << " to move, Space" str << "/Ctrl+A|R" if @max.nil? str << " to select" str << " (all|rev)" if @max.nil? str << (filterable? ? "," : " and") str << " Enter to finish" str << " and letters to filter" if filterable? str << ")" str.join end
Header part showing the minimum/maximum number of choices
@return [String]
@api private
# File lib/tty/prompt/multi_list.rb, line 131 def minmax_help help = [] help << "min. #{@min}" if @min help << "max. #{@max}" if @max "(%s) " % [help.join(", ")] end
Render initial help text and then currently selected choices
@api private
# File lib/tty/prompt/multi_list.rb, line 162 def render_header instructions = @prompt.decorate(help, @help_color) minmax_suffix = @min || @max ? minmax_help : "" print_selected = @selected.size.nonzero? && @echo if @done && @echo @prompt.decorate(selected_names, @active_color) elsif (@first_render && (help_start? || help_always?)) || (help_always? && !@filter.any? && !@done) minmax_suffix + (print_selected ? "#{selected_names} " : "") + instructions elsif filterable? && @filter.any? minmax_suffix + (print_selected ? "#{selected_names} " : "") + @prompt.decorate(filter_help, @help_color) else minmax_suffix + (print_selected ? selected_names : "") end end
Generate selected items names
@return [String]
@api private
# File lib/tty/prompt/multi_list.rb, line 122 def selected_names @selected.map(&:name).join(", ") end
Setup default options and active selection
@api private
# File lib/tty/prompt/multi_list.rb, line 94 def setup_defaults validate_defaults # At this stage, @choices matches all the visible choices. default_indexes = @default.map do |d| if d.to_s =~ INTEGER_MATCHER d - 1 else choices.index(choices.find_by(:name, d.to_s)) end end @selected = SelectedChoices.new(@choices.values_at(*default_indexes), default_indexes) if @default.empty? # no default, pick the first non-disabled choice @active = choices.index { |choice| !choice.disabled? } + 1 elsif @default.last.to_s =~ INTEGER_MATCHER @active = @default.last elsif default_choice = choices.find_by(:name, @default.last.to_s) @active = choices.index(default_choice) + 1 end end