mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-22 18:50:08 +03:00
feature #1427: Improve command_parser
* Add support for commands without actions (create..): main * Add exit_code method * Add option method instead of set :option (deprecated) * Add format method instead of set :format (deprecated) * Improve option :proc handling(cherry picked from commit 8572f13fe8cac6583d3bff250fa9e7953272d4f4)
This commit is contained in:
parent
98048f42f7
commit
c71ba4a27e
@ -54,25 +54,18 @@ module CommandParser
|
||||
attr_reader :options, :args
|
||||
|
||||
def initialize(args=[], &block)
|
||||
@opts = Array.new
|
||||
@available_options = Array.new
|
||||
@commands = Hash.new
|
||||
@formats = Hash.new
|
||||
@script = nil
|
||||
|
||||
@main = nil
|
||||
|
||||
@exit_code = nil
|
||||
|
||||
@args = args
|
||||
@options = Hash.new
|
||||
|
||||
set :format, :file, "Path to a file" do |arg|
|
||||
format_file(arg)
|
||||
end
|
||||
|
||||
set :format, :range, "List of id's in the form 1,8..15" do |arg|
|
||||
format_range(arg)
|
||||
end
|
||||
|
||||
set :format, :text, "String" do |arg|
|
||||
format_text(arg)
|
||||
end
|
||||
define_default_formats
|
||||
|
||||
instance_eval(&block)
|
||||
|
||||
@ -80,11 +73,7 @@ module CommandParser
|
||||
end
|
||||
|
||||
def usage(str)
|
||||
@usage=<<EOT
|
||||
## SYNOPSIS
|
||||
|
||||
#{str}
|
||||
EOT
|
||||
@usage=str
|
||||
end
|
||||
|
||||
def version(str)
|
||||
@ -95,15 +84,27 @@ EOT
|
||||
@description = str
|
||||
end
|
||||
|
||||
def set(e, *args, &block)
|
||||
case e
|
||||
when :option
|
||||
add_option(args[0])
|
||||
when :format
|
||||
add_format(args[0], args[1], block)
|
||||
def format(format, description, &block)
|
||||
@formats[format] = {
|
||||
:desc => description,
|
||||
:proc => block
|
||||
}
|
||||
end
|
||||
|
||||
def option(options)
|
||||
if options.instance_of?(Array)
|
||||
options.each { |o| @available_options << o }
|
||||
elsif options.instance_of?(Hash)
|
||||
@available_options << options
|
||||
end
|
||||
end
|
||||
|
||||
# Define the exit code to be returned by the command
|
||||
# @param [Integer] code
|
||||
def exit_code(code)
|
||||
@exit_code = code
|
||||
end
|
||||
|
||||
def exit_with_code(code, output=nil)
|
||||
puts output if output
|
||||
exit code
|
||||
@ -130,28 +131,40 @@ EOT
|
||||
@commands[name.to_sym] = cmd
|
||||
end
|
||||
|
||||
def script(*args_format, &block)
|
||||
@script=Hash.new
|
||||
@script[:args_format] = Array.new
|
||||
def main(*args_format, &block)
|
||||
@main=Hash.new
|
||||
@main[:arity] = 0
|
||||
@main[:args_format] = Array.new
|
||||
args_format.collect {|args|
|
||||
if args.instance_of?(Array)
|
||||
@script[:arity]+=1 unless args.include?(nil)
|
||||
@script[:args_format] << args
|
||||
@main[:arity]+=1 unless args.include?(nil)
|
||||
@main[:args_format] << args
|
||||
elsif args.instance_of?(Hash) && args[:options]
|
||||
@opts << args[:options]
|
||||
@available_options << args[:options]
|
||||
else
|
||||
@script[:arity]+=1
|
||||
@script[:args_format] << [args]
|
||||
@main[:arity]+=1
|
||||
@main[:args_format] << [args]
|
||||
end
|
||||
}
|
||||
|
||||
@script[:proc] = block
|
||||
@main[:proc] = block
|
||||
end
|
||||
|
||||
# DEPRECATED, use format and options instead
|
||||
def set(e, *args, &block)
|
||||
case e
|
||||
when :option
|
||||
option(args[0])
|
||||
when :format
|
||||
format(args[0], args[1], &block)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def run
|
||||
comm_name=""
|
||||
if @script
|
||||
comm=@script
|
||||
if @main
|
||||
comm=@main
|
||||
elsif
|
||||
if @args[0] && !@args[0].match(/^-/)
|
||||
comm_name=@args.shift.to_sym
|
||||
@ -160,7 +173,7 @@ EOT
|
||||
end
|
||||
|
||||
if comm.nil?
|
||||
help
|
||||
print_help
|
||||
exit -1
|
||||
end
|
||||
|
||||
@ -175,133 +188,17 @@ EOT
|
||||
puts rc[1]
|
||||
exit rc.first
|
||||
else
|
||||
exit rc
|
||||
exit(@exit_code || rc)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def help
|
||||
puts @usage if @usage
|
||||
puts
|
||||
puts @description if @description
|
||||
puts
|
||||
print_options
|
||||
puts
|
||||
print_commands
|
||||
puts
|
||||
print_formatters
|
||||
puts
|
||||
if @version
|
||||
puts "## LICENSE"
|
||||
puts @version
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def print_options
|
||||
puts "## OPTIONS"
|
||||
|
||||
shown_opts = Array.new
|
||||
opt_format = "#{' '*5}%-25s %s"
|
||||
@commands.each{ |key,value|
|
||||
value[:options].flatten.each { |o|
|
||||
if shown_opts.include?(o[:name])
|
||||
next
|
||||
else
|
||||
shown_opts << o[:name]
|
||||
|
||||
str = ""
|
||||
str << o[:short].split(' ').first << ', ' if o[:short]
|
||||
str << o[:large]
|
||||
|
||||
printf opt_format, str, o[:description]
|
||||
puts
|
||||
end
|
||||
}
|
||||
}
|
||||
|
||||
@opts.each{ |o|
|
||||
str = ""
|
||||
str << o[:short].split(' ').first << ', ' if o[:short]
|
||||
str << o[:large]
|
||||
|
||||
printf opt_format, str, o[:description]
|
||||
puts
|
||||
}
|
||||
end
|
||||
|
||||
def print_commands
|
||||
puts "## COMMANDS"
|
||||
|
||||
cmd_format5 = "#{' '*3}%s"
|
||||
cmd_format10 = "#{' '*8}%s"
|
||||
@commands.each{ |key,value|
|
||||
printf cmd_format5, "* #{key} "
|
||||
|
||||
args_str=value[:args_format].collect{ |a|
|
||||
if a.include?(nil)
|
||||
"[<#{a.compact.join("|")}>]"
|
||||
else
|
||||
"<#{a.join("|")}>"
|
||||
end
|
||||
}.join(' ')
|
||||
printf "#{args_str}"
|
||||
puts
|
||||
|
||||
value[:desc].split("\n").each { |l|
|
||||
printf cmd_format10, l
|
||||
puts
|
||||
}
|
||||
|
||||
unless value[:options].empty?
|
||||
opts_str=value[:options].flatten.collect{|o|
|
||||
o[:name]
|
||||
}.join(', ')
|
||||
printf cmd_format10, "valid options: #{opts_str}"
|
||||
puts
|
||||
end
|
||||
puts
|
||||
}
|
||||
end
|
||||
|
||||
def print_formatters
|
||||
puts "## ARGUMENT FORMATS"
|
||||
|
||||
cmd_format5 = "#{' '*3}%s"
|
||||
cmd_format10 = "#{' '*8}%s"
|
||||
@formats.each{ |key,value|
|
||||
printf cmd_format5, "* #{key}"
|
||||
puts
|
||||
|
||||
value[:desc].split("\n").each { |l|
|
||||
printf cmd_format10, l
|
||||
puts
|
||||
}
|
||||
|
||||
puts
|
||||
}
|
||||
end
|
||||
|
||||
def add_option(option)
|
||||
if option.instance_of?(Array)
|
||||
option.each { |o| @opts << o }
|
||||
elsif option.instance_of?(Hash)
|
||||
@opts << option
|
||||
end
|
||||
end
|
||||
|
||||
def add_format(format, description, block)
|
||||
@formats[format] = {
|
||||
:desc => description,
|
||||
:proc => block
|
||||
}
|
||||
end
|
||||
|
||||
def parse(extra_options)
|
||||
@cmdparse=OptionParser.new do |opts|
|
||||
merge = @opts
|
||||
merge = @opts + extra_options if extra_options
|
||||
merge = @available_options
|
||||
merge = @available_options + extra_options if extra_options
|
||||
merge.flatten.each do |e|
|
||||
args = []
|
||||
args << e[:short] if e[:short]
|
||||
@ -311,9 +208,16 @@ EOT
|
||||
|
||||
opts.on(*args) do |o|
|
||||
if e[:proc]
|
||||
e[:proc].call(o, @options)
|
||||
rc = e[:proc].call(o, @options)
|
||||
if rc.instance_of?(Array) && rc[0] == 0
|
||||
options[e[:name].to_sym] = rc[1]
|
||||
else
|
||||
puts rc[1]
|
||||
puts "option #{e[:name]}: Parsing error"
|
||||
exit -1
|
||||
end
|
||||
elsif e[:name]=="help"
|
||||
help
|
||||
print_help
|
||||
exit
|
||||
elsif e[:name]=="version"
|
||||
puts @version
|
||||
@ -399,7 +303,126 @@ EOT
|
||||
end
|
||||
|
||||
########################################################################
|
||||
# Formatters for arguments
|
||||
# Printers
|
||||
########################################################################
|
||||
|
||||
def print_help
|
||||
if @usage
|
||||
puts "## SYNOPSIS"
|
||||
puts
|
||||
puts @usage
|
||||
puts
|
||||
end
|
||||
puts @description if @description
|
||||
puts
|
||||
print_options
|
||||
puts
|
||||
print_commands
|
||||
puts
|
||||
print_formatters
|
||||
puts
|
||||
if @version
|
||||
puts "## LICENSE"
|
||||
puts @version
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def print_options
|
||||
puts "## OPTIONS"
|
||||
|
||||
shown_opts = Array.new
|
||||
opt_format = "#{' '*5}%-25s %s"
|
||||
@commands.each{ |key,value|
|
||||
value[:options].flatten.each { |o|
|
||||
if shown_opts.include?(o[:name])
|
||||
next
|
||||
else
|
||||
shown_opts << o[:name]
|
||||
|
||||
str = ""
|
||||
str << o[:short].split(' ').first << ', ' if o[:short]
|
||||
str << o[:large]
|
||||
|
||||
printf opt_format, str, o[:description]
|
||||
puts
|
||||
end
|
||||
}
|
||||
}
|
||||
|
||||
@available_options.each{ |o|
|
||||
str = ""
|
||||
str << o[:short].split(' ').first << ', ' if o[:short]
|
||||
str << o[:large]
|
||||
|
||||
printf opt_format, str, o[:description]
|
||||
puts
|
||||
}
|
||||
end
|
||||
|
||||
def print_commands
|
||||
cmd_format5 = "#{' '*3}%s"
|
||||
cmd_format10 = "#{' '*8}%s"
|
||||
|
||||
if @main
|
||||
print_command(@main)
|
||||
else
|
||||
puts "## COMMANDS"
|
||||
|
||||
@commands.each{ |key,value|
|
||||
printf cmd_format5, "* #{key} "
|
||||
|
||||
print_command(value)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def print_command(command)
|
||||
args_str=command[:args_format].collect{ |a|
|
||||
if a.include?(nil)
|
||||
"[<#{a.compact.join("|")}>]"
|
||||
else
|
||||
"<#{a.join("|")}>"
|
||||
end
|
||||
}.join(' ')
|
||||
printf "#{args_str}"
|
||||
puts
|
||||
|
||||
command[:desc].split("\n").each { |l|
|
||||
printf cmd_format10, l
|
||||
puts
|
||||
}
|
||||
|
||||
unless command[:options].empty?
|
||||
opts_str=command[:options].flatten.collect{|o|
|
||||
o[:name]
|
||||
}.join(', ')
|
||||
printf cmd_format10, "valid options: #{opts_str}"
|
||||
puts
|
||||
end
|
||||
puts
|
||||
end
|
||||
|
||||
def print_formatters
|
||||
puts "## ARGUMENT FORMATS"
|
||||
|
||||
cmd_format5 = "#{' '*3}%s"
|
||||
cmd_format10 = "#{' '*8}%s"
|
||||
@formats.each{ |key,value|
|
||||
printf cmd_format5, "* #{key}"
|
||||
puts
|
||||
|
||||
value[:desc].split("\n").each { |l|
|
||||
printf cmd_format10, l
|
||||
puts
|
||||
}
|
||||
|
||||
puts
|
||||
}
|
||||
end
|
||||
|
||||
########################################################################
|
||||
# Default Formatters for arguments
|
||||
########################################################################
|
||||
def format_text(arg)
|
||||
arg.instance_of?(String) ? [0,arg] : [-1]
|
||||
@ -432,6 +455,20 @@ EOT
|
||||
|
||||
return 0,ids.uniq
|
||||
end
|
||||
|
||||
def define_default_formats
|
||||
format :file, "Path to a file" do |arg|
|
||||
format_file(arg)
|
||||
end
|
||||
|
||||
format :range, "List of id's in the form 1,8..15" do |arg|
|
||||
format_range(arg)
|
||||
end
|
||||
|
||||
format :text, "String" do |arg|
|
||||
format_text(arg)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -25,18 +25,10 @@ class OneClusterHelper < OpenNebulaHelper::OneHelper
|
||||
:description => "Selects the cluster",
|
||||
:format => String,
|
||||
:proc => lambda { |o, options|
|
||||
ch = OneClusterHelper.new
|
||||
rc, cid = ch.to_id(o)
|
||||
if rc == 0
|
||||
options[:cluster] = cid
|
||||
else
|
||||
puts cid
|
||||
puts "option cluster: Parsing error"
|
||||
exit -1
|
||||
end
|
||||
OpenNebulaHelper.rname_to_id(o, "CLUSTER")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def self.rname
|
||||
"CLUSTER"
|
||||
end
|
||||
|
@ -24,15 +24,7 @@ class OneDatastoreHelper < OpenNebulaHelper::OneHelper
|
||||
:description => "Selects the datastore",
|
||||
:format => String,
|
||||
:proc => lambda { |o, options|
|
||||
ch = OneDatastoreHelper.new
|
||||
rc, dsid = ch.to_id(o)
|
||||
if rc == 0
|
||||
options[:datastore] = dsid
|
||||
else
|
||||
puts dsid
|
||||
puts "option datastore: Parsing error"
|
||||
exit -1
|
||||
end
|
||||
OpenNebulaHelper.rname_to_id(o, "DATASTORE")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,14 +32,7 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
|
||||
:description => "Selects the image",
|
||||
:format => String,
|
||||
:proc => lambda { |o, options|
|
||||
rc, imid = OpenNebulaHelper.rname_to_id(o, "IMAGE")
|
||||
if rc == 0
|
||||
options[:image] = imid
|
||||
else
|
||||
puts imid
|
||||
puts "option image: Parsing error"
|
||||
exit -1
|
||||
end
|
||||
OpenNebulaHelper.rname_to_id(o, "IMAGE")
|
||||
}
|
||||
}
|
||||
|
||||
@ -188,13 +181,13 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
|
||||
"USED CPU" => "CPU",
|
||||
"NET_TX" => "NET_TX",
|
||||
"NET_RX" => "NET_RX"
|
||||
}
|
||||
}
|
||||
|
||||
poll_attrs.each { |k,v|
|
||||
poll_attrs.each { |k,v|
|
||||
if k == "USED CPU"
|
||||
puts str % [k,vm[v]]
|
||||
puts str % [k,vm[v]]
|
||||
elsif k == "USED MEMORY"
|
||||
puts str % [k, OpenNebulaHelper.unit_to_str(vm[v].to_i, {})]
|
||||
puts str % [k, OpenNebulaHelper.unit_to_str(vm[v].to_i, {})]
|
||||
else
|
||||
puts str % [k, OpenNebulaHelper.unit_to_str(vm[v].to_i/1024, {})]
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user