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

Merge pull request #237 from waldyr/refactor/add-formatters

Refactoring - Add formatters
This commit is contained in:
Gerry 2016-05-22 01:19:56 +10:00
commit f3eea33763
13 changed files with 562 additions and 351 deletions

View file

@ -0,0 +1,24 @@
autoload :CGI, "cgi"
module AwesomePrint
module Colorize
# Pick the color and apply it to the given string as necessary.
#------------------------------------------------------------------------------
def colorize(str, type)
str = CGI.escapeHTML(str) if options[:html]
if options[:plain] || !options[:color][type] || !inspector.colorize?
str
#
# Check if the string color method is defined by awesome_print and accepts
# html parameter or it has been overriden by some gem such as colorize.
#
elsif str.method(options[:color][type]).arity == -1 # Accepts html parameter.
str.send(options[:color][type], options[:html])
else
str = %Q|<kbd style="color:#{options[:color][type]}">#{str}</kbd>| if options[:html]
str.send(options[:color][type])
end
end
end
end

View file

@ -3,19 +3,27 @@
# Awesome Print is freely distributable under the terms of MIT license.
# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
#------------------------------------------------------------------------------
autoload :CGI, "cgi"
require "shellwords"
require_relative "formatters/object_formatter"
require_relative "formatters/hash_formatter"
require_relative "formatters/array_formatter"
require_relative "formatters/simple_formatter"
require_relative "formatters/method_formatter"
require_relative "formatters/class_formatter"
require_relative "formatters/dir_formatter"
require_relative "formatters/file_formatter"
require_relative "colorize"
module AwesomePrint
class Formatter
include Colorize
attr_reader :inspector, :options
CORE = [ :array, :bigdecimal, :class, :dir, :file, :hash, :method, :rational, :set, :struct, :unboundmethod ]
DEFAULT_LIMIT_SIZE = 7
def initialize(inspector)
@inspector = inspector
@options = inspector.options
@indentation = @options[:indent].abs
end
# Main entry point to format an object.
@ -37,292 +45,71 @@ module AwesomePrint
CORE.grep(type)[0] || :self
end
# Pick the color and apply it to the given string as necessary.
#------------------------------------------------------------------------------
def colorize(str, type)
str = CGI.escapeHTML(str) if @options[:html]
if @options[:plain] || !@options[:color][type] || !@inspector.colorize?
str
#
# Check if the string color method is defined by awesome_print and accepts
# html parameter or it has been overriden by some gem such as colorize.
#
elsif str.method(@options[:color][type]).arity == -1 # Accepts html parameter.
str.send(@options[:color][type], @options[:html])
else
str = %Q|<kbd style="color:#{@options[:color][type]}">#{str}</kbd>| if @options[:html]
str.send(@options[:color][type])
end
end
private
# Check whether a variable_name is a method or ivar
#------------------------------------------------------------------------------
def valid_instance_var?(variable_name)
variable_name.to_s.start_with?('@')
end
# Catch all method to format an arbitrary object.
#------------------------------------------------------------------------------
def awesome_self(object, type)
if @options[:raw] && object.instance_variables.any?
return awesome_object(object)
awesome_object(object)
elsif hash = convert_to_hash(object)
awesome_hash(hash)
else
colorize(object.inspect.to_s, type)
awesome_simple(object.inspect.to_s, type, @inspector)
end
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 = indent
index << colorize("[#{arr.size.to_s.rjust(width)}] ", :array) if @options[:index]
indented do
arr << (index << @inspector.awesome(item))
end
end
data = limited(data, width) if should_be_limited?
"[\n" << data.join(",\n") << "\n#{outdent}]"
else
"[ " << a.map{ |item| @inspector.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.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|
indented do
align(key, width) << colorize(" => ", :hash) << @inspector.awesome(value)
end
end
data = limited(data, width, :hash => true) if should_be_limited?
if @options[:multiline]
"{\n" << data.join(",\n") << "\n#{outdent}}"
else
"{ #{data.join(', ')} }"
end
end
# Format an object.
#------------------------------------------------------------------------------
def awesome_object(o)
awesome_object_data(o, o.instance_variables)
end
def awesome_object_data(o, variables)
vars = variables.map do |var|
property = var.to_s[1..-1].to_sym # to_s because of some monkey patching done by Puppet.
accessor = if o.respond_to?(:"#{property}=")
o.respond_to?(property) ? :accessor : :writer
else
o.respond_to?(property) ? :reader : nil
end
if accessor
[ "attr_#{accessor} :#{property}", var ]
else
[ var.to_s, var ]
end
end
data = vars.sort.map do |declaration, var|
key = left_aligned do
align(declaration, declaration.size)
end
unless @options[:plain]
if key =~ /(@\w+)/
key.sub!($1, colorize($1, :variable))
else
key.sub!(/(attr_\w+)\s(\:\w+)/, "#{colorize('\\1', :keyword)} #{colorize('\\2', :method)}")
end
end
indented do
var_contents = if valid_instance_var?(var)
o.instance_variable_get(var)
else
o.send(var) # Enables handling of Struct attributes
end
key << colorize(" = ", :hash) + @inspector.awesome(var_contents)
end
end
if @options[:multiline]
"#<#{awesome_instance(o)}\n#{data.join(%Q/,\n/)}\n#{outdent}>"
else
"#<#{awesome_instance(o)} #{data.join(', ')}>"
end
end
# Format a set.
#------------------------------------------------------------------------------
def awesome_set(s)
awesome_array(s.to_a)
end
# Format a Struct.
#------------------------------------------------------------------------------
def awesome_struct(s)
awesome_object_data(s, s.members)
end
# Format Class object.
#------------------------------------------------------------------------------
def awesome_class(c)
if superclass = c.superclass # <-- Assign and test if nil.
colorize("#{c.inspect} < #{superclass}", :class)
else
colorize(c.inspect, :class)
end
end
# Format File object.
#------------------------------------------------------------------------------
def awesome_file(f)
ls = File.directory?(f) ? `ls -adlF #{f.path.shellescape}` : `ls -alF #{f.path.shellescape}`
colorize(ls.empty? ? f.inspect : "#{f.inspect}\n#{ls.chop}", :file)
end
# Format Dir object.
#------------------------------------------------------------------------------
def awesome_dir(d)
ls = `ls -alF #{d.path.shellescape}`
colorize(ls.empty? ? d.inspect : "#{d.inspect}\n#{ls.chop}", :dir)
end
# Format BigDecimal object.
#------------------------------------------------------------------------------
def awesome_bigdecimal(n)
colorize(n.to_s("F"), :bigdecimal)
o = n.to_s("F")
type = :bigdecimal
awesome_simple(o, type, @inspector)
end
# Format Rational object.
#------------------------------------------------------------------------------
def awesome_rational(n)
colorize(n.to_s, :rational)
o = n.to_s
type = :rational
awesome_simple(o, type, @inspector)
end
def awesome_simple(o, type, inspector)
AwesomePrint::Formatters::SimpleFormatter.new(o, type, inspector).format
end
def awesome_array(a)
Formatters::ArrayFormatter.new(a, @inspector).format
end
def awesome_set(s)
Formatters::ArrayFormatter.new(s.to_a, @inspector).format
end
def awesome_hash(h)
Formatters::HashFormatter.new(h, @inspector).format
end
def awesome_object(o)
Formatters::ObjectFormatter.new(o, o.instance_variables, @inspector).format
end
def awesome_struct(s)
Formatters::ObjectFormatter.new(s, s.members, @inspector).format
end
# Format a method.
#------------------------------------------------------------------------------
def awesome_method(m)
name, args, owner = method_tuple(m)
"#{colorize(owner, :class)}##{colorize(name, :method)}#{colorize(args, :args)}"
Formatters::MethodFormatter.new(m, @inspector).format
end
alias :awesome_unboundmethod :awesome_method
# Format object instance.
#------------------------------------------------------------------------------
def awesome_instance(o)
"#{o.class}:0x%08x" % (o.__id__ * 2)
def awesome_class(c)
Formatters::ClassFormatter.new(c, @inspector).format
end
# Format object.methods array.
#------------------------------------------------------------------------------
def methods_array(a)
a.sort! { |x, y| x.to_s <=> y.to_s } # Can't simply a.sort! because of o.methods << [ :blah ]
object = a.instance_variable_get('@__awesome_methods__')
tuples = a.map do |name|
if name.is_a?(Symbol) || name.is_a?(String) # Ignore garbage, ex. 42.methods << [ :blah ]
tuple = if object.respond_to?(name, true) # Is this a regular method?
the_method = object.method(name) rescue nil # Avoid potential ArgumentError if object#method is overridden.
if the_method && the_method.respond_to?(:arity) # Is this original object#method?
method_tuple(the_method) # Yes, we are good.
end
elsif object.respond_to?(:instance_method) # Is this an unbound method?
method_tuple(object.instance_method(name)) rescue nil # Rescue to avoid NameError when the method is not
end # available (ex. File.lchmod on Ubuntu 12).
end
tuple || [ name.to_s, '(?)', '?' ] # Return WTF default if all the above fails.
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 = indent
index << "[#{arr.size.to_s.rjust(width)}]" if @options[:index]
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}]"
def awesome_file(f)
Formatters::FileFormatter.new(f, @inspector).format
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
# method.to_s formats to handle:
#
# #<Method: Fixnum#zero?>
# #<Method: Fixnum(Integer)#years>
# #<Method: User(#<Module:0x00000103207c00>)#_username>
# #<Method: User(id: integer, username: string).table_name>
# #<Method: User(id: integer, username: string)(ActiveRecord::Base).current>
# #<UnboundMethod: Hello#world>
#
if method.to_s =~ /(Unbound)*Method: (.*)[#\.]/
unbound, klass = $1 && '(unbound)', $2
if klass && klass =~ /(\(\w+:\s.*?\))/ # Is this ActiveRecord-style class?
klass.sub!($1, '') # Yes, strip the fields leaving class name only.
end
owner = "#{klass}#{unbound}".gsub('(', ' (')
end
[ method.name.to_s, "(#{args.join(', ')})", owner.to_s ]
end
# Format hash keys as plain strings 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
def awesome_dir(d)
Formatters::DirFormatter.new(d, @inspector).format
end
# Utility methods.
@ -331,6 +118,7 @@ module AwesomePrint
if ! object.respond_to?(:to_hash)
return nil
end
if object.method(:to_hash).arity != 0
return nil
end
@ -342,91 +130,5 @@ module AwesomePrint
return hash
end
def align(value, width)
if @options[:multiline]
if @options[:indent] > 0
value.rjust(width)
elsif @options[:indent] == 0
indent + value.ljust(width)
else
indent[0, @indentation + @options[:indent]] + value.ljust(width)
end
else
value
end
end
def indented
@indentation += @options[:indent].abs
yield
ensure
@indentation -= @options[:indent].abs
end
def left_aligned
current, @options[:indent] = @options[:indent], 0
yield
ensure
@options[:indent] = current
end
def indent
' ' * @indentation
end
def outdent
' ' * (@indentation - @options[:indent].abs)
end
# To support limited output, for example:
#
# ap ('a'..'z').to_a, :limit => 3
# [
# [ 0] "a",
# [ 1] .. [24],
# [25] "z"
# ]
#
# ap (1..100).to_a, :limit => true # Default limit is 7.
# [
# [ 0] 1,
# [ 1] 2,
# [ 2] 3,
# [ 3] .. [96],
# [97] 98,
# [98] 99,
# [99] 100
# ]
#------------------------------------------------------------------------------
def should_be_limited?
@options[:limit] == true or (@options[:limit].is_a?(Fixnum) and @options[:limit] > 0)
end
def get_limit_size
@options[:limit] == true ? DEFAULT_LIMIT_SIZE : @options[:limit]
end
def limited(data, width, is_hash = false)
limit = get_limit_size
if data.length <= limit
data
else
# Calculate how many elements to be displayed above and below the separator.
head = limit / 2
tail = head - (limit - 1) % 2
# Add the proper elements to the temp array and format the separator.
temp = data[0, head] + [ nil ] + data[-tail, tail]
if is_hash
temp[head] = "#{indent}#{data[head].strip} .. #{data[data.length - tail - 1].strip}"
else
temp[head] = "#{indent}[#{head.to_s.rjust(width)}] .. [#{data.length - tail - 1}]"
end
temp
end
end
end
end

View file

@ -0,0 +1,73 @@
require_relative 'base_formatter'
module AwesomePrint
module Formatters
class ArrayFormatter < BaseFormatter
attr_reader :array, :inspector, :options
def initialize(array, inspector)
@array = array
@inspector = inspector
@options = inspector.options
end
def format
return "[]" if array == []
if array.instance_variable_defined?('@__awesome_methods__')
methods_array(array)
elsif options[:multiline]
width = (array.size - 1).to_s.size
data = array.inject([]) do |arr, item|
index = indent
index << colorize("[#{arr.size.to_s.rjust(width)}] ", :array) if options[:index]
indented do
arr << (index << inspector.awesome(item))
end
end
data = limited(data, width) if should_be_limited?
"[\n" << data.join(",\n") << "\n#{outdent}]"
else
"[ " << array.map{ |item| inspector.awesome(item) }.join(", ") << " ]"
end
end
private
def methods_array(a)
a.sort! { |x, y| x.to_s <=> y.to_s } # Can't simply a.sort! because of o.methods << [ :blah ]
object = a.instance_variable_get('@__awesome_methods__')
tuples = a.map do |name|
if name.is_a?(Symbol) || name.is_a?(String) # Ignore garbage, ex. 42.methods << [ :blah ]
tuple = if object.respond_to?(name, true) # Is this a regular method?
the_method = object.method(name) rescue nil # Avoid potential ArgumentError if object#method is overridden.
if the_method && the_method.respond_to?(:arity) # Is this original object#method?
method_tuple(the_method) # Yes, we are good.
end
elsif object.respond_to?(:instance_method) # Is this an unbound method?
method_tuple(object.instance_method(name)) rescue nil # Rescue to avoid NameError when the method is not
end # available (ex. File.lchmod on Ubuntu 12).
end
tuple || [ name.to_s, '(?)', '?' ] # Return WTF default if all the above fails.
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 = indent
index << "[#{arr.size.to_s.rjust(width)}]" if @options[:index]
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
end
end
end

View file

@ -0,0 +1,138 @@
require_relative "../colorize"
module AwesomePrint
module Formatters
class BaseFormatter
include Colorize
DEFAULT_LIMIT_SIZE = 7
# To support limited output, for example:
#
# ap ('a'..'z').to_a, :limit => 3
# [
# [ 0] "a",
# [ 1] .. [24],
# [25] "z"
# ]
#
# ap (1..100).to_a, :limit => true # Default limit is 7.
# [
# [ 0] 1,
# [ 1] 2,
# [ 2] 3,
# [ 3] .. [96],
# [97] 98,
# [98] 99,
# [99] 100
# ]
#------------------------------------------------------------------------------
def should_be_limited?
options[:limit] or (options[:limit].is_a?(Fixnum) and options[:limit] > 0)
end
def get_limit_size
case options[:limit]
when true
DEFAULT_LIMIT_SIZE
else
options[:limit]
end
end
def limited(data, width, is_hash = false)
limit = get_limit_size
if data.length <= limit
data
else
# Calculate how many elements to be displayed above and below the separator.
head = limit / 2
tail = head - (limit - 1) % 2
# Add the proper elements to the temp array and format the separator.
temp = data[0, head] + [ nil ] + data[-tail, tail]
if is_hash
temp[head] = "#{indent}#{data[head].strip} .. #{data[data.length - tail - 1].strip}"
else
temp[head] = "#{indent}[#{head.to_s.rjust(width)}] .. [#{data.length - tail - 1}]"
end
temp
end
end
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
# method.to_s formats to handle:
#
# #<Method: Fixnum#zero?>
# #<Method: Fixnum(Integer)#years>
# #<Method: User(#<Module:0x00000103207c00>)#_username>
# #<Method: User(id: integer, username: string).table_name>
# #<Method: User(id: integer, username: string)(ActiveRecord::Base).current>
# #<UnboundMethod: Hello#world>
#
if method.to_s =~ /(Unbound)*Method: (.*)[#\.]/
unbound, klass = $1 && '(unbound)', $2
if klass && klass =~ /(\(\w+:\s.*?\))/ # Is this ActiveRecord-style class?
klass.sub!($1, '') # Yes, strip the fields leaving class name only.
end
owner = "#{klass}#{unbound}".gsub('(', ' (')
end
[ method.name.to_s, "(#{args.join(', ')})", owner.to_s ]
end
#
# Indentation related methods
#-----------------------------------------
def indentation
inspector.current_indentation
end
def indented
inspector.increase_indentation(&Proc.new)
end
def indent
' ' * indentation
end
def outdent
' ' * (indentation - options[:indent].abs)
end
def align(value, width)
if options[:multiline]
if options[:indent] > 0
value.rjust(width)
elsif options[:indent] == 0
indent + value.ljust(width)
else
indent[0, indentation + options[:indent]] + value.ljust(width)
end
else
value
end
end
end
end
end

View file

@ -0,0 +1,24 @@
require_relative 'base_formatter'
module AwesomePrint
module Formatters
class ClassFormatter < BaseFormatter
attr_reader :klass, :inspector, :options
def initialize(klass, inspector)
@klass = klass
@inspector = inspector
@options = inspector.options
end
def format
if superclass = klass.superclass # <-- Assign and test if nil.
colorize("#{klass.inspect} < #{superclass}", :class)
else
colorize(klass.inspect, :class)
end
end
end
end
end

View file

@ -0,0 +1,22 @@
require_relative 'base_formatter'
require "shellwords"
module AwesomePrint
module Formatters
class DirFormatter < BaseFormatter
attr_reader :dir, :inspector, :options
def initialize(dir, inspector)
@dir = dir
@inspector = inspector
@options = inspector.options
end
def format
ls = `ls -alF #{dir.path.shellescape}`
colorize(ls.empty? ? dir.inspect : "#{dir.inspect}\n#{ls.chop}", :dir)
end
end
end
end

View file

@ -0,0 +1,22 @@
require_relative 'base_formatter'
require "shellwords"
module AwesomePrint
module Formatters
class FileFormatter < BaseFormatter
attr_reader :file, :inspector, :options
def initialize(file, inspector)
@file = file
@inspector = inspector
@options = inspector.options
end
def format
ls = File.directory?(file) ? `ls -adlF #{file.path.shellescape}` : `ls -alF #{file.path.shellescape}`
colorize(ls.empty? ? file.inspect : "#{file.inspect}\n#{ls.chop}", :file)
end
end
end
end

View file

@ -0,0 +1,54 @@
require_relative 'base_formatter'
module AwesomePrint
module Formatters
class HashFormatter < BaseFormatter
attr_reader :hash, :inspector, :options
def initialize(hash, inspector)
@hash = hash
@inspector = inspector
@options = inspector.options
end
def format
return "{}" if hash == {}
keys = hash.keys
keys = keys.sort { |a, b| a.to_s <=> b.to_s } if options[:sort_keys]
data = keys.map do |key|
plain_single_line do
[ inspector.awesome(key), hash[key] ]
end
end
width = data.map { |key, | key.size }.max || 0
width += indentation if options[:indent] > 0
data = data.map do |key, value|
indented do
align(key, width) << colorize(" => ", :hash) << inspector.awesome(value)
end
end
data = limited(data, width, :hash => true) if should_be_limited?
if options[:multiline]
"{\n" << data.join(",\n") << "\n#{outdent}}"
else
"{ #{data.join(', ')} }"
end
end
private
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
end
end
end

View file

@ -0,0 +1,22 @@
require_relative 'base_formatter'
module AwesomePrint
module Formatters
class MethodFormatter < BaseFormatter
attr_reader :method, :inspector, :options
def initialize(method, inspector)
@method = method
@inspector = inspector
@options = inspector.options
end
def format
name, args, owner = method_tuple(method)
"#{colorize(owner, :class)}##{colorize(name, :method)}#{colorize(args, :args)}"
end
end
end
end

View file

@ -0,0 +1,80 @@
require_relative 'base_formatter'
module AwesomePrint
module Formatters
class ObjectFormatter < BaseFormatter
attr_reader :object, :variables, :inspector, :options
def initialize(object, variables, inspector)
@object = object
@variables = variables
@inspector = inspector
@options = inspector.options
end
def format
vars = variables.map do |var|
property = var.to_s[1..-1].to_sym # to_s because of some monkey patching done by Puppet.
accessor = if object.respond_to?(:"#{property}=")
object.respond_to?(property) ? :accessor : :writer
else
object.respond_to?(property) ? :reader : nil
end
if accessor
[ "attr_#{accessor} :#{property}", var ]
else
[ var.to_s, var ]
end
end
data = vars.sort.map do |declaration, var|
key = left_aligned do
align(declaration, declaration.size)
end
unless options[:plain]
if key =~ /(@\w+)/
key.sub!($1, colorize($1, :variable))
else
key.sub!(/(attr_\w+)\s(\:\w+)/, "#{colorize('\\1', :keyword)} #{colorize('\\2', :method)}")
end
end
indented do
var_contents = if valid_instance_var?(var)
object.instance_variable_get(var)
else
object.send(var) # Enables handling of Struct attributes
end
key << colorize(" = ", :hash) + inspector.awesome(var_contents)
end
end
if options[:multiline]
"#<#{awesome_instance}\n#{data.join(%Q/,\n/)}\n#{outdent}>"
else
"#<#{awesome_instance} #{data.join(', ')}>"
end
end
private
def valid_instance_var?(variable_name)
variable_name.to_s.start_with?('@')
end
def awesome_instance
"#{object.class}:0x%08x" % (object.__id__ * 2)
end
def left_aligned
current, options[:indent] = options[:indent], 0
yield
ensure
options[:indent] = current
end
end
end
end

View file

@ -0,0 +1,21 @@
require_relative 'base_formatter'
module AwesomePrint
module Formatters
class SimpleFormatter < BaseFormatter
attr_reader :string, :type, :inspector, :options
def initialize(string, type, inspector)
@string = string
@type = type
@inspector = inspector
@options = inspector.options
end
def format
colorize(string, type)
end
end
end
end

View file

@ -0,0 +1,18 @@
module AwesomePrint
class Indentator
attr_reader :shift_width, :indentation
def initialize(indentation)
@indentation = indentation
@shift_width = indentation.freeze
end
def indent
@indentation += shift_width
yield
ensure
@indentation -= shift_width
end
end
end

View file

@ -3,6 +3,8 @@
# Awesome Print is freely distributable under the terms of MIT license.
# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
#------------------------------------------------------------------------------
require_relative "indentator"
module AwesomePrint
class << self # Class accessors for custom defaults.
@ -48,7 +50,7 @@ module AwesomePrint
end
class Inspector
attr_accessor :options
attr_accessor :options, :indentator
AP = :__awesome_print__
@ -90,8 +92,17 @@ module AwesomePrint
merge_options!(options)
@formatter = AwesomePrint::Formatter.new(self)
@indentator = AwesomePrint::Indentator.new(@options[:indent].abs)
Thread.current[AP] ||= []
end
def current_indentation
indentator.indentation
end
def increase_indentation
indentator.indent(&Proc.new)
end
# Dispatcher that detects data nesting and invokes object-aware formatter.
#------------------------------------------------------------------------------