lib/tty/prompt/question.rb in tty-prompt-0.10.1 vs lib/tty/prompt/question.rb in tty-prompt-0.11.0
- old
+ new
@@ -1,22 +1,22 @@
# encoding: utf-8
-require 'tty/prompt/question/modifier'
-require 'tty/prompt/question/validation'
-require 'tty/prompt/question/checks'
-require 'tty/prompt/converter_dsl'
-require 'tty/prompt/converters'
+require_relative 'converters'
+require_relative 'evaluator'
+require_relative 'question/modifier'
+require_relative 'question/validation'
+require_relative 'question/checks'
+require_relative 'utils'
module TTY
# A class responsible for shell prompt interactions.
class Prompt
# A class responsible for gathering user input
#
# @api public
class Question
include Checks
- include Converters
UndefinedSetting = Module.new
# Store question message
# @api public
@@ -40,10 +40,11 @@
@validation = options.fetch(:validation) { UndefinedSetting }
@read = options.fetch(:read) { 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 }
@messages = Utils.deep_copy(options.fetch(:messages) { { } })
@done = false
@input = nil
@evaluator = Evaluator.new(self)
@@ -98,16 +99,21 @@
# Read answer and convert to type
#
# @api private
def render
+ @errors = []
until @done
- render_question
+ lines = render_question
result = process_input
- errors = result.errors
- render_error_or_finish(result)
- refresh(errors.count)
+ if result.failure?
+ @errors = result.errors
+ render_error(result.errors)
+ else
+ @done = true
+ end
+ refresh(lines)
end
render_question
convert_result(result.value)
end
@@ -122,11 +128,13 @@
header += @prompt.decorate("#{@input}", @active_color)
elsif default? && !Utils.blank?(@default)
header += @prompt.decorate("(#{default})", @help_color) + ' '
end
@prompt.print(header)
- @prompt.print("\n") if @done
+ @prompt.puts if @done
+
+ header.lines.count + (@done ? 1 : 0)
end
# Decide how to handle input from user
#
# @api private
@@ -144,58 +152,52 @@
def read_input
case @read
when :keypress
@prompt.read_keypress
when :multiline
- @prompt.read_multiline
+ @prompt.read_multiline.each(&:chomp!)
else
- @prompt.read_line(echo)
+ @prompt.read_line(echo: echo).chomp
end
end
# Handle error condition
#
# @api private
- def render_error_or_finish(result)
- if result.failure?
- result.errors.each do |err|
- @prompt.print(@prompt.clear_line)
- @prompt.print(@prompt.decorate('>>', :red) + ' ' + err)
- end
- @prompt.print(@prompt.cursor.up(result.errors.count))
- else
- @done = true
- if result.errors.count.nonzero?
- @prompt.print(@prompt.cursor.down(result.errors.count))
- end
+ def render_error(errors)
+ errors.each do |err|
+ newline = (@echo ? '' : "\n")
+ @prompt.print(newline + @prompt.decorate('>>', :red) + ' ' + err)
end
end
# Determine area of the screen to clear
#
- # @param [Integer] errors
+ # @param [Array[String]] errors
#
# @api private
- def refresh(errors = nil)
- lines = @message.scan("\n").length
- lines += ((!echo? || errors.nonzero?) ? 1 : 2) # clear user enter
-
- if errors.nonzero? && @done
- lines += errors
+ def refresh(lines)
+ if @done
+ if @errors.count.zero? && @echo
+ @prompt.print(@prompt.cursor.up(lines))
+ else
+ lines += @errors.count
+ end
+ else
+ @prompt.print(@prompt.cursor.up(lines))
end
-
@prompt.print(@prompt.clear_lines(lines))
end
# Convert value to expected type
#
# @param [Object] value
#
# @api private
def convert_result(value)
if convert? & !Utils.blank?(value)
- converter_registry.(@convert, value)
+ Converters.convert(@convert, value)
else
value
end
end
@@ -301,13 +303,13 @@
#
# @api public
def in(value = (not_set = true), message = nil)
messages[:range?] = message if message
if in? && !@in.is_a?(Range)
- @in = converter_registry.(:range, @in)
+ @in = Converters.convert(:range, @in)
end
return @in if not_set
- @in = converter_registry.(:range, value)
+ @in = Converters.convert(:range, value)
end
# Check if range is set
#
# @return [Boolean]