awesome_print 1.6.1 → 1.7.0
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.
- checksums.yaml +4 -4
- data/Appraisals +16 -3
- data/{CHANGELOG → CHANGELOG.md} +55 -18
- data/CONTRIBUTING.md +43 -3
- data/README.md +13 -52
- data/lib/awesome_print.rb +2 -2
- data/lib/awesome_print/colorize.rb +24 -0
- data/lib/awesome_print/ext/nobrainer.rb +49 -0
- data/lib/awesome_print/formatter.rb +53 -326
- data/lib/awesome_print/formatters/array_formatter.rb +73 -0
- data/lib/awesome_print/formatters/base_formatter.rb +138 -0
- data/lib/awesome_print/formatters/class_formatter.rb +24 -0
- data/lib/awesome_print/formatters/dir_formatter.rb +22 -0
- data/lib/awesome_print/formatters/file_formatter.rb +22 -0
- data/lib/awesome_print/formatters/hash_formatter.rb +54 -0
- data/lib/awesome_print/formatters/method_formatter.rb +22 -0
- data/lib/awesome_print/formatters/object_formatter.rb +80 -0
- data/lib/awesome_print/formatters/simple_formatter.rb +21 -0
- data/lib/awesome_print/indentator.rb +18 -0
- data/lib/awesome_print/inspector.rb +12 -1
- data/lib/awesome_print/version.rb +1 -1
- data/spec/active_record_helper.rb +19 -29
- data/spec/colors_spec.rb +2 -2
- data/spec/formats_spec.rb +73 -34
- data/spec/methods_spec.rb +6 -6
- data/spec/misc_spec.rb +4 -2
- data/spec/objects_spec.rb +52 -8
- data/spec/spec_helper.rb +49 -34
- metadata +31 -6
- data/lib/awesome_print/ext/no_brainer.rb +0 -58
@@ -3,19 +3,27 @@
|
|
3
3
|
# Awesome Print is freely distributable under the terms of MIT license.
|
4
4
|
# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
|
5
5
|
#------------------------------------------------------------------------------
|
6
|
-
|
7
|
-
|
6
|
+
require_relative "formatters/object_formatter"
|
7
|
+
require_relative "formatters/hash_formatter"
|
8
|
+
require_relative "formatters/array_formatter"
|
9
|
+
require_relative "formatters/simple_formatter"
|
10
|
+
require_relative "formatters/method_formatter"
|
11
|
+
require_relative "formatters/class_formatter"
|
12
|
+
require_relative "formatters/dir_formatter"
|
13
|
+
require_relative "formatters/file_formatter"
|
14
|
+
require_relative "colorize"
|
8
15
|
|
9
16
|
module AwesomePrint
|
10
17
|
class Formatter
|
18
|
+
include Colorize
|
19
|
+
|
20
|
+
attr_reader :inspector, :options
|
11
21
|
|
12
22
|
CORE = [ :array, :bigdecimal, :class, :dir, :file, :hash, :method, :rational, :set, :struct, :unboundmethod ]
|
13
|
-
DEFAULT_LIMIT_SIZE = 7
|
14
23
|
|
15
24
|
def initialize(inspector)
|
16
25
|
@inspector = inspector
|
17
26
|
@options = inspector.options
|
18
|
-
@indentation = @options[:indent].abs
|
19
27
|
end
|
20
28
|
|
21
29
|
# Main entry point to format an object.
|
@@ -37,25 +45,6 @@ module AwesomePrint
|
|
37
45
|
CORE.grep(type)[0] || :self
|
38
46
|
end
|
39
47
|
|
40
|
-
# Pick the color and apply it to the given string as necessary.
|
41
|
-
#------------------------------------------------------------------------------
|
42
|
-
def colorize(str, type)
|
43
|
-
str = CGI.escapeHTML(str) if @options[:html]
|
44
|
-
if @options[:plain] || !@options[:color][type] || !@inspector.colorize?
|
45
|
-
str
|
46
|
-
#
|
47
|
-
# Check if the string color method is defined by awesome_print and accepts
|
48
|
-
# html parameter or it has been overriden by some gem such as colorize.
|
49
|
-
#
|
50
|
-
elsif str.method(@options[:color][type]).arity == -1 # Accepts html parameter.
|
51
|
-
str.send(@options[:color][type], @options[:html])
|
52
|
-
else
|
53
|
-
str = %Q|<kbd style="color:#{@options[:color][type]}">#{str}</kbd>| if @options[:html]
|
54
|
-
str.send(@options[:color][type])
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
|
59
48
|
private
|
60
49
|
|
61
50
|
# Catch all method to format an arbitrary object.
|
@@ -63,345 +52,83 @@ module AwesomePrint
|
|
63
52
|
def awesome_self(object, type)
|
64
53
|
if @options[:raw] && object.instance_variables.any?
|
65
54
|
awesome_object(object)
|
66
|
-
elsif object
|
67
|
-
awesome_hash(
|
68
|
-
else
|
69
|
-
colorize(object.inspect.to_s, type)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
# Format an array.
|
74
|
-
#------------------------------------------------------------------------------
|
75
|
-
def awesome_array(a)
|
76
|
-
return "[]" if a == []
|
77
|
-
|
78
|
-
if a.instance_variable_defined?('@__awesome_methods__')
|
79
|
-
methods_array(a)
|
80
|
-
elsif @options[:multiline]
|
81
|
-
width = (a.size - 1).to_s.size
|
82
|
-
|
83
|
-
data = a.inject([]) do |arr, item|
|
84
|
-
index = indent
|
85
|
-
index << colorize("[#{arr.size.to_s.rjust(width)}] ", :array) if @options[:index]
|
86
|
-
indented do
|
87
|
-
arr << (index << @inspector.awesome(item))
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
data = limited(data, width) if should_be_limited?
|
92
|
-
"[\n" << data.join(",\n") << "\n#{outdent}]"
|
93
|
-
else
|
94
|
-
"[ " << a.map{ |item| @inspector.awesome(item) }.join(", ") << " ]"
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
# Format a hash. If @options[:indent] if negative left align hash keys.
|
99
|
-
#------------------------------------------------------------------------------
|
100
|
-
def awesome_hash(h)
|
101
|
-
return "{}" if h == {}
|
102
|
-
|
103
|
-
keys = @options[:sort_keys] ? h.keys.sort { |a, b| a.to_s <=> b.to_s } : h.keys
|
104
|
-
data = keys.map do |key|
|
105
|
-
plain_single_line do
|
106
|
-
[ @inspector.awesome(key), h[key] ]
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
width = data.map { |key, | key.size }.max || 0
|
111
|
-
width += @indentation if @options[:indent] > 0
|
112
|
-
|
113
|
-
data = data.map do |key, value|
|
114
|
-
indented do
|
115
|
-
align(key, width) << colorize(" => ", :hash) << @inspector.awesome(value)
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
data = limited(data, width, :hash => true) if should_be_limited?
|
120
|
-
if @options[:multiline]
|
121
|
-
"{\n" << data.join(",\n") << "\n#{outdent}}"
|
55
|
+
elsif hash = convert_to_hash(object)
|
56
|
+
awesome_hash(hash)
|
122
57
|
else
|
123
|
-
|
58
|
+
awesome_simple(object.inspect.to_s, type, @inspector)
|
124
59
|
end
|
125
60
|
end
|
126
61
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
property = var.to_s[1..-1].to_sym # to_s because of some monkey patching done by Puppet.
|
132
|
-
accessor = if o.respond_to?(:"#{property}=")
|
133
|
-
o.respond_to?(property) ? :accessor : :writer
|
134
|
-
else
|
135
|
-
o.respond_to?(property) ? :reader : nil
|
136
|
-
end
|
137
|
-
if accessor
|
138
|
-
[ "attr_#{accessor} :#{property}", var ]
|
139
|
-
else
|
140
|
-
[ var.to_s, var ]
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
data = vars.sort.map do |declaration, var|
|
145
|
-
key = left_aligned do
|
146
|
-
align(declaration, declaration.size)
|
147
|
-
end
|
148
|
-
|
149
|
-
unless @options[:plain]
|
150
|
-
if key =~ /(@\w+)/
|
151
|
-
key.sub!($1, colorize($1, :variable))
|
152
|
-
else
|
153
|
-
key.sub!(/(attr_\w+)\s(\:\w+)/, "#{colorize('\\1', :keyword)} #{colorize('\\2', :method)}")
|
154
|
-
end
|
155
|
-
end
|
156
|
-
indented do
|
157
|
-
key << colorize(" = ", :hash) + @inspector.awesome(o.instance_variable_get(var))
|
158
|
-
end
|
159
|
-
end
|
160
|
-
if @options[:multiline]
|
161
|
-
"#<#{awesome_instance(o)}\n#{data.join(%Q/,\n/)}\n#{outdent}>"
|
162
|
-
else
|
163
|
-
"#<#{awesome_instance(o)} #{data.join(', ')}>"
|
164
|
-
end
|
62
|
+
def awesome_bigdecimal(n)
|
63
|
+
o = n.to_s("F")
|
64
|
+
type = :bigdecimal
|
65
|
+
awesome_simple(o, type, @inspector)
|
165
66
|
end
|
166
67
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
68
|
+
def awesome_rational(n)
|
69
|
+
o = n.to_s
|
70
|
+
type = :rational
|
71
|
+
awesome_simple(o, type, @inspector)
|
171
72
|
end
|
172
73
|
|
173
|
-
|
174
|
-
|
175
|
-
def awesome_struct(s)
|
176
|
-
#
|
177
|
-
# The code is slightly uglier because of Ruby 1.8.6 quirks:
|
178
|
-
# awesome_hash(Hash[s.members.zip(s.values)]) <-- ArgumentError: odd number of arguments for Hash)
|
179
|
-
# awesome_hash(Hash[*s.members.zip(s.values).flatten]) <-- s.members returns strings, not symbols.
|
180
|
-
#
|
181
|
-
hash = {}
|
182
|
-
s.each_pair { |key, value| hash[key] = value }
|
183
|
-
awesome_hash(hash)
|
74
|
+
def awesome_simple(o, type, inspector)
|
75
|
+
AwesomePrint::Formatters::SimpleFormatter.new(o, type, inspector).format
|
184
76
|
end
|
185
77
|
|
186
|
-
|
187
|
-
|
188
|
-
def awesome_class(c)
|
189
|
-
if superclass = c.superclass # <-- Assign and test if nil.
|
190
|
-
colorize("#{c.inspect} < #{superclass}", :class)
|
191
|
-
else
|
192
|
-
colorize(c.inspect, :class)
|
193
|
-
end
|
78
|
+
def awesome_array(a)
|
79
|
+
Formatters::ArrayFormatter.new(a, @inspector).format
|
194
80
|
end
|
195
81
|
|
196
|
-
|
197
|
-
|
198
|
-
def awesome_file(f)
|
199
|
-
ls = File.directory?(f) ? `ls -adlF #{f.path.shellescape}` : `ls -alF #{f.path.shellescape}`
|
200
|
-
colorize(ls.empty? ? f.inspect : "#{f.inspect}\n#{ls.chop}", :file)
|
82
|
+
def awesome_set(s)
|
83
|
+
Formatters::ArrayFormatter.new(s.to_a, @inspector).format
|
201
84
|
end
|
202
85
|
|
203
|
-
|
204
|
-
|
205
|
-
def awesome_dir(d)
|
206
|
-
ls = `ls -alF #{d.path.shellescape}`
|
207
|
-
colorize(ls.empty? ? d.inspect : "#{d.inspect}\n#{ls.chop}", :dir)
|
86
|
+
def awesome_hash(h)
|
87
|
+
Formatters::HashFormatter.new(h, @inspector).format
|
208
88
|
end
|
209
89
|
|
210
|
-
|
211
|
-
|
212
|
-
def awesome_bigdecimal(n)
|
213
|
-
colorize(n.to_s("F"), :bigdecimal)
|
90
|
+
def awesome_object(o)
|
91
|
+
Formatters::ObjectFormatter.new(o, o.instance_variables, @inspector).format
|
214
92
|
end
|
215
93
|
|
216
|
-
|
217
|
-
|
218
|
-
def awesome_rational(n)
|
219
|
-
colorize(n.to_s, :rational)
|
94
|
+
def awesome_struct(s)
|
95
|
+
Formatters::ObjectFormatter.new(s, s.members, @inspector).format
|
220
96
|
end
|
221
97
|
|
222
|
-
# Format a method.
|
223
|
-
#------------------------------------------------------------------------------
|
224
98
|
def awesome_method(m)
|
225
|
-
|
226
|
-
"#{colorize(owner, :class)}##{colorize(name, :method)}#{colorize(args, :args)}"
|
99
|
+
Formatters::MethodFormatter.new(m, @inspector).format
|
227
100
|
end
|
228
101
|
alias :awesome_unboundmethod :awesome_method
|
229
102
|
|
230
|
-
|
231
|
-
|
232
|
-
def awesome_instance(o)
|
233
|
-
"#{o.class}:0x%08x" % (o.__id__ * 2)
|
234
|
-
end
|
235
|
-
|
236
|
-
# Format object.methods array.
|
237
|
-
#------------------------------------------------------------------------------
|
238
|
-
def methods_array(a)
|
239
|
-
a.sort! { |x, y| x.to_s <=> y.to_s } # Can't simply a.sort! because of o.methods << [ :blah ]
|
240
|
-
object = a.instance_variable_get('@__awesome_methods__')
|
241
|
-
tuples = a.map do |name|
|
242
|
-
if name.is_a?(Symbol) || name.is_a?(String) # Ignore garbage, ex. 42.methods << [ :blah ]
|
243
|
-
tuple = if object.respond_to?(name, true) # Is this a regular method?
|
244
|
-
the_method = object.method(name) rescue nil # Avoid potential ArgumentError if object#method is overridden.
|
245
|
-
if the_method && the_method.respond_to?(:arity) # Is this original object#method?
|
246
|
-
method_tuple(the_method) # Yes, we are good.
|
247
|
-
end
|
248
|
-
elsif object.respond_to?(:instance_method) # Is this an unbound method?
|
249
|
-
method_tuple(object.instance_method(name)) rescue nil # Rescue to avoid NameError when the method is not
|
250
|
-
end # available (ex. File.lchmod on Ubuntu 12).
|
251
|
-
end
|
252
|
-
tuple || [ name.to_s, '(?)', '?' ] # Return WTF default if all the above fails.
|
253
|
-
end
|
254
|
-
|
255
|
-
width = (tuples.size - 1).to_s.size
|
256
|
-
name_width = tuples.map { |item| item[0].size }.max || 0
|
257
|
-
args_width = tuples.map { |item| item[1].size }.max || 0
|
258
|
-
|
259
|
-
data = tuples.inject([]) do |arr, item|
|
260
|
-
index = indent
|
261
|
-
index << "[#{arr.size.to_s.rjust(width)}]" if @options[:index]
|
262
|
-
indented do
|
263
|
-
arr << "#{index} #{colorize(item[0].rjust(name_width), :method)}#{colorize(item[1].ljust(args_width), :args)} #{colorize(item[2], :class)}"
|
264
|
-
end
|
265
|
-
end
|
266
|
-
|
267
|
-
"[\n" << data.join("\n") << "\n#{outdent}]"
|
103
|
+
def awesome_class(c)
|
104
|
+
Formatters::ClassFormatter.new(c, @inspector).format
|
268
105
|
end
|
269
106
|
|
270
|
-
|
271
|
-
|
272
|
-
def method_tuple(method)
|
273
|
-
if method.respond_to?(:parameters) # Ruby 1.9.2+
|
274
|
-
# See http://ruby.runpaint.org/methods#method-objects-parameters
|
275
|
-
args = method.parameters.inject([]) do |arr, (type, name)|
|
276
|
-
name ||= (type == :block ? 'block' : "arg#{arr.size + 1}")
|
277
|
-
arr << case type
|
278
|
-
when :req then name.to_s
|
279
|
-
when :opt, :rest then "*#{name}"
|
280
|
-
when :block then "&#{name}"
|
281
|
-
else '?'
|
282
|
-
end
|
283
|
-
end
|
284
|
-
else # See http://ruby-doc.org/core/classes/Method.html#M001902
|
285
|
-
args = (1..method.arity.abs).map { |i| "arg#{i}" }
|
286
|
-
args[-1] = "*#{args[-1]}" if method.arity < 0
|
287
|
-
end
|
288
|
-
|
289
|
-
# method.to_s formats to handle:
|
290
|
-
#
|
291
|
-
# #<Method: Fixnum#zero?>
|
292
|
-
# #<Method: Fixnum(Integer)#years>
|
293
|
-
# #<Method: User(#<Module:0x00000103207c00>)#_username>
|
294
|
-
# #<Method: User(id: integer, username: string).table_name>
|
295
|
-
# #<Method: User(id: integer, username: string)(ActiveRecord::Base).current>
|
296
|
-
# #<UnboundMethod: Hello#world>
|
297
|
-
#
|
298
|
-
if method.to_s =~ /(Unbound)*Method: (.*)[#\.]/
|
299
|
-
unbound, klass = $1 && '(unbound)', $2
|
300
|
-
if klass && klass =~ /(\(\w+:\s.*?\))/ # Is this ActiveRecord-style class?
|
301
|
-
klass.sub!($1, '') # Yes, strip the fields leaving class name only.
|
302
|
-
end
|
303
|
-
owner = "#{klass}#{unbound}".gsub('(', ' (')
|
304
|
-
end
|
305
|
-
|
306
|
-
[ method.name.to_s, "(#{args.join(', ')})", owner.to_s ]
|
107
|
+
def awesome_file(f)
|
108
|
+
Formatters::FileFormatter.new(f, @inspector).format
|
307
109
|
end
|
308
110
|
|
309
|
-
|
310
|
-
|
311
|
-
def plain_single_line
|
312
|
-
plain, multiline = @options[:plain], @options[:multiline]
|
313
|
-
@options[:plain], @options[:multiline] = true, false
|
314
|
-
yield
|
315
|
-
ensure
|
316
|
-
@options[:plain], @options[:multiline] = plain, multiline
|
111
|
+
def awesome_dir(d)
|
112
|
+
Formatters::DirFormatter.new(d, @inspector).format
|
317
113
|
end
|
318
114
|
|
319
115
|
# Utility methods.
|
320
116
|
#------------------------------------------------------------------------------
|
321
|
-
def
|
322
|
-
if
|
323
|
-
|
324
|
-
value.rjust(width)
|
325
|
-
elsif @options[:indent] == 0
|
326
|
-
indent + value.ljust(width)
|
327
|
-
else
|
328
|
-
indent[0, @indentation + @options[:indent]] + value.ljust(width)
|
329
|
-
end
|
330
|
-
else
|
331
|
-
value
|
117
|
+
def convert_to_hash(object)
|
118
|
+
if ! object.respond_to?(:to_hash)
|
119
|
+
return nil
|
332
120
|
end
|
333
|
-
end
|
334
|
-
|
335
|
-
def indented
|
336
|
-
@indentation += @options[:indent].abs
|
337
|
-
yield
|
338
|
-
ensure
|
339
|
-
@indentation -= @options[:indent].abs
|
340
|
-
end
|
341
|
-
|
342
|
-
def left_aligned
|
343
|
-
current, @options[:indent] = @options[:indent], 0
|
344
|
-
yield
|
345
|
-
ensure
|
346
|
-
@options[:indent] = current
|
347
|
-
end
|
348
|
-
|
349
|
-
def indent
|
350
|
-
' ' * @indentation
|
351
|
-
end
|
352
121
|
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
# To support limited output, for example:
|
358
|
-
#
|
359
|
-
# ap ('a'..'z').to_a, :limit => 3
|
360
|
-
# [
|
361
|
-
# [ 0] "a",
|
362
|
-
# [ 1] .. [24],
|
363
|
-
# [25] "z"
|
364
|
-
# ]
|
365
|
-
#
|
366
|
-
# ap (1..100).to_a, :limit => true # Default limit is 7.
|
367
|
-
# [
|
368
|
-
# [ 0] 1,
|
369
|
-
# [ 1] 2,
|
370
|
-
# [ 2] 3,
|
371
|
-
# [ 3] .. [96],
|
372
|
-
# [97] 98,
|
373
|
-
# [98] 99,
|
374
|
-
# [99] 100
|
375
|
-
# ]
|
376
|
-
#------------------------------------------------------------------------------
|
377
|
-
def should_be_limited?
|
378
|
-
@options[:limit] == true or (@options[:limit].is_a?(Fixnum) and @options[:limit] > 0)
|
379
|
-
end
|
380
|
-
|
381
|
-
def get_limit_size
|
382
|
-
@options[:limit] == true ? DEFAULT_LIMIT_SIZE : @options[:limit]
|
383
|
-
end
|
384
|
-
|
385
|
-
def limited(data, width, is_hash = false)
|
386
|
-
limit = get_limit_size
|
387
|
-
if data.length <= limit
|
388
|
-
data
|
389
|
-
else
|
390
|
-
# Calculate how many elements to be displayed above and below the separator.
|
391
|
-
head = limit / 2
|
392
|
-
tail = head - (limit - 1) % 2
|
393
|
-
|
394
|
-
# Add the proper elements to the temp array and format the separator.
|
395
|
-
temp = data[0, head] + [ nil ] + data[-tail, tail]
|
396
|
-
|
397
|
-
if is_hash
|
398
|
-
temp[head] = "#{indent}#{data[head].strip} .. #{data[data.length - tail - 1].strip}"
|
399
|
-
else
|
400
|
-
temp[head] = "#{indent}[#{head.to_s.rjust(width)}] .. [#{data.length - tail - 1}]"
|
401
|
-
end
|
122
|
+
if object.method(:to_hash).arity != 0
|
123
|
+
return nil
|
124
|
+
end
|
402
125
|
|
403
|
-
|
126
|
+
hash = object.to_hash
|
127
|
+
if ! hash.respond_to?(:keys) || ! hash.respond_to?('[]')
|
128
|
+
return nil
|
404
129
|
end
|
130
|
+
|
131
|
+
return hash
|
405
132
|
end
|
406
133
|
end
|
407
134
|
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require_relative 'base_formatter'
|
2
|
+
|
3
|
+
module AwesomePrint
|
4
|
+
module Formatters
|
5
|
+
class ArrayFormatter < BaseFormatter
|
6
|
+
|
7
|
+
attr_reader :array, :inspector, :options
|
8
|
+
|
9
|
+
def initialize(array, inspector)
|
10
|
+
@array = array
|
11
|
+
@inspector = inspector
|
12
|
+
@options = inspector.options
|
13
|
+
end
|
14
|
+
|
15
|
+
def format
|
16
|
+
return "[]" if array == []
|
17
|
+
|
18
|
+
if array.instance_variable_defined?('@__awesome_methods__')
|
19
|
+
methods_array(array)
|
20
|
+
elsif options[:multiline]
|
21
|
+
width = (array.size - 1).to_s.size
|
22
|
+
|
23
|
+
data = array.inject([]) do |arr, item|
|
24
|
+
index = indent
|
25
|
+
index << colorize("[#{arr.size.to_s.rjust(width)}] ", :array) if options[:index]
|
26
|
+
indented do
|
27
|
+
arr << (index << inspector.awesome(item))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
data = limited(data, width) if should_be_limited?
|
32
|
+
"[\n" << data.join(",\n") << "\n#{outdent}]"
|
33
|
+
else
|
34
|
+
"[ " << array.map{ |item| inspector.awesome(item) }.join(", ") << " ]"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def methods_array(a)
|
41
|
+
a.sort! { |x, y| x.to_s <=> y.to_s } # Can't simply a.sort! because of o.methods << [ :blah ]
|
42
|
+
object = a.instance_variable_get('@__awesome_methods__')
|
43
|
+
tuples = a.map do |name|
|
44
|
+
if name.is_a?(Symbol) || name.is_a?(String) # Ignore garbage, ex. 42.methods << [ :blah ]
|
45
|
+
tuple = if object.respond_to?(name, true) # Is this a regular method?
|
46
|
+
the_method = object.method(name) rescue nil # Avoid potential ArgumentError if object#method is overridden.
|
47
|
+
if the_method && the_method.respond_to?(:arity) # Is this original object#method?
|
48
|
+
method_tuple(the_method) # Yes, we are good.
|
49
|
+
end
|
50
|
+
elsif object.respond_to?(:instance_method) # Is this an unbound method?
|
51
|
+
method_tuple(object.instance_method(name)) rescue nil # Rescue to avoid NameError when the method is not
|
52
|
+
end # available (ex. File.lchmod on Ubuntu 12).
|
53
|
+
end
|
54
|
+
tuple || [ name.to_s, '(?)', '?' ] # Return WTF default if all the above fails.
|
55
|
+
end
|
56
|
+
|
57
|
+
width = (tuples.size - 1).to_s.size
|
58
|
+
name_width = tuples.map { |item| item[0].size }.max || 0
|
59
|
+
args_width = tuples.map { |item| item[1].size }.max || 0
|
60
|
+
|
61
|
+
data = tuples.inject([]) do |arr, item|
|
62
|
+
index = indent
|
63
|
+
index << "[#{arr.size.to_s.rjust(width)}]" if @options[:index]
|
64
|
+
indented do
|
65
|
+
arr << "#{index} #{colorize(item[0].rjust(name_width), :method)}#{colorize(item[1].ljust(args_width), :args)} #{colorize(item[2], :class)}"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
"[\n" << data.join("\n") << "\n#{outdent}]"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|