Module: PP::PPMethods

Included in:
PP, SingleLine
Defined in:
lib/pp.rb

Overview

Module that defines helper methods for pretty_print.

Instance Method Summary collapse

Instance Method Details

#check_inspect_key(id) ⇒ Object

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.



169
170
171
172
173
# File 'lib/pp.rb', line 169

def check_inspect_key(id)
  Thread.current[:__recursive_key__] &&
  Thread.current[:__recursive_key__][:inspect] &&
  Thread.current[:__recursive_key__][:inspect].include?(id)
end

#comma_breakableObject

A convenience method which is same as follows:

text ','
breakable


232
233
234
235
# File 'lib/pp.rb', line 232

def comma_breakable
  text ','
  breakable
end

#guard_inspect_keyObject

Yields to a block and preserves the previous set of objects being printed.



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/pp.rb', line 147

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]

  begin
    Thread.current[:__recursive_key__][:inspect] = {}.compare_by_identity
    yield
  ensure
    Thread.current[:__recursive_key__][:inspect] = save
  end
end

#object_address_group(obj, &block) ⇒ Object

A convenience method, like object_group, but also reformats the Object’s object_id.



222
223
224
225
226
# File 'lib/pp.rb', line 222

def object_address_group(obj, &block)
  str = Kernel.instance_method(:to_s).bind_call(obj)
  str.chomp!('>')
  group(1, str, '>', &block)
end

#object_group(obj, &block) ⇒ Object

A convenience method which is same as follows:

group(1, '#<' + obj.class.name, '>') { ... }


216
217
218
# File 'lib/pp.rb', line 216

def object_group(obj, &block) # :yield:
  group(1, '#<' + obj.class.name, '>', &block)
end

#pop_inspect_key(id) ⇒ Object

Removes an object from the set of objects being pretty printed.



182
183
184
# File 'lib/pp.rb', line 182

def pop_inspect_key(id)
  Thread.current[:__recursive_key__][:inspect].delete id
end

#pp(obj) ⇒ Object

Adds obj to the pretty printing buffer using Object#pretty_print or Object#pretty_print_cycle.

Object#pretty_print_cycle is used when obj is already printed, a.k.a the object reference chain has a cycle.



191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/pp.rb', line 191

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 ::Delegator === obj

  if check_inspect_key(obj)
    group {obj.pretty_print_cycle self}
    return
  end

  begin
    push_inspect_key(obj)
    group do
      obj.pretty_print self
    rescue NoMethodError
      text Kernel.instance_method(:inspect).bind_call(obj)
    end
  ensure
    pop_inspect_key(obj) unless PP.sharing_detection
  end
end

#pp_hash(obj) ⇒ Object

A pretty print for a Hash



291
292
293
294
295
296
297
298
299
# File 'lib/pp.rb', line 291

def pp_hash(obj)
  group(1, '{', '}') {
    seplist(obj, nil, :each_pair) {|k, v|
      group {
        pp_hash_pair k, v
      }
    }
  }
end

#pp_hash_pair(k, v) ⇒ Object

A pretty print for a pair of Hash



303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
# File 'lib/pp.rb', line 303

def pp_hash_pair(k, v)
  if Symbol === k
    sym_s = k.inspect
    if sym_s[1].match?(/["$@!]/) || sym_s[-1].match?(/[%&*+\-\/<=>@\]^`|~]/)
      text "#{k.to_s.inspect}:"
    else
      text "#{k}:"
    end
  else
    pp k
    text ' '
    text '=>'
  end
  group(1) {
    breakable
    pp v
  }
end

#pp_object(obj) ⇒ Object

A present standard failsafe for pretty printing any given Object



275
276
277
278
279
280
281
282
283
284
285
286
287
288
# File 'lib/pp.rb', line 275

def pp_object(obj)
  object_address_group(obj) {
    seplist(obj.pretty_print_instance_variables, lambda { text ',' }) {|v|
      breakable
      v = v.to_s if Symbol === v
      text v
      text '='
      group(1) {
        breakable ''
        pp(obj.instance_eval(v))
      }
    }
  }
end

#push_inspect_key(id) ⇒ Object

Adds the object_id id to the set of objects being pretty printed, so as to not repeat objects.



177
178
179
# File 'lib/pp.rb', line 177

def push_inspect_key(id)
  Thread.current[:__recursive_key__][:inspect][id] = true
end

#seplist(list, sep = nil, iter_method = :each) ⇒ Object

Adds a separated list. The list is separated by comma with breakable space, by default.

#seplist iterates the list using iter_method. It yields each object to the block given for #seplist. The procedure separator_proc is called between each yields.

If the iteration is zero times, separator_proc is not called at all.

If separator_proc is nil or not given, lambda { comma_breakable } is used. If iter_method is not given, :each is used.

For example, following 3 code fragments has similar effect.

q.seplist([1,2,3]) {|v| xxx v }

q.seplist([1,2,3], lambda { q.comma_breakable }, :each) {|v| xxx v }

xxx 1
q.comma_breakable
xxx 2
q.comma_breakable
xxx 3


261
262
263
264
265
266
267
268
269
270
271
272
# File 'lib/pp.rb', line 261

def seplist(list, sep=nil, iter_method=:each) # :yield: element
  sep ||= lambda { comma_breakable }
  first = true
  list.__send__(iter_method) {|*v|
    if first
      first = false
    else
      sep.call
    end
    RUBY_VERSION >= "3.0" ? yield(*v, **{}) : yield(*v)
  }
end