mirror of
https://github.com/awesome-print/awesome_print
synced 2023-03-27 23:22:34 -04:00
Finally figured it out: properly intercept Array#grep
This commit is contained in:
parent
777d16d91b
commit
d401b1471d
2 changed files with 66 additions and 14 deletions
|
@ -3,18 +3,18 @@
|
|||
# Awesome Print is freely distributable under the terms of MIT license.
|
||||
# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
|
||||
#------------------------------------------------------------------------------
|
||||
#
|
||||
# The following makes it possible to invoke awesome_print while performing
|
||||
# operations on method arrays, ex:
|
||||
#
|
||||
# ap [].methods - Object.methods
|
||||
# ap ''.methods.grep(/!|\?/)
|
||||
#
|
||||
# If you could think of a better way please let me know: twitter.com/mid :-)
|
||||
#
|
||||
class Array
|
||||
#
|
||||
# The following makes it possible to invoke awesome_print while performing
|
||||
# operations on method arrays, ex:
|
||||
#
|
||||
# ap [].methods - Object.methods
|
||||
# ap ''.methods.grep(/!|\?/)
|
||||
#
|
||||
# If you could think of a better way please let me know: twitter.com/mid :-)
|
||||
#
|
||||
[ :-, :& ].each do |operator|
|
||||
alias_method :"original_#{operator.object_id}", operator
|
||||
alias :"original_#{operator.object_id}" :"#{operator}"
|
||||
define_method operator do |*args|
|
||||
arr = self.send(:"original_#{operator.object_id}", *args)
|
||||
if self.instance_variable_defined?('@__awesome_methods__')
|
||||
|
@ -24,10 +24,40 @@ class Array
|
|||
arr
|
||||
end
|
||||
end
|
||||
|
||||
alias_method :original_grep, :grep
|
||||
define_method :grep do |*args, &blk|
|
||||
arr = original_grep(*args, &blk)
|
||||
#
|
||||
# Intercepting Array#grep needs a special treatment since grep accepts
|
||||
# an optional block.
|
||||
#
|
||||
alias :original_grep :grep
|
||||
def grep(pattern, &blk)
|
||||
#
|
||||
# The following looks rather insane and I've sent numerous hours trying
|
||||
# to figure it out. The problem is that if grep gets called with the
|
||||
# block, for example:
|
||||
#
|
||||
# [].methods.grep(/(.+?)_by/) { $1.to_sym }
|
||||
#
|
||||
# ...then simple:
|
||||
#
|
||||
# original_grep(pattern, &blk)
|
||||
#
|
||||
# doesn't set $1 within the grep block which causes nil.to_sym failure.
|
||||
# The workaround below has been tested with Ruby 1.8.7/Rails 2.3.8 and
|
||||
# Ruby 1.9.2/Rails 3.0.0. For more info see the following thread dating
|
||||
# back to 1993 when Ruby 1.8.0 was as fresh off the grill as Ruby 1.9.2
|
||||
# is in 2010 :-)
|
||||
#
|
||||
# http://www.justskins.com/forums/bug-when-rerouting-string-52852.html
|
||||
#
|
||||
# BTW, if you figure out a better way of intercepting Array#grep please
|
||||
# let me know: twitter.com/mid -- or just say hi so I know you've read
|
||||
# the comment :-)
|
||||
#
|
||||
arr = unless blk
|
||||
original_grep(pattern)
|
||||
else
|
||||
original_grep(pattern) { |match| eval("%Q/#{match}/ =~ #{pattern.inspect}", blk.binding); yield match }
|
||||
end
|
||||
if self.instance_variable_defined?('@__awesome_methods__')
|
||||
arr.instance_variable_set('@__awesome_methods__', self.instance_variable_get('@__awesome_methods__'))
|
||||
arr.reject! { |item| !(item.is_a?(Symbol) || item.is_a?(String)) } # grep block might return crap.
|
||||
|
|
|
@ -384,4 +384,26 @@ describe "Methods arrays" do
|
|||
out = Hello.methods.grep(/^m\d$/).ai(:plain => true)
|
||||
out.should == "[\n [0] m1() Hello\n [1] m2() Hello\n [2] m3() Hello\n]"
|
||||
end
|
||||
|
||||
it "obj1.methods.grep(pattern, &block) should pass the matching string within the block" do
|
||||
class Hello
|
||||
def self.m_one; end
|
||||
def self.m_two; end
|
||||
end
|
||||
|
||||
out = Hello.methods.grep(/^m_(.+)$/) { $1.to_sym }
|
||||
out.should == [:one, :two]
|
||||
end
|
||||
|
||||
it "obj1.methods.grep(pattern, &block) should be awesome printed" do
|
||||
class Hello
|
||||
def self.m0; end
|
||||
def self.none; end
|
||||
def self.m1; end
|
||||
def self.one; end
|
||||
end
|
||||
|
||||
out = Hello.methods.grep(/^m(\d)$/) { %w(none one)[$1.to_i] }.ai(:plain => true)
|
||||
out.should == "[\n [0] none() Hello\n [1] one() Hello\n]"
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue