summaryrefslogtreecommitdiff
path: root/lib/pp.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pp.rb')
-rw-r--r--lib/pp.rb158
1 files changed, 119 insertions, 39 deletions
diff --git a/lib/pp.rb b/lib/pp.rb
index 1ec5a880eb..5fd29a373a 100644
--- a/lib/pp.rb
+++ b/lib/pp.rb
@@ -63,7 +63,8 @@ require 'prettyprint'
class PP < PrettyPrint
- VERSION = "0.5.0"
+ # The version string
+ VERSION = "0.6.3"
# Returns the usable width for +out+.
# As the width of +out+:
@@ -138,26 +139,19 @@ class PP < PrettyPrint
end
end
+ # Module that defines helper methods for pretty_print.
module PPMethods
# Yields to a block
# and preserves the previous set of objects being printed.
def guard_inspect_key
- if Thread.current[:__recursive_key__] == nil
- Thread.current[:__recursive_key__] = {}.compare_by_identity
- end
-
- if Thread.current[:__recursive_key__][:inspect] == nil
- Thread.current[:__recursive_key__][:inspect] = {}.compare_by_identity
- end
-
- save = Thread.current[:__recursive_key__][:inspect]
-
+ recursive_state = Thread.current[:__recursive_key__] ||= {}.compare_by_identity
+ save = recursive_state[:inspect] ||= {}.compare_by_identity
begin
- Thread.current[:__recursive_key__][:inspect] = {}.compare_by_identity
+ recursive_state[:inspect] = {}.compare_by_identity
yield
ensure
- Thread.current[:__recursive_key__][:inspect] = save
+ recursive_state[:inspect] = save
end
end
@@ -165,9 +159,8 @@ class PP < PrettyPrint
# to be pretty printed. Used to break cycles in chains of objects to be
# pretty printed.
def check_inspect_key(id)
- Thread.current[:__recursive_key__] &&
- Thread.current[:__recursive_key__][:inspect] &&
- Thread.current[:__recursive_key__][:inspect].include?(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
@@ -181,6 +174,24 @@ class PP < PrettyPrint
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
+
# Adds +obj+ to the pretty printing buffer
# using Object#pretty_print or Object#pretty_print_cycle.
#
@@ -189,18 +200,19 @@ class PP < PrettyPrint
def pp(obj)
# If obj is a Delegator then use the object being delegated to for cycle
# detection
- obj = obj.__getobj__ if defined?(::Delegator) and obj.is_a?(::Delegator)
+ obj = obj.__getobj__ if defined?(::Delegator) and ::Delegator === obj
if check_inspect_key(obj)
group {obj.pretty_print_cycle self}
return
end
- begin
- push_inspect_key(obj)
- group {obj.pretty_print self}
- ensure
- pop_inspect_key(obj) 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
@@ -255,15 +267,20 @@ 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
- RUBY_VERSION >= "3.0" ? yield(*v, **{}) : 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)
@@ -292,14 +309,33 @@ class PP < PrettyPrint
}
end
- # A pretty print for a pair of Hash
- def pp_hash_pair(k, v)
- pp k
- text '=>'
- group(1) {
- breakable ''
- pp v
- }
+ 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
@@ -352,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.
@@ -395,6 +432,28 @@ class Hash # :nodoc:
end
end
+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
+
+ 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 = {}
@@ -425,18 +484,37 @@ class Struct # :nodoc:
end
end
+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}", '>') {
- q.seplist(PP.mcall(self, Kernel, :class).members, lambda { q.text "," }) {|member|
+
+ 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 public_send(member)
+ q.pp value
}
}
}
@@ -445,15 +523,17 @@ class Data # :nodoc:
def pretty_print_cycle(q) # :nodoc:
q.text sprintf("#<data %s:...>", PP.mcall(self, Kernel, :class).name)
end
-end if defined?(Data.define)
+end if has_data_define
class Range # :nodoc:
def pretty_print(q) # :nodoc:
- q.pp self.begin if self.begin
+ 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 if self.end
+ q.pp self.end if !end_nil || begin_nil
end
end
@@ -582,7 +662,7 @@ class MatchData # :nodoc:
end
if defined?(RubyVM::AbstractSyntaxTree)
- class RubyVM::AbstractSyntaxTree::Node
+ class RubyVM::AbstractSyntaxTree::Node # :nodoc:
def pretty_print_children(q, names = [])
children.zip(names) do |c, n|
if n
@@ -647,7 +727,7 @@ module Kernel
# prints arguments in pretty form.
#
- # pp returns argument(s).
+ # +#pp+ returns argument(s).
def pp(*objs)
objs.each {|obj|
PP.pp(obj)