diff --git a/lib/rubikon/application/instance_methods.rb b/lib/rubikon/application/instance_methods.rb index 6647532..395d10a 100644 --- a/lib/rubikon/application/instance_methods.rb +++ b/lib/rubikon/application/instance_methods.rb @@ -244,7 +244,7 @@ def help_command app_help = lambda { |info| @__app__.instance_eval { help(info) } } - unless args.first.nil? + unless cmd.nil? if commands.keys.include?(cmd) puts commands[cmd].help else diff --git a/lib/rubikon/has_arguments.rb b/lib/rubikon/has_arguments.rb index 24b69f3..8b2c7cd 100644 --- a/lib/rubikon/has_arguments.rb +++ b/lib/rubikon/has_arguments.rb @@ -19,10 +19,6 @@ module HasArguments include Parameter - # @return [Array] The arguments given to this parameter - attr_reader :args - alias_method :arguments, :args - # Creates a new parameter with arguments with the given name and an # optional code block # @@ -44,9 +40,9 @@ module HasArguments def initialize(app, name, *options, &block) super(app, name, &block) - @arg_names = nil + @arg_names = [] @arg_values = nil - @args = [] + @args = {} @description = options.shift if options.first.is_a? String @@ -80,7 +76,9 @@ def initialize(app, name, *options, &block) end arg.each do |arg_name, opt| @arg_names << arg_name.to_sym - @min_arg_count += 1 unless opt.include? :optional + unless opt.include?(:optional) || opt.include?(:remainder) + @min_arg_count += 1 + end if opt.include? :remainder @max_arg_count = -1 break @@ -108,10 +106,21 @@ def initialize(app, name, *options, &block) # @see #args # @since 0.4.0 def [](arg) - arg = @arg_names.index(arg) if arg.is_a? Symbol @args[arg] end + # Returns the arguments given to this parameter. They are given as a Hash + # when there are named arguments or as an Array when there are no named + # arguments + # + # @return [Array, Hash] The arguments given to this + # parameter + # @since 0.6.0 + def args + @arg_names.empty? ? @args.values : @args + end + alias_method :arguments, :args + protected # Adds an argument to this parameter. Arguments can be accessed inside the @@ -126,10 +135,20 @@ def [](arg) # @see #args # @since 0.3.0 def <<(arg) - if args_full? && @args.size == @max_arg_count - raise ExtraArgumentError.new(@name) + raise ExtraArgumentError.new(@name) unless more_args? + + if @arg_names.size > @args.size + name = @arg_names[@args.size] + if @max_arg_count == -1 && @arg_names.size == @args.size + 1 + @args[name] = [arg] + else + @args[name] = arg + end + elsif !@arg_names.empty? && @max_arg_count == -1 + @args[@arg_names.last] << arg + else + @args[@args.size] = arg end - @args << arg end # Marks this parameter as active when it has been supplied by the user on @@ -178,8 +197,8 @@ def check_args # @user = name # end def method_missing(name, *args, &block) - if args.empty? && !block_given? && !@arg_names.nil? && @arg_names.include?(name) - @args[@arg_names.index(name)] + if args.empty? && !block_given? && !@arg_names.empty? && @arg_names.include?(name) + @args[name] else super end diff --git a/samples/helloworld/hello_world.rb b/samples/helloworld/hello_world.rb index b6eb4a9..374d265 100755 --- a/samples/helloworld/hello_world.rb +++ b/samples/helloworld/hello_world.rb @@ -3,7 +3,7 @@ # This code is free software; you can redistribute it and/or modify it under # the terms of the new BSD License. # -# Copyright (c) 2010, Sebastian Staudt +# Copyright (c) 2010-2011, Sebastian Staudt if ENV['RUBIKON_DEV'] require File.join(File.expand_path(File.dirname(__FILE__)), '..', '..', 'lib', 'rubikon') @@ -17,14 +17,14 @@ class HelloWorld < Rubikon::Application::Base # Greet the whole world per default flag :more, 'Display more information while greeting' - option :names, -1, 'One or more names to greet' option :name, 'A single name to greet', :who + option :names, 'One or more names to greet', :people => :remainder default 'Simple hello world' do debug 'Starting to greet the world...' if given? :name - greet parameters[:name].who + greet who elsif given? :names - names.args.each do |name| + names.people.each do |name| greet name end else diff --git a/test/test_has_arguments.rb b/test/test_has_arguments.rb index d28338a..2b71b90 100644 --- a/test/test_has_arguments.rb +++ b/test/test_has_arguments.rb @@ -24,13 +24,13 @@ class TestHasArguments < Test::Unit::TestCase should 'allow a Numeric as argument count' do has_arg = HasArg.new 1 assert_equal 1..1, has_arg.arg_count - assert_nil has_arg.arg_names + assert_equal [], has_arg.arg_names end should 'allow a Range as argument count' do has_arg = HasArg.new 1..3 assert_equal 1..3, has_arg.arg_count - assert_nil has_arg.arg_names + assert_equal [], has_arg.arg_names end should 'allow a Symbol Array as argument names' do @@ -89,6 +89,30 @@ class TestHasArguments < Test::Unit::TestCase end end + should 'provide optional named arguments' do + has_arg = HasArg.new :required, :optional => :optional + has_arg << 'argument' + assert has_arg.args_full? + assert has_arg.more_args? + has_arg << 'argument' + assert !has_arg.more_args? + assert_equal 'argument', has_arg.required + assert_equal 'argument', has_arg.optional + end + + should 'provide named arguments taking all remainding arguments' do + has_arg = HasArg.new :required, :remainder => :remainder + has_arg << 'argument' + assert has_arg.args_full? + assert has_arg.more_args? + has_arg << 'argument' + assert has_arg.more_args? + has_arg << 'argument' + assert has_arg.more_args? + assert_equal 'argument', has_arg.required + assert_equal %w{argument argument}, has_arg.remainder + end + should 'call its code block if it is activated' do block_run = false has_arg = HasArg.new nil do