Project

General

Profile

Bug #7656 ยป ruby-docs_PrettyPrint-PP_20130206.patch

PrettyPrint and PP documentation - vbatts (Vincent Batts), 02/07/2013 02:52 PM

View differences:

lib/pp.rb
106 106
  end
107 107

  
108 108
  module PPMethods
109

  
110
    # Yields to a block
111
    # and preserves the previous set of objects being printed.
109 112
    def guard_inspect_key
110 113
      if Thread.current[:__recursive_key__] == nil
111 114
        Thread.current[:__recursive_key__] = {}.untrust
......
125 128
      end
126 129
    end
127 130

  
131
    # Check whether the object_id +id+ is in the current buffer of objects
132
    # to be pretty printed. Used to break cycles in chains of objects to be
133
    # pretty printed.
128 134
    def check_inspect_key(id)
129 135
      Thread.current[:__recursive_key__] &&
130 136
      Thread.current[:__recursive_key__][:inspect] &&
131 137
      Thread.current[:__recursive_key__][:inspect].include?(id)
132 138
    end
139

  
140
    # Adds the object_id +id+ to the set of objects being pretty printed, so
141
    # as to not repeat objects.
133 142
    def push_inspect_key(id)
134 143
      Thread.current[:__recursive_key__][:inspect][id] = true
135 144
    end
145

  
146
    # Removes an object from the set of objects being pretty printed.
136 147
    def pop_inspect_key(id)
137 148
      Thread.current[:__recursive_key__][:inspect].delete id
138 149
    end
......
165 176
      group(1, '#<' + obj.class.name, '>', &block)
166 177
    end
167 178

  
179
    # A mask used in formating object_id's into a hexadecimal id
168 180
    PointerMask = (1 << ([""].pack("p").size * 8)) - 1
169 181

  
170 182
    case Object.new.inspect
171 183
    when /\A\#<Object:0x([0-9a-f]+)>\z/
184
      # String Formating for hexadecimal id
172 185
      PointerFormat = "%0#{$1.length}x"
173 186
    else
174 187
      PointerFormat = "%x"
175 188
    end
176 189

  
177
    def object_address_group(obj, &block)
190
    # A convenience method, like object_group, but also reformats the Object's
191
    # object_id.
192
    def object_address_group(obj, &block) # :yield:
178 193
      id = PointerFormat % (obj.object_id * 2 & PointerMask)
179 194
      group(1, "\#<#{obj.class}:0x#{id}", '>', &block)
180 195
    end
......
225 240
      }
226 241
    end
227 242

  
243
    # A present standard failsafe for pretty printing any given Object
228 244
    def pp_object(obj)
229 245
      object_address_group(obj) {
230 246
        seplist(obj.pretty_print_instance_variables, lambda { text ',' }) {|v|
......
240 256
      }
241 257
    end
242 258

  
259
    # A pretty print for a Hash
243 260
    def pp_hash(obj)
244 261
      group(1, '{', '}') {
245 262
        seplist(obj, nil, :each_pair) {|k, v|
......
325 342
end
326 343

  
327 344
class Array
328
  def pretty_print(q)
345
  def pretty_print(q) # :nodoc:
329 346
    q.group(1, '[', ']') {
330 347
      q.seplist(self) {|v|
331 348
        q.pp v
......
333 350
    }
334 351
  end
335 352

  
336
  def pretty_print_cycle(q)
353
  def pretty_print_cycle(q) # :nodoc:
337 354
    q.text(empty? ? '[]' : '[...]')
338 355
  end
339 356
end
340 357

  
341 358
class Hash
342
  def pretty_print(q)
359
  def pretty_print(q) # :nodoc:
343 360
    q.pp_hash self
344 361
  end
345 362

  
346
  def pretty_print_cycle(q)
363
  def pretty_print_cycle(q) # :nodoc:
347 364
    q.text(empty? ? '{}' : '{...}')
348 365
  end
349 366
end
350 367

  
351 368
class << ENV
352
  def pretty_print(q)
369
  def pretty_print(q) # :nodoc:
353 370
    h = {}
354 371
    ENV.keys.sort.each {|k|
355 372
      h[k] = ENV[k]
......
359 376
end
360 377

  
361 378
class Struct
362
  def pretty_print(q)
379
  def pretty_print(q) # :nodoc:
363 380
    q.group(1, sprintf("#<struct %s", PP.mcall(self, Kernel, :class).name), '>') {
364 381
      q.seplist(PP.mcall(self, Struct, :members), lambda { q.text "," }) {|member|
365 382
        q.breakable
......
373 390
    }
374 391
  end
375 392

  
376
  def pretty_print_cycle(q)
393
  def pretty_print_cycle(q) # :nodoc:
377 394
    q.text sprintf("#<struct %s:...>", PP.mcall(self, Kernel, :class).name)
378 395
  end
379 396
end
380 397

  
381 398
class Range
382
  def pretty_print(q)
399
  def pretty_print(q) # :nodoc:
383 400
    q.pp self.begin
384 401
    q.breakable ''
385 402
    q.text(self.exclude_end? ? '...' : '..')
......
390 407

  
391 408
class File < IO
392 409
  class Stat
393
    def pretty_print(q)
410
    def pretty_print(q) # :nodoc:
394 411
      require 'etc.so'
395 412
      q.object_group(self) {
396 413
        q.breakable
......
471 488
end
472 489

  
473 490
class MatchData
474
  def pretty_print(q)
491
  def pretty_print(q) # :nodoc:
475 492
    nc = []
476 493
    self.regexp.named_captures.each {|name, indexes|
477 494
      indexes.each {|i| nc[i] = name }
lib/prettyprint.rb
90 90
    @group_queue = GroupQueue.new(root_group)
91 91
    @indent = 0
92 92
  end
93
  attr_reader :output, :maxwidth, :newline, :genspace
94
  attr_reader :indent, :group_queue
93

  
94
  # The output object.
95
  #
96
  # This defaults to '', and should accept the << method
97
  attr_reader :output
98

  
99
  # The maximum width of a line, before it is seperated in to a newline
100
  #
101
  # This defaults to 79, and should be a Fixnum
102
  attr_reader :maxwidth
103

  
104
  # The value that is appended to +output+ to add a new line.
105
  #
106
  # This defaults to "\n", and should be String
107
  attr_reader :newline
108

  
109
  # A lambda or Proc, that takes one argument, of a Fixnum, and returns
110
  # the corresponding number of spaces.
111
  #
112
  # By default this is:
113
  #   lambda {|n| ' ' * n}
114
  attr_reader :genspace
115

  
116
  # The number of spaces to be indented
117
  attr_reader :indent
118

  
119
  # The PrettyPrint::GroupQueue of groups in stack to be pretty printed
120
  attr_reader :group_queue
95 121

  
96 122
  # Returns the group most recently added to the stack.
97 123
  def current_group
......
166 192
  # may cause 2 results:
167 193
  # (break,break), (non-break,non-break).
168 194
  #
169
  # The text sep+ is inserted if a line is not broken at this point.
195
  # The text +sep+ is inserted if a line is not broken at this point.
170 196
  #
171 197
  # If +sep+ is not specified, " " is used.
172 198
  #
......
210 236
  # before grouping. If +close_obj+ is specified, <tt>text close_obj,
211 237
  # close_width</tt> is called after grouping.
212 238
  #
239
  # Here is a contrived example to see the +depth+ of the group increase:
240
  #
241
  #   p q.current_group  #=>   #<PrettyPrint::Group:0x00000000cf0210 @break=false, @breakables=[], @depth=0>
242
  #   q.group(1, '[',']') {
243
  #       p q.current_group
244
  #     }
245
  #   #=> <PrettyPrint::Group:0x00000000d29060 @break=false, @breakables=[], @depth=1>
246
  #
213 247
  def group(indent=0, open_obj='', close_obj='', open_width=open_obj.length, close_width=close_obj.length)
214 248
    text open_obj, open_width
215 249
    group_sub {
......
220 254
    text close_obj, close_width
221 255
  end
222 256

  
257
  # Takes a &blok and queues a new group that is indented 1 further.
223 258
  def group_sub
224 259
    group = Group.new(@group_stack.last.depth + 1)
225 260
    @group_stack.push group
......
256 291
    @buffer_width = 0
257 292
  end
258 293

  
294
  # The Text class is the means by which to collect strings from objects.
295
  #
296
  # This class is intended for internal use of the PrettyPrint buffers.
259 297
  class Text
298

  
299
    # Create a new PrettyPrint::Text object.
300
    #
301
    # This contructor takes no arguments. The workflow is to append a Text
302
    # object to the buffer, and being able to call the buffer.last() to
303
    # reference it.
304
    # As there are objects, use PrettyPrint::Text#add to include the objects
305
    # and the width to utilized by the String version of this object.
260 306
    def initialize
261 307
      @objs = []
262 308
      @width = 0
263 309
    end
310

  
311
    # The total width of the objects included in this PrettyPrint::Text object.
264 312
    attr_reader :width
265 313

  
314
    # Render the String text of the objects that have been added to this
315
    # PrettyPrint::Text. Output the text to +out+, and increment the width
316
    # to +output_width+
266 317
    def output(out, output_width)
267 318
      @objs.each {|obj| out << obj}
268 319
      output_width + @width
269 320
    end
270 321

  
322
    # Include +obj+ in the objects to be pretty printed, and increment
323
    # this Text object's total width by +width+
271 324
    def add(obj, width)
272 325
      @objs << obj
273 326
      @width += width
274 327
    end
275 328
  end
276 329

  
330
  # The Breakable class is used for breaking up object information
331
  #
332
  # This class is intended for internal use of the PrettyPrint buffers.
277 333
  class Breakable
334

  
335
    # Create a new Breakable object.
336
    #
337
    # Arguments:
338
    # * +sep+ String of the seperator
339
    # * +width+ Fixnum width of the +sep+
340
    # * +q+ parent PrettyPrint object, to base from
278 341
    def initialize(sep, width, q)
279 342
      @obj = sep
280 343
      @width = width
......
283 346
      @group = q.current_group
284 347
      @group.breakables.push self
285 348
    end
286
    attr_reader :obj, :width, :indent
287 349

  
350
    # holds the seperator String
351
    #
352
    # (+sep+ from #new)
353
    attr_reader :obj
354

  
355
    # the width of +obj+ / +sep+
356
    attr_reader :width
357

  
358
    # the number of spaces to indent.
359
    #
360
    # This is inferred from +q+ PrettyPrint, given in #new
361
    attr_reader :indent
362

  
363
    # Render the String text of the objects that have been added to this
364
    # PrettyPrint::Breakable. Output the text to +out+, and increment the width
365
    # to +output_width+
288 366
    def output(out, output_width)
289 367
      @group.breakables.shift
290 368
      if @group.break?
......
299 377
    end
300 378
  end
301 379

  
380
  # The Group class is used for making indentation easier.
381
  #
382
  # While this class does neither the breaking into newlines nor indentation,
383
  # it is used in a stack (as well as a queue) within PrettyPrint, to group
384
  # objects.
385
  #
386
  # For information on using groups, see PrettyPrint#group
387
  #
388
  # This class is intended for internal use of the PrettyPrint buffers.
302 389
  class Group
390
    # Create a Group object
391
    #
392
    # Arguments:
393
    # * +depth+ - this group's relation to previous groups
394
    #
395
    # Contrived example:
396
    #   out = ""
397
    #   => ""
398
    #   q = PrettyPrint.new(out)
399
    #   => #<PrettyPrint:0x82f85c0 @output="", @maxwidth=79, @newline="\n", @genspace=#<Proc:0x82f8368@/home/vbatts/.rvm/rubies/ruby-head/lib/ruby/2.0.0/prettyprint.rb:82 (lambda)>, @output_width=0, @buffer_width=0, @buffer=[], @group_stack=[#<PrettyPrint::Group:0x82f8138 @depth=0, @breakables=[], @break=false>], @group_queue=#<PrettyPrint::GroupQueue:0x82fb7c0 @queue=[[#<PrettyPrint::Group:0x82f8138 @depth=0, @breakables=[], @break=false>]]>, @indent=0>
400
    #   q.group {
401
    #     q.text q.current_group.inspect
402
    #     q.text q.newline
403
    #     q.group(q.current_group.depth + 1) {
404
    #       q.text q.current_group.inspect
405
    #       q.text q.newline
406
    #       q.group(q.current_group.depth + 1) {
407
    #         q.text q.current_group.inspect
408
    #         q.text q.newline
409
    #         q.group(q.current_group.depth + 1) {
410
    #           q.text q.current_group.inspect
411
    #           q.text q.newline
412
    #         }
413
    #       }
414
    #     }
415
    #   }
416
    #   => 284
417
    #    puts out
418
    #   #<PrettyPrint::Group:0x8354758 @depth=1, @breakables=[], @break=false>
419
    #   #<PrettyPrint::Group:0x8354550 @depth=2, @breakables=[], @break=false>
420
    #   #<PrettyPrint::Group:0x83541cc @depth=3, @breakables=[], @break=false>
421
    #   #<PrettyPrint::Group:0x8347e54 @depth=4, @breakables=[], @break=false>
422
    #
303 423
    def initialize(depth)
304 424
      @depth = depth
305 425
      @breakables = []
306 426
      @break = false
307 427
    end
308
    attr_reader :depth, :breakables
309 428

  
429
    # this group's relation to previous groups
430
    attr_reader :depth
431

  
432
    # Array to hold the Breakable objects for this Group
433
    attr_reader :breakables
434

  
435
    # Makes a break for this Group, and returns true
310 436
    def break
311 437
      @break = true
312 438
    end
313 439

  
440
    # Boolean of whether this Group has made a break
314 441
    def break?
315 442
      @break
316 443
    end
317 444

  
445
    # Boolean of whether this Group has been queried for being first
446
    #
447
    # This is used as a predicate, and ought to be called first.
318 448
    def first?
319 449
      if defined? @first
320 450
        false
......
325 455
    end
326 456
  end
327 457

  
458
  # The GroupQueue class is used for managing the queue of Group to be pretty
459
  # printed.
460
  #
461
  # This queue groups the Group objects, based on their depth.
462
  #
463
  # This class is intended for internal use of the PrettyPrint buffers.
328 464
  class GroupQueue
465
    # Create a GroupQueue object
466
    #
467
    # Arguments:
468
    # * +groups+ - one or more PrettyPrint::Group objects
329 469
    def initialize(*groups)
330 470
      @queue = []
331 471
      groups.each {|g| enq g}
332 472
    end
333 473

  
474
    # Enqueue +group+
475
    #
476
    # This does not strictly append the group to the end of the queue,
477
    # but instead adds it in line, base on the +group.depth+
334 478
    def enq(group)
335 479
      depth = group.depth
336 480
      @queue << [] until depth < @queue.length
337 481
      @queue[depth] << group
338 482
    end
339 483

  
484
    # returns the outer group of the queue
340 485
    def deq
341 486
      @queue.each {|gs|
342 487
        (gs.length-1).downto(0) {|i|
......
352 497
      return nil
353 498
    end
354 499

  
500
    # Remote +group+ from this queue
355 501
    def delete(group)
356 502
      @queue[group.depth].delete(group)
357 503
    end
358 504
  end
359 505

  
506
  # PrettyPrint::SingleLine is used by PrettyPrint.singleline_format
507
  #
508
  # It is passed to be similar to a PrettyPrint object itself, by responding to:
509
  # * #text
510
  # * #breakable
511
  # * #nest
512
  # * #group
513
  # * #flush
514
  # * #first?
515
  #
516
  # but instead, the output has no line breaks
517
  #
360 518
  class SingleLine
519
    # Create a PrettyPrint::SingleLine object
520
    #
521
    # Arguments:
522
    # * +output+ - String (or similar) to store rendered text. Needs to respond to '<<'
523
    # * +maxwidth+ - Argument position expected to be here for compatibility.
524
    #                This argument is a noop.
525
    # * +newline+ - Argument position expected to be here for compatibility.
526
    #               This argument is a noop.
361 527
    def initialize(output, maxwidth=nil, newline=nil)
362 528
      @output = output
363 529
      @first = [true]
364 530
    end
365 531

  
532
    # Add +obj+ to the text to be outputed.
533
    #
534
    # +width+ argument is here for compatibility. It is a noop argument.
366 535
    def text(obj, width=nil)
367 536
      @output << obj
368 537
    end
369 538

  
539
    # Appends +sep+ to the text to be outputed. By default +sep+ is ' '
540
    #
541
    # +width+ argument is here for compatibility. It is a noop argument.
370 542
    def breakable(sep=' ', width=nil)
371 543
      @output << sep
372 544
    end
373 545

  
546
    # Takes +indent+ arg, but does nothing with it. Yields to a &blok
374 547
    def nest(indent)
375 548
      yield
376 549
    end
377 550

  
551
    # Opens a &blok for grouping objects to be pretty printed.
552
    #
553
    # Arguments:
554
    # * +indent+ - noop argument. Present for compatibility.
555
    # * +open_obj+ - text appended before the &blok. Default is ''
556
    # * +close_obj+ - text appended after the &blok. Default is ''
557
    # * +open_width+ - noop argument. Present for compatibility.
558
    # * +close_width+ - noop argument. Present for compatibility.
378 559
    def group(indent=nil, open_obj='', close_obj='', open_width=nil, close_width=nil)
379 560
      @first.push true
380 561
      @output << open_obj
......
383 564
      @first.pop
384 565
    end
385 566

  
567
    # Method present for compatibility, but is a noop
386 568
    def flush
387 569
    end
388 570

  
571
    # This is used as a predicate, and ought to be called first.
389 572
    def first?
390 573
      result = @first[-1]
391 574
      @first[-1] = false