class TTY::Prompt::Expander
A class responsible for rendering expanding options Used by {Prompt} to display key options question.
@api private
Constants
- DELETE_KEYS
Names for delete keys
- HELP_CHOICE
Public Class Methods
Create instance of Expander
@api public
# File lib/tty/prompt/expander.rb, line 23 def initialize(prompt, options = {}) @prompt = prompt @prefix = options.fetch(:prefix) { @prompt.prefix } @default = options.fetch(:default, 1) @auto_hint = options.fetch(:auto_hint, false) @active_color = options.fetch(:active_color) { @prompt.active_color } @help_color = options.fetch(:help_color) { @prompt.help_color } @quiet = options.fetch(:quiet) { @prompt.quiet } @choices = Choices.new @selected = nil @done = false @status = :collapsed @hint = nil @default_key = false end
Public Instance Methods
Execute this prompt
@api public
# File lib/tty/prompt/expander.rb, line 141 def call(message, possibilities, &block) choices(possibilities) @message = message block.call(self) if block setup_defaults choice(HELP_CHOICE) @prompt.subscribe(self) do render end end
Add a single choice
@api public
# File lib/tty/prompt/expander.rb, line 120 def choice(value, &block) if block @choices << value.update(value: block) else @choices << value end end
Add multiple choices
@param [Array] values
the values to add as choices
@api public
# File lib/tty/prompt/expander.rb, line 134 def choices(values) values.each { |val| choice(val) } end
# File lib/tty/prompt/expander.rb, line 43 def collapsed? @status == :collapsed end
Set default value.
@api public
# File lib/tty/prompt/expander.rb, line 104 def default(value = (not_set = true)) return @default if not_set @default = value end
# File lib/tty/prompt/expander.rb, line 47 def expand @status = :expanded end
# File lib/tty/prompt/expander.rb, line 39 def expanded? @status == :expanded end
Respond to submit event
@api public
# File lib/tty/prompt/expander.rb, line 54 def keyenter(_) if @input.nil? || @input.empty? @input = @choices[@default - 1].key @default_key = true end selected = select_choice(@input) if selected && selected.key.to_s == "h" expand @selected = nil @input = "" elsif selected @done = true @selected = selected @hint = nil else @input = "" end end
Respond to key press event
@api public
# File lib/tty/prompt/expander.rb, line 79 def keypress(event) if DELETE_KEYS.include?(event.key.name) @input.chop! unless @input.empty? elsif event.value =~ /^[^\e\n\r]/ @input += event.value end @selected = select_choice(@input) if @selected && !@default_key && collapsed? @hint = @selected.name end end
Set quiet mode.
@api public
# File lib/tty/prompt/expander.rb, line 113 def quiet(value) @quiet = value end
Select choice by given key
@return [Choice]
@api private
# File lib/tty/prompt/expander.rb, line 97 def select_choice(key) @choices.find_by(:key, key) end
Private Instance Methods
@api private
# File lib/tty/prompt/expander.rb, line 185 def answer @selected.value end
# File lib/tty/prompt/expander.rb, line 237 def load_auto_hint if @hint.nil? && collapsed? if @selected @hint = @selected.name else if @input.empty? @hint = @choices[@default - 1].name else @hint = "invalid option" end end end end
Create possible keys with current choice highlighted
@return [String]
@api private
# File lib/tty/prompt/expander.rb, line 159 def possible_keys keys = @choices.pluck(:key) default_key = keys[@default - 1] if @selected index = keys.index(@selected.key) keys[index] = @prompt.decorate(keys[index], @active_color) elsif @input.to_s.empty? && default_key keys[@default - 1] = @prompt.decorate(default_key, @active_color) end keys.join(",") end
# File lib/tty/prompt/expander.rb, line 255 def read_input @prompt.read_keypress end
Refresh the current input
@param [Integer] lines
@return [String]
@api private
# File lib/tty/prompt/expander.rb, line 266 def refresh(lines) if (@hint && (!@selected || @done)) || (@auto_hint && collapsed?) @hint = nil @prompt.clear_lines(lines, :down) + @prompt.cursor.prev_line elsif expanded? @prompt.clear_lines(lines) else @prompt.clear_line end end
@api private
# File lib/tty/prompt/expander.rb, line 172 def render @input = "" until @done question = render_question @prompt.print(question) read_input @prompt.print(refresh(question.lines.count)) end @prompt.print(render_question) unless @quiet answer end
Render message with options
@return [String]
@api private
# File lib/tty/prompt/expander.rb, line 194 def render_header header = ["#{@prefix}#{@message} "] if @done selected_item = @selected.name.to_s header << @prompt.decorate(selected_item, @active_color) elsif collapsed? header << %[(enter "h" for help) ] header << "[#{possible_keys}] " header << @input end header.join end
Show hint for selected option key
return [String]
@api private
# File lib/tty/prompt/expander.rb, line 212 def render_hint "\n" + @prompt.decorate(">> ", @active_color) + @hint + @prompt.cursor.prev_line + @prompt.cursor.forward(@prompt.strip(render_header).size) end
Render question with menu
@return [String]
@api private
# File lib/tty/prompt/expander.rb, line 224 def render_question load_auto_hint if @auto_hint header = render_header header << render_hint if @hint header << "\n" if @done if !@done && expanded? header << render_menu header << render_footer end header end
# File lib/tty/prompt/expander.rb, line 293 def setup_defaults validate_choices end
# File lib/tty/prompt/expander.rb, line 297 def validate_choices errors = [] keys = [] @choices.each do |choice| if choice.key.nil? errors << "Choice #{choice.name} is missing a :key attribute" next end if choice.key.length != 1 errors << "Choice key `#{choice.key}` is more than one character long." end if choice.key.to_s == "h" errors << "Choice key `#{choice.key}` is reserved for help menu." end if keys.include?(choice.key) errors << "Choice key `#{choice.key}` is a duplicate." end keys << choice.key if choice.key end errors.each { |err| raise ConfigurationError, err } end