puts_debuggerer 0.6.1 → 0.8.2

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.
Files changed (5) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +260 -42
  3. data/VERSION +1 -0
  4. data/lib/puts_debuggerer.rb +218 -37
  5. metadata +50 -28
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 23082ac8b052016747f52fc3ed37c17ee1f9c8d1
4
- data.tar.gz: 8dd8dd68fabe0aaef0c6ba78912688cfa2160897
2
+ SHA256:
3
+ metadata.gz: 8b80118305f3b8201241cb75a16fab616e1db9789daf829c5b4ea68ad7a6d94d
4
+ data.tar.gz: dd345085a3bcbf718cdb49983b3c2d1838b1914b231e6fc033ff30ea992fac32
5
5
  SHA512:
6
- metadata.gz: 2b798fcdf87f121abda0664bbf190fb2de2ba258eb431dfd7a287061aaa03dc408e7101c5d96ceaa725a31294324eb68cb36fdeb44165b13abd434f296e1b12d
7
- data.tar.gz: c884b97e883fb7b5e85c4e0a094dc87a463df2a4a7efef72b34fd7110d4358bbb5ff5ed7402895c79e4a6f3f6bdf47f4a98c78364779723508d4a521f8ee35a3
6
+ metadata.gz: 1ac9056936792d4f8c46e4ae4114b0911a6442ef5b6ee5a6a1aebd6e405c3abc37466d207f19e94c6eaf9bd58374cd30ab2f66581777b9e37b2f572953c9261a
7
+ data.tar.gz: 7e0bbb0fcb9c502a252227b74a68a91d39f8ecbbf5cf85a18c4f561dae0a71baa5d258680835c573d2c5f6555e142f1b911f6a3c94302022cbd3a3ac4caeda01
data/README.md CHANGED
@@ -1,22 +1,127 @@
1
- # puts_debuggerer v0.6.0
1
+ # Puts Debuggerer (debugger-less debugging FTW)
2
2
  [![Gem Version](https://badge.fury.io/rb/puts_debuggerer.svg)](http://badge.fury.io/rb/puts_debuggerer)
3
3
  [![Build Status](https://travis-ci.org/AndyObtiva/puts_debuggerer.svg?branch=master)](https://travis-ci.org/AndyObtiva/puts_debuggerer)
4
4
  [![Coverage Status](https://coveralls.io/repos/github/AndyObtiva/puts_debuggerer/badge.svg?branch=master)](https://coveralls.io/github/AndyObtiva/puts_debuggerer?branch=master)
5
5
 
6
- Yes, many of us avoid debuggers like the plague and clamp on to our puts
7
- statements like an umbrella in a stormy day.
8
- Why not make it official and have puts debugging become its own perfectly
9
- legitimate thing?!!
6
+ Debuggers are great! They help us troubleshoot complicated programming problems by inspecting values produced by code, line by line. They are invaluable when trying to understand what is going on in a large application composed of thousands or millions of lines of code.
10
7
 
11
- Enter puts_debuggerer. A guilt-free puts debugger Ruby gem FTW!
8
+ In day-to-day test-driven development and simple debugging though, a puts statement can be a lot quicker in revealing what is going on than halting execution completely just to inspect a single value or a few. This is certainly true when writing the simplest possible code that could possibly work, and running a test every few seconds or minutes. Problem is you need to locate puts statements in large output logs, know which methods were invoked, find out what variable names are being printed, and see nicely formatted output. Enter puts_debuggerer. A guilt-free puts debugging Ruby gem FTW that prints file names, line numbers, code statements, and formats output nicely courtesy of awesome_print.
12
9
 
13
- In other words, puts_debuggerer is a Ruby library that provides improved puts debugging, automatically displaying bonus useful information such as source line numbers and source code, among many other goodies (mentioned in the README.)
10
+ Basic Example:
14
11
 
15
- Partially inspired (only partially ;) by this blog post:
12
+ ```ruby
13
+ # /Users/User/trivia_app.rb # line 1
14
+ require 'puts_debuggerer' # line 2
15
+ bug_or_band = 'beattle' # line 3
16
+ pd bug_or_band # line 4
17
+ ```
18
+
19
+ Output:
20
+
21
+ ```bash
22
+ [PD] trivia_app.rb:4
23
+ > pd bug_or_band # line 4
24
+ => "beattle"
25
+ ```
26
+
27
+ ## Background
28
+
29
+ For initial background, please read this blog post by Aaron Patterson (part of the inspiration for this gem):
16
30
  https://tenderlovemaking.com/2016/02/05/i-am-a-puts-debuggerer.html
17
- (Credit to Tenderlove.)
18
31
 
19
- Love PD?! Why not promote with [merchandise](https://www.zazzle.com/i+heart+pd+gifts)?
32
+ It can be quite frustrating to lose puts statements in a large output or log file. One way to help find them is add a header (e.g. `puts "The Order Total"`) or an announcer (e.g. `puts '*'*80`) before every puts statement. Unfortunately, that leads to repetitive wasteful effort that adds up quickly over many work sessions and interrupts thinking flow while solving problems.
33
+
34
+ puts_debuggerer automates that work via the short and simple `pd` command, automatically printing meaningful headers for output and accelerating problem solving work due to ease of typing.
35
+
36
+ Example without pd:
37
+
38
+ ```ruby
39
+ puts order_total
40
+ ```
41
+
42
+ Output:
43
+ ```
44
+ 195.50
45
+ ```
46
+
47
+ Which gets lost in a logging stream such as:
48
+
49
+ ```
50
+ (2.7ms) CREATE TABLE "ar_internal_metadata" ("key" character varying PRIMARY KEY, "value" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
51
+ ActiveRecord::InternalMetadata Load (0.4ms) SELECT "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = $1 LIMIT $2 [["key", :environment], ["LIMIT", 1]]
52
+ (0.2ms) BEGIN
53
+ SQL (0.3ms) INSERT INTO "ar_internal_metadata" ("key", "value", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "key" [["key", "environment"], ["value", "development"], ["created_at", 2017-08-24 22:56:52 UTC], ["updated_at", 2017-08-24 22:56:52 UTC]]
54
+ (0.3ms) COMMIT
55
+ 195.50
56
+ ActiveRecord::InternalMetadata Load (0.3ms) SELECT "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = $1 LIMIT $2 [["key", :environment], ["LIMIT", 1]]
57
+ (0.2ms) BEGIN
58
+ (0.2ms) COMMIT
59
+ ```
60
+
61
+ Problem can be mitigated by adding a few more puts statements:
62
+
63
+ ```ruby
64
+ puts "*"*40
65
+ puts "order_total"
66
+ puts order_total
67
+ ```
68
+
69
+ But those add up pretty quickly when inspecting multiple variables:
70
+
71
+ ```ruby
72
+ puts "*"*40
73
+ puts "order_total"
74
+ puts order_total
75
+ puts "*"*40
76
+ puts "order_summary"
77
+ puts order_summary
78
+ puts "*"*40
79
+ puts "order_details"
80
+ puts order_details
81
+ ```
82
+
83
+ Here is a simple example using `pd` instead:
84
+
85
+ ```ruby
86
+ pd order_total
87
+ ```
88
+
89
+ Output:
90
+
91
+ ```
92
+ [PD] /Users/User/ordering/order.rb:39
93
+ > pd order_total
94
+ => 195.50
95
+ ```
96
+
97
+ This is not only easy to locate in a logging stream such as the one below, but also includes the `order_total` variable for easy findability among other pd statements.
98
+
99
+ ```
100
+ (2.7ms) CREATE TABLE "ar_internal_metadata" ("key" character varying PRIMARY KEY, "value" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
101
+ ActiveRecord::InternalMetadata Load (0.4ms) SELECT "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = $1 LIMIT $2 [["key", :environment], ["LIMIT", 1]]
102
+ [PD] /Users/User/ordering/order.rb:39
103
+ > pd order_total
104
+ => 195.50
105
+ (0.2ms) BEGIN
106
+ SQL (0.3ms) INSERT INTO "ar_internal_metadata" ("key", "value", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "key" [["key", "environment"], ["value", "development"], ["created_at", 2017-08-24 22:56:52 UTC], ["updated_at", 2017-08-24 22:56:52 UTC]]
107
+ (0.3ms) COMMIT
108
+ [PD] /Users/User/ordering/order.rb:72
109
+ > pd order_subtotal
110
+ => 181.00
111
+ ActiveRecord::InternalMetadata Load (0.3ms) SELECT "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = $1 LIMIT $2 [["key", :environment], ["LIMIT", 1]]
112
+ (0.2ms) BEGIN
113
+ (0.2ms) COMMIT
114
+ ```
115
+
116
+ And it is easy to search for using the `[PD]` announcer (customizable).
117
+
118
+ When inspecting multiple variables, debugging code is still a snap:
119
+
120
+ ```ruby
121
+ pd order_total
122
+ pd order_summary
123
+ pd order_details
124
+ ```
20
125
 
21
126
  ## Instructions
22
127
 
@@ -25,7 +130,7 @@ Love PD?! Why not promote with [merchandise](https://www.zazzle.com/i+heart+pd+g
25
130
  Add the following to bundler's `Gemfile`.
26
131
 
27
132
  ```ruby
28
- gem 'puts_debuggerer', '~> 0.6.0'
133
+ gem 'puts_debuggerer', '~> 0.8.2'
29
134
  ```
30
135
 
31
136
  This is the recommended way for [Rails](rubyonrails.org) apps. Optionally, you may create an initializer under `config/initializers` named `puts_debuggerer_options.rb` to enable further customizations as per the [Options](#options) section below.
@@ -35,20 +140,29 @@ This is the recommended way for [Rails](rubyonrails.org) apps. Optionally, you m
35
140
  Or manually install and require library.
36
141
 
37
142
  ```bash
38
- gem install puts_debuggerer -v0.6.0
143
+ gem install puts_debuggerer -v0.8.2
39
144
  ```
40
145
 
41
146
  ```ruby
42
147
  require 'puts_debuggerer'
43
148
  ```
44
149
 
45
- ### Usage
150
+ ### Awesome Print
46
151
 
47
- Simply invoke global `pd` method anywhere in your code passing an object or an expression argument.
152
+ puts_debuggerer comes with [awesome_print](https://github.com/awesome-print/awesome_print).
48
153
 
49
- It will then provide helpful debugging information by printing the source file, line number, and source code in addition to output (works even in IRB).
154
+ You may disable when needed by not requiring in Ruby or by adding an explicit reference to awesome_print with `require: false` in bundler:
50
155
 
51
- Example Code:
156
+ ```ruby
157
+ gem "awesome_print", require: false
158
+ gem "puts_debugger"
159
+ ```
160
+
161
+ ### Usage
162
+
163
+ First, add `pd` method anywhere in your code to display details about an object or expression (if you're used to awesome_print, you're in luck! puts_debuggerer includes awesome_print as the default print engine for output).
164
+
165
+ Example:
52
166
 
53
167
  ```ruby
54
168
  # /Users/User/finance_calculator_app/pd_test.rb # line 1
@@ -57,7 +171,7 @@ pd "Show me the source of the bug: #{bug}" # line 3
57
171
  pd "Show me the result of the calculation: #{(12.0/3.0)}" # line 4
58
172
  ```
59
173
 
60
- Example Printout:
174
+ Output:
61
175
 
62
176
  ```bash
63
177
  [PD] /Users/User/finance_calculator_app/pd_test.rb:3
@@ -68,17 +182,18 @@ Example Printout:
68
182
  => "Show me the result of the calculation: 4.0"
69
183
  ```
70
184
 
71
- Quickly locate printed lines using Find feature (e.g. CTRL+F) by looking for:
185
+ In addition to the main object/expression output, you get to see the source file name, line number, and source code to help you debug and troubleshoot problems quicker (it even works in IRB).
186
+
187
+ Second, quickly locate printed lines using the Find feature (e.g. CTRL+F) by looking for:
72
188
  * [PD]
73
189
  * file:line_number
74
190
  * known ruby expression.
75
191
 
76
- This gives you the added benefit of easily removing your `pd` statements later
77
- on once done debugging.
192
+ Third, easily remove your ` pd ` statements via the source code Find feature once done debugging.
78
193
 
79
194
  Note that `pd` returns the passed in object or expression argument unchanged, permitting debugging with shorter syntax than tap, and supporting chaining of extra method invocations afterward.
80
195
 
81
- Example Code:
196
+ Example:
82
197
 
83
198
  ```ruby
84
199
  # /Users/User/greeting_app/pd_test.rb # line 1
@@ -86,7 +201,7 @@ name = 'Robert' # line 2
86
201
  greeting = "Hello #{pd(name)}" # line 3
87
202
  ```
88
203
 
89
- Example Printout:
204
+ Output:
90
205
 
91
206
  ```bash
92
207
  [PD] /Users/User/greeting_app/pd_test.rb:3
@@ -216,20 +331,56 @@ Prints out:
216
331
  ********************************************************************************
217
332
  ```
218
333
 
334
+ #### `PutsDebuggerer.printer`
335
+ (default = `:puts`)
336
+
337
+ Printer is a global method symbol or lambda expression to use in printing to the user.
338
+ Examples of global methods are `:puts` and `:print`.
339
+ An example of a lambda expression is `lambda {|output| Rails.logger.info(output)}`
340
+
341
+ Defaults to `:puts`
342
+ In Rails, it defaults to:
343
+ ```ruby
344
+ lambda do |output|
345
+ puts output if Rails.env.test?
346
+ Rails.logger.debug(output)
347
+ end
348
+ ```
349
+
350
+ Example:
351
+
352
+ ```ruby
353
+ # File Name: /Users/User/example.rb
354
+ PutsDebuggerer.printer = lambda {|output| Rails.logger.error(output)}
355
+ str = "Hello"
356
+ pd str
357
+ ```
358
+
359
+ Prints out in the Rails app log as error lines:
360
+
361
+ ```bash
362
+ [PD] /Users/User/example.rb:5
363
+ > pd str
364
+ => Hello
365
+ ```
366
+
219
367
  #### `PutsDebuggerer.print_engine`
220
- (default = `:p`)
368
+ (default = `:ap`)
221
369
 
222
- Print engine is a global method symbol or lambda expression to use in object printout. Examples of global methods are `:p`, `:ap`, and `:pp`. An example of a lambda expression is `lambda {|o| Rails.logger.info(o)}`
370
+ Print engine is similar to `printer`, except it is focused on the scope of formatting
371
+ the data object being printed (excluding metadata such as file name, line number,
372
+ and expression, which are handled by the `printer`).
373
+ As such, it is also a global method symbol or lambda expression.
374
+ Examples of global methods are `:p`, `:ap`, and `:pp`.
375
+ An example of a lambda expression is `lambda {|object| puts object.to_a.join(" | ")}`
223
376
 
224
- Defaults to Ruby's built-in `p` method identified by the symbol `:p`.
225
- If it finds [awesome_print](https://github.com/awesome-print/awesome_print) loaded, it defaults to `ap` as `:ap` instead. Also, if it finds Rails loaded without ap, it relies on `lambda {|o| Rails.logger.debug(o)}` as the print engine. Otherwise if both Rails and [awesome_print](https://github.com/awesome-print/awesome_print) are loaded, then it relies on `lambda {|o| Rails.logger.ap(o)}` instead
377
+ Defaults to [awesome_print](https://github.com/awesome-print/awesome_print).
226
378
 
227
379
  Example:
228
380
 
229
381
  ```ruby
230
382
  # File Name: /Users/User/example.rb
231
- require 'awesome_print'
232
- PutsDebuggerer.print_engine = :ap
383
+ PutsDebuggerer.print_engine = :p
233
384
  array = [1, [2, 3]]
234
385
  pd array
235
386
  ```
@@ -239,13 +390,7 @@ Prints out:
239
390
  ```bash
240
391
  [PD] /Users/User/example.rb:5
241
392
  > pd array
242
- => [
243
- [0] 1,
244
- [1] [
245
- [0] 2,
246
- [1] 3
247
- ]
248
- ]
393
+ => [1, [2, 3]]
249
394
  ```
250
395
 
251
396
  #### `PutsDebuggerer.announcer`
@@ -348,20 +493,80 @@ Prints out:
348
493
  /Users/User/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/irb/context.rb:381:in \`evaluate\'
349
494
  ```
350
495
 
351
- ### Bonus
496
+ #### `PutsDebuggerer.run_at`
497
+ (default = nil)
498
+
499
+ Set condition for when to run as specified by an index, array, or range.
500
+ * Default value is `nil` meaning always
501
+ * Value as an Integer index (1-based) specifies at which run to print once
502
+ * Value as an Array of indices specifies at which runs to print multiple times
503
+ * Value as a range specifies at which runs to print multiple times,
504
+ indefinitely if it ends with ..-1 or ...-1
352
505
 
353
- puts_debuggerer comes with a number of bonus goodies.
506
+ Can be set globally via `PutsDebuggerer.run_at` or piecemeal via `pd object, run_at: run_at_value`
354
507
 
355
- It comes with [awesome_print](https://github.com/awesome-print/awesome_print).
508
+ Global usage should be good enough for most cases. When there is a need to track
509
+ a single expression among several, you may add the option piecemeal, but it expects
510
+ the same exact `object` passed to `pd` for counting.
356
511
 
357
- You may disable by not requiring in Ruby or by adding an explicit reference to awesome_print with `require: false` in bundler:
512
+ Examples (global):
358
513
 
359
514
  ```ruby
360
- gem "awesome_print", require: false
361
- gem "puts_debugger"
515
+ PutsDebuggerer.run_at = 1
516
+ pd (x=1) # prints standard PD output
517
+ pd (x=1) # prints nothing
518
+
519
+ PutsDebuggerer.run_at = 2
520
+ pd (x=1) # prints nothing
521
+ pd (x=1) # prints standard PD output
522
+
523
+ PutsDebuggerer.run_at = [1, 3]
524
+ pd (x=1) # prints standard PD output
525
+ pd (x=1) # prints nothing
526
+ pd (x=1) # prints standard PD output
527
+ pd (x=1) # prints nothing
528
+
529
+ PutsDebuggerer.run_at = 3..5
530
+ pd (x=1) # prints nothing
531
+ pd (x=1) # prints nothing
532
+ pd (x=1) # prints standard PD output
533
+ pd (x=1) # prints standard PD output
534
+ pd (x=1) # prints standard PD output
535
+ pd (x=1) # prints nothing
536
+ pd (x=1) # prints nothing
537
+
538
+ PutsDebuggerer.run_at = 3...6
539
+ pd (x=1) # prints nothing
540
+ pd (x=1) # prints nothing
541
+ pd (x=1) # prints standard PD output
542
+ pd (x=1) # prints standard PD output
543
+ pd (x=1) # prints standard PD output
544
+ pd (x=1) # prints nothing
545
+
546
+ PutsDebuggerer.run_at = 3..-1
547
+ pd (x=1) # prints nothing
548
+ pd (x=1) # prints nothing
549
+ pd (x=1) # prints standard PD output
550
+ pd (x=1) # ... continue printing indefinitely on all subsequent runs
551
+
552
+ PutsDebuggerer.run_at = 3...-1
553
+ pd (x=1) # prints nothing
554
+ pd (x=1) # prints nothing
555
+ pd (x=1) # prints standard PD output
556
+ pd (x=1) # ... continue printing indefinitely on all subsequent runs
362
557
  ```
363
558
 
364
- Additionally, puts_debuggerer comes with the following bonus utility methods:
559
+ You may reset the run_at number counter via:
560
+ `PutsDebuggerer.reset_run_at_global_number` for global usage.
561
+
562
+ And:
563
+ `PutsDebuggerer.reset_run_at_number` or
564
+ `PutsDebuggerer.reset_run_at_numbers`
565
+ for piecemeal usage.
566
+
567
+ ### Bonus API
568
+
569
+ puts_debuggerer comes with the following bonus API methods:
365
570
 
366
571
  #### `__caller_line_number__(caller_depth=0)`
367
572
 
@@ -405,6 +610,12 @@ Prints out `puts __caller_source_line__`
405
610
 
406
611
  ## Release Notes
407
612
 
613
+ * v0.8.2: require 'stringio' for projects that don't require automatically via other gems
614
+ * v0.8.1: `printer` option support for Rails test environment
615
+ * v0.8.0: `printer` option support
616
+ * v0.7.1: default print engine to :ap (AwesomePrint)
617
+ * v0.7.0: `run_at` option, global and piecemeal.
618
+ * v0.6.1: updated README and broke apart specs
408
619
  * v0.6.0: unofficial erb support, returning evaluated object/expression, removed static syntax support (replaced with header support)
409
620
  * v0.5.1: support for print engine lambdas and smart defaults for leveraging Rails and AwesomePrint debuggers in Rails
410
621
  * v0.5.0: custom formatter, caller backtrace, per-puts piecemeal options, and multi-line support
@@ -413,6 +624,13 @@ Prints out `puts __caller_source_line__`
413
624
  * v0.2.0: App path exclusion support, Rails root support, improved format
414
625
  * v0.1.0: File/line/expression print out
415
626
 
627
+ ## TODO
628
+
629
+ * fix issue with printing in rspec inside a Rails project without having to do extra configuration
630
+ * fix issue with erb support
631
+ * display run_at run number in printout
632
+ * implement fallback in irb for when line number cannot be discovered (issue happens in pry, perhaps this just means support pry)
633
+
416
634
  ## Contributing
417
635
 
418
636
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.8.2
@@ -1,10 +1,18 @@
1
1
  require 'ripper'
2
+ require 'awesome_print'
3
+ require 'stringio'
2
4
 
3
5
  module PutsDebuggerer
4
6
  HEADER_DEFAULT = '*'*80
5
7
  FOOTER_DEFAULT = '*'*80
6
- PRINT_ENGINE_DEFAULT = :p
7
- PRINT_ENGINE_MESSAGE_INVALID = 'print_engine must be a valid global method symbol (e.g. :p or :puts) or lambda/proc'
8
+ PRINTER_DEFAULT = :puts
9
+ PRINTER_RAILS = lambda do |output|
10
+ puts output if Rails.env.test?
11
+ Rails.logger.debug(output)
12
+ end
13
+ PRINT_ENGINE_DEFAULT = :ap
14
+ PRINTER_MESSAGE_INVALID = 'printer must be a valid global method symbol (e.g. :puts) or lambda/proc receiving a text arg'
15
+ 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'
8
16
  ANNOUNCER_DEFAULT = '[PD]'
9
17
  FORMATTER_DEFAULT = -> (data) {
10
18
  puts data[:header] if data[:header]
@@ -14,6 +22,9 @@ module PutsDebuggerer
14
22
  puts data[:footer] if data[:footer]
15
23
  }
16
24
  CALLER_DEPTH_ZERO = 4 #depth includes pd + with_options method + nested block + build_pd_data method
25
+ OBJECT_RUN_AT = {}
26
+ STACK_TRACE_CALL_LINE_NUMBER_REGEX = /\:(\d+)\:in /
27
+ STACK_TRACE_CALL_SOURCE_FILE_REGEX = /[ ]*([^:]+)\:\d+\:in /
17
28
 
18
29
  class << self
19
30
  # Application root path to exclude when printing out file path
@@ -101,17 +112,55 @@ module PutsDebuggerer
101
112
  !!@footer
102
113
  end
103
114
 
104
- # Print engine to use in object printout (e.g. `p`, `ap`, `pp`).
105
- # It is represented by the print engine's global method name as a symbol
106
- # (e.g. `:ap` for awesome_print).
107
- # Defaults to Ruby's built-in `p` method identified by the symbol `:p`.
108
- # If it finds awesome_print loaded, it defaults to `ap` as `:ap` instead.
115
+ # Printer is a global method symbol or lambda expression to use in printing to the user.
116
+ # Examples of global methods are `:puts` and `:print`.
117
+ # An example of a lambda expression is `lambda {|output| Rails.logger.ap(output)}`
118
+ #
119
+ # Defaults to `:puts`
120
+ # In Rails, it defaults to: `lambda {|output| Rails.logger.ap(output)}`
121
+ #
122
+ # Example:
123
+ #
124
+ # # File Name: /Users/User/example.rb
125
+ # PutsDebuggerer.printer = lambda {|output| Rails.logger.error(output)}
126
+ # str = "Hello"
127
+ # pd str
128
+ #
129
+ # Prints out in the Rails app log as error lines:
130
+ #
131
+ # [PD] /Users/User/example.rb:5
132
+ # > pd str
133
+ # => Hello
134
+ attr_reader :printer
135
+
136
+ def printer=(printer)
137
+ if printer.nil?
138
+ if Object.const_defined?(:Rails)
139
+ @printer = PRINTER_RAILS
140
+ else
141
+ @printer = PRINTER_DEFAULT
142
+ end
143
+ elsif printer.is_a?(Proc)
144
+ @printer = printer
145
+ else
146
+ @printer = method(printer).name rescue raise(PRINTER_MESSAGE_INVALID)
147
+ end
148
+ end
149
+
150
+ # Print engine is similar to `printer`, except it is focused on the scope of formatting
151
+ # the data object being printed (excluding metadata such as file name, line number,
152
+ # and expression, which are handled by the `printer`).
153
+ # As such, it is also a global method symbol or lambda expression.
154
+ # Examples of global methods are `:p`, `:ap`, and `:pp`.
155
+ # An example of a lambda expression is `lambda {|object| puts object.to_a.join(" | ")}`
156
+ #
157
+ # Defaults to [awesome_print](https://github.com/awesome-print/awesome_print).
109
158
  #
110
159
  # Example:
111
160
  #
112
161
  # # File Name: /Users/User/example.rb
113
162
  # require 'awesome_print'
114
- # PutsDebuggerer.print_engine = :ap
163
+ # PutsDebuggerer.print_engine = :p
115
164
  # array = [1, [2, 3]]
116
165
  # pd array
117
166
  #
@@ -119,28 +168,15 @@ module PutsDebuggerer
119
168
  #
120
169
  # [PD] /Users/User/example.rb:5
121
170
  # > pd array
122
- # => [
123
- # [0] 1,
124
- # [1] [
125
- # [0] 2,
126
- # [1] 3
127
- # ]
171
+ # => [1, [2, 3]]
128
172
  # ]
129
173
  attr_reader :print_engine
130
174
 
131
175
  def print_engine=(engine)
132
176
  if engine.nil?
133
- if Object.const_defined?(:Rails)
134
- if Object.respond_to?(:ap, 'Hello')
135
- @print_engine = lambda {|object| Rails.logger.ap(object)}
136
- else
137
- @print_engine = lambda {|object| Rails.logger.debug(object)}
138
- end
139
- else
140
- @print_engine = method(:ap).name rescue PRINT_ENGINE_DEFAULT
141
- end
177
+ @print_engine = PRINT_ENGINE_DEFAULT
142
178
  elsif engine.is_a?(Proc)
143
- @print_engine = engine #TODO check that it takes one parameter or else fail fast
179
+ @print_engine = engine
144
180
  else
145
181
  @print_engine = method(engine).name rescue raise(PRINT_ENGINE_MESSAGE_INVALID)
146
182
  end
@@ -254,11 +290,13 @@ module PutsDebuggerer
254
290
  {
255
291
  header: header,
256
292
  footer: footer,
293
+ printer: printer,
257
294
  print_engine: print_engine,
258
295
  app_path: app_path,
259
296
  announcer: announcer,
260
297
  formatter: formatter,
261
- caller: caller
298
+ caller: caller,
299
+ run_at: run_at
262
300
  }
263
301
  end
264
302
 
@@ -268,14 +306,117 @@ module PutsDebuggerer
268
306
  send("#{option}=", value)
269
307
  end
270
308
  end
309
+
310
+ # When to run as specified by an index, array, or range.
311
+ # * Default value is `nil` meaning always
312
+ # * Value as an Integer index (1-based) specifies at which run to print once
313
+ # * Value as an Array of indices specifies at which runs to print multiple times
314
+ # * Value as a range specifies at which runs to print multiple times,
315
+ # indefinitely if it ends with ..-1
316
+ #
317
+ # Example:
318
+ #
319
+ # PutsDebuggerer.run_at = 1
320
+ # pd (x=1) # prints standard PD output
321
+ # pd (x=1) # prints nothing
322
+ #
323
+ # PutsDebuggerer.run_at = 2
324
+ # pd (x=1) # prints nothing
325
+ # pd (x=1) # prints standard PD output
326
+ #
327
+ # PutsDebuggerer.run_at = [1, 3]
328
+ # pd (x=1) # prints standard PD output
329
+ # pd (x=1) # prints nothing
330
+ # pd (x=1) # prints standard PD output
331
+ # pd (x=1) # prints nothing
332
+ #
333
+ # PutsDebuggerer.run_at = 3..5
334
+ # pd (x=1) # prints nothing
335
+ # pd (x=1) # prints nothing
336
+ # pd (x=1) # prints standard PD output
337
+ # pd (x=1) # prints standard PD output
338
+ # pd (x=1) # prints standard PD output
339
+ # pd (x=1) # prints nothing
340
+ # pd (x=1) # prints nothing
341
+ #
342
+ # PutsDebuggerer.run_at = 3...6
343
+ # pd (x=1) # prints nothing
344
+ # pd (x=1) # prints nothing
345
+ # pd (x=1) # prints standard PD output
346
+ # pd (x=1) # prints standard PD output
347
+ # pd (x=1) # prints standard PD output
348
+ # pd (x=1) # prints nothing
349
+ #
350
+ # PutsDebuggerer.run_at = 3..-1
351
+ # pd (x=1) # prints nothing
352
+ # pd (x=1) # prints nothing
353
+ # pd (x=1) # prints standard PD output
354
+ # pd (x=1) ... continue printing indefinitely on all subsequent runs
355
+ #
356
+ # PutsDebuggerer.run_at = 3...-1
357
+ # pd (x=1) # prints nothing
358
+ # pd (x=1) # prints nothing
359
+ # pd (x=1) # prints standard PD output
360
+ # pd (x=1) ... continue printing indefinitely on all subsequent runs
361
+ attr_reader :run_at
362
+
363
+ def run_at=(value)
364
+ @run_at = value
365
+ end
366
+
367
+ def run_at?
368
+ !!@run_at
369
+ end
370
+
371
+ attr_reader :run_at_global_number
372
+
373
+ def run_at_global_number=(value)
374
+ @run_at_global_number = value
375
+ end
376
+
377
+ def init_run_at_global_number
378
+ @run_at_global_number = 1
379
+ end
380
+
381
+ def increment_run_at_global_number
382
+ @run_at_global_number += 1
383
+ end
384
+
385
+ def reset_run_at_global_number
386
+ @run_at_global_number = nil
387
+ end
388
+
389
+ def run_at_number(object, run_at)
390
+ PutsDebuggerer::OBJECT_RUN_AT[[object,run_at]]
391
+ end
392
+
393
+ def init_run_at_number(object, run_at)
394
+ PutsDebuggerer::OBJECT_RUN_AT[[object,run_at]] = 1
395
+ end
396
+
397
+ def increment_run_at_number(object, run_at)
398
+ PutsDebuggerer::OBJECT_RUN_AT[[object,run_at]] += 1
399
+ end
400
+
401
+ def reset_run_at_number(object, run_at)
402
+ PutsDebuggerer::OBJECT_RUN_AT.delete([object, run_at])
403
+ end
404
+
405
+ def reset_run_at_numbers
406
+ PutsDebuggerer::OBJECT_RUN_AT.clear
407
+ end
408
+
271
409
  end
272
410
  end
273
411
 
274
- PutsDebuggerer.print_engine = PutsDebuggerer::PRINT_ENGINE_DEFAULT
275
- PutsDebuggerer.announcer = PutsDebuggerer::ANNOUNCER_DEFAULT
276
- PutsDebuggerer.formatter = PutsDebuggerer::FORMATTER_DEFAULT
277
- PutsDebuggerer.app_path = nil #TODO also have it set Rails root on first PD
412
+ # setting values to nil defaults them properly
413
+ PutsDebuggerer.printer = nil
414
+ PutsDebuggerer.print_engine = nil
415
+ PutsDebuggerer.announcer = nil
416
+ PutsDebuggerer.formatter = nil
417
+ PutsDebuggerer.app_path = nil
278
418
  PutsDebuggerer.caller = nil
419
+ PutsDebuggerer.run_at = nil
279
420
 
280
421
  # Prints object with bonus info such as file name, line number and source
281
422
  # expression. Optionally prints out header and footer.
@@ -307,16 +448,56 @@ PutsDebuggerer.caller = nil
307
448
  # => "Show me the source of the bug: beattle"
308
449
  # [PD] /Users/User/finance_calculator_app/pd_test.rb:4 "What line number am I?"
309
450
  def pd(object, options=nil)
310
- __with_pd_options__(options) do |print_engine_options|
311
- formatter_pd_data = __build_pd_data__(object, print_engine_options) #depth adds build method
312
- PutsDebuggerer.formatter.call(formatter_pd_data)
451
+ run_at = ((options && options[:run_at]) || PutsDebuggerer.run_at)
452
+
453
+ if __run_pd__(object, run_at)
454
+ __with_pd_options__(options) do |print_engine_options|
455
+ formatter_pd_data = __build_pd_data__(object, print_engine_options) #depth adds build method
456
+ stdout = $stdout
457
+ $stdout = sio = StringIO.new
458
+ PutsDebuggerer.formatter.call(formatter_pd_data)
459
+ $stdout = stdout
460
+ if PutsDebuggerer.printer.is_a?(Proc)
461
+ PutsDebuggerer.printer.call(sio.string)
462
+ else
463
+ send(PutsDebuggerer.send(:printer), sio.string)
464
+ end
465
+ end
313
466
  end
467
+
314
468
  object
315
469
  end
316
470
 
317
-
318
- STACK_TRACE_CALL_LINE_NUMBER_REGEX = /\:(\d+)\:in /
319
- STACK_TRACE_CALL_SOURCE_FILE_REGEX = /[ ]*([^:]+)\:\d+\:in /
471
+ def __run_pd__(object, run_at)
472
+ run_pd = false
473
+ if run_at.nil?
474
+ run_pd = true
475
+ else
476
+ if PutsDebuggerer.run_at?
477
+ if PutsDebuggerer.run_at_global_number.nil?
478
+ PutsDebuggerer.init_run_at_global_number
479
+ else
480
+ PutsDebuggerer.increment_run_at_global_number
481
+ end
482
+ run_number = PutsDebuggerer.run_at_global_number
483
+ else
484
+ if PutsDebuggerer.run_at_number(object, run_at).nil?
485
+ PutsDebuggerer.init_run_at_number(object, run_at)
486
+ else
487
+ PutsDebuggerer.increment_run_at_number(object, run_at)
488
+ end
489
+ run_number = PutsDebuggerer.run_at_number(object, run_at)
490
+ end
491
+ if run_at.is_a?(Integer)
492
+ run_pd = true if run_at == run_number
493
+ elsif run_at.is_a?(Array)
494
+ run_pd = true if run_at.include?(run_number)
495
+ elsif run_at.is_a?(Range)
496
+ run_pd = true if run_at.cover?(run_number) || (run_at.end == -1 && run_number >= run_at.begin)
497
+ end
498
+ end
499
+ run_pd
500
+ end
320
501
 
321
502
  # Provides caller line number starting 1 level above caller of
322
503
  # this method.
@@ -329,7 +510,7 @@ STACK_TRACE_CALL_SOURCE_FILE_REGEX = /[ ]*([^:]+)\:\d+\:in /
329
510
  #
330
511
  # prints out `3`
331
512
  def __caller_line_number__(caller_depth=0)
332
- caller[caller_depth][STACK_TRACE_CALL_LINE_NUMBER_REGEX, 1].to_i
513
+ caller[caller_depth][PutsDebuggerer::STACK_TRACE_CALL_LINE_NUMBER_REGEX, 1].to_i
333
514
  end
334
515
 
335
516
  # Provides caller file starting 1 level above caller of
@@ -342,7 +523,7 @@ end
342
523
  #
343
524
  # prints out `lib/example.rb`
344
525
  def __caller_file__(caller_depth=0)
345
- caller[caller_depth][STACK_TRACE_CALL_SOURCE_FILE_REGEX, 1]
526
+ caller[caller_depth][PutsDebuggerer::STACK_TRACE_CALL_SOURCE_FILE_REGEX, 1]
346
527
  end
347
528
 
348
529
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puts_debuggerer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Maleh
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-07-20 00:00:00.000000000 Z
11
+ date: 2020-06-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: awesome_print
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 1.7.0
19
+ version: 1.8.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 1.7.0
26
+ version: 1.8.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rspec
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -67,71 +67,93 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '3.12'
69
69
  - !ruby/object:Gem::Dependency
70
- name: bundler
70
+ name: jeweler
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '1.0'
75
+ version: 2.3.9
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '1.0'
82
+ version: 2.3.9
83
83
  - !ruby/object:Gem::Dependency
84
- name: jeweler
84
+ name: bundler
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 2.3.0
89
+ version: 2.1.4
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: 2.3.0
96
+ version: 2.1.4
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: coveralls
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - '='
102
102
  - !ruby/object:Gem::Version
103
- version: 0.8.5
103
+ version: 0.8.23
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - '='
109
109
  - !ruby/object:Gem::Version
110
- version: 0.8.5
110
+ version: 0.8.23
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: simplecov
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: 0.10.0
117
+ version: 0.16.1
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 0.16.1
125
+ - !ruby/object:Gem::Dependency
126
+ name: simplecov-lcov
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 0.7.0
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 0.7.0
139
+ - !ruby/object:Gem::Dependency
140
+ name: undercover
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: 0.3.4
118
146
  type: :development
119
147
  prerelease: false
120
148
  version_requirements: !ruby/object:Gem::Requirement
121
149
  requirements:
122
150
  - - "~>"
123
151
  - !ruby/object:Gem::Version
124
- version: 0.10.0
152
+ version: 0.3.4
125
153
  description: |
126
- Yes, many of us avoid debuggers like the plague and clamp on to our puts statements like an umbrella in a stormy day. Why not make it official and have puts debugging become its own perfectly legitimate thing?!!
127
-
128
- Enter puts_debuggerer. A guilt-free puts debugger Ruby gem FTW!
129
-
130
- In other words, puts_debuggerer is a Ruby library for improved puts debugging, automatically displaying bonus useful information such as source line number and source code.
131
-
132
- Partially inspired (only partially ;) by this blog post:
133
- https://tenderlovemaking.com/2016/02/05/i-am-a-puts-debuggerer.html
134
- (Credit to Tenderlove.)
154
+ Debuggers are great! They help us troubleshoot complicated programming problems by inspecting values produced by code, line by line. They are invaluable when trying to understand what is going on in a large application composed of thousands or millions of lines of code.
155
+ In day-to-day test-driven development and simple debugging though, a puts statement can be a lot quicker in revealing what is going on than halting execution completely just to inspect a single value or a few. This is certainly true when writing the simplest possible code that could possibly work, and running a test every few seconds or minutes. Problem is you need to locate puts statements in large output logs, know which methods were invoked, find out what variable names are being printed, and see nicely formatted output. Enter puts_debuggerer. A guilt-free puts debugging Ruby gem FTW that prints file names, line numbers, code statements, and formats output nicely courtesy of awesome_print.
156
+ Partially inspired by this blog post: https://tenderlovemaking.com/2016/02/05/i-am-a-puts-debuggerer.html (Credit to Tenderlove.)
135
157
  email: andy.am@gmail.com
136
158
  executables: []
137
159
  extensions: []
@@ -141,12 +163,13 @@ extra_rdoc_files:
141
163
  files:
142
164
  - LICENSE.txt
143
165
  - README.md
166
+ - VERSION
144
167
  - lib/puts_debuggerer.rb
145
168
  homepage: http://github.com/AndyObtiva/puts_debuggerer
146
169
  licenses:
147
170
  - MIT
148
171
  metadata: {}
149
- post_install_message:
172
+ post_install_message:
150
173
  rdoc_options: []
151
174
  require_paths:
152
175
  - lib
@@ -161,9 +184,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
161
184
  - !ruby/object:Gem::Version
162
185
  version: '0'
163
186
  requirements: []
164
- rubyforge_project:
165
- rubygems_version: 2.6.10
166
- signing_key:
187
+ rubygems_version: 3.1.2
188
+ signing_key:
167
189
  specification_version: 4
168
190
  summary: Ruby library for improved puts debugging, automatically displaying bonus
169
191
  useful information such as source line number and source code.