summaryrefslogtreecommitdiff
path: root/lib/pp.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pp.rb')
-rw-r--r--lib/pp.rb658
1 files changed, 371 insertions, 287 deletions
diff --git a/lib/pp.rb b/lib/pp.rb
index 1a4ebe16d3..5fd29a373a 100644
--- a/lib/pp.rb
+++ b/lib/pp.rb
@@ -1,11 +1,17 @@
-# == Pretty-printer for Ruby objects.
+# frozen_string_literal: true
+
+require 'prettyprint'
+
+##
+# A pretty-printer for Ruby objects.
#
-# = Which seems better?
+##
+# == What PP Does
#
-# non-pretty-printed output by #p is:
+# Standard output by #p returns this:
# #<PP:0x81fedf0 @genspace=#<Proc:0x81feda0>, @group_queue=#<PrettyPrint::GroupQueue:0x81fed3c @queue=[[#<PrettyPrint::Group:0x81fed78 @breakables=[], @depth=0, @break=false>], []]>, @buffer=[], @newline="\n", @group_stack=[#<PrettyPrint::Group:0x81fed78 @breakables=[], @depth=0, @break=false>], @buffer_width=0, @indent=0, @maxwidth=79, @output_width=2, @output=#<IO:0x8114ee4>>
#
-# pretty-printed output by #pp is:
+# Pretty-printed output returns this:
# #<PP:0x81fedf0
# @buffer=[],
# @buffer_width=0,
@@ -23,57 +29,72 @@
# @output=#<IO:0x8114ee4>,
# @output_width=2>
#
-# I like the latter. If you do too, this library is for you.
+##
+# == Usage
+#
+# pp(obj) #=> obj
+# pp obj #=> obj
+# pp(obj1, obj2, ...) #=> [obj1, obj2, ...]
+# pp() #=> nil
+#
+# Output <tt>obj(s)</tt> to <tt>$></tt> in pretty printed format.
+#
+# It returns <tt>obj(s)</tt>.
#
-# = Usage
+##
+# == Output Customization
#
-# pp(obj)
+# To define a customized pretty printing function for your classes,
+# redefine method <code>#pretty_print(pp)</code> in the class.
+# Note that <code>require 'pp'</code> is needed before redefining <code>#pretty_print(pp)</code>.
#
-# output +obj+ to +$>+ in pretty printed format.
+# <code>#pretty_print</code> takes the +pp+ argument, which is an instance of the PP class.
+# The method uses #text, #breakable, #nest, #group and #pp to print the
+# object.
#
-# It returns +nil+.
+##
+# == Pretty-Print JSON
#
-# = Output Customization
-# To define your customized pretty printing function for your classes,
-# redefine a method #pretty_print(+pp+) in the class.
-# It takes an argument +pp+ which is an instance of the class PP.
-# The method should use PP#text, PP#breakable, PP#nest, PP#group and
-# PP#pp to print the object.
+# To pretty-print JSON refer to JSON#pretty_generate.
#
-# = Author
-# Tanaka Akira <akr@m17n.org>
+##
+# == Author
+# Tanaka Akira <akr@fsij.org>
-require 'prettyprint'
+class PP < PrettyPrint
-module Kernel
- # returns a pretty printed object as a string.
- def pretty_inspect
- PP.pp(self, '')
- end
+ # The version string
+ VERSION = "0.6.3"
- private
- # prints arguments in pretty form.
+ # Returns the usable width for +out+.
+ # As the width of +out+:
+ # 1. If +out+ is assigned to a tty device, its width is used.
+ # 2. Otherwise, or it could not get the value, the +COLUMN+
+ # environment variable is assumed to be set to the width.
+ # 3. If +COLUMN+ is not set to a non-zero number, 80 is assumed.
#
- # pp returns nil.
- def pp(*objs) # :doc:
- objs.each {|obj|
- PP.pp(obj)
- }
- nil
+ # And finally, returns the above width value - 1.
+ # * This -1 is for Windows command prompt, which moves the cursor to
+ # the next line if it reaches the last column.
+ def PP.width_for(out)
+ begin
+ require 'io/console'
+ _, width = out.winsize
+ rescue LoadError, NoMethodError, SystemCallError
+ end
+ (width || ENV['COLUMNS']&.to_i&.nonzero? || 80) - 1
end
- module_function :pp
-end
-class PP < PrettyPrint
# Outputs +obj+ to +out+ in pretty printed format of
# +width+ columns in width.
#
- # If +out+ is omitted, +$>+ is assumed.
- # If +width+ is omitted, 79 is assumed.
+ # If +out+ is omitted, <code>$></code> is assumed.
+ # If +width+ is omitted, the width of +out+ is assumed (see
+ # width_for).
#
# PP.pp returns +out+.
- def PP.pp(obj, out=$>, width=79)
- q = PP.new(out, width)
+ def PP.pp(obj, out=$>, width=width_for(out))
+ q = new(out, width)
q.guard_inspect_key {q.pp obj}
q.flush
#$pp = q
@@ -93,32 +114,81 @@ class PP < PrettyPrint
# :stopdoc:
def PP.mcall(obj, mod, meth, *args, &block)
- mod.instance_method(meth).bind(obj).call(*args, &block)
+ mod.instance_method(meth).bind_call(obj, *args, &block)
end
# :startdoc:
- @sharing_detection = false
- class << self
- # Returns the sharing detection flag as a boolean value.
- # It is false by default.
- attr_accessor :sharing_detection
+ if defined? ::Ractor
+ class << self
+ # Returns the sharing detection flag as a boolean value.
+ # It is false (nil) by default.
+ def sharing_detection
+ Ractor.current[:pp_sharing_detection]
+ end
+ # Sets the sharing detection flag to b.
+ def sharing_detection=(b)
+ Ractor.current[:pp_sharing_detection] = b
+ end
+ end
+ else
+ @sharing_detection = false
+ class << self
+ # Returns the sharing detection flag as a boolean value.
+ # It is false by default.
+ attr_accessor :sharing_detection
+ end
end
+ # Module that defines helper methods for pretty_print.
module PPMethods
- InspectKey = :__inspect_key__
+ # Yields to a block
+ # and preserves the previous set of objects being printed.
def guard_inspect_key
- if Thread.current[InspectKey] == nil
- Thread.current[InspectKey] = []
- end
-
- save = Thread.current[InspectKey]
-
+ recursive_state = Thread.current[:__recursive_key__] ||= {}.compare_by_identity
+ save = recursive_state[:inspect] ||= {}.compare_by_identity
begin
- Thread.current[InspectKey] = []
+ recursive_state[:inspect] = {}.compare_by_identity
yield
ensure
- Thread.current[InspectKey] = save
+ recursive_state[:inspect] = save
+ end
+ end
+
+ # Check whether the object_id +id+ is in the current buffer of objects
+ # to be pretty printed. Used to break cycles in chains of objects to be
+ # pretty printed.
+ def check_inspect_key(id)
+ recursive_state = Thread.current[:__recursive_key__] or return false
+ recursive_state[:inspect]&.include?(id)
+ end
+
+ # Adds the object_id +id+ to the set of objects being pretty printed, so
+ # as to not repeat objects.
+ def push_inspect_key(id)
+ Thread.current[:__recursive_key__][:inspect][id] = true
+ end
+
+ # Removes an object from the set of objects being pretty printed.
+ def pop_inspect_key(id)
+ Thread.current[:__recursive_key__][:inspect].delete id
+ end
+
+ private def guard_inspect(object) # :nodoc:
+ recursive_state = Thread.current[:__recursive_key__]
+
+ if recursive_state&.key?(:inspect)
+ begin
+ push_inspect_key(object)
+ yield
+ ensure
+ pop_inspect_key(object) unless PP.sharing_detection
+ end
+ else
+ guard_inspect_key do
+ push_inspect_key(object)
+ yield
+ end
end
end
@@ -128,18 +198,21 @@ class PP < PrettyPrint
# Object#pretty_print_cycle is used when +obj+ is already
# printed, a.k.a the object reference chain has a cycle.
def pp(obj)
- id = obj.__id__
+ # If obj is a Delegator then use the object being delegated to for cycle
+ # detection
+ obj = obj.__getobj__ if defined?(::Delegator) and ::Delegator === obj
- if Thread.current[InspectKey].include? id
+ if check_inspect_key(obj)
group {obj.pretty_print_cycle self}
return
end
- begin
- Thread.current[InspectKey] << id
- group {obj.pretty_print self}
- ensure
- Thread.current[InspectKey].pop unless PP.sharing_detection
+ guard_inspect(obj) do
+ group do
+ obj.pretty_print self
+ rescue NoMethodError
+ text Kernel.instance_method(:inspect).bind_call(obj)
+ end
end
end
@@ -150,10 +223,12 @@ class PP < PrettyPrint
group(1, '#<' + obj.class.name, '>', &block)
end
+ # A convenience method, like object_group, but also reformats the Object's
+ # object_id.
def object_address_group(obj, &block)
- id = "%x" % (obj.__id__ * 2)
- id.sub!(/\Af(?=[[:xdigit:]]{2}+\z)/, '') if id.sub!(/\A\.\./, '')
- group(1, "\#<#{obj.class}:0x#{id}", '>', &block)
+ str = Kernel.instance_method(:to_s).bind_call(obj)
+ str.chomp!('>')
+ group(1, str, '>', &block)
end
# A convenience method which is same as follows:
@@ -182,7 +257,7 @@ class PP < PrettyPrint
#
# q.seplist([1,2,3]) {|v| xxx v }
#
- # q.seplist([1,2,3], lambda { comma_breakable }, :each) {|v| xxx v }
+ # q.seplist([1,2,3], lambda { q.comma_breakable }, :each) {|v| xxx v }
#
# xxx 1
# q.comma_breakable
@@ -192,16 +267,22 @@ class PP < PrettyPrint
def seplist(list, sep=nil, iter_method=:each) # :yield: element
sep ||= lambda { comma_breakable }
first = true
+ kwsplat = EMPTY_KWHASH
list.__send__(iter_method) {|*v|
if first
first = false
else
sep.call
end
- yield(*v)
+ kwsplat ? yield(*v, **kwsplat) : yield(*v)
}
end
+ EMPTY_KWHASH = if RUBY_VERSION >= "3.0" # :nodoc:
+ {}.freeze
+ end
+ private_constant :EMPTY_KWHASH
+ # A present standard failsafe for pretty printing any given Object
def pp_object(obj)
object_address_group(obj) {
seplist(obj.pretty_print_instance_variables, lambda { text ',' }) {|v|
@@ -217,33 +298,57 @@ class PP < PrettyPrint
}
end
+ # A pretty print for a Hash
def pp_hash(obj)
group(1, '{', '}') {
seplist(obj, nil, :each_pair) {|k, v|
group {
- pp k
- text '=>'
- group(1) {
- breakable ''
- pp v
- }
+ pp_hash_pair k, v
}
}
}
end
+
+ if RUBY_VERSION >= '3.4.'
+ # A pretty print for a pair of Hash
+ def pp_hash_pair(k, v)
+ if Symbol === k
+ if k.inspect.match?(%r[\A:["$@!]|[%&*+\-\/<=>@\]^`|~]\z])
+ k = k.to_s.inspect
+ end
+ text "#{k}:"
+ else
+ pp k
+ text ' '
+ text '=>'
+ end
+ group(1) {
+ breakable
+ pp v
+ }
+ end
+ else
+ def pp_hash_pair(k, v)
+ pp k
+ text '=>'
+ group(1) {
+ breakable ''
+ pp v
+ }
+ end
+ end
end
include PPMethods
- class SingleLine < PrettyPrint::SingleLine
+ class SingleLine < PrettyPrint::SingleLine # :nodoc:
include PPMethods
end
- module ObjectMixin
+ module ObjectMixin # :nodoc:
# 1. specific pretty_print
# 2. specific inspect
- # 3. specific to_s if instance variable is empty
- # 4. generic pretty_print
+ # 3. generic pretty_print
# A default pretty printing method for general objects.
# It calls #pretty_print_instance_variables to list instance variables.
@@ -255,10 +360,15 @@ class PP < PrettyPrint
# This module provides predefined #pretty_print methods for some of
# the most commonly used built-in classes for convenience.
def pretty_print(q)
- if /\(Kernel\)#/ !~ Object.instance_method(:method).bind(self).call(:inspect).inspect
+ umethod_method = Object.instance_method(:method)
+ begin
+ inspect_method = umethod_method.bind_call(self, :inspect)
+ rescue NameError
+ end
+ if inspect_method && inspect_method.owner != Kernel
+ q.text self.inspect
+ elsif !inspect_method && self.respond_to?(:inspect)
q.text self.inspect
- elsif /\(Kernel\)#/ !~ Object.instance_method(:method).bind(self).call(:to_s).inspect && instance_variables.empty?
- q.text self.to_s
else
q.pp_object(self)
end
@@ -278,7 +388,8 @@ class PP < PrettyPrint
# This method should return an array of names of instance variables as symbols or strings as:
# +[:@a, :@b]+.
def pretty_print_instance_variables
- instance_variables.sort
+ ivars = respond_to?(:instance_variables_to_inspect, true) ? instance_variables_to_inspect || instance_variables : instance_variables
+ ivars.sort
end
# Is #inspect implementation using #pretty_print.
@@ -289,16 +400,16 @@ class PP < PrettyPrint
# However, doing this requires that every class that #inspect is called on
# implement #pretty_print, or a RuntimeError will be raised.
def pretty_print_inspect
- if /\(PP::ObjectMixin\)#/ =~ Object.instance_method(:method).bind(self).call(:pretty_print).inspect
+ if Object.instance_method(:method).bind_call(self, :pretty_print).owner == PP::ObjectMixin
raise "pretty_print is not overridden for #{self.class}"
end
- PP.singleline_pp(self, '')
+ PP.singleline_pp(self, ''.dup)
end
end
end
-class Array
- def pretty_print(q)
+class Array # :nodoc:
+ def pretty_print(q) # :nodoc:
q.group(1, '[', ']') {
q.seplist(self) {|v|
q.pp v
@@ -306,30 +417,56 @@ class Array
}
end
- def pretty_print_cycle(q)
+ def pretty_print_cycle(q) # :nodoc:
q.text(empty? ? '[]' : '[...]')
end
end
-class Hash
- def pretty_print(q)
+class Hash # :nodoc:
+ def pretty_print(q) # :nodoc:
q.pp_hash self
end
- def pretty_print_cycle(q)
+ def pretty_print_cycle(q) # :nodoc:
q.text(empty? ? '{}' : '{...}')
end
end
-class << ENV
- def pretty_print(q)
- q.pp_hash self
+if defined?(Set)
+ if set_pp = Set.instance_method(:initialize).source_location
+ set_pp = !set_pp.first.end_with?("/set.rb") # not defined in set.rb
+ else
+ set_pp = true # defined in C
end
end
+class Set # :nodoc:
+ def pretty_print(pp) # :nodoc:
+ pp.group(1, "#{self.class.name}[", ']') {
+ pp.seplist(self) { |o|
+ pp.pp o
+ }
+ }
+ end
-class Struct
- def pretty_print(q)
- q.group(1, '#<struct ' + PP.mcall(self, Kernel, :class).name, '>') {
+ def pretty_print_cycle(pp) # :nodoc:
+ name = self.class.name
+ pp.text(empty? ? "#{name}[]" : "#{name}[...]")
+ end
+end if set_pp
+
+class << ENV # :nodoc:
+ def pretty_print(q) # :nodoc:
+ h = {}
+ ENV.keys.sort.each {|k|
+ h[k] = ENV[k]
+ }
+ q.pp_hash h
+ end
+end
+
+class Struct # :nodoc:
+ def pretty_print(q) # :nodoc:
+ q.group(1, sprintf("#<struct %s", PP.mcall(self, Kernel, :class).name), '>') {
q.seplist(PP.mcall(self, Struct, :members), lambda { q.text "," }) {|member|
q.breakable
q.text member.to_s
@@ -342,25 +479,83 @@ class Struct
}
end
- def pretty_print_cycle(q)
+ def pretty_print_cycle(q) # :nodoc:
q.text sprintf("#<struct %s:...>", PP.mcall(self, Kernel, :class).name)
end
end
-class Range
- def pretty_print(q)
- q.pp self.begin
+verbose, $VERBOSE = $VERBOSE, nil
+begin
+ has_data_define = defined?(Data.define)
+ensure
+ $VERBOSE = verbose
+end
+
+class Data # :nodoc:
+ def pretty_print(q) # :nodoc:
+ class_name = PP.mcall(self, Kernel, :class).name
+ class_name = " #{class_name}" if class_name
+ q.group(1, "#<data#{class_name}", '>') {
+
+ members = PP.mcall(self, Kernel, :class).members
+ values = []
+ members.select! do |member|
+ begin
+ values << __send__(member)
+ true
+ rescue NoMethodError
+ false
+ end
+ end
+
+ q.seplist(members.zip(values), lambda { q.text "," }) {|(member, value)|
+ q.breakable
+ q.text member.to_s
+ q.text '='
+ q.group(1) {
+ q.breakable ''
+ q.pp value
+ }
+ }
+ }
+ end
+
+ def pretty_print_cycle(q) # :nodoc:
+ q.text sprintf("#<data %s:...>", PP.mcall(self, Kernel, :class).name)
+ end
+end if has_data_define
+
+class Range # :nodoc:
+ def pretty_print(q) # :nodoc:
+ begin_nil = self.begin == nil
+ end_nil = self.end == nil
+ q.pp self.begin if !begin_nil || end_nil
q.breakable ''
q.text(self.exclude_end? ? '...' : '..')
q.breakable ''
- q.pp self.end
+ q.pp self.end if !end_nil || begin_nil
end
end
-class File
- class Stat
- def pretty_print(q)
- require 'etc.so'
+class String # :nodoc:
+ def pretty_print(q) # :nodoc:
+ lines = self.lines
+ if lines.size > 1
+ q.group(0, '', '') do
+ q.seplist(lines, lambda { q.text ' +'; q.breakable }) do |v|
+ q.pp v
+ end
+ end
+ else
+ q.text inspect
+ end
+ end
+end
+
+class File < IO # :nodoc:
+ class Stat # :nodoc:
+ def pretty_print(q) # :nodoc:
+ require 'etc'
q.object_group(self) {
q.breakable
q.text sprintf("dev=0x%x", self.dev); q.comma_breakable
@@ -410,8 +605,10 @@ class File
q.comma_breakable
q.group {
q.text sprintf("rdev=0x%x", self.rdev)
- q.breakable
- q.text sprintf('(%d, %d)', self.rdev_major, self.rdev_minor)
+ if self.rdev_major && self.rdev_minor
+ q.breakable
+ q.text sprintf('(%d, %d)', self.rdev_major, self.rdev_minor)
+ end
}
q.comma_breakable
q.text "size="; q.pp self.size; q.comma_breakable
@@ -439,18 +636,68 @@ class File
end
end
-class MatchData
- def pretty_print(q)
+class MatchData # :nodoc:
+ def pretty_print(q) # :nodoc:
+ nc = []
+ self.regexp.named_captures.each {|name, indexes|
+ indexes.each {|i| nc[i] = name }
+ }
q.object_group(self) {
q.breakable
- q.seplist(1..self.size, lambda { q.breakable }) {|i|
- q.pp self[i-1]
+ q.seplist(0...self.size, lambda { q.breakable }) {|i|
+ if i == 0
+ q.pp self[i]
+ else
+ if nc[i]
+ q.text nc[i]
+ else
+ q.pp i
+ end
+ q.text ':'
+ q.pp self[i]
+ end
}
}
end
end
-class Object
+if defined?(RubyVM::AbstractSyntaxTree)
+ class RubyVM::AbstractSyntaxTree::Node # :nodoc:
+ def pretty_print_children(q, names = [])
+ children.zip(names) do |c, n|
+ if n
+ q.breakable
+ q.text "#{n}:"
+ end
+ q.group(2) do
+ q.breakable
+ q.pp c
+ end
+ end
+ end
+
+ def pretty_print(q)
+ q.group(1, "(#{type}@#{first_lineno}:#{first_column}-#{last_lineno}:#{last_column}", ")") {
+ case type
+ when :SCOPE
+ pretty_print_children(q, %w"tbl args body")
+ when :ARGS
+ pretty_print_children(q, %w[pre_num pre_init opt first_post post_num post_init rest kw kwrest block])
+ when :DEFN
+ pretty_print_children(q, %w[mid body])
+ when :ARYPTN
+ pretty_print_children(q, %w[const pre rest post])
+ when :HSHPTN
+ pretty_print_children(q, %w[const kw kwrest])
+ else
+ pretty_print_children(q)
+ end
+ }
+ end
+ end
+end
+
+class Object < BasicObject # :nodoc:
include PP::ObjectMixin
end
@@ -470,185 +717,22 @@ end
}
}
-# :enddoc:
-if __FILE__ == $0
- require 'test/unit'
-
- class PPTest < Test::Unit::TestCase
- def test_list0123_12
- assert_equal("[0, 1, 2, 3]\n", PP.pp([0,1,2,3], '', 12))
- end
-
- def test_list0123_11
- assert_equal("[0,\n 1,\n 2,\n 3]\n", PP.pp([0,1,2,3], '', 11))
- end
-
- OverriddenStruct = Struct.new("OverriddenStruct", :members, :class)
- def test_struct_override_members # [ruby-core:7865]
- a = OverriddenStruct.new(1,2)
- assert_equal("#<struct Struct::OverriddenStruct members=1, class=2>\n", PP.pp(a, ''))
- end
-
- def test_redefined_method
- o = ""
- def o.method
- end
- assert_equal(%(""\n), PP.pp(o, ""))
- end
- end
-
- class HasInspect
- def initialize(a)
- @a = a
- end
-
- def inspect
- return "<inspect:#{@a.inspect}>"
- end
- end
-
- class HasPrettyPrint
- def initialize(a)
- @a = a
- end
-
- def pretty_print(q)
- q.text "<pretty_print:"
- q.pp @a
- q.text ">"
- end
- end
-
- class HasBoth
- def initialize(a)
- @a = a
- end
-
- def inspect
- return "<inspect:#{@a.inspect}>"
- end
-
- def pretty_print(q)
- q.text "<pretty_print:"
- q.pp @a
- q.text ">"
- end
- end
-
- class PrettyPrintInspect < HasPrettyPrint
- alias inspect pretty_print_inspect
- end
-
- class PrettyPrintInspectWithoutPrettyPrint
- alias inspect pretty_print_inspect
- end
-
- class PPInspectTest < Test::Unit::TestCase
- def test_hasinspect
- a = HasInspect.new(1)
- assert_equal("<inspect:1>\n", PP.pp(a, ''))
- end
-
- def test_hasprettyprint
- a = HasPrettyPrint.new(1)
- assert_equal("<pretty_print:1>\n", PP.pp(a, ''))
- end
-
- def test_hasboth
- a = HasBoth.new(1)
- assert_equal("<pretty_print:1>\n", PP.pp(a, ''))
- end
-
- def test_pretty_print_inspect
- a = PrettyPrintInspect.new(1)
- assert_equal("<pretty_print:1>", a.inspect)
- a = PrettyPrintInspectWithoutPrettyPrint.new
- assert_raise(RuntimeError) { a.inspect }
- end
-
- def test_proc
- a = proc {1}
- assert_equal("#{a.inspect}\n", PP.pp(a, ''))
- end
-
- def test_to_s_with_iv
- a = Object.new
- def a.to_s() "aaa" end
- a.instance_eval { @a = nil }
- result = PP.pp(a, '')
- assert_equal("#{a.inspect}\n", result)
- assert_match(/\A#<Object.*>\n\z/m, result)
- a = 1.0
- a.instance_eval { @a = nil }
- result = PP.pp(a, '')
- assert_equal("#{a.inspect}\n", result)
- end
-
- def test_to_s_without_iv
- a = Object.new
- def a.to_s() "aaa" end
- result = PP.pp(a, '')
- assert_equal("#{a.inspect}\n", result)
- assert_equal("aaa\n", result)
- end
- end
-
- class PPCycleTest < Test::Unit::TestCase
- def test_array
- a = []
- a << a
- assert_equal("[[...]]\n", PP.pp(a, ''))
- assert_equal("#{a.inspect}\n", PP.pp(a, ''))
- end
-
- def test_hash
- a = {}
- a[0] = a
- assert_equal("{0=>{...}}\n", PP.pp(a, ''))
- assert_equal("#{a.inspect}\n", PP.pp(a, ''))
- end
-
- S = Struct.new("S", :a, :b)
- def test_struct
- a = S.new(1,2)
- a.b = a
- assert_equal("#<struct Struct::S a=1, b=#<struct Struct::S:...>>\n", PP.pp(a, ''))
- assert_equal("#{a.inspect}\n", PP.pp(a, ''))
- end
-
- def test_object
- a = Object.new
- a.instance_eval {@a = a}
- assert_equal(a.inspect + "\n", PP.pp(a, ''))
- end
-
- def test_anonymous
- a = Class.new.new
- assert_equal(a.inspect + "\n", PP.pp(a, ''))
- end
-
- def test_withinspect
- a = []
- a << HasInspect.new(a)
- assert_equal("[<inspect:[...]>]\n", PP.pp(a, ''))
- assert_equal("#{a.inspect}\n", PP.pp(a, ''))
- end
-
- def test_share_nil
- begin
- PP.sharing_detection = true
- a = [nil, nil]
- assert_equal("[nil, nil]\n", PP.pp(a, ''))
- ensure
- PP.sharing_detection = false
- end
- end
+module Kernel
+ # Returns a pretty printed object as a string.
+ #
+ # See the PP module for more information.
+ def pretty_inspect
+ PP.pp(self, ''.dup)
end
- class PPSingleLineTest < Test::Unit::TestCase
- def test_hash
- assert_equal("{1=>1}", PP.singleline_pp({ 1 => 1}, '')) # [ruby-core:02699]
- assert_equal("[1#{', 1'*99}]", PP.singleline_pp([1]*100, ''))
- end
+ # prints arguments in pretty form.
+ #
+ # +#pp+ returns argument(s).
+ def pp(*objs)
+ objs.each {|obj|
+ PP.pp(obj)
+ }
+ objs.size <= 1 ? objs.first : objs
end
+ module_function :pp
end