method_lister 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|