awesome_print 1.2.0 → 1.9.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -2
  3. data/Appraisals +62 -0
  4. data/CHANGELOG.md +180 -0
  5. data/CONTRIBUTING.md +82 -0
  6. data/Gemfile +3 -2
  7. data/LICENSE +16 -19
  8. data/README.md +112 -87
  9. data/Rakefile +17 -4
  10. data/awesome_print.gemspec +33 -0
  11. data/init.rb +1 -0
  12. data/lib/ap.rb +2 -2
  13. data/lib/awesome_print.rb +22 -16
  14. data/lib/awesome_print/colorize.rb +24 -0
  15. data/lib/awesome_print/core_ext/{array.rb → awesome_method_array.rb} +16 -18
  16. data/lib/awesome_print/core_ext/class.rb +3 -2
  17. data/lib/awesome_print/core_ext/kernel.rb +1 -1
  18. data/lib/awesome_print/core_ext/logger.rb +1 -1
  19. data/lib/awesome_print/core_ext/method.rb +2 -2
  20. data/lib/awesome_print/core_ext/object.rb +3 -2
  21. data/lib/awesome_print/core_ext/string.rb +3 -3
  22. data/lib/awesome_print/custom_defaults.rb +57 -0
  23. data/lib/awesome_print/ext/action_view.rb +8 -4
  24. data/lib/awesome_print/ext/active_record.rb +47 -13
  25. data/lib/awesome_print/ext/active_support.rb +1 -1
  26. data/lib/awesome_print/ext/mongo_mapper.rb +16 -13
  27. data/lib/awesome_print/ext/mongoid.rb +9 -7
  28. data/lib/awesome_print/ext/nobrainer.rb +52 -0
  29. data/lib/awesome_print/ext/nokogiri.rb +4 -4
  30. data/lib/awesome_print/ext/ostruct.rb +27 -0
  31. data/lib/awesome_print/ext/ripple.rb +6 -7
  32. data/lib/awesome_print/ext/sequel.rb +7 -6
  33. data/lib/awesome_print/formatter.rb +54 -327
  34. data/lib/awesome_print/formatters.rb +15 -0
  35. data/lib/awesome_print/formatters/array_formatter.rb +139 -0
  36. data/lib/awesome_print/formatters/base_formatter.rb +140 -0
  37. data/lib/awesome_print/formatters/class_formatter.rb +25 -0
  38. data/lib/awesome_print/formatters/dir_formatter.rb +22 -0
  39. data/lib/awesome_print/formatters/file_formatter.rb +22 -0
  40. data/lib/awesome_print/formatters/hash_formatter.rb +106 -0
  41. data/lib/awesome_print/formatters/method_formatter.rb +22 -0
  42. data/lib/awesome_print/formatters/object_formatter.rb +78 -0
  43. data/lib/awesome_print/formatters/simple_formatter.rb +21 -0
  44. data/lib/awesome_print/formatters/struct_formatter.rb +71 -0
  45. data/lib/awesome_print/indentator.rb +18 -0
  46. data/lib/awesome_print/inspector.rb +92 -94
  47. data/lib/awesome_print/version.rb +2 -2
  48. data/spec/active_record_helper.rb +30 -0
  49. data/spec/colors_spec.rb +31 -31
  50. data/spec/core_ext/logger_spec.rb +43 -0
  51. data/spec/core_ext/string_spec.rb +20 -0
  52. data/spec/ext/action_view_spec.rb +21 -0
  53. data/spec/ext/active_record_spec.rb +260 -0
  54. data/spec/ext/active_support_spec.rb +30 -0
  55. data/spec/ext/mongo_mapper_spec.rb +261 -0
  56. data/spec/ext/mongoid_spec.rb +67 -0
  57. data/spec/ext/nobrainer_spec.rb +59 -0
  58. data/spec/ext/nokogiri_spec.rb +46 -0
  59. data/spec/ext/ostruct_spec.rb +22 -0
  60. data/spec/ext/ripple_spec.rb +48 -0
  61. data/spec/formats_spec.rb +272 -205
  62. data/spec/methods_spec.rb +173 -177
  63. data/spec/misc_spec.rb +129 -105
  64. data/spec/objects_spec.rb +162 -27
  65. data/spec/spec_helper.rb +75 -37
  66. data/spec/support/active_record_data.rb +20 -0
  67. data/spec/support/active_record_data/3_2_diana.txt +24 -0
  68. data/spec/support/active_record_data/3_2_diana_legacy.txt +24 -0
  69. data/spec/support/active_record_data/3_2_multi.txt +50 -0
  70. data/spec/support/active_record_data/3_2_multi_legacy.txt +50 -0
  71. data/spec/support/active_record_data/4_0_diana.txt +98 -0
  72. data/spec/support/active_record_data/4_0_multi.txt +198 -0
  73. data/spec/support/active_record_data/4_1_diana.txt +97 -0
  74. data/spec/support/active_record_data/4_1_multi.txt +196 -0
  75. data/spec/support/active_record_data/4_2_diana.txt +109 -0
  76. data/spec/support/active_record_data/4_2_diana_legacy.txt +109 -0
  77. data/spec/support/active_record_data/4_2_multi.txt +220 -0
  78. data/spec/support/active_record_data/4_2_multi_legacy.txt +220 -0
  79. data/spec/support/active_record_data/5_0_diana.txt +105 -0
  80. data/spec/support/active_record_data/5_0_multi.txt +212 -0
  81. data/spec/support/active_record_data/5_1_diana.txt +104 -0
  82. data/spec/support/active_record_data/5_1_multi.txt +210 -0
  83. data/spec/support/active_record_data/5_2_diana.txt +104 -0
  84. data/spec/support/active_record_data/5_2_multi.txt +210 -0
  85. data/spec/support/active_record_data/6_0_diana.txt +104 -0
  86. data/spec/support/active_record_data/6_0_multi.txt +210 -0
  87. data/spec/support/active_record_data/6_1_diana.txt +109 -0
  88. data/spec/support/active_record_data/6_1_multi.txt +220 -0
  89. data/spec/support/ext_verifier.rb +42 -0
  90. data/spec/support/mongoid_versions.rb +26 -0
  91. data/spec/support/rails_versions.rb +55 -0
  92. metadata +163 -32
  93. data/CHANGELOG +0 -96
  94. data/lib/awesome_print/ext/no_brainer.rb +0 -58
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2010-2013 Michael Dvorkin
1
+ # Copyright (c) 2010-2016 Michael Dvorkin and contributors
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
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2010-2013 Michael Dvorkin
1
+ # Copyright (c) 2010-2016 Michael Dvorkin and contributors
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
@@ -18,7 +18,7 @@ module AwesomePrint
18
18
  cast = cast_without_mongo_mapper(object, type)
19
19
 
20
20
  if defined?(::MongoMapper::Document)
21
- if object.is_a?(Class) && (object.ancestors & [ ::MongoMapper::Document, ::MongoMapper::EmbeddedDocument ]).size > 0
21
+ if object.is_a?(Class) && (object.ancestors & [::MongoMapper::Document, ::MongoMapper::EmbeddedDocument]).size > 0
22
22
  cast = :mongo_mapper_class
23
23
  elsif object.is_a?(::MongoMapper::Document) || object.is_a?(::MongoMapper::EmbeddedDocument)
24
24
  cast = :mongo_mapper_instance
@@ -38,7 +38,7 @@ module AwesomePrint
38
38
  return object.inspect if !defined?(::ActiveSupport::OrderedHash) || !object.respond_to?(:keys)
39
39
 
40
40
  data = object.keys.sort.inject(::ActiveSupport::OrderedHash.new) do |hash, c|
41
- hash[c.first] = (c.last.type || "undefined").to_s.underscore.intern
41
+ hash[c.first] = (c.last.type || 'undefined').to_s.underscore.intern
42
42
  hash
43
43
  end
44
44
 
@@ -49,7 +49,10 @@ module AwesomePrint
49
49
  end
50
50
  end
51
51
 
52
- "class #{object} < #{object.superclass} " << awesome_hash(data)
52
+ name = "class #{awesome_simple(object.to_s, :class)}"
53
+ base = "< #{awesome_simple(object.superclass.to_s, :class)}"
54
+
55
+ [name, base, awesome_hash(data)].join(' ')
53
56
  end
54
57
 
55
58
  # Format MongoMapper instance object.
@@ -65,7 +68,7 @@ module AwesomePrint
65
68
  return object.inspect if !defined?(::ActiveSupport::OrderedHash)
66
69
  return awesome_object(object) if @options[:raw]
67
70
 
68
- data = object.keys.keys.sort_by{|k| k}.inject(::ActiveSupport::OrderedHash.new) do |hash, name|
71
+ data = object.keys.keys.sort_by { |k| k }.inject(::ActiveSupport::OrderedHash.new) do |hash, name|
69
72
  hash[name] = object[name]
70
73
  hash
71
74
  end
@@ -73,11 +76,11 @@ module AwesomePrint
73
76
  # Add in associations
74
77
  if @options[:mongo_mapper][:show_associations]
75
78
  object.associations.each do |name, assoc|
76
- if @options[:mongo_mapper][:inline_embedded] and assoc.embeddable?
77
- data[name.to_s] = object.send(name)
78
- else
79
- data[name.to_s] = assoc
80
- end
79
+ data[name.to_s] = if @options[:mongo_mapper][:inline_embedded] and assoc.embeddable?
80
+ object.send(name)
81
+ else
82
+ assoc
83
+ end
81
84
  end
82
85
  end
83
86
 
@@ -93,7 +96,7 @@ module AwesomePrint
93
96
  return object.inspect if !defined?(::ActiveSupport::OrderedHash)
94
97
  return awesome_object(object) if @options[:raw]
95
98
 
96
- association = object.class.name.split('::').last.titleize.downcase.sub(/ association$/,'')
99
+ association = object.class.name.split('::').last.titleize.downcase.sub(/ association$/, '')
97
100
  association = "embeds #{association}" if object.embeddable?
98
101
  class_name = object.class_name
99
102
 
@@ -111,8 +114,8 @@ module AwesomePrint
111
114
  def apply_default_mongo_mapper_options
112
115
  @options[:color][:assoc] ||= :greenish
113
116
  @options[:mongo_mapper] ||= {
114
- :show_associations => false, # Display association data for MongoMapper documents and classes.
115
- :inline_embedded => false # Display embedded associations inline with MongoMapper documents.
117
+ show_associations: false, # Display association data for MongoMapper documents and classes.
118
+ inline_embedded: false # Display embedded associations inline with MongoMapper documents.
116
119
  }
117
120
  end
118
121
  end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2010-2013 Michael Dvorkin
1
+ # Copyright (c) 2010-2016 Michael Dvorkin and contributors
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
@@ -20,7 +20,7 @@ module AwesomePrint
20
20
  cast = :mongoid_class
21
21
  elsif object.class.ancestors.include?(::Mongoid::Document)
22
22
  cast = :mongoid_document
23
- elsif (defined?(::BSON) && object.is_a?(::BSON::ObjectId)) || (defined?(::Moped) && object.is_a?(::Moped::BSON::ObjectId))
23
+ elsif (defined?(::BSON) && object.is_a?(::BSON::ObjectId)) || (defined?(::Moped::BSON) && object.is_a?(::Moped::BSON::ObjectId))
24
24
  cast = :mongoid_bson_id
25
25
  end
26
26
  end
@@ -33,10 +33,14 @@ module AwesomePrint
33
33
  return object.inspect if !defined?(::ActiveSupport::OrderedHash) || !object.respond_to?(:fields)
34
34
 
35
35
  data = object.fields.sort_by { |key| key }.inject(::ActiveSupport::OrderedHash.new) do |hash, c|
36
- hash[c[1].name.to_sym] = (c[1].type || "undefined").to_s.underscore.intern
36
+ hash[c[1].name.to_sym] = (c[1].type || 'undefined').to_s.underscore.intern
37
37
  hash
38
38
  end
39
- "class #{object} < #{object.superclass} " << awesome_hash(data)
39
+
40
+ name = "class #{awesome_simple(object.to_s, :class)}"
41
+ base = "< #{awesome_simple(object.superclass.to_s, :class)}"
42
+
43
+ [name, base, awesome_hash(data)].join(' ')
40
44
  end
41
45
 
42
46
  # Format Mongoid Document object.
@@ -48,9 +52,7 @@ module AwesomePrint
48
52
  hash[c[0].to_sym] = c[1]
49
53
  hash
50
54
  end
51
- if !object.errors.empty?
52
- data = {:errors => object.errors, :attributes => data}
53
- end
55
+ data = { errors: object.errors, attributes: data } if !object.errors.empty?
54
56
  "#{object} #{awesome_hash(data)}"
55
57
  end
56
58
 
@@ -0,0 +1,52 @@
1
+ # Copyright (c) 2010-2016 Michael Dvorkin and contributors
2
+ #
3
+ # Awesome Print is freely distributable under the terms of MIT license.
4
+ # See LICENSE file or http://www.opensource.org/licenses/mit-license.php
5
+ #------------------------------------------------------------------------------
6
+ module AwesomePrint
7
+ module NoBrainer
8
+
9
+ def self.included(base)
10
+ base.send :alias_method, :cast_without_nobrainer, :cast
11
+ base.send :alias_method, :cast, :cast_with_nobrainer
12
+ end
13
+
14
+ # Add NoBrainer class names to the dispatcher pipeline.
15
+ #------------------------------------------------------------------------------
16
+ def cast_with_nobrainer(object, type)
17
+ cast = cast_without_nobrainer(object, type)
18
+ if defined?(::NoBrainer::Document)
19
+ if object.is_a?(Class) && object < ::NoBrainer::Document
20
+ cast = :nobrainer_class
21
+ elsif object.is_a?(::NoBrainer::Document)
22
+ cast = :nobrainer_document
23
+ end
24
+ end
25
+ cast
26
+ end
27
+
28
+ # Format NoBrainer class object.
29
+ #------------------------------------------------------------------------------
30
+ def awesome_nobrainer_class(object)
31
+ name = "#{awesome_simple(object, :class)} < #{awesome_simple(object.superclass, :class)}"
32
+ data = Hash[object.fields.map do |field, options|
33
+ [field, (options[:type] || Object).to_s.underscore.to_sym]
34
+ end]
35
+
36
+ name = "class #{awesome_simple(object.to_s, :class)}"
37
+ base = "< #{awesome_simple(object.superclass.to_s, :class)}"
38
+
39
+ [name, base, awesome_hash(data)].join(' ')
40
+ end
41
+
42
+ # Format NoBrainer Document object.
43
+ #------------------------------------------------------------------------------
44
+ def awesome_nobrainer_document(object)
45
+ data = object.inspectable_attributes.symbolize_keys
46
+ data = { errors: object.errors, attributes: data } if object.errors.present?
47
+ "#{object} #{awesome_hash(data)}"
48
+ end
49
+ end
50
+ end
51
+
52
+ AwesomePrint::Formatter.send(:include, AwesomePrint::NoBrainer)
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2010-2013 Michael Dvorkin
1
+ # Copyright (c) 2010-2016 Michael Dvorkin and contributors
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
@@ -15,7 +15,7 @@ module AwesomePrint
15
15
  #------------------------------------------------------------------------------
16
16
  def cast_with_nokogiri(object, type)
17
17
  cast = cast_without_nokogiri(object, type)
18
- if (defined?(::Nokogiri::XML::Node) && object.is_a?(::Nokogiri::XML::Node)) ||
18
+ if (defined?(::Nokogiri::XML::Node) && object.is_a?(::Nokogiri::XML::Node)) ||
19
19
  (defined?(::Nokogiri::XML::NodeSet) && object.is_a?(::Nokogiri::XML::NodeSet))
20
20
  cast = :nokogiri_xml_node
21
21
  end
@@ -25,9 +25,9 @@ module AwesomePrint
25
25
  #------------------------------------------------------------------------------
26
26
  def awesome_nokogiri_xml_node(object)
27
27
  if object.is_a?(::Nokogiri::XML::NodeSet) && object.empty?
28
- return "[]"
28
+ return '[]'
29
29
  end
30
- xml = object.to_xml(:indent => 2)
30
+ xml = object.to_xml(indent: 2)
31
31
  #
32
32
  # Colorize tag, id/class name, and contents.
33
33
  #
@@ -0,0 +1,27 @@
1
+ # Copyright (c) 2010-2016 Michael Dvorkin and contributors
2
+ #
3
+ # Awesome Print is freely distributable under the terms of MIT license.
4
+ # See LICENSE file or http://www.opensource.org/licenses/mit-license.php
5
+ #------------------------------------------------------------------------------
6
+ module AwesomePrint
7
+ module OpenStruct
8
+ def self.included(base)
9
+ base.send :alias_method, :cast_without_ostruct, :cast
10
+ base.send :alias_method, :cast, :cast_with_ostruct
11
+ end
12
+
13
+ def cast_with_ostruct(object, type)
14
+ cast = cast_without_ostruct(object, type)
15
+ if (defined?(::OpenStruct)) && (object.is_a?(::OpenStruct))
16
+ cast = :open_struct_instance
17
+ end
18
+ cast
19
+ end
20
+
21
+ def awesome_open_struct_instance(object)
22
+ "#{object.class} #{awesome_hash(object.marshal_dump)}"
23
+ end
24
+ end
25
+ end
26
+
27
+ AwesomePrint::Formatter.send(:include, AwesomePrint::OpenStruct)
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2010-2013 Michael Dvorkin
1
+ # Copyright (c) 2010-2016 Michael Dvorkin and contributors
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
@@ -52,7 +52,7 @@ module AwesomePrint
52
52
  end
53
53
  end
54
54
 
55
- "##{object} " << awesome_hash(data)
55
+ "#{object} " << awesome_hash(data)
56
56
  end
57
57
 
58
58
  # Format Ripple class object.
@@ -60,11 +60,10 @@ module AwesomePrint
60
60
  def awesome_ripple_document_class(object)
61
61
  return object.inspect if !defined?(::ActiveSupport::OrderedHash) || !object.respond_to?(:properties)
62
62
 
63
- data = object.properties.inject(::ActiveSupport::OrderedHash.new) do |hash, (name, defn)|
64
- hash[name.to_sym] = defn.type.to_s.downcase.to_sym
65
- hash
66
- end
67
- "class #{object} < #{object.superclass} " << awesome_hash(data)
63
+ name = "class #{awesome_simple(object.to_s, :class)}"
64
+ base = "< #{awesome_simple(object.superclass.to_s, :class)}"
65
+
66
+ [name, base, awesome_hash(data)].join(' ')
68
67
  end
69
68
  end
70
69
  end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2010-2013 Michael Dvorkin
1
+ # Copyright (c) 2010-2016 Michael Dvorkin and contributors
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
@@ -32,9 +32,7 @@ module AwesomePrint
32
32
  hash[c[0].to_sym] = c[1]
33
33
  hash
34
34
  end
35
- if !object.errors.empty?
36
- data = {:errors => object.errors, :values => data}
37
- end
35
+ data = { errors: object.errors, values: data } if !object.errors.empty?
38
36
  "#{object} #{awesome_hash(data)}"
39
37
  end
40
38
 
@@ -47,8 +45,11 @@ module AwesomePrint
47
45
  # Format Sequel Model class.
48
46
  #------------------------------------------------------------------------------
49
47
  def awesome_sequel_model_class(object)
50
- data = object.db_schema.inject({}) {|h, (name,data)| h.merge(name => data[:db_type])}
51
- "class #{object} < #{object.superclass} " << awesome_hash(data)
48
+ data = object.db_schema.inject({}) { |h, (prop, defn)| h.merge(prop => defn[:db_type]) }
49
+ name = "class #{awesome_simple(object.to_s, :class)}"
50
+ base = "< #{awesome_simple(object.superclass.to_s, :class)}"
51
+
52
+ [name, base, awesome_hash(data)].join(' ')
52
53
  end
53
54
  end
54
55
 
@@ -1,21 +1,21 @@
1
- # Copyright (c) 2010-2013 Michael Dvorkin
1
+ # Copyright (c) 2010-2016 Michael Dvorkin and contributors
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
- autoload :CGI, "cgi"
7
- require "shellwords"
6
+ require 'awesome_print/formatters'
8
7
 
9
8
  module AwesomePrint
10
9
  class Formatter
10
+ include Colorize
11
11
 
12
- CORE = [ :array, :bigdecimal, :class, :dir, :file, :hash, :method, :rational, :set, :struct, :unboundmethod ]
13
- DEFAULT_LIMIT_SIZE = 7
12
+ attr_reader :inspector, :options
13
+
14
+ CORE_FORMATTERS = [:array, :bigdecimal, :class, :dir, :file, :hash, :method, :rational, :set, :struct, :unboundmethod]
14
15
 
15
16
  def initialize(inspector)
16
17
  @inspector = inspector
17
18
  @options = inspector.options
18
- @indentation = @options[:indent].abs
19
19
  end
20
20
 
21
21
  # Main entry point to format an object.
@@ -34,28 +34,9 @@ module AwesomePrint
34
34
  # directory for custom formatters that ship with awesome_print.
35
35
  #------------------------------------------------------------------------------
36
36
  def cast(object, type)
37
- CORE.grep(type)[0] || :self
38
- end
39
-
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
37
+ CORE_FORMATTERS.include?(type) ? type : :self
56
38
  end
57
39
 
58
-
59
40
  private
60
41
 
61
42
  # Catch all method to format an arbitrary object.
@@ -63,345 +44,91 @@ module AwesomePrint
63
44
  def awesome_self(object, type)
64
45
  if @options[:raw] && object.instance_variables.any?
65
46
  awesome_object(object)
66
- elsif object == ENV
67
- awesome_hash(object.to_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}}"
47
+ elsif (hash = convert_to_hash(object))
48
+ awesome_hash(hash)
122
49
  else
123
- "{ #{data.join(', ')} }"
50
+ awesome_simple(object.inspect.to_s, type, @inspector)
124
51
  end
125
52
  end
126
53
 
127
- # Format an object.
128
- #------------------------------------------------------------------------------
129
- def awesome_object(o)
130
- vars = o.instance_variables.map do |var|
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
54
+ def awesome_bigdecimal(n)
55
+ o = n.to_s('F')
56
+ type = :bigdecimal
57
+ awesome_simple(o, type, @inspector)
165
58
  end
166
59
 
167
- # Format a set.
168
- #------------------------------------------------------------------------------
169
- def awesome_set(s)
170
- awesome_array(s.to_a)
60
+ def awesome_rational(n)
61
+ o = n.to_s
62
+ type = :rational
63
+ awesome_simple(o, type, @inspector)
171
64
  end
172
65
 
173
- # Format a Struct.
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)
66
+ def awesome_simple(o, type, inspector = @inspector)
67
+ AwesomePrint::Formatters::SimpleFormatter.new(o, type, inspector).format
184
68
  end
185
69
 
186
- # Format Class object.
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
70
+ def awesome_array(a)
71
+ Formatters::ArrayFormatter.new(a, @inspector).format
194
72
  end
195
73
 
196
- # Format File object.
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)
74
+ def awesome_set(s)
75
+ Formatters::ArrayFormatter.new(s.to_a, @inspector).format
201
76
  end
202
77
 
203
- # Format Dir object.
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)
78
+ def awesome_hash(h)
79
+ Formatters::HashFormatter.new(h, @inspector).format
208
80
  end
209
81
 
210
- # Format BigDecimal object.
211
- #------------------------------------------------------------------------------
212
- def awesome_bigdecimal(n)
213
- colorize(n.to_s("F"), :bigdecimal)
82
+ def awesome_object(o)
83
+ Formatters::ObjectFormatter.new(o, @inspector).format
214
84
  end
215
85
 
216
- # Format Rational object.
217
- #------------------------------------------------------------------------------
218
- def awesome_rational(n)
219
- colorize(n.to_s, :rational)
86
+ def awesome_struct(s)
87
+ Formatters::StructFormatter.new(s, @inspector).format
220
88
  end
221
89
 
222
- # Format a method.
223
- #------------------------------------------------------------------------------
224
90
  def awesome_method(m)
225
- name, args, owner = method_tuple(m)
226
- "#{colorize(owner, :class)}##{colorize(name, :method)}#{colorize(args, :args)}"
91
+ Formatters::MethodFormatter.new(m, @inspector).format
227
92
  end
228
93
  alias :awesome_unboundmethod :awesome_method
229
94
 
230
- # Format object instance.
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}]"
95
+ def awesome_class(c)
96
+ Formatters::ClassFormatter.new(c, @inspector).format
268
97
  end
269
98
 
270
- # Return [ name, arguments, owner ] tuple for a given method.
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 ]
99
+ def awesome_file(f)
100
+ Formatters::FileFormatter.new(f, @inspector).format
307
101
  end
308
102
 
309
- # Format hash keys as plain strings regardless of underlying data type.
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
103
+ def awesome_dir(d)
104
+ Formatters::DirFormatter.new(d, @inspector).format
317
105
  end
318
106
 
319
107
  # Utility methods.
320
108
  #------------------------------------------------------------------------------
321
- def align(value, width)
322
- if @options[:multiline]
323
- if @options[:indent] > 0
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
332
- end
333
- end
334
109
 
335
- def indented
336
- @indentation += @options[:indent].abs
337
- yield
338
- ensure
339
- @indentation -= @options[:indent].abs
110
+ # A class (ex. `Net::HTTP.Get`) might have `attr_reader :method` accessor
111
+ # which causes `object.method(:to_hash)` throw `ArgumentError (wrong number
112
+ # of arguments (given 1, expected 0))`. The following tries to avoid that.
113
+ def has_method_accessor?(object)
114
+ !object.method(:method)
115
+ rescue ArgumentError
116
+ true
340
117
  end
341
118
 
342
- def left_aligned
343
- current, @options[:indent] = @options[:indent], 0
344
- yield
345
- ensure
346
- @options[:indent] = current
347
- end
119
+ def convert_to_hash(object)
120
+ return nil if has_method_accessor?(object)
121
+ return nil if !object.respond_to?(:to_hash) || object.method(:to_hash).arity != 0
348
122
 
349
- def indent
350
- ' ' * @indentation
351
- end
123
+ # ActionController::Parameters will raise if they are not yet permitted
124
+ # and we try to convert to hash.
125
+ # https://api.rubyonrails.org/classes/ActionController/Parameters.html
126
+ return nil if object.respond_to?(:permitted?) && !object.permitted?
352
127
 
353
- def outdent
354
- ' ' * (@indentation - @options[:indent].abs)
355
- end
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
128
+ hash = object.to_hash
129
+ return nil if !hash.respond_to?(:keys) || !hash.respond_to?(:[])
384
130
 
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
402
-
403
- temp
404
- end
131
+ hash
405
132
  end
406
133
  end
407
134
  end