问题
I'd like to be able to use ruby's OptionParser to parse sub-commands of the form
COMMAND [GLOBAL FLAGS] [SUB-COMMAND [SUB-COMMAND FLAGS]]
like:
git branch -a
gem list foo
I know I could switch to a different option parser library (like Trollop), but I'm interested in learning how to do this from within OptionParser, since I'd like to learn the library better.
Any tips?
回答1:
Figured it out. I need to use OptionParser#order!
. It will parse all the options from the start of ARGV
until it finds a non-option (that isn't an option argument), removing everything it processes from ARGV
, and then it will quit.
So I just need to do something like:
global = OptionParser.new do |opts|
# ...
end
subcommands = {
'foo' => OptionParser.new do |opts|
# ...
end,
# ...
'baz' => OptionParser.new do |opts|
# ...
end
}
global.order!
subcommands[ARGV.shift].order!
回答2:
It looks like the OptionParser syntax has changed some. I had to use the following so that the arguments array had all of the options not parsed by the opts object.
begin
opts.order!(arguments)
rescue OptionParser::InvalidOption => io
# Prepend the invalid option onto the arguments array
arguments = io.recover(arguments)
rescue => e
raise "Argument parsing failed: #{e.to_s()}"
end
回答3:
There are also other gems you can look at such as main.
回答4:
GLI is the way to go, https://github.com/davetron5000/gli. An excerpt from a tutorial:
#!/usr/bin/env ruby
require 'gli'
require 'hacer'
include GLI::App
program_desc 'A simple todo list'
flag [:t,:tasklist], :default_value => File.join(ENV['HOME'],'.todolist')
pre do |global_options,command,options,args|
$todo_list = Hacer::Todolist.new(global_options[:tasklist])
end
command :add do |c|
c.action do |global_options,options,args|
$todo_list.create(args)
end
end
command :list do |c|
c.action do
$todo_list.list.each do |todo|
printf("%5d - %s\n",todo.todo_id,todo.text)
end
end
end
command :done do |c|
c.action do |global_options,options,args|
id = args.shift.to_i
$todo_list.list.each do |todo|
$todo_list.complete(todo) if todo.todo_id == id
end
end
end
exit run(ARGV)
You can find the tutorial at http://davetron5000.github.io/gli/.
来源:https://stackoverflow.com/questions/2732894/using-rubys-optionparser-to-parse-sub-commands