--------------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 ighline.rb" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename ighline.rb" module HighLine #prompt ext 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 l) begin valid rue default ption(options, :default) if default defaultstr |#{default}|" else defaultstr " end base ption(options, :base) print prompt, "#{defaultstr} " $stdout.flush input ets.chomp if default && input "" input efault end #comvert the input to the correct type input ase type when :string: input when :integer: convert(input, base) rescue valid alse when :float: Float(input) rescue valid alse when :bool valid nput /^(y|n|yes|no)$/ input[0] ?y when Proc: input ype.call(input) rescue valid alse end #validate the input valid && alidate(options, :validate) do |test| case test when Regexp: input test when Proc: test.call(input) end end valid && alidate(options, :within) { |range| range input} valid && alidate(options, :above) { |value| input > value} valid && alidate(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 il if options && options.key?(key) result ptions[key] end result end #helper function for validation def validate(options, key) result rue if options && options.key?(key) result ield options[key] end result end #converts a string to an integer #input he value to convert #base he 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 nteger(input) else value nteger(input) end else value nteger(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--