Here's my solution.
I ran out of time, mainly for documentation, but I think I've got
something worth showing here. I'm using unit tests, so you can read
those (primarily "tc_highline.rb") to see how my module works.
It covers the basics in the quiz and is pretty open for new additions.
The killer feature is the type you specify in to ask(). It's really
powerful in that it can take a Proc that does the conversion to
whatever you like. agree(), my version of ask_if() from the quiz, is
implemented in these terms:
def agree( yes_or_no_question )
ask( yes_or_no_question,
lambda { |a| a =~ /\AY(?:es)?\Z/i ? true : false } )
end
Here are some other examples from my test cases:
def test_membership
@input << "112\n-541\n28\n"
@input.rewind
answer = @terminal.ask("Tell me your age.", Integer) do |q|
q.member = 0..105
end
assert_equal(28, answer)
end
def test_reask
number = 61676
@input << "Junk!\n" << number << "\n"
@input.rewind
answer = @terminal.ask("Favorite number? ", Integer)
assert_kind_of(Integer, number)
assert_instance_of(Fixnum, number)
assert_equal(number, answer)
assert_equal( "Favorite number? " +
"You must enter a valid Integer.\n" +
"? ", @output.string )
# ...
end
def test_type_conversion
# ...
@input.truncate(@input.rewind)
number = 10.5002
@input << number << "\n"
@input.rewind
answer = @terminal.ask( "Favorite number? ",
lambda { |n| n.to_f.abs.round } )
assert_kind_of(Integer, answer)
assert_instance_of(Fixnum, answer)
assert_equal(11, answer)
# ...
@input.truncate(@input.rewind)
@input << "6/16/76\n"
@input.rewind
answer = @terminal.ask("Enter your birthday.", Date)
assert_instance_of(Date, answer)
assert_equal(16, answer.day)
assert_equal(6, answer.month)
assert_equal(76, answer.year)
# ...
@input.truncate(@input.rewind)
@input << "gen\n"
@input.rewind
answer = @terminal.ask("Select a mode: ", [:generate, :run])
assert_instance_of(Symbol, answer)
assert_equal(:generate, answer)
end
def test_validation
@input << "system 'rm -rf /'\n105\n0b101_001\n"
@input.rewind
answer = @terminal.ask("Enter a binary number: ") do |q|
q.validate = /\A(?:0b)?[01_]+\Z/
end
assert_equal("0b101_001", answer)
end
I had a lot of fun working on this library and may just keep working on
it to see if I can't turn it into something genuinely useful.
You can load my library two different ways:
# This first way loads the class system, useful if you want to manage
many HighLine
# objects, say for socket work.
require "highline"
# Or you can take the easy out an import methods to the top level.
require "highline/import"
You can find my code here:
http://rubyquiz.com/highline.zip
Enjoy.
James Edward Gray II