Class: CommandParser::CmdParser

Inherits:
Object
  • Object
show all
Defined in:
lib/command_parser.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(args = [], &block) ⇒ CmdParser

Returns a new instance of CmdParser.



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/command_parser.rb', line 56

def initialize(args=[], &block)
    @available_options = Array.new
    @commands = Hash.new
    @command_list = Array.new
    @formats = Hash.new

    @main = nil

    @exit_code = nil

    @args = args
    @options = Hash.new

    @before_proc=nil
    @comm_name=nil

    define_default_formats

    instance_eval(&block)

    addons = Dir["#{OpenNebulaHelper::CLI_ADDONS_LOCATION}/#{File.basename($0)}/*"]
    if defined?(addons) and !addons.nil?
            addons.each do |addon_path|
                addon_code = File.read(addon_path)
                instance_eval(addon_code)
            end
    end

    self.run
end

Instance Attribute Details

#argsObject (readonly)

Returns the value of attribute args.



54
55
56
# File 'lib/command_parser.rb', line 54

def args
  @args
end

#optionsObject (readonly)

Returns the value of attribute options.



54
55
56
# File 'lib/command_parser.rb', line 54

def options
  @options
end

Instance Method Details

#before_proc(&block) ⇒ Object

Defines a proc to be called before any command

Parameters:

  • block (Proc)


114
115
116
# File 'lib/command_parser.rb', line 114

def before_proc(&block)
    @before_proc = block
end

#command(name, desc, *args_format, &block) ⇒ Object

Defines a new action for the command, several actions can be defined for a command. For example: create, delete, list. The options and args variables can be used inside the block, and they contain the parsedarguments and options.

Examples:

Definining two arguments:
    $ onetest test a1 a2

CommandParser::CmdParser.new(ARGV) do
    description "Test"
    usage "onetest <command> <args> [options]"
    version "1.0"

    options VERBOSE, HELP

    command :test, "Test", :test1, :test2, :options => XML do
        puts options[:xml]
        puts options[:verbose]
        puts args[0]
        puts args[1]
        [0, "It works"]
    end
end

Defining optional arguments: test1 is mandatory, test2 optional
    $ onetest test a1 | $ onetest test a1 a2

CommandParser::CmdParser.new(ARGV) do
    description "Test"
    usage "onetest <command> <args> [options]"
    version "1.0"

    options VERBOSE, HELP

    command :test, "Test", :test1, [:test2, nil], :options => XML do
        puts options[:xml]
        puts options[:verbose]
        puts args[0]
        puts "It works"
        0
    end
end

Defining an argument with different formats:
    $ onetest test a1 a2 | $ onetest test a1 123

CommandParser::CmdParser.new(ARGV) do
    description "Test"
    usage "onetest <command> <args> [options]"
    version "1.0"

    options VERBOSE, HELP

    format :format1, "String to Integer" do
        [0, arg.to_i]
    end

    command :test, "Test", :test1, [:format1, format2], :options => XML do
        puts options[:xml]
        puts options[:verbose]
        puts args[0]
        0
    end
end

Parameters:

  • name (Symbol)

    Name of the action (i.e: :create, :list)

  • desc (String)

    Description of the action

  • args_format (Array<Symbol, Array<Symbol, nil>>, Hash)

    arguments or specific options for this actiion Note that the first argument of the command is the action and should not be defined using this parameter. The rest of the argument must be defined using this parameter. This parameter can use formats previously defined with the format method Options are specified using a hash :options => … containing the hashes representing the options. The option method doc contains the hash that has to be used to specify an option

Yield Returns:

  • (Integer, Array[Integer, String])

    the block must return the exit_code and if a String is returned it will be printed



283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
# File 'lib/command_parser.rb', line 283

def command(name, desc, *args_format, &block)
    if name.is_a? (Array)
        name = name.join(" ").to_sym
    end

    cmd = Hash.new
    cmd[:desc] = desc
    cmd[:arity] = 0
    cmd[:options] = []
    cmd[:args_format] = Array.new
    args_format.each {|args|
        if args.instance_of?(Array)
            cmd[:arity]+=1 unless args.include?(nil)
            cmd[:args_format] << args
        elsif args.instance_of?(Hash) && args[:options]
            if args[:options].is_a? Array
                args[:options].flatten!
                args[:options] = args[:options].sort_by {|o| o[:name] }
            end

            cmd[:options] << args[:options]
        else
            cmd[:arity]+=1
            cmd[:args_format] << [args]
        end
    }
    cmd[:proc] = block
    @command_list << name.to_sym
    @commands[name.to_sym] = cmd
end

#deprecated_command(name, new_command) ⇒ Object



314
315
316
317
318
319
320
321
322
323
324
325
326
# File 'lib/command_parser.rb', line 314

def deprecated_command(name, new_command)
    cmd = Hash.new
    cmd[:desc] = "Deprecated, use #{new_command} instead"
    cmd[:arity] = 0
    cmd[:options] = []
    cmd[:args_format] = [[:string, nil]] * 20
    cmd[:deprecated] = new_command
    cmd[:proc] = lambda do
        print_deprecated(new_command)
    end

    @commands[name.to_sym] = cmd
end

#description(str) ⇒ Object

Defines the additional information of the command

Parameters:



102
103
104
# File 'lib/command_parser.rb', line 102

def description(str)
    @description = str
end

#exit_code(code) ⇒ Object

Defines the exit code to be returned by the command

Parameters:

  • code (Integer)


191
192
193
# File 'lib/command_parser.rb', line 191

def exit_code(code)
    @exit_code = code
end

#exit_with_code(code, output = nil) ⇒ Object



195
196
197
198
# File 'lib/command_parser.rb', line 195

def exit_with_code(code, output=nil)
    puts output if output
    exit code
end

#format(format, description, &block) ⇒ Object

Defines a block that will be used to parse the arguments of the command. Formats defined using this method con be used in the arguments section of the command method, when defining a new action

Parameters:

  • format (Symbol)

    name of the format

  • description (String)

Yield Returns:

  • (Array[Integer, String])

    the block must return an Array containing the result (0:success, 1:failure) and the new value for the argument.



129
130
131
132
133
134
# File 'lib/command_parser.rb', line 129

def format(format, description, &block)
    @formats[format] = {
        :desc => description,
        :proc => block
    }
end

#main(*args_format, &block) ⇒ Object

Defines a new action for the command, several actions can be defined for a command. For example: create, delete, list. The options and args variables can be used inside the block, and they contain the parsedarguments and options.

Examples:

Definining two arguments:
    $ onetest a1 a2

CommandParser::CmdParser.new(ARGV) do
    description "Test"
    usage "onetest <args> [options]"
    version "1.0"

    options XML, VERBOSE, HELP

    main :test1, :test2 do
        puts options[:xml]
        puts options[:verbose]
        puts args[0]
        puts args[1]
        [0, "It works"]
    end
end

Defining optional arguments: test1 is mandatory, test2 optional
    $ onetest a1 | $ onetest a1 a2

CommandParser::CmdParser.new(ARGV) do
    description "Test"
    usage "onetest <args> [<options>]"
    version "1.0"

    options XML, VERBOSE, HELP

    main :test1, [:test2, nil] do
        puts options[:xml]
        puts options[:verbose]
        puts args[0]
        puts "It works"
        0
    end
end

Defining an argument with different formats:
    $ onetest a1 a2 | $ onetest a1 123

CommandParser::CmdParser.new(ARGV) do
    description "Test"
    usage "onetest <args> [<options>]"
    version "1.0"

    options XML, VERBOSE, HELP

    format :format1, "String to Integer" do
        [0, arg.to_i]
    end

    main :test1, [:format1, :format2] do
        puts options[:xml]
        puts options[:verbose]
        puts args[0]
        puts args[1]
        0
    end
end

Parameters:

  • args_format (Array<Symbol, Array<Symbol, nil>>)

    arguments or specific options for this actiion Note that the first argument of the command is the action and should not be defined using this parameter. The rest of the argument must be defined using this parameter. This parameter can use formats previously defined with the format method

Yield Returns:

  • (Integer, Array[Integer, String])

    the block must return the exit_code and if a String is returned it will be printed



407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
# File 'lib/command_parser.rb', line 407

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)
            @main[:arity]+=1 unless args.include?(nil)
            @main[:args_format] << args
        elsif args.instance_of?(Hash) && args[:options]
            @available_options << args[:options]
        else
            @main[:arity]+=1
            @main[:args_format] << [args]
        end
    }

    @main[:proc] = block
end

#name(str) ⇒ Object

Defines the name of the command

Parameters:



108
109
110
# File 'lib/command_parser.rb', line 108

def name(str)
    @name = str
end

#option(options) ⇒ Object

Defines a global option for the command that will be used for all the actions

Examples:

This example will define the following options:
    options[:type] = type

TYPE={
    :name => "type",
    :short => "-t type",
    :large => "--type type",
    :format => String,
    :description => "Type of the new Image"
}

This example will define the following options:
    options[:check] = true
    options[:datastore] = id

DATASTORE = {
    :name   => "datastore",
    :short  => "-d id|name",
    :large  => "--datastore id|name" ,
    :description => "Selects the datastore",
    :format => String,
    :proc   => lambda { |o, options|
        options[:check] = true
        [0, OpenNebulaHelper.dname_to_id(o)]
    }
}

Parameters:

  • options (Hash, Array<Hash>)

    the option to be included. An array of options can be also provided

Options Hash (options):

  • :name (String)
  • :short (String)
  • :large (String)
  • :multiple (Boolean)
  • :description (String)
  • :format (Class)
  • :proc (Block)

    The block receives the value of the option and the hash of options. The block must return an Array containing the result (0:success, 1:failure) and the new value for the argument or nil. More than one option can be specified in the block using the options hash. This hash will be available inside the command block.



181
182
183
184
185
186
187
# File 'lib/command_parser.rb', line 181

def option(options)
    if options.instance_of?(Array)
        options.each { |o| @available_options << o }
    elsif options.instance_of?(Hash)
        @available_options << options
    end
end

#runObject



437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
# File 'lib/command_parser.rb', line 437

def run
    comm_name=""

    if @main
        comm_name = @name
        comm      = @main
    elsif
        if @args[0] && !@args[0].match(/^-/)
            while comm.nil? and @args.size > 0 do
                current = @args.shift

                if comm_name.empty?
                    @comm_name = comm_name = "#{current}".to_sym
                else
                    @comm_name = comm_name = "#{comm_name} #{current}".to_sym
                end

                comm      = @commands[comm_name]
            end
        end
    end

    if comm.nil?
        print_help
        exit 0
    end

    if comm[:deprecated]
        print_deprecated(comm[:deprecated])
    end

    extra_options = comm[:options] if comm
    parse(extra_options)

    if comm
        begin
            @before_proc.call if @before_proc
        rescue StandardError => e
            STDERR.puts e.message
            exit(-1)
        end

        check_args!(comm_name, comm[:arity], comm[:args_format])

        begin
            rc = comm[:proc].call

            if rc.instance_of?(Array) && rc[0] != 0
                STDERR.puts rc[1]
                exit(rc[0])
            elsif rc.instance_of?(Array)
                puts rc[1]
                exit(rc[0])
            else
                exit(@exit_code || rc)
            end
        rescue StandardError => e
            STDERR.puts e.message
            exit(-1)
        end
    end
end

#set(e, *args, &block) ⇒ Object

DEPRECATED, use format and options instead



427
428
429
430
431
432
433
434
# File 'lib/command_parser.rb', line 427

def set(e, *args, &block)
    case e
    when :option
        option(args[0])
    when :format
        format(args[0], args[1], &block)
    end
end

#usage(str) ⇒ Object

Defines the usage information of the command

Parameters:



89
90
91
92
# File 'lib/command_parser.rb', line 89

def usage(str)
    @usage = str
    @name ||= @usage.split(' ').first
end

#version(str) ⇒ Object

Defines the version the command

Parameters:



96
97
98
# File 'lib/command_parser.rb', line 96

def version(str)
    @version = str
end