[QUIZ] HighLine (#29)

The three rules of Ruby Quiz:

1. Please do not post any solutions or spoiler discussion for this quiz until
48 hours have passed from the time on this message.

2. Support Ruby Quiz by submitting ideas as often as you can:

http://www.rubyquiz.com/

3. Enjoy!

···

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

When you stop and think about it, methods like gets(), while handy, are still
pretty low level. In running Ruby Quiz I'm always seeing solutions with helper
methods similar to this:

  # by Markus Koenig
  
  def ask(prompt)
    loop do
      print prompt, ' '
      $stdout.flush
      s = gets
      exit if s == nil
      s.chomp!
      if s == 'y' or s == 'yes'
        return true
      elsif s == 'n' or s == 'no'
        return false
      else
        $stderr.puts "Please answer yes or no."
      end
    end
  end

Surely we can make something like that better! We don't always need Rails or a
GUI framework and there's no reason writing a command-line application can't be
equally smooth.

This week's Ruby Quiz is to start a module called HighLine (for high-level,
line-oriented interface). Ideally this module would eventually cover many
aspects of terminal interaction, but for this quiz we'll just focus on getting
input.

What I really think we need here is to take a page out of the optparse book.
Here are some general ideas:

  age = ask("What is your age?", Integer, :within => 0..105)
  num = eval "0b#{ ask( 'Enter a binary number.',
                        String, :validate => /^[01_]+$/ ) }"
  
  if ask_if("Would you like to continue?") # ...

None of these ideas are etched in stone. Feel free to call your input method
prompt() or use a set of classes. Rework the interface any way you like. Just
be sure to tell us how to use your system.

The goal is to provide an easy-to-use, yet robust method of requesting input.
It should free the programmer of common concerns like calls to chomp() and
ensuring valid input.

Hi,

Not that this necessarily mitigates the educational value of this Quiz, but: EasyPrompt sort of does what you're saying below.

http://easyprompt.rubyforge.org/

Example:

irb(main):001:0> require 'easyprompt'
   => true
   irb(main):002:0> prompt = EasyPrompt.new
   => #<EasyPrompt:0x5a42a0 @stdout=#<EasyPrompt::MockableStdout:0x5a3e04>>
   irb(main):003:0> fname = prompt.ask( "What's your first name?" )
   What's your first name? John
   => "John"
   irb(main):004:0> lname = prompt.ask( "What's your last name?", "Doe" )
   What's your last name? [Doe]
   => "Doe"
   irb(main):005:0> correct = prompt.ask( "Is your name #{ fname } #{ lname }?", true, :boolean )
   Is your name John Doe? [y]
   => true

It's mockable, too! Everything must be mockable.

···

On Apr 22, 2005, at 8:45 AM, Ruby Quiz wrote:

The three rules of Ruby Quiz:

1. Please do not post any solutions or spoiler discussion for this quiz until
48 hours have passed from the time on this message.

2. Support Ruby Quiz by submitting ideas as often as you can:

http://www.rubyquiz.com/

3. Enjoy!

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

When you stop and think about it, methods like gets(), while handy, are still
pretty low level. In running Ruby Quiz I'm always seeing solutions with helper
methods similar to this:

  # by Markus Koenig
  
  def ask(prompt)
    loop do
      print prompt, ' '
      $stdout.flush
      s = gets
      exit if s == nil
      s.chomp!
      if s == 'y' or s == 'yes'
        return true
      elsif s == 'n' or s == 'no'
        return false
      else
        $stderr.puts "Please answer yes or no."
      end
    end
  end

Surely we can make something like that better! We don't always need Rails or a
GUI framework and there's no reason writing a command-line application can't be
equally smooth.

This week's Ruby Quiz is to start a module called HighLine (for high-level,
line-oriented interface). Ideally this module would eventually cover many
aspects of terminal interaction, but for this quiz we'll just focus on getting
input.

What I really think we need here is to take a page out of the optparse book.
Here are some general ideas:

  age = ask("What is your age?", Integer, :within => 0..105)
  num = eval "0b#{ ask( 'Enter a binary number.',
                        String, :validate => /^[01_]+$/ ) }"
  
  if ask_if("Would you like to continue?") # ...

None of these ideas are etched in stone. Feel free to call your input method
prompt() or use a set of classes. Rework the interface any way you like. Just
be sure to tell us how to use your system.

The goal is to provide an easy-to-use, yet robust method of requesting input.
It should free the programmer of common concerns like calls to chomp() and
ensuring valid input.

Francis Hwang

Is using a class instead of a module allowed?

···

On 4/22/05, Ruby Quiz <james@grayproductions.net> wrote:

The three rules of Ruby Quiz:

1. Please do not post any solutions or spoiler discussion for this quiz
until
48 hours have passed from the time on this message.

2. Support Ruby Quiz by submitting ideas as often as you can:

http://www.rubyquiz.com/

3. Enjoy!

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

When you stop and think about it, methods like gets(), while handy, are
still
pretty low level. In running Ruby Quiz I'm always seeing solutions with
helper
methods similar to this:

# by Markus Koenig

def ask(prompt)
loop do
print prompt, ' '
$stdout.flush
s = gets
exit if s == nil
s.chomp!
if s == 'y' or s == 'yes'
return true
elsif s == 'n' or s == 'no'
return false
else
$stderr.puts "Please answer yes or no."
end
end
end

Surely we can make something like that better! We don't always need Rails
or a
GUI framework and there's no reason writing a command-line application
can't be
equally smooth.

This week's Ruby Quiz is to start a module called HighLine (for
high-level,
line-oriented interface). Ideally this module would eventually cover many
aspects of terminal interaction, but for this quiz we'll just focus on
getting
input.

What I really think we need here is to take a page out of the optparse
book.
Here are some general ideas:

age = ask("What is your age?", Integer, :within => 0..105)
num = eval "0b#{ ask( 'Enter a binary number.',
String, :validate => /^[01_]+$/ ) }"

if ask_if("Would you like to continue?") # ...

None of these ideas are etched in stone. Feel free to call your input
method
prompt() or use a set of classes. Rework the interface any way you like.
Just
be sure to tell us how to use your system.

The goal is to provide an easy-to-use, yet robust method of requesting
input.
It should free the programmer of common concerns like calls to chomp() and
ensuring valid input.

--
Bill Atkins

Ruby Quiz <james@grayproductions.net> writes:

What I really think we need here is to take a page out of the optparse book.
Here are some general ideas:

  age = ask("What is your age?", Integer, :within => 0..105)
  num = eval "0b#{ ask( 'Enter a binary number.',
                        String, :validate => /^[01_]+$/ ) }"

Do not ever do that.

irb(main):004:0> Integer("0b1011")
=> 11
irb(main):005:0> "1011".to_i(2)
=> 11

irb(main):006:0> "foo\nbar" =~ /^foo$/
=> 0

···

--
Christian Neukirchen <chneukirchen@gmail.com> http://chneukirchen.org

Thanks for the link. I wasn't aware of this project. I like it.

James Edward Gray II

···

On Apr 22, 2005, at 9:24 AM, Francis Hwang wrote:

Hi,

Not that this necessarily mitigates the educational value of this Quiz, but: EasyPrompt sort of does what you're saying below.

http://easyprompt.rubyforge.org/

Disregard. :slight_smile:

···

On 4/22/05, Bill Atkins <batkins57@gmail.com> wrote:

Is using a class instead of a module allowed?

On 4/22/05, Ruby Quiz <james@grayproductions.net> wrote:
>
> The three rules of Ruby Quiz:
>
> 1. Please do not post any solutions or spoiler discussion for this quiz
> until
> 48 hours have passed from the time on this message.
>
> 2. Support Ruby Quiz by submitting ideas as often as you can:
>
> http://www.rubyquiz.com/
>
> 3. Enjoy!
>
>
> -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
>
> When you stop and think about it, methods like gets(), while handy, are
> still
> pretty low level. In running Ruby Quiz I'm always seeing solutions with
> helper
> methods similar to this:
>
> # by Markus Koenig
>
> def ask(prompt)
> loop do
> print prompt, ' '
> $stdout.flush
> s = gets
> exit if s == nil
> s.chomp!
> if s == 'y' or s == 'yes'
> return true
> elsif s == 'n' or s == 'no'
> return false
> else
> $stderr.puts "Please answer yes or no."
> end
> end
> end
>
> Surely we can make something like that better! We don't always need
> Rails or a
> GUI framework and there's no reason writing a command-line application
> can't be
> equally smooth.
>
> This week's Ruby Quiz is to start a module called HighLine (for
> high-level,
> line-oriented interface). Ideally this module would eventually cover
> many
> aspects of terminal interaction, but for this quiz we'll just focus on
> getting
> input.
>
> What I really think we need here is to take a page out of the optparse
> book.
> Here are some general ideas:
>
> age = ask("What is your age?", Integer, :within => 0..105)
> num = eval "0b#{ ask( 'Enter a binary number.',
> String, :validate => /^[01_]+$/ ) }"
>
> if ask_if("Would you like to continue?") # ...
>
> None of these ideas are etched in stone. Feel free to call your input
> method
> prompt() or use a set of classes. Rework the interface any way you like.
> Just
> be sure to tell us how to use your system.
>
> The goal is to provide an easy-to-use, yet robust method of requesting
> input.
> It should free the programmer of common concerns like calls to chomp()
> and
> ensuring valid input.
>
>

--
Bill Atkins

--
Bill Atkins

Definitely! Rework the interface any way you like.

James Edward Gray II

···

On Apr 22, 2005, at 9:46 AM, Bill Atkins wrote:

Is using a class instead of a module allowed?

I'm not exactly sure what you're trying to show here. Even 0 would be a fine binary number. However, the point was that I have created a safe eval() because ask() should not return anything that doesn't validate.

Obviously, using Integer() is better style though.

James Edward Gray II

···

On Apr 22, 2005, at 10:12 AM, Christian Neukirchen wrote:

Ruby Quiz <james@grayproductions.net> writes:

What I really think we need here is to take a page out of the optparse book.
Here are some general ideas:

  age = ask("What is your age?", Integer, :within => 0..105)
  num = eval "0b#{ ask( 'Enter a binary number.',
                        String, :validate => /^[01_]+$/ ) }"

Do not ever do that.

irb(main):004:0> Integer("0b1011")
=> 11
irb(main):005:0> "1011".to_i(2)
=> 11

irb(main):006:0> "foo\nbar" =~ /^foo$/
=> 0

>> num = eval "0b#{ ask( 'Enter a binary number.',
>> String, :validate => /^[01_]+$/ ) }"
>
> Do not ever do that.
>
> irb(main):004:0> Integer("0b1011")
> => 11
> irb(main):005:0> "1011".to_i(2)
> => 11
>
> irb(main):006:0> "foo\nbar" =~ /^foo$/
> => 0

I'm not exactly sure what you're trying to show here. Even 0 would be
a fine binary number. However, the point was that I have created a
safe eval() because ask() should not return anything that doesn't
validate.

I think he meant along the lines of:

irb --simple-prompt

p "looks ok!" if "01010\nsystem('rm -rf /')" =~ /^[01_]+$/

"looks ok!"

Regards,

Bill

···

From: "James Edward Gray II" <james@grayproductions.net>

James Edward Gray II wrote:

Hi,

Not that this necessarily mitigates the educational value of this
Quiz, but: EasyPrompt sort of does what you're saying below.

http://easyprompt.rubyforge.org/

Thanks for the link. I wasn't aware of this project. I like it.

Given the existence of this library, do we still want to proceed with this
Quiz? :slight_smile:

I suppose it will be worth it simply because we will see various
implementations and APIs for this concept, even if we are duplicating
EasyPrompt.

But sometimes I think programmers have too much of a penchant for
continually re-inventing the wheel...

Ryan Leavengood

···

On Apr 22, 2005, at 9:24 AM, Francis Hwang wrote:

Oops, my Perl habits are showing. My bad. The Regexp should be /\A[01_]+\Z/. I'll correct it on the Ruby Quiz site.

Thanks.

James Edward Gray II

···

On Apr 22, 2005, at 10:41 AM, Bill Kelly wrote:

I think he meant along the lines of:

irb --simple-prompt

p "looks ok!" if "01010\nsystem('rm -rf /')" =~ /^[01_]+$/

"looks ok!"

James Edward Gray II wrote:

Hi,

Not that this necessarily mitigates the educational value of this
Quiz, but: EasyPrompt sort of does what you're saying below.

http://easyprompt.rubyforge.org/

Thanks for the link. I wasn't aware of this project. I like it.

Given the existence of this library, do we still want to proceed with this
Quiz? :slight_smile:

Heck yeah! Take a glance back at what I didn't know when I ran the Quoted Printable quiz and it turned out just fine. If we used what I don't know as a barrier, there wouldn't be any quizzes! :wink:

I suppose it will be worth it simply because we will see various
implementations and APIs for this concept, even if we are duplicating
EasyPrompt.

I wouldn't declare EasyPrompt robust. Did you glance at the API? It's well... Easy. :slight_smile: I'm confident I can add features to it in under an hour. It's not even capable of some of the ideas I'm tossing around in the quiz.

What it did do for me, was give me more ideas. Have yourself a look, then think bigger... :slight_smile:

But sometimes I think programmers have too much of a penchant for
continually re-inventing the wheel...

We all know that's a good coding habit, but I really don't think it applies much to Ruby Quiz.

To me, Ruby Quiz is about writing regular code to keep our skills in shape. The goal is to find interesting exercises to support that. I use a lot of methods to find them. Sometimes, I dream them up (like this week). Some are suggested.

Other times I adapt challenges I've seen elsewhere. Obviously, these have been worked before, some even in Ruby. No big deal. If I ruled out all those ideas, we would miss out on some great little puzzles that have taught me a lot. That's how I know they're good and worth using. They're proven. By contrast, some of my ideas flop and nobody works them.

Ruby Quiz isn't a professional software coding assignment. (You certainly won't be paid for it!) It's gaming for super geeks. Use it to sharpen your reflexes. Give yourself little challenges going in: "This will be the sexiest solution to prime numbers ever written; I'll solve this sucker in five lines; this weather program will scrape and digitally modify Google's satellite photos to add rain and snow above your own house, because I can do that and it would be awesome; etc." Then when the big job comes along, you'll have all those experiences to draw on, putting you that much ahead in the big game. (I've actually adapted quiz solutions to job problems!)

"Of course, that's just my opinion. I could be wrong." --Dennis Miller

James Edward Gray II

···

On Apr 22, 2005, at 10:56 AM, Ryan Leavengood wrote:

On Apr 22, 2005, at 9:24 AM, Francis Hwang wrote:

"Ryan Leavengood" <mrcode@netrox.net> asked:

···

On Apr 22, 2005, at 9:24 AM, Francis Hwang wrote:

Not that this necessarily mitigates the educational value of this
Quiz, but: EasyPrompt sort of does what you're saying below.

http://easyprompt.rubyforge.org/

Given the existence of this library, do we still want to proceed with this
Quiz? :slight_smile:

... sometimes I think programmers have too much of a penchant for
continually re-inventing the wheel...

I think it's a good one for any newbies out there to have a shot at.
Reinventing wheels is a good thing to do for the purpose of learning to
program.

Maybe others of us might look at how EasyPrompt might be extended.

Cheers,
Dave

Dave Burt wrote:

"Ryan Leavengood" <mrcode@netrox.net> asked:

... sometimes I think programmers have too much of a penchant for
continually re-inventing the wheel...

I think it's a good one for any newbies out there to have a shot at.
Reinventing wheels is a good thing to do for the purpose of learning to
program.

Maybe others of us might look at how EasyPrompt might be extended.

Yeah I agree this quiz has potential for both newbies and more experienced
Rubyists. I will certainly try my hand in it. But I have a rule about not
reading code or APIs for other projects similar to something I'm solving,
so as not to taint my own problem-solving and API design. So I probably
won't look at EasyPrompt until I've written up my quiz solution...

Ryan

James Edward Gray II wrote:
[excellent argument for Ruby Quiz snipped]

"Of course, that's just my opinion. I could be wrong." --Dennis Miller

Well consider me convinced. I certainly do see the value in Ruby Quizzes.
Actually, I'll admit that the last Ruby Quiz was a big influence in
bringing me back to being more active in the Ruby community.

In fact I'd like to thank for the work you do in preparing the quizzes and
summarizing them at the end. It is appreciated.

Anyhow, you can expect my solution to this quiz on Sunday (even if it
slightly reinvents the EasyPrompt wheel :wink:

Ryan

Agreed. EasyPrompt is a pretty quick little thing; I just released it 'cause I wrote it once, then needed it again in another piece of code. The only mildly difficult thing in it is the MockCommandLineUser. Mostly I was just pointing it out as an informational aside.

But if people want me to add specific things, by all means let me know!

Francis Hwang

···

On Apr 22, 2005, at 12:43 PM, James Edward Gray II wrote:

On Apr 22, 2005, at 10:56 AM, Ryan Leavengood wrote:

I suppose it will be worth it simply because we will see various
implementations and APIs for this concept, even if we are duplicating
EasyPrompt.

I wouldn't declare EasyPrompt robust. Did you glance at the API? It's well... Easy. :slight_smile: I'm confident I can add features to it in under an hour. It's not even capable of some of the ideas I'm tossing around in the quiz.

What it did do for me, was give me more ideas. Have yourself a look, then think bigger... :slight_smile:

My pleasure.

I myself am eternally grateful to all the people who work the quizzes and submit ideas to me. Without all the wonderful help, I would be sunk. Thanks so much!

Ruby Quiz has really grown into more than I expected of it. I only started it because I'm a quiz junkie and Ruby seemed lacking in the programming challenges area when I showed up. I did it for me, not you! <laughs>

But things change.

Now most of my time goes into running the quiz and I don't often end up with enough left over to actually work them. I don't regret it though. The Ruby Quiz site has become a killer resource for just reading interesting code, if I do say so myself. There are some really great idioms in the solutions all over that site.

I say we've built something great here and I'm proud to be a part of it. Thanks again!

James Edward Gray II

···

On Apr 22, 2005, at 12:35 PM, Ryan Leavengood wrote:

In fact I'd like to thank for the work you do in preparing the quizzes and
summarizing them at the end. It is appreciated.

Francis Hwang wrote:

I suppose it will be worth it simply because we will see various
implementations and APIs for this concept, even if we are duplicating
EasyPrompt.

I wouldn't declare EasyPrompt robust. Did you glance at the API? It's well... Easy. :slight_smile: I'm confident I can add features to it in under an hour. It's not even capable of some of the ideas I'm tossing around in the quiz.

What it did do for me, was give me more ideas. Have yourself a look, then think bigger... :slight_smile:

Agreed. EasyPrompt is a pretty quick little thing; I just released it 'cause I wrote it once, then needed it again in another piece of code. The only mildly difficult thing in it is the MockCommandLineUser. Mostly I was just pointing it out as an informational aside.

But if people want me to add specific things, by all means let me know!

Intra-line editing?
History via (or a la) Readline?
ANSI Colors?

Hal
(who secretly misses the good old days of command lines)

···

On Apr 22, 2005, at 12:43 PM, James Edward Gray II wrote:

On Apr 22, 2005, at 10:56 AM, Ryan Leavengood wrote:

Francis Hwang wrote:
>
>
>>
>>> I suppose it will be worth it simply because we will see various
>>> implementations and APIs for this concept, even if we are duplicating
>>> EasyPrompt.
>>
>>
>> I wouldn't declare EasyPrompt robust. Did you glance at the API?
>> It's well... Easy. :slight_smile: I'm confident I can add features to it in
>> under an hour. It's not even capable of some of the ideas I'm tossing
>> around in the quiz.
>>
>> What it did do for me, was give me more ideas. Have yourself a look,
>> then think bigger... :slight_smile:
>
>
> Agreed. EasyPrompt is a pretty quick little thing; I just released it
> 'cause I wrote it once, then needed it again in another piece of code.
> The only mildly difficult thing in it is the MockCommandLineUser. Mostly
> I was just pointing it out as an informational aside.
>
> But if people want me to add specific things, by all means let me know!

Intra-line editing?
History via (or a la) Readline?
ANSI Colors?

Maybe eventually a readline replacement :slight_smile: no more libreadline required!

Hal
(who secretly misses the good old days of command lines)

Mark
(who learned to like the command line when he learned it wasn't always DOS)

···

On 4/22/05, Hal Fulton <hal9000@hypermetrics.com> wrote:

> On Apr 22, 2005, at 12:43 PM, James Edward Gray II wrote:
>> On Apr 22, 2005, at 10:56 AM, Ryan Leavengood wrote:

Well, maybe I need to backpedal a bit and say "if people have specific things they'd like me to add that wouldn't require me to drop my other 15 projects, let me know."

Though the idea of replacing readline is intriguing ... Would the main benefit of that be just getting away from an external lib dependency that could make distribution harder? (And if so, I wonder if there are any plans for RubyGems or RPA to interface with other package-management systems so installing a Ruby lib based on a non-Ruby lib could be easier.)

Francis Hwang

···

On Apr 22, 2005, at 8:15 PM, Mark Hubbart wrote:

On 4/22/05, Hal Fulton <hal9000@hypermetrics.com> wrote:

Intra-line editing?
History via (or a la) Readline?
ANSI Colors?

Maybe eventually a readline replacement :slight_smile: no more libreadline required!