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.
- checksums.yaml +5 -5
- data/README.md +260 -42
- data/VERSION +1 -0
- data/lib/puts_debuggerer.rb +218 -37
- metadata +50 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8b80118305f3b8201241cb75a16fab616e1db9789daf829c5b4ea68ad7a6d94d
|
4
|
+
data.tar.gz: dd345085a3bcbf718cdb49983b3c2d1838b1914b231e6fc033ff30ea992fac32
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1ac9056936792d4f8c46e4ae4114b0911a6442ef5b6ee5a6a1aebd6e405c3abc37466d207f19e94c6eaf9bd58374cd30ab2f66581777b9e37b2f572953c9261a
|
7
|
+
data.tar.gz: 7e0bbb0fcb9c502a252227b74a68a91d39f8ecbbf5cf85a18c4f561dae0a71baa5d258680835c573d2c5f6555e142f1b911f6a3c94302022cbd3a3ac4caeda01
|
data/README.md
CHANGED
@@ -1,22 +1,127 @@
|
|
1
|
-
#
|
1
|
+
# Puts Debuggerer (debugger-less debugging FTW)
|
2
2
|
[](http://badge.fury.io/rb/puts_debuggerer)
|
3
3
|
[](https://travis-ci.org/AndyObtiva/puts_debuggerer)
|
4
4
|
[](https://coveralls.io/github/AndyObtiva/puts_debuggerer?branch=master)
|
5
5
|
|
6
|
-
|
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
|
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
|
-
|
10
|
+
Basic Example:
|
14
11
|
|
15
|
-
|
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
|
-
|
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.
|
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.
|
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
|
-
###
|
150
|
+
### Awesome Print
|
46
151
|
|
47
|
-
|
152
|
+
puts_debuggerer comes with [awesome_print](https://github.com/awesome-print/awesome_print).
|
48
153
|
|
49
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
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 = `:
|
368
|
+
(default = `:ap`)
|
221
369
|
|
222
|
-
Print engine is
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
506
|
+
Can be set globally via `PutsDebuggerer.run_at` or piecemeal via `pd object, run_at: run_at_value`
|
354
507
|
|
355
|
-
|
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
|
-
|
512
|
+
Examples (global):
|
358
513
|
|
359
514
|
```ruby
|
360
|
-
|
361
|
-
|
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
|
-
|
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
|
data/lib/puts_debuggerer.rb
CHANGED
@@ -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
|
-
|
7
|
-
|
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
|
-
#
|
105
|
-
#
|
106
|
-
#
|
107
|
-
#
|
108
|
-
#
|
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 = :
|
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
|
-
|
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
|
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
|
-
|
275
|
-
PutsDebuggerer.
|
276
|
-
PutsDebuggerer.
|
277
|
-
PutsDebuggerer.
|
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
|
-
|
311
|
-
|
312
|
-
|
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
|
-
|
319
|
-
|
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.
|
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:
|
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.
|
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.
|
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:
|
70
|
+
name: jeweler
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
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:
|
82
|
+
version: 2.3.9
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: bundler
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: 2.
|
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.
|
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.
|
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.
|
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.
|
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.
|
152
|
+
version: 0.3.4
|
125
153
|
description: |
|
126
|
-
|
127
|
-
|
128
|
-
|
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
|
-
|
165
|
-
|
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.
|