class KXI::CLI::Verb
Represents a verb of console interface
Public Class Methods
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
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
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
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
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
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
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
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
Gets the description of verb @return [String] Description of verb
# File lib/kxi/cli/verb.rb, line 15 def description @desc end
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
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
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
Gets the name of verb @return [String] Name of verb
# File lib/kxi/cli/verb.rb, line 9 def name @name end
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
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
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
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