Strange behaviour in OptionParser class

H

Hunter Kelly

If I run the following:

#!/usr/bin/ruby -w

require 'optparse'

$host = "localhost"
$user = nil
$db = nil

opts = OptionParser.new
opts.on("-h", "--host", "=HOST", "hostname") { | h | $host = h }
opts.on("-u", "--user", "=USER", "username") { | u | $user = u }
opts.on("--db=DATABASE", "database") { | db | $db=db }

words=%w(--user --host=hostname --db=dbname blah blah blah)
rest = opts.parse(*words)

puts "user: #{$user} rest: #{rest.join(',')} host: #{$host} db:
#{$db}"

------

I get the following output:

user: --host=hostname ok: blah,blah,blah host: localhost db: dbname

I would think that this should generate some form of error: if an
option has a mandatory argument, it doesn't really make sense to me to
blithely assign the next argument - particularly in this case, where it
is obviously another option.

Am I correct in my thinking here, or did I miss something, or is this
just something that OptionParser doesn't support?

Thanks,

Hunter
 
R

Robert Klemme

Hunter Kelly said:
If I run the following:

#!/usr/bin/ruby -w

require 'optparse'

$host = "localhost"
$user = nil
$db = nil

opts = OptionParser.new
opts.on("-h", "--host", "=HOST", "hostname") { | h | $host = h }
opts.on("-u", "--user", "=USER", "username") { | u | $user = u }
opts.on("--db=DATABASE", "database") { | db | $db=db }

words=%w(--user --host=hostname --db=dbname blah blah blah)
rest = opts.parse(*words)

puts "user: #{$user} rest: #{rest.join(',')} host: #{$host} db:
#{$db}"

------

I get the following output:

user: --host=hostname ok: blah,blah,blah host: localhost db: dbname

I would think that this should generate some form of error: if an
option has a mandatory argument, it doesn't really make sense to me to
blithely assign the next argument - particularly in this case, where it
is obviously another option.

Am I correct in my thinking here, or did I miss something, or is this
just something that OptionParser doesn't support?

I think you missed something. :) How do you want OP to detect whether
it's a valid option value or an option if it's a string field without
further speficiation? It might for example be an option of another
program that is invoked later so it's not uncommon to have options as
values of options.

Note, that you can use a regexp for validation if you want to prevent this
case:

opts.on("-u", "--user", "=USER", /[^-].*/, "username") { | u | $user = u }
opts.on("-u", "--user", "=USER", /\w+/, "username") { | u | $user = u }

Also, for numeric options you can use Integer etc. plus you can throw
OptionParser::InvalidArgument from the block or you define a criterium
like this:

crit = Object.new
def crit.match(o)
/^[^-]/ === o && [o]
end
....
opts.on("-u", "--user", "=USER", crit, "username") { | u | $user = u }

Any of these will happily throw with your command line. So there's plenty
of ways to do it if you want to be more restrictive... :))

Kind regards

robert
 
H

Hunter Kelly

Yah, that's fair enough I suppse (It's what I ended up doing in the
end), but it seems to me that the default behaviour should be to not
match it if it looks like another option. For the special case of
options for another program (or whatever), then put in the special
matching objects or whatever.

I think for me, it's just that it violated the principal of least
surprise. There was an option that needs an argument, and one was
obviously not passed in - that looks like an error to me.

Thanks,

Hunter
 
R

Robert Klemme

Hunter Kelly said:
Yah, that's fair enough I suppse (It's what I ended up doing in the
end), but it seems to me that the default behaviour should be to not
match it if it looks like another option. For the special case of
options for another program (or whatever), then put in the special
matching objects or whatever.

I don't think so. It's your case which is the more restrictive one => you
should specify that you dont't want to accept option like things as
values. I would not want the general case of "any string" to need
explicit mentioning. IMHO this is the most reasonable default.
I think for me, it's just that it violated the principal of least
surprise. There was an option that needs an argument, and one was
obviously not passed in - that looks like an error to me.

This is clearly dependend on the expections: I would be surprised if a
string option value was rejected if I did not specify the string I
expected. :) To me this means: use any string.

You're welcome!

Kind regards

robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,175
Latest member
Vinay Kumar_ Nevatia
Top