awesome_print_lite 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +43 -0
- data/Rakefile +14 -0
- data/awesome_print_lite.gemspec +27 -0
- data/lib/awesome_print_lite.rb +20 -0
- data/lib/awesome_print_lite/core_ext/array.rb +81 -0
- data/lib/awesome_print_lite/core_ext/class.rb +22 -0
- data/lib/awesome_print_lite/core_ext/kernel.rb +26 -0
- data/lib/awesome_print_lite/core_ext/logger.rb +20 -0
- data/lib/awesome_print_lite/core_ext/method.rb +21 -0
- data/lib/awesome_print_lite/core_ext/object.rb +22 -0
- data/lib/awesome_print_lite/core_ext/string.rb +32 -0
- data/lib/awesome_print_lite/formatter.rb +410 -0
- data/lib/awesome_print_lite/inspector.rb +174 -0
- data/lib/awesome_print_lite/version.rb +3 -0
- data/spec/colors_spec.rb +106 -0
- data/spec/core_ext/string_spec.rb +20 -0
- data/spec/formats_spec.rb +725 -0
- data/spec/methods_spec.rb +459 -0
- data/spec/misc_spec.rb +238 -0
- data/spec/objects_spec.rb +129 -0
- data/spec/spec_helper.rb +55 -0
- metadata +145 -0
@@ -0,0 +1,174 @@
|
|
1
|
+
# Copyright (c) 2010-2013 Michael Dvorkin
|
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 AwesomePrintLite
|
7
|
+
|
8
|
+
class << self # Class accessors for custom defaults.
|
9
|
+
attr_accessor :defaults, :force_colors
|
10
|
+
|
11
|
+
# Class accessor to force colorized output (ex. forked subprocess where TERM
|
12
|
+
# might be dumb).
|
13
|
+
#------------------------------------------------------------------------------
|
14
|
+
def force_colors!(value = true)
|
15
|
+
@force_colors = value
|
16
|
+
end
|
17
|
+
|
18
|
+
def console?
|
19
|
+
!!(defined?(IRB) || defined?(Pry)|| defined?(OpalIrb))
|
20
|
+
end
|
21
|
+
|
22
|
+
def rails_console?
|
23
|
+
console? && !!(defined?(Rails::Console) || ENV["RAILS_ENV"])
|
24
|
+
end
|
25
|
+
=begin
|
26
|
+
def irb!
|
27
|
+
return unless defined?(IRB)
|
28
|
+
unless IRB.version.include?("DietRB")
|
29
|
+
IRB::Irb.class_eval do
|
30
|
+
def output_value
|
31
|
+
ap @context.last_value
|
32
|
+
end
|
33
|
+
end
|
34
|
+
else # MacRuby
|
35
|
+
IRB.formatter = Class.new(IRB::Formatter) do
|
36
|
+
def inspect_object(object)
|
37
|
+
object.ai
|
38
|
+
end
|
39
|
+
end.new
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def pry!
|
44
|
+
if defined?(Pry)
|
45
|
+
Pry.print = proc { |output, value| output.puts value.ai }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
=end
|
49
|
+
end
|
50
|
+
|
51
|
+
class Inspector
|
52
|
+
attr_accessor :options
|
53
|
+
|
54
|
+
AP = :__awesome_print__
|
55
|
+
|
56
|
+
def initialize(options = {})
|
57
|
+
@options = {
|
58
|
+
:indent => 4, # Indent using 4 spaces.
|
59
|
+
:index => true, # Display array indices.
|
60
|
+
:html => false, # Use ANSI color codes rather than HTML.
|
61
|
+
:multiline => true, # Display in multiple lines.
|
62
|
+
:plain => false, # Use colors.
|
63
|
+
:raw => false, # Do not recursively format object instance variables.
|
64
|
+
:sort_keys => false, # Do not sort hash keys.
|
65
|
+
:limit => false, # Limit large output for arrays and hashes. Set to a boolean or integer.
|
66
|
+
:color => {
|
67
|
+
:args => :pale,
|
68
|
+
:array => :white,
|
69
|
+
:bigdecimal => :blue,
|
70
|
+
:class => :yellow,
|
71
|
+
:date => :greenish,
|
72
|
+
:falseclass => :red,
|
73
|
+
:fixnum => :blue,
|
74
|
+
:float => :blue,
|
75
|
+
:hash => :pale,
|
76
|
+
:keyword => :cyan,
|
77
|
+
:method => :purpleish,
|
78
|
+
:nilclass => :red,
|
79
|
+
:rational => :blue,
|
80
|
+
:string => :yellowish,
|
81
|
+
:struct => :pale,
|
82
|
+
:symbol => :cyanish,
|
83
|
+
:time => :greenish,
|
84
|
+
:trueclass => :green,
|
85
|
+
:variable => :cyanish
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
# Merge custom defaults and let explicit options parameter override them.
|
90
|
+
if RUBY_ENGINE != 'opal'
|
91
|
+
merge_custom_defaults!
|
92
|
+
end
|
93
|
+
merge_options!(options)
|
94
|
+
|
95
|
+
@formatter = AwesomePrintLite::Formatter.new(self)
|
96
|
+
@ap ||= []
|
97
|
+
end
|
98
|
+
|
99
|
+
# Dispatcher that detects data nesting and invokes object-aware formatter.
|
100
|
+
#------------------------------------------------------------------------------
|
101
|
+
def awesome(object)
|
102
|
+
if @ap.include?(object.object_id)
|
103
|
+
nested(object)
|
104
|
+
else
|
105
|
+
begin
|
106
|
+
@ap << object.object_id
|
107
|
+
unnested(object)
|
108
|
+
ensure
|
109
|
+
@ap.pop
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Return true if we are to colorize the output.
|
115
|
+
#------------------------------------------------------------------------------
|
116
|
+
def colorize?
|
117
|
+
AwesomePrintLite.force_colors ||= false
|
118
|
+
AwesomePrintLite.force_colors || (STDOUT.tty? && ((ENV['TERM'] && ENV['TERM'] != 'dumb') || ENV['ANSICON']))
|
119
|
+
end
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
# Format nested data, for example:
|
124
|
+
# arr = [1, 2]; arr << arr
|
125
|
+
# => [1,2, [...]]
|
126
|
+
# hash = { :a => 1 }; hash[:b] = hash
|
127
|
+
# => { :a => 1, :b => {...} }
|
128
|
+
#------------------------------------------------------------------------------
|
129
|
+
def nested(object)
|
130
|
+
case printable(object)
|
131
|
+
when :array then @formatter.colorize("[...]", :array)
|
132
|
+
when :hash then @formatter.colorize("{...}", :hash)
|
133
|
+
when :struct then @formatter.colorize("{...}", :struct)
|
134
|
+
else @formatter.colorize("...#{object.class}...", :class)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
#------------------------------------------------------------------------------
|
139
|
+
def unnested(object)
|
140
|
+
@formatter.format(object, printable(object))
|
141
|
+
end
|
142
|
+
|
143
|
+
# Turn class name into symbol, ex: Hello::World => :hello_world. Classes that
|
144
|
+
# inherit from Array, Hash, File, Dir, and Struct are treated as the base class.
|
145
|
+
#------------------------------------------------------------------------------
|
146
|
+
def printable(object)
|
147
|
+
case object
|
148
|
+
when Array then :array
|
149
|
+
when Hash then :hash
|
150
|
+
when File then :file
|
151
|
+
when Dir then :dir
|
152
|
+
when Struct then :struct
|
153
|
+
else object.class.to_s.gsub(/:+/, "_").downcase.to_sym
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# Update @options by first merging the :color hash and then the remaining keys.
|
158
|
+
#------------------------------------------------------------------------------
|
159
|
+
def merge_options!(options = {})
|
160
|
+
@options[:color].merge!(options.delete(:color) || {})
|
161
|
+
@options.merge!(options)
|
162
|
+
end
|
163
|
+
|
164
|
+
# Load ~/.aprc file with custom defaults that override default options.
|
165
|
+
#------------------------------------------------------------------------------
|
166
|
+
def merge_custom_defaults!
|
167
|
+
dotfile = File.join(ENV["HOME"], ".aprc")
|
168
|
+
load dotfile if File.readable?(dotfile)
|
169
|
+
merge_options!(AwesomePrintLite.defaults) if AwesomePrintLite.defaults.is_a?(Hash)
|
170
|
+
rescue => e
|
171
|
+
$stderr.puts "Could not load #{dotfile}: #{e}"
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
data/spec/colors_spec.rb
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe "AwesomePrint" do
|
4
|
+
def stub_tty!(output = true, stream = STDOUT)
|
5
|
+
if output
|
6
|
+
stream.instance_eval { def tty?; true; end }
|
7
|
+
else
|
8
|
+
stream.instance_eval { def tty?; false; end }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
before do
|
13
|
+
stub_dotfile!
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "colorization" do
|
17
|
+
PLAIN = '[ 1, :two, "three", [ nil, [ true, false ] ] ]'
|
18
|
+
COLORIZED = "[ \e[1;34m1\e[0m, \e[0;36m:two\e[0m, \e[0;33m\"three\"\e[0m, [ \e[1;31mnil\e[0m, [ \e[1;32mtrue\e[0m, \e[1;31mfalse\e[0m ] ] ]"
|
19
|
+
|
20
|
+
before do
|
21
|
+
ENV['TERM'] = "xterm-colors"
|
22
|
+
ENV.delete('ANSICON')
|
23
|
+
@arr = [ 1, :two, "three", [ nil, [ true, false] ] ]
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "default settings (no forced colors)" do
|
27
|
+
before do
|
28
|
+
AwesomePrintLite.force_colors! false
|
29
|
+
end
|
30
|
+
|
31
|
+
it "colorizes tty processes by default" do
|
32
|
+
stub_tty!
|
33
|
+
expect(@arr.ai(:multiline => false)).to eq(COLORIZED)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "colorizes processes with ENV['ANSICON'] by default" do
|
37
|
+
begin
|
38
|
+
stub_tty!
|
39
|
+
term, ENV['ANSICON'] = ENV['ANSICON'], "1"
|
40
|
+
expect(@arr.ai(:multiline => false)).to eq(COLORIZED)
|
41
|
+
ensure
|
42
|
+
ENV['ANSICON'] = term
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
it "does not colorize tty processes running in dumb terminals by default" do
|
47
|
+
begin
|
48
|
+
stub_tty!
|
49
|
+
term, ENV['TERM'] = ENV['TERM'], "dumb"
|
50
|
+
expect(@arr.ai(:multiline => false)).to eq(PLAIN)
|
51
|
+
ensure
|
52
|
+
ENV['TERM'] = term
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
it "does not colorize subprocesses by default" do
|
57
|
+
begin
|
58
|
+
stub_tty! false
|
59
|
+
expect(@arr.ai(:multiline => false)).to eq(PLAIN)
|
60
|
+
ensure
|
61
|
+
stub_tty!
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "forced colors override" do
|
67
|
+
before do
|
68
|
+
AwesomePrintLite.force_colors!
|
69
|
+
end
|
70
|
+
|
71
|
+
it "still colorizes tty processes" do
|
72
|
+
stub_tty!
|
73
|
+
expect(@arr.ai(:multiline => false)).to eq(COLORIZED)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "colorizes processes with ENV['ANSICON'] set to 0" do
|
77
|
+
begin
|
78
|
+
stub_tty!
|
79
|
+
term, ENV['ANSICON'] = ENV['ANSICON'], "1"
|
80
|
+
expect(@arr.ai(:multiline => false)).to eq(COLORIZED)
|
81
|
+
ensure
|
82
|
+
ENV['ANSICON'] = term
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
it "colorizes dumb terminals" do
|
87
|
+
begin
|
88
|
+
stub_tty!
|
89
|
+
term, ENV['TERM'] = ENV['TERM'], "dumb"
|
90
|
+
expect(@arr.ai(:multiline => false)).to eq(COLORIZED)
|
91
|
+
ensure
|
92
|
+
ENV['TERM'] = term
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
it "colorizes subprocess" do
|
97
|
+
begin
|
98
|
+
stub_tty! false
|
99
|
+
expect(@arr.ai(:multiline => false)).to eq(COLORIZED)
|
100
|
+
ensure
|
101
|
+
stub_tty!
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe "String extensions" do
|
4
|
+
[ :gray, :red, :green, :yellow, :blue, :purple, :cyan, :white ].each_with_index do |color, i|
|
5
|
+
it "should have #{color} color" do
|
6
|
+
expect(color.to_s.send(color)).to eq("\e[1;#{30+i}m#{color}\e[0m")
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should have #{color}ish color" do
|
10
|
+
expect(color.to_s.send(:"#{color}ish")).to eq("\e[0;#{30+i}m#{color}\e[0m")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should have black and pale colors" do
|
15
|
+
expect("black".send(:black)).to eq("black".send(:grayish))
|
16
|
+
expect("pale".send(:pale)).to eq("pale".send(:whiteish))
|
17
|
+
expect("pale".send(:pale)).to eq("\e[0;37mpale\e[0m")
|
18
|
+
expect("whiteish".send(:whiteish)).to eq("\e[0;37mwhiteish\e[0m")
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,725 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require "set"
|
3
|
+
|
4
|
+
RSpec.describe "AwesomePrint" do
|
5
|
+
before do
|
6
|
+
stub_dotfile!
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "Array" do
|
10
|
+
before do
|
11
|
+
@arr = [ 1, :two, "three", [ nil, [ true, false] ] ]
|
12
|
+
end
|
13
|
+
|
14
|
+
it "empty array" do
|
15
|
+
expect([].ai).to eq("[]")
|
16
|
+
end
|
17
|
+
|
18
|
+
it "plain multiline" do
|
19
|
+
expect(@arr.ai(:plain => true)).to eq <<-EOS.strip
|
20
|
+
[
|
21
|
+
[0] 1,
|
22
|
+
[1] :two,
|
23
|
+
[2] "three",
|
24
|
+
[3] [
|
25
|
+
[0] nil,
|
26
|
+
[1] [
|
27
|
+
[0] true,
|
28
|
+
[1] false
|
29
|
+
]
|
30
|
+
]
|
31
|
+
]
|
32
|
+
EOS
|
33
|
+
end
|
34
|
+
|
35
|
+
it "plain multiline without index" do
|
36
|
+
expect(@arr.ai(:plain => true, :index => false)).to eq <<-EOS.strip
|
37
|
+
[
|
38
|
+
1,
|
39
|
+
:two,
|
40
|
+
"three",
|
41
|
+
[
|
42
|
+
nil,
|
43
|
+
[
|
44
|
+
true,
|
45
|
+
false
|
46
|
+
]
|
47
|
+
]
|
48
|
+
]
|
49
|
+
EOS
|
50
|
+
end
|
51
|
+
|
52
|
+
it "plain multiline indented" do
|
53
|
+
expect(@arr.ai(:plain => true, :indent => 2)).to eq <<-EOS.strip
|
54
|
+
[
|
55
|
+
[0] 1,
|
56
|
+
[1] :two,
|
57
|
+
[2] "three",
|
58
|
+
[3] [
|
59
|
+
[0] nil,
|
60
|
+
[1] [
|
61
|
+
[0] true,
|
62
|
+
[1] false
|
63
|
+
]
|
64
|
+
]
|
65
|
+
]
|
66
|
+
EOS
|
67
|
+
end
|
68
|
+
|
69
|
+
it "plain multiline indented without index" do
|
70
|
+
expect(@arr.ai(:plain => true, :indent => 2, :index => false)).to eq <<-EOS.strip
|
71
|
+
[
|
72
|
+
1,
|
73
|
+
:two,
|
74
|
+
"three",
|
75
|
+
[
|
76
|
+
nil,
|
77
|
+
[
|
78
|
+
true,
|
79
|
+
false
|
80
|
+
]
|
81
|
+
]
|
82
|
+
]
|
83
|
+
EOS
|
84
|
+
end
|
85
|
+
|
86
|
+
it "plain single line" do
|
87
|
+
expect(@arr.ai(:plain => true, :multiline => false)).to eq('[ 1, :two, "three", [ nil, [ true, false ] ] ]')
|
88
|
+
end
|
89
|
+
|
90
|
+
it "colored multiline (default)" do
|
91
|
+
expect(@arr.ai).to eq <<-EOS.strip
|
92
|
+
[
|
93
|
+
\e[1;37m[0] \e[0m\e[1;34m1\e[0m,
|
94
|
+
\e[1;37m[1] \e[0m\e[0;36m:two\e[0m,
|
95
|
+
\e[1;37m[2] \e[0m\e[0;33m\"three\"\e[0m,
|
96
|
+
\e[1;37m[3] \e[0m[
|
97
|
+
\e[1;37m[0] \e[0m\e[1;31mnil\e[0m,
|
98
|
+
\e[1;37m[1] \e[0m[
|
99
|
+
\e[1;37m[0] \e[0m\e[1;32mtrue\e[0m,
|
100
|
+
\e[1;37m[1] \e[0m\e[1;31mfalse\e[0m
|
101
|
+
]
|
102
|
+
]
|
103
|
+
]
|
104
|
+
EOS
|
105
|
+
end
|
106
|
+
|
107
|
+
it "colored multiline indented" do
|
108
|
+
expect(@arr.ai(:indent => 8)).to eq <<-EOS.strip
|
109
|
+
[
|
110
|
+
\e[1;37m[0] \e[0m\e[1;34m1\e[0m,
|
111
|
+
\e[1;37m[1] \e[0m\e[0;36m:two\e[0m,
|
112
|
+
\e[1;37m[2] \e[0m\e[0;33m\"three\"\e[0m,
|
113
|
+
\e[1;37m[3] \e[0m[
|
114
|
+
\e[1;37m[0] \e[0m\e[1;31mnil\e[0m,
|
115
|
+
\e[1;37m[1] \e[0m[
|
116
|
+
\e[1;37m[0] \e[0m\e[1;32mtrue\e[0m,
|
117
|
+
\e[1;37m[1] \e[0m\e[1;31mfalse\e[0m
|
118
|
+
]
|
119
|
+
]
|
120
|
+
]
|
121
|
+
EOS
|
122
|
+
end
|
123
|
+
|
124
|
+
it "colored single line" do
|
125
|
+
expect(@arr.ai(:multiline => false)).to eq("[ \e[1;34m1\e[0m, \e[0;36m:two\e[0m, \e[0;33m\"three\"\e[0m, [ \e[1;31mnil\e[0m, [ \e[1;32mtrue\e[0m, \e[1;31mfalse\e[0m ] ] ]")
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
#------------------------------------------------------------------------------
|
130
|
+
describe "Nested Array" do
|
131
|
+
before do
|
132
|
+
@arr = [ 1, 2 ]
|
133
|
+
@arr << @arr
|
134
|
+
end
|
135
|
+
|
136
|
+
it "plain multiline" do
|
137
|
+
expect(@arr.ai(:plain => true)).to eq <<-EOS.strip
|
138
|
+
[
|
139
|
+
[0] 1,
|
140
|
+
[1] 2,
|
141
|
+
[2] [...]
|
142
|
+
]
|
143
|
+
EOS
|
144
|
+
end
|
145
|
+
|
146
|
+
it "plain multiline without index" do
|
147
|
+
expect(@arr.ai(:plain => true, :index => false)).to eq <<-EOS.strip
|
148
|
+
[
|
149
|
+
1,
|
150
|
+
2,
|
151
|
+
[...]
|
152
|
+
]
|
153
|
+
EOS
|
154
|
+
end
|
155
|
+
|
156
|
+
it "plain single line" do
|
157
|
+
expect(@arr.ai(:plain => true, :multiline => false)).to eq("[ 1, 2, [...] ]")
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
#------------------------------------------------------------------------------
|
162
|
+
describe "Limited Output Array" do
|
163
|
+
before(:each) do
|
164
|
+
@arr = (1..1000).to_a
|
165
|
+
end
|
166
|
+
|
167
|
+
it "plain limited output large" do
|
168
|
+
expect(@arr.ai(:plain => true, :limit => true)).to eq <<-EOS.strip
|
169
|
+
[
|
170
|
+
[ 0] 1,
|
171
|
+
[ 1] 2,
|
172
|
+
[ 2] 3,
|
173
|
+
[ 3] .. [996],
|
174
|
+
[997] 998,
|
175
|
+
[998] 999,
|
176
|
+
[999] 1000
|
177
|
+
]
|
178
|
+
EOS
|
179
|
+
end
|
180
|
+
|
181
|
+
it "plain limited output small" do
|
182
|
+
@arr = @arr[0..3]
|
183
|
+
expect(@arr.ai(:plain => true, :limit => true)).to eq <<-EOS.strip
|
184
|
+
[
|
185
|
+
[0] 1,
|
186
|
+
[1] 2,
|
187
|
+
[2] 3,
|
188
|
+
[3] 4
|
189
|
+
]
|
190
|
+
EOS
|
191
|
+
end
|
192
|
+
|
193
|
+
it "plain limited output with 10 lines" do
|
194
|
+
expect(@arr.ai(:plain => true, :limit => 10)).to eq <<-EOS.strip
|
195
|
+
[
|
196
|
+
[ 0] 1,
|
197
|
+
[ 1] 2,
|
198
|
+
[ 2] 3,
|
199
|
+
[ 3] 4,
|
200
|
+
[ 4] 5,
|
201
|
+
[ 5] .. [995],
|
202
|
+
[996] 997,
|
203
|
+
[997] 998,
|
204
|
+
[998] 999,
|
205
|
+
[999] 1000
|
206
|
+
]
|
207
|
+
EOS
|
208
|
+
end
|
209
|
+
|
210
|
+
it "plain limited output with 11 lines" do
|
211
|
+
expect(@arr.ai(:plain => true, :limit => 11)).to eq <<-EOS.strip
|
212
|
+
[
|
213
|
+
[ 0] 1,
|
214
|
+
[ 1] 2,
|
215
|
+
[ 2] 3,
|
216
|
+
[ 3] 4,
|
217
|
+
[ 4] 5,
|
218
|
+
[ 5] .. [994],
|
219
|
+
[995] 996,
|
220
|
+
[996] 997,
|
221
|
+
[997] 998,
|
222
|
+
[998] 999,
|
223
|
+
[999] 1000
|
224
|
+
]
|
225
|
+
EOS
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
#------------------------------------------------------------------------------
|
230
|
+
describe "Limited Output Hash" do
|
231
|
+
before(:each) do
|
232
|
+
@hash = ("a".."z").inject({}) { |h, v| h.merge({ v => v.to_sym }) }
|
233
|
+
end
|
234
|
+
|
235
|
+
it "plain limited output" do
|
236
|
+
expect(@hash.ai(:sort_keys => true, :plain => true, :limit => true)).to eq <<-EOS.strip
|
237
|
+
{
|
238
|
+
"a" => :a,
|
239
|
+
"b" => :b,
|
240
|
+
"c" => :c,
|
241
|
+
"d" => :d .. "w" => :w,
|
242
|
+
"x" => :x,
|
243
|
+
"y" => :y,
|
244
|
+
"z" => :z
|
245
|
+
}
|
246
|
+
EOS
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
#------------------------------------------------------------------------------
|
251
|
+
describe "Hash" do
|
252
|
+
before do
|
253
|
+
@hash = { 1 => { :sym => { "str" => { [1, 2, 3] => { { :k => :v } => Hash } } } } }
|
254
|
+
end
|
255
|
+
|
256
|
+
it "empty hash" do
|
257
|
+
expect({}.ai).to eq("{}")
|
258
|
+
end
|
259
|
+
|
260
|
+
it "plain multiline" do
|
261
|
+
expect(@hash.ai(:plain => true)).to eq <<-EOS.strip
|
262
|
+
{
|
263
|
+
1 => {
|
264
|
+
:sym => {
|
265
|
+
"str" => {
|
266
|
+
[ 1, 2, 3 ] => {
|
267
|
+
{ :k => :v } => Hash < Object
|
268
|
+
}
|
269
|
+
}
|
270
|
+
}
|
271
|
+
}
|
272
|
+
}
|
273
|
+
EOS
|
274
|
+
end
|
275
|
+
|
276
|
+
it "plain multiline indented" do
|
277
|
+
expect(@hash.ai(:plain => true, :indent => 1)).to eq <<-EOS.strip
|
278
|
+
{
|
279
|
+
1 => {
|
280
|
+
:sym => {
|
281
|
+
"str" => {
|
282
|
+
[ 1, 2, 3 ] => {
|
283
|
+
{ :k => :v } => Hash < Object
|
284
|
+
}
|
285
|
+
}
|
286
|
+
}
|
287
|
+
}
|
288
|
+
}
|
289
|
+
EOS
|
290
|
+
end
|
291
|
+
|
292
|
+
it "plain single line" do
|
293
|
+
expect(@hash.ai(:plain => true, :multiline => false)).to eq('{ 1 => { :sym => { "str" => { [ 1, 2, 3 ] => { { :k => :v } => Hash < Object } } } } }')
|
294
|
+
end
|
295
|
+
|
296
|
+
it "colored multiline (default)" do
|
297
|
+
expect(@hash.ai).to eq <<-EOS.strip
|
298
|
+
{
|
299
|
+
1\e[0;37m => \e[0m{
|
300
|
+
:sym\e[0;37m => \e[0m{
|
301
|
+
\"str\"\e[0;37m => \e[0m{
|
302
|
+
[ 1, 2, 3 ]\e[0;37m => \e[0m{
|
303
|
+
{ :k => :v }\e[0;37m => \e[0m\e[1;33mHash < Object\e[0m
|
304
|
+
}
|
305
|
+
}
|
306
|
+
}
|
307
|
+
}
|
308
|
+
}
|
309
|
+
EOS
|
310
|
+
end
|
311
|
+
|
312
|
+
it "colored multiline indented" do
|
313
|
+
expect(@hash.ai(:indent => 2)).to eq <<-EOS.strip
|
314
|
+
{
|
315
|
+
1\e[0;37m => \e[0m{
|
316
|
+
:sym\e[0;37m => \e[0m{
|
317
|
+
\"str\"\e[0;37m => \e[0m{
|
318
|
+
[ 1, 2, 3 ]\e[0;37m => \e[0m{
|
319
|
+
{ :k => :v }\e[0;37m => \e[0m\e[1;33mHash < Object\e[0m
|
320
|
+
}
|
321
|
+
}
|
322
|
+
}
|
323
|
+
}
|
324
|
+
}
|
325
|
+
EOS
|
326
|
+
end
|
327
|
+
|
328
|
+
it "colored single line" do
|
329
|
+
expect(@hash.ai(:multiline => false)).to eq("{ 1\e[0;37m => \e[0m{ :sym\e[0;37m => \e[0m{ \"str\"\e[0;37m => \e[0m{ [ 1, 2, 3 ]\e[0;37m => \e[0m{ { :k => :v }\e[0;37m => \e[0m\e[1;33mHash < Object\e[0m } } } } }")
|
330
|
+
end
|
331
|
+
|
332
|
+
end
|
333
|
+
|
334
|
+
#------------------------------------------------------------------------------
|
335
|
+
describe "Nested Hash" do
|
336
|
+
before do
|
337
|
+
@hash = {}
|
338
|
+
@hash[:a] = @hash
|
339
|
+
end
|
340
|
+
|
341
|
+
it "plain multiline" do
|
342
|
+
expect(@hash.ai(:plain => true)).to eq <<-EOS.strip
|
343
|
+
{
|
344
|
+
:a => {...}
|
345
|
+
}
|
346
|
+
EOS
|
347
|
+
end
|
348
|
+
|
349
|
+
it "plain single line" do
|
350
|
+
expect(@hash.ai(:plain => true, :multiline => false)).to eq('{ :a => {...} }')
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
#------------------------------------------------------------------------------
|
355
|
+
describe "Hash with several keys" do
|
356
|
+
before do
|
357
|
+
@hash = {"b" => "b", :a => "a", :z => "z", "alpha" => "alpha"}
|
358
|
+
end
|
359
|
+
|
360
|
+
it "plain multiline" do
|
361
|
+
out = @hash.ai(:plain => true)
|
362
|
+
if RUBY_VERSION.to_f < 1.9 # Order of @hash keys is not guaranteed.
|
363
|
+
expect(out).to match(/^\{[^\}]+\}/m)
|
364
|
+
expect(out).to match(/ "b" => "b",?/)
|
365
|
+
expect(out).to match(/ :a => "a",?/)
|
366
|
+
expect(out).to match(/ :z => "z",?/)
|
367
|
+
expect(out).to match(/ "alpha" => "alpha",?$/)
|
368
|
+
else
|
369
|
+
expect(out).to eq <<-EOS.strip
|
370
|
+
{
|
371
|
+
"b" => "b",
|
372
|
+
:a => "a",
|
373
|
+
:z => "z",
|
374
|
+
"alpha" => "alpha"
|
375
|
+
}
|
376
|
+
EOS
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
it "plain multiline with sorted keys" do
|
381
|
+
expect(@hash.ai(:plain => true, :sort_keys => true)).to eq <<-EOS.strip
|
382
|
+
{
|
383
|
+
:a => "a",
|
384
|
+
"alpha" => "alpha",
|
385
|
+
"b" => "b",
|
386
|
+
:z => "z"
|
387
|
+
}
|
388
|
+
EOS
|
389
|
+
end
|
390
|
+
|
391
|
+
end
|
392
|
+
|
393
|
+
#------------------------------------------------------------------------------
|
394
|
+
describe "Negative options[:indent]" do
|
395
|
+
#
|
396
|
+
# With Ruby < 1.9 the order of hash keys is not defined so we can't
|
397
|
+
# reliably compare the output string.
|
398
|
+
#
|
399
|
+
it "hash keys must be left aligned" do
|
400
|
+
hash = { [0, 0, 255] => :yellow, :red => "rgb(255, 0, 0)", "magenta" => "rgb(255, 0, 255)" }
|
401
|
+
out = hash.ai(:plain => true, :indent => -4, :sort_keys => true)
|
402
|
+
expect(out).to eq <<-EOS.strip
|
403
|
+
{
|
404
|
+
[ 0, 0, 255 ] => :yellow,
|
405
|
+
"magenta" => "rgb(255, 0, 255)",
|
406
|
+
:red => "rgb(255, 0, 0)"
|
407
|
+
}
|
408
|
+
EOS
|
409
|
+
end
|
410
|
+
|
411
|
+
it "nested hash keys should be indented (array of hashes)" do
|
412
|
+
arr = [ { :a => 1, :bb => 22, :ccc => 333}, { 1 => :a, 22 => :bb, 333 => :ccc} ]
|
413
|
+
out = arr.ai(:plain => true, :indent => -4, :sort_keys => true)
|
414
|
+
expect(out).to eq <<-EOS.strip
|
415
|
+
[
|
416
|
+
[0] {
|
417
|
+
:a => 1,
|
418
|
+
:bb => 22,
|
419
|
+
:ccc => 333
|
420
|
+
},
|
421
|
+
[1] {
|
422
|
+
1 => :a,
|
423
|
+
22 => :bb,
|
424
|
+
333 => :ccc
|
425
|
+
}
|
426
|
+
]
|
427
|
+
EOS
|
428
|
+
end
|
429
|
+
|
430
|
+
it "nested hash keys should be indented (hash of hashes)" do
|
431
|
+
arr = { :first => { :a => 1, :bb => 22, :ccc => 333}, :second => { 1 => :a, 22 => :bb, 333 => :ccc} }
|
432
|
+
out = arr.ai(:plain => true, :indent => -4, :sort_keys => true)
|
433
|
+
expect(out).to eq <<-EOS.strip
|
434
|
+
{
|
435
|
+
:first => {
|
436
|
+
:a => 1,
|
437
|
+
:bb => 22,
|
438
|
+
:ccc => 333
|
439
|
+
},
|
440
|
+
:second => {
|
441
|
+
1 => :a,
|
442
|
+
22 => :bb,
|
443
|
+
333 => :ccc
|
444
|
+
}
|
445
|
+
}
|
446
|
+
EOS
|
447
|
+
end
|
448
|
+
end
|
449
|
+
|
450
|
+
#------------------------------------------------------------------------------
|
451
|
+
describe "Class" do
|
452
|
+
it "shoud show superclass (plain)" do
|
453
|
+
expect(self.class.ai(:plain => true)).to eq("#{self.class} < #{self.class.superclass}")
|
454
|
+
end
|
455
|
+
|
456
|
+
it "shoud show superclass (color)" do
|
457
|
+
expect(self.class.ai).to eq("#{self.class} < #{self.class.superclass}".yellow)
|
458
|
+
end
|
459
|
+
end
|
460
|
+
|
461
|
+
#------------------------------------------------------------------------------
|
462
|
+
describe "Rational" do
|
463
|
+
|
464
|
+
it "should present Rational object with arbitrary precision" do
|
465
|
+
rat = Rational(201020102010201020102010201020102010, 2)
|
466
|
+
out = rat.ai(:plain => true)
|
467
|
+
#
|
468
|
+
# Ruby 1.9 slightly changed the format of Rational#to_s, see
|
469
|
+
# http://techtime.getharvest.com/blog/harvest-is-now-on-ruby-1-dot-9-3 and
|
470
|
+
# http://www.ruby-forum.com/topic/189397
|
471
|
+
#
|
472
|
+
if RUBY_VERSION < "1.9"
|
473
|
+
expect(out).to eq("100510051005100510051005100510051005")
|
474
|
+
else
|
475
|
+
expect(out).to eq("100510051005100510051005100510051005/1")
|
476
|
+
end
|
477
|
+
end
|
478
|
+
end
|
479
|
+
|
480
|
+
#------------------------------------------------------------------------------
|
481
|
+
describe "Utility methods" do
|
482
|
+
it "should merge options" do
|
483
|
+
ap = AwesomePrintLite::Inspector.new
|
484
|
+
ap.send(:merge_options!, { :color => { :array => :black }, :indent => 0 })
|
485
|
+
options = ap.instance_variable_get("@options")
|
486
|
+
expect(options[:color][:array]).to eq(:black)
|
487
|
+
expect(options[:indent]).to eq(0)
|
488
|
+
end
|
489
|
+
end
|
490
|
+
|
491
|
+
#------------------------------------------------------------------------------
|
492
|
+
describe "Set" do
|
493
|
+
before do
|
494
|
+
@arr = [1, :two, "three" ]
|
495
|
+
@set = Set.new(@arr)
|
496
|
+
end
|
497
|
+
|
498
|
+
it "empty set" do
|
499
|
+
expect(Set.new.ai).to eq([].ai)
|
500
|
+
end
|
501
|
+
|
502
|
+
if RUBY_VERSION > "1.9"
|
503
|
+
it "plain multiline" do
|
504
|
+
expect(@set.ai(:plain => true)).to eq(@arr.ai(:plain => true))
|
505
|
+
end
|
506
|
+
|
507
|
+
it "plain multiline indented" do
|
508
|
+
expect(@set.ai(:plain => true, :indent => 1)).to eq(@arr.ai(:plain => true, :indent => 1))
|
509
|
+
end
|
510
|
+
|
511
|
+
it "plain single line" do
|
512
|
+
expect(@set.ai(:plain => true, :multiline => false)).to eq(@arr.ai(:plain => true, :multiline => false))
|
513
|
+
end
|
514
|
+
|
515
|
+
it "colored multiline (default)" do
|
516
|
+
expect(@set.ai).to eq(@arr.ai)
|
517
|
+
end
|
518
|
+
else # Prior to Ruby 1.9 the order of set values is unpredicatble.
|
519
|
+
it "plain multiline" do
|
520
|
+
expect(@set.sort_by{ |x| x.to_s }.ai(:plain => true)).to eq(@arr.sort_by{ |x| x.to_s }.ai(:plain => true))
|
521
|
+
end
|
522
|
+
|
523
|
+
it "plain multiline indented" do
|
524
|
+
expect(@set.sort_by{ |x| x.to_s }.ai(:plain => true, :indent => 1)).to eq(@arr.sort_by{ |x| x.to_s }.ai(:plain => true, :indent => 1))
|
525
|
+
end
|
526
|
+
|
527
|
+
it "plain single line" do
|
528
|
+
expect(@set.sort_by{ |x| x.to_s }.ai(:plain => true, :multiline => false)).to eq(@arr.sort_by{ |x| x.to_s }.ai(:plain => true, :multiline => false))
|
529
|
+
end
|
530
|
+
|
531
|
+
it "colored multiline (default)" do
|
532
|
+
expect(@set.sort_by{ |x| x.to_s }.ai).to eq(@arr.sort_by{ |x| x.to_s }.ai)
|
533
|
+
end
|
534
|
+
end
|
535
|
+
end
|
536
|
+
|
537
|
+
#------------------------------------------------------------------------------
|
538
|
+
describe "Struct" do
|
539
|
+
before do
|
540
|
+
@struct = unless defined?(Struct::SimpleStruct)
|
541
|
+
Struct.new("SimpleStruct", :name, :address).new
|
542
|
+
else
|
543
|
+
Struct::SimpleStruct.new
|
544
|
+
end
|
545
|
+
@struct.name = "Herman Munster"
|
546
|
+
@struct.address = "1313 Mockingbird Lane"
|
547
|
+
end
|
548
|
+
|
549
|
+
it "empty struct" do
|
550
|
+
expect(Struct.new("EmptyStruct").ai).to eq("\e[1;33mStruct::EmptyStruct < Struct\e[0m")
|
551
|
+
end
|
552
|
+
|
553
|
+
it "plain multiline" do
|
554
|
+
s1 = <<-EOS.strip
|
555
|
+
{
|
556
|
+
:address => "1313 Mockingbird Lane",
|
557
|
+
:name => "Herman Munster"
|
558
|
+
}
|
559
|
+
EOS
|
560
|
+
s2 = <<-EOS.strip
|
561
|
+
{
|
562
|
+
:name => "Herman Munster",
|
563
|
+
:address => "1313 Mockingbird Lane"
|
564
|
+
}
|
565
|
+
EOS
|
566
|
+
expect(@struct.ai(:plain => true)).to satisfy { |match| match == s1 || match == s2 }
|
567
|
+
end
|
568
|
+
|
569
|
+
it "plain multiline indented" do
|
570
|
+
s1 = <<-EOS.strip
|
571
|
+
{
|
572
|
+
:address => "1313 Mockingbird Lane",
|
573
|
+
:name => "Herman Munster"
|
574
|
+
}
|
575
|
+
EOS
|
576
|
+
s2 = <<-EOS.strip
|
577
|
+
{
|
578
|
+
:name => "Herman Munster",
|
579
|
+
:address => "1313 Mockingbird Lane"
|
580
|
+
}
|
581
|
+
EOS
|
582
|
+
expect(@struct.ai(:plain => true, :indent => 1)).to satisfy { |match| match == s1 || match == s2 }
|
583
|
+
end
|
584
|
+
|
585
|
+
it "plain single line" do
|
586
|
+
s1 = "{ :address => \"1313 Mockingbird Lane\", :name => \"Herman Munster\" }"
|
587
|
+
s2 = "{ :name => \"Herman Munster\", :address => \"1313 Mockingbird Lane\" }"
|
588
|
+
expect(@struct.ai(:plain => true, :multiline => false)).to satisfy { |match| match == s1 || match == s2 }
|
589
|
+
end
|
590
|
+
|
591
|
+
it "colored multiline (default)" do
|
592
|
+
s1 = <<-EOS.strip
|
593
|
+
{
|
594
|
+
:address\e[0;37m => \e[0m\e[0;33m\"1313 Mockingbird Lane\"\e[0m,
|
595
|
+
:name\e[0;37m => \e[0m\e[0;33m\"Herman Munster\"\e[0m
|
596
|
+
}
|
597
|
+
EOS
|
598
|
+
s2 = <<-EOS.strip
|
599
|
+
{
|
600
|
+
:name\e[0;37m => \e[0m\e[0;33m\"Herman Munster\"\e[0m,
|
601
|
+
:address\e[0;37m => \e[0m\e[0;33m\"1313 Mockingbird Lane\"\e[0m
|
602
|
+
}
|
603
|
+
EOS
|
604
|
+
expect(@struct.ai).to satisfy { |match| match == s1 || match == s2 }
|
605
|
+
end
|
606
|
+
end
|
607
|
+
|
608
|
+
#------------------------------------------------------------------------------
|
609
|
+
describe "Inherited from standard Ruby classes" do
|
610
|
+
after do
|
611
|
+
Object.instance_eval{ remove_const :My } if defined?(My)
|
612
|
+
end
|
613
|
+
|
614
|
+
it "inherited from Array should be displayed as Array" do
|
615
|
+
class My < Array; end
|
616
|
+
|
617
|
+
my = My.new([ 1, :two, "three", [ nil, [ true, false ] ] ])
|
618
|
+
expect(my.ai(:plain => true)).to eq <<-EOS.strip
|
619
|
+
[
|
620
|
+
[0] 1,
|
621
|
+
[1] :two,
|
622
|
+
[2] "three",
|
623
|
+
[3] [
|
624
|
+
[0] nil,
|
625
|
+
[1] [
|
626
|
+
[0] true,
|
627
|
+
[1] false
|
628
|
+
]
|
629
|
+
]
|
630
|
+
]
|
631
|
+
EOS
|
632
|
+
end
|
633
|
+
|
634
|
+
it "inherited from Hash should be displayed as Hash" do
|
635
|
+
class My < Hash; end
|
636
|
+
|
637
|
+
my = My[ { 1 => { :sym => { "str" => { [1, 2, 3] => { { :k => :v } => Hash } } } } } ]
|
638
|
+
expect(my.ai(:plain => true)).to eq <<-EOS.strip
|
639
|
+
{
|
640
|
+
1 => {
|
641
|
+
:sym => {
|
642
|
+
"str" => {
|
643
|
+
[ 1, 2, 3 ] => {
|
644
|
+
{ :k => :v } => Hash < Object
|
645
|
+
}
|
646
|
+
}
|
647
|
+
}
|
648
|
+
}
|
649
|
+
}
|
650
|
+
EOS
|
651
|
+
end
|
652
|
+
|
653
|
+
|
654
|
+
it "should handle a class that defines its own #send method" do
|
655
|
+
class My
|
656
|
+
def send(arg1, arg2, arg3); end
|
657
|
+
end
|
658
|
+
|
659
|
+
my = My.new
|
660
|
+
expect { my.methods.ai(:plain => true) }.not_to raise_error
|
661
|
+
end
|
662
|
+
|
663
|
+
it "should handle a class defines its own #method method (ex. request.method)" do
|
664
|
+
class My
|
665
|
+
def method
|
666
|
+
'POST'
|
667
|
+
end
|
668
|
+
end
|
669
|
+
|
670
|
+
my = My.new
|
671
|
+
expect { my.methods.ai(:plain => true) }.not_to raise_error
|
672
|
+
end
|
673
|
+
|
674
|
+
describe "should handle a class that defines its own #to_hash method" do
|
675
|
+
it "that takes arguments" do
|
676
|
+
class My
|
677
|
+
def to_hash(a, b)
|
678
|
+
end
|
679
|
+
end
|
680
|
+
|
681
|
+
my = My.new
|
682
|
+
expect { my.ai(:plain => true) }.not_to raise_error
|
683
|
+
end
|
684
|
+
|
685
|
+
it "that returns nil" do
|
686
|
+
class My
|
687
|
+
def to_hash()
|
688
|
+
return nil
|
689
|
+
end
|
690
|
+
end
|
691
|
+
|
692
|
+
my = My.new
|
693
|
+
expect { my.ai(:plain => true) }.not_to raise_error
|
694
|
+
end
|
695
|
+
|
696
|
+
it "that returns an object that doesn't support #keys" do
|
697
|
+
class My
|
698
|
+
def to_hash()
|
699
|
+
object = Object.new
|
700
|
+
object.define_singleton_method('[]') { return nil }
|
701
|
+
|
702
|
+
return object
|
703
|
+
end
|
704
|
+
end
|
705
|
+
|
706
|
+
my = My.new
|
707
|
+
expect { my.ai(:plain => true) }.not_to raise_error
|
708
|
+
end
|
709
|
+
|
710
|
+
it "that returns an object that doesn't support subscripting" do
|
711
|
+
class My
|
712
|
+
def to_hash()
|
713
|
+
object = Object.new
|
714
|
+
object.define_singleton_method(:keys) { return [:foo] }
|
715
|
+
|
716
|
+
return object
|
717
|
+
end
|
718
|
+
end
|
719
|
+
|
720
|
+
my = My.new
|
721
|
+
expect { my.ai(:plain => true) }.not_to raise_error
|
722
|
+
end
|
723
|
+
end
|
724
|
+
end
|
725
|
+
end
|