Class: CommandParser::CmdParser

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

Overview

CmdParser class to handle command line arguments and options

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

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

Returns a new instance of CmdParser.



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/command_parser.rb', line 65

def initialize(args = [], &block)
    @available_options = []
    @commands = {}
    @command_list = []
    @formats = {}

    @main = nil

    @exit_code = nil

    @args = args
    @options = {}

    @before_proc=nil
    @comm_name=nil

    define_default_formats

    instance_eval(&block)

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

    run
end

Instance Attribute Details

#argsObject (readonly)

Returns the value of attribute args.



63
64
65
# File 'lib/command_parser.rb', line 63

def args
  @args
end

#optionsObject (readonly)

Returns the value of attribute options.



63
64
65
# File 'lib/command_parser.rb', line 63

def options
  @options
end

Instance Method Details

#before_proc(&block) ⇒ Object

Defines a proc to be called before any command

Parameters:

  • block (Proc)


125
126
127
# File 'lib/command_parser.rb', line 125

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



294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
# File 'lib/command_parser.rb', line 294

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

    cmd = {}
    cmd[:desc] = desc
    cmd[:arity] = 0
    cmd[:options] = []
    cmd[:args_format] = []
    args_format.each do |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
    end
    cmd[:proc] = block
    @command_list << name.to_sym
    @commands[name.to_sym] = cmd
end

#deprecated_command(name, new_command) ⇒ Object



325
326
327
328
329
330
331
# File 'lib/command_parser.rb', line 325

def deprecated_command(name, new_command)
    cmd = @commands[name.to_sym] || {}
    cmd[:desc] += "\nDeprecated, use #{new_command} instead"
    cmd[:deprecated] = new_command

    @commands[name.to_sym] = cmd
end

#description(str) ⇒ Object

Defines the additional information of the command

Parameters:



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

def description(str)
    @description = str
end

#exit_code(code) ⇒ Object

Defines the exit code to be returned by the command

Parameters:

  • code (Integer)


202
203
204
# File 'lib/command_parser.rb', line 202

def exit_code(code)
    @exit_code = code
end

#exit_with_code(code, output = nil) ⇒ Object



206
207
208
209
# File 'lib/command_parser.rb', line 206

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.



140
141
142
143
144
145
# File 'lib/command_parser.rb', line 140

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



412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
# File 'lib/command_parser.rb', line 412

def main(*args_format, &block)
    @main={}
    @main[:arity] = 0
    @main[:args_format] = []
    args_format.collect do |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
    end

    @main[:proc] = block
end

#name(str) ⇒ Object

Defines the name of the command

Parameters:



119
120
121
# File 'lib/command_parser.rb', line 119

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.



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

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



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
499
500
# File 'lib/command_parser.rb', line 441

def run
    comm_name=''

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

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

            comm = @commands[comm_name]
        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



432
433
434
435
436
437
438
439
# File 'lib/command_parser.rb', line 432

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:



98
99
100
101
102
103
# File 'lib/command_parser.rb', line 98

def usage(str)
    @usage = str
    # rubocop:disable Naming/MemoizedInstanceVariableName
    @name ||= @usage.split(' ').first
    # rubocop:enable Naming/MemoizedInstanceVariableName
end

#version(str) ⇒ Object

Defines the version the command

Parameters:



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

def version(str)
    @version = str
end