method_lister 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.markdown +208 -0
- data/lib/method_lister/color_display.rb +77 -0
- data/lib/method_lister/find_result.rb +50 -0
- data/lib/method_lister/finder.rb +113 -0
- data/lib/method_lister/ruby_ext.rb +24 -0
- data/lib/method_lister/simple_display.rb +55 -0
- data/lib/method_lister.rb +7 -0
- data/spec/color_display_spec.rb +37 -0
- data/spec/find_result_spec.rb +161 -0
- data/spec/finder_spec.rb +146 -0
- data/spec/helpers/matchers/list_methods.rb +42 -0
- data/spec/helpers/object_mother/find_result.rb +3 -0
- data/spec/helpers/object_mother/find_scenario.rb +45 -0
- data/spec/rcov.opts +6 -0
- data/spec/ruby_ext_spec.rb +55 -0
- data/spec/scenarios/class_with_inheritance.rb +17 -0
- data/spec/scenarios/class_with_inheritance_and_modules.rb +25 -0
- data/spec/scenarios/eigenclass.rb +18 -0
- data/spec/scenarios/eigenclass_with_modules.rb +26 -0
- data/spec/scenarios/filters_results_without_methods.rb +20 -0
- data/spec/scenarios/mixed_visibility_methods.rb +39 -0
- data/spec/scenarios/object_without_eigenclass.rb +4 -0
- data/spec/scenarios/overloaded_methods.rb +35 -0
- data/spec/scenarios/overloaded_methods_with_modules_mixed_in.rb +26 -0
- data/spec/scenarios/private_methods.rb +14 -0
- data/spec/scenarios/single_class.rb +11 -0
- data/spec/scenarios/single_class_with_module_mixed_in.rb +19 -0
- data/spec/simple_display_spec.rb +38 -0
- data/spec/spec.opts +7 -0
- data/spec/spec_helper.rb +14 -0
- metadata +100 -0
data/README.markdown
ADDED
@@ -0,0 +1,208 @@
|
|
1
|
+
About
|
2
|
+
=====
|
3
|
+
|
4
|
+
Method Lister is used to query objects and discover which ancestor implements
|
5
|
+
which methods. It's quite common to have a lot of mixins and several classes
|
6
|
+
in an object's class hierarchy, especially in a Rails application. To help
|
7
|
+
with this Method Lister adds the ability to find out in which classes/modules
|
8
|
+
the methods on an object are implemented.
|
9
|
+
|
10
|
+
Method Lister adds 3 methods to all objects in the system: `ls`, `grep`, and
|
11
|
+
`which`. Since these names are sometimes taken you can also use `mls`,
|
12
|
+
`mgrep`, and `mwhich`.
|
13
|
+
|
14
|
+
Method Lister is intended to be used from IRB or during debugging.
|
15
|
+
|
16
|
+
Install
|
17
|
+
=======
|
18
|
+
|
19
|
+
Get the gem:
|
20
|
+
|
21
|
+
# Add GitHub as a Gem Source (only have to do this once)
|
22
|
+
gem sources -a http://gems.github.com
|
23
|
+
|
24
|
+
# Install the gem
|
25
|
+
sudo gem install matthew-method_lister
|
26
|
+
|
27
|
+
# Otherwise, build the gem and install it
|
28
|
+
rake gem
|
29
|
+
sudo gem install pkg/*.gem
|
30
|
+
|
31
|
+
Open up `~/.irbrc` and add these lines:
|
32
|
+
|
33
|
+
require 'rubygems'
|
34
|
+
require 'method_lister'
|
35
|
+
|
36
|
+
Usage
|
37
|
+
=====
|
38
|
+
|
39
|
+
`ls` or `mls`
|
40
|
+
-------------
|
41
|
+
|
42
|
+
The `ls` command will list all methods an object responds to, organized by the
|
43
|
+
module or class which provides the implementation. For example (results may
|
44
|
+
vary, depending on what you have loaded):
|
45
|
+
|
46
|
+
>> [].ls
|
47
|
+
========== Module Kernel ==========
|
48
|
+
PUBLIC: == === =~ __id__ __send__ class clone display dup eql? equal?
|
49
|
+
extend freeze frozen? gem grep hash id inspect instance_eval instance_of?
|
50
|
+
instance_variable_defined? instance_variable_get instance_variable_set
|
51
|
+
instance_variables is_a? kind_of? ls method methods mgrep mls mwhich nil?
|
52
|
+
object_id pretty_inspect private_methods protected_methods public_methods
|
53
|
+
require respond_to? send singleton_methods taint tainted? to_a to_s type
|
54
|
+
untaint which
|
55
|
+
|
56
|
+
PRIVATE: Array Float Integer String URI ` abort at_exit autoload autoload?
|
57
|
+
binding block_given? callcc caller catch chomp chomp! chop chop! eval exec
|
58
|
+
exit exit! fail fork format gem_original_require getc gets
|
59
|
+
global_variables gsub gsub! initialize_copy iterator? lambda load
|
60
|
+
local_variables loop method_missing open p pp print printf proc putc puts
|
61
|
+
raise rand readline readlines remove_instance_variable scan select
|
62
|
+
set_trace_func singleton_method_added singleton_method_removed
|
63
|
+
singleton_method_undefined sleep split sprintf srand sub sub! syscall
|
64
|
+
system test throw trace_var trap untrace_var warn
|
65
|
+
|
66
|
+
========== Module PP::ObjectMixin ==========
|
67
|
+
PUBLIC: pretty_print pretty_print_cycle pretty_print_inspect
|
68
|
+
pretty_print_instance_variables
|
69
|
+
|
70
|
+
========== Class Object ==========
|
71
|
+
PRIVATE: initialize irb_binding timeout
|
72
|
+
|
73
|
+
========== Module Enumerable ==========
|
74
|
+
PUBLIC: all? any? collect detect each_with_index entries find find_all
|
75
|
+
grep include? inject map max member? min partition reject select sort
|
76
|
+
sort_by to_a zip
|
77
|
+
|
78
|
+
========== Class Array ==========
|
79
|
+
PUBLIC: & * + - << <=> == [] []= assoc at clear collect collect! compact
|
80
|
+
compact! concat delete delete_at delete_if each each_index empty? eql?
|
81
|
+
fetch fill first flatten flatten! frozen? hash include? index indexes
|
82
|
+
indices insert inspect join last length map map! nitems pack pop
|
83
|
+
pretty_print pretty_print_cycle push rassoc reject reject! replace reverse
|
84
|
+
reverse! reverse_each rindex select shift size slice slice! sort sort!
|
85
|
+
to_a to_ary to_s transpose uniq uniq! unshift values_at zip |
|
86
|
+
|
87
|
+
PRIVATE: initialize initialize_copy
|
88
|
+
|
89
|
+
You can show only the public methods by passing in "true":
|
90
|
+
|
91
|
+
>> [].ls true
|
92
|
+
========== Module Kernel ==========
|
93
|
+
PUBLIC: == === =~ __id__ __send__ class clone display dup eql? equal?
|
94
|
+
extend freeze frozen? gem grep hash id inspect instance_eval instance_of?
|
95
|
+
instance_variable_defined? instance_variable_get instance_variable_set
|
96
|
+
instance_variables is_a? kind_of? ls method methods mgrep mls mwhich nil?
|
97
|
+
object_id pretty_inspect private_methods protected_methods public_methods
|
98
|
+
require respond_to? send singleton_methods taint tainted? to_a to_s type
|
99
|
+
untaint which
|
100
|
+
|
101
|
+
========== Module PP::ObjectMixin ==========
|
102
|
+
PUBLIC: pretty_print pretty_print_cycle pretty_print_inspect
|
103
|
+
pretty_print_instance_variables
|
104
|
+
|
105
|
+
========== Module Enumerable ==========
|
106
|
+
PUBLIC: all? any? collect detect each_with_index entries find find_all
|
107
|
+
grep include? inject map max member? min partition reject select sort
|
108
|
+
sort_by to_a zip
|
109
|
+
|
110
|
+
========== Class Array ==========
|
111
|
+
PUBLIC: & * + - << <=> == [] []= assoc at clear collect collect! compact
|
112
|
+
compact! concat delete delete_at delete_if each each_index empty? eql?
|
113
|
+
fetch fill first flatten flatten! frozen? hash include? index indexes
|
114
|
+
indices insert inspect join last length map map! nitems pack pop
|
115
|
+
pretty_print pretty_print_cycle push rassoc reject reject! replace reverse
|
116
|
+
reverse! reverse_each rindex select shift size slice slice! sort sort!
|
117
|
+
to_a to_ary to_s transpose uniq uniq! unshift values_at zip |
|
118
|
+
|
119
|
+
`grep` or `mgrep`
|
120
|
+
-----------------
|
121
|
+
|
122
|
+
The `grep` command takes a regular expression and only returns methods which
|
123
|
+
match the given regex. In this example we'll use `mgrep` since on Array
|
124
|
+
objects `grep` is already taken:
|
125
|
+
|
126
|
+
>> [].mgrep /f/
|
127
|
+
========== Module Kernel ==========
|
128
|
+
PUBLIC: freeze frozen? instance_of? instance_variable_defined? kind_of?
|
129
|
+
|
130
|
+
PRIVATE: fail fork format method_missing printf set_trace_func
|
131
|
+
singleton_method_undefined sprintf
|
132
|
+
|
133
|
+
========== Module Enumerable ==========
|
134
|
+
PUBLIC: find find_all
|
135
|
+
|
136
|
+
========== Class Array ==========
|
137
|
+
PUBLIC: delete_if fetch fill first flatten flatten! frozen? shift unshift
|
138
|
+
|
139
|
+
Similar to `ls` you can pass in an extra argument of "true" to see only the
|
140
|
+
public methods:
|
141
|
+
|
142
|
+
>> [].mgrep /f/, true
|
143
|
+
========== Module Kernel ==========
|
144
|
+
PUBLIC: freeze frozen? instance_of? instance_variable_defined? kind_of?
|
145
|
+
|
146
|
+
========== Module Enumerable ==========
|
147
|
+
PUBLIC: find find_all
|
148
|
+
|
149
|
+
========== Class Array ==========
|
150
|
+
PUBLIC: delete_if fetch fill first flatten flatten! frozen? shift unshift
|
151
|
+
|
152
|
+
Note that `method_missing` is always considered a match, since it could always
|
153
|
+
potentially execute.
|
154
|
+
|
155
|
+
`which` or `mwhich`
|
156
|
+
-------------------
|
157
|
+
|
158
|
+
The `which` command is for finding which classes or modules implement the
|
159
|
+
method you're seeking. You can pass the method name in as a string or symbol.
|
160
|
+
|
161
|
+
>> [].which :to_a
|
162
|
+
========== Module Kernel ==========
|
163
|
+
PUBLIC: to_a
|
164
|
+
|
165
|
+
========== Module Enumerable ==========
|
166
|
+
PUBLIC: to_a
|
167
|
+
|
168
|
+
========== Class Array ==========
|
169
|
+
PUBLIC: to_a
|
170
|
+
|
171
|
+
Logically the `which` command is the same as `grep(/^your_method$/)` and so
|
172
|
+
the same comments apply about `method_missing` and the optional parameter to
|
173
|
+
see only public methods.
|
174
|
+
|
175
|
+
Known Bugs
|
176
|
+
==========
|
177
|
+
|
178
|
+
If a singleton method overrides some method from an ancestor then the method
|
179
|
+
will be reported on the ancestor only and not both the ancestor and the
|
180
|
+
eigenclass. For example:
|
181
|
+
|
182
|
+
>> class Foo; def doit; end; end
|
183
|
+
=> nil
|
184
|
+
|
185
|
+
>> f = Foo.new
|
186
|
+
=> #<Foo:0x3395a0>
|
187
|
+
|
188
|
+
>> class << f; def doit; end; end
|
189
|
+
=> nil
|
190
|
+
|
191
|
+
>> f.mgrep /doit/
|
192
|
+
========== Module Kernel ==========
|
193
|
+
PRIVATE: method_missing
|
194
|
+
|
195
|
+
========== Class Foo ==========
|
196
|
+
PUBLIC: doit
|
197
|
+
|
198
|
+
This was done on purpose to support listing singleton methods on cloned
|
199
|
+
objects. I couldn't support both features since the reflection methods for
|
200
|
+
eigenclasses are buggy.
|
201
|
+
|
202
|
+
License
|
203
|
+
=======
|
204
|
+
|
205
|
+
Copyright 2008, 2009, Matthew O'Connor All rights reserved.
|
206
|
+
|
207
|
+
This program is free software; you can redistribute it and/or modify it under
|
208
|
+
the same terms as Ruby 1.8.7 itself.
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module MethodLister
|
2
|
+
class ColorDisplay < SimpleDisplay
|
3
|
+
def initialize
|
4
|
+
@ansi = AnsiEscape.new
|
5
|
+
end
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def location_description(result)
|
10
|
+
color(super, :yellow_fg, :bold)
|
11
|
+
end
|
12
|
+
|
13
|
+
def color_method_overloaded_from_kernel(source, method)
|
14
|
+
if source != Kernel and Kernel.instance_methods.member? method
|
15
|
+
color(method, :green_fg)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def color_method_missing(source, method)
|
20
|
+
color(method, :red_fg) if method == "method_missing"
|
21
|
+
end
|
22
|
+
|
23
|
+
def color_method_array_primative(source, method)
|
24
|
+
exempt_sources = [Kernel, Fixnum, Hash, String, Enumerable, Array]
|
25
|
+
unless exempt_sources.member? source
|
26
|
+
primatives = %w{[] []= each <<}
|
27
|
+
color(method, :magenta_fg) if primatives.member? method
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def process_method(result, method)
|
32
|
+
color_method(result.object, method)
|
33
|
+
end
|
34
|
+
|
35
|
+
def color_method(source, method)
|
36
|
+
coloring_methods.each do |coloring_method|
|
37
|
+
colored_method = self.send(coloring_method, source, method)
|
38
|
+
return colored_method if colored_method
|
39
|
+
end
|
40
|
+
method
|
41
|
+
end
|
42
|
+
|
43
|
+
def coloring_methods
|
44
|
+
private_methods.select {|method| method =~ /^color_method_/}
|
45
|
+
end
|
46
|
+
|
47
|
+
def color(string, *colors)
|
48
|
+
output_is_to_tty? ? @ansi.color_string(string, *colors) : string
|
49
|
+
end
|
50
|
+
|
51
|
+
def output_is_to_tty?
|
52
|
+
$stdout.tty?
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class AnsiEscape
|
57
|
+
Colors = {
|
58
|
+
:none => 0, :black_fg => 30, :red_fg => 31, :green_fg => 32,
|
59
|
+
:yellow_fg => 33, :blue_fg => 34, :magenta_fg => 35, :cyan_fg => 36,
|
60
|
+
:white_fg => 37, :black_bg => 40, :red_bg => 41, :green_bg => 42,
|
61
|
+
:yellow_bg => 43, :blue_bg => 44, :magenta_bg => 45, :cyan_bg => 46,
|
62
|
+
:white_bg => 47, :bold => 1, :underline => 4, :blink => 5,
|
63
|
+
:reverse => 7, :invisible => 8
|
64
|
+
}
|
65
|
+
|
66
|
+
def color_string(string, *colors)
|
67
|
+
color_code(*colors) + string + color_code(:none)
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def color_code(*colors)
|
73
|
+
ansi_codes = colors.map {|c| Colors[c]}.compact.join(";")
|
74
|
+
"\e[#{ansi_codes}m" unless ansi_codes.empty?
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module MethodLister
|
2
|
+
class FindResult
|
3
|
+
attr_reader :object
|
4
|
+
VISIBILITIES = [:public, :protected, :private]
|
5
|
+
|
6
|
+
def initialize(object, options={})
|
7
|
+
@object = object
|
8
|
+
@methods = Hash.new
|
9
|
+
VISIBILITIES.each do |visibility|
|
10
|
+
@methods[visibility] = options[visibility] || Array.new
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def methods(visibility)
|
15
|
+
if visibility == :all
|
16
|
+
VISIBILITIES.inject(Array.new) { |result, viz| result + methods(viz) }
|
17
|
+
elsif VISIBILITIES.include? visibility
|
18
|
+
@methods[visibility]
|
19
|
+
else
|
20
|
+
raise ArgumentError, "Unknown visibility #{visibility.inspect}"
|
21
|
+
end.sort
|
22
|
+
end
|
23
|
+
|
24
|
+
def has_methods?(visibility=:all)
|
25
|
+
!methods(visibility).empty?
|
26
|
+
end
|
27
|
+
|
28
|
+
def narrow_to_methods_matching!(rx)
|
29
|
+
VISIBILITIES.each do |visibility|
|
30
|
+
@methods[visibility] = @methods[visibility].select do |method|
|
31
|
+
method =~ rx || method == "method_missing"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
def ==(other)
|
38
|
+
object.eql?(other.object) &&
|
39
|
+
methods(:all).sort == other.methods(:all).sort
|
40
|
+
end
|
41
|
+
|
42
|
+
def inspect
|
43
|
+
repr = "object=#{object.inspect}\n"
|
44
|
+
VISIBILITIES.each do |visibility|
|
45
|
+
repr += "#{visibility}=#{methods(visibility).sort.inspect}\n"
|
46
|
+
end
|
47
|
+
repr
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module MethodLister
|
2
|
+
class Finder
|
3
|
+
def find_all(object)
|
4
|
+
@results, @seen = Array.new, Hash.new
|
5
|
+
record_methods_for_eigenclass(object)
|
6
|
+
search_class_hierarchy(object.class)
|
7
|
+
@results
|
8
|
+
end
|
9
|
+
|
10
|
+
def ls(object)
|
11
|
+
find_all(object).select { |results| results.has_methods? }
|
12
|
+
end
|
13
|
+
|
14
|
+
def grep(rx, object)
|
15
|
+
ls(object).map do |result|
|
16
|
+
result.narrow_to_methods_matching!(rx)
|
17
|
+
end.select { |result| result.has_methods? }
|
18
|
+
end
|
19
|
+
|
20
|
+
def which(method, object)
|
21
|
+
grep(/^#{Regexp.escape(method.to_s)}$/, object)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def search_class_hierarchy(klass)
|
27
|
+
while klass
|
28
|
+
scan :class, klass
|
29
|
+
klass = klass.superclass
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def scan(type, klass_or_module)
|
34
|
+
unless @seen.has_key? klass_or_module
|
35
|
+
@seen[klass_or_module] = true
|
36
|
+
record_methods_for klass_or_module
|
37
|
+
scan_modules(type, klass_or_module)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def scan_modules(type, klass_or_module)
|
42
|
+
modules_for(type, klass_or_module).each do |a_module|
|
43
|
+
scan :module, a_module
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def record_methods_for(klass_or_module)
|
48
|
+
record_result(
|
49
|
+
klass_or_module,
|
50
|
+
:public => klass_or_module.public_instance_methods(false),
|
51
|
+
:protected => klass_or_module.protected_instance_methods(false),
|
52
|
+
:private => klass_or_module.private_instance_methods(false)
|
53
|
+
)
|
54
|
+
end
|
55
|
+
|
56
|
+
def record_result(*args)
|
57
|
+
@results << FindResult.new(*args)
|
58
|
+
end
|
59
|
+
|
60
|
+
def modules_for(obj_type, klass_or_module)
|
61
|
+
case obj_type
|
62
|
+
when :module
|
63
|
+
klass_or_module.included_modules
|
64
|
+
when :class
|
65
|
+
if superclass = klass_or_module.superclass
|
66
|
+
klass_or_module.included_modules - superclass.included_modules
|
67
|
+
else
|
68
|
+
klass_or_module.included_modules
|
69
|
+
end
|
70
|
+
when :eigenclass
|
71
|
+
eigenclass = get_eigenclass(klass_or_module)
|
72
|
+
eigenclass.included_modules - klass_or_module.class.included_modules
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# This method is awfully complicated and does not give accurate answers
|
77
|
+
# because the reflection methods for eigenclasses do not work correctly.
|
78
|
+
# The singleton_methods(false) call will return all public and protected
|
79
|
+
# singleton methods, but not the private ones. And the
|
80
|
+
# *_instance_methods(false) calls will include the methods defined on the
|
81
|
+
# class in addition to singleton methods. c.f the following test scenarios:
|
82
|
+
# mixed_visibility_methods.rb and cloned_eigenclass.rb
|
83
|
+
def record_methods_for_eigenclass(object)
|
84
|
+
@seen[object] = true
|
85
|
+
return unless eigenclass = get_eigenclass(object)
|
86
|
+
|
87
|
+
our_public_methods = eigenclass.public_instance_methods(false)
|
88
|
+
our_protected_methods = eigenclass.protected_instance_methods(false)
|
89
|
+
our_private_methods = eigenclass.private_instance_methods(false)
|
90
|
+
|
91
|
+
ancestor_methods = Hash.new
|
92
|
+
[:public, :protected, :private].each do |method_type|
|
93
|
+
ancestor_methods[method_type] = eigenclass.ancestors.map do |ancestor|
|
94
|
+
ancestor.send("#{method_type}_instance_methods", false)
|
95
|
+
end.flatten.uniq
|
96
|
+
end
|
97
|
+
|
98
|
+
record_result(object,
|
99
|
+
:public => our_public_methods - ancestor_methods[:public],
|
100
|
+
:protected => our_protected_methods - ancestor_methods[:protected],
|
101
|
+
:private => our_private_methods - ancestor_methods[:private]
|
102
|
+
)
|
103
|
+
|
104
|
+
scan_modules(:eigenclass, object)
|
105
|
+
end
|
106
|
+
|
107
|
+
def get_eigenclass(object)
|
108
|
+
class << object; self; end
|
109
|
+
rescue TypeError
|
110
|
+
nil
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Kernel
|
2
|
+
def mls(show_public_only=false,
|
3
|
+
displayer=MethodLister::ColorDisplay.new,
|
4
|
+
finder=MethodLister::Finder.new)
|
5
|
+
displayer.display finder.ls(self), show_public_only
|
6
|
+
end
|
7
|
+
alias :ls :mls
|
8
|
+
|
9
|
+
def mgrep(regex,
|
10
|
+
show_public_only=false,
|
11
|
+
displayer=MethodLister::ColorDisplay.new,
|
12
|
+
finder=MethodLister::Finder.new)
|
13
|
+
displayer.display finder.grep(regex, self), show_public_only
|
14
|
+
end
|
15
|
+
alias :grep :mgrep
|
16
|
+
|
17
|
+
def mwhich(method,
|
18
|
+
show_public_only=false,
|
19
|
+
displayer=MethodLister::ColorDisplay.new,
|
20
|
+
finder=MethodLister::Finder.new)
|
21
|
+
displayer.display finder.which(method, self), show_public_only
|
22
|
+
end
|
23
|
+
alias :which :mwhich
|
24
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module MethodLister
|
2
|
+
class SimpleDisplay
|
3
|
+
def display(findings, show_public_only=false)
|
4
|
+
findings.reverse.each do |result|
|
5
|
+
list = method_list(result, show_public_only)
|
6
|
+
if !list.empty?
|
7
|
+
puts header(result)
|
8
|
+
puts list
|
9
|
+
puts seperator(result)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
nil
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def header(result)
|
18
|
+
"========== #{location_description(result)} =========="
|
19
|
+
end
|
20
|
+
|
21
|
+
def method_list(result, show_public_only)
|
22
|
+
FindResult::VISIBILITIES.map do |visibility|
|
23
|
+
(visibility == :public || !show_public_only) ?
|
24
|
+
method_set(result, visibility) :
|
25
|
+
nil
|
26
|
+
end.compact.join("\n\n")
|
27
|
+
end
|
28
|
+
|
29
|
+
def method_set(result, visibility)
|
30
|
+
if result.has_methods?(visibility)
|
31
|
+
"#{visibility.to_s.upcase}: " +
|
32
|
+
result.methods(visibility).map {|method|
|
33
|
+
process_method(result, method)
|
34
|
+
}.join(" ")
|
35
|
+
else
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def process_method(result, method)
|
41
|
+
method
|
42
|
+
end
|
43
|
+
|
44
|
+
def seperator(result)
|
45
|
+
""
|
46
|
+
end
|
47
|
+
|
48
|
+
def location_description(result)
|
49
|
+
object = result.object
|
50
|
+
return "Class #{object}" if object.kind_of? Class
|
51
|
+
return "Module #{object}" if object.kind_of? Module
|
52
|
+
return "Eigenclass"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/spec_helper")
|
2
|
+
|
3
|
+
describe MethodLister::ColorDisplay do
|
4
|
+
describe "#display" do
|
5
|
+
before do
|
6
|
+
@results = [
|
7
|
+
result(Object.new, :public => ["foo"]),
|
8
|
+
result(Array, :public => ["bar"] + Array.public_instance_methods(false)),
|
9
|
+
result(Kernel, :public => ["baz"] + Kernel.public_instance_methods(false)),
|
10
|
+
]
|
11
|
+
|
12
|
+
@displayer = MethodLister::ColorDisplay.new
|
13
|
+
|
14
|
+
@output = ""
|
15
|
+
stub(@displayer).puts do |*args|
|
16
|
+
@output += args.map {|arg| arg.to_s}.join("") + "\n"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
it "attempts to write out the relevant information" do
|
21
|
+
@displayer.display @results
|
22
|
+
@output.should =~ /Module Kernel.*.*Class Array.*bar.*Eigenclass.*foo/m
|
23
|
+
end
|
24
|
+
|
25
|
+
it "does not add ANSI codes if output is not a tty" do
|
26
|
+
mock(@displayer).output_is_to_tty? { false }.times(any_times)
|
27
|
+
@displayer.display @results
|
28
|
+
@output.should_not =~ /\e\[0m;/m
|
29
|
+
end
|
30
|
+
|
31
|
+
it "does add ANSI codes if output is a tty" do
|
32
|
+
mock(@displayer).output_is_to_tty? { true }.times(any_times)
|
33
|
+
@displayer.display @results
|
34
|
+
@output.should =~ /\e\[0m/m
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|