awesome_print_motion 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,27 @@
1
+ # Mac OS
2
+ .DS_Store
3
+
4
+ # TextMate
5
+ *.tmproj
6
+ tmtags
7
+
8
+ # Emacs
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ # Vim
14
+ *.swp
15
+
16
+ # Gem
17
+ coverage
18
+ rdoc
19
+ pkg
20
+ .rvmrc
21
+
22
+ # Test
23
+ test/.repl_history
24
+ test/build
25
+ test/resources/*.nib
26
+ test/resources/*.momd
27
+ test/resources/*.storyboardc
@@ -0,0 +1,2 @@
1
+ 0.1.0
2
+ - Initial RubyMotion port based on awesome_print 1.1.0
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+ gemspec
3
+
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2010-2012 Michael Dvorkin
2
+ http://www.dvorkin.net
3
+ %w(mike dvorkin.net) * "@" || %w(mike fatfreecrm.com) * "@"
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,81 @@
1
+ ## Awesome Print for RubyMotion ##
2
+ Awesome Print for RubyMotion is a RubyMotion gem that pretty prints RubyMotion objects in full color
3
+ exposing their internal structure with proper indentation.
4
+
5
+ Current version is based on Awesome Print v1.1.0. Please see http://github.com/michaeldv/awesome_print
6
+ for more information.
7
+
8
+ ### Installation ###
9
+ # Installing as Ruby gem
10
+ $ gem install awesome_print_motion
11
+
12
+ # Cloning the repository
13
+ $ git clone git://github.com/michaeldv/awesome_print_motion.git
14
+
15
+ ### Usage ###
16
+ Generate RubyMotion project, then require "awesome_print_motion" in projects's Rakefile:
17
+
18
+ # -*- coding: utf-8 -*-
19
+ $:.unshift("/Library/RubyMotion/lib")
20
+ require "motion/project"
21
+ require "awesome_print_motion"
22
+
23
+ Motion::Project::App.setup do |app|
24
+ app.name = "your_app_name"
25
+ end
26
+
27
+ Within AppDelegate you can use <code>ap object, options</code> method. For example:
28
+
29
+ class AppDelegate
30
+ def application(application, didFinishLaunchingWithOptions:launchOptions)
31
+ ap self, :raw => true
32
+ true
33
+ end
34
+ end
35
+
36
+ AwesomePrint also becomes available in RubyMotion console:
37
+
38
+ Build ./build/iPhoneSimulator-6.0-Development
39
+ Simulate ./build/iPhoneSimulator-6.0-Development/your_app_name.app
40
+ (main)> ap [ false, 42, %w(forty two), { :now => Time.now, :class => Time.now.class, :distance => 42e42 } ]
41
+ [
42
+ [0] false,
43
+ [1] 42,
44
+ [2] [
45
+ [0] "forty",
46
+ [1] "two"
47
+ ],
48
+ [3] {
49
+ :now => 2012-10-23 17:09:19 -0700,
50
+ :class => Time < NSDate,
51
+ :distance => Infinity
52
+ }
53
+ ]
54
+ => nil
55
+ (main)> ap [1,2,3]
56
+
57
+ Supported options and color codes are documented at http://github.com/michaeldv/awesome_print.
58
+
59
+ ### Differences with Ruby awesome_print v1.1.0 ###
60
+ * No support for :html formatting option.
61
+ * No integration with Logger.
62
+ * No integration IRB or Pry.
63
+ * AwesomePrint extensions are supported but none are bundled.
64
+ * AwesomePrint specs haven't been ported yet.
65
+ * Not compatible with Ruby 1.8.6 and 1.8.7 ;-)
66
+
67
+
68
+ ### Note on Patches/Pull Requests ###
69
+ * Fork the project on Github.
70
+ * Make your feature addition or bug fix.
71
+ * Commit, do not mess with Rakefile, version, or history.
72
+ * Send me commit URL (*do not* send pull requests).
73
+
74
+ ### License ###
75
+ Copyright (c) 2010-2012 Michael Dvorkin
76
+
77
+ http://www.dvorkin.net
78
+
79
+ %w(mike dvorkin.net) * "@" || %w(mike fatfreecrm.com) * "@"
80
+
81
+ Released under the MIT license. See LICENSE file for details.
@@ -0,0 +1,2 @@
1
+ require "bundler"
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,9 @@
1
+ # Copyright (c) 2010-2012 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
+ # Keeping this to allow require "ap"
8
+ #
9
+ require File.dirname(__FILE__) + "/awesome_print_motion"
@@ -0,0 +1,18 @@
1
+ # Copyright (c) 2010-2012 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
+ unless defined?(Motion::Project::Config)
7
+ raise "This file must be required within a RubyMotion project Rakefile."
8
+ end
9
+
10
+ Motion::Project::App.setup do |app|
11
+ Dir.glob("#{File.dirname(__FILE__)}/awesome_print_motion/core_ext/*.rb").each do |file|
12
+ app.files.unshift(file)
13
+ end
14
+
15
+ Dir.glob("#{File.dirname(__FILE__)}/awesome_print_motion/*.rb").each do |file|
16
+ app.files.unshift(file)
17
+ end
18
+ end
@@ -0,0 +1,81 @@
1
+ # Copyright (c) 2010-2012 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
+ #
62
+ # The binding can only be used with Ruby-defined methods, therefore
63
+ # we must rescue potential "ArgumentError: Can't create Binding from
64
+ # C level Proc" error.
65
+ #
66
+ # For example, the following raises ArgumentError since #succ method
67
+ # is defined in C.
68
+ #
69
+ # [ 0, 1, 2, 3, 4 ].grep(1..2, &:succ)
70
+ #
71
+ eval("%Q/#{match.to_s.gsub('/', '\/')}/ =~ #{pattern.inspect}", blk.binding) rescue ArgumentError
72
+ yield match
73
+ end
74
+ end
75
+ if self.instance_variable_defined?('@__awesome_methods__')
76
+ arr.instance_variable_set('@__awesome_methods__', self.instance_variable_get('@__awesome_methods__'))
77
+ arr.reject! { |item| !(item.is_a?(Symbol) || item.is_a?(String)) } # grep block might return crap.
78
+ end
79
+ arr
80
+ end
81
+ end
@@ -0,0 +1,22 @@
1
+ # Copyright (c) 2010-2012 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
+ #
8
+ # Intercept methods below to inject @__awesome_print__ instance variable
9
+ # so we know it is the *methods* array when formatting an array.
10
+ #
11
+ # Remaining public/private etc. '_methods' are handled in core_ext/object.rb.
12
+ #
13
+ %w(instance_methods private_instance_methods protected_instance_methods public_instance_methods).each do |name|
14
+ original_method = instance_method(name)
15
+
16
+ define_method name do |*args|
17
+ methods = original_method.bind(self).call(*args)
18
+ methods.instance_variable_set('@__awesome_methods__', self)
19
+ methods
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,21 @@
1
+ # Copyright (c) 2010-2012 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 Kernel
7
+
8
+ def ai(options = {})
9
+ ap = AwesomePrint::Inspector.new(options)
10
+ ap.awesome self
11
+ end
12
+ alias :awesome_inspect :ai
13
+
14
+ def ap(object, options = {})
15
+ puts object.ai(options)
16
+ object unless AwesomePrint.console?
17
+ end
18
+ alias :awesome_print :ap
19
+
20
+ module_function :ap
21
+ end
@@ -0,0 +1,22 @@
1
+ # Copyright (c) 2010-2012 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 Object #:nodoc:
7
+ #
8
+ # Intercept methods below to inject @__awesome_print__ instance variable
9
+ # so we know it is the *methods* array when formatting an array.
10
+ #
11
+ # Remaining instance '_methods' are handled in core_ext/class.rb.
12
+ #
13
+ %w(methods private_methods protected_methods public_methods singleton_methods).each do |name|
14
+ original_method = instance_method(name)
15
+
16
+ define_method name do |*args|
17
+ methods = original_method.bind(self).call(*args)
18
+ methods.instance_variable_set('@__awesome_methods__', self)
19
+ methods
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,400 @@
1
+ # Copyright (c) 2010-2012 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
+ ### autoload :CGI, "cgi"
7
+ ### require "shellwords"
8
+
9
+ module AwesomePrint
10
+ class Formatter
11
+
12
+ CORE = [ :array, :hash, :class, :file, :dir, :bigdecimal, :rational, :struct, :method, :unboundmethod ]
13
+ DEFAULT_LIMIT_SIZE = 7
14
+
15
+ def initialize(inspector)
16
+ @inspector = inspector
17
+ @options = inspector.options
18
+ @indentation = @options[:indent].abs
19
+ end
20
+
21
+ # Main entry point to format an object.
22
+ #------------------------------------------------------------------------------
23
+ def format(object, type = nil)
24
+ core_class = cast(object, type)
25
+ if core_class != :self
26
+ send(:"awesome_#{core_class}", object) # Core formatters.
27
+ else
28
+ awesome_self(object, type) # Catch all that falls back to object.inspect.
29
+ end
30
+ end
31
+
32
+ # Hook this when adding custom formatters. Check out lib/awesome_print/ext
33
+ # directory for custom formatters that ship with awesome_print.
34
+ #------------------------------------------------------------------------------
35
+ def cast(object, type)
36
+ CORE.grep(type)[0] || :self
37
+ end
38
+
39
+ # Pick the color and apply it to the given string as necessary.
40
+ #------------------------------------------------------------------------------
41
+ def colorize(str, type)
42
+ if @options[:plain] || !@options[:color][type] || !@inspector.colorize?
43
+ str
44
+ else
45
+ Painter.send(@options[:color][type], str)
46
+ end
47
+ end
48
+
49
+
50
+ private
51
+
52
+ # Catch all method to format an arbitrary object.
53
+ #------------------------------------------------------------------------------
54
+ def awesome_self(object, type)
55
+ if @options[:raw] && object.instance_variables.any?
56
+ awesome_object(object)
57
+ else
58
+ colorize(object.inspect.to_s, type)
59
+ end
60
+ end
61
+
62
+ # Format an array.
63
+ #------------------------------------------------------------------------------
64
+ def awesome_array(a)
65
+ return "[]" if a == []
66
+
67
+ if a.instance_variable_defined?('@__awesome_methods__')
68
+ methods_array(a)
69
+ elsif @options[:multiline]
70
+ width = (a.size - 1).to_s.size
71
+
72
+ data = a.inject([]) do |arr, item|
73
+ index = indent
74
+ index << colorize("[#{arr.size.to_s.rjust(width)}] ", :array) if @options[:index]
75
+ indented do
76
+ arr << (index << @inspector.awesome(item))
77
+ end
78
+ end
79
+
80
+ data = limited(data, width) if should_be_limited?
81
+ "[\n" << data.join(",\n") << "\n#{outdent}]"
82
+ else
83
+ "[ " << a.map{ |item| @inspector.awesome(item) }.join(", ") << " ]"
84
+ end
85
+ end
86
+
87
+ # Format a hash. If @options[:indent] if negative left align hash keys.
88
+ #------------------------------------------------------------------------------
89
+ def awesome_hash(h)
90
+ return "{}" if h == {}
91
+
92
+ keys = @options[:sort_keys] ? h.keys.sort { |a, b| a.to_s <=> b.to_s } : h.keys
93
+ data = keys.map do |key|
94
+ plain_single_line do
95
+ [ @inspector.awesome(key), h[key] ]
96
+ end
97
+ end
98
+
99
+ width = data.map { |key, | key.size }.max || 0
100
+ width += @indentation if @options[:indent] > 0
101
+
102
+ data = data.map do |key, value|
103
+ indented do
104
+ align(key, width) << colorize(" => ", :hash) << @inspector.awesome(value)
105
+ end
106
+ end
107
+
108
+ data = limited(data, width, :hash => true) if should_be_limited?
109
+ if @options[:multiline]
110
+ "{\n" << data.join(",\n") << "\n#{outdent}}"
111
+ else
112
+ "{ #{data.join(', ')} }"
113
+ end
114
+ end
115
+
116
+ # Format an object.
117
+ #------------------------------------------------------------------------------
118
+ def awesome_object(o)
119
+ vars = o.instance_variables.map do |var|
120
+ next if var =~ /^__.*?__$/ # Skip internal RubyMotion variables.
121
+ property = var[1..-1].to_sym
122
+ accessor = if o.respond_to?(:"#{property}=")
123
+ o.respond_to?(property) ? :accessor : :writer
124
+ else
125
+ o.respond_to?(property) ? :reader : nil
126
+ end
127
+ if accessor
128
+ [ "attr_#{accessor} :#{property}", var ]
129
+ else
130
+ [ var.to_s, var ]
131
+ end
132
+ end
133
+
134
+ data = vars.compact.sort.map do |declaration, var|
135
+ key = left_aligned do
136
+ align(declaration, declaration.size)
137
+ end
138
+
139
+ unless @options[:plain]
140
+ if key =~ /(@\w+)/
141
+ key.sub!($1, colorize($1, :variable))
142
+ else
143
+ key.sub!(/(attr_\w+)\s(\:\w+)/, "#{colorize('\\1', :keyword)} #{colorize('\\2', :method)}")
144
+ end
145
+ end
146
+ indented do
147
+ key << colorize(" = ", :hash) + @inspector.awesome(o.instance_variable_get(var))
148
+ end
149
+ end
150
+ if @options[:multiline]
151
+ "#<#{awesome_instance(o)}\n#{data.join(%Q/,\n/)}\n#{outdent}>"
152
+ else
153
+ "#<#{awesome_instance(o)} #{data.join(', ')}>"
154
+ end
155
+ end
156
+
157
+ # Format a Struct.
158
+ #------------------------------------------------------------------------------
159
+ def awesome_struct(s)
160
+ #
161
+ # The code is slightly uglier because of Ruby 1.8.6 quirks:
162
+ # awesome_hash(Hash[s.members.zip(s.values)]) <-- ArgumentError: odd number of arguments for Hash)
163
+ # awesome_hash(Hash[*s.members.zip(s.values).flatten]) <-- s.members returns strings, not symbols.
164
+ #
165
+ hash = {}
166
+ s.each_pair { |key, value| hash[key] = value }
167
+ awesome_hash(hash)
168
+ end
169
+
170
+ # Format Class object.
171
+ #------------------------------------------------------------------------------
172
+ def awesome_class(c)
173
+ if superclass = c.superclass # <-- Assign and test if nil.
174
+ colorize("#{c.inspect} < #{superclass}", :class)
175
+ else
176
+ colorize(c.inspect, :class)
177
+ end
178
+ end
179
+
180
+ # Format File object.
181
+ #------------------------------------------------------------------------------
182
+ def awesome_file(f)
183
+ ls = File.directory?(f) ? `ls -adlF #{f.path.shellescape}` : `ls -alF #{f.path.shellescape}`
184
+ colorize(ls.empty? ? f.inspect : "#{f.inspect}\n#{ls.chop}", :file)
185
+ end
186
+
187
+ # Format Dir object.
188
+ #------------------------------------------------------------------------------
189
+ def awesome_dir(d)
190
+ ls = `ls -alF #{d.path.shellescape}`
191
+ colorize(ls.empty? ? d.inspect : "#{d.inspect}\n#{ls.chop}", :dir)
192
+ end
193
+
194
+ # Format BigDecimal object.
195
+ #------------------------------------------------------------------------------
196
+ def awesome_bigdecimal(n)
197
+ colorize(n.to_s("F"), :bigdecimal)
198
+ end
199
+
200
+ # Format Rational object.
201
+ #------------------------------------------------------------------------------
202
+ def awesome_rational(n)
203
+ colorize(n.to_s, :rational)
204
+ end
205
+
206
+ # Format a method.
207
+ #------------------------------------------------------------------------------
208
+ def awesome_method(m)
209
+ name, args, owner = method_tuple(m)
210
+ "#{colorize(owner, :class)}##{colorize(name, :method)}#{colorize(args, :args)}"
211
+ end
212
+ alias :awesome_unboundmethod :awesome_method
213
+
214
+ # Format object instance.
215
+ #------------------------------------------------------------------------------
216
+ def awesome_instance(o)
217
+ "#{o.class}:0x%08x" % (o.__id__ * 2)
218
+ end
219
+
220
+ # Format object.methods array.
221
+ #------------------------------------------------------------------------------
222
+ def methods_array(a)
223
+ a.sort! { |x, y| x.to_s <=> y.to_s } # Can't simply a.sort! because of o.methods << [ :blah ]
224
+ object = a.instance_variable_get('@__awesome_methods__')
225
+ tuples = a.map do |name|
226
+ if name.is_a?(Symbol) || name.is_a?(String) # Ignore garbage, ex. 42.methods << [ :blah ]
227
+ tuple = if object.respond_to?(name, true) # Is this a regular method?
228
+ the_method = silently do # Suppress RubyMotion warnings.
229
+ object.method(name) rescue nil # Avoid potential ArgumentError if object#method is overridden.
230
+ end
231
+ if the_method && the_method.respond_to?(:arity) # Is this original object#method?
232
+ method_tuple(the_method) # Yes, we are good.
233
+ end
234
+ elsif object.respond_to?(:instance_method) # Is this an unbound method?
235
+ method_tuple(object.instance_method(name))
236
+ end
237
+ end
238
+ tuple || [ name.to_s, '(?)', '?' ] # Return WTF default if all the above fails.
239
+ end
240
+
241
+ width = (tuples.size - 1).to_s.size
242
+ name_width = tuples.map { |item| item[0].size }.max || 0
243
+ args_width = tuples.map { |item| item[1].size }.max || 0
244
+
245
+ data = tuples.inject([]) do |arr, item|
246
+ index = indent
247
+ index << "[#{arr.size.to_s.rjust(width)}]" if @options[:index]
248
+ indented do
249
+ arr << "#{index} #{colorize(item[0].rjust(name_width), :method)}#{colorize(item[1].ljust(args_width), :args)} #{colorize(item[2], :class)}"
250
+ end
251
+ end
252
+
253
+ "[\n" << data.join("\n") << "\n#{outdent}]"
254
+ end
255
+
256
+ # Return [ name, arguments, owner ] tuple for a given method.
257
+ #------------------------------------------------------------------------------
258
+ def method_tuple(method)
259
+ if method.respond_to?(:parameters) # Ruby 1.9.2+
260
+ # See http://ruby.runpaint.org/methods#method-objects-parameters
261
+ args = method.parameters.inject([]) do |arr, (type, name)|
262
+ name ||= (type == :block ? 'block' : "arg#{arr.size + 1}")
263
+ arr << case type
264
+ when :req then name.to_s
265
+ when :opt, :rest then "*#{name}"
266
+ when :block then "&#{name}"
267
+ else '?'
268
+ end
269
+ end
270
+ else # See http://ruby-doc.org/core/classes/Method.html#M001902
271
+ args = (1..method.arity.abs).map { |i| "arg#{i}" }
272
+ args[-1] = "*#{args[-1]}" if method.arity < 0
273
+ end
274
+
275
+ # method.to_s formats to handle:
276
+ #
277
+ # #<Method: Fixnum#zero?>
278
+ # #<Method: Fixnum(Integer)#years>
279
+ # #<Method: User(#<Module:0x00000103207c00>)#_username>
280
+ # #<Method: User(id: integer, username: string).table_name>
281
+ # #<Method: User(id: integer, username: string)(ActiveRecord::Base).current>
282
+ # #<UnboundMethod: Hello#world>
283
+ #
284
+ if method.to_s =~ /(Unbound)*Method: (.*)[#\.]/
285
+ unbound, klass = $1 && '(unbound)', $2
286
+ if klass && klass =~ /(\(\w+:\s.*?\))/ # Is this ActiveRecord-style class?
287
+ klass.sub!($1, '') # Yes, strip the fields leaving class name only.
288
+ end
289
+ owner = "#{klass}#{unbound}".gsub('(', ' (')
290
+ end
291
+
292
+ [ method.name.to_s, "(#{args.join(', ')})", owner.to_s ]
293
+ end
294
+
295
+ # Format hash keys as plain strings regardless of underlying data type.
296
+ #------------------------------------------------------------------------------
297
+ def plain_single_line
298
+ plain, multiline = @options[:plain], @options[:multiline]
299
+ @options[:plain], @options[:multiline] = true, false
300
+ yield
301
+ ensure
302
+ @options[:plain], @options[:multiline] = plain, multiline
303
+ end
304
+
305
+ # Utility methods.
306
+ #------------------------------------------------------------------------------
307
+ def align(value, width)
308
+ if @options[:multiline]
309
+ if @options[:indent] > 0
310
+ value.rjust(width)
311
+ elsif @options[:indent] == 0
312
+ indent + value.ljust(width)
313
+ else
314
+ indent[0, @indentation + @options[:indent]] + value.ljust(width)
315
+ end
316
+ else
317
+ value
318
+ end
319
+ end
320
+
321
+ def indented
322
+ @indentation += @options[:indent].abs
323
+ yield
324
+ ensure
325
+ @indentation -= @options[:indent].abs
326
+ end
327
+
328
+ def left_aligned
329
+ current, @options[:indent] = @options[:indent], 0
330
+ yield
331
+ ensure
332
+ @options[:indent] = current
333
+ end
334
+
335
+ def silently
336
+ current, Exception.log_exceptions = Exception.log_exceptions, false
337
+ yield
338
+ ensure
339
+ Exception.log_exceptions = current
340
+ end
341
+
342
+ def indent
343
+ ' ' * @indentation
344
+ end
345
+
346
+ def outdent
347
+ ' ' * (@indentation - @options[:indent].abs)
348
+ end
349
+
350
+ # To support limited output, for example:
351
+ #
352
+ # ap ('a'..'z').to_a, :limit => 3
353
+ # [
354
+ # [ 0] "a",
355
+ # [ 1] .. [24],
356
+ # [25] "z"
357
+ # ]
358
+ #
359
+ # ap (1..100).to_a, :limit => true # Default limit is 7.
360
+ # [
361
+ # [ 0] 1,
362
+ # [ 1] 2,
363
+ # [ 2] 3,
364
+ # [ 3] .. [96],
365
+ # [97] 98,
366
+ # [98] 99,
367
+ # [99] 100
368
+ # ]
369
+ #------------------------------------------------------------------------------
370
+ def should_be_limited?
371
+ @options[:limit] == true or (@options[:limit].is_a?(Fixnum) and @options[:limit] > 0)
372
+ end
373
+
374
+ def get_limit_size
375
+ @options[:limit] == true ? DEFAULT_LIMIT_SIZE : @options[:limit]
376
+ end
377
+
378
+ def limited(data, width, is_hash = false)
379
+ limit = get_limit_size
380
+ if data.length <= limit
381
+ data
382
+ else
383
+ # Calculate how many elements to be displayed above and below the separator.
384
+ head = limit / 2
385
+ tail = head - (limit - 1) % 2
386
+
387
+ # Add the proper elements to the temp array and format the separator.
388
+ temp = data[0, head] + [ nil ] + data[-tail, tail]
389
+
390
+ if is_hash
391
+ temp[head] = "#{indent}#{data[head].strip} .. #{data[data.length - tail - 1].strip}"
392
+ else
393
+ temp[head] = "#{indent}[#{head.to_s.rjust(width)}] .. [#{data.length - tail - 1}]"
394
+ end
395
+
396
+ temp
397
+ end
398
+ end
399
+ end
400
+ end
@@ -0,0 +1,143 @@
1
+ # Copyright (c) 2010-2012 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 AwesomePrint
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?(MotionRepl)
20
+ end
21
+ end
22
+
23
+ class Inspector
24
+ attr_accessor :options
25
+
26
+ AP = :__awesome_print__
27
+
28
+ def initialize(options = {})
29
+ @options = {
30
+ :indent => 4, # Indent using 4 spaces.
31
+ :index => true, # Display array indices.
32
+ :multiline => true, # Display in multiple lines.
33
+ :plain => false, # Use colors.
34
+ :raw => false, # Do not recursively format object instance variables.
35
+ :sort_keys => false, # Do not sort hash keys.
36
+ :limit => false, # Limit large output for arrays and hashes. Set to a boolean or integer.
37
+ :color => {
38
+ :args => :pale,
39
+ :array => :white,
40
+ :bigdecimal => :blue,
41
+ :class => :yellow,
42
+ :date => :greenish,
43
+ :falseclass => :red,
44
+ :fixnum => :blue,
45
+ :float => :blue,
46
+ :hash => :pale,
47
+ :keyword => :cyan,
48
+ :method => :purpleish,
49
+ :nilclass => :red,
50
+ :rational => :blue,
51
+ :string => :yellowish,
52
+ :struct => :pale,
53
+ :symbol => :cyanish,
54
+ :time => :greenish,
55
+ :trueclass => :green,
56
+ :variable => :cyanish
57
+ }
58
+ }
59
+
60
+ # Merge custom defaults and let explicit options parameter override them.
61
+ merge_custom_defaults!
62
+ merge_options!(options)
63
+
64
+ @formatter = AwesomePrint::Formatter.new(self)
65
+ Thread.current[AP] ||= []
66
+ end
67
+
68
+ # Dispatcher that detects data nesting and invokes object-aware formatter.
69
+ #------------------------------------------------------------------------------
70
+ def awesome(object)
71
+ if Thread.current[AP].include?(object.object_id)
72
+ nested(object)
73
+ else
74
+ begin
75
+ Thread.current[AP] << object.object_id
76
+ unnested(object)
77
+ ensure
78
+ Thread.current[AP].pop
79
+ end
80
+ end
81
+ end
82
+
83
+ # Return true if we are to colorize the output.
84
+ #------------------------------------------------------------------------------
85
+ def colorize?
86
+ AwesomePrint.force_colors ||= false
87
+ AwesomePrint.force_colors || (STDOUT.tty? && ((ENV['TERM'] && ENV['TERM'] != 'dumb') || ENV['ANSICON']))
88
+ end
89
+
90
+ private
91
+
92
+ # Format nested data, for example:
93
+ # arr = [1, 2]; arr << arr
94
+ # => [1,2, [...]]
95
+ # hash = { :a => 1 }; hash[:b] = hash
96
+ # => { :a => 1, :b => {...} }
97
+ #------------------------------------------------------------------------------
98
+ def nested(object)
99
+ case printable(object)
100
+ when :array then @formatter.colorize("[...]", :array)
101
+ when :hash then @formatter.colorize("{...}", :hash)
102
+ when :struct then @formatter.colorize("{...}", :struct)
103
+ else @formatter.colorize("...#{object.class}...", :class)
104
+ end
105
+ end
106
+
107
+ #------------------------------------------------------------------------------
108
+ def unnested(object)
109
+ @formatter.format(object, printable(object))
110
+ end
111
+
112
+ # Turn class name into symbol, ex: Hello::World => :hello_world. Classes that
113
+ # inherit from Array, Hash, File, Dir, and Struct are treated as the base class.
114
+ #------------------------------------------------------------------------------
115
+ def printable(object)
116
+ case object
117
+ when Array then :array
118
+ when Hash then :hash
119
+ when File then :file
120
+ when Dir then :dir
121
+ when Struct then :struct
122
+ else object.class.to_s.gsub(/:+/, "_").downcase.to_sym
123
+ end
124
+ end
125
+
126
+ # Update @options by first merging the :color hash and then the remaining keys.
127
+ #------------------------------------------------------------------------------
128
+ def merge_options!(options = {})
129
+ @options[:color].merge!(options.delete(:color) || {})
130
+ @options.merge!(options)
131
+ end
132
+
133
+ # Load ~/.aprc file with custom defaults that override default options.
134
+ #------------------------------------------------------------------------------
135
+ def merge_custom_defaults!
136
+ dotfile = File.join(ENV["HOME"], ".aprc")
137
+ load dotfile if File.readable?(dotfile)
138
+ merge_options!(AwesomePrint.defaults) if AwesomePrint.defaults.is_a?(Hash)
139
+ rescue => e
140
+ $stderr.puts "Could not load #{dotfile}: #{e}"
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,63 @@
1
+ # Copyright (c) 2010-2012 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 AwesomePrint
7
+ module Painter
8
+ extend self
9
+ #
10
+ # ANSI color codes:
11
+ # \e => escape
12
+ # 30 => color base
13
+ # 1 => bright
14
+ # 0 => normal
15
+ #
16
+ %w(gray red green yellow blue purple cyan white).each_with_index do |color, i|
17
+ define_method color do |str|
18
+ "\e[1;#{30+i}m#{str}\e[0m"
19
+ end
20
+
21
+ define_method "#{color}ish" do |str|
22
+ "\e[0;#{30+i}m#{str}\e[0m"
23
+ end
24
+ end
25
+
26
+ alias :black :grayish
27
+ alias :pale :whiteish
28
+ end
29
+ end
30
+
31
+ #
32
+ # The method_missing-based approach works with RubyMotion 1.24 or earlier.
33
+ #
34
+ # module AwesomePrint
35
+ # class Painter
36
+ # #
37
+ # # ANSI color codes:
38
+ # # \e => escape
39
+ # # 30 => color base
40
+ # # 1 => bright
41
+ # # 0 => normal
42
+ # #
43
+ # ANSI = { gray: 30, red: 31, green: 32, yellow: 33, blue: 34, purple: 35, cyan: 36, white: 37 }
44
+ # METHOD_NAMES = ANSI.keys + [ :black, :pale ] + ANSI.keys.map { |key| :"#{key}ish" }
45
+ #
46
+ # def self.method_missing(method, *args)
47
+ # return super if !respond_to?(method)
48
+ #
49
+ # method = :grayish if method == :black
50
+ # method = :whiteish if method == :pale
51
+ #
52
+ # if method.to_s =~ /(.+?)ish/
53
+ # "\e[0;#{ANSI[$1.to_sym]}"
54
+ # else
55
+ # "\e[1;#{ANSI[method]}"
56
+ # end << "m#{args[0]}\e[0m"
57
+ # end
58
+ #
59
+ # def self.respond_to?(method)
60
+ # METHOD_NAMES.include?(method)
61
+ # end
62
+ # end
63
+ # end
@@ -0,0 +1,10 @@
1
+ # Copyright (c) 2010-2012 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 AwesomePrint
7
+ def self.version
8
+ "0.1.0"
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ # -*- coding: utf-8 -*-
2
+ $:.unshift("/Library/RubyMotion/lib")
3
+ require "motion/project"
4
+ require "quickie_motion"
5
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/awesome_print_motion")
6
+
7
+ Motion::Project::App.setup do |app|
8
+ app.name = "awesome_print_test"
9
+ end
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: awesome_print_motion
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Michael Dvorkin
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-10-23 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: quickie
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: ! 'Great RubyMotion dubugging companion: pretty print RubyMotion objects
47
+ to visualize their structure'
48
+ email: mike@dvorkin.net
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - CHANGELOG
54
+ - Gemfile
55
+ - LICENSE
56
+ - Rakefile
57
+ - README.md
58
+ - lib/ap.rb
59
+ - lib/awesome_print_motion/core_ext/array.rb
60
+ - lib/awesome_print_motion/core_ext/class.rb
61
+ - lib/awesome_print_motion/core_ext/kernel.rb
62
+ - lib/awesome_print_motion/core_ext/object.rb
63
+ - lib/awesome_print_motion/formatter.rb
64
+ - lib/awesome_print_motion/inspector.rb
65
+ - lib/awesome_print_motion/painter.rb
66
+ - lib/awesome_print_motion/version.rb
67
+ - lib/awesome_print_motion.rb
68
+ - .gitignore
69
+ - test/Rakefile
70
+ homepage: http://github.com/michaeldv/awesome_print_motion
71
+ licenses: []
72
+ post_install_message:
73
+ rdoc_options: []
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ! '>='
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ requirements: []
89
+ rubyforge_project:
90
+ rubygems_version: 1.8.24
91
+ signing_key:
92
+ specification_version: 3
93
+ summary: Pretty print RubyMotion objects with proper indentation and colors
94
+ test_files:
95
+ - test/Rakefile