class TTY::Prompt::Question

A class responsible for gathering user input

@api public

Constants

UndefinedSetting

Attributes

message[R]

Store question message @api public

messages[R]

Stores all the error messages displayed to user The currently supported messages are:

* :range?
* :required?
* :valid?
modifier[R]
validation[R]

Public Class Methods

new(prompt, **options) click to toggle source

Initialize a Question

@api public

# File lib/tty/prompt/question.rb, line 37
def initialize(prompt, **options)
  # Option deprecation
  if options[:validation]
    warn "[DEPRECATION] The `:validation` option is deprecated. Use `:validate` instead."
    options[:validate] = options[:validation]
  end

  @prompt       = prompt
  @prefix       = options.fetch(:prefix) { @prompt.prefix }
  @default      = options.fetch(:default) { UndefinedSetting }
  @required     = options.fetch(:required) { false }
  @echo         = options.fetch(:echo) { true }
  @in           = options.fetch(:in) { UndefinedSetting }
  @modifier     = options.fetch(:modifier) { [] }
  @validation   = options.fetch(:validate) { UndefinedSetting }
  @convert      = options.fetch(:convert) { UndefinedSetting }
  @active_color = options.fetch(:active_color) { @prompt.active_color }
  @help_color   = options.fetch(:help_color) { @prompt.help_color }
  @error_color  = options.fetch(:error_color) { :red }
  @value        = options.fetch(:value) { UndefinedSetting }
  @quiet        = options.fetch(:quiet) { @prompt.quiet }
  @messages     = Utils.deep_copy(options.fetch(:messages) { {} })
  @done         = false
  @first_render = true
  @input        = nil

  @evaluator = Evaluator.new(self)

  @evaluator << CheckRequired
  @evaluator << CheckDefault
  @evaluator << CheckRange
  @evaluator << CheckValidation
  @evaluator << CheckModifier
  @evaluator << CheckConversion
end

Public Instance Methods

call(message = "", &block) click to toggle source

Call the question

@param [String] message

@return [self]

@api public

# File lib/tty/prompt/question.rb, line 107
def call(message = "", &block)
  @message = message
  block.call(self) if block
  @prompt.subscribe(self) do
    render
  end
end
convert(value = (not_set = true), message = nil) click to toggle source

Specify answer conversion

@api public

# File lib/tty/prompt/question.rb, line 237
def convert(value = (not_set = true), message = nil)
  messages[:convert?] = message if message
  if not_set
    @convert
  else
    @convert = value
  end
end
convert?() click to toggle source

Check if conversion is set

@return [Boolean]

@api public

# File lib/tty/prompt/question.rb, line 251
def convert?
  @convert != UndefinedSetting
end
convert_result(value) click to toggle source

Convert value to expected type

@param [Object] value

@api private

# File lib/tty/prompt/question.rb, line 221
def convert_result(value)
  if convert? && !Utils.blank?(value)
    case @convert
    when Proc
      @convert.call(value)
    else
      Converters.convert(@convert, value)
    end
  else
    value
  end
end
default(value = (not_set = true)) click to toggle source

Set default value.

@api public

# File lib/tty/prompt/question.rb, line 258
def default(value = (not_set = true))
  return @default if not_set

  @default = value
end
default?() click to toggle source

Check if default value is set

@return [Boolean]

@api public

# File lib/tty/prompt/question.rb, line 269
def default?
  @default != UndefinedSetting
end
echo(value = nil) click to toggle source

Turn terminal echo on or off. This is used to secure the display so that the entered characters are not echoed back to the screen.

@api public

# File lib/tty/prompt/question.rb, line 331
def echo(value = nil)
  return @echo if value.nil?

  @echo = value
end
Also aliased as: echo?
echo?(value = nil)
Alias for: echo
in(value = (not_set = true), message = nil) click to toggle source

Set expected range of values

@param [String] value

@api public

# File lib/tty/prompt/question.rb, line 353
def in(value = (not_set = true), message = nil)
  messages[:range?] = message if message
  if in? && !@in.is_a?(Range)
    @in = Converters.convert(:range, @in)
  end
  return @in if not_set

  @in = Converters.convert(:range, value)
end
in?() click to toggle source

Check if range is set

@return [Boolean]

@api public

# File lib/tty/prompt/question.rb, line 368
def in?
  @in != UndefinedSetting
end
inspect() click to toggle source

String representation of this question @api public

# File lib/tty/prompt/question.rb, line 386
def inspect
  "#<#{self.class.name} @message=#{message}, @input=#{@input}>"
end
message_for(name, tokens = nil) click to toggle source

Retrieve message based on the key

@param [Symbol] name

the name of message key

@param [Hash] tokens

the tokens to evaluate

@return [Array]

@api private

# File lib/tty/prompt/question.rb, line 91
def message_for(name, tokens = nil)
  template = @messages[name]
  if template && !template.match(/\%\{/).nil?
    [template % tokens]
  else
    [template || ""]
  end
end
modify(*rules) click to toggle source

Modify string according to the rule given.

@param [Symbol] rule

@api public

# File lib/tty/prompt/question.rb, line 323
def modify(*rules)
  @modifier = rules
end
process_input(question) click to toggle source

Decide how to handle input from user

@api private

# File lib/tty/prompt/question.rb, line 161
def process_input(question)
  @input = read_input(question)
  if Utils.blank?(@input)
    @input = default? ? default : nil
  end
  @evaluator.(@input)
end
quiet(value) click to toggle source

Set quiet mode.

@api public

# File lib/tty/prompt/question.rb, line 375
def quiet(value)
  @quiet = value
end
raw(value = nil) click to toggle source

Turn raw mode on or off. This enables character-based input.

@api public

# File lib/tty/prompt/question.rb, line 341
def raw(value = nil)
  return @raw if value.nil?

  @raw = value
end
Also aliased as: raw?
raw?(value = nil)
Alias for: raw
read_input(question) click to toggle source

Process input

@api private

# File lib/tty/prompt/question.rb, line 172
def read_input(question)
  options = { echo: echo }
  if value? && @first_render
    options[:value] = @value
    @first_render = false
  end
  @prompt.read_line(question, **options).chomp
end
refresh(lines, lines_to_clear) click to toggle source

Determine area of the screen to clear

@param [Integer] lines

number of lines to clear

@return [String]

@api private

# File lib/tty/prompt/question.rb, line 201
def refresh(lines, lines_to_clear)
  output = []
  if @done
    if @errors.count.zero?
      output << @prompt.cursor.up(lines)
    else
      lines += @errors.count
      lines_to_clear += @errors.count
    end
  else
    output << @prompt.cursor.up(lines)
  end
  output.join + @prompt.clear_lines(lines_to_clear)
end
render() click to toggle source

Read answer and convert to type

@api private

# File lib/tty/prompt/question.rb, line 118
def render
  @errors = []
  until @done
    result = process_input(render_question)
    if result.failure?
      @errors = result.errors
      @prompt.print(render_error(result.errors))
    else
      @done = true
    end
    question    = render_question
    input_line  = question + result.value.to_s
    total_lines = @prompt.count_screen_lines(input_line)
    @prompt.print(refresh(question.lines.count, total_lines))
  end
  @prompt.print(render_question) unless @quiet
  result.value
end
render_error(errors) click to toggle source

Handle error condition

@return [String]

@api private

# File lib/tty/prompt/question.rb, line 186
def render_error(errors)
  errors.reduce([]) do |acc, err|
    acc << @prompt.decorate(">>", :red) + " " + err
    acc
  end.join("\n")
end
render_question() click to toggle source

Render question

@return [String]

@api private

# File lib/tty/prompt/question.rb, line 142
def render_question
  header = []
  if !Utils.blank?(@prefix) || !Utils.blank?(message)
    header << "#{@prefix}#{message} "
  end
  if !echo?
    header
  elsif @done
    header << @prompt.decorate(@input.to_s, @active_color)
  elsif default? && !Utils.blank?(@default)
    header << @prompt.decorate("(#{default})", @help_color) + " "
  end
  header << "\n" if @done
  header.join
end
required(value = (not_set = true), message = nil) click to toggle source

Ensure that passed argument is present or not

@return [Boolean]

@api public

# File lib/tty/prompt/question.rb, line 278
def required(value = (not_set = true), message = nil)
  messages[:required?] = message if message
  return @required if not_set

  @required = value
end
Also aliased as: required?
required?(value = (not_set = true), message = nil)
Alias for: required
to_s() click to toggle source

@api public

# File lib/tty/prompt/question.rb, line 380
def to_s
  message.to_s
end
validate(value = nil, message = nil, &block) click to toggle source

Set validation rule for an argument

@param [Object] value

@return [Question]

@api public

# File lib/tty/prompt/question.rb, line 293
def validate(value = nil, message = nil, &block)
  messages[:valid?] = message if message
  @validation = (value || block)
end
validation?() click to toggle source
# File lib/tty/prompt/question.rb, line 314
def validation?
  @validation != UndefinedSetting
end
value(val) click to toggle source

Prepopulate input with custom content

@api public

# File lib/tty/prompt/question.rb, line 301
def value(val)
  return @value if val.nil?

  @value = val
end
value?() click to toggle source

Check if custom value is present

@api private

# File lib/tty/prompt/question.rb, line 310
def value?
  @value != UndefinedSetting
end