Hi there, I'm trying to wrap a command line tool with a Ruby script in order to be able to clean up and validate any user supplied arguments before calling the tool. I'm therefore trying to use OptionParser to parse the command line arguments and pass them on to the tool after processing. However, the tool accepts short arguments that have multi character names. For example, '-o filename' and '-oo filename' where the double 'o' signifies that the file should be overwritten and not appended to. OptionParser can't cope with multi char short options so what can I do here? Can I extend OptionParser in any way or should I try and manually parse for these short options before calling option parser? Doesn't seem too clean that way. Cheers.
on 2013-03-01 13:45
on 2013-03-01 14:04
On Fri, Mar 1, 2013 at 1:45 PM, Shareef J. <lists@ruby-forum.com> wrote: > I'm trying to wrap a command line tool with a Ruby script in order to be > able to clean up and validate any user supplied arguments before calling > the tool. I'm therefore trying to use OptionParser to parse the command > line arguments and pass them on to the tool after processing. > > However, the tool accepts short arguments that have multi character > names. I think this is self contradictory: short options are one character options. :-) > For example, '-o filename' and '-oo filename' where the double > 'o' signifies that the file should be overwritten and not appended to. > OptionParser can't cope with multi char short options so what can I do > here? Can I extend OptionParser in any way or should I try and manually > parse for these short options before calling option parser? Doesn't > seem too clean that way. That doesn't seem to fit the model of OptionParser well. You would have to define that -o takes an optional argument but if you do that it'll use the second "o" as argument. irb(main):017:0> op = OptionParser.new do |opts| irb(main):018:1* opts.on('-o=[arg]') {|v| o += 1; o_val << v if v} irb(main):019:1> end => Usage: irb [options] -o=[arg] irb(main):020:0> op.parse %w{-o} => [] irb(main):021:0> o => 1 irb(main):022:0> o_val => [] irb(main):023:0> o = 0; o_val = [] => [] irb(main):024:0> op.parse %w{-o val} => ["val"] irb(main):025:0> o => 1 irb(main):026:0> o_val => [] irb(main):027:0> o = 0; o_val = [] => [] irb(main):028:0> op.parse %w{-oo val} => ["val"] irb(main):029:0> o => 1 irb(main):030:0> o_val => ["o"] If the tool has an option --dry-run or similar I'd simply add that to the command line and see what it reports. Other than that I'd probably avoid the validation. Reason is that you need to change your validation every time the tool's API changes - and you have the validation code in two places. Kind regards robert
on 2013-03-04 11:09
Robert, thanks for that. Unfortunately the validation needs to be there so I'll have to roll my own solution. Was just hoping that I could reuse a library.
on 2013-03-04 12:05
Actually, with minimal hacking I've managed to get it to do what I want.
Here's the patch file for anyone interested. I'm running 1.9.2.
$ cat optparse.patch
--- optparse.rb 2013-03-04 10:58:37.789740398 +0000
+++ optparse.rb.modified 2013-03-04 10:55:44.866359326 +0000
@@ -1154,6 +1154,15 @@
end
sdesc << "-#{q}"
short << Regexp.new(q)
+ when /^-(.\S)(.+)?/
+ q, a = $1, $2
+ if a
+ o = notwice(NilClass, klass, 'type')
+ default_style = default_style.guess(arg = a)
+ default_pattern, conv = search(:atype, o) unless
default_pattern
+ end
+ sdesc << "-#{q}"
+ short << q
when /^-(.)(.+)?/
q, a = $1, $2
if a
@@ -1281,7 +1290,7 @@
end
# short option
- when /\A-(.)((=).*|.+)?/m
+ when /\A-(.(?:.)?)((=).*|.+)?/m
opt, has_arg, eq, val, rest = $1, $3, $3, $2, $2
begin
sw, = search(:short, opt)
on 2013-03-04 13:20
Am 04.03.2013 12:05, schrieb Shareef J.: > Actually, with minimal hacking I've managed to get it to do what I want. > Here's the patch file for anyone interested. I'm running 1.9.2. You could always parse and modify the command line arguments before passing them on to OptionParser. Then you wouldn't have to meddle with library internals.
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.