puts_debuggerer 0.8.0 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.10.1
@@ -0,0 +1 @@
1
+ require 'puts_debuggerer'
@@ -1,23 +1,70 @@
1
- require 'ripper'
2
- require 'awesome_print'
1
+ require 'stringio'
2
+
3
+ require 'puts_debuggerer/core_ext/kernel'
4
+ require 'puts_debuggerer/run_determiner'
5
+ require 'puts_debuggerer/source_file'
6
+
7
+ # in case 'logger' is not required
8
+ class Logger
9
+ end
10
+
11
+ # in case 'logging' is not required
12
+ module Logging
13
+ class Logger
14
+ end
15
+ end
3
16
 
4
17
  module PutsDebuggerer
18
+ SOURCE_LINE_COUNT_DEFAULT = 1
5
19
  HEADER_DEFAULT = '*'*80
20
+ WRAPPER_DEFAULT = '*'*80
6
21
  FOOTER_DEFAULT = '*'*80
22
+ LOGGER_FORMATTER_DECORATOR = proc { |original_formatter|
23
+ proc { |severity, datetime, progname, msg|
24
+ original_formatter.call(severity, datetime, progname, msg.pd_inspect)
25
+ }
26
+ }
27
+ LOGGING_LAYOUT_DECORATOR = proc {|original_layout|
28
+ original_layout.clone.tap do |layout|
29
+ layout.singleton_class.class_eval do
30
+ alias original_format_obj format_obj
31
+ def format_obj(obj)
32
+ obj.pdi # alias to pd_inspect
33
+ end
34
+ end
35
+ end
36
+ }
37
+ RETURN_DEFAULT = true
38
+ OBJECT_PRINTER_DEFAULT = lambda do |object, print_engine_options=nil, source_line_count=nil, run_number=nil|
39
+ lambda do
40
+ if object.is_a?(Exception) && object.respond_to?(:full_message)
41
+ puts object.full_message
42
+ elsif PutsDebuggerer.print_engine.is_a?(Proc)
43
+ PutsDebuggerer.print_engine.call(object)
44
+ else
45
+ send(PutsDebuggerer.print_engine, object)
46
+ end
47
+ end
48
+ end
7
49
  PRINTER_DEFAULT = :puts
50
+ PRINTER_RAILS = lambda do |output|
51
+ puts output if Rails.env.test?
52
+ Rails.logger.debug(output)
53
+ end
8
54
  PRINT_ENGINE_DEFAULT = :ap
9
- PRINTER_MESSAGE_INVALID = 'printer must be a valid global method symbol (e.g. :puts) or lambda/proc receiving a text arg'
55
+ PRINTER_MESSAGE_INVALID = 'printer must be a valid global method symbol (e.g. :puts), a logger, or a lambda/proc receiving a text arg'
10
56
  PRINT_ENGINE_MESSAGE_INVALID = 'print_engine must be a valid global method symbol (e.g. :p, :ap or :pp) or lambda/proc receiving an object arg'
11
57
  ANNOUNCER_DEFAULT = '[PD]'
12
58
  FORMATTER_DEFAULT = -> (data) {
59
+ puts data[:wrapper] if data[:wrapper]
13
60
  puts data[:header] if data[:header]
14
- print "#{data[:announcer]} #{data[:file]}:#{data[:line_number]}#{__format_pd_expression__(data[:pd_expression], data[:object])} "
61
+ print "#{data[:announcer]} #{data[:file]}:#{data[:line_number]}#{" (run:#{data[:run_number]})" if data[:run_number]}#{__format_pd_expression__(data[:pd_expression], data[:object])} "
15
62
  data[:object_printer].call
16
63
  puts data[:caller].map {|l| ' ' + l} unless data[:caller].to_a.empty?
17
64
  puts data[:footer] if data[:footer]
65
+ puts data[:wrapper] if data[:wrapper]
18
66
  }
19
67
  CALLER_DEPTH_ZERO = 4 #depth includes pd + with_options method + nested block + build_pd_data method
20
- OBJECT_RUN_AT = {}
21
68
  STACK_TRACE_CALL_LINE_NUMBER_REGEX = /\:(\d+)\:in /
22
69
  STACK_TRACE_CALL_SOURCE_FILE_REGEX = /[ ]*([^:]+)\:\d+\:in /
23
70
 
@@ -41,6 +88,28 @@ module PutsDebuggerer
41
88
  @app_path = (path || Rails.root.to_s) rescue nil
42
89
  end
43
90
 
91
+ # Source Line Count.
92
+ # * Default value is `1`
93
+ #
94
+ # Example:
95
+ #
96
+ # PutsDebuggerer.source_line_count = 2
97
+ # pd (true ||
98
+ # false), source_line_count: 2
99
+ #
100
+ # Prints out:
101
+ #
102
+ # ********************************************************************************
103
+ # [PD] /Users/User/example.rb:2
104
+ # > pd (true ||
105
+ # false), source_line_count: 2
106
+ # => "true"
107
+ attr_reader :source_line_count
108
+
109
+ def source_line_count=(value)
110
+ @source_line_count = value || SOURCE_LINE_COUNT_DEFAULT
111
+ end
112
+
44
113
  # Header to include at the top of every print out.
45
114
  # * Default value is `nil`
46
115
  # * Value `true` enables header as `'*'*80`
@@ -60,19 +129,24 @@ module PutsDebuggerer
60
129
  # => "1"
61
130
  attr_reader :header
62
131
 
63
- def header=(value)
64
- if value.equal?(true)
65
- @header = HEADER_DEFAULT
66
- elsif value == ''
67
- @header = nil
68
- else
69
- @header = value
70
- end
71
- end
72
-
73
- def header?
74
- !!@header
75
- end
132
+ # Wrapper to include at the top and bottom of every print out (both header and footer).
133
+ # * Default value is `nil`
134
+ # * Value `true` enables wrapper as `'*'*80`
135
+ # * Value `false`, `nil`, or empty string disables wrapper
136
+ # * Any other string value gets set as a custom wrapper
137
+ #
138
+ # Example:
139
+ #
140
+ # PutsDebuggerer.wrapper = true
141
+ # pd (x=1)
142
+ #
143
+ # Prints out:
144
+ #
145
+ # [PD] /Users/User/example.rb:2
146
+ # > pd x=1
147
+ # => "1"
148
+ # ********************************************************************************
149
+ attr_reader :wrapper
76
150
 
77
151
  # Footer to include at the bottom of every print out.
78
152
  # * Default value is `nil`
@@ -92,24 +166,27 @@ module PutsDebuggerer
92
166
  # => "1"
93
167
  # ********************************************************************************
94
168
  attr_reader :footer
95
-
96
- def footer=(value)
97
- if value.equal?(true)
98
- @footer = FOOTER_DEFAULT
99
- elsif value == ''
100
- @footer = nil
101
- else
102
- @footer = value
169
+
170
+ ['header', 'footer', 'wrapper'].each do |boundary_option|
171
+ define_method("#{boundary_option}=") do |value|
172
+ if value.equal?(true)
173
+ instance_variable_set(:"@#{boundary_option}", const_get(:"#{boundary_option.upcase}_DEFAULT"))
174
+ elsif value == ''
175
+ instance_variable_set(:"@#{boundary_option}", nil)
176
+ else
177
+ instance_variable_set(:"@#{boundary_option}", value)
178
+ end
179
+ end
180
+
181
+ define_method("#{boundary_option}?") do
182
+ !!instance_variable_get(:"@#{boundary_option}")
103
183
  end
104
184
  end
105
185
 
106
- def footer?
107
- !!@footer
108
- end
109
-
110
- # Printer is a global method symbol or lambda expression to use in printing to the user.
111
- # Examples of global methods are `:puts` and `:print`.
186
+ # Printer is a global method symbol, lambda expression, or logger to use in printing to the user.
187
+ # Examples of a global method are `:puts` and `:print`.
112
188
  # An example of a lambda expression is `lambda {|output| Rails.logger.ap(output)}`
189
+ # Examples of a logger are a Ruby `Logger` instance or `Logging::Logger` instance
113
190
  #
114
191
  # Defaults to `:puts`
115
192
  # In Rails, it defaults to: `lambda {|output| Rails.logger.ap(output)}`
@@ -130,17 +207,37 @@ module PutsDebuggerer
130
207
 
131
208
  def printer=(printer)
132
209
  if printer.nil?
133
- if Object.const_defined?(:Rails)
134
- @printer = lambda {|output| Rails.logger.debug(output)}
135
- else
136
- @printer = PRINTER_DEFAULT
210
+ @printer = printer_default
211
+ elsif printer.is_a?(Logger)
212
+ @printer = printer
213
+ @logger_original_formatter = printer.formatter || Logger::Formatter.new
214
+ printer.formatter = LOGGER_FORMATTER_DECORATOR.call(@logger_original_formatter)
215
+ elsif printer.is_a?(Logging::Logger)
216
+ @printer = printer
217
+ @logging_original_layouts = printer.appenders.reduce({}) do |hash, appender|
218
+ hash.merge(appender => appender.layout)
137
219
  end
138
- elsif printer.is_a?(Proc)
220
+ printer.appenders.each do |appender|
221
+ appender.layout = LOGGING_LAYOUT_DECORATOR.call(appender.layout)
222
+ end
223
+ elsif printer == false || printer.is_a?(Proc) || printer.respond_to?(:log) # a logger
139
224
  @printer = printer
140
225
  else
141
226
  @printer = method(printer).name rescue raise(PRINTER_MESSAGE_INVALID)
142
227
  end
143
228
  end
229
+
230
+ def printer_default
231
+ Object.const_defined?(:Rails) ? PRINTER_RAILS : PRINTER_DEFAULT
232
+ end
233
+
234
+ # Logger original formatter before it was decorated with PutsDebuggerer::LOGGER_FORMATTER_DECORATOR
235
+ # upon setting the logger as a printer.
236
+ attr_reader :logger_original_formatter
237
+
238
+ # Logging library original layouts before being decorated with PutsDebuggerer::LOGGING_LAYOUT_DECORATOR
239
+ # upon setting the Logging library logger as a printer.
240
+ attr_reader :logging_original_layouts
144
241
 
145
242
  # Print engine is similar to `printer`, except it is focused on the scope of formatting
146
243
  # the data object being printed (excluding metadata such as file name, line number,
@@ -165,17 +262,25 @@ module PutsDebuggerer
165
262
  # > pd array
166
263
  # => [1, [2, 3]]
167
264
  # ]
168
- attr_reader :print_engine
265
+ def print_engine
266
+ if @print_engine.nil?
267
+ require 'awesome_print' if RUBY_PLATFORM != 'opal'
268
+ @print_engine = print_engine_default
269
+ end
270
+ @print_engine
271
+ end
169
272
 
170
273
  def print_engine=(engine)
171
- if engine.nil?
172
- @print_engine = PRINT_ENGINE_DEFAULT
173
- elsif engine.is_a?(Proc)
274
+ if engine.is_a?(Proc) || engine.nil?
174
275
  @print_engine = engine
175
276
  else
176
277
  @print_engine = method(engine).name rescue raise(PRINT_ENGINE_MESSAGE_INVALID)
177
278
  end
178
279
  end
280
+
281
+ def print_engine_default
282
+ Object.const_defined?(:AwesomePrint) ? PRINT_ENGINE_DEFAULT : :p
283
+ end
179
284
 
180
285
  # Announcer (e.g. [PD]) to announce every print out with (default: "[PD]")
181
286
  #
@@ -201,12 +306,14 @@ module PutsDebuggerer
201
306
  # * :announcer (string)
202
307
  # * :caller (array)
203
308
  # * :file (string)
309
+ # * :wrapper (string)
204
310
  # * :footer (string)
205
311
  # * :header (string)
206
312
  # * :line_number (string)
207
313
  # * :pd_expression (string)
208
314
  # * :object (object)
209
315
  # * :object_printer (proc)
316
+ # * :source_line_count (integer)
210
317
  #
211
318
  # NOTE: data for :object_printer is not a string, yet a proc that must
212
319
  # be called to output value. It is a proc as it automatically handles usage
@@ -284,9 +391,11 @@ module PutsDebuggerer
284
391
  def options
285
392
  {
286
393
  header: header,
394
+ wrapper: wrapper,
287
395
  footer: footer,
288
396
  printer: printer,
289
397
  print_engine: print_engine,
398
+ source_line_count: source_line_count,
290
399
  app_path: app_path,
291
400
  announcer: announcer,
292
401
  formatter: formatter,
@@ -363,44 +472,25 @@ module PutsDebuggerer
363
472
  !!@run_at
364
473
  end
365
474
 
366
- attr_reader :run_at_global_number
367
-
368
- def run_at_global_number=(value)
369
- @run_at_global_number = value
475
+ def determine_options(objects)
476
+ objects.delete_at(-1) if objects.size > 1 && objects.last.is_a?(Hash)
370
477
  end
371
478
 
372
- def init_run_at_global_number
373
- @run_at_global_number = 1
479
+ def determine_object(objects)
480
+ objects.compact.size > 1 ? objects : objects.first
374
481
  end
375
482
 
376
- def increment_run_at_global_number
377
- @run_at_global_number += 1
483
+ def determine_run_at(options)
484
+ ((options && options[:run_at]) || PutsDebuggerer.run_at)
378
485
  end
379
486
 
380
- def reset_run_at_global_number
381
- @run_at_global_number = nil
382
- end
383
-
384
- def run_at_number(object, run_at)
385
- PutsDebuggerer::OBJECT_RUN_AT[[object,run_at]]
386
- end
387
-
388
- def init_run_at_number(object, run_at)
389
- PutsDebuggerer::OBJECT_RUN_AT[[object,run_at]] = 1
390
- end
391
-
392
- def increment_run_at_number(object, run_at)
393
- PutsDebuggerer::OBJECT_RUN_AT[[object,run_at]] += 1
394
- end
395
-
396
- def reset_run_at_number(object, run_at)
397
- PutsDebuggerer::OBJECT_RUN_AT.delete([object, run_at])
398
- end
399
-
400
- def reset_run_at_numbers
401
- PutsDebuggerer::OBJECT_RUN_AT.clear
487
+ def determine_printer(options)
488
+ if options && options.has_key?(:printer)
489
+ options[:printer]
490
+ else
491
+ PutsDebuggerer.printer
492
+ end
402
493
  end
403
-
404
494
  end
405
495
  end
406
496
 
@@ -412,6 +502,7 @@ PutsDebuggerer.formatter = nil
412
502
  PutsDebuggerer.app_path = nil
413
503
  PutsDebuggerer.caller = nil
414
504
  PutsDebuggerer.run_at = nil
505
+ PutsDebuggerer.source_line_count = nil
415
506
 
416
507
  # Prints object with bonus info such as file name, line number and source
417
508
  # expression. Optionally prints out header and footer.
@@ -442,56 +533,56 @@ PutsDebuggerer.run_at = nil
442
533
  # > pd "Show me the source of the bug: #{bug}"
443
534
  # => "Show me the source of the bug: beattle"
444
535
  # [PD] /Users/User/finance_calculator_app/pd_test.rb:4 "What line number am I?"
445
- def pd(object, options=nil)
446
- run_at = ((options && options[:run_at]) || PutsDebuggerer.run_at)
447
-
448
- if __run_pd__(object, run_at)
536
+ def pd(*objects)
537
+ options = PutsDebuggerer.determine_options(objects) || {}
538
+ object = PutsDebuggerer.determine_object(objects)
539
+ run_at = PutsDebuggerer.determine_run_at(options)
540
+ printer = PutsDebuggerer.determine_printer(options)
541
+ pd_inspect = options.delete(:pd_inspect)
542
+ logger_formatter_decorated = PutsDebuggerer.printer.is_a?(Logger) && PutsDebuggerer.printer.formatter != PutsDebuggerer.logger_original_formatter
543
+ logging_layouts_decorated = PutsDebuggerer.printer.is_a?(Logging::Logger) && PutsDebuggerer.printer.appenders.map(&:layout) != (PutsDebuggerer.logging_original_layouts.values)
544
+
545
+ string = nil
546
+ if PutsDebuggerer::RunDeterminer.run_pd?(object, run_at)
449
547
  __with_pd_options__(options) do |print_engine_options|
450
- formatter_pd_data = __build_pd_data__(object, print_engine_options) #depth adds build method
548
+ run_number = PutsDebuggerer::RunDeterminer.run_number(object, run_at)
549
+ formatter_pd_data = __build_pd_data__(object, print_engine_options, PutsDebuggerer.source_line_count, run_number, pd_inspect, logger_formatter_decorated, logging_layouts_decorated) #depth adds build method
451
550
  stdout = $stdout
452
551
  $stdout = sio = StringIO.new
453
552
  PutsDebuggerer.formatter.call(formatter_pd_data)
454
553
  $stdout = stdout
554
+ string = sio.string
455
555
  if PutsDebuggerer.printer.is_a?(Proc)
456
- PutsDebuggerer.printer.call(sio.string)
457
- else
458
- send(PutsDebuggerer.send(:printer), sio.string)
556
+ PutsDebuggerer.printer.call(string)
557
+ elsif PutsDebuggerer.printer.is_a?(Logger)
558
+ logger_formatter = PutsDebuggerer.printer.formatter
559
+ begin
560
+ PutsDebuggerer.printer.formatter = PutsDebuggerer.logger_original_formatter
561
+ PutsDebuggerer.printer.debug(string)
562
+ ensure
563
+ PutsDebuggerer.printer.formatter = logger_formatter
564
+ end
565
+ elsif PutsDebuggerer.printer.is_a?(Logging::Logger)
566
+ logging_layouts = PutsDebuggerer.printer.appenders.reduce({}) do |hash, appender|
567
+ hash.merge(appender => appender.layout)
568
+ end
569
+ begin
570
+ PutsDebuggerer.logging_original_layouts.each do |appender, original_layout|
571
+ appender.layout = original_layout
572
+ end
573
+ PutsDebuggerer.printer.debug(string)
574
+ ensure
575
+ PutsDebuggerer.logging_original_layouts.each do |appender, original_layout|
576
+ appender.layout = logging_layouts[appender]
577
+ end
578
+ end
579
+ elsif PutsDebuggerer.printer != false
580
+ send(PutsDebuggerer.send(:printer), string)
459
581
  end
460
582
  end
461
583
  end
462
584
 
463
- object
464
- end
465
-
466
- def __run_pd__(object, run_at)
467
- run_pd = false
468
- if run_at.nil?
469
- run_pd = true
470
- else
471
- if PutsDebuggerer.run_at?
472
- if PutsDebuggerer.run_at_global_number.nil?
473
- PutsDebuggerer.init_run_at_global_number
474
- else
475
- PutsDebuggerer.increment_run_at_global_number
476
- end
477
- run_number = PutsDebuggerer.run_at_global_number
478
- else
479
- if PutsDebuggerer.run_at_number(object, run_at).nil?
480
- PutsDebuggerer.init_run_at_number(object, run_at)
481
- else
482
- PutsDebuggerer.increment_run_at_number(object, run_at)
483
- end
484
- run_number = PutsDebuggerer.run_at_number(object, run_at)
485
- end
486
- if run_at.is_a?(Integer)
487
- run_pd = true if run_at == run_number
488
- elsif run_at.is_a?(Array)
489
- run_pd = true if run_at.include?(run_number)
490
- elsif run_at.is_a?(Range)
491
- run_pd = true if run_at.cover?(run_number) || (run_at.end == -1 && run_number >= run_at.begin)
492
- end
493
- end
494
- run_pd
585
+ printer ? object : string
495
586
  end
496
587
 
497
588
  # Provides caller line number starting 1 level above caller of
@@ -505,7 +596,7 @@ end
505
596
  #
506
597
  # prints out `3`
507
598
  def __caller_line_number__(caller_depth=0)
508
- caller[caller_depth][PutsDebuggerer::STACK_TRACE_CALL_LINE_NUMBER_REGEX, 1].to_i
599
+ caller[caller_depth] && caller[caller_depth][PutsDebuggerer::STACK_TRACE_CALL_LINE_NUMBER_REGEX, 1].to_i
509
600
  end
510
601
 
511
602
  # Provides caller file starting 1 level above caller of
@@ -518,7 +609,7 @@ end
518
609
  #
519
610
  # prints out `lib/example.rb`
520
611
  def __caller_file__(caller_depth=0)
521
- caller[caller_depth][PutsDebuggerer::STACK_TRACE_CALL_SOURCE_FILE_REGEX, 1]
612
+ result = caller[caller_depth] && caller[caller_depth][PutsDebuggerer::STACK_TRACE_CALL_SOURCE_FILE_REGEX, 1]
522
613
  end
523
614
 
524
615
 
@@ -530,23 +621,14 @@ end
530
621
  # puts __caller_source_line__
531
622
  #
532
623
  # prints out `puts __caller_source_line__`
533
- def __caller_source_line__(caller_depth=0, source_file=nil, source_line_number=nil)
624
+ def __caller_source_line__(caller_depth=0, source_line_count=nil, source_file=nil, source_line_number=nil)
534
625
  source_line_number ||= __caller_line_number__(caller_depth+1)
535
626
  source_file ||= __caller_file__(caller_depth+1)
536
- source_line = nil
627
+ source_line = ''
537
628
  if source_file == '(irb)'
538
- source_line = conf.io.line(source_line_number)
629
+ source_line = conf.io.line(source_line_number) # TODO handle multi-lines in source_line_count
539
630
  else
540
- f = File.new(source_file)
541
- source_line = ''
542
- done = false
543
- f.each_line do |line|
544
- if !done && f.lineno == source_line_number
545
- source_line << line
546
- done = true if Ripper.sexp_raw(source_line) || source_line.include?('%>') #the last condition is for erb support (unofficial)
547
- source_line_number+=1
548
- end
549
- end
631
+ source_line = PutsDebuggerer::SourceFile.new(source_file).source(source_line_count, source_line_number)
550
632
  end
551
633
  source_line
552
634
  end
@@ -562,43 +644,42 @@ def __with_pd_options__(options=nil)
562
644
  PutsDebuggerer.options = permanent_options
563
645
  end
564
646
 
565
- def __build_pd_data__(object, print_engine_options=nil)
647
+ def __build_pd_data__(object, print_engine_options=nil, source_line_count=nil, run_number=nil, pd_inspect=false, logger_formatter_decorated=false, logging_layouts_decorated=false)
566
648
  depth = PutsDebuggerer::CALLER_DEPTH_ZERO
649
+ depth += 1 if pd_inspect
650
+ depth += 4 if pd_inspect && logger_formatter_decorated
651
+ depth += 8 if pd_inspect && logging_layouts_decorated
567
652
  pd_data = {
568
653
  announcer: PutsDebuggerer.announcer,
569
- file: __caller_file__(depth).sub(PutsDebuggerer.app_path.to_s, ''),
654
+ file: __caller_file__(depth)&.sub(PutsDebuggerer.app_path.to_s, ''),
570
655
  line_number: __caller_line_number__(depth),
571
- pd_expression: __caller_pd_expression__(depth),
656
+ pd_expression: __caller_pd_expression__(depth, source_line_count),
657
+ run_number: run_number,
572
658
  object: object,
573
- object_printer: lambda do
574
- if PutsDebuggerer.print_engine.is_a?(Proc)
575
- PutsDebuggerer.print_engine.call(object)
576
- else
577
- if print_engine_options.to_h.empty?
578
- send(PutsDebuggerer.print_engine, object)
579
- else
580
- send(PutsDebuggerer.print_engine, object, print_engine_options) rescue send(PutsDebuggerer.print_engine, object)
581
- end
582
- end
583
- end
659
+ object_printer: PutsDebuggerer::OBJECT_PRINTER_DEFAULT.call(object, print_engine_options, source_line_count, run_number)
584
660
  }
585
- if PutsDebuggerer.caller?
586
- start_depth = depth.to_i
587
- caller_depth = PutsDebuggerer.caller == -1 ? -1 : (start_depth + PutsDebuggerer.caller)
588
- pd_data[:caller] = caller[start_depth..caller_depth].to_a
661
+ pd_data[:caller] = __caller_caller__(depth)
662
+ ['header', 'wrapper', 'footer'].each do |boundary_option|
663
+ pd_data[boundary_option.to_sym] = PutsDebuggerer.send(boundary_option) if PutsDebuggerer.send("#{boundary_option}?")
589
664
  end
590
- pd_data[:header] = PutsDebuggerer.header if PutsDebuggerer.header?
591
- pd_data[:footer] = PutsDebuggerer.footer if PutsDebuggerer.footer?
592
665
  pd_data
593
666
  end
594
667
 
668
+ # Returns the caller stack trace of the caller of pd
669
+ def __caller_caller__(depth)
670
+ return unless PutsDebuggerer.caller?
671
+ start_depth = depth.to_i + 1
672
+ caller_depth = PutsDebuggerer.caller == -1 ? -1 : (start_depth + PutsDebuggerer.caller)
673
+ caller[start_depth..caller_depth].to_a
674
+ end
675
+
595
676
  def __format_pd_expression__(expression, object)
596
677
  "\n > #{expression}\n =>"
597
678
  end
598
679
 
599
- def __caller_pd_expression__(depth=0)
680
+ def __caller_pd_expression__(depth=0, source_line_count=nil)
600
681
  # Caller Source Line Depth 2 = 1 to pd method + 1 to caller
601
- source_line = __caller_source_line__(depth+1)
682
+ source_line = __caller_source_line__(depth+1, source_line_count)
602
683
  source_line = __extract_pd_expression__(source_line)
603
684
  source_line = source_line.gsub(/(^'|'$)/, '"') if source_line.start_with?("'") && source_line.end_with?("'")
604
685
  source_line = source_line.gsub(/(^\(|\)$)/, '') if source_line.start_with?("(") && source_line.end_with?(")")
@@ -613,5 +694,5 @@ end
613
694
  #
614
695
  # outputs `(x=1)`
615
696
  def __extract_pd_expression__(source_line)
616
- source_line.strip
697
+ source_line.to_s.strip
617
698
  end