awesome_print_motion 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.
@@ -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