1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
# frozen_string_literal: true
require_relative "question"
require_relative "utils"
module TTY
class Prompt
class ConfirmQuestion < Question
# Create confirmation question
#
# @param [Hash] options
# @option options [String] :suffix
# @option options [String] :positive
# @option options [String] :negative
#
# @api public
def initialize(prompt, **options)
super
@suffix = options.fetch(:suffix) { UndefinedSetting }
@positive = options.fetch(:positive) { UndefinedSetting }
@negative = options.fetch(:negative) { UndefinedSetting }
end
def positive?
@positive != UndefinedSetting
end
def negative?
@negative != UndefinedSetting
end
def suffix?
@suffix != UndefinedSetting
end
# Set question suffix
#
# @api public
def suffix(value = (not_set = true))
return @negative if not_set
@suffix = value
end
# Set value for matching positive choice
#
# @api public
def positive(value = (not_set = true))
return @positive if not_set
@positive = value
end
# Set value for matching negative choice
#
# @api public
def negative(value = (not_set = true))
return @negative if not_set
@negative = value
end
def call(message, &block)
return if Utils.blank?(message)
@message = message
block.call(self) if block
setup_defaults
render
end
# Render confirmation question
#
# @return [String]
#
# @api private
def render_question
header = "#{@prefix}#{message} "
if !@done
header += @prompt.decorate("(#{@suffix})", @help_color) + " "
else
answer = conversion.call(@input)
label = answer ? @positive : @negative
header += @prompt.decorate(label, @active_color)
end
header << "\n" if @done
header
end
protected
# Decide how to handle input from user
#
# @api private
def process_input(question)
@input = read_input(question)
if Utils.blank?(@input)
@input = default ? positive : negative
end
@evaluator.call(@input)
end
# @api private
def setup_defaults
infer_default
@convert = conversion
return if suffix? && positive?
if suffix? && (!positive? || !negative?)
parts = @suffix.split("/")
@positive = parts[0]
@negative = parts[1]
elsif !suffix? && positive?
@suffix = create_suffix
else
create_default_labels
end
end
# @api private
def infer_default
converted = Converters.convert(:bool, default.to_s)
if converted == Const::Undefined
raise InvalidArgument, "default needs to be `true` or `false`"
else
default(converted)
end
end
# @api private
def create_default_labels
@suffix = default ? "Y/n" : "y/N"
@positive = default ? "Yes" : "yes"
@negative = default ? "no" : "No"
@validation = /^(y(es)?|no?)$/i
@messages[:valid?] = "Invalid input."
end
# @api private
def create_suffix
(default ? positive.capitalize : positive.downcase) + "/" +
(default ? negative.downcase : negative.capitalize)
end
# Create custom conversion
#
# @api private
def conversion
->(input) do
positive_word = Regexp.escape(positive)
positive_letter = Regexp.escape(positive[0])
pattern = Regexp.new("^(#{positive_word}|#{positive_letter})$", true)
!input.match(pattern).nil?
end
end
end # ConfirmQuestion
end # Prompt
end # TTY
|