awesome_print 0.2.1 → 0.4.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.
- data/CHANGELOG +28 -0
- data/LICENSE +2 -1
- data/README.md +105 -24
- data/Rakefile +7 -9
- data/VERSION +1 -1
- data/init.rb +1 -1
- data/lib/ap/awesome_print.rb +126 -26
- data/lib/ap/core_ext/array.rb +71 -0
- data/lib/ap/core_ext/class.rb +17 -0
- data/lib/ap/core_ext/kernel.rb +2 -1
- data/lib/ap/core_ext/logger.rb +2 -2
- data/lib/ap/core_ext/method.rb +21 -0
- data/lib/ap/core_ext/object.rb +17 -0
- data/lib/ap/core_ext/string.rb +9 -8
- data/lib/ap/mixin/action_view.rb +4 -25
- data/lib/ap/mixin/active_record.rb +11 -10
- data/lib/ap/mixin/active_support.rb +3 -1
- data/lib/ap/mixin/mongo_mapper.rb +54 -0
- data/lib/ap.rb +18 -9
- data/lib/awesome_print.rb +26 -0
- data/rails/init.rb +9 -1
- data/spec/action_view_spec.rb +16 -26
- data/spec/active_record_spec.rb +78 -60
- data/spec/awesome_print_spec.rb +216 -0
- data/spec/colorization_spec.rb +84 -0
- data/spec/logger_spec.rb +1 -1
- data/spec/methods_spec.rb +428 -0
- data/spec/mongo_mapper_spec.rb +63 -0
- data/spec/spec_helper.rb +44 -7
- metadata +28 -18
- data/spec/spec.opts +0 -1
data/CHANGELOG
CHANGED
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
0.4.0
|
|
2
|
+
- 'ap object' now returns the object (Stephan Hagemann)
|
|
3
|
+
- Added :html => true option to enable HTML colors rather that ANSI (ex. Sinatra templates)
|
|
4
|
+
- Added AwesomePrint.force_colors! to allow color output on demand (Andrew O'Brien)
|
|
5
|
+
- Added MongoMapper formatter mixin (Elpizo Choi)
|
|
6
|
+
- Fixed formatting of methods array when object#method is overridden
|
|
7
|
+
- Fixed potential stack errors by checking whether AwesomePrint is already loaded
|
|
8
|
+
- Improved Ruby 1.8.6 and 1.8.7 compatibility
|
|
9
|
+
- Improved Windows compatibility (Viktar Basharymau)
|
|
10
|
+
|
|
11
|
+
0.3.2
|
|
12
|
+
- Make sure Rails mixins get loaded in Rails console when required from .irbrc
|
|
13
|
+
- Fixed an issue with classes that define their own #send method (ex: Socket)
|
|
14
|
+
- Fixed compatibility issue with Liquid gem that defines Module#liquid_methods
|
|
15
|
+
- Fixed hash spec for Ruby < 1.9 where order of hash keys is not guaranteed
|
|
16
|
+
- Added :sorted_hash_keys option to sort hash keys (Ed Ruder)
|
|
17
|
+
|
|
18
|
+
0.3.1 RubyConf X edition
|
|
19
|
+
- Fixed Ruby 1.8.6 compatibility issues (thanks, Tim!)
|
|
20
|
+
- Fixed stack overflow issue with Rails 2.3.x console
|
|
21
|
+
|
|
22
|
+
0.3.0
|
|
23
|
+
- Display object.methods and family in human readable format
|
|
24
|
+
- Objects inherited from Array, Hash, File, Dir, and Struct are shown as their base class
|
|
25
|
+
- Added option to suppress array index in output (Sean Gallagher)
|
|
26
|
+
- Updated README on how to set up ~/.irbrc for MacRuby (Eloy Duran)
|
|
27
|
+
- Specs pass 100% with Ruby 1.8.7/RSpec 1.3 and Ruby 1.9.2/RSpec 2.0
|
|
28
|
+
|
|
1
29
|
0.2.1
|
|
2
30
|
- ap can now be used within Rails templates (ex. <%= ap object %>)
|
|
3
31
|
- Added support for printing Struct
|
data/LICENSE
CHANGED
data/README.md
CHANGED
|
@@ -8,21 +8,24 @@ objects and usage within Rails templates are supported via included mixins.
|
|
|
8
8
|
$ gem install awesome_print
|
|
9
9
|
|
|
10
10
|
# Installing as Rails plugin
|
|
11
|
-
$ ruby script/plugin install http://github.com/michaeldv/
|
|
11
|
+
$ ruby script/plugin install http://github.com/michaeldv/awesome_print.git
|
|
12
12
|
|
|
13
13
|
# Cloning the repository
|
|
14
|
-
$ git clone git://github.com/michaeldv/
|
|
14
|
+
$ git clone git://github.com/michaeldv/awesome_print.git
|
|
15
15
|
|
|
16
16
|
### Usage ###
|
|
17
17
|
|
|
18
|
-
require "
|
|
18
|
+
require "awesome_print"
|
|
19
19
|
ap object, options = {}
|
|
20
20
|
|
|
21
21
|
Default options:
|
|
22
22
|
|
|
23
|
-
:multiline => true,
|
|
24
|
-
:plain
|
|
25
|
-
:indent
|
|
23
|
+
:multiline => true, # Display in multiple lines.
|
|
24
|
+
:plain => false, # Use colors.
|
|
25
|
+
:indent => 4, # Indent using 4 spaces.
|
|
26
|
+
:index => true, # Display array indices.
|
|
27
|
+
:html => false, # Use ANSI color codes rather than HTML.
|
|
28
|
+
:sorted_hash_keys => false, # Do not sort hash keys.
|
|
26
29
|
:color => {
|
|
27
30
|
:array => :white,
|
|
28
31
|
:bignum => :blue,
|
|
@@ -46,7 +49,7 @@ Supported color names:
|
|
|
46
49
|
|
|
47
50
|
### Examples ###
|
|
48
51
|
$ cat > 1.rb
|
|
49
|
-
require "
|
|
52
|
+
require "awesome_print"
|
|
50
53
|
data = [ false, 42, %w(forty two), { :now => Time.now, :class => Time.now.class, :distance => 42e42 } ]
|
|
51
54
|
ap data
|
|
52
55
|
^D
|
|
@@ -66,7 +69,7 @@ Supported color names:
|
|
|
66
69
|
]
|
|
67
70
|
|
|
68
71
|
$ cat > 2.rb
|
|
69
|
-
require "
|
|
72
|
+
require "awesome_print"
|
|
70
73
|
data = { :now => Time.now, :class => Time.now.class, :distance => 42e42 }
|
|
71
74
|
ap data, :indent => -2 # <-- Left align hash keys.
|
|
72
75
|
^D
|
|
@@ -78,7 +81,7 @@ Supported color names:
|
|
|
78
81
|
}
|
|
79
82
|
|
|
80
83
|
$ cat > 3.rb
|
|
81
|
-
require "
|
|
84
|
+
require "awesome_print"
|
|
82
85
|
data = [ false, 42, %w(forty two) ]
|
|
83
86
|
data << data # <-- Nested array.
|
|
84
87
|
ap data, :multiline => false
|
|
@@ -86,10 +89,58 @@ Supported color names:
|
|
|
86
89
|
$ ruby 3.rb
|
|
87
90
|
[ false, 42, [ "forty", "two" ], [...] ]
|
|
88
91
|
|
|
92
|
+
$ cat > 4.rb
|
|
93
|
+
require "awesome_print"
|
|
94
|
+
class Hello
|
|
95
|
+
def self.world(x, y, z = nil, &blk)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
ap Hello.methods - Class.methods
|
|
99
|
+
^D
|
|
100
|
+
$ ruby 4.rb
|
|
101
|
+
[
|
|
102
|
+
[0] world(x, y, *z, &blk) Hello
|
|
103
|
+
]
|
|
104
|
+
|
|
105
|
+
$ cat > 5.rb
|
|
106
|
+
require "awesome_print"
|
|
107
|
+
ap (''.methods - Object.methods).grep(/!/)
|
|
108
|
+
^D
|
|
109
|
+
$ ruby 5.rb
|
|
110
|
+
[
|
|
111
|
+
[ 0] capitalize!() String
|
|
112
|
+
[ 1] chomp!(*arg1) String
|
|
113
|
+
[ 2] chop!() String
|
|
114
|
+
[ 3] delete!(*arg1) String
|
|
115
|
+
[ 4] downcase!() String
|
|
116
|
+
[ 5] encode!(*arg1) String
|
|
117
|
+
[ 6] gsub!(*arg1) String
|
|
118
|
+
[ 7] lstrip!() String
|
|
119
|
+
[ 8] next!() String
|
|
120
|
+
[ 9] reverse!() String
|
|
121
|
+
[10] rstrip!() String
|
|
122
|
+
[11] slice!(*arg1) String
|
|
123
|
+
[12] squeeze!(*arg1) String
|
|
124
|
+
[13] strip!() String
|
|
125
|
+
[14] sub!(*arg1) String
|
|
126
|
+
[15] succ!() String
|
|
127
|
+
[16] swapcase!() String
|
|
128
|
+
[17] tr!(arg1, arg2) String
|
|
129
|
+
[18] tr_s!(arg1, arg2) String
|
|
130
|
+
[19] upcase!() String
|
|
131
|
+
]
|
|
132
|
+
|
|
133
|
+
$ cat > 6.rb
|
|
134
|
+
require "awesome_print"
|
|
135
|
+
ap 42 == ap(42)
|
|
136
|
+
^D
|
|
137
|
+
$ ruby 6.rb
|
|
138
|
+
42
|
|
139
|
+
true
|
|
140
|
+
|
|
89
141
|
### Example (Rails console) ###
|
|
90
|
-
$
|
|
91
|
-
|
|
92
|
-
rails> require "ap"
|
|
142
|
+
$ rails console
|
|
143
|
+
rails> require "awesome_print"
|
|
93
144
|
rails> ap Account.all(:limit => 2)
|
|
94
145
|
[
|
|
95
146
|
[0] #<Account:0x1033220b8> {
|
|
@@ -149,33 +200,47 @@ To use awesome_print as default formatter in irb and Rails console add the follo
|
|
|
149
200
|
lines into your ~/.irbrc file:
|
|
150
201
|
|
|
151
202
|
require "rubygems"
|
|
152
|
-
require "
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
203
|
+
require "awesome_print"
|
|
204
|
+
|
|
205
|
+
unless IRB.version.include?('DietRB')
|
|
206
|
+
IRB::Irb.class_eval do
|
|
207
|
+
def output_value
|
|
208
|
+
ap @context.last_value
|
|
209
|
+
end
|
|
156
210
|
end
|
|
211
|
+
else # MacRuby
|
|
212
|
+
IRB.formatter = Class.new(IRB::Formatter) do
|
|
213
|
+
def inspect_object(object)
|
|
214
|
+
object.ai
|
|
215
|
+
end
|
|
216
|
+
end.new
|
|
157
217
|
end
|
|
158
218
|
|
|
159
219
|
### Logger Convenience Method ###
|
|
160
|
-
awesome_print adds
|
|
161
|
-
|
|
220
|
+
awesome_print adds the 'ap' method to the Logger and ActiveSupport::BufferedLogger classes
|
|
221
|
+
letting you call:
|
|
162
222
|
|
|
163
223
|
logger.ap object
|
|
164
224
|
|
|
165
|
-
By default, this logs at the :debug level. You can override that globally with
|
|
225
|
+
By default, this logs at the :debug level. You can override that globally with:
|
|
166
226
|
|
|
167
227
|
:log_level => :info
|
|
168
228
|
|
|
169
|
-
in the custom defaults (see below)
|
|
229
|
+
in the custom defaults (see below). You can also override on a per call basis with:
|
|
170
230
|
|
|
171
231
|
logger.ap object, :warn
|
|
172
232
|
|
|
173
233
|
### ActionView Convenience Method ###
|
|
174
|
-
awesome_print adds
|
|
234
|
+
awesome_print adds the 'ap' method to the ActionView::Base class making it available
|
|
175
235
|
within Rails templates. For example:
|
|
176
236
|
|
|
177
237
|
<%= ap @accounts.first %>
|
|
178
238
|
|
|
239
|
+
With other web frameworks (ex: in Sinatra templates) you can explicitly request HTML
|
|
240
|
+
formatting:
|
|
241
|
+
|
|
242
|
+
<%= ap @accounts.first, :html => true %>
|
|
243
|
+
|
|
179
244
|
### Setting Custom Defaults ###
|
|
180
245
|
You can set your own default options by creating ``.aprc`` file in your home
|
|
181
246
|
directory. Within that file assign your defaults to ``AwesomePrint.defaults``.
|
|
@@ -190,6 +255,12 @@ For example:
|
|
|
190
255
|
}
|
|
191
256
|
}
|
|
192
257
|
|
|
258
|
+
### Running Specs ###
|
|
259
|
+
|
|
260
|
+
$ gem install rspec # RSpec 2.x is the requirement.
|
|
261
|
+
$ rake spec # Run the entire spec suite.
|
|
262
|
+
$ rspec spec/logger_spec.rb # Run individual spec file.
|
|
263
|
+
|
|
193
264
|
### Note on Patches/Pull Requests ###
|
|
194
265
|
* Fork the project on Github.
|
|
195
266
|
* Make your feature addition or bug fix.
|
|
@@ -199,12 +270,22 @@ For example:
|
|
|
199
270
|
|
|
200
271
|
### Contributors ###
|
|
201
272
|
|
|
273
|
+
* Andrew O'Brien -- https://github.com/AndrewO
|
|
202
274
|
* Daniel Bretoi -- http://github.com/danielb2
|
|
203
|
-
*
|
|
275
|
+
* Eloy Duran -- http://github.com/alloy
|
|
276
|
+
* Elpizo Choi -- https://github.com/fuJiin
|
|
277
|
+
* Benoit Daloze -- http://github.com/eregon
|
|
278
|
+
* Sean Gallagher -- http://github.com/torandu
|
|
279
|
+
* Stephan Hagemann -- https://github.com/shageman
|
|
280
|
+
* Tim Harper -- http://github.com/timcharper
|
|
204
281
|
* Tobias Crawley -- http://github.com/tobias
|
|
282
|
+
* Viktar Basharymau -- https://github.com/DNNX
|
|
205
283
|
|
|
206
284
|
### License ###
|
|
207
|
-
Copyright (c) 2010 Michael Dvorkin
|
|
285
|
+
Copyright (c) 2010-2011 Michael Dvorkin
|
|
286
|
+
|
|
287
|
+
twitter.com/mid
|
|
288
|
+
|
|
208
289
|
%w(mike dvorkin.net) * "@" || %w(mike fatfreecrm.com) * "@"
|
|
209
290
|
|
|
210
|
-
Released under the MIT license. See LICENSE file for details.
|
|
291
|
+
Released under the MIT license. See LICENSE file for details.
|
data/Rakefile
CHANGED
|
@@ -11,9 +11,8 @@ begin
|
|
|
11
11
|
gem.email = "mike@dvorkin.net"
|
|
12
12
|
gem.homepage = "http://github.com/michaeldv/awesome_print"
|
|
13
13
|
gem.authors = ["Michael Dvorkin"]
|
|
14
|
-
gem.add_development_dependency "rspec", ">=
|
|
14
|
+
gem.add_development_dependency "rspec", ">= 2.5.0"
|
|
15
15
|
gem.files = FileList["[A-Z]*", "lib/**/*.rb", "rails/*.rb", "spec/*", "init.rb"]
|
|
16
|
-
gem.has_rdoc = false
|
|
17
16
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
|
18
17
|
end
|
|
19
18
|
Jeweler::GemcutterTasks.new
|
|
@@ -21,16 +20,15 @@ rescue LoadError
|
|
|
21
20
|
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
|
22
21
|
end
|
|
23
22
|
|
|
24
|
-
require
|
|
25
|
-
|
|
26
|
-
spec.
|
|
27
|
-
spec.
|
|
23
|
+
require "rspec/core/rake_task"
|
|
24
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
|
25
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
|
26
|
+
spec.rspec_opts = ['--color']
|
|
28
27
|
end
|
|
29
28
|
|
|
30
|
-
|
|
31
|
-
spec.libs << 'lib' << 'spec'
|
|
32
|
-
spec.pattern = 'spec/**/*_spec.rb'
|
|
29
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
|
33
30
|
spec.rcov = true
|
|
31
|
+
spec.rcov_opts = %q[--exclude "spec"]
|
|
34
32
|
end
|
|
35
33
|
|
|
36
34
|
task :spec => :check_dependencies
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.4.0
|
data/init.rb
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
require File.join(File.dirname(__FILE__), "lib", "
|
|
1
|
+
require File.join(File.dirname(__FILE__), "lib", "awesome_print")
|
data/lib/ap/awesome_print.rb
CHANGED
|
@@ -1,19 +1,24 @@
|
|
|
1
|
-
# Copyright (c) 2010 Michael Dvorkin
|
|
1
|
+
# Copyright (c) 2010-2011 Michael Dvorkin
|
|
2
2
|
#
|
|
3
3
|
# Awesome Print is freely distributable under the terms of MIT license.
|
|
4
4
|
# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
|
|
5
5
|
#------------------------------------------------------------------------------
|
|
6
|
+
require "cgi"
|
|
6
7
|
require "shellwords"
|
|
7
8
|
|
|
8
9
|
class AwesomePrint
|
|
9
|
-
AP = :__awesome_print__
|
|
10
|
-
CORE = [ :array, :hash, :class, :file, :dir, :bigdecimal, :rational, :struct ]
|
|
10
|
+
AP = :__awesome_print__ unless defined?(AwesomePrint::AP)
|
|
11
|
+
CORE = [ :array, :hash, :class, :file, :dir, :bigdecimal, :rational, :struct, :method, :unboundmethod ] unless defined?(AwesomePrint::CORE)
|
|
12
|
+
@@force_colors = false
|
|
11
13
|
|
|
12
14
|
def initialize(options = {})
|
|
13
15
|
@options = {
|
|
14
|
-
:multiline => true,
|
|
15
|
-
:plain => false,
|
|
16
|
-
:indent => 4,
|
|
16
|
+
:multiline => true, # Display in multiple lines.
|
|
17
|
+
:plain => false, # Use colors.
|
|
18
|
+
:indent => 4, # Indent using 4 spaces.
|
|
19
|
+
:index => true, # Display array indices.
|
|
20
|
+
:html => false, # Use ANSI color codes rather than HTML.
|
|
21
|
+
:sorted_hash_keys => false, # Do not sort hash keys.
|
|
17
22
|
:color => {
|
|
18
23
|
:array => :white,
|
|
19
24
|
:bigdecimal => :blue,
|
|
@@ -28,7 +33,9 @@ class AwesomePrint
|
|
|
28
33
|
:string => :yellowish,
|
|
29
34
|
:symbol => :cyanish,
|
|
30
35
|
:time => :greenish,
|
|
31
|
-
:trueclass => :green
|
|
36
|
+
:trueclass => :green,
|
|
37
|
+
:method => :purpleish,
|
|
38
|
+
:args => :pale
|
|
32
39
|
}
|
|
33
40
|
}
|
|
34
41
|
|
|
@@ -39,7 +46,8 @@ class AwesomePrint
|
|
|
39
46
|
@indentation = @options[:indent].abs
|
|
40
47
|
Thread.current[AP] ||= []
|
|
41
48
|
end
|
|
42
|
-
|
|
49
|
+
|
|
50
|
+
|
|
43
51
|
private
|
|
44
52
|
|
|
45
53
|
# Format an array.
|
|
@@ -47,18 +55,23 @@ class AwesomePrint
|
|
|
47
55
|
def awesome_array(a)
|
|
48
56
|
return "[]" if a == []
|
|
49
57
|
|
|
50
|
-
if @
|
|
58
|
+
if a.instance_variable_defined?('@__awesome_methods__')
|
|
59
|
+
methods_array(a)
|
|
60
|
+
elsif @options[:multiline]
|
|
51
61
|
width = (a.size - 1).to_s.size
|
|
52
62
|
data = a.inject([]) do |arr, item|
|
|
53
|
-
index =
|
|
63
|
+
index = if @options[:index]
|
|
64
|
+
colorize("#{indent}[#{arr.size.to_s.rjust(width)}] ", :array)
|
|
65
|
+
else
|
|
66
|
+
colorize(indent, :array)
|
|
67
|
+
end
|
|
54
68
|
indented do
|
|
55
69
|
arr << (index << awesome(item))
|
|
56
70
|
end
|
|
57
71
|
end
|
|
58
72
|
"[\n" << data.join(",\n") << "\n#{outdent}]"
|
|
59
73
|
else
|
|
60
|
-
|
|
61
|
-
"[ #{data.join(', ')} ]"
|
|
74
|
+
"[ " << a.map{ |item| awesome(item) }.join(", ") << " ]"
|
|
62
75
|
end
|
|
63
76
|
end
|
|
64
77
|
|
|
@@ -67,23 +80,24 @@ class AwesomePrint
|
|
|
67
80
|
def awesome_hash(h)
|
|
68
81
|
return "{}" if h == {}
|
|
69
82
|
|
|
70
|
-
|
|
83
|
+
keys = @options[:sorted_hash_keys] ? h.keys.sort { |a, b| a.to_s <=> b.to_s } : h.keys
|
|
84
|
+
data = keys.map do |key|
|
|
71
85
|
plain_single_line do
|
|
72
|
-
|
|
86
|
+
[ awesome(key), h[key] ]
|
|
73
87
|
end
|
|
74
88
|
end
|
|
75
89
|
|
|
76
90
|
width = data.map { |key, | key.size }.max || 0
|
|
77
91
|
width += @indentation if @options[:indent] > 0
|
|
78
92
|
|
|
79
|
-
data = data.
|
|
93
|
+
data = data.map do |key, value|
|
|
80
94
|
if @options[:multiline]
|
|
81
95
|
formatted_key = (@options[:indent] >= 0 ? key.rjust(width) : indent + key.ljust(width))
|
|
82
96
|
else
|
|
83
97
|
formatted_key = key
|
|
84
98
|
end
|
|
85
99
|
indented do
|
|
86
|
-
|
|
100
|
+
formatted_key << colorize(" => ", :hash) << awesome(value)
|
|
87
101
|
end
|
|
88
102
|
end
|
|
89
103
|
if @options[:multiline]
|
|
@@ -93,7 +107,7 @@ class AwesomePrint
|
|
|
93
107
|
end
|
|
94
108
|
end
|
|
95
109
|
|
|
96
|
-
# Format a Struct. If @options[:indent]
|
|
110
|
+
# Format a Struct. If @options[:indent] is negative left align hash keys.
|
|
97
111
|
#------------------------------------------------------------------------------
|
|
98
112
|
def awesome_struct(s)
|
|
99
113
|
h = {}
|
|
@@ -132,10 +146,18 @@ class AwesomePrint
|
|
|
132
146
|
end
|
|
133
147
|
alias :awesome_rational :awesome_bigdecimal
|
|
134
148
|
|
|
149
|
+
# Format a method.
|
|
150
|
+
#------------------------------------------------------------------------------
|
|
151
|
+
def awesome_method(m)
|
|
152
|
+
name, args, owner = method_tuple(m)
|
|
153
|
+
"#{colorize(owner, :class)}##{colorize(name, :method)}#{colorize(args, :args)}"
|
|
154
|
+
end
|
|
155
|
+
alias :awesome_unboundmethod :awesome_method
|
|
156
|
+
|
|
135
157
|
# Catch all method to format an arbitrary object.
|
|
136
158
|
#------------------------------------------------------------------------------
|
|
137
159
|
def awesome_self(object, appear = {})
|
|
138
|
-
colorize(object.inspect << appear[:with].to_s, appear[:as] || declassify(object))
|
|
160
|
+
colorize(object.inspect.to_s << appear[:with].to_s, appear[:as] || declassify(object))
|
|
139
161
|
end
|
|
140
162
|
|
|
141
163
|
# Dispatcher that detects data nesting and invokes object-aware formatter.
|
|
@@ -153,6 +175,40 @@ class AwesomePrint
|
|
|
153
175
|
end
|
|
154
176
|
end
|
|
155
177
|
|
|
178
|
+
# Format object.methods array.
|
|
179
|
+
#------------------------------------------------------------------------------
|
|
180
|
+
def methods_array(a)
|
|
181
|
+
object = a.instance_variable_get('@__awesome_methods__')
|
|
182
|
+
tuples = a.map do |name|
|
|
183
|
+
tuple = if object.respond_to?(name, true) # Is this a regular method?
|
|
184
|
+
the_method = object.method(name) rescue nil # Avoid potential ArgumentError if object#method is overridden.
|
|
185
|
+
if the_method && the_method.respond_to?(:arity) # Is this original object#method?
|
|
186
|
+
method_tuple(the_method) # Yes, we are good.
|
|
187
|
+
end
|
|
188
|
+
elsif object.respond_to?(:instance_method) # Is this an unbound method?
|
|
189
|
+
method_tuple(object.instance_method(name))
|
|
190
|
+
end
|
|
191
|
+
tuple || [ name.to_s, '(?)', '' ] # Return WTF default if all the above fails.
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
width = (tuples.size - 1).to_s.size
|
|
195
|
+
name_width = tuples.map { |item| item[0].size }.max || 0
|
|
196
|
+
args_width = tuples.map { |item| item[1].size }.max || 0
|
|
197
|
+
|
|
198
|
+
data = tuples.inject([]) do |arr, item|
|
|
199
|
+
index = if @options[:index]
|
|
200
|
+
"#{indent}[#{arr.size.to_s.rjust(width)}]"
|
|
201
|
+
else
|
|
202
|
+
indent
|
|
203
|
+
end
|
|
204
|
+
indented do
|
|
205
|
+
arr << "#{index} #{colorize(item[0].rjust(name_width), :method)}#{colorize(item[1].ljust(args_width), :args)} #{colorize(item[2], :class)}"
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
"[\n" << data.join("\n") << "\n#{outdent}]"
|
|
210
|
+
end
|
|
211
|
+
|
|
156
212
|
# Format nested data, for example:
|
|
157
213
|
# arr = [1, 2]; arr << arr
|
|
158
214
|
# => [1,2, [...]]
|
|
@@ -174,26 +230,57 @@ class AwesomePrint
|
|
|
174
230
|
CORE.grep(declassify(object))[0] || :self
|
|
175
231
|
end
|
|
176
232
|
|
|
177
|
-
# Turn class name into symbol, ex: Hello::World => :hello_world.
|
|
233
|
+
# Turn class name into symbol, ex: Hello::World => :hello_world. Classes that
|
|
234
|
+
# inherit from Array, Hash, File, Dir, and Struct are treated as the base class.
|
|
178
235
|
#------------------------------------------------------------------------------
|
|
179
236
|
def declassify(object)
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
237
|
+
case object
|
|
238
|
+
when Array then :array
|
|
239
|
+
when Hash then :hash
|
|
240
|
+
when File then :file
|
|
241
|
+
when Dir then :dir
|
|
242
|
+
when Struct then :struct
|
|
243
|
+
else object.class.to_s.gsub(/:+/, "_").downcase.to_sym
|
|
184
244
|
end
|
|
185
245
|
end
|
|
186
246
|
|
|
187
247
|
# Pick the color and apply it to the given string as necessary.
|
|
188
248
|
#------------------------------------------------------------------------------
|
|
189
249
|
def colorize(s, type)
|
|
190
|
-
|
|
191
|
-
|
|
250
|
+
s = CGI.escapeHTML(s) if @options[:html]
|
|
251
|
+
if @options[:plain] || !@options[:color][type] || !colorize?
|
|
252
|
+
@options[:html] ? "<pre>#{s}</pre>" : s
|
|
192
253
|
else
|
|
193
|
-
s.send(@options[:color][type])
|
|
254
|
+
s.send(@options[:color][type], @options[:html])
|
|
194
255
|
end
|
|
195
256
|
end
|
|
196
257
|
|
|
258
|
+
# Return [ name, arguments, owner ] tuple for a given method.
|
|
259
|
+
#------------------------------------------------------------------------------
|
|
260
|
+
def method_tuple(method)
|
|
261
|
+
if method.respond_to?(:parameters) # Ruby 1.9.2+
|
|
262
|
+
# See http://ruby.runpaint.org/methods#method-objects-parameters
|
|
263
|
+
args = method.parameters.inject([]) do |arr, (type, name)|
|
|
264
|
+
name ||= (type == :block ? 'block' : "arg#{arr.size + 1}")
|
|
265
|
+
arr << case type
|
|
266
|
+
when :req then name.to_s
|
|
267
|
+
when :opt, :rest then "*#{name}"
|
|
268
|
+
when :block then "&#{name}"
|
|
269
|
+
else '?'
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
else # See http://ruby-doc.org/core/classes/Method.html#M001902
|
|
273
|
+
args = (1..method.arity.abs).map { |i| "arg#{i}" }
|
|
274
|
+
args[-1] = "*#{args[-1]}" if method.arity < 0
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
if method.to_s =~ /(Unbound)*Method: (.*?)[#\.]/
|
|
278
|
+
owner = "#{$2}#{$1 ? '(unbound)' : ''}".gsub('(', ' (')
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
[ method.name.to_s, "(#{args.join(', ')})", owner.to_s ]
|
|
282
|
+
end
|
|
283
|
+
|
|
197
284
|
# Format hash keys as plain string regardless of underlying data type.
|
|
198
285
|
#------------------------------------------------------------------------------
|
|
199
286
|
def plain_single_line
|
|
@@ -239,6 +326,19 @@ class AwesomePrint
|
|
|
239
326
|
$stderr.puts "Could not load #{dotfile}: #{e}"
|
|
240
327
|
end
|
|
241
328
|
|
|
329
|
+
# Return true if we are to colorize the output.
|
|
330
|
+
#------------------------------------------------------------------------------
|
|
331
|
+
def colorize?
|
|
332
|
+
@@force_colors || (STDOUT.tty? && ((ENV['TERM'] && ENV['TERM'] != 'dumb') || ENV['ANSICON']))
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
# Class accessor to force colorized output (ex. forked subprocess where TERM
|
|
336
|
+
# might be dumb).
|
|
337
|
+
#------------------------------------------------------------------------------
|
|
338
|
+
def self.force_colors!(value = true)
|
|
339
|
+
@@force_colors = value
|
|
340
|
+
end
|
|
341
|
+
|
|
242
342
|
# Class accessors for custom defaults.
|
|
243
343
|
#------------------------------------------------------------------------------
|
|
244
344
|
def self.defaults
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Copyright (c) 2010-2011 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
|
+
#
|
|
7
|
+
# The following makes it possible to invoke awesome_print while performing
|
|
8
|
+
# operations on method arrays, ex:
|
|
9
|
+
#
|
|
10
|
+
# ap [].methods - Object.methods
|
|
11
|
+
# ap ''.methods.grep(/!|\?/)
|
|
12
|
+
#
|
|
13
|
+
# If you could think of a better way please let me know :-)
|
|
14
|
+
#
|
|
15
|
+
class Array #:nodoc:
|
|
16
|
+
[ :-, :& ].each do |operator|
|
|
17
|
+
original_operator = instance_method(operator)
|
|
18
|
+
|
|
19
|
+
define_method operator do |*args|
|
|
20
|
+
arr = original_operator.bind(self).call(*args)
|
|
21
|
+
if self.instance_variable_defined?('@__awesome_methods__')
|
|
22
|
+
arr.instance_variable_set('@__awesome_methods__', self.instance_variable_get('@__awesome_methods__'))
|
|
23
|
+
arr.sort! { |a, b| a.to_s <=> b.to_s } # Need the block since Ruby 1.8.x can't sort arrays of symbols.
|
|
24
|
+
end
|
|
25
|
+
arr
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
#
|
|
29
|
+
# Intercepting Array#grep needs a special treatment since grep accepts
|
|
30
|
+
# an optional block.
|
|
31
|
+
#
|
|
32
|
+
alias :original_grep :grep
|
|
33
|
+
def grep(pattern, &blk)
|
|
34
|
+
#
|
|
35
|
+
# The following looks rather insane and I've sent numerous hours trying
|
|
36
|
+
# to figure it out. The problem is that if grep gets called with the
|
|
37
|
+
# block, for example:
|
|
38
|
+
#
|
|
39
|
+
# [].methods.grep(/(.+?)_by/) { $1.to_sym }
|
|
40
|
+
#
|
|
41
|
+
# ...then simple:
|
|
42
|
+
#
|
|
43
|
+
# original_grep(pattern, &blk)
|
|
44
|
+
#
|
|
45
|
+
# doesn't set $1 within the grep block which causes nil.to_sym failure.
|
|
46
|
+
# The workaround below has been tested with Ruby 1.8.7/Rails 2.3.8 and
|
|
47
|
+
# Ruby 1.9.2/Rails 3.0.0. For more info see the following thread dating
|
|
48
|
+
# back to 2003 when Ruby 1.8.0 was as fresh off the grill as Ruby 1.9.2
|
|
49
|
+
# is in 2010 :-)
|
|
50
|
+
#
|
|
51
|
+
# http://www.justskins.com/forums/bug-when-rerouting-string-52852.html
|
|
52
|
+
#
|
|
53
|
+
# BTW, if you figure out a better way of intercepting Array#grep please
|
|
54
|
+
# let me know: twitter.com/mid -- or just say hi so I know you've read
|
|
55
|
+
# the comment :-)
|
|
56
|
+
#
|
|
57
|
+
arr = unless blk
|
|
58
|
+
original_grep(pattern)
|
|
59
|
+
else
|
|
60
|
+
original_grep(pattern) do |match|
|
|
61
|
+
eval("%Q/#{match.to_s.gsub('/', '\/')}/ =~ #{pattern.inspect}", blk.binding)
|
|
62
|
+
yield match
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
if self.instance_variable_defined?('@__awesome_methods__')
|
|
66
|
+
arr.instance_variable_set('@__awesome_methods__', self.instance_variable_get('@__awesome_methods__'))
|
|
67
|
+
arr.reject! { |item| !(item.is_a?(Symbol) || item.is_a?(String)) } # grep block might return crap.
|
|
68
|
+
end
|
|
69
|
+
arr
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Copyright (c) 2010-2011 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
|
+
class Class #:nodoc:
|
|
7
|
+
# Remaining public/private etc. '_methods' are handled in core_ext/object.rb.
|
|
8
|
+
%w(instance_methods private_instance_methods protected_instance_methods public_instance_methods).each do |name|
|
|
9
|
+
original_method = instance_method(name)
|
|
10
|
+
|
|
11
|
+
define_method name do |*args|
|
|
12
|
+
methods = original_method.bind(self).call(*args)
|
|
13
|
+
methods.instance_variable_set('@__awesome_methods__', self) # Evil?!
|
|
14
|
+
methods.sort!
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
data/lib/ap/core_ext/kernel.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c) 2010 Michael Dvorkin
|
|
1
|
+
# Copyright (c) 2010-2011 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
|
|
@@ -13,6 +13,7 @@ module Kernel
|
|
|
13
13
|
|
|
14
14
|
def ap(object, options = {})
|
|
15
15
|
puts object.ai(options)
|
|
16
|
+
object
|
|
16
17
|
end
|
|
17
18
|
alias :awesome_print :ap
|
|
18
19
|
|
data/lib/ap/core_ext/logger.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c) 2010 Michael Dvorkin
|
|
1
|
+
# Copyright (c) 2010-2011 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
|
|
@@ -14,5 +14,5 @@ module AwesomePrintLogger
|
|
|
14
14
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
Logger.send(:include, AwesomePrintLogger)
|
|
17
|
+
Logger.send(:include, AwesomePrintLogger)
|
|
18
18
|
ActiveSupport::BufferedLogger.send(:include, AwesomePrintLogger) if defined?(::ActiveSupport::BufferedLogger)
|