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