def self.run(args = ARGV)
@input ||= $stdin
@output ||= $stdout
@output.string = "" if @output.respond_to?(:string)
args = Shellwords.split(args) if args.respond_to?(:split)
@option_defs ||= {}
orig = args
@parser = OptionParser.new
opts = @topics.each_with_object({}) do |tpc, o|
tpc.option_defs.each do |k, optdef|
@parser.on(*optdef) do |v|
o[k] = (o[k] ? Array(o[k]).push(v) : v )
end
@option_defs[k] = optdef
end
end
@parser.parse! args
preprocess_options(args, opts)
@topics.each do |tpc|
tpc.commands.each do |k, v|
next unless args[0..v[:parts].length - 1] == v[:parts]
args = args[v[:parts].length..-1]
if v[:argc] == -1
elsif args.length > v[:argc]
return handle_bad_command(orig, "Too many command line parameters given.")
elsif args.length < v[:argc]
(v[:argc] - args.length).times { args << nil }
end
opts.keys.each do |o|
next if v[:options].include?(o) || @global_options.include?(o)
return handle_bad_command(orig, "Invalid option: #{o}")
end
return tpc.new(self, opts, @input, @output).send(k, *args)
end
end
@output.puts "#{File.basename($0)}: subcommand not found"
rescue Exception => e
@output.puts "#{File.basename($0)} error", "#{e.class}: #{e.message}", (e.backtrace if opts[:trace])
ensure
puts @output.string if opts[:trace] && @print_on_trace && @output.respond_to?(:string)
end