OptionParser error handling (InvalidArgument)

Hello,

I'd like to make an OptParser error look a bit more explanatory. I tried to deal with it outside OpiontParser like this:

···

----------------------------------------------------
# check if options[:no] is interger

if options[:no]
        begin
                $no = Integer(options[:no])
        rescue ArgumentError
                puts "#{$no} is not an Integer!"
        else
                true
        end
else
        $no = 0
end
----------------------------------------------------
but didn't work. The error I get from cli is:

f2bread.rb:483:in `<main>': invalid argument: -s duck (OptionParser::InvalidArgument)

Apparently I need to somehow handle this from within OptionParser. Any ideas on how to proceed? I found this post[1] online which explains what I want but I couldn't figure how exactly it works. So some actual codes with a sort of explanation of where *exactly* sits on the program (outside or inside "OptionParser.new" class?).

The relevant OptionParser lines, where is specified that '-n' accepts Integers, are:
----------------------------------------------------
opts.on('-n', '--no N', Integer, 'Number of top entries to be displayed. By default all entries are displayed.') do |no|
                options[:no] = no
        end
----------------------------------------------------

[1] http://blog.segment7.net/2008/01/05/optionparser-argument-casting

Best Regards,

Panagiotis Atmatzidis
-----------------------------
Pharmacy Student at VFU

email4lists: ml@convalesco.org
More info: http://about.me/atmosx

The wise man said: "Never argue with an idiot, he brings you down to his level and beat you with experience."

What do you mean, more explanatory?

···

On Aug 3, 2012, at 10:03 AM, Panagiotis Atmatzidis <ml@convalesco.org> wrote:

Hello,

I'd like to make an OptParser error look a bit more explanatory. I tried to deal with it outside OpiontParser like this:

----------------------------------------------------
# check if options[:no] is interger

if options[:no]
       begin
               $no = Integer(options[:no])
       rescue ArgumentError
               puts "#{$no} is not an Integer!"
       else
               true
       end
else
       $no = 0
end
----------------------------------------------------
but didn't work. The error I get from cli is:

f2bread.rb:483:in `<main>': invalid argument: -s duck (OptionParser::InvalidArgument)

Apparently I need to somehow handle this from within OptionParser. Any ideas on how to proceed? I found this post[1] online which explains what I want but I couldn't figure how exactly it works. So some actual codes with a sort of explanation of where *exactly* sits on the program (outside or inside "OptionParser.new" class?).

The relevant OptionParser lines, where is specified that '-n' accepts Integers, are:
----------------------------------------------------
opts.on('-n', '--no N', Integer, 'Number of top entries to be displayed. By default all entries are displayed.') do |no|
               options[:no] = no
       end
----------------------------------------------------

[1] http://blog.segment7.net/2008/01/05/optionparser-argument-casting

Best Regards,

Panagiotis Atmatzidis
-----------------------------
Pharmacy Student at VFU

email4lists: ml@convalesco.org
More info: http://about.me/atmosx

The wise man said: "Never argue with an idiot, he brings you down to his level and beat you with experience."

It is not clear to me what your problem is.

Slightly adapted from the post cited by you:

···

-----
require 'optparse'

options = {}

opts = OptionParser.new do |opts|
   # Cast 'no' argument to an Integer.
   opts.on('-n', '--no N', Integer, 'Number of...') do |no|
     options[:no] = no
   end
end

opts.parse!(ARGV)

p options
-----

results (as it should) in

$ ruby optparse.rb -n 34
{:no=>34}

$ ruby optparse.rb -n duck
optparse.rb:12:in `<main>': invalid argument: -n duck (OptionParser::InvalidArgument)

Am 03.08.2012 18:03, schrieb Panagiotis Atmatzidis:

----------------------------------------------------
# check if options[:no] is interger

if options[:no]
         begin
                 $no = Integer(options[:no])
         rescue ArgumentError
                 puts "#{$no} is not an Integer!"
         else
                 true
         end
else
         $no = 0
end

This is not necessary, since the option value has already been
cast to an integer, or an exception has been raised.

Btw, you should not use global variables.

----------------------------------------------------
but didn't work. The error I get from cli is:

f2bread.rb:483:in `<main>': invalid argument: -s duck (OptionParser::InvalidArgument)

Apparently I need to somehow handle this from within OptionParser. Any ideas on how to proceed? I found this post[1] online which explains what I want but I couldn't figure how exactly it works. So some actual codes with a sort of explanation of where *exactly* sits on the program (outside or inside "OptionParser.new" class?).

The relevant OptionParser lines, where is specified that '-n' accepts Integers, are:
----------------------------------------------------
  opts.on('-n', '--no N', Integer, 'Number of top entries to be displayed. By default all entries are displayed.') do |no|
                 options[:no] = no
         end
----------------------------------------------------

actually, it *did* work. "duck" is not an integer,
so an exception is raised.

[1] http://blog.segment7.net/2008/01/05/optionparser-argument-casting

--
<https://github.com/stomar/&gt;

Maybe you were looking for something like this:

···

-----
require 'optparse'

options = {
   :no => 0
}

opts = OptionParser.new do |opts|
   opts.on('-n', '--no N',
           "Number of... Default value: #{options[:no]}") do |no|
     if /\A[+]?\d+\Z/ === no # nonnegative integer?
       options[:no] = no
     else
       warn "#{no} is not a nonnegative integer, using default value"
     end
   end
end

opts.parse!(ARGV)

p options
-----

$ ruby optparse.rb -n -5
-5 is not a nonnegative integer, using default value
{:no=>0}

$ ruby optparse.rb -n 3
{:no=>"3"}

Am 03.08.2012 18:03, schrieb Panagiotis Atmatzidis:

----------------------------------------------------
# check if options[:no] is interger

if options[:no]
         begin
                 $no = Integer(options[:no])
         rescue ArgumentError
                 puts "#{$no} is not an Integer!"
         else
                 true
         end
else
         $no = 0
end
----------------------------------------------------

Personally, I do not like provoking an exception only to
test whether no is an integer.
Also, the 'else' part from begin-rescue-else is useless.

--
<https://github.com/stomar/&gt;

Hello

What do you mean, more explanatory?

I want to print an output similar to the one after the rescue keyword below. Just that.

···

On 3 Αυγ 2012, at 19:56 , Jam <jam@jamandbees.net> wrote:

On Aug 3, 2012, at 10:03 AM, Panagiotis Atmatzidis <ml@convalesco.org> wrote:

Hello,

I'd like to make an OptParser error look a bit more explanatory. I tried to deal with it outside OpiontParser like this:

----------------------------------------------------
# check if options[:no] is interger

if options[:no]
      begin
              $no = Integer(options[:no])
      rescue ArgumentError
              puts "#{$no} is not an Integer!"
      else
              true
      end
else
      $no = 0
end
----------------------------------------------------
but didn't work. The error I get from cli is:

f2bread.rb:483:in `<main>': invalid argument: -s duck (OptionParser::InvalidArgument)

Apparently I need to somehow handle this from within OptionParser. Any ideas on how to proceed? I found this post[1] online which explains what I want but I couldn't figure how exactly it works. So some actual codes with a sort of explanation of where *exactly* sits on the program (outside or inside "OptionParser.new" class?).

The relevant OptionParser lines, where is specified that '-n' accepts Integers, are:
----------------------------------------------------
opts.on('-n', '--no N', Integer, 'Number of top entries to be displayed. By default all entries are displayed.') do |no|
              options[:no] = no
      end
----------------------------------------------------

[1] http://blog.segment7.net/2008/01/05/optionparser-argument-casting

Best Regards,

Panagiotis Atmatzidis
-----------------------------
Pharmacy Student at VFU

email4lists: ml@convalesco.org
More info: http://about.me/atmosx

The wise man said: "Never argue with an idiot, he brings you down to his level and beat you with experience."

Panagiotis Atmatzidis
-----------------------------
Pharmacy Student at VFU

email4lists: ml@convalesco.org
More info: http://about.me/atmosx

The wise man said: "Never argue with an idiot, he brings you down to his level and beat you with experience."

Hello,

Thanks for the reply.

It is not clear to me what your problem is.

I dislike the way the error is displayed. I'd like to print a message like the one after the 'rescue' keyword. Maybe it's not a good practice though and I should leave it as is.

Slightly adapted from the post cited by you:

-----
require 'optparse'

options = {}

opts = OptionParser.new do |opts|
# Cast 'no' argument to an Integer.
opts.on('-n', '--no N', Integer, 'Number of...') do |no|
   options[:no] = no
end
end

opts.parse!(ARGV)

p options
-----

results (as it should) in

$ ruby optparse.rb -n 34
{:no=>34}

$ ruby optparse.rb -n duck
optparse.rb:12:in `<main>': invalid argument: -n duck (OptionParser::InvalidArgument)

----------------------------------------------------
# check if options[:no] is interger

if options[:no]
        begin
                $no = Integer(options[:no])
        rescue ArgumentError
                puts "#{$no} is not an Integer!"
        else
                true
        end
else
        $no = 0
end

This is not necessary, since the option value has already been
cast to an integer, or an exception has been raised.

Btw, you should not use global variables.

Why not?

----------------------------------------------------
but didn't work. The error I get from cli is:

f2bread.rb:483:in `<main>': invalid argument: -s duck (OptionParser::InvalidArgument)

Apparently I need to somehow handle this from within OptionParser. Any ideas on how to proceed? I found this post[1] online which explains what I want but I couldn't figure how exactly it works. So some actual codes with a sort of explanation of where *exactly* sits on the program (outside or inside "OptionParser.new" class?).

The relevant OptionParser lines, where is specified that '-n' accepts Integers, are:
----------------------------------------------------
opts.on('-n', '--no N', Integer, 'Number of top entries to be displayed. By default all entries are displayed.') do |no|
                options[:no] = no
        end
----------------------------------------------------

actually, it *did* work. "duck" is not an integer,
so an exception is raised.

I just want to print a predefined error message. It seems more easy to read to me, although as I said above, it might not be a good practice and I'm not sure anymore if I should add it or no :stuck_out_tongue: given the fact that you're the second person pointing out that "it's working as it should".

[1] http://blog.segment7.net/2008/01/05/optionparser-argument-casting

--
<https://github.com/stomar/&gt;

A bit off-topic now. In your next email you told me that you dislike raising an exception in order to identify an integer. A second approach I found online was using regexp. However this was the answer I got from a user at 'stackoverflow' which convinced that this is the right way to go in ruby:

"Sarah: you can use a Regex but in order to handle all the cases that Ruby does when parsing integers (negative numbers, hex, octal, underscores e.g. 1_000_000) it would be a very big Regex and easy to get wrong. Integer() is canonical because with Integer ()you know for sure that anything that Ruby considers an integer literal will be accepted, and everything else will be rejected. Duplicating what the language already gives you is arguably a worse code smell than using exceptions for control. – Avdi " from How to test if a string is basically an integer in quotes using Ruby - Stack Overflow

Best Regards

Panagiotis Atmatzidis

···

On 3 Αυγ 2012, at 21:21 , sto.mar@web.de wrote:

Am 03.08.2012 18:03, schrieb Panagiotis Atmatzidis:

-----------------------------
Pharmacy Student at VFU

email4lists: ml@convalesco.org
More info: http://about.me/atmosx

The wise man said: "Never argue with an idiot, he brings you down to his level and beat you with experience."

A bit off-topic now. In your next email you told me that you dislike
raising an exception in order to identify an integer. A second
approach I found online was using regexp.

That's what I did in my version, too.

However this was the answer I got from a user at 'stackoverflow'
which convinced that this is the right way to go in ruby:

"Sarah: you can use a Regex but in order to handle all the cases that
Ruby does when parsing integers (negative numbers, hex, octal,
underscores e.g. 1_000_000) it would be a very big Regex and easy to
get wrong. Integer() is canonical because with Integer ()you know
for sure that anything that Ruby considers an integer literal will be
accepted, and everything else will be rejected. Duplicating what the
language already gives you is arguably a worse code smell than using
exceptions for control. – Avdi " from
How to test if a string is basically an integer in quotes using Ruby - Stack Overflow

Imo there is no "canonical" way that fits all use cases.

Here, in connection with command line arguments, I prefer
using a regexp (probably as a second choice after using the Integer
cast from optparse): I do not expect an octal integer as user input,
the regexp is rather simple, and the approach is flexible.
I can for example test for integers or for nonnegative integers, with

/\A[+-]?\d+\Z/ === str or /\A[+]?\d+\Z/ === str

Partly a matter of taste.

···

Am 04.08.2012 01:31, schrieb Panagiotis Atmatzidis:

--
<https://github.com/stomar/&gt;