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 `': 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 A.

What do you mean, more explanatory?

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 `’: invalid argument: -n duck
(OptionParser::InvalidArgument)

Am 03.08.2012 18:03, schrieb Panagiotis A.:

     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.

             options[:no] = no
     end

actually, it did work. “duck” is not an integer,
so an exception is raised.

Hello

On 3 Αυγ 2012, at 19:56 , Jam [email protected] wrote:

What do you mean, more explanatory?

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

  begin

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

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 A.

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 A.:

     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.

Hello,

Thanks for the reply.

On 3 Αυγ 2012, at 21:21 , [email protected] wrote:

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.

options[:no] = no
$ ruby optparse.rb -n 34

if options[:no]

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?

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/

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

Best Regards

Panagiotis A.

Am 04.08.2012 01:31, schrieb Panagiotis A.:

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.

exceptions for control. – Avdi " from

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.