[SOLUTION] Highline (#29)

Discussion in 'Ruby' started by mark sparshatt, Apr 24, 2005.

  1. --------------020708000909060406020505
    Content-Type: text/plain; charset=ISO-8859-1; format=flowed
    Content-Transfer-Encoding: 7bit

    This is my attempt at a solution. It's implemented as a module
    containing two public methods.

    ask(prompt, type, options)

    ask_if(prompt)

    For ask type can either be a symbol (one of :string, :integer, :float or
    :bool) or it can be a Proc object which is called in order to do the
    conversion.

    options is a hash which can have the following keys,
    :validate - this can be either a regular expression or a Proc object
    :within - compares the value to the specified range
    :above
    :below
    :default
    :base - when converting to an integer this specifies the base of the
    number. it can be one of b,o,d or x

    ask_if is just an alias for ask(prompt, :bool)

    --
    Mark Sparshatt

    --------------020708000909060406020505
    Content-Type: text/plain;
    name="highline.rb"
    Content-Transfer-Encoding: 7bit
    Content-Disposition: inline;
    filename="highline.rb"

    module HighLine
    #prompt = text to display
    #type can be one of :string, :integer, :float, :bool or a proc
    #if it's a proc then it is called with the entered string. If the input cannot be converted then it should throw an exception
    #if type == :bool then y,yes are converted to true. n,no are converted to false. All other values are rejected.
    #
    #options should be a hash of validation options
    #:validate => regular expresion or proc
    #if validate is a regular expression then the input is matched against it
    #if it's a proc then the proc is called and the input is accepted if it returns true
    #:between => range
    #the input is checked if it lies within the range
    #:above => value
    #the input is checked if it is above the value
    #:below => value
    #the input is checked if it is less than the value
    #:default => string
    #if the user doesn't enter a value then the default value is returned
    #:base => [b, o, d, x]
    #when asking for integers this will take a number in binary, octal, decimal or hexadecimal
    def ask(prompt, type, options=nil)
    begin
    valid = true

    default = option(options, :default)
    if default
    defaultstr = " |#{default}|"
    else
    defaultstr = ""
    end

    base = option(options, :base)

    print prompt, "#{defaultstr} "
    $stdout.flush
    input = gets.chomp

    if default && input == ""
    input = default
    end

    #comvert the input to the correct type
    input = case type
    when :string: input
    when :integer: convert(input, base) rescue valid = false
    when :float: Float(input) rescue valid = false
    when :bool
    valid = input =~ /^(y|n|yes|no)$/
    input[0] == ?y
    when Proc: input = type.call(input) rescue valid = false
    end

    #validate the input
    valid &&= validate(options, :validate) do |test|
    case test
    when Regexp: input =~ test
    when Proc: test.call(input)
    end
    end
    valid &&= validate(options, :within) { |range| range === input}
    valid &&= validate(options, :above) { |value| input > value}
    valid &&= validate(options, :below) { |value| input < value}

    puts "Not a valid value" unless valid
    end until valid

    return input
    end

    #asks a yes/no question
    def ask_if(prompt)
    ask(prompt, :bool)
    end

    private

    #extracts a key from the options hash
    def option(options, key)
    result = nil
    if options && options.key?(key)
    result = options[key]
    end
    result
    end

    #helper function for validation
    def validate(options, key)
    result = true
    if options && options.key?(key)
    result = yield options[key]
    end
    result
    end

    #converts a string to an integer
    #input = the value to convert
    #base = the numeric base of the value b,o,d,x
    def convert(input, base)
    if base
    if ["b", "o", "d", "x"].include?(base)
    input = "0#{base}#{input}"
    value = Integer(input)
    else
    value = Integer(input)
    end
    else
    value = Integer(input)
    end

    value
    end
    end



    if __FILE__ == $0
    include HighLine
    #string input using a regexp to validate, returns test as the default value
    p ask("enter a string, (all lower case)", :string, :validate => /^[a-z]*$/, :default => "test")
    #string input using a proc to validate
    p ask("enter a string, (between 3 and 6 characters)", :string, :validate => proc { |input| (3..6) === input.length})

    #integer intput using :within
    p ask("enter an integer, (0-10)", :integer, :within => 0..10)
    #float input using :above
    p ask("enter a float, (> 6)", :float, :above => 6)

    #getting a binary value
    p ask("enter a binary number", :integer, :base => "b")

    #using a proc to convert the a comma seperated list into an array
    p ask("enter a comma seperated list", proc { |x| x.split(/,/)})

    p ask_if("do you want to continue?")
    end

    --------------020708000909060406020505--
     
    mark sparshatt, Apr 24, 2005
    #1
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ruby Quiz

    [QUIZ] HighLine (#29)

    Ruby Quiz, Apr 22, 2005, in forum: Ruby
    Replies:
    8
    Views:
    144
    James Edward Gray II
    Apr 22, 2005
  2. Ryan Leavengood

    [SOLUTION] HighLine (#29)

    Ryan Leavengood, Apr 24, 2005, in forum: Ruby
    Replies:
    6
    Views:
    118
    James Edward Gray II
    Apr 29, 2005
  3. Ruby Quiz

    [SUMMARY] HighLine (#29)

    Ruby Quiz, Apr 28, 2005, in forum: Ruby
    Replies:
    0
    Views:
    153
    Ruby Quiz
    Apr 28, 2005
  4. James Edward Gray II

    [ANN] HighLine 0.2.0

    James Edward Gray II, Apr 29, 2005, in forum: Ruby
    Replies:
    2
    Views:
    106
    James Edward Gray II
    Apr 29, 2005
  5. James Edward Gray II

    [ANN] HighLine 0.3.0 -- Now with ANSI colors!

    James Edward Gray II, May 4, 2005, in forum: Ruby
    Replies:
    0
    Views:
    109
    James Edward Gray II
    May 4, 2005
Loading...

Share This Page