awesome_print_lite 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|