1
0
Fork 0
mirror of https://github.com/awesome-print/awesome_print synced 2023-03-27 23:22:34 -04:00

Initial implementation of formatting an arbitrary Ruby object

This commit is contained in:
Mike Dvorkin 2011-02-09 19:20:56 -08:00
parent dfbebd4887
commit 62041f2aa4
6 changed files with 64 additions and 45 deletions

View file

@ -7,7 +7,7 @@ module Kernel
def ai(options = {}) def ai(options = {})
ap = AwesomePrint::Inspector.new(options) ap = AwesomePrint::Inspector.new(options)
ap.send(:awesome, self) ap.awesome self
end end
alias :awesome_inspect :ai alias :awesome_inspect :ai

View file

@ -19,13 +19,12 @@ module AwesomePrint
# Main entry point to format an object. # Main entry point to format an object.
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
def format(object, type = nil) def format(object, type = nil)
klass = cast(object, type) core_class = cast(object, type)
return send(:"awesome_#{klass}", object) if klass != :self return send(:"awesome_#{core_class}", object) if core_class != :self
send(:awesome_self, object, :as => type) # Catch all that falls back on object.inspect. awesome_self(object, :as => type) # Catch all that falls back on object.inspect.
end end
# Hook this when adding custom formatters. Check out how it's done in # Hook this when adding custom formatters.
# ap/lib/mixin/active_record.rb
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
def cast(object, type) def cast(object, type)
CORE.grep(type)[0] || :self CORE.grep(type)[0] || :self
@ -44,7 +43,8 @@ module AwesomePrint
# Catch all method to format an arbitrary object. # Catch all method to format an arbitrary object.
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
def awesome_self(object, appear = {}) def awesome_self(object, appear = {})
colorize(object.inspect.to_s << appear[:with].to_s, appear[:as]) return awesome_object(object) if object.instance_variables.any?
colorize(object.inspect.to_s, appear[:as])
end end
# Format an array. # Format an array.
@ -56,19 +56,17 @@ module AwesomePrint
methods_array(a) methods_array(a)
elsif @options[:multiline] elsif @options[:multiline]
width = (a.size - 1).to_s.size width = (a.size - 1).to_s.size
data = a.inject([]) do |arr, item| data = a.inject([]) do |arr, item|
index = if @options[:index] index = indent
colorize("#{indent}[#{arr.size.to_s.rjust(width)}] ", :array) index << colorize("[#{arr.size.to_s.rjust(width)}] ", :array) if @options[:index]
else
colorize(indent, :array)
end
indented do indented do
arr << (index << @inspector.send(:awesome, item)) arr << (index << @inspector.awesome(item))
end end
end end
"[\n" << data.join(",\n") << "\n#{outdent}]" "[\n" << data.join(",\n") << "\n#{outdent}]"
else else
"[ " << a.map{ |item| @inspector.send(:awesome, item) }.join(", ") << " ]" "[ " << a.map{ |item| @inspector.awesome(item) }.join(", ") << " ]"
end end
end end
@ -80,7 +78,7 @@ module AwesomePrint
keys = @options[:sort_keys] ? h.keys.sort { |a, b| a.to_s <=> b.to_s } : h.keys keys = @options[:sort_keys] ? h.keys.sort { |a, b| a.to_s <=> b.to_s } : h.keys
data = keys.map do |key| data = keys.map do |key|
plain_single_line do plain_single_line do
[ @inspector.send(:awesome, key), h[key] ] [ @inspector.awesome(key), h[key] ]
end end
end end
@ -94,7 +92,31 @@ module AwesomePrint
formatted_key = key formatted_key = key
end end
indented do indented do
formatted_key << colorize(" => ", :hash) << @inspector.send(:awesome, value) formatted_key << colorize(" => ", :hash) << @inspector.awesome(value)
end
end
if @options[:multiline]
"{\n" << data.join(",\n") << "\n#{outdent}}"
else
"{ #{data.join(', ')} }"
end
end
# Format an object.
#------------------------------------------------------------------------------
def awesome_object(o)
vars = o.instance_variables.sort
width = vars.map { |var| var.size }.max || 0
width += @indentation if @options[:indent] > 0
data = vars.map do |var|
if @options[:multiline]
formatted_key = (@options[:indent] >= 0 ? var.rjust(width) : indent + var.ljust(width))
else
formatted_key = var
end
indented do
formatted_key << colorize(" => ", :hash) + @inspector.awesome(o.instance_variable_get(var))
end end
end end
if @options[:multiline] if @options[:multiline]
@ -116,9 +138,9 @@ module AwesomePrint
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
def awesome_class(c) def awesome_class(c)
if superclass = c.superclass # <-- Assign and test if nil. if superclass = c.superclass # <-- Assign and test if nil.
awesome_self(c, :as => :class, :with => " < #{superclass}") colorize("#{c.inspect} < #{superclass}", :class)
else else
awesome_self(c, :as => :class) colorize(c.inspect, :class)
end end
end end
@ -126,20 +148,20 @@ module AwesomePrint
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
def awesome_file(f) def awesome_file(f)
ls = File.directory?(f) ? `ls -adlF #{f.path.shellescape}` : `ls -alF #{f.path.shellescape}` 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}") colorize(ls.empty? ? f.inspect : "#{f.inspect}\n#{ls.chop}", :file)
end end
# Format Dir object. # Format Dir object.
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
def awesome_dir(d) def awesome_dir(d)
ls = `ls -alF #{d.path.shellescape}` ls = `ls -alF #{d.path.shellescape}`
awesome_self(d, :as => :dir, :with => ls.empty? ? nil : "\n#{ls.chop}") colorize(ls.empty? ? d.inspect : "#{d.inspect}\n#{ls.chop}", :dir)
end end
# Format BigDecimal and Rational objects by convering them to Float. # Format BigDecimal and Rational objects by convering them to Float.
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
def awesome_bigdecimal(n) def awesome_bigdecimal(n)
awesome_self(n.to_f, :as => :bigdecimal) colorize(n.to_f.inspect, :bigdecimal)
end end
alias :awesome_rational :awesome_bigdecimal alias :awesome_rational :awesome_bigdecimal
@ -170,11 +192,8 @@ module AwesomePrint
args_width = tuples.map { |item| item[1].size }.max || 0 args_width = tuples.map { |item| item[1].size }.max || 0
data = tuples.inject([]) do |arr, item| data = tuples.inject([]) do |arr, item|
index = if @options[:index] index = indent
"#{indent}[#{arr.size.to_s.rjust(width)}]" index << "[#{arr.size.to_s.rjust(width)}]" if @options[:index]
else
indent
end
indented do indented do
arr << "#{index} #{colorize(item[0].rjust(name_width), :method)}#{colorize(item[1].ljust(args_width), :args)} #{colorize(item[2], :class)}" arr << "#{index} #{colorize(item[0].rjust(name_width), :method)}#{colorize(item[1].ljust(args_width), :args)} #{colorize(item[2], :class)}"
end end

View file

@ -49,8 +49,6 @@ module AwesomePrint
Thread.current[AP] ||= [] Thread.current[AP] ||= []
end end
private
# Dispatcher that detects data nesting and invokes object-aware formatter. # Dispatcher that detects data nesting and invokes object-aware formatter.
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
def awesome(object) def awesome(object)
@ -66,6 +64,8 @@ module AwesomePrint
end end
end end
private
# Format nested data, for example: # Format nested data, for example:
# arr = [1, 2]; arr << arr # arr = [1, 2]; arr << arr
# => [1,2, [...]] # => [1,2, [...]]

View file

@ -26,7 +26,7 @@ module AwesomePrint
# Format ActiveSupport::TimeWithZone as standard Time. # Format ActiveSupport::TimeWithZone as standard Time.
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
def awesome_active_support_time(object) def awesome_active_support_time(object)
awesome_self(object, :as => :time) colorize(object.inspect, :time)
end end
# Format HashWithIndifferentAccess as standard Hash. # Format HashWithIndifferentAccess as standard Hash.

0
spec/active_support_spec.rb Executable file → Normal file
View file

View file

@ -91,14 +91,14 @@ EOS
it "colored multiline (default)" do it "colored multiline (default)" do
@arr.ai.should == <<-EOS.strip @arr.ai.should == <<-EOS.strip
[ [
\e[1;37m [0] \e[0m\e[1;34m1\e[0m, \e[1;37m[0] \e[0m\e[1;34m1\e[0m,
\e[1;37m [1] \e[0m\e[0;36m:two\e[0m, \e[1;37m[1] \e[0m\e[0;36m:two\e[0m,
\e[1;37m [2] \e[0m\e[0;33m\"three\"\e[0m, \e[1;37m[2] \e[0m\e[0;33m\"three\"\e[0m,
\e[1;37m [3] \e[0m[ \e[1;37m[3] \e[0m[
\e[1;37m [0] \e[0m\e[1;31mnil\e[0m, \e[1;37m[0] \e[0m\e[1;31mnil\e[0m,
\e[1;37m [1] \e[0m[ \e[1;37m[1] \e[0m[
\e[1;37m [0] \e[0m\e[1;32mtrue\e[0m, \e[1;37m[0] \e[0m\e[1;32mtrue\e[0m,
\e[1;37m [1] \e[0m\e[1;31mfalse\e[0m \e[1;37m[1] \e[0m\e[1;31mfalse\e[0m
] ]
] ]
] ]
@ -108,14 +108,14 @@ EOS
it "colored multiline indented" do it "colored multiline indented" do
@arr.ai(:indent => 8).should == <<-EOS.strip @arr.ai(:indent => 8).should == <<-EOS.strip
[ [
\e[1;37m [0] \e[0m\e[1;34m1\e[0m, \e[1;37m[0] \e[0m\e[1;34m1\e[0m,
\e[1;37m [1] \e[0m\e[0;36m:two\e[0m, \e[1;37m[1] \e[0m\e[0;36m:two\e[0m,
\e[1;37m [2] \e[0m\e[0;33m\"three\"\e[0m, \e[1;37m[2] \e[0m\e[0;33m\"three\"\e[0m,
\e[1;37m [3] \e[0m[ \e[1;37m[3] \e[0m[
\e[1;37m [0] \e[0m\e[1;31mnil\e[0m, \e[1;37m[0] \e[0m\e[1;31mnil\e[0m,
\e[1;37m [1] \e[0m[ \e[1;37m[1] \e[0m[
\e[1;37m [0] \e[0m\e[1;32mtrue\e[0m, \e[1;37m[0] \e[0m\e[1;32mtrue\e[0m,
\e[1;37m [1] \e[0m\e[1;31mfalse\e[0m \e[1;37m[1] \e[0m\e[1;31mfalse\e[0m
] ]
] ]
] ]