Need Help With OptionParser

B

Bryan Richardson

[Note: parts of this message were removed to make it a legal post.]

Hello all,

I'm wrapping a bunch of scripts with an command-line program, and I'm
wanting to use OptionParser to grab some of the options for the wrapper
application. Can anyone tell me if it's possible to rescue all the invalid
options for the wrapper application such that I can leave them in ARGV so
they're available to my scripts when I load them?
 
N

Nobuyoshi Nakada

Hi,

At Wed, 20 Feb 2008 10:00:17 +0900,
Bryan Richardson wrote in [ruby-talk:291710]:
I'm wrapping a bunch of scripts with an command-line program, and I'm
wanting to use OptionParser to grab some of the options for the wrapper
application. Can anyone tell me if it's possible to rescue all the invalid
options for the wrapper application such that I can leave them in ARGV so
they're available to my scripts when I load them?

OptionParser raises an OptionParser::InvalidOption, which has
erred option in args.

others = []
ARGV.options do |opt|
opt.on("--foo=BAR") {|foo| puts "foo option #{foo}"}
begin
opt.parse!
rescue OptionParser::InvalidOption => e
others.concat(e.args)
end
end
exec("your command", *ohters)
 
B

Bryan Richardson

[Note: parts of this message were removed to make it a legal post.]

Perfect!!! Thanks for the help.

Hi,

At Wed, 20 Feb 2008 10:00:17 +0900,
Bryan Richardson wrote in [ruby-talk:291710]:
I'm wrapping a bunch of scripts with an command-line program, and I'm
wanting to use OptionParser to grab some of the options for the wrapper
application. Can anyone tell me if it's possible to rescue all the invalid
options for the wrapper application such that I can leave them in ARGV so
they're available to my scripts when I load them?

OptionParser raises an OptionParser::InvalidOption, which has
erred option in args.

others = []
ARGV.options do |opt|
opt.on("--foo=BAR") {|foo| puts "foo option #{foo}"}
begin
opt.parse!
rescue OptionParser::InvalidOption => e
others.concat(e.args)
end
end
exec("your command", *ohters)
 
7

7stud --

Bryan said:
Perfect!!! Thanks for the help.


I see several problems with that solution:

1) It uses an undocumented feature: the .options attribute of ARGV.

2) It uses the try/except mechanism which slows down your program when a
exception actually occurs.

3) The fact that an option might not be a wrapper option is not an
exceptional event--you regularly expect that to be the case.

4) It requires that you use a user defined array in place of ARGV.


Here's another solution:


require 'optparse'

p ARGV
puts

opts = OptionParser.new do |opts|

#wrapper option where value is required:
opts.on("-t=RANDOM_CHARS") do |val|
puts "-t option entered with value=#{val}"

opt_index = ARGV.index('-t')

#delete option and its value:
ARGV.delete_at(opt_index) #rest of elements move one spot to the
left
ARGV.delete_at(opt_index)
end

#wrapper option where value is optional:
opts.on("-y [=RANDOM_CHARS]") do |val| #val==nil if no value for
option
puts "-y option entered with value=#{val}"

opt_index = ARGV.index('-y')
ARGV.delete_at(opt_index)

if val
ARGV.delete_at(opt_index)
end

end

#non-wrapper option:
opts.on("-a=RANDOM_CHARS") do |val|
puts "-a option entered with value=#{val}"
end

end


opts.parse(ARGV)
p ARGV


Problems with that solution:

I'm not thrilled with the code that deletes elements out of ARGV--that's
inefficient because the rest of the elements have to be shuffled over
one spot. On the other hand, if I collect all the desired options into
an array and then assign the array to ARGV, I get a warning:

warning: already initialized constant ARGV
 
N

Nobuyoshi Nakada

Hi,

At Wed, 20 Feb 2008 15:44:31 +0900,
I see several problems with that solution:

1) It uses an undocumented feature: the .options attribute of ARGV.

It's an documented feature of OptionParser.
4) It requires that you use a user defined array in place of ARGV.

Sorry, I'm not sure what you mean by "a user defined array".
 
7

7stud --

Try this one:


require 'optparse'

p ARGV
puts

non_wrapper_options = []
opts = OptionParser.new do |opts|

#wrapper option where value is required:
opts.on("-t=RANDOM_CHARS") do |val|
puts "-t option entered with value=#{val}"
end

#wrapper option where value is optional:
opts.on("-y [=RANDOM_CHARS]") do |val|
puts "-y option entered with value=#{val}"
end

#non-wrapper option where value is optional:
opts.on("-a[=RANDOM_CHARS]") do |val|
puts "-a option entered with value=#{val}"

non_wrapper_options << '-a'
if val
non_wrapper_options << val
end

end
end


opts.parse(ARGV)

ARGV.replace(non_wrapper_options)
puts
p ARGV


--output:--
$ ruby optparseEx2.rb -y -thello -a goodbye
["-y", "-thello", "-a", "goodbye"]

-y option entered with value=
-t option entered with value=hello
-a option entered with value=

["-a"]
 
R

Robert Klemme

2008/2/20 said:
I see several problems with that solution:
2) It uses the try/except mechanism which slows down your program when a
exception actually occurs.

Options are only parsed once per invocation. The exception time is
easily dominated by process exec time and the runtime of the wrapped
program.
3) The fact that an option might not be a wrapper option is not an
exceptional event--you regularly expect that to be the case.

Well, but from OptionParser's perspective it *is* an exception: the
option is unkown to OptionParser and hence it cannot process properly.
I do agree though that it is a bit odd, especially considering that
all other options still are parsed properly which might not
necessarily be expected (I would expect OptionParser to bail out at
the first unknown option by default).
Problems with that solution:

I'm not thrilled with the code that deletes elements out of ARGV--that's
inefficient because the rest of the elements have to be shuffled over
one spot. On the other hand, if I collect all the desired options into
an array and then assign the array to ARGV, I get a warning:

warning: already initialized constant ARGV

Another issue I see with your solution is that you might run into
problems because you remove items from a collection that is being
iterated over. That's usually unsafe.

This on is a bit artificial: by using ARGV.index to find an option
your code assumes that OptionParser will process options left to
right. If it chooses a different approach you might end up deleting
the wrong instance of a duplicated option.

Kind regards

robert
 
7

7stud --

Robert said:
Options are only parsed once per invocation. The exception time is
easily dominated by process exec time and the runtime of the wrapped
program.
Options are only parsed once per invocation.

What's an invocation, and what's that go to do with anything?
The exception time is
easily dominated by process exec time and the runtime of the wrapped
program.

I don't know what that means. Are you saying that if the program runs
for an hour, the extra exception processing time only takes an
additional 15 seconds?
 
R

Robert Klemme

2008/2/20 said:
What's an invocation, and what's that go to do with anything?

Process invocation in this case.
I don't know what that means. Are you saying that if the program runs
for an hour, the extra exception processing time only takes an
additional 15 seconds?

Apart from the fact that processing a single exception uses less than
15 seconds, yes. The exception processing time is negligible compared
to the time necessary for exec and for running the wrapped program.

Cheers

robert
 
7

7stud --

Robert said:
Process invocation in this case.


Apart from the fact that processing a single exception uses less than
15 seconds, yes.

How do you know there won't be 40 million exceptions? Would process
exec time and the runtime of the wrapped program dominate the exception
time in that case?
 
R

Robert Klemme

2008/2/20 said:
How do you know there won't be 40 million exceptions? Would process
exec time and the runtime of the wrapped program dominate the exception
time in that case?

Yes, because you get at most 1 exception per process invocation - so
there must be 40 million process invocations which are several orders
of magnitude more expensive than the exception processing.

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

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top