<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -10,4 +10,13 @@
 
 == 0.4.3 2009-07-07
 
-* Fixed a serious Bug where default values could not be overriden by passing arguments without keyword
\ No newline at end of file
+* Fixed a serious bug where default values could not be overriden by passing arguments without keyword
+
+== 0.6 2009-08-06
+
+* Fixed a bug where converting a block to proc argument using ampersand would blow method call
+* Passing a keyword not corresponding to an argument name raises an error
+* Using RubyParser in Ruby 1.9.1 instead of Regexp to extract argument names and default values
+* Method definition that uses splat operator is now ignored
+* Last Hash argument is not used for assigning argument values if total number of arguments has been passed
+* named_arguments_for can be called passing a Class method name eg: named_args_for :instance_method, 'self.class_method'</diff>
      <filename>History.txt</filename>
    </modified>
    <modified>
      <diff>@@ -10,20 +10,24 @@ Arguments has been tested with Ruby 1.8.6 and ruby 1.9.1 and eventually will wor
 == SYNOPSIS:
 
     require 'arguments'
-
+    
     class Example
       def meth(a = :a, b = :b, c = :c)
         [a,b,c]
       end
-
-      named_args_for :meth
-
+       
       class &lt;&lt; self
         def class_method(a = :a, b = :b, c = :c)
           [a,b,c]
         end
+        
+        def other_class_method(a = :a, b = :b, c = :c)
+          [a,b,c]
+        end        
         named_args_for :class_method
       end
+      
+      named_args_for :meth, :'self.other_class_method'
     end
     
     nu = Example.new
@@ -32,40 +36,58 @@ Arguments has been tested with Ruby 1.8.6 and ruby 1.9.1 and eventually will wor
     nu.meth(:b =&gt; nil, :a =&gt; 'something') #=&gt; ['something', nil, :c]
     
     Example.class_method(:b =&gt; nil, :a =&gt; 'something') #=&gt; ['something', nil, :c]
+    Example.other_class_method(:b =&gt; nil, :a =&gt; 'something') #=&gt; ['something', nil, :c]
+    
     
 
 
 * #named_arguments_for is aliased as #named_args_for and #named_args
 * Calling #named_args_for without arguments patches all previously declared methods in scope
+* Last Hash argument is used to assign argument values unless passing all accepted arguments:
+
+  nu.meth(1, :c =&gt; 'string') #=&gt; [1, :b, 'string']
+  nu.meth(1, 2, :a =&gt; 'string')  #=&gt; [1, 2, {:a =&gt; 'string'}]
+
 * Any number of method names (Symbol or String) corresponding to existing methods can be passed
 * Methods with no optionals won't be patched (will behave as usual with no named params)
 * Same for methods with splatted arguments and for native methods (not declared in Ruby)
 * Keyword argument take precedence over argument order:
       
       nu.meth(10, :a =&gt; -10) #=&gt; [-10, :b, :c]
+      
+* pasing a key not corresponding to an argument name will raise ArgumentError:
 
+      nu.meth(10, :four =&gt; -10) #=&gt; ArgumentError: `four` is not an argument name.
 
 == LIMITATIONS
 
 * Performance penalty occurs only in 1.8.6 due to ParseTree use and only while calling Class#named_args\_for, penalty while calling the actuall method is neglectable.
 * With Ruby 1.8.6 it can patch methods declared with eval, with 1.9.1 only methods declared in a source file.
-* If last argument is a Hash is taken as an options Hash and not assigned to the argument varible, if you want to pass a has as a last argument use keywords.
-
-== TODO
-
-Don't use last argument (Hash) as options if passed total number of args.
 
 == REQUIREMENTS:
 
-Ruby 1.8.6:
+- Ruby2Ruby 1.1.9
 
+Ruby 1.8.6:
 - ParseTree &gt;= 3.0.3
-- Ruby2Ruby 1.1.9
+
+Ruby 1.9.1
+- RubyParser &gt;= 2.0.2
 
 == INSTALL:
 
     sudo gem install maca-arguments &#8211;source http://gems.github.com
 
+== LATEST CHANGES (0.6)
+
+* Fixed a bug where converting a block to proc argument using ampersand would blow method call
+* Passing a keyword not corresponding to an argument name raises an error
+* Using RubyParser in Ruby 1.9.1 instead of Regexp to extract argument names and default values
+* Method definition that uses splat operator is now ignored
+* Last Hash argument is not used for assigning argument values if total number of arguments has been passed
+* named_arguments_for can be called passing a Class method name eg: named_args_for :instance_method, 'self.class_method'
+
+
 == LICENSE:
 
 (The MIT License)</diff>
      <filename>README.rdoc</filename>
    </modified>
    <modified>
      <diff>@@ -2,7 +2,7 @@
 
 Gem::Specification.new do |s|
   s.name = %q{arguments}
-  s.version = &quot;0.5.1&quot;
+  s.version = &quot;0.6&quot;
 
   s.required_rubygems_version = Gem::Requirement.new(&quot;&gt;= 0&quot;) if s.respond_to? :required_rubygems_version=
   s.authors = [&quot;Macario Ortega&quot;]</diff>
      <filename>arguments.gemspec</filename>
    </modified>
    <modified>
      <diff>@@ -7,7 +7,7 @@ require 'arguments/class'
 RUBY_VERSION.to_f &gt;= 1.9 ? require( 'arguments/vm' ) : require( 'arguments/mri' )
 
 module Arguments
-  VERSION = '0.5.1'
+  VERSION = '0.6'
   
   def self.names klass, method
     args = ast_for_method(klass, method).assoc(:args)</diff>
      <filename>lib/arguments.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,19 +1,21 @@
 class Class
   def named_arguments_for *methods
     methods = instance_methods - Object.methods if methods.empty?
-    
+        
     methods.each do |meth|
-      next if self.instance_method(meth).arity == 0 # unless option for patching methods with no opts...
-      names   = Arguments.names self, meth
+      meth    = meth.to_s
+      klass   = meth.sub!(/^self./, '') ? (class &lt;&lt; self; self; end) : self
+      names   = Arguments.names klass, meth
       next if names.empty? or names.inject(false) { |bol, pair| bol || /^\*/ === pair.first.to_s }
-
       assigns = []
+      names.pop if /^&amp;/ === names[-1][0].to_s
+      
       names.each_with_index do |name, index|
         unless name.size == 1
           assigns &lt;&lt; &lt;&lt;-RUBY_EVAL
             #{ name.first } =
-            if opts.key?(:#{ name.first })
-              opts[:#{ name.first }]
+            if opts.key? :#{ name.first }
+              opts.delete :#{ name.first }
             else
               args.size &gt;= #{ index + 1 } ? args[#{ index }] : #{ name.last }
             end
@@ -21,7 +23,7 @@ class Class
         else
           assigns &lt;&lt; &lt;&lt;-RUBY_EVAL 
             begin
-              #{ name.first } = opts.key?(:#{ name.first }) ? opts[:#{ name.first }] : args.fetch(#{ index })
+              #{ name.first } = opts.key?(:#{ name.first }) ? opts.delete(:#{ name.first }) : args.fetch(#{ index })
             rescue 
               raise ArgumentError.new('passing `#{ name.first }` is required')
             end
@@ -29,10 +31,13 @@ class Class
         end
       end
 
-      self.module_eval &lt;&lt;-RUBY_EVAL, __FILE__, __LINE__
+      klass.module_eval &lt;&lt;-RUBY_EVAL, __FILE__, __LINE__
         def __#{ meth }_with_keyword_arguments *args, &amp;block
-          opts = args.last.kind_of?( Hash ) ? args.pop : {}
+          opts = args.last.kind_of?( Hash ) &amp;&amp; args.size &lt; #{ names.size } ? args.pop : {}
           #{ assigns.join(&quot;\n&quot;) }
+          unless opts.empty?
+            raise ArgumentError.new(&quot;`\#{ opts.keys.join(', ') }` \#{ opts.size == 1 ? 'is not a recognized argument keyword' : 'are not recognized argument keywords' }&quot;) 
+          end
           __original_#{ meth } #{ names.collect{ |n| n.first }.join(', ') }, &amp;block
         end
         </diff>
      <filename>lib/arguments/class.rb</filename>
    </modified>
    <modified>
      <diff>@@ -15,6 +15,7 @@ module Arguments
   def self.ast_for_method klass, method
     source, line = klass.instance_method(method).source_location
     str = IO.readlines( source )[ (line-1)..-1 ].join
-    PermissiveRubyParser.new.parse( str ).assoc( :defn )
+    ast = PermissiveRubyParser.new.parse( str )
+    ast.assoc( :defn ) or ast
   end
 end
\ No newline at end of file</diff>
      <filename>lib/arguments/vm.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,20 +1,15 @@
 require &quot;#{ dir = File.dirname __FILE__ }/../lib/arguments&quot;
 require 'benchmark'
 
-# TODO: Refactor specs for clarity
+# TODO: Refactor specs for clarity and better coverage
 describe Arguments do
 
   before do
     Object.send(:remove_const, 'Klass') rescue nil
     load &quot;#{ dir }/klass.rb&quot;
-    # load &quot;#{ dir }/module.rb&quot;
     @instance = Klass.new
   end
-  
-  it &quot;should respond to named_arguments&quot; do
-    Klass.send( :named_arguments_for, :three )
-  end
-  
+
   it &quot;should not respond to named_arguments&quot; do
     lambda { Klass.new.send( :named_arguments_for ) }.should raise_error( NoMethodError )
   end
@@ -30,7 +25,13 @@ describe Arguments do
   
   it &quot;should raise ArgumentError if not passing required params&quot; do
     Klass.send( :named_arguments_for, :two )
-    lambda { @instance.two( :three =&gt; 3 ) }.should raise_error(ArgumentError)
+    error =
+    begin 
+      @instance.two( :three =&gt; 3 )
+    rescue ArgumentError =&gt; e
+      e
+    end
+    error.to_s.should == &quot;passing `one` is required&quot;
   end
   
   it &quot;should override passed value with hash&quot; do
@@ -48,61 +49,84 @@ describe Arguments do
     @instance.with_block( 1, :three =&gt; nil, :two =&gt; 'something' ){ :block }.should == [1, 'something', nil, :block]
   end
   
+  it &quot;should patch methods that accept proc as argument&quot; do
+    Klass.send( :named_arguments_for, :with_block2 )
+    @instance.with_block2(1, :three =&gt; nil, :two =&gt; 'something'){ :block }.should == [1, 'something', nil, :block]
+  end
+  
   it &quot;should override defaults on standard passing&quot; do
     Klass.send( :named_arguments_for, :asr )
-    @instance.asr(0, 1, 2, :curve =&gt; 3).should == [0, 1, 2, 3]
+    @instance.asr(0, 1, :curve =&gt; 3).should == [0, 1, 1, 3]
   end
 
   it &quot;should work with class methods&quot; do
-    Klass.asr(0, 1, 2, :curve =&gt; 3).should == [0, 1, 2, 3]
-  end
-  
-  # it &quot;should work with class methods&quot; do
-  #    Klass.send( :named_arguments_for, &quot;self.class_method&quot;)
-  #    Klass.class_method(:a =&gt; 1).should == 1
-  #  end
-  # 
-  #  it &quot;should work with class methods called like :self.method_name&quot; do
-  #    Klass.send( :named_arguments_for, :&quot;self.class_method2&quot;)
-  #    Klass.class_method2(:a =&gt; 1).should == 1
-  #  end
-  # 
-  #  it &quot;should work with class methods passed in by string instead of symboL&quot; do
-  #    Klass.send( :named_arguments_for, &quot;self.class_method3&quot;)
-  #    Klass.class_method3(:a =&gt; 1).should == 1
-  #  end
-
-  # it &quot;should not patch methods that accept no args&quot; do
-  #   # Arguments.should_not_receive(:names)
-  #   Klass.send( :named_arguments_for, :no_args )
-  #   lambda { @instance.no_args(1) }.should raise_error(ArgumentError)
-  #   @instance.no_args.should be_nil
-  # end
+    (class &lt;&lt; Klass; self; end).send( :named_arguments_for, :k_method )
+    Klass.k_method(:d =&gt; :d).should == [1, 2, 3, :d]
+  end
+  
+  it &quot;should override defaults on standard passing&quot; do
+    Klass.send( :named_arguments_for, 'self.k_method' )
+    Klass.k_method(:d =&gt; :d).should == [1, 2, 3, :d]
+  end
+  
+  it &quot;should not use options if all arguments are passed&quot; do
+    Klass.send( :named_arguments_for, :two )
+    @instance.two( 1, 2, :three =&gt; nil ).should == [1, 2, {:three =&gt; nil}]
+  end
+  
+  it &quot;should raise ArgumentError if passing a not recoginized keyword&quot; do
+    Klass.send( :named_arguments_for, :two )
+    error =
+    begin 
+      @instance.two( 1, :four =&gt; nil )
+    rescue ArgumentError =&gt; e
+      e
+    end
+    error.to_s.should == &quot;`four` is not a recognized argument keyword&quot;
+  end
+  
+  it &quot;should raise ArgumentError if passing recoginized keywords&quot; do
+    Klass.send( :named_arguments_for, :two )
+    error =
+    begin 
+      @instance.two( 1, :four =&gt; nil, :five =&gt; nil  )
+    rescue ArgumentError =&gt; e
+      e
+    end
+    error.to_s.should == &quot;`four, five` are not recognized argument keywords&quot;
+  end
+  
+  it &quot;should not patch methods that accept no args&quot; do
+    Klass.send( :named_arguments_for, :no_args )
+    lambda { @instance.no_args(1) }.should raise_error(ArgumentError)
+    @instance.no_args.should be_nil
+  end
   
   it &quot;should not patch methods that use splatter op&quot; do
     Klass.send( :named_arguments_for, :splatted )
     @instance.splatted(1, :args =&gt; 1).should == [1, {:args =&gt; 1}]
   
     Klass.send( :named_arguments_for, :splatted2 )
-    @instance.splatted2(:a =&gt; 1, :&quot;*args&quot; =&gt; 3).should == []
+    @instance.splatted2(:a =&gt; 1, :&quot;*rest&quot; =&gt; 3).should == [{:a =&gt; 1, :'*rest' =&gt; 3}, []]
   
     Klass.send( :named_arguments_for, :splatted3 )
-    @instance.splatted3(:a =&gt; 1, :&quot;*args&quot; =&gt; 3).should == []
-    @instance.splatted3(1, :b =&gt; 2, :args =&gt; 1).should == [{:b =&gt; 2, :args =&gt; 1}]
+    @instance.splatted3(:a =&gt; 1, :&quot;*args&quot; =&gt; 3).should == [{:a =&gt; 1, :&quot;*args&quot; =&gt; 3}, []]
+    @instance.splatted3(1, :b =&gt; 2, :args =&gt; 1).should == [1, [{:b =&gt; 2, :args =&gt; 1}]]
   
     Klass.send( :named_arguments_for, :splatted4 )
-    @instance.splatted4(1, :b =&gt; 2, :args =&gt; 1).should == []
+    @instance.splatted4(1, :b =&gt; 2, :args =&gt; 1).should == [1, {:b =&gt; 2, :args =&gt; 1}, []]
   end
   
   it &quot;should not patch methods with no optionals&quot; do
     Klass.send( :named_arguments_for, :no_opts )
-    @instance.no_opts(1, 2, :c =&gt; 1).should == {:c =&gt; 1}
+    @instance.method(:no_opts).arity.should == 3
+  end
+  
+  it &quot;should patch all methods&quot; do
+    Klass.send( :named_args )
+    @instance.two(1, :three =&gt; 3).should == [1, 2, 3]
   end
   
-  # it &quot;should patch all methods&quot; do
-  #   Klass.send( :named_args )
-  # end
-  # 
   it &quot;should benchmark without hack&quot; do
     puts Benchmark.measure {
       1_000.times do</diff>
      <filename>spec/arguments_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -10,6 +10,10 @@ class Klass
   def with_block one, two = 2, three = 3
     [one, two, three, yield]
   end
+  
+  def with_block2 one, two = 2, three = 3, &amp;action
+    [one, two, three, action.call]
+  end
 
   def asr attackTime = 3, sustainLevel = 2, releaseTime = 1, curve = 0
     [attackTime, sustainLevel, releaseTime, curve]
@@ -23,26 +27,29 @@ class Klass
   end
 
   def splatted2 a=1, *rest
-    rest
+    [a, rest]
   end
 
   def splatted3 a, *rest
-    rest
+    [a, rest]
   end
   
   def splatted4 a, b=1, *rest
-    rest
+    [a, b, rest]
   end
 
   def no_opts a, b, c
-    c
+    [a, b, c]
   end
   
   class &lt;&lt; self
     def asr attackTime = 3, sustainLevel = 2, releaseTime = 1, curve = 0
       [attackTime, sustainLevel, releaseTime, curve]
     end
-    named_arguments_for :asr
+    
+    def k_method a = 1, b = 2, c = 3, d = 4
+      [a, b, c, d]
+    end
   end
   
   def == other</diff>
      <filename>spec/klass.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>f1fff97688c7fca6280ef211e8424ba88347b1cb</id>
    </parent>
  </parents>
  <author>
    <name>Macario</name>
    <email>macarui@gmail.com</email>
  </author>
  <url>http://github.com/maca/arguments/commit/a3a514b05e1d23ebb3f5ceec88dfd714499ba933</url>
  <id>a3a514b05e1d23ebb3f5ceec88dfd714499ba933</id>
  <committed-date>2009-08-06T21:14:58-07:00</committed-date>
  <authored-date>2009-08-06T21:14:58-07:00</authored-date>
  <message>fixed to_proc (&amp;proc) and splat (*rest) bugs, will raise error if passing unknown keys, last hash is not used for assing if total args passed, version bump</message>
  <tree>a8c7ce3f9117d11dc508ddc728da2ca78281f67b</tree>
  <committer>
    <name>Macario</name>
    <email>macarui@gmail.com</email>
  </committer>
</commit>
