diff --git a/lib/ap.rb b/lib/ap.rb
index 835355b..3922810 100755
--- a/lib/ap.rb
+++ b/lib/ap.rb
@@ -7,7 +7,8 @@
require File.dirname(__FILE__) + "/ap/core_ext/#{file}"
end
-require File.dirname(__FILE__) + "/ap/awesome_print"
+require File.dirname(__FILE__) + "/ap/inspector"
+require File.dirname(__FILE__) + "/ap/formatter"
require File.dirname(__FILE__) + "/ap/core_ext/logger" if defined?(Logger)
require File.dirname(__FILE__) + "/ap/mixin/action_view" if defined?(ActionView)
diff --git a/lib/ap/awesome_print.rb b/lib/ap/awesome_print.rb
deleted file mode 100755
index e17fb36..0000000
--- a/lib/ap/awesome_print.rb
+++ /dev/null
@@ -1,332 +0,0 @@
-# Copyright (c) 2010-2011 Michael Dvorkin
-#
-# Awesome Print is freely distributable under the terms of MIT license.
-# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
-#------------------------------------------------------------------------------
-require "shellwords"
-
-class AwesomePrint
- AP = :__awesome_print__ unless defined?(AwesomePrint::AP)
- CORE = [ :array, :hash, :class, :file, :dir, :bigdecimal, :rational, :struct, :method, :unboundmethod ] unless defined?(AwesomePrint::CORE)
-
- def initialize(options = {})
- @options = {
- :multiline => true,
- :plain => false,
- :indent => 4,
- :index => true,
- :sorted_hash_keys => false,
- :color => {
- :array => :white,
- :bigdecimal => :blue,
- :class => :yellow,
- :date => :greenish,
- :falseclass => :red,
- :fixnum => :blue,
- :float => :blue,
- :hash => :pale,
- :struct => :pale,
- :nilclass => :red,
- :string => :yellowish,
- :symbol => :cyanish,
- :time => :greenish,
- :trueclass => :green,
- :method => :purpleish,
- :args => :pale
- }
- }
-
- # Merge custom defaults and let explicit options parameter override them.
- merge_custom_defaults!
- merge_options!(options)
-
- @indentation = @options[:indent].abs
- Thread.current[AP] ||= []
- end
-
- private
-
- # Format an array.
- #------------------------------------------------------------------------------
- def awesome_array(a)
- return "[]" if a == []
-
- if a.instance_variable_defined?('@__awesome_methods__')
- methods_array(a)
- elsif @options[:multiline]
- width = (a.size - 1).to_s.size
- data = a.inject([]) do |arr, item|
- index = if @options[:index]
- colorize("#{indent}[#{arr.size.to_s.rjust(width)}] ", :array)
- else
- colorize(indent, :array)
- end
- indented do
- arr << (index << awesome(item))
- end
- end
- "[\n" << data.join(",\n") << "\n#{outdent}]"
- else
- "[ " << a.map{ |item| awesome(item) }.join(", ") << " ]"
- end
- end
-
- # Format a hash. If @options[:indent] if negative left align hash keys.
- #------------------------------------------------------------------------------
- def awesome_hash(h)
- return "{}" if h == {}
-
- keys = @options[:sorted_hash_keys] ? h.keys.sort { |a, b| a.to_s <=> b.to_s } : h.keys
- data = keys.map do |key|
- plain_single_line do
- [ awesome(key), h[key] ]
- end
- end
-
- width = data.map { |key, | key.size }.max || 0
- width += @indentation if @options[:indent] > 0
-
- data = data.map do |key, value|
- if @options[:multiline]
- formatted_key = (@options[:indent] >= 0 ? key.rjust(width) : indent + key.ljust(width))
- else
- formatted_key = key
- end
- indented do
- formatted_key << colorize(" => ", :hash) << awesome(value)
- end
- end
- if @options[:multiline]
- "{\n" << data.join(",\n") << "\n#{outdent}}"
- else
- "{ #{data.join(', ')} }"
- end
- end
-
- # Format a Struct. If @options[:indent] if negative left align hash keys.
- #------------------------------------------------------------------------------
- def awesome_struct(s)
- h = {}
- s.each_pair { |k,v| h[k] = v }
- awesome_hash(h)
- end
-
- # Format Class object.
- #------------------------------------------------------------------------------
- def awesome_class(c)
- if superclass = c.superclass # <-- Assign and test if nil.
- awesome_self(c, :with => " < #{superclass}")
- else
- awesome_self(c)
- end
- end
-
- # Format File object.
- #------------------------------------------------------------------------------
- def awesome_file(f)
- ls = File.directory?(f) ? `ls -adlF #{f.path.shellescape}` : `ls -alF #{f.path.shellescape}`
- awesome_self(f, :with => ls.empty? ? nil : "\n#{ls.chop}")
- end
-
- # Format Dir object.
- #------------------------------------------------------------------------------
- def awesome_dir(d)
- ls = `ls -alF #{d.path.shellescape}`
- awesome_self(d, :with => ls.empty? ? nil : "\n#{ls.chop}")
- end
-
- # Format BigDecimal and Rational objects by convering them to Float.
- #------------------------------------------------------------------------------
- def awesome_bigdecimal(n)
- awesome_self(n.to_f, :as => :bigdecimal)
- end
- alias :awesome_rational :awesome_bigdecimal
-
- # Format a method.
- #------------------------------------------------------------------------------
- def awesome_method(m)
- name, args, owner = method_tuple(m)
- "#{colorize(owner, :class)}##{colorize(name, :method)}#{colorize(args, :args)}"
- end
- alias :awesome_unboundmethod :awesome_method
-
- # Catch all method to format an arbitrary object.
- #------------------------------------------------------------------------------
- def awesome_self(object, appear = {})
- colorize(object.inspect.to_s << appear[:with].to_s, appear[:as] || declassify(object))
- end
-
- # Dispatcher that detects data nesting and invokes object-aware formatter.
- #------------------------------------------------------------------------------
- def awesome(object)
- if Thread.current[AP].include?(object.object_id)
- nested(object)
- else
- begin
- Thread.current[AP] << object.object_id
- send(:"awesome_#{printable(object)}", object)
- ensure
- Thread.current[AP].pop
- end
- end
- end
-
- # Format object.methods array.
- #------------------------------------------------------------------------------
- def methods_array(a)
- object = a.instance_variable_get('@__awesome_methods__')
- tuples = a.map do |name|
- if object.respond_to?(name, true) # Regular method?
- method_tuple(object.method(name))
- elsif object.respond_to?(:instance_method) # Unbound method?
- method_tuple(object.instance_method(name))
- else # WTF method.
- [ name.to_s, '(?)', '' ]
- end
- end
-
- width = (tuples.size - 1).to_s.size
- name_width = tuples.map { |item| item[0].size }.max || 0
- args_width = tuples.map { |item| item[1].size }.max || 0
-
- data = tuples.inject([]) do |arr, item|
- index = if @options[:index]
- "#{indent}[#{arr.size.to_s.rjust(width)}]"
- else
- indent
- end
- indented do
- arr << "#{index} #{colorize(item[0].rjust(name_width), :method)}#{colorize(item[1].ljust(args_width), :args)} #{colorize(item[2], :class)}"
- end
- end
-
- "[\n" << data.join("\n") << "\n#{outdent}]"
- end
-
- # Format nested data, for example:
- # arr = [1, 2]; arr << arr
- # => [1,2, [...]]
- # hsh = { :a => 1 }; hsh[:b] = hsh
- # => { :a => 1, :b => {...} }
- #------------------------------------------------------------------------------
- def nested(object)
- case printable(object)
- when :array then colorize("[...]", :array)
- when :hash then colorize("{...}", :hash)
- when :struct then colorize("{...}", :struct)
- else colorize("...#{object.class}...", :class)
- end
- end
-
- # Return one of the "core" types that have a formatter of :self otherwise.
- #------------------------------------------------------------------------------
- def printable(object)
- CORE.grep(declassify(object))[0] || :self
- end
-
- # Turn class name into symbol, ex: Hello::World => :hello_world. Classes that
- # inherit from Array, Hash, File, Dir, and Struct are treated as the base class.
- #------------------------------------------------------------------------------
- def declassify(object)
- case object
- when Array then :array
- when Hash then :hash
- when File then :file
- when Dir then :dir
- when Struct then :struct
- else object.class.to_s.gsub(/:+/, "_").downcase.to_sym
- end
- end
-
- # Pick the color and apply it to the given string as necessary.
- #------------------------------------------------------------------------------
- def colorize(s, type)
- if @options[:plain] || @options[:color][type].nil?
- s
- else
- s.send(@options[:color][type])
- end
- end
-
- # Return [ name, arguments, owner ] tuple for a given method.
- #------------------------------------------------------------------------------
- def method_tuple(method)
- if method.respond_to?(:parameters) # Ruby 1.9.2+
- # See http://ruby.runpaint.org/methods#method-objects-parameters
- args = method.parameters.inject([]) do |arr, (type, name)|
- name ||= (type == :block ? 'block' : "arg#{arr.size + 1}")
- arr << case type
- when :req then name.to_s
- when :opt, :rest then "*#{name}"
- when :block then "{name}"
- else '?'
- end
- end
- else # See http://ruby-doc.org/core/classes/Method.html#M001902
- args = (1..method.arity.abs).map { |i| "arg#{i}" }
- args[-1] = "*#{args[-1]}" if method.arity < 0
- end
-
- if method.to_s =~ /(Unbound)*Method: (.*?)[#\.]/
- owner = "#{$2}#{$1 ? '(unbound)' : ''}".gsub('(', ' (')
- end
-
- [ method.name.to_s, "(#{args.join(', ')})", owner.to_s ]
- end
-
- # Format hash keys as plain string regardless of underlying data type.
- #------------------------------------------------------------------------------
- def plain_single_line
- plain, multiline = @options[:plain], @options[:multiline]
- @options[:plain], @options[:multiline] = true, false
- yield
- ensure
- @options[:plain], @options[:multiline] = plain, multiline
- end
-
- #------------------------------------------------------------------------------
- def indented
- @indentation += @options[:indent].abs
- yield
- ensure
- @indentation -= @options[:indent].abs
- end
-
- def indent
- @indent = ' ' * @indentation
- end
-
- def outdent
- @outdent = ' ' * (@indentation - @options[:indent].abs)
- end
-
- # Update @options by first merging the :color hash and then the remaining keys.
- #------------------------------------------------------------------------------
- def merge_options!(options = {})
- @options[:color].merge!(options.delete(:color) || {})
- @options.merge!(options)
- end
-
- # Load ~/.aprc file with custom defaults that override default options.
- #------------------------------------------------------------------------------
- def merge_custom_defaults!
- dotfile = File.join(ENV["HOME"], ".aprc")
- if File.readable?(dotfile)
- load dotfile
- merge_options!(self.class.defaults)
- end
- rescue => e
- $stderr.puts "Could not load #{dotfile}: #{e}"
- end
-
- # Class accessors for custom defaults.
- #------------------------------------------------------------------------------
- def self.defaults
- @@defaults ||= {}
- end
-
- def self.defaults=(args = {})
- @@defaults = args
- end
-
-end
diff --git a/lib/ap/core_ext/kernel.rb b/lib/ap/core_ext/kernel.rb
index 5f93600..ab043b9 100644
--- a/lib/ap/core_ext/kernel.rb
+++ b/lib/ap/core_ext/kernel.rb
@@ -6,7 +6,7 @@
module Kernel
def ai(options = {})
- ap = AwesomePrint.new(options)
+ ap = AwesomePrint::Inspector.new(options)
ap.send(:awesome, self)
end
alias :awesome_inspect :ai
diff --git a/lib/ap/core_ext/logger.rb b/lib/ap/core_ext/logger.rb
index a0e5720..04a5920 100644
--- a/lib/ap/core_ext/logger.rb
+++ b/lib/ap/core_ext/logger.rb
@@ -3,16 +3,17 @@
# Awesome Print is freely distributable under the terms of MIT license.
# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
#------------------------------------------------------------------------------
-module AwesomePrintLogger
+module AwesomePrint
+ module Logger
- # Add ap method to logger
- #------------------------------------------------------------------------------
- def ap(object, level = nil)
- level ||= AwesomePrint.defaults[:log_level] || :debug
- send level, object.ai
+ # Add ap method to logger
+ #------------------------------------------------------------------------------
+ def ap(object, level = nil)
+ level ||= AwesomePrint.defaults[:log_level] || :debug
+ send level, object.ai
+ end
end
-
end
-Logger.send(:include, AwesomePrintLogger)
-ActiveSupport::BufferedLogger.send(:include, AwesomePrintLogger) if defined?(::ActiveSupport::BufferedLogger)
+Logger.send(:include, AwesomePrint::Logger)
+ActiveSupport::BufferedLogger.send(:include, AwesomePrint::Logger) if defined?(::ActiveSupport::BufferedLogger)
diff --git a/lib/ap/formatter.rb b/lib/ap/formatter.rb
new file mode 100755
index 0000000..7dab041
--- /dev/null
+++ b/lib/ap/formatter.rb
@@ -0,0 +1,238 @@
+# Copyright (c) 2010-2011 Michael Dvorkin
+#
+# Awesome Print is freely distributable under the terms of MIT license.
+# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
+#------------------------------------------------------------------------------
+require "shellwords"
+
+module AwesomePrint
+ class Formatter
+
+ CORE = [ :array, :hash, :class, :file, :dir, :bigdecimal, :rational, :struct, :method, :unboundmethod ]
+
+ def initialize(inspector)
+ @inspector = inspector
+ @options = inspector.options
+ @indentation = @options[:indent].abs
+ end
+
+ # Main entry point to format an object.
+ #------------------------------------------------------------------------------
+ def format(object, type = nil)
+ klass = cast(object, type)
+ return send(:"awesome_#{klass}", object) if klass != :self
+ send(:awesome_self, object, :as => type) # Catch all that falls back on object.inspect.
+ end
+
+ # Hook this when adding custom formatters. Check out how it's done in
+ # ap/lib/mixin/active_record.rb
+ #------------------------------------------------------------------------------
+ def cast(object, type)
+ CORE.grep(type)[0] || :self
+ end
+
+ # Pick the color and apply it to the given string as necessary.
+ #------------------------------------------------------------------------------
+ def colorize(s, type = nil)
+ return s if @options[:plain] || @options[:color][type].nil?
+ s.send(@options[:color][type])
+ end
+
+
+ private
+
+ # Catch all method to format an arbitrary object.
+ #------------------------------------------------------------------------------
+ def awesome_self(object, appear = {})
+ colorize(object.inspect.to_s << appear[:with].to_s, appear[:as])
+ end
+
+ # Format an array.
+ #------------------------------------------------------------------------------
+ def awesome_array(a)
+ return "[]" if a == []
+
+ if a.instance_variable_defined?('@__awesome_methods__')
+ methods_array(a)
+ elsif @options[:multiline]
+ width = (a.size - 1).to_s.size
+ data = a.inject([]) do |arr, item|
+ index = if @options[:index]
+ colorize("#{indent}[#{arr.size.to_s.rjust(width)}] ", :array)
+ else
+ colorize(indent, :array)
+ end
+ indented do
+ arr << (index << @inspector.send(:awesome, item))
+ end
+ end
+ "[\n" << data.join(",\n") << "\n#{outdent}]"
+ else
+ "[ " << a.map{ |item| @inspector.send(:awesome, item) }.join(", ") << " ]"
+ end
+ end
+
+ # Format a hash. If @options[:indent] if negative left align hash keys.
+ #------------------------------------------------------------------------------
+ def awesome_hash(h)
+ return "{}" if h == {}
+
+ keys = @options[:sort_keys] ? h.keys.sort { |a, b| a.to_s <=> b.to_s } : h.keys
+ data = keys.map do |key|
+ plain_single_line do
+ [ @inspector.send(:awesome, key), h[key] ]
+ end
+ end
+
+ width = data.map { |key, | key.size }.max || 0
+ width += @indentation if @options[:indent] > 0
+
+ data = data.map do |key, value|
+ if @options[:multiline]
+ formatted_key = (@options[:indent] >= 0 ? key.rjust(width) : indent + key.ljust(width))
+ else
+ formatted_key = key
+ end
+ indented do
+ formatted_key << colorize(" => ", :hash) << @inspector.send(:awesome, value)
+ end
+ end
+ if @options[:multiline]
+ "{\n" << data.join(",\n") << "\n#{outdent}}"
+ else
+ "{ #{data.join(', ')} }"
+ end
+ end
+
+ # Format a Struct. If @options[:indent] if negative left align hash keys.
+ #------------------------------------------------------------------------------
+ def awesome_struct(s)
+ h = {}
+ s.each_pair { |k,v| h[k] = v }
+ awesome_hash(h)
+ end
+
+ # Format Class object.
+ #------------------------------------------------------------------------------
+ def awesome_class(c)
+ if superclass = c.superclass # <-- Assign and test if nil.
+ awesome_self(c, :as => :class, :with => " < #{superclass}")
+ else
+ awesome_self(c, :as => :class)
+ end
+ end
+
+ # Format File object.
+ #------------------------------------------------------------------------------
+ def awesome_file(f)
+ ls = File.directory?(f) ? `ls -adlF #{f.path.shellescape}` : `ls -alF #{f.path.shellescape}`
+ awesome_self(f, :as => :file, :with => ls.empty? ? nil : "\n#{ls.chop}")
+ end
+
+ # Format Dir object.
+ #------------------------------------------------------------------------------
+ def awesome_dir(d)
+ ls = `ls -alF #{d.path.shellescape}`
+ awesome_self(d, :as => :dir, :with => ls.empty? ? nil : "\n#{ls.chop}")
+ end
+
+ # Format BigDecimal and Rational objects by convering them to Float.
+ #------------------------------------------------------------------------------
+ def awesome_bigdecimal(n)
+ awesome_self(n.to_f, :as => :bigdecimal)
+ end
+ alias :awesome_rational :awesome_bigdecimal
+
+ # Format a method.
+ #------------------------------------------------------------------------------
+ def awesome_method(m)
+ name, args, owner = method_tuple(m)
+ "#{colorize(owner, :class)}##{colorize(name, :method)}#{colorize(args, :args)}"
+ end
+ alias :awesome_unboundmethod :awesome_method
+
+ # Format object.methods array.
+ #------------------------------------------------------------------------------
+ def methods_array(a)
+ object = a.instance_variable_get('@__awesome_methods__')
+ tuples = a.map do |name|
+ if object.respond_to?(name, true) # Regular method?
+ method_tuple(object.method(name))
+ elsif object.respond_to?(:instance_method) # Unbound method?
+ method_tuple(object.instance_method(name))
+ else # WTF method.
+ [ name.to_s, '(?)', '' ]
+ end
+ end
+
+ width = (tuples.size - 1).to_s.size
+ name_width = tuples.map { |item| item[0].size }.max || 0
+ args_width = tuples.map { |item| item[1].size }.max || 0
+
+ data = tuples.inject([]) do |arr, item|
+ index = if @options[:index]
+ "#{indent}[#{arr.size.to_s.rjust(width)}]"
+ else
+ indent
+ end
+ indented do
+ arr << "#{index} #{colorize(item[0].rjust(name_width), :method)}#{colorize(item[1].ljust(args_width), :args)} #{colorize(item[2], :class)}"
+ end
+ end
+
+ "[\n" << data.join("\n") << "\n#{outdent}]"
+ end
+
+ # Return [ name, arguments, owner ] tuple for a given method.
+ #------------------------------------------------------------------------------
+ def method_tuple(method)
+ if method.respond_to?(:parameters) # Ruby 1.9.2+
+ # See http://ruby.runpaint.org/methods#method-objects-parameters
+ args = method.parameters.inject([]) do |arr, (type, name)|
+ name ||= (type == :block ? 'block' : "arg#{arr.size + 1}")
+ arr << case type
+ when :req then name.to_s
+ when :opt, :rest then "*#{name}"
+ when :block then "{name}"
+ else '?'
+ end
+ end
+ else # See http://ruby-doc.org/core/classes/Method.html#M001902
+ args = (1..method.arity.abs).map { |i| "arg#{i}" }
+ args[-1] = "*#{args[-1]}" if method.arity < 0
+ end
+
+ if method.to_s =~ /(Unbound)*Method: (.*?)[#\.]/
+ owner = "#{$2}#{$1 ? '(unbound)' : ''}".gsub('(', ' (')
+ end
+
+ [ method.name.to_s, "(#{args.join(', ')})", owner.to_s ]
+ end
+
+ # Format hash keys as plain string regardless of underlying data type.
+ #------------------------------------------------------------------------------
+ def plain_single_line
+ plain, multiline = @options[:plain], @options[:multiline]
+ @options[:plain], @options[:multiline] = true, false
+ yield
+ ensure
+ @options[:plain], @options[:multiline] = plain, multiline
+ end
+
+ #------------------------------------------------------------------------------
+ def indented
+ @indentation += @options[:indent].abs
+ yield
+ ensure
+ @indentation -= @options[:indent].abs
+ end
+
+ def indent
+ ' ' * @indentation
+ end
+
+ def outdent
+ ' ' * (@indentation - @options[:indent].abs)
+ end
+ end
+end
diff --git a/lib/ap/inspector.rb b/lib/ap/inspector.rb
new file mode 100755
index 0000000..ea9a7c6
--- /dev/null
+++ b/lib/ap/inspector.rb
@@ -0,0 +1,122 @@
+# Copyright (c) 2010-2011 Michael Dvorkin
+#
+# Awesome Print is freely distributable under the terms of MIT license.
+# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
+#------------------------------------------------------------------------------
+module AwesomePrint
+
+ class << self # Class accessors for custom defaults.
+ attr_accessor :defaults
+ end
+
+ class Inspector
+ attr_accessor :options
+
+ AP = :__awesome_print__
+
+ def initialize(options = {})
+ @options = {
+ :color => {
+ :array => :white,
+ :bigdecimal => :blue,
+ :class => :yellow,
+ :date => :greenish,
+ :falseclass => :red,
+ :fixnum => :blue,
+ :float => :blue,
+ :hash => :pale,
+ :struct => :pale,
+ :nilclass => :red,
+ :string => :yellowish,
+ :symbol => :cyanish,
+ :time => :greenish,
+ :trueclass => :green,
+ :method => :purpleish,
+ :args => :pale
+ },
+ :indent => 4,
+ :index => true,
+ :multiline => true,
+ :plain => false,
+ :sort_keys => false
+ }
+
+ # Merge custom defaults and let explicit options parameter override them.
+ merge_custom_defaults!
+ merge_options!(options)
+
+ @formatter = AwesomePrint::Formatter.new(self)
+ Thread.current[AP] ||= []
+ end
+
+ private
+
+ # Dispatcher that detects data nesting and invokes object-aware formatter.
+ #------------------------------------------------------------------------------
+ def awesome(object)
+ if Thread.current[AP].include?(object.object_id)
+ nested(object)
+ else
+ begin
+ Thread.current[AP] << object.object_id
+ unnested(object)
+ ensure
+ Thread.current[AP].pop
+ end
+ end
+ end
+
+ # Format nested data, for example:
+ # arr = [1, 2]; arr << arr
+ # => [1,2, [...]]
+ # hash = { :a => 1 }; hash[:b] = hash
+ # => { :a => 1, :b => {...} }
+ #------------------------------------------------------------------------------
+ def nested(object)
+ case printable(object)
+ when :array then @formatter.colorize("[...]", :array)
+ when :hash then @formatter.colorize("{...}", :hash)
+ when :struct then @formatter.colorize("{...}", :struct)
+ else @formatter.colorize("...#{object.class}...", :class)
+ end
+ end
+
+ #------------------------------------------------------------------------------
+ def unnested(object)
+ @formatter.format(object, printable(object))
+ end
+
+ # Turn class name into symbol, ex: Hello::World => :hello_world. Classes that
+ # inherit from Array, Hash, File, Dir, and Struct are treated as the base class.
+ #------------------------------------------------------------------------------
+ def printable(object)
+ case object
+ when Array then :array
+ when Hash then :hash
+ when File then :file
+ when Dir then :dir
+ when Struct then :struct
+ else object.class.to_s.gsub(/:+/, "_").downcase.to_sym
+ end
+ end
+
+ # Update @options by first merging the :color hash and then the remaining keys.
+ #------------------------------------------------------------------------------
+ def merge_options!(options = {})
+ @options[:color].merge!(options.delete(:color) || {})
+ @options.merge!(options)
+ end
+
+ # Load ~/.aprc file with custom defaults that override default options.
+ #------------------------------------------------------------------------------
+ def merge_custom_defaults!
+ dotfile = File.join(ENV["HOME"], ".aprc")
+ if File.readable?(dotfile)
+ load dotfile
+ merge_options!(AwesomePrint.defaults)
+ end
+ rescue => e
+ $stderr.puts "Could not load #{dotfile}: #{e}"
+ end
+ end
+end
diff --git a/lib/ap/mixin/action_view.rb b/lib/ap/mixin/action_view.rb
index 1a34c6e..ab8ecd3 100644
--- a/lib/ap/mixin/action_view.rb
+++ b/lib/ap/mixin/action_view.rb
@@ -3,36 +3,37 @@
# Awesome Print is freely distributable under the terms of MIT license.
# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
#------------------------------------------------------------------------------
-module AwesomePrintActionView
+module AwesomePrint
+ module ActionView
- def self.included(base)
- unless base.const_defined?(:AP_ANSI_TO_HTML)
- hash = {} # Build ANSI => HTML color map.
- [ :gray, :red, :green, :yellow, :blue, :purple, :cyan, :white ].each_with_index do |color, i|
- hash["\033[1;#{30+i}m"] = color
+ def self.included(base)
+ unless base.const_defined?(:AP_ANSI_TO_HTML)
+ hash = {} # Build ANSI => HTML color map.
+ [ :gray, :red, :green, :yellow, :blue, :purple, :cyan, :white ].each_with_index do |color, i|
+ hash["\033[1;#{30+i}m"] = color
+ end
+ [ :black, :darkred, :darkgreen, :brown, :navy, :darkmagenta, :darkcyan, :slategray ].each_with_index do |color, i|
+ hash["\033[0;#{30+i}m"] = color
+ end
+ base.const_set(:AP_ANSI_TO_HTML, hash.freeze)
end
- [ :black, :darkred, :darkgreen, :brown, :navy, :darkmagenta, :darkcyan, :slategray ].each_with_index do |color, i|
- hash["\033[0;#{30+i}m"] = color
- end
- base.const_set(:AP_ANSI_TO_HTML, hash.freeze)
- end
- end
-
- def ap_debug(object, options = {})
- formatted = h(object.ai(options))
-
- unless options[:plain]
- self.class::AP_ANSI_TO_HTML.each do |key, value|
- formatted.gsub!(key, %Q||)
- end
- formatted.gsub!("\033[0m", "")
end
- content_tag(:pre, formatted, :class => "debug_dump")
+ def ap_debug(object, options = {})
+ formatted = h(object.ai(options))
+
+ unless options[:plain]
+ self.class::AP_ANSI_TO_HTML.each do |key, value|
+ formatted.gsub!(key, %Q||)
+ end
+ formatted.gsub!("\033[0m", "")
+ end
+
+ content_tag(:pre, formatted, :class => "debug_dump")
+ end
+
+ alias_method :ap, :ap_debug
end
-
- alias_method :ap, :ap_debug
-
end
-ActionView::Base.send(:include, AwesomePrintActionView) if defined?(ActionView)
+ActionView::Base.send(:include, AwesomePrint::ActionView) if defined?(ActionView)
diff --git a/lib/ap/mixin/active_record.rb b/lib/ap/mixin/active_record.rb
index 3f7a8cd..2fffd79 100644
--- a/lib/ap/mixin/active_record.rb
+++ b/lib/ap/mixin/active_record.rb
@@ -3,52 +3,52 @@
# Awesome Print is freely distributable under the terms of MIT license.
# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
#------------------------------------------------------------------------------
-module AwesomePrintActiveRecord
+module AwesomePrint
+ module ActiveRecord
- def self.included(base)
- base.send :alias_method, :printable_without_active_record, :printable
- base.send :alias_method, :printable, :printable_with_active_record
- end
+ def self.included(base)
+ base.send :alias_method, :cast_without_active_record, :cast
+ base.send :alias_method, :cast, :cast_with_active_record
+ end
- # Add ActiveRecord class names to the dispatcher pipeline.
- #------------------------------------------------------------------------------
- def printable_with_active_record(object)
- printable = printable_without_active_record(object)
- return printable if !defined?(ActiveRecord::Base)
-
- if printable == :self
- if object.is_a?(ActiveRecord::Base)
- printable = :active_record_instance
+ def cast_with_active_record(object, type)
+ cast = cast_without_active_record(object, type)
+ if defined?(::ActiveRecord)
+ if object.is_a?(::ActiveRecord::Base)
+ cast = :active_record_instance
+ elsif object.is_a?(Class) and object.ancestors.include?(::ActiveRecord::Base)
+ cast = :active_record_class
+ end
end
- elsif printable == :class and object.ancestors.include?(ActiveRecord::Base)
- printable = :active_record_class
+ cast
end
- printable
- end
- # Format ActiveRecord instance object.
- #------------------------------------------------------------------------------
- def awesome_active_record_instance(object)
- return object.inspect if !defined?(ActiveSupport::OrderedHash)
+ private
- data = object.class.column_names.inject(ActiveSupport::OrderedHash.new) do |hash, name|
- hash[name.to_sym] = object.send(name) if object.has_attribute?(name) || object.new_record?
- hash
+ # Format ActiveRecord instance object.
+ #------------------------------------------------------------------------------
+ def awesome_active_record_instance(object)
+ return object.inspect if !defined?(::ActiveSupport::OrderedHash)
+
+ data = object.class.column_names.inject(::ActiveSupport::OrderedHash.new) do |hash, name|
+ hash[name.to_sym] = object.send(name) if object.has_attribute?(name) || object.new_record?
+ hash
+ end
+ "#{object} " + awesome_hash(data)
end
- "#{object} " + awesome_hash(data)
- end
- # Format ActiveRecord class object.
- #------------------------------------------------------------------------------
- def awesome_active_record_class(object)
- return object.inspect if !defined?(ActiveSupport::OrderedHash) || !object.respond_to?(:columns)
+ # Format ActiveRecord class object.
+ #------------------------------------------------------------------------------
+ def awesome_active_record_class(object)
+ return object.inspect if !defined?(::ActiveSupport::OrderedHash) || !object.respond_to?(:columns)
- data = object.columns.inject(ActiveSupport::OrderedHash.new) do |hash, c|
- hash[c.name.to_sym] = c.type
- hash
+ data = object.columns.inject(::ActiveSupport::OrderedHash.new) do |hash, c|
+ hash[c.name.to_sym] = c.type
+ hash
+ end
+ "class #{object} < #{object.superclass} " << awesome_hash(data)
end
- "class #{object} < #{object.superclass} " << awesome_hash(data)
end
end
-AwesomePrint.send(:include, AwesomePrintActiveRecord)
+AwesomePrint::Formatter.send(:include, AwesomePrint::ActiveRecord)
diff --git a/lib/ap/mixin/active_support.rb b/lib/ap/mixin/active_support.rb
index c906841..490940b 100644
--- a/lib/ap/mixin/active_support.rb
+++ b/lib/ap/mixin/active_support.rb
@@ -3,44 +3,38 @@
# Awesome Print is freely distributable under the terms of MIT license.
# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
#------------------------------------------------------------------------------
-module AwesomePrintActiveSupport
+module AwesomePrint
+ module ActiveSupport
- def self.included(base)
- base.send :alias_method, :printable_without_active_support, :printable
- base.send :alias_method, :printable, :printable_with_active_support
- end
-
- # Add ActiveSupport class names to the dispatcher pipeline.
- #------------------------------------------------------------------------------
- def printable_with_active_support(object)
- printable = printable_without_active_support(object)
- return printable if !defined?(ActiveSupport::TimeWithZone) || !defined?(HashWithIndifferentAccess)
-
- if printable == :self
- if object.is_a?(ActiveSupport::TimeWithZone)
- printable = :active_support_time
- elsif object.is_a?(HashWithIndifferentAccess)
- printable = :hash_with_indifferent_access
- end
+ def self.included(base)
+ base.send :alias_method, :cast_without_active_support, :cast
+ base.send :alias_method, :cast, :cast_with_active_support
end
- printable
- end
- # Format ActiveSupport::TimeWithZone as standard Time.
- #------------------------------------------------------------------------------
- def awesome_active_support_time(object)
- awesome_self(object, :as => :time)
- end
+ def cast_with_active_support(object, type)
+ cast = cast_without_active_support(object, type)
+ if defined?(::ActiveSupport) && defined?(::HashWithIndifferentAccess)
+ if object.is_a?(::ActiveSupport::TimeWithZone)
+ cast = :active_support_time
+ elsif object.is_a?(::HashWithIndifferentAccess)
+ cast = :hash_with_indifferent_access
+ end
+ end
+ cast
+ end
- # Format HashWithIndifferentAccess as standard Hash.
- #
- # NOTE: can't use awesome_self(object, :as => :hash) since awesome_self uses
- # object.inspect internally, i.e. it would convert hash to string.
- #------------------------------------------------------------------------------
- def awesome_hash_with_indifferent_access(object)
- awesome_hash(object)
- end
+ # Format ActiveSupport::TimeWithZone as standard Time.
+ #------------------------------------------------------------------------------
+ def awesome_active_support_time(object)
+ awesome_self(object, :as => :time)
+ end
+ # Format HashWithIndifferentAccess as standard Hash.
+ #------------------------------------------------------------------------------
+ def awesome_hash_with_indifferent_access(object)
+ awesome_hash(object)
+ end
+ end
end
-AwesomePrint.send(:include, AwesomePrintActiveSupport)
+AwesomePrint::Formatter.send(:include, AwesomePrint::ActiveSupport)
diff --git a/lib/awesome_print.rb b/lib/awesome_print.rb
index fc1cc15..d887f1d 100755
--- a/lib/awesome_print.rb
+++ b/lib/awesome_print.rb
@@ -14,7 +14,8 @@
require File.dirname(__FILE__) + "/ap/core_ext/#{file}"
end
-require File.dirname(__FILE__) + "/ap/awesome_print"
+require File.dirname(__FILE__) + "/ap/inspector"
+require File.dirname(__FILE__) + "/ap/formatter"
require File.dirname(__FILE__) + "/ap/core_ext/logger" if defined?(Logger)
require File.dirname(__FILE__) + "/ap/mixin/action_view" if defined?(ActionView)
diff --git a/spec/action_view_spec.rb b/spec/action_view_spec.rb
index 7bff0f9..d9cde3b 100644
--- a/spec/action_view_spec.rb
+++ b/spec/action_view_spec.rb
@@ -4,7 +4,7 @@ require 'action_view'
require 'ap/mixin/action_view'
describe "AwesomePrint ActionView extensions" do
- before(:each) do
+ before do
@view = ActionView::Base.new
end
diff --git a/spec/active_record_spec.rb b/spec/active_record_spec.rb
index e5e5836..ee86346 100644
--- a/spec/active_record_spec.rb
+++ b/spec/active_record_spec.rb
@@ -4,53 +4,51 @@ require 'active_record'
require 'ap/mixin/active_record'
-if defined?(::ActiveRecord)
+# Create tableless ActiveRecord model.
+#------------------------------------------------------------------------------
+class User < ActiveRecord::Base
+ def self.columns()
+ @columns ||= []
+ end
+
+ def self.column(name, sql_type = nil, default = nil, null = true)
+ columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type.to_s, null)
+ end
+
+ column :id, :integer
+ column :name, :string
+ column :rank, :integer
+ column :admin, :boolean
+ column :created_at, :datetime
+
+ def self.table_exists?
+ true
+ end
+end
+
+class SubUser < User
+ def self.columns
+ User.columns
+ end
+end
+
+describe "AwesomePrint::ActiveRecord" do
+ before do
+ stub_dotfile!
+ end
- # Create tableless ActiveRecord model.
#------------------------------------------------------------------------------
- class User < ActiveRecord::Base
- def self.columns()
- @columns ||= []
+ describe "ActiveRecord instance" do
+ before do
+ ActiveRecord::Base.default_timezone = :utc
+ @diana = User.new(:name => "Diana", :rank => 1, :admin => false, :created_at => "1992-10-10 12:30:00")
+ @laura = User.new(:name => "Laura", :rank => 2, :admin => true, :created_at => "2003-05-26 14:15:00")
+ @ap = AwesomePrint::Inspector.new(:plain => true)
end
- def self.column(name, sql_type = nil, default = nil, null = true)
- columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type.to_s, null)
- end
-
- column :id, :integer
- column :name, :string
- column :rank, :integer
- column :admin, :boolean
- column :created_at, :datetime
-
- def self.table_exists?
- true
- end
- end
-
- class SubUser < User
- def self.columns
- User.columns
- end
- end
-
- describe "AwesomePrint/ActiveRecord" do
- before(:each) do
- stub_dotfile!
- end
-
- #------------------------------------------------------------------------------
- describe "ActiveRecord instance" do
- before(:each) do
- ActiveRecord::Base.default_timezone = :utc
- @diana = User.new(:name => "Diana", :rank => 1, :admin => false, :created_at => "1992-10-10 12:30:00")
- @laura = User.new(:name => "Laura", :rank => 2, :admin => true, :created_at => "2003-05-26 14:15:00")
- @ap = AwesomePrint.new(:plain => true)
- end
-
- it "display single record" do
- out = @ap.send(:awesome, @diana)
- str = <<-EOS.strip
+ it "display single record" do
+ out = @ap.send(:awesome, @diana)
+ str = <<-EOS.strip
# {
:id => nil,
:name => "Diana",
@@ -59,18 +57,18 @@ if defined?(::ActiveRecord)
:created_at => ?
}
EOS
- if RUBY_VERSION.to_f < 1.9
- str.sub!('?', 'Sat Oct 10 12:30:00 UTC 1992')
- else
- str.sub!('?', '1992-10-10 12:30:00 UTC')
- end
-
- out.gsub(/0x([a-f\d]+)/, "0x01234567").should == str
+ if RUBY_VERSION.to_f < 1.9
+ str.sub!('?', 'Sat Oct 10 12:30:00 UTC 1992')
+ else
+ str.sub!('?', '1992-10-10 12:30:00 UTC')
end
- it "display multiple records" do
- out = @ap.send(:awesome, [ @diana, @laura ])
- str = <<-EOS.strip
+ out.gsub(/0x([a-f\d]+)/, "0x01234567").should == str
+ end
+
+ it "display multiple records" do
+ out = @ap.send(:awesome, [ @diana, @laura ])
+ str = <<-EOS.strip
[
[0] # {
:id => nil,
@@ -88,23 +86,23 @@ EOS
}
]
EOS
- if RUBY_VERSION.to_f < 1.9
- str.sub!('?', 'Sat Oct 10 12:30:00 UTC 1992')
- str.sub!('!', 'Mon May 26 14:15:00 UTC 2003')
- else
- str.sub!('?', '1992-10-10 12:30:00 UTC')
- str.sub!('!', '2003-05-26 14:15:00 UTC')
- end
-
- out.gsub(/0x([a-f\d]+)/, "0x01234567").should == str
+ if RUBY_VERSION.to_f < 1.9
+ str.sub!('?', 'Sat Oct 10 12:30:00 UTC 1992')
+ str.sub!('!', 'Mon May 26 14:15:00 UTC 2003')
+ else
+ str.sub!('?', '1992-10-10 12:30:00 UTC')
+ str.sub!('!', '2003-05-26 14:15:00 UTC')
end
- end
- #------------------------------------------------------------------------------
- describe "ActiveRecord class" do
- it "should print the class" do
- @ap = AwesomePrint.new(:plain => true)
- @ap.send(:awesome, User).should == <<-EOS.strip
+ out.gsub(/0x([a-f\d]+)/, "0x01234567").should == str
+ end
+ end
+
+ #------------------------------------------------------------------------------
+ describe "ActiveRecord class" do
+ it "should print the class" do
+ @ap = AwesomePrint::Inspector.new(:plain => true)
+ @ap.send(:awesome, User).should == <<-EOS.strip
class User < ActiveRecord::Base {
:id => :integer,
:name => :string,
@@ -117,7 +115,7 @@ class User < ActiveRecord::Base {
end
it "should print the class for non-direct subclasses of AR::Base" do
- @ap = AwesomePrint.new(:plain => true)
+ @ap = AwesomePrint::Inspector.new(:plain => true)
@ap.send(:awesome, SubUser).should == <<-EOS.strip
class SubUser < User {
:id => :integer,
@@ -128,7 +126,6 @@ class SubUser < User {
}
EOS
- end
end
end
end
diff --git a/spec/active_support_spec.rb b/spec/active_support_spec.rb
new file mode 100755
index 0000000..9cf3939
--- /dev/null
+++ b/spec/active_support_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
+
+require 'active_support'
+require 'ap/mixin/active_support'
+
+describe "AwesomePrint::ActiveSupport" do
+ before do
+ stub_dotfile!
+ @ap = AwesomePrint::Inspector.new()
+ end
+
+ it "should format ActiveSupport::TimeWithZone as regular Time" do
+ Time.zone = 'Eastern Time (US & Canada)'
+ time = Time.utc(2007, 2, 10, 20, 30, 45).in_time_zone
+ @ap.send(:awesome, time).should == "\e[0;32mSat, 10 Feb 2007 15:30:45 EST -05:00\e[0m"
+ end
+
+ it "should format HashWithIndifferentAccess as regular Hash" do
+ hash = HashWithIndifferentAccess.new({ :hello => "world" })
+ @ap.send(:awesome, hash).should == "{\n \"hello\"\e[0;37m => \e[0m\e[0;33m\"world\"\e[0m\n}"
+ end
+end
diff --git a/spec/awesome_print_spec.rb b/spec/awesome_print_spec.rb
index 1a265ec..1cedd6d 100644
--- a/spec/awesome_print_spec.rb
+++ b/spec/awesome_print_spec.rb
@@ -3,12 +3,12 @@ require "bigdecimal"
require "rational"
describe "AwesomePrint" do
- before(:each) do
+ before do
stub_dotfile!
end
describe "Array" do
- before(:each) do
+ before do
@arr = [ 1, :two, "three", [ nil, [ true, false] ] ]
end
@@ -129,7 +129,7 @@ EOS
#------------------------------------------------------------------------------
describe "Nested Array" do
- before(:each) do
+ before do
@arr = [ 1, 2 ]
@arr << @arr
end
@@ -161,7 +161,7 @@ EOS
#------------------------------------------------------------------------------
describe "Hash" do
- before(:each) do
+ before do
@hash = { 1 => { :sym => { "str" => { [1, 2, 3] => { { :k => :v } => Hash } } } } }
end
@@ -245,7 +245,7 @@ EOS
#------------------------------------------------------------------------------
describe "Nested Hash" do
- before(:each) do
+ before do
@hash = {}
@hash[:a] = @hash
end
@@ -265,7 +265,7 @@ EOS
#------------------------------------------------------------------------------
describe "Hash with several keys" do
- before(:each) do
+ before do
@hash = {"b" => "b", :a => "a", :z => "z", "alpha" => "alpha"}
end
@@ -290,7 +290,7 @@ EOS
end
it "plain multiline with sorted keys" do
- @hash.ai(:plain => true, :sorted_hash_keys => true).should == <<-EOS.strip
+ @hash.ai(:plain => true, :sort_keys => true).should == <<-EOS.strip
{
:a => "a",
"alpha" => "alpha",
@@ -304,7 +304,7 @@ EOS
#------------------------------------------------------------------------------
describe "Negative options[:indent]" do
- before(:each) do
+ before do
@hash = { [0, 0, 255] => :yellow, :red => "rgb(255, 0, 0)", "magenta" => "rgb(255, 0, 255)" }
end
@@ -363,7 +363,7 @@ EOS
#------------------------------------------------------------------------------
describe "Utility methods" do
it "should merge options" do
- ap = AwesomePrint.new
+ ap = AwesomePrint::Inspector.new
ap.send(:merge_options!, { :color => { :array => :black }, :indent => 0 })
options = ap.instance_variable_get("@options")
options[:color][:array].should == :black
@@ -374,7 +374,7 @@ EOS
#------------------------------------------------------------------------------
describe "Struct" do
- before(:each) do
+ before do
@struct = unless defined?(Struct::SimpleStruct)
Struct.new("SimpleStruct", :name, :address).new
else
diff --git a/spec/logger_spec.rb b/spec/logger_spec.rb
index b5a9c80..7e80326 100644
--- a/spec/logger_spec.rb
+++ b/spec/logger_spec.rb
@@ -17,8 +17,8 @@ describe "AwesomePrint logging extensions" do
end
describe "the log level" do
- before(:each) do
- AwesomePrint.defaults = { }
+ before do
+ AwesomePrint.defaults = {}
end
it "should fallback to the default :debug log level" do