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
data/spec/misc_spec.rb ADDED
@@ -0,0 +1,250 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe "AwesomePrint" do
4
+
5
+ describe "Misc" do
6
+ before do
7
+ stub_dotfile!
8
+ end
9
+
10
+ it "handle weird objects that return nil on inspect" do
11
+ weird = Class.new do
12
+ def inspect
13
+ nil
14
+ end
15
+ end
16
+ expect(weird.new.ai(:plain => true)).to eq('')
17
+ end
18
+
19
+ it "handle frozen object.inspect" do
20
+ weird = Class.new do
21
+ def inspect
22
+ "ice".freeze
23
+ end
24
+ end
25
+ expect(weird.new.ai(:plain => false)).to eq("ice")
26
+ end
27
+
28
+ # See https://github.com/michaeldv/awesome_print/issues/35
29
+ it "handle array grep when pattern contains / chapacter" do
30
+ hash = { "1/x" => 1, "2//x" => :"2" }
31
+ grepped = hash.keys.sort.grep(/^(\d+)\//) { $1 }
32
+ expect(grepped.ai(:plain => true, :multiline => false)).to eq('[ "1", "2" ]')
33
+ end
34
+
35
+ # See https://github.com/michaeldv/awesome_print/issues/85
36
+ if RUBY_VERSION >= "1.8.7"
37
+ it "handle array grep when a method is defined in C and thus doesn't have a binding" do
38
+ arr = (0..6).to_a
39
+ grepped = arr.grep(1..4, &:succ)
40
+ expect(grepped.ai(:plain => true, :multiline => false)).to eq('[ 2, 3, 4, 5 ]')
41
+ end
42
+ end
43
+
44
+ it "returns value passed as a parameter" do
45
+ object = rand
46
+ allow(self).to receive(:puts)
47
+ expect(ap object).to eq(object)
48
+ end
49
+
50
+ # Require different file name this time (lib/ap.rb vs. lib/awesome_print).
51
+ it "several require 'awesome_print' should do no harm" do
52
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/ap')
53
+ expect { rand.ai }.not_to raise_error
54
+ end
55
+
56
+ it "format ENV as hash" do
57
+ expect(ENV.ai(:plain => true)).to eq(ENV.to_hash.ai(:plain => true))
58
+ expect(ENV.ai).to eq(ENV.to_hash.ai)
59
+ end
60
+
61
+ # See https://github.com/michaeldv/awesome_print/issues/134
62
+ it "IPAddr workaround" do
63
+ require "ipaddr"
64
+ ipaddr = IPAddr.new("3ffe:505:2::1")
65
+ expect(ipaddr.ai).to eq("#<IPAddr: IPv6:3ffe:0505:0002:0000:0000:0000:0000:0001/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff>")
66
+ end
67
+
68
+ # See https://github.com/michaeldv/awesome_print/issues/139
69
+ it "Object that overrides == and expects the :id method" do
70
+ weird = Class.new do
71
+ # Raises NoMethodError: undefined method `id' when "other" is nil or ENV.
72
+ def ==(other)
73
+ self.id == other.id
74
+ end
75
+ alias :eql? :==
76
+ end
77
+ expect { weird.new.ai }.not_to raise_error
78
+ end
79
+ end
80
+
81
+ #------------------------------------------------------------------------------
82
+ describe "HTML output" do
83
+ before do
84
+ stub_dotfile!
85
+ end
86
+
87
+ it "wraps ap output with plain <pre> tag" do
88
+ markup = rand
89
+ expect(markup.ai(:html => true, :plain => true)).to eq("<pre>#{markup}</pre>")
90
+ end
91
+
92
+ it "wraps ap output with <pre> tag with colorized <kbd>" do
93
+ markup = rand
94
+ expect(markup.ai(:html => true)).to eq(%Q|<pre><kbd style="color:blue">#{markup}</kbd></pre>|)
95
+ end
96
+
97
+ it "wraps multiline ap output with <pre> tag with colorized <kbd>" do
98
+ markup = [ 1, :two, "three" ]
99
+ expect(markup.ai(:html => true)).to eq <<-EOS.strip
100
+ <pre>[
101
+ <kbd style="color:white">[0] </kbd><kbd style="color:blue">1</kbd>,
102
+ <kbd style="color:white">[1] </kbd><kbd style="color:darkcyan">:two</kbd>,
103
+ <kbd style="color:white">[2] </kbd><kbd style="color:brown">&quot;three&quot;</kbd>
104
+ ]</pre>
105
+ EOS
106
+ end
107
+
108
+ it "wraps hash ap output with only an outer <pre> tag" do
109
+ markup = [ { "hello" => "world" } ]
110
+ expect(markup.ai(:html => true)).to eq <<-EOS.strip
111
+ <pre>[
112
+ <kbd style="color:white">[0] </kbd>{
113
+ &quot;hello&quot;<kbd style="color:slategray"> =&gt; </kbd><kbd style="color:brown">&quot;world&quot;</kbd>
114
+ }
115
+ ]</pre>
116
+ EOS
117
+ end
118
+
119
+ it "encodes HTML entities (plain)" do
120
+ markup = ' &<hello>'
121
+ expect(markup.ai(:html => true, :plain => true)).to eq('<pre>&quot; &amp;&lt;hello&gt;&quot;</pre>')
122
+ end
123
+
124
+ it "encodes HTML entities (color)" do
125
+ markup = ' &<hello>'
126
+ expect(markup.ai(:html => true)).to eq('<pre><kbd style="color:brown">&quot; &amp;&lt;hello&gt;&quot;</kbd></pre>')
127
+ end
128
+ end
129
+
130
+ #------------------------------------------------------------------------------
131
+ describe "AwesomePrint.defaults" do
132
+ before do
133
+ stub_dotfile!
134
+ end
135
+
136
+ after do
137
+ AwesomePrint.defaults = nil
138
+ end
139
+
140
+ # See https://github.com/michaeldv/awesome_print/issues/98
141
+ it "should properly merge the defaults" do
142
+ AwesomePrint.defaults = { :indent => -2, :sort_keys => true }
143
+ hash = { [0, 0, 255] => :yellow, :red => "rgb(255, 0, 0)", "magenta" => "rgb(255, 0, 255)" }
144
+ out = hash.ai(:plain => true)
145
+ expect(out).to eq <<-EOS.strip
146
+ {
147
+ [ 0, 0, 255 ] => :yellow,
148
+ "magenta" => "rgb(255, 0, 255)",
149
+ :red => "rgb(255, 0, 0)"
150
+ }
151
+ EOS
152
+ end
153
+ end
154
+
155
+ #------------------------------------------------------------------------------
156
+ describe "Coexistence with the colorize gem" do
157
+ before do
158
+ stub_dotfile!
159
+ end
160
+
161
+ before do # Redefine String#red just like colorize gem does it.
162
+ @awesome_method = "".method(:red)
163
+
164
+ String.instance_eval do
165
+ define_method :red do # Method arity is now 0 in Ruby 1.9+.
166
+ "[red]#{self}[/red]"
167
+ end
168
+ end
169
+ end
170
+
171
+ after do # Restore String#red method.
172
+ awesome_method = @awesome_method
173
+ String.instance_eval do
174
+ define_method :red, awesome_method
175
+ end
176
+ end
177
+
178
+ it "shoud not raise ArgumentError when formatting HTML" do
179
+ out = "hello".ai(:color => { :string => :red }, :html => true)
180
+ if RUBY_VERSION >= "1.9"
181
+ expect(out).to eq(%Q|<pre>[red]<kbd style="color:red">&quot;hello&quot;</kbd>[/red]</pre>|)
182
+ else
183
+ expect(out).to eq(%Q|<pre>[red]&quot;hello&quot;[/red]</pre>|)
184
+ end
185
+ end
186
+
187
+ it "shoud not raise ArgumentError when formatting HTML (shade color)" do
188
+ out = "hello".ai(:color => { :string => :redish }, :html => true)
189
+ expect(out).to eq(%Q|<pre><kbd style="color:darkred">&quot;hello&quot;</kbd></pre>|)
190
+ end
191
+
192
+ it "shoud not raise ArgumentError when formatting non-HTML" do
193
+ out = "hello".ai(:color => { :string => :red }, :html => false)
194
+ expect(out).to eq(%Q|[red]"hello"[/red]|)
195
+ end
196
+
197
+ it "shoud not raise ArgumentError when formatting non-HTML (shade color)" do
198
+ out = "hello".ai(:color => { :string => :redish }, :html => false)
199
+ expect(out).to eq(%Q|\e[0;31m"hello"\e[0m|)
200
+ end
201
+ end
202
+
203
+ #------------------------------------------------------------------------------
204
+ describe "Console" do
205
+ it "should detect IRB" do
206
+ class IRB; end
207
+ ENV.delete('RAILS_ENV')
208
+ expect(AwesomePrint.console?).to eq(true)
209
+ expect(AwesomePrint.rails_console?).to eq(false)
210
+ Object.instance_eval{ remove_const :IRB }
211
+ end
212
+
213
+ it "should detect Pry" do
214
+ class Pry; end
215
+ ENV.delete('RAILS_ENV')
216
+ expect(AwesomePrint.console?).to eq(true)
217
+ expect(AwesomePrint.rails_console?).to eq(false)
218
+ Object.instance_eval{ remove_const :Pry }
219
+ end
220
+
221
+ it "should detect Rails::Console" do
222
+ class IRB; end
223
+ module Rails; class Console; end; end
224
+ expect(AwesomePrint.console?).to eq(true)
225
+ expect(AwesomePrint.rails_console?).to eq(true)
226
+ Object.instance_eval{ remove_const :IRB }
227
+ Object.instance_eval{ remove_const :Rails }
228
+ end
229
+
230
+ it "should detect ENV['RAILS_ENV']" do
231
+ class Pry; end
232
+ ENV["RAILS_ENV"] = "development"
233
+ expect(AwesomePrint.console?).to eq(true)
234
+ expect(AwesomePrint.rails_console?).to eq(true)
235
+ Object.instance_eval{ remove_const :Pry }
236
+ end
237
+
238
+ it "should return the actual object when *not* running under console" do
239
+ expect(capture! { ap([ 1, 2, 3 ]) }).to eq([ 1, 2, 3 ])
240
+ expect(capture! { ap({ :a => 1 }) }).to eq({ :a => 1 })
241
+ end
242
+
243
+ it "should return nil when running under console" do
244
+ class IRB; end
245
+ expect(capture! { ap([ 1, 2, 3 ]) }).to eq(nil)
246
+ expect(capture! { ap({ :a => 1 }) }).to eq(nil)
247
+ Object.instance_eval{ remove_const :IRB }
248
+ end
249
+ end
250
+ end
data/spec/objects_spec.rb CHANGED
@@ -1,6 +1,6 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
1
+ require 'spec_helper'
2
2
 
3
- describe "Single method" do
3
+ RSpec.describe "Objects" do
4
4
  before do
5
5
  stub_dotfile!
6
6
  end
@@ -9,7 +9,7 @@ describe "Single method" do
9
9
  Object.instance_eval{ remove_const :Hello } if defined?(Hello)
10
10
  end
11
11
 
12
- describe "object" do
12
+ describe "Formatting an object" do
13
13
  it "attributes" do
14
14
  class Hello
15
15
  attr_reader :abra
@@ -21,15 +21,17 @@ describe "Single method" do
21
21
  end
22
22
  end
23
23
 
24
- out = Hello.new.ai(:plain => true)
24
+ hello = Hello.new
25
+ out = hello.ai(:plain => true, :raw => true)
25
26
  str = <<-EOS.strip
26
- #<Hello:0x01234567
27
+ #<Hello:placeholder_id
27
28
  attr_accessor :dabra = 3,
28
29
  attr_reader :abra = 1,
29
30
  attr_writer :ca = 2
30
31
  >
31
32
  EOS
32
- out.gsub(/0x([a-f\d]+)/, "0x01234567").should == str
33
+ expect(out).to be_similar_to(str)
34
+ expect(hello.ai(:plain => true, :raw => false)).to eq(hello.inspect)
33
35
  end
34
36
 
35
37
  it "instance variables" do
@@ -39,15 +41,17 @@ EOS
39
41
  end
40
42
  end
41
43
 
42
- out = Hello.new.ai(:plain => true)
44
+ hello = Hello.new
45
+ out = hello.ai(:plain => true, :raw => true)
43
46
  str = <<-EOS.strip
44
- #<Hello:0x01234567
47
+ #<Hello:placeholder_id
45
48
  @abra = 1,
46
49
  @ca = 2,
47
50
  @dabra = 3
48
51
  >
49
52
  EOS
50
- out.gsub(/0x([a-f\d]+)/, "0x01234567").should == str
53
+ expect(out).to be_similar_to(str)
54
+ expect(hello.ai(:plain => true, :raw => false)).to eq(hello.inspect)
51
55
  end
52
56
 
53
57
  it "attributes and instance variables" do
@@ -62,9 +66,10 @@ EOS
62
66
  end
63
67
  end
64
68
 
65
- out = Hello.new.ai(:plain => true)
69
+ hello = Hello.new
70
+ out = hello.ai(:plain => true, :raw => true)
66
71
  str = <<-EOS.strip
67
- #<Hello:0x01234567
72
+ #<Hello:placeholder_id
68
73
  @doo = 1,
69
74
  @dooby = 2,
70
75
  @scooby = 3,
@@ -73,7 +78,52 @@ EOS
73
78
  attr_writer :ca = 2
74
79
  >
75
80
  EOS
76
- out.gsub(/0x([a-f\d]+)/, "0x01234567").should == str
81
+ expect(out).to be_similar_to(str)
82
+ expect(hello.ai(:plain => true, :raw => false)).to eq(hello.inspect)
83
+ end
84
+
85
+ it "without the plain options print the colorized values" do
86
+ class Hello
87
+ attr_reader :abra
88
+ attr_writer :ca
89
+
90
+ def initialize
91
+ @abra, @ca = 1, 2
92
+ @dabra = 3
93
+ end
94
+ end
95
+
96
+ hello = Hello.new
97
+ out = hello.ai(:raw => true)
98
+ str = <<-EOS.strip
99
+ #<Hello:placeholder_id
100
+ \e[0;36m@dabra\e[0m\e[0;37m = \e[0m\e[1;34m3\e[0m,
101
+ \e[1;36mattr_reader\e[0m \e[0;35m:abra\e[0m\e[0;37m = \e[0m\e[1;34m1\e[0m,
102
+ \e[1;36mattr_writer\e[0m \e[0;35m:ca\e[0m\e[0;37m = \e[0m\e[1;34m2\e[0m
103
+ >
104
+ EOS
105
+ expect(out).to be_similar_to(str)
106
+ expect(hello.ai(:plain => true, :raw => false)).to eq(hello.inspect)
107
+ end
108
+
109
+ it "with multine as false show inline values" do
110
+ class Hello
111
+ attr_reader :abra
112
+ attr_writer :ca
113
+
114
+ def initialize
115
+ @abra, @ca = 1, 2
116
+ @dabra = 3
117
+ end
118
+ end
119
+
120
+ hello = Hello.new
121
+ out = hello.ai(:multiline => false, :plain => true, :raw => true)
122
+ str = <<-EOS.strip
123
+ #<Hello:placeholder_id @dabra = 3, attr_reader :abra = 1, attr_writer :ca = 2>
124
+ EOS
125
+ expect(out).to be_similar_to(str)
126
+ expect(hello.ai(:plain => true, :raw => false)).to eq(hello.inspect)
77
127
  end
78
128
  end
79
129
  end
data/spec/spec_helper.rb CHANGED
@@ -1,4 +1,4 @@
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
@@ -6,46 +6,78 @@
6
6
  #
7
7
  # Running specs from the command line:
8
8
  # $ rake spec # Entire spec suite.
9
- # $ rspec spec/logger_spec.rb # Individual spec file.
9
+ # $ rspec spec/objects_spec.rb # Individual spec file.
10
10
  #
11
+ # NOTE: To successfully run specs with Ruby 1.8.6 the older versions of
12
+ # Bundler and RSpec gems are required:
13
+ #
14
+ # $ gem install bundler -v=1.0.2
15
+ # $ gem install rspec -v=2.6.0
16
+ #
17
+ require 'codeclimate-test-reporter'
18
+ CodeClimate::TestReporter.start
11
19
  $LOAD_PATH.unshift(File.dirname(__FILE__))
12
20
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
21
+
22
+ Dir[File.dirname(__FILE__) + '/support/**/*.rb'].each do |file|
23
+ require file
24
+ end
25
+
26
+ ExtVerifier.require_dependencies!(%w{rails active_record action_view
27
+ active_support/all mongoid mongo_mapper ripple nobrainer})
28
+ require 'nokogiri'
13
29
  require 'awesome_print'
14
30
 
31
+ RSpec.configure do |config|
32
+ config.disable_monkey_patching!
33
+ # TODO: Make specs not order dependent
34
+ # config.order = :random
35
+ Kernel.srand config.seed
36
+ config.filter_run focus: true
37
+ config.run_all_when_everything_filtered = true
38
+ config.expect_with :rspec do |expectations|
39
+ expectations.syntax = :expect
40
+ end
41
+ config.mock_with :rspec do |mocks|
42
+ mocks.syntax = :expect
43
+ mocks.verify_partial_doubles = true
44
+ end
45
+ if config.files_to_run.one?
46
+ config.default_formatter = 'doc'
47
+ end
48
+ end
49
+
50
+ # This matcher handles the normalization of objects to replace non deterministic
51
+ # parts (such as object IDs) with simple placeholder strings before doing a
52
+ # comparison with a given string. It's important that this method only matches
53
+ # a string which strictly conforms to the expected object ID format.
54
+ RSpec::Matchers.define :be_similar_to do |expected, options|
55
+ match do |actual|
56
+ options ||= {}
57
+ @actual = normalize_object_id_strings(actual, options)
58
+ values_match? expected, @actual
59
+ end
60
+
61
+ diffable
62
+ end
63
+
64
+ # Override the Object IDs with a placeholder so that we are only checking
65
+ # that an ID is present and not that it matches a certain value. This is
66
+ # necessary as the Object IDs are not deterministic.
67
+ def normalize_object_id_strings(str, options)
68
+ str = str.gsub(/#<(.*?):0x[a-f\d]+/, '#<\1:placeholder_id') unless options[:skip_standard]
69
+ str = str.gsub(/BSON::ObjectId\('[a-f\d]{24}'\)/, 'placeholder_bson_id') unless options[:skip_bson]
70
+ str
71
+ end
72
+
15
73
  def stub_dotfile!
16
74
  dotfile = File.join(ENV["HOME"], ".aprc")
17
- File.should_receive(:readable?).at_least(:once).with(dotfile).and_return(false)
75
+ expect(File).to receive(:readable?).at_least(:once).with(dotfile).and_return(false)
18
76
  end
19
77
 
20
- # The following is needed for the Infinity Test. It runs tests as subprocesses,
21
- # which sets STDOUT.tty? to false and would otherwise prematurely disallow colors.
22
- ### AwesomePrint.force_colors!
23
-
24
- # Ruby 1.8.6 only: define missing String methods that are needed for the specs to pass.
25
- if RUBY_VERSION < '1.8.7'
26
- class String
27
- def shellescape # Taken from Ruby 1.9.2 standard library, see lib/shellwords.rb.
28
- return "''" if self.empty?
29
- str = self.dup
30
- str.gsub!(/([^A-Za-z0-9_\-.,:\/@\n])/n, "\\\\\\1")
31
- str.gsub!(/\n/, "'\n'")
32
- str
33
- end
34
-
35
- def start_with?(*prefixes)
36
- prefixes.each do |prefix|
37
- prefix = prefix.to_s
38
- return true if prefix == self[0, prefix.size]
39
- end
40
- false
41
- end
42
-
43
- def end_with?(*suffixes)
44
- suffixes.each do |suffix|
45
- suffix = suffix.to_s
46
- return true if suffix == self[-suffix.size, suffix.size]
47
- end
48
- false
49
- end
50
- end
78
+ def capture!
79
+ standard, $stdout = $stdout, StringIO.new
80
+ yield
81
+ ensure
82
+ $stdout = standard
51
83
  end