tty 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/README.md +45 -115
- data/lib/tty.rb +3 -31
- data/lib/tty/plugins/plugin.rb +2 -2
- data/lib/tty/terminal.rb +2 -58
- data/lib/tty/terminal/home.rb +27 -9
- data/lib/tty/version.rb +1 -1
- data/spec/tty/plugins/plugin/load_spec.rb +10 -18
- data/spec/tty/system/editor/open_spec.rb +1 -1
- data/spec/tty/terminal/home_spec.rb +18 -26
- data/spec/tty/tty_spec.rb +1 -1
- data/spec/tty/vector/new_spec.rb +1 -1
- metadata +2 -83
- data/lib/tty/shell.rb +0 -211
- data/lib/tty/shell/distance.rb +0 -49
- data/lib/tty/shell/question.rb +0 -335
- data/lib/tty/shell/question/modifier.rb +0 -93
- data/lib/tty/shell/question/validation.rb +0 -92
- data/lib/tty/shell/reader.rb +0 -110
- data/lib/tty/shell/response.rb +0 -249
- data/lib/tty/shell/response_delegation.rb +0 -55
- data/lib/tty/shell/statement.rb +0 -60
- data/lib/tty/shell/suggestion.rb +0 -126
- data/lib/tty/support/utils.rb +0 -16
- data/lib/tty/terminal/echo.rb +0 -38
- data/lib/tty/terminal/raw.rb +0 -38
- data/spec/tty/shell/ask_spec.rb +0 -77
- data/spec/tty/shell/distance/distance_spec.rb +0 -75
- data/spec/tty/shell/distance/initialize_spec.rb +0 -14
- data/spec/tty/shell/error_spec.rb +0 -30
- data/spec/tty/shell/print_table_spec.rb +0 -24
- data/spec/tty/shell/question/argument_spec.rb +0 -30
- data/spec/tty/shell/question/character_spec.rb +0 -24
- data/spec/tty/shell/question/default_spec.rb +0 -25
- data/spec/tty/shell/question/in_spec.rb +0 -23
- data/spec/tty/shell/question/initialize_spec.rb +0 -24
- data/spec/tty/shell/question/modifier/apply_to_spec.rb +0 -34
- data/spec/tty/shell/question/modifier/letter_case_spec.rb +0 -27
- data/spec/tty/shell/question/modifier/whitespace_spec.rb +0 -33
- data/spec/tty/shell/question/modify_spec.rb +0 -44
- data/spec/tty/shell/question/valid_spec.rb +0 -46
- data/spec/tty/shell/question/validate_spec.rb +0 -30
- data/spec/tty/shell/question/validation/coerce_spec.rb +0 -24
- data/spec/tty/shell/question/validation/valid_value_spec.rb +0 -28
- data/spec/tty/shell/reader/getc_spec.rb +0 -42
- data/spec/tty/shell/response/read_bool_spec.rb +0 -40
- data/spec/tty/shell/response/read_char_spec.rb +0 -16
- data/spec/tty/shell/response/read_date_spec.rb +0 -20
- data/spec/tty/shell/response/read_email_spec.rb +0 -42
- data/spec/tty/shell/response/read_multiple_spec.rb +0 -23
- data/spec/tty/shell/response/read_number_spec.rb +0 -28
- data/spec/tty/shell/response/read_range_spec.rb +0 -31
- data/spec/tty/shell/response/read_spec.rb +0 -68
- data/spec/tty/shell/response/read_string_spec.rb +0 -19
- data/spec/tty/shell/say_spec.rb +0 -67
- data/spec/tty/shell/statement/initialize_spec.rb +0 -15
- data/spec/tty/shell/suggest_spec.rb +0 -50
- data/spec/tty/shell/warn_spec.rb +0 -30
- data/spec/tty/terminal/color_spec.rb +0 -16
- data/spec/tty/terminal/echo_spec.rb +0 -21
| @@ -1,92 +0,0 @@ | |
| 1 | 
            -
            # encoding: utf-8
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            module TTY
         | 
| 4 | 
            -
              class Shell
         | 
| 5 | 
            -
                class Question
         | 
| 6 | 
            -
                  # A class representing question validation.
         | 
| 7 | 
            -
                  class Validation
         | 
| 8 | 
            -
                    # @api private
         | 
| 9 | 
            -
                    attr_reader :validation
         | 
| 10 | 
            -
                    private :validation
         | 
| 11 | 
            -
             | 
| 12 | 
            -
                    # Initialize a Validation
         | 
| 13 | 
            -
                    #
         | 
| 14 | 
            -
                    # @param [Object] validation
         | 
| 15 | 
            -
                    #
         | 
| 16 | 
            -
                    # @return [undefined]
         | 
| 17 | 
            -
                    #
         | 
| 18 | 
            -
                    # @api private
         | 
| 19 | 
            -
                    def initialize(validation = nil)
         | 
| 20 | 
            -
                      @validation = validation ? coerce(validation) : validation
         | 
| 21 | 
            -
                    end
         | 
| 22 | 
            -
             | 
| 23 | 
            -
                    # Convert validation into known type.
         | 
| 24 | 
            -
                    #
         | 
| 25 | 
            -
                    # @param [Object] validation
         | 
| 26 | 
            -
                    #
         | 
| 27 | 
            -
                    # @raise [TTY::ValidationCoercion] failed to convert validation
         | 
| 28 | 
            -
                    #
         | 
| 29 | 
            -
                    # @api private
         | 
| 30 | 
            -
                    def coerce(validation)
         | 
| 31 | 
            -
                      case validation
         | 
| 32 | 
            -
                      when Proc
         | 
| 33 | 
            -
                        validation
         | 
| 34 | 
            -
                      when Regexp, String
         | 
| 35 | 
            -
                        Regexp.new(validation.to_s)
         | 
| 36 | 
            -
                      else
         | 
| 37 | 
            -
                        fail TTY::ValidationCoercion, "Wrong type, got #{validation.class}"
         | 
| 38 | 
            -
                      end
         | 
| 39 | 
            -
                    end
         | 
| 40 | 
            -
             | 
| 41 | 
            -
                    # Check if validation is required
         | 
| 42 | 
            -
                    #
         | 
| 43 | 
            -
                    # @return [Boolean]
         | 
| 44 | 
            -
                    #
         | 
| 45 | 
            -
                    # @api public
         | 
| 46 | 
            -
                    def validate?
         | 
| 47 | 
            -
                      !!validation
         | 
| 48 | 
            -
                    end
         | 
| 49 | 
            -
             | 
| 50 | 
            -
                    # Test if the value matches the validation
         | 
| 51 | 
            -
                    #
         | 
| 52 | 
            -
                    # @example
         | 
| 53 | 
            -
                    #   validation.valid_value?(value) # => true or false
         | 
| 54 | 
            -
                    #
         | 
| 55 | 
            -
                    # @param [Object] value
         | 
| 56 | 
            -
                    #  the value to validate
         | 
| 57 | 
            -
                    #
         | 
| 58 | 
            -
                    # @return [undefined]
         | 
| 59 | 
            -
                    #
         | 
| 60 | 
            -
                    # @api public
         | 
| 61 | 
            -
                    def valid_value?(value)
         | 
| 62 | 
            -
                      check_validation(value)
         | 
| 63 | 
            -
                    end
         | 
| 64 | 
            -
             | 
| 65 | 
            -
                    private
         | 
| 66 | 
            -
             | 
| 67 | 
            -
                    # Check if provided value passes validation
         | 
| 68 | 
            -
                    #
         | 
| 69 | 
            -
                    # @param [String] value
         | 
| 70 | 
            -
                    #
         | 
| 71 | 
            -
                    # @raise [TTY::InvalidArgument] unkown type of argument
         | 
| 72 | 
            -
                    #
         | 
| 73 | 
            -
                    # @return [undefined]
         | 
| 74 | 
            -
                    #
         | 
| 75 | 
            -
                    # @api private
         | 
| 76 | 
            -
                    def check_validation(value)
         | 
| 77 | 
            -
                      if validate? && value
         | 
| 78 | 
            -
                        value = value.to_s
         | 
| 79 | 
            -
                        if validation.is_a?(Regexp) && validation =~ value
         | 
| 80 | 
            -
                        elsif validation.is_a?(Proc) && validation.call(value)
         | 
| 81 | 
            -
                        else
         | 
| 82 | 
            -
                          fail TTY::InvalidArgument, "Invalid input for #{value}"
         | 
| 83 | 
            -
                        end
         | 
| 84 | 
            -
                        true
         | 
| 85 | 
            -
                      else
         | 
| 86 | 
            -
                        false
         | 
| 87 | 
            -
                      end
         | 
| 88 | 
            -
                    end
         | 
| 89 | 
            -
                  end # Validation
         | 
| 90 | 
            -
                end # Question
         | 
| 91 | 
            -
              end # Shell
         | 
| 92 | 
            -
            end # TTY
         | 
    
        data/lib/tty/shell/reader.rb
    DELETED
    
    | @@ -1,110 +0,0 @@ | |
| 1 | 
            -
            # encoding: utf-8
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            module TTY
         | 
| 4 | 
            -
              # A class responsible for shell prompt interactions.
         | 
| 5 | 
            -
              class Shell
         | 
| 6 | 
            -
                # A class responsible for reading character input from STDIN
         | 
| 7 | 
            -
                class Reader
         | 
| 8 | 
            -
                  # @api private
         | 
| 9 | 
            -
                  attr_reader :shell
         | 
| 10 | 
            -
                  private :shell
         | 
| 11 | 
            -
             | 
| 12 | 
            -
                  # Key input constants for decimal codes
         | 
| 13 | 
            -
                  CARRIAGE_RETURN = 13.freeze
         | 
| 14 | 
            -
                  NEWLINE         = 10.freeze
         | 
| 15 | 
            -
                  BACKSPACE       = 127.freeze
         | 
| 16 | 
            -
                  DELETE          = 8.freeze
         | 
| 17 | 
            -
             | 
| 18 | 
            -
                  # Initialize a Reader
         | 
| 19 | 
            -
                  #
         | 
| 20 | 
            -
                  # @api public
         | 
| 21 | 
            -
                  def initialize(shell = Shell.new)
         | 
| 22 | 
            -
                    @shell = shell
         | 
| 23 | 
            -
                  end
         | 
| 24 | 
            -
             | 
| 25 | 
            -
                  # Get input in unbuffered mode.
         | 
| 26 | 
            -
                  #
         | 
| 27 | 
            -
                  # @example
         | 
| 28 | 
            -
                  #   buffer do
         | 
| 29 | 
            -
                  #     ...
         | 
| 30 | 
            -
                  #   end
         | 
| 31 | 
            -
                  #
         | 
| 32 | 
            -
                  # @return [String]
         | 
| 33 | 
            -
                  #
         | 
| 34 | 
            -
                  # @api public
         | 
| 35 | 
            -
                  def buffer(&block)
         | 
| 36 | 
            -
                    bufferring = shell.output.sync
         | 
| 37 | 
            -
                    # Immediately flush output
         | 
| 38 | 
            -
                    shell.output.sync = true
         | 
| 39 | 
            -
             | 
| 40 | 
            -
                    value = block.call if block_given?
         | 
| 41 | 
            -
             | 
| 42 | 
            -
                    shell.output.sync = bufferring
         | 
| 43 | 
            -
                    value
         | 
| 44 | 
            -
                  end
         | 
| 45 | 
            -
             | 
| 46 | 
            -
                  # Get a value from STDIN one key at a time. Each key press is echoed back
         | 
| 47 | 
            -
                  # to the shell masked with character(if given). The input finishes when
         | 
| 48 | 
            -
                  # enter key is pressed.
         | 
| 49 | 
            -
                  #
         | 
| 50 | 
            -
                  # @param [String] mask
         | 
| 51 | 
            -
                  #   the character to use as mask
         | 
| 52 | 
            -
                  #
         | 
| 53 | 
            -
                  # @return [String]
         | 
| 54 | 
            -
                  #
         | 
| 55 | 
            -
                  # @api public
         | 
| 56 | 
            -
                  def getc(mask = (not_set = true))
         | 
| 57 | 
            -
                    value = ''
         | 
| 58 | 
            -
                    buffer do
         | 
| 59 | 
            -
                      begin
         | 
| 60 | 
            -
                        while (char = shell.input.getbyte) &&
         | 
| 61 | 
            -
                            !(char == CARRIAGE_RETURN || char == NEWLINE)
         | 
| 62 | 
            -
                          value = handle_char value, char, not_set, mask
         | 
| 63 | 
            -
                        end
         | 
| 64 | 
            -
                      ensure
         | 
| 65 | 
            -
                        TTY.terminal.echo_on
         | 
| 66 | 
            -
                      end
         | 
| 67 | 
            -
                    end
         | 
| 68 | 
            -
                    value
         | 
| 69 | 
            -
                  end
         | 
| 70 | 
            -
             | 
| 71 | 
            -
                  # Get a value from STDIN using line input.
         | 
| 72 | 
            -
                  #
         | 
| 73 | 
            -
                  # @api public
         | 
| 74 | 
            -
                  def gets
         | 
| 75 | 
            -
                    shell.input.gets
         | 
| 76 | 
            -
                  end
         | 
| 77 | 
            -
             | 
| 78 | 
            -
                  # Reads at maximum +maxlen+ characters.
         | 
| 79 | 
            -
                  #
         | 
| 80 | 
            -
                  # @param [Integer] maxlen
         | 
| 81 | 
            -
                  #
         | 
| 82 | 
            -
                  # @api public
         | 
| 83 | 
            -
                  def readpartial(maxlen)
         | 
| 84 | 
            -
                    shell.input.readpartial(maxlen)
         | 
| 85 | 
            -
                  end
         | 
| 86 | 
            -
             | 
| 87 | 
            -
                  private
         | 
| 88 | 
            -
             | 
| 89 | 
            -
                  # Handle single character by appending to or removing from output
         | 
| 90 | 
            -
                  #
         | 
| 91 | 
            -
                  # @api private
         | 
| 92 | 
            -
                  def handle_char(value, char, not_set, mask)
         | 
| 93 | 
            -
                    if char == BACKSPACE || char == DELETE
         | 
| 94 | 
            -
                      value.slice!(-1, 1) unless value.empty?
         | 
| 95 | 
            -
                    else
         | 
| 96 | 
            -
                      print_char char, not_set, mask
         | 
| 97 | 
            -
                      value << char
         | 
| 98 | 
            -
                    end
         | 
| 99 | 
            -
                    value
         | 
| 100 | 
            -
                  end
         | 
| 101 | 
            -
             | 
| 102 | 
            -
                  # Print out character back to shell STDOUT
         | 
| 103 | 
            -
                  #
         | 
| 104 | 
            -
                  # @api private
         | 
| 105 | 
            -
                  def print_char(char, not_set, mask)
         | 
| 106 | 
            -
                    shell.output.putc((not_set || !mask) ? char : mask)
         | 
| 107 | 
            -
                  end
         | 
| 108 | 
            -
                end # Reader
         | 
| 109 | 
            -
              end # Shell
         | 
| 110 | 
            -
            end # TTY
         | 
    
        data/lib/tty/shell/response.rb
    DELETED
    
    | @@ -1,249 +0,0 @@ | |
| 1 | 
            -
            # encoding: utf-8
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            require 'date'
         | 
| 4 | 
            -
             | 
| 5 | 
            -
            module TTY
         | 
| 6 | 
            -
              # A class responsible for shell prompt interactions
         | 
| 7 | 
            -
              class Shell
         | 
| 8 | 
            -
                # A class representing a shell response
         | 
| 9 | 
            -
                class Response
         | 
| 10 | 
            -
                  VALID_TYPES = [
         | 
| 11 | 
            -
                    :boolean,
         | 
| 12 | 
            -
                    :string,
         | 
| 13 | 
            -
                    :symbol,
         | 
| 14 | 
            -
                    :integer,
         | 
| 15 | 
            -
                    :float,
         | 
| 16 | 
            -
                    :date,
         | 
| 17 | 
            -
                    :datetime
         | 
| 18 | 
            -
                  ]
         | 
| 19 | 
            -
             | 
| 20 | 
            -
                  attr_reader :reader
         | 
| 21 | 
            -
                  private :reader
         | 
| 22 | 
            -
             | 
| 23 | 
            -
                  attr_reader :shell
         | 
| 24 | 
            -
                  private :shell
         | 
| 25 | 
            -
             | 
| 26 | 
            -
                  attr_reader :question
         | 
| 27 | 
            -
                  private :question
         | 
| 28 | 
            -
             | 
| 29 | 
            -
                  # Initialize a Response
         | 
| 30 | 
            -
                  #
         | 
| 31 | 
            -
                  # @api public
         | 
| 32 | 
            -
                  def initialize(question, shell = Shell.new)
         | 
| 33 | 
            -
                    @question  = question
         | 
| 34 | 
            -
                    @shell     = shell
         | 
| 35 | 
            -
                    @converter = Necromancer.new
         | 
| 36 | 
            -
                    @reader    = Reader.new(shell)
         | 
| 37 | 
            -
                  end
         | 
| 38 | 
            -
             | 
| 39 | 
            -
                  # Read input from STDIN either character or line
         | 
| 40 | 
            -
                  #
         | 
| 41 | 
            -
                  # @param [Symbol] type
         | 
| 42 | 
            -
                  #
         | 
| 43 | 
            -
                  # @return [undefined]
         | 
| 44 | 
            -
                  #
         | 
| 45 | 
            -
                  # @api public
         | 
| 46 | 
            -
                  def read(type = nil)
         | 
| 47 | 
            -
                    question.evaluate_response read_input
         | 
| 48 | 
            -
                  end
         | 
| 49 | 
            -
             | 
| 50 | 
            -
                  # @api private
         | 
| 51 | 
            -
                  def read_input
         | 
| 52 | 
            -
                    reader = Reader.new(shell)
         | 
| 53 | 
            -
             | 
| 54 | 
            -
                    if question.mask? && question.echo?
         | 
| 55 | 
            -
                      reader.getc(question.mask)
         | 
| 56 | 
            -
                    else
         | 
| 57 | 
            -
                      TTY.terminal.echo(question.echo) do
         | 
| 58 | 
            -
                        TTY.terminal.raw(question.raw) do
         | 
| 59 | 
            -
                          if question.raw?
         | 
| 60 | 
            -
                            reader.readpartial(10)
         | 
| 61 | 
            -
                          elsif question.character?
         | 
| 62 | 
            -
                            reader.getc(question.mask)
         | 
| 63 | 
            -
                          else
         | 
| 64 | 
            -
                            reader.gets
         | 
| 65 | 
            -
                          end
         | 
| 66 | 
            -
                        end
         | 
| 67 | 
            -
                      end
         | 
| 68 | 
            -
                    end
         | 
| 69 | 
            -
                  end
         | 
| 70 | 
            -
             | 
| 71 | 
            -
                  # Read answer and cast to String type
         | 
| 72 | 
            -
                  #
         | 
| 73 | 
            -
                  # @param [String] error
         | 
| 74 | 
            -
                  #   error to display on failed conversion to string type
         | 
| 75 | 
            -
                  #
         | 
| 76 | 
            -
                  # @api public
         | 
| 77 | 
            -
                  def read_string(error = nil)
         | 
| 78 | 
            -
                    question.evaluate_response(String(read_input).strip)
         | 
| 79 | 
            -
                  end
         | 
| 80 | 
            -
             | 
| 81 | 
            -
                  # Read answer's first character
         | 
| 82 | 
            -
                  #
         | 
| 83 | 
            -
                  # @api public
         | 
| 84 | 
            -
                  def read_char
         | 
| 85 | 
            -
                    question.char(true)
         | 
| 86 | 
            -
                    question.evaluate_response String(read_input).chars.to_a[0]
         | 
| 87 | 
            -
                  end
         | 
| 88 | 
            -
             | 
| 89 | 
            -
                  # Read multiple line answer and cast to String type
         | 
| 90 | 
            -
                  #
         | 
| 91 | 
            -
                  # @api public
         | 
| 92 | 
            -
                  def read_text
         | 
| 93 | 
            -
                    question.evaluate_response String(read_input)
         | 
| 94 | 
            -
                  end
         | 
| 95 | 
            -
             | 
| 96 | 
            -
                  # Read ansewr and cast to Symbol type
         | 
| 97 | 
            -
                  #
         | 
| 98 | 
            -
                  # @api public
         | 
| 99 | 
            -
                  def read_symbol(error = nil)
         | 
| 100 | 
            -
                    question.evaluate_response(read_input.to_sym)
         | 
| 101 | 
            -
                  end
         | 
| 102 | 
            -
             | 
| 103 | 
            -
                  # Read answer from predifined choicse
         | 
| 104 | 
            -
                  #
         | 
| 105 | 
            -
                  # @api public
         | 
| 106 | 
            -
                  def read_choice(type = nil)
         | 
| 107 | 
            -
                    question.argument(:required) unless question.default?
         | 
| 108 | 
            -
                    question.evaluate_response read_input
         | 
| 109 | 
            -
                  end
         | 
| 110 | 
            -
             | 
| 111 | 
            -
                  # Read integer value
         | 
| 112 | 
            -
                  #
         | 
| 113 | 
            -
                  # @api public
         | 
| 114 | 
            -
                  def read_int(error = nil)
         | 
| 115 | 
            -
                    response = @converter.convert(read_input).to(:integer)
         | 
| 116 | 
            -
                    question.evaluate_response(response)
         | 
| 117 | 
            -
                  end
         | 
| 118 | 
            -
             | 
| 119 | 
            -
                  # Read float value
         | 
| 120 | 
            -
                  #
         | 
| 121 | 
            -
                  # @api public
         | 
| 122 | 
            -
                  def read_float(error = nil)
         | 
| 123 | 
            -
                    response = @converter.convert(read_input).to(:float)
         | 
| 124 | 
            -
                    question.evaluate_response(response)
         | 
| 125 | 
            -
                  end
         | 
| 126 | 
            -
             | 
| 127 | 
            -
                  # Read regular expression
         | 
| 128 | 
            -
                  #
         | 
| 129 | 
            -
                  # @api public
         | 
| 130 | 
            -
                  def read_regex(error = nil)
         | 
| 131 | 
            -
                    question.evaluate_response Kernel.send(:Regex, read_input)
         | 
| 132 | 
            -
                  end
         | 
| 133 | 
            -
             | 
| 134 | 
            -
                  # Read range expression
         | 
| 135 | 
            -
                  #
         | 
| 136 | 
            -
                  # @api public
         | 
| 137 | 
            -
                  def read_range
         | 
| 138 | 
            -
                    response = @converter.convert(read_input).to(:range, strict: true)
         | 
| 139 | 
            -
                    question.evaluate_response(response)
         | 
| 140 | 
            -
                  end
         | 
| 141 | 
            -
             | 
| 142 | 
            -
                  # Read date
         | 
| 143 | 
            -
                  #
         | 
| 144 | 
            -
                  # @api public
         | 
| 145 | 
            -
                  def read_date
         | 
| 146 | 
            -
                    response = @converter.convert(read_input).to(:date)
         | 
| 147 | 
            -
                    question.evaluate_response(response)
         | 
| 148 | 
            -
                  end
         | 
| 149 | 
            -
             | 
| 150 | 
            -
                  # Read datetime
         | 
| 151 | 
            -
                  #
         | 
| 152 | 
            -
                  # @api public
         | 
| 153 | 
            -
                  def read_datetime
         | 
| 154 | 
            -
                    response = @converter.convert(read_input).to(:datetime)
         | 
| 155 | 
            -
                    question.evaluate_response(response)
         | 
| 156 | 
            -
                  end
         | 
| 157 | 
            -
             | 
| 158 | 
            -
                  # Read boolean
         | 
| 159 | 
            -
                  #
         | 
| 160 | 
            -
                  # @api public
         | 
| 161 | 
            -
                  def read_bool(error = nil)
         | 
| 162 | 
            -
                    response = @converter.convert(read_input).to(:boolean, strict: true)
         | 
| 163 | 
            -
                    question.evaluate_response(response)
         | 
| 164 | 
            -
                  end
         | 
| 165 | 
            -
             | 
| 166 | 
            -
                  # Read file contents
         | 
| 167 | 
            -
                  #
         | 
| 168 | 
            -
                  # @api public
         | 
| 169 | 
            -
                  def read_file(error = nil)
         | 
| 170 | 
            -
                    question.evaluate_response File.open(File.join(directory, read_input))
         | 
| 171 | 
            -
                  end
         | 
| 172 | 
            -
             | 
| 173 | 
            -
                  # Read string answer and validate against email regex
         | 
| 174 | 
            -
                  #
         | 
| 175 | 
            -
                  # @return [String]
         | 
| 176 | 
            -
                  #
         | 
| 177 | 
            -
                  # @api public
         | 
| 178 | 
            -
                  def read_email
         | 
| 179 | 
            -
                    question.validate(/^[a-z0-9._%+-]+@([a-z0-9-]+\.)+[a-z]{2,6}$/i)
         | 
| 180 | 
            -
                    question.prompt(question.statement) if question.error
         | 
| 181 | 
            -
                    with_exception { read_string }
         | 
| 182 | 
            -
                  end
         | 
| 183 | 
            -
             | 
| 184 | 
            -
                  # Read answer provided on multiple lines
         | 
| 185 | 
            -
                  #
         | 
| 186 | 
            -
                  # @api public
         | 
| 187 | 
            -
                  def read_multiple
         | 
| 188 | 
            -
                    response = ''
         | 
| 189 | 
            -
                    loop do
         | 
| 190 | 
            -
                      value = question.evaluate_response read_input
         | 
| 191 | 
            -
                      break if !value || value == ''
         | 
| 192 | 
            -
                      next  if value !~ /\S/
         | 
| 193 | 
            -
                      response << value
         | 
| 194 | 
            -
                    end
         | 
| 195 | 
            -
                    response
         | 
| 196 | 
            -
                  end
         | 
| 197 | 
            -
             | 
| 198 | 
            -
                  # Read password
         | 
| 199 | 
            -
                  #
         | 
| 200 | 
            -
                  # @api public
         | 
| 201 | 
            -
                  def read_password
         | 
| 202 | 
            -
                    question.echo false
         | 
| 203 | 
            -
                    question.evaluate_response read_input
         | 
| 204 | 
            -
                  end
         | 
| 205 | 
            -
             | 
| 206 | 
            -
                  # Read a single keypress
         | 
| 207 | 
            -
                  #
         | 
| 208 | 
            -
                  # @api public
         | 
| 209 | 
            -
                  def read_keypress
         | 
| 210 | 
            -
                    question.echo false
         | 
| 211 | 
            -
                    question.raw true
         | 
| 212 | 
            -
                    question.evaluate_response(read_input).tap do |key|
         | 
| 213 | 
            -
                      raise Interrupt if key == "\x03" # Ctrl-C
         | 
| 214 | 
            -
                    end
         | 
| 215 | 
            -
                  end
         | 
| 216 | 
            -
             | 
| 217 | 
            -
                  private
         | 
| 218 | 
            -
             | 
| 219 | 
            -
                  # Ignore exception
         | 
| 220 | 
            -
                  #
         | 
| 221 | 
            -
                  # @api private
         | 
| 222 | 
            -
                  def with_exception(&block)
         | 
| 223 | 
            -
                    yield
         | 
| 224 | 
            -
                  rescue
         | 
| 225 | 
            -
                    question.error? ? block.call : raise
         | 
| 226 | 
            -
                  end
         | 
| 227 | 
            -
             | 
| 228 | 
            -
                  # @param [Symbol] type
         | 
| 229 | 
            -
                  #   :boolean, :string, :numeric, :array
         | 
| 230 | 
            -
                  #
         | 
| 231 | 
            -
                  # @api private
         | 
| 232 | 
            -
                  def read_type(class_or_name)
         | 
| 233 | 
            -
                    raise TypeError, "Type #{type} is not valid" if type && !valid_type?(type)
         | 
| 234 | 
            -
                    case type
         | 
| 235 | 
            -
                    when :string, ::String
         | 
| 236 | 
            -
                      read_string
         | 
| 237 | 
            -
                    when :symbol, ::Symbol
         | 
| 238 | 
            -
                      read_symbol
         | 
| 239 | 
            -
                    when :float, ::Float
         | 
| 240 | 
            -
                      read_float
         | 
| 241 | 
            -
                    end
         | 
| 242 | 
            -
                  end
         | 
| 243 | 
            -
             | 
| 244 | 
            -
                  def valid_type?(type)
         | 
| 245 | 
            -
                    self.class::VALID_TYPES.include? type.to_sym
         | 
| 246 | 
            -
                  end
         | 
| 247 | 
            -
                end # Response
         | 
| 248 | 
            -
              end # Shell
         | 
| 249 | 
            -
            end # TTY
         |