class KXI::CLI::Verb

Represents a verb of console interface

Public Class Methods

new(nm, desc, ctx = nil) { |self| ... } click to toggle source

Instantiates the {KXI::CLI::Verb} class @param nm [String] Name of verb @param desc [String] Description of verb @param ctx [String] Context of verb @yield [verb] Initialization body of verb @yieldparam verb [KXI::CLI::Verb] Initialized verb @raise [Exception] When name of verb is invalid

# File lib/kxi/cli/verb.rb, line 47
def initialize(nm, desc, ctx = nil)
        raise(Exception.new('Invalid name of verb!')) unless /^[A-Za-z0-9][A-Za-z0-9\-]*$/m =~ nm
        @name   = nm.downcase
        @desc   = desc
        @verbs  = KXI::Collections::ArrayCollection.new
        @args   = KXI::Collections::ArrayCollection.new
        @action = nil
        @ctx    = ctx
        @help   = false
        yield(self) if block_given?
end

Public Instance Methods

act(args = nil) click to toggle source

Parses and executes action of verb @param args [Array<String>] Given arguments

# File lib/kxi/cli/verb.rb, line 132
def act(args = nil)
        args = ARGV if args == nil
        hf   = (args.include?('-h') or args.include?('--help') or args.include?('-?'))
        if @verbs.count > 0
                v = args.shift
                if @help and (v == 'help' or hf)
                        if v == 'help' or v == nil
                                help
                        else
                                verb = @verbs.first { |i| i.name == v.downcase }
                                if verb == nil
                                        help
                                else
                                        verb.act(args)
                                end
                        end
                else
                        raise(KXI::Exceptions::VerbExpectedException.new(@verbs.select { |i| i.name }.to_array)) if v == nil
                        verb = @verbs.first { |i| i.name == v.downcase }
                        raise(KXI::Exceptions::VerbExpectedException.new(@verbs.select { |i| i.name }.to_array)) if verb == nil
                        verb.act(args)
                end
        else
                if @help and hf
                        help
                else
                        vals = KXI::CLI::ArgumentValues.new(@args.to_array)
                        anon = @args.of_type(KXI::CLI::AnonymousArgument).order_by_descending { |a, b| a.order <=> b.order }
                        
                        ar = nil
                        args.each do |val|
                                if val.start_with?('-')
                                        raise(KXI::Exceptions::ArgumentException.new(ar.name, 'Expected value!')) if ar != nil
                                        raise(KXI::Exceptions::ArgumentException.new(val, 'Invalid syntax!')) if val.start_with?('---')
                                        if val.start_with?('--')
                                                raise(KXI::Exceptions::ArgumentException.new(val, 'Expected argument name!')) if val.length == 2
                                                nm  = val[2..val.length - 1].downcase
                                                arg = @args.first { |i| i.name == nm }
                                                raise(KXI::Exceptions::ArgumentException.new(nm, 'No such argument exists!')) if arg == nil
                                                if arg.is_a?(KXI::CLI::FlagArgument)
                                                        vals.set(arg, true)
                                                elsif arg.is_a?(KXI::CLI::NamedArgument)
                                                        ar = arg
                                                else
                                                        raise(KXI::Exceptions::ArgumentException.new(nm, 'Argument cannot be assigned explicitly!'))
                                                end
                                        else
                                                raise(KXI::Exceptions::ArgumentException.new(val, 'Expected short argument name!')) if val.length == 1
                                                nm  = val[1]
                                                arg = @args.of_type(KXI::CLI::ExplicitArgument).first { |i| i.shortcut == nm }
                                                raise(KXI::Exceptions::ArgumentException.new(nm, 'No such argument exists!')) if arg == nil
                                                if arg.is_a?(KXI::CLI::FlagArgument)
                                                        vals.set(arg, true)
                                                elsif arg.is_a?(KXI::CLI::NamedArgument)
                                                        if val.length == 2
                                                                ar = arg
                                                        else
                                                                vals.set(arg, val[2..val.length - 1])
                                                        end
                                                end
                                        end
                                else
                                        if ar != nil
                                                vals.set(ar, val)
                                                ar = nil
                                        else
                                                an = anon.first
                                                raise(KXI::Exceptions::NoArgumentException.new(val)) if an == nil
                                                vals.set(an, val)
                                                anon.remove_at(0) unless an.variadic?
                                        end
                                end
                        end
                        vals.finish
                        if @action == nil
                                raise(KXI::Exceptions::NotImplementedException.new)
                        else
                                @action.call(vals)
                        end
                end
        end
end
action(&block) click to toggle source

Assigns action to this verb @yield [args] Action of verb @yieldparam args [KXI::CLI::ArgumentValues] Parsed values of arguments

# File lib/kxi/cli/verb.rb, line 22
def action(&block)
        @action = block
end
add_argument(arg) click to toggle source

Adds argument @param arg [KXI::CLI::Argument] Argument to add

# File lib/kxi/cli/verb.rb, line 249
def add_argument(arg)
        check_name(arg.name)
        if arg.is_a?(KXI::CLI::ExplicitArgument) and arg.shortcut != nil
                raise(Exception.new("Short name '#{arg.shortcut}' is already in use!")) if @args.of_type(KXI::CLI::ExplicitArgument).any { |i| i.shortcut == arg.shortcut }
        end
        if arg.is_a?(KXI::CLI::AnonymousArgument) and arg.variadic?
                raise(Exception.new("Verb can have only one variadic anonymous argument! (argument '#{arg.name}')")) if @args.of_type(KXI::CLI::AnonymousArgument).any { |i| i.variadic? }
                raise(Exception.new("Verb cannot contain both optional and variadic anonymous arguments! (argument '#{arg.name}')")) if @args.of_type(KXI::CLI::AnonymousArgument).any { |i| not i.required? }
        end
        @args.add(arg)
        @verbs.foreach { |i| i.add_argument(arg) }
        return arg
end
add_verb(v) click to toggle source

Adds child verb @param v [KXI::CLI::Verb] Verb to add

# File lib/kxi/cli/verb.rb, line 265
def add_verb(v)
        @args.foreach { |a| v.add_argument(a) }
        @verbs.add(v)
        v.enable_help if @help
        return v
end
anonymous(name, desc, df = nil, var = false, &validator) click to toggle source

Creates new optional anonymous argument @param name [String] Name of argument @param desc [String] Description of argument @param df [Object, nil] Default value of argument @param var [Bool] Determines whether argument is variadic @yield [val] Validator function for value of argument @yieldparam val [String, Array<String>] Value of argument @return [KXI::CLI::AnonymousArgument] Anonymous argument

# File lib/kxi/cli/verb.rb, line 76
def anonymous(name, desc, df = nil, var = false, &validator)
        add_argument(KXI::CLI::AnonymousArgument.new(name, desc, false, df, var, &validator))
end
anonymous!(name, desc, var = false, &validator) click to toggle source

Creates new mandatory anonymous argument @param name [String] Name of argument @param desc [String] Description of argument @param var [Bool] Determines whether argument is variadic @yield [val] Validator function for value of argument @yieldparam val [String, Array<String>] Value of argument @return [KXI::CLI::AnonymousArgument] Anonymous argument

# File lib/kxi/cli/verb.rb, line 88
def anonymous!(name, desc, var = false, &validator)
        add_argument(KXI::CLI::AnonymousArgument.new(name, desc, true, nil, var, &validator))
end
arguments() click to toggle source

Gets the arguments assigned to this verb @return [KXI::Collections::ProtectedCollection] Arguments of verb

# File lib/kxi/cli/verb.rb, line 28
def arguments
        KXI::Collections::ProtectedCollection.new(@args)
end
description() click to toggle source

Gets the description of verb @return [String] Description of verb

# File lib/kxi/cli/verb.rb, line 15
def description
        @desc
end
enable_help() click to toggle source

Enables help for this verb and it's children

# File lib/kxi/cli/verb.rb, line 33
def enable_help
        unless @help
                @help = true
                @verbs.foreach { |i| i.enable_help }
        end
end
flag(name, desc, sh = nil) click to toggle source

Creates new flag argument @param name [String] Name of flag @param desc [String] Description of flag @param sh [String, nil] Shortcut symbol @return [KXI::CLI::FlagArgument] Flag argument

# File lib/kxi/cli/verb.rb, line 126
def flag(name, desc, sh = nil)
        add_argument(KXI::CLI::FlagArgument.new(name, desc, sh))
end
help() click to toggle source

Prints help message of verb

# File lib/kxi/cli/verb.rb, line 216
def help
        puts(@name)
        puts("\t#{@desc}")
        puts
        puts('Usage:')
        if @verbs.count == 0
                print("\t")
                print("#{@ctx} ") if @ctx != nil
                print(@name)
                args = @args.order_by_descending { |a, b| a.order <=> b.order }
                args.where { |i| i.required? or i.is_a?(KXI::CLI::AnonymousArgument) }.foreach do |i|
                        print(" #{i.syntax}")
                end
                puts
                if args.count > 0
                        puts
                        max = args.max { |a, b| a.headline.length <=> b.headline.length }.headline.length
                        args.foreach do |a|
                                puts("\t#{a.headline.ljust(max)}   #{a.description}")
                        end
                end
        else
                max = @verbs.max { |a, b| a.name.length <=> b.name.length }.name.length
                @verbs.foreach do |v|
                        print("\t")
                        print("#{@ctx} ") if @ctx != nil
                        puts("#{@name} #{v.name.ljust(max)}   #{v.description}")
                end
        end
end
name() click to toggle source

Gets the name of verb @return [String] Name of verb

# File lib/kxi/cli/verb.rb, line 9
def name
        @name
end
named(name, val, desc, sh = nil, df = nil, var = false, &validator) click to toggle source

Creates new optional named argument @param name [String] Name of argument @param val [String] Name of value @param desc [String] Description of argument @param sh [String, nil] Shortcut symbol @param df [Object, nil] Default value of argument @param var [Bool] Determines whether argument is variadic @yield [val] Validator function for value of argument @yieldparam val [String, Array<String>] Value of argument @return [KXI::CLI::NamedArgument] Named argument

# File lib/kxi/cli/verb.rb, line 102
def named(name, val, desc, sh = nil, df = nil, var = false, &validator)
        add_argument(KXI::CLI::NamedArgument.new(name, val, desc, sh, false, df, var, &validator))
end
named!(name, val, desc, sh = nil, var = false, &validator) click to toggle source

Creates new mandatory named argument @param name [String] Name of argument @param val [String] Name of value @param desc [String] Description of argument @param sh [String, nil] Shortcut symbol @param var [Bool] Determines whether argument is variadic @yield [val] Validator function for value of argument @yieldparam val [String, Array<String>] Value of argument @return [KXI::CLI::NamedArgument] Named argument

# File lib/kxi/cli/verb.rb, line 116
def named!(name, val, desc, sh = nil, var = false, &validator)
        add_argument(KXI::CLI::NamedArgument.new(name, val, desc, sh, true, nil, var, &validator))
end
verb(name, desc) { |v| ... } click to toggle source

Creates a new child verb @param name [String] Name of verb @param desc [String] Description of verb @return [KXI::CLI::Verb] Child verb

# File lib/kxi/cli/verb.rb, line 63
def verb(name, desc)
        check_name(name)
        add_verb(Verb.new(name, desc, @ctx == nil ? @name : "#{@ctx} #{@name}") { |v| yield(v) if block_given? })
end

Private Instance Methods

check_name(nm) click to toggle source

Checks an argument name @param [string] nm Name to check

# File lib/kxi/cli/verb.rb, line 274
def check_name(nm)
        raise(Exception.new('Name must contain at least two characters!')) if nm == nil or nm.length < 2
        nm = nm.downcase
        raise(Exception.new("Name '#{nm}' is already in use!")) unless @verbs.all { |i| i.name != nm } && @args.all { |i| i.name != nm }
end