[rubygems/rubygems] Use a constant empty tar header to avoid extra allocations
[ruby.git] / lib / pp.rb
blob1ec5a880eb8fac5a13c5ac2ea603833cf5bae794
1 # frozen_string_literal: true
3 require 'prettyprint'
5 ##
6 # A pretty-printer for Ruby objects.
8 ##
9 # == What PP Does
11 # Standard output by #p returns this:
12 #   #<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>>
14 # Pretty-printed output returns this:
15 #   #<PP:0x81fedf0
16 #    @buffer=[],
17 #    @buffer_width=0,
18 #    @genspace=#<Proc:0x81feda0>,
19 #    @group_queue=
20 #     #<PrettyPrint::GroupQueue:0x81fed3c
21 #      @queue=
22 #       [[#<PrettyPrint::Group:0x81fed78 @break=false, @breakables=[], @depth=0>],
23 #        []]>,
24 #    @group_stack=
25 #     [#<PrettyPrint::Group:0x81fed78 @break=false, @breakables=[], @depth=0>],
26 #    @indent=0,
27 #    @maxwidth=79,
28 #    @newline="\n",
29 #    @output=#<IO:0x8114ee4>,
30 #    @output_width=2>
33 # == Usage
35 #   pp(obj)             #=> obj
36 #   pp obj              #=> obj
37 #   pp(obj1, obj2, ...) #=> [obj1, obj2, ...]
38 #   pp()                #=> nil
40 # Output <tt>obj(s)</tt> to <tt>$></tt> in pretty printed format.
42 # It returns <tt>obj(s)</tt>.
45 # == Output Customization
47 # To define a customized pretty printing function for your classes,
48 # redefine method <code>#pretty_print(pp)</code> in the class.
49 # Note that <code>require 'pp'</code> is needed before redefining <code>#pretty_print(pp)</code>.
51 # <code>#pretty_print</code> takes the +pp+ argument, which is an instance of the PP class.
52 # The method uses #text, #breakable, #nest, #group and #pp to print the
53 # object.
56 # == Pretty-Print JSON
58 # To pretty-print JSON refer to JSON#pretty_generate.
61 # == Author
62 # Tanaka Akira <akr@fsij.org>
64 class PP < PrettyPrint
66   VERSION = "0.5.0"
68   # Returns the usable width for +out+.
69   # As the width of +out+:
70   # 1. If +out+ is assigned to a tty device, its width is used.
71   # 2. Otherwise, or it could not get the value, the +COLUMN+
72   #    environment variable is assumed to be set to the width.
73   # 3. If +COLUMN+ is not set to a non-zero number, 80 is assumed.
74   #
75   # And finally, returns the above width value - 1.
76   # * This -1 is for Windows command prompt, which moves the cursor to
77   #   the next line if it reaches the last column.
78   def PP.width_for(out)
79     begin
80       require 'io/console'
81       _, width = out.winsize
82     rescue LoadError, NoMethodError, SystemCallError
83     end
84     (width || ENV['COLUMNS']&.to_i&.nonzero? || 80) - 1
85   end
87   # Outputs +obj+ to +out+ in pretty printed format of
88   # +width+ columns in width.
89   #
90   # If +out+ is omitted, <code>$></code> is assumed.
91   # If +width+ is omitted, the width of +out+ is assumed (see
92   # width_for).
93   #
94   # PP.pp returns +out+.
95   def PP.pp(obj, out=$>, width=width_for(out))
96     q = new(out, width)
97     q.guard_inspect_key {q.pp obj}
98     q.flush
99     #$pp = q
100     out << "\n"
101   end
103   # Outputs +obj+ to +out+ like PP.pp but with no indent and
104   # newline.
105   #
106   # PP.singleline_pp returns +out+.
107   def PP.singleline_pp(obj, out=$>)
108     q = SingleLine.new(out)
109     q.guard_inspect_key {q.pp obj}
110     q.flush
111     out
112   end
114   # :stopdoc:
115   def PP.mcall(obj, mod, meth, *args, &block)
116     mod.instance_method(meth).bind_call(obj, *args, &block)
117   end
118   # :startdoc:
120   if defined? ::Ractor
121     class << self
122       # Returns the sharing detection flag as a boolean value.
123       # It is false (nil) by default.
124       def sharing_detection
125         Ractor.current[:pp_sharing_detection]
126       end
127       # Sets the sharing detection flag to b.
128       def sharing_detection=(b)
129         Ractor.current[:pp_sharing_detection] = b
130       end
131     end
132   else
133     @sharing_detection = false
134     class << self
135       # Returns the sharing detection flag as a boolean value.
136       # It is false by default.
137       attr_accessor :sharing_detection
138     end
139   end
141   module PPMethods
143     # Yields to a block
144     # and preserves the previous set of objects being printed.
145     def guard_inspect_key
146       if Thread.current[:__recursive_key__] == nil
147         Thread.current[:__recursive_key__] = {}.compare_by_identity
148       end
150       if Thread.current[:__recursive_key__][:inspect] == nil
151         Thread.current[:__recursive_key__][:inspect] = {}.compare_by_identity
152       end
154       save = Thread.current[:__recursive_key__][:inspect]
156       begin
157         Thread.current[:__recursive_key__][:inspect] = {}.compare_by_identity
158         yield
159       ensure
160         Thread.current[:__recursive_key__][:inspect] = save
161       end
162     end
164     # Check whether the object_id +id+ is in the current buffer of objects
165     # to be pretty printed. Used to break cycles in chains of objects to be
166     # pretty printed.
167     def check_inspect_key(id)
168       Thread.current[:__recursive_key__] &&
169       Thread.current[:__recursive_key__][:inspect] &&
170       Thread.current[:__recursive_key__][:inspect].include?(id)
171     end
173     # Adds the object_id +id+ to the set of objects being pretty printed, so
174     # as to not repeat objects.
175     def push_inspect_key(id)
176       Thread.current[:__recursive_key__][:inspect][id] = true
177     end
179     # Removes an object from the set of objects being pretty printed.
180     def pop_inspect_key(id)
181       Thread.current[:__recursive_key__][:inspect].delete id
182     end
184     # Adds +obj+ to the pretty printing buffer
185     # using Object#pretty_print or Object#pretty_print_cycle.
186     #
187     # Object#pretty_print_cycle is used when +obj+ is already
188     # printed, a.k.a the object reference chain has a cycle.
189     def pp(obj)
190       # If obj is a Delegator then use the object being delegated to for cycle
191       # detection
192       obj = obj.__getobj__ if defined?(::Delegator) and obj.is_a?(::Delegator)
194       if check_inspect_key(obj)
195         group {obj.pretty_print_cycle self}
196         return
197       end
199       begin
200         push_inspect_key(obj)
201         group {obj.pretty_print self}
202       ensure
203         pop_inspect_key(obj) unless PP.sharing_detection
204       end
205     end
207     # A convenience method which is same as follows:
208     #
209     #   group(1, '#<' + obj.class.name, '>') { ... }
210     def object_group(obj, &block) # :yield:
211       group(1, '#<' + obj.class.name, '>', &block)
212     end
214     # A convenience method, like object_group, but also reformats the Object's
215     # object_id.
216     def object_address_group(obj, &block)
217       str = Kernel.instance_method(:to_s).bind_call(obj)
218       str.chomp!('>')
219       group(1, str, '>', &block)
220     end
222     # A convenience method which is same as follows:
223     #
224     #   text ','
225     #   breakable
226     def comma_breakable
227       text ','
228       breakable
229     end
231     # Adds a separated list.
232     # The list is separated by comma with breakable space, by default.
233     #
234     # #seplist iterates the +list+ using +iter_method+.
235     # It yields each object to the block given for #seplist.
236     # The procedure +separator_proc+ is called between each yields.
237     #
238     # If the iteration is zero times, +separator_proc+ is not called at all.
239     #
240     # If +separator_proc+ is nil or not given,
241     # +lambda { comma_breakable }+ is used.
242     # If +iter_method+ is not given, :each is used.
243     #
244     # For example, following 3 code fragments has similar effect.
245     #
246     #   q.seplist([1,2,3]) {|v| xxx v }
247     #
248     #   q.seplist([1,2,3], lambda { q.comma_breakable }, :each) {|v| xxx v }
249     #
250     #   xxx 1
251     #   q.comma_breakable
252     #   xxx 2
253     #   q.comma_breakable
254     #   xxx 3
255     def seplist(list, sep=nil, iter_method=:each) # :yield: element
256       sep ||= lambda { comma_breakable }
257       first = true
258       list.__send__(iter_method) {|*v|
259         if first
260           first = false
261         else
262           sep.call
263         end
264         RUBY_VERSION >= "3.0" ? yield(*v, **{}) : yield(*v)
265       }
266     end
268     # A present standard failsafe for pretty printing any given Object
269     def pp_object(obj)
270       object_address_group(obj) {
271         seplist(obj.pretty_print_instance_variables, lambda { text ',' }) {|v|
272           breakable
273           v = v.to_s if Symbol === v
274           text v
275           text '='
276           group(1) {
277             breakable ''
278             pp(obj.instance_eval(v))
279           }
280         }
281       }
282     end
284     # A pretty print for a Hash
285     def pp_hash(obj)
286       group(1, '{', '}') {
287         seplist(obj, nil, :each_pair) {|k, v|
288           group {
289             pp_hash_pair k, v
290           }
291         }
292       }
293     end
295     # A pretty print for a pair of Hash
296     def pp_hash_pair(k, v)
297       pp k
298       text '=>'
299       group(1) {
300         breakable ''
301         pp v
302       }
303     end
304   end
306   include PPMethods
308   class SingleLine < PrettyPrint::SingleLine # :nodoc:
309     include PPMethods
310   end
312   module ObjectMixin # :nodoc:
313     # 1. specific pretty_print
314     # 2. specific inspect
315     # 3. generic pretty_print
317     # A default pretty printing method for general objects.
318     # It calls #pretty_print_instance_variables to list instance variables.
319     #
320     # If +self+ has a customized (redefined) #inspect method,
321     # the result of self.inspect is used but it obviously has no
322     # line break hints.
323     #
324     # This module provides predefined #pretty_print methods for some of
325     # the most commonly used built-in classes for convenience.
326     def pretty_print(q)
327       umethod_method = Object.instance_method(:method)
328       begin
329         inspect_method = umethod_method.bind_call(self, :inspect)
330       rescue NameError
331       end
332       if inspect_method && inspect_method.owner != Kernel
333         q.text self.inspect
334       elsif !inspect_method && self.respond_to?(:inspect)
335         q.text self.inspect
336       else
337         q.pp_object(self)
338       end
339     end
341     # A default pretty printing method for general objects that are
342     # detected as part of a cycle.
343     def pretty_print_cycle(q)
344       q.object_address_group(self) {
345         q.breakable
346         q.text '...'
347       }
348     end
350     # Returns a sorted array of instance variable names.
351     #
352     # This method should return an array of names of instance variables as symbols or strings as:
353     # +[:@a, :@b]+.
354     def pretty_print_instance_variables
355       instance_variables.sort
356     end
358     # Is #inspect implementation using #pretty_print.
359     # If you implement #pretty_print, it can be used as follows.
360     #
361     #   alias inspect pretty_print_inspect
362     #
363     # However, doing this requires that every class that #inspect is called on
364     # implement #pretty_print, or a RuntimeError will be raised.
365     def pretty_print_inspect
366       if Object.instance_method(:method).bind_call(self, :pretty_print).owner == PP::ObjectMixin
367         raise "pretty_print is not overridden for #{self.class}"
368       end
369       PP.singleline_pp(self, ''.dup)
370     end
371   end
374 class Array # :nodoc:
375   def pretty_print(q) # :nodoc:
376     q.group(1, '[', ']') {
377       q.seplist(self) {|v|
378         q.pp v
379       }
380     }
381   end
383   def pretty_print_cycle(q) # :nodoc:
384     q.text(empty? ? '[]' : '[...]')
385   end
388 class Hash # :nodoc:
389   def pretty_print(q) # :nodoc:
390     q.pp_hash self
391   end
393   def pretty_print_cycle(q) # :nodoc:
394     q.text(empty? ? '{}' : '{...}')
395   end
398 class << ENV # :nodoc:
399   def pretty_print(q) # :nodoc:
400     h = {}
401     ENV.keys.sort.each {|k|
402       h[k] = ENV[k]
403     }
404     q.pp_hash h
405   end
408 class Struct # :nodoc:
409   def pretty_print(q) # :nodoc:
410     q.group(1, sprintf("#<struct %s", PP.mcall(self, Kernel, :class).name), '>') {
411       q.seplist(PP.mcall(self, Struct, :members), lambda { q.text "," }) {|member|
412         q.breakable
413         q.text member.to_s
414         q.text '='
415         q.group(1) {
416           q.breakable ''
417           q.pp self[member]
418         }
419       }
420     }
421   end
423   def pretty_print_cycle(q) # :nodoc:
424     q.text sprintf("#<struct %s:...>", PP.mcall(self, Kernel, :class).name)
425   end
428 class Data # :nodoc:
429   def pretty_print(q) # :nodoc:
430     class_name = PP.mcall(self, Kernel, :class).name
431     class_name = " #{class_name}" if class_name
432     q.group(1, "#<data#{class_name}", '>') {
433       q.seplist(PP.mcall(self, Kernel, :class).members, lambda { q.text "," }) {|member|
434         q.breakable
435         q.text member.to_s
436         q.text '='
437         q.group(1) {
438           q.breakable ''
439           q.pp public_send(member)
440         }
441       }
442     }
443   end
445   def pretty_print_cycle(q) # :nodoc:
446     q.text sprintf("#<data %s:...>", PP.mcall(self, Kernel, :class).name)
447   end
448 end if defined?(Data.define)
450 class Range # :nodoc:
451   def pretty_print(q) # :nodoc:
452     q.pp self.begin if self.begin
453     q.breakable ''
454     q.text(self.exclude_end? ? '...' : '..')
455     q.breakable ''
456     q.pp self.end if self.end
457   end
460 class String # :nodoc:
461   def pretty_print(q) # :nodoc:
462     lines = self.lines
463     if lines.size > 1
464       q.group(0, '', '') do
465         q.seplist(lines, lambda { q.text ' +'; q.breakable }) do |v|
466           q.pp v
467         end
468       end
469     else
470       q.text inspect
471     end
472   end
475 class File < IO # :nodoc:
476   class Stat # :nodoc:
477     def pretty_print(q) # :nodoc:
478       require 'etc'
479       q.object_group(self) {
480         q.breakable
481         q.text sprintf("dev=0x%x", self.dev); q.comma_breakable
482         q.text "ino="; q.pp self.ino; q.comma_breakable
483         q.group {
484           m = self.mode
485           q.text sprintf("mode=0%o", m)
486           q.breakable
487           q.text sprintf("(%s %c%c%c%c%c%c%c%c%c)",
488             self.ftype,
489             (m & 0400 == 0 ? ?- : ?r),
490             (m & 0200 == 0 ? ?- : ?w),
491             (m & 0100 == 0 ? (m & 04000 == 0 ? ?- : ?S) :
492                              (m & 04000 == 0 ? ?x : ?s)),
493             (m & 0040 == 0 ? ?- : ?r),
494             (m & 0020 == 0 ? ?- : ?w),
495             (m & 0010 == 0 ? (m & 02000 == 0 ? ?- : ?S) :
496                              (m & 02000 == 0 ? ?x : ?s)),
497             (m & 0004 == 0 ? ?- : ?r),
498             (m & 0002 == 0 ? ?- : ?w),
499             (m & 0001 == 0 ? (m & 01000 == 0 ? ?- : ?T) :
500                              (m & 01000 == 0 ? ?x : ?t)))
501         }
502         q.comma_breakable
503         q.text "nlink="; q.pp self.nlink; q.comma_breakable
504         q.group {
505           q.text "uid="; q.pp self.uid
506           begin
507             pw = Etc.getpwuid(self.uid)
508           rescue ArgumentError
509           end
510           if pw
511             q.breakable; q.text "(#{pw.name})"
512           end
513         }
514         q.comma_breakable
515         q.group {
516           q.text "gid="; q.pp self.gid
517           begin
518             gr = Etc.getgrgid(self.gid)
519           rescue ArgumentError
520           end
521           if gr
522             q.breakable; q.text "(#{gr.name})"
523           end
524         }
525         q.comma_breakable
526         q.group {
527           q.text sprintf("rdev=0x%x", self.rdev)
528           if self.rdev_major && self.rdev_minor
529             q.breakable
530             q.text sprintf('(%d, %d)', self.rdev_major, self.rdev_minor)
531           end
532         }
533         q.comma_breakable
534         q.text "size="; q.pp self.size; q.comma_breakable
535         q.text "blksize="; q.pp self.blksize; q.comma_breakable
536         q.text "blocks="; q.pp self.blocks; q.comma_breakable
537         q.group {
538           t = self.atime
539           q.text "atime="; q.pp t
540           q.breakable; q.text "(#{t.tv_sec})"
541         }
542         q.comma_breakable
543         q.group {
544           t = self.mtime
545           q.text "mtime="; q.pp t
546           q.breakable; q.text "(#{t.tv_sec})"
547         }
548         q.comma_breakable
549         q.group {
550           t = self.ctime
551           q.text "ctime="; q.pp t
552           q.breakable; q.text "(#{t.tv_sec})"
553         }
554       }
555     end
556   end
559 class MatchData # :nodoc:
560   def pretty_print(q) # :nodoc:
561     nc = []
562     self.regexp.named_captures.each {|name, indexes|
563       indexes.each {|i| nc[i] = name }
564     }
565     q.object_group(self) {
566       q.breakable
567       q.seplist(0...self.size, lambda { q.breakable }) {|i|
568         if i == 0
569           q.pp self[i]
570         else
571           if nc[i]
572             q.text nc[i]
573           else
574             q.pp i
575           end
576           q.text ':'
577           q.pp self[i]
578         end
579       }
580     }
581   end
584 if defined?(RubyVM::AbstractSyntaxTree)
585   class RubyVM::AbstractSyntaxTree::Node
586     def pretty_print_children(q, names = [])
587       children.zip(names) do |c, n|
588         if n
589           q.breakable
590           q.text "#{n}:"
591         end
592         q.group(2) do
593           q.breakable
594           q.pp c
595         end
596       end
597     end
599     def pretty_print(q)
600       q.group(1, "(#{type}@#{first_lineno}:#{first_column}-#{last_lineno}:#{last_column}", ")") {
601         case type
602         when :SCOPE
603           pretty_print_children(q, %w"tbl args body")
604         when :ARGS
605           pretty_print_children(q, %w[pre_num pre_init opt first_post post_num post_init rest kw kwrest block])
606         when :DEFN
607           pretty_print_children(q, %w[mid body])
608         when :ARYPTN
609           pretty_print_children(q, %w[const pre rest post])
610         when :HSHPTN
611           pretty_print_children(q, %w[const kw kwrest])
612         else
613           pretty_print_children(q)
614         end
615       }
616     end
617   end
620 class Object < BasicObject # :nodoc:
621   include PP::ObjectMixin
624 [Numeric, Symbol, FalseClass, TrueClass, NilClass, Module].each {|c|
625   c.class_eval {
626     def pretty_print_cycle(q)
627       q.text inspect
628     end
629   }
632 [Numeric, FalseClass, TrueClass, Module].each {|c|
633   c.class_eval {
634     def pretty_print(q)
635       q.text inspect
636     end
637   }
640 module Kernel
641   # Returns a pretty printed object as a string.
642   #
643   # See the PP module for more information.
644   def pretty_inspect
645     PP.pp(self, ''.dup)
646   end
648   # prints arguments in pretty form.
649   #
650   # pp returns argument(s).
651   def pp(*objs)
652     objs.each {|obj|
653       PP.pp(obj)
654     }
655     objs.size <= 1 ? objs.first : objs
656   end
657   module_function :pp