puts_debuggerer 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f418876a84bf9553ec518205bad58db7b3abc120f1cd9fcff49e6edd49267247
4
- data.tar.gz: 808081fdf435cd30c4d1bb1f6a4f6211068e2ae2d52c039e3f99bbbf77071744
3
+ metadata.gz: b97ba980916a6d84faa8817ed75f1cc5d19841435e707a61090c5bfaf511872e
4
+ data.tar.gz: 05e9a62ad2893e1394e18359652f5de012536b90f61ba6a2507501daaf73b774
5
5
  SHA512:
6
- metadata.gz: 4e85ad239c06a374f8e8319649cca570af59aae4b828b64e2d4e9e1102af8a41123f8896da3ce8e2ec103d5300c4968493063419a258ed672ee82de05358e3f4
7
- data.tar.gz: 2c56e41a7649d11ca7998d86b1682d2b16e59ecf70b94ef71c3672857c03693932d9ef797218fb65c9cfea7563c0df6428bf2e48a1ca4ac2366f38677b6bdfb8
6
+ metadata.gz: 397639f53099e9fa91b5cbc7a42b0fe7c465eb2835e6b08307c5ae0b0e01036f6d3ee428c204375f2a5c977543715955f3efbd448bceb4dde59bea21f9a09290
7
+ data.tar.gz: b53f8db42dea2a575f438357e43966a478692cb73342dbc9255ed7e23196758f2e166180e26283bd06f19974a2a570e2bc01f52f5d37f27d57b939e16e40e797
@@ -1,5 +1,15 @@
1
1
  # Change Log
2
2
 
3
+ ## 0.10.0
4
+
5
+ - Support `require 'pd`' as a shorter alternative to `require 'puts_debuggerer'`
6
+ - Support `printer` as a Logger object or Logging::Logger (from "logging" gem). Basically any object that responds to :debug method.
7
+ - Support `printer: false` option to return rendered String instead of printing and returning object
8
+ - Set logger formatter to PutsDebuggerer::LOGGER_FORMATTER_DECORATOR when passing as printer (keeping format the same, but decorating msg with pd)
9
+ - Add pd_inspect (and pdi alias) Kernel core extension methods
10
+ - Made awesome_print gem require happen only if printer is set to :ap or :awesome_print
11
+ - Support logging gem logger and Decorate logger layout with PutsDebuggerer::LOGGING_LAYOUT_DECORATOR for logging gem
12
+
3
13
  ## 0.9.0
4
14
 
5
15
  - Provide partial support for Opal Ruby (missing display of file name, line number, and source code)
data/README.md CHANGED
@@ -2,10 +2,17 @@
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
+ [![Maintainability](https://api.codeclimate.com/v1/badges/81d8f6e046eb1b4a36f4/maintainability)](https://codeclimate.com/github/AndyObtiva/puts_debuggerer/maintainability)
6
+
7
+ (credit to Aaron Patterson for partial inspiration: https://tenderlovemaking.com/2016/02/05/i-am-a-puts-debuggerer.html)
5
8
 
6
9
  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.
7
10
 
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.
11
+ In day-to-day test-driven development and simple app 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. Still, there are a number of problems with puts debugging, like difficulty in locating puts statements in a large output log, knowing which methods and line numbers were invoked, identifying which variables were printed, and seeing the content of structured hashes and arrays in an understandable format.
12
+
13
+ Enter [puts_debuggerer](https://rubygems.org/gems/puts_debuggerer)! A guilt-free puts debugging Ruby gem FTW that prints file names, line numbers, code statements, headers, footers, stack traces, and formats output nicely courtesy of [awesome_print](https://rubygems.org/gems/awesome_print).
14
+
15
+ [puts_debuggerer](https://rubygems.org/gems/puts_debuggerer) automates tips mentioned in [this blog post](https://tenderlovemaking.com/2016/02/05/i-am-a-puts-debuggerer.html) by Aaron Patterson.
9
16
 
10
17
  Basic Example:
11
18
 
@@ -19,17 +26,14 @@ pd bug_or_band # line 4
19
26
  Output:
20
27
 
21
28
  ```bash
22
- [PD] trivia_app.rb:4
29
+ [PD] /Users/User/trivia_app.rb:4
23
30
  > pd bug_or_band # line 4
24
31
  => "beattle"
25
32
  ```
26
33
 
27
34
  ## Background
28
35
 
29
- For initial background, please read this blog post by Aaron Patterson (part of the inspiration for this gem):
30
- https://tenderlovemaking.com/2016/02/05/i-am-a-puts-debuggerer.html
31
-
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.
36
+ It can be quite frustrating to lose puts statements in a large output or log file. One way to help find them is add an announcer (e.g. `puts "The Order Total"`) or a header (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
37
 
34
38
  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
39
 
@@ -80,7 +84,7 @@ puts "order_details"
80
84
  puts order_details
81
85
  ```
82
86
 
83
- Here is a simple example using `pd` instead:
87
+ Here is a simple example using `pd` instead, which provides everything the puts statements above provide in addition to deducing the file name and line number automatically for dead easy debugging:
84
88
 
85
89
  ```ruby
86
90
  pd order_total
@@ -94,7 +98,15 @@ Output:
94
98
  => 195.50
95
99
  ```
96
100
 
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.
101
+ This is not only easy to locate in a logging stream such as the one below, but also announces the `order_total` variable with `[PD]` for easy findability among other pd statements (you may always enter `[PD]` or variable name `order_total` using the CMD+F Quick Find to instantly jump to that line in the log):
102
+
103
+ ```ruby
104
+ pd order_total
105
+ pd order_summary
106
+ pd order_details
107
+ ```
108
+
109
+ Output:
98
110
 
99
111
  ```
100
112
  (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)
@@ -105,24 +117,184 @@ This is not only easy to locate in a logging stream such as the one below, but a
105
117
  (0.2ms) BEGIN
106
118
  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
119
  (0.3ms) COMMIT
108
- [PD] /Users/User/ordering/order.rb:72
109
- > pd order_subtotal
110
- => 181.00
120
+ [PD] /Users/User/ordering/order.rb:40
121
+ > pd order_summary
122
+ => "Pragmatic Ruby Book"
111
123
  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
124
  (0.2ms) BEGIN
113
125
  (0.2ms) COMMIT
126
+ [PD] /Users/User/ordering/order.rb:41
127
+ > pd order_details
128
+ => "[Hard Cover] Pragmatic Ruby Book - English Version"
129
+ ```
130
+
131
+ What if you would like to add a header for faster findability? Just use the `header` option:
132
+
133
+ ```ruby
134
+ pd order_total, header: true
135
+ pd order_summary
136
+ pd order_details
114
137
  ```
115
138
 
116
- And it is easy to search for using the `[PD]` announcer (customizable).
139
+ Output:
140
+
141
+ ```
142
+ (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)
143
+ 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]]
144
+ ********************************************************************************
145
+ [PD] /Users/User/ordering/order.rb:39
146
+ > pd order_total, header: true
147
+ => 195.50
148
+ (0.2ms) BEGIN
149
+ 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]]
150
+ (0.3ms) COMMIT
151
+ [PD] /Users/User/ordering/order.rb:40
152
+ > pd order_summary
153
+ => "Pragmatic Ruby Book"
154
+ 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]]
155
+ (0.2ms) BEGIN
156
+ (0.2ms) COMMIT
157
+ [PD] /Users/User/ordering/order.rb:41
158
+ > pd order_details
159
+ => "[Hard Cover] Pragmatic Ruby Book - English Version"
160
+ ```
117
161
 
118
- When inspecting multiple variables, debugging code is still a snap:
162
+ Wanna customize the header and add a footer too? No problem:
119
163
 
120
164
  ```ruby
121
- pd order_total
165
+ pd order_total, header: '>'*80
166
+ pd order_summary
167
+ pd order_details, footer: '<'*80
168
+ ```
169
+
170
+ Output:
171
+
172
+ ```
173
+ (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)
174
+ 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]]
175
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
176
+ [PD] /Users/User/ordering/order.rb:39
177
+ > pd order_total, header: '>'*80
178
+ => 195.50
179
+ (0.2ms) BEGIN
180
+ 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]]
181
+ (0.3ms) COMMIT
182
+ [PD] /Users/User/ordering/order.rb:40
183
+ > pd order_summary
184
+ => "Pragmatic Ruby Book"
185
+ 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]]
186
+ (0.2ms) BEGIN
187
+ (0.2ms) COMMIT
188
+ [PD] /Users/User/ordering/order.rb:41
189
+ > pd order_details, footer: '<'*80
190
+ => "[Hard Cover] Pragmatic Ruby Book - English Version"
191
+ <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
192
+ ```
193
+
194
+ Need a quick stack trace? Just use the `caller` option (you may surround with header and footer too via `wrapper`).
195
+
196
+ ```ruby
197
+ pd order_total, caller: true, wrapper: true
122
198
  pd order_summary
123
199
  pd order_details
124
200
  ```
125
201
 
202
+ Output:
203
+
204
+ ```
205
+ (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)
206
+ 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]]
207
+ ********************************************************************************
208
+ [PD] /Users/User/ordering/order.rb:39
209
+ > pd order_total, caller: true, wrapper: true
210
+ => 195.50
211
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'
212
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'
213
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
214
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi'
215
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require'
216
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/activesupport-5.2.4.3/lib/active_support/dependencies.rb:291:in `block in require'
217
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/activesupport-5.2.4.3/lib/active_support/dependencies.rb:257:in `load_dependency'
218
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/activesupport-5.2.4.3/lib/active_support/dependencies.rb:291:in `require'
219
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/railties-5.2.4.3/lib/rails/commands/server/server_command.rb:145:in `block in perform'
220
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/railties-5.2.4.3/lib/rails/commands/server/server_command.rb:142:in `tap'
221
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/railties-5.2.4.3/lib/rails/commands/server/server_command.rb:142:in `perform'
222
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/thor-1.0.1/lib/thor/command.rb:27:in `run'
223
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/thor-1.0.1/lib/thor/invocation.rb:127:in `invoke_command'
224
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/thor-1.0.1/lib/thor.rb:392:in `dispatch'
225
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/railties-5.2.4.3/lib/rails/command/base.rb:69:in `perform'
226
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/railties-5.2.4.3/lib/rails/command.rb:46:in `invoke'
227
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/railties-5.2.4.3/lib/rails/commands.rb:18:in `<main>'
228
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'
229
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'
230
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
231
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi'
232
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require'
233
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/activesupport-5.2.4.3/lib/active_support/dependencies.rb:291:in `block in require'
234
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/activesupport-5.2.4.3/lib/active_support/dependencies.rb:257:in `load_dependency'
235
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/activesupport-5.2.4.3/lib/active_support/dependencies.rb:291:in `require'
236
+ /Users/User/code/sample-glimmer-dsl-opal-rails5-app/bin/rails:9:in `<top (required)>'
237
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/spring-2.1.0/lib/spring/client/rails.rb:28:in `load'
238
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/spring-2.1.0/lib/spring/client/rails.rb:28:in `call'
239
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/spring-2.1.0/lib/spring/client/command.rb:7:in `call'
240
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/spring-2.1.0/lib/spring/client.rb:30:in `run'
241
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/spring-2.1.0/bin/spring:49:in `<top (required)>'
242
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/spring-2.1.0/lib/spring/binstub.rb:11:in `load'
243
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/spring-2.1.0/lib/spring/binstub.rb:11:in `<top (required)>'
244
+ /Users/User/code/sample-glimmer-dsl-opal-rails5-app/bin/spring:15:in `require'
245
+ /Users/User/code/sample-glimmer-dsl-opal-rails5-app/bin/spring:15:in `<top (required)>'
246
+ bin/rails:3:in `load'
247
+ bin/rails:3:in `<main>'
248
+ ********************************************************************************
249
+ (0.2ms) BEGIN
250
+ 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]]
251
+ (0.3ms) COMMIT
252
+ [PD] /Users/User/ordering/order.rb:40
253
+ > pd order_summary
254
+ => "Pragmatic Ruby Book"
255
+ 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]]
256
+ (0.2ms) BEGIN
257
+ (0.2ms) COMMIT
258
+ [PD] /Users/User/ordering/order.rb:41
259
+ > pd order_details
260
+ => "[Hard Cover] Pragmatic Ruby Book - English Version"
261
+ ```
262
+
263
+ Is the stack trace too long? Shorten it by passing number of lines to display to `caller` option.
264
+
265
+ ```ruby
266
+ pd order_total, caller: 3, wrapper: true
267
+ pd order_summary
268
+ pd order_details
269
+ ```
270
+
271
+ ```
272
+ (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)
273
+ 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]]
274
+ ********************************************************************************
275
+ [PD] /Users/User/ordering/order.rb:39
276
+ > pd order_total, caller: 3, wrapper: true
277
+ => 195.50
278
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'
279
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'
280
+ /Users/User/.rvm/gems/ruby-2.7.1/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
281
+ ********************************************************************************
282
+ (0.2ms) BEGIN
283
+ 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]]
284
+ (0.3ms) COMMIT
285
+ [PD] /Users/User/ordering/order.rb:40
286
+ > pd order_summary
287
+ => "Pragmatic Ruby Book"
288
+ 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]]
289
+ (0.2ms) BEGIN
290
+ (0.2ms) COMMIT
291
+ [PD] /Users/User/ordering/order.rb:41
292
+ > pd order_details
293
+ => "[Hard Cover] Pragmatic Ruby Book - English Version"
294
+ ```
295
+
296
+ There are many more options and powerful features in [puts_debuggerer](https://rubygems.org/gems/puts_debuggerer) as detailed below.
297
+
126
298
  ## Instructions
127
299
 
128
300
  ### Option 1: Bundler
@@ -130,7 +302,7 @@ pd order_details
130
302
  Add the following to bundler's `Gemfile`.
131
303
 
132
304
  ```ruby
133
- gem 'puts_debuggerer', '~> 0.9.0'
305
+ gem 'puts_debuggerer', '~> 0.10.0'
134
306
  ```
135
307
 
136
308
  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.
@@ -140,7 +312,7 @@ This is the recommended way for [Rails](rubyonrails.org) apps. Optionally, you m
140
312
  Or manually install and require library.
141
313
 
142
314
  ```bash
143
- gem install puts_debuggerer -v0.9.0
315
+ gem install puts_debuggerer -v0.10.0
144
316
  ```
145
317
 
146
318
  ```ruby
@@ -155,7 +327,7 @@ You may disable when needed by not requiring in Ruby or by adding an explicit re
155
327
 
156
328
  ```ruby
157
329
  gem "awesome_print", require: false
158
- gem "puts_debugger"
330
+ gem "puts_debuggerer"
159
331
  ```
160
332
 
161
333
  ### Usage
@@ -209,8 +381,15 @@ Output:
209
381
  => "Hello Robert"
210
382
  ```
211
383
 
384
+ Alternatively, you may want to use `object.pd_inspect` (or alias `obj.pdi`) to
385
+ return formatted string without printing.
386
+
212
387
  Happy puts_debuggerering!
213
388
 
389
+ #### Ruby Logger and Logging::Logger
390
+
391
+ Ruby Logger and Logging::Logger (from [logging gem](https://github.com/TwP/logging)) are supported as [printers](#putsdebuggererprinter) (learn more under [PutsDebuggerer#printer](#putsdebuggererprinter)).
392
+
214
393
  ### Options
215
394
 
216
395
  Options enable more data to be displayed with puts_debuggerer, such as the caller
@@ -292,9 +471,25 @@ Header to include at the top of every print out.
292
471
 
293
472
  Example:
294
473
 
474
+ ```ruby
475
+ pd (x=1), header: true
476
+ ```
477
+
478
+ Prints out:
479
+
480
+ ```bash
481
+ ********************************************************************************
482
+ [PD] /Users/User/example.rb:1
483
+ > pd (x=1), header: true
484
+ => "1"
485
+ ```
486
+
487
+ Global Option Example:
488
+
295
489
  ```ruby
296
490
  PutsDebuggerer.header = true
297
491
  pd (x=1)
492
+ pd (x=2)
298
493
  ```
299
494
 
300
495
  Prints out:
@@ -302,8 +497,12 @@ Prints out:
302
497
  ```bash
303
498
  ********************************************************************************
304
499
  [PD] /Users/User/example.rb:2
305
- > pd x=1
500
+ > pd (x=1)
306
501
  => "1"
502
+ ********************************************************************************
503
+ [PD] /Users/User/example.rb:3
504
+ > pd (x=2)
505
+ => "2"
307
506
  ```
308
507
 
309
508
  #### `PutsDebuggerer.footer`
@@ -317,18 +516,38 @@ Footer to include at the bottom of every print out.
317
516
 
318
517
  Example:
319
518
 
519
+ ```ruby
520
+ pd (x=1), footer: true
521
+ ```
522
+
523
+ Prints out:
524
+
525
+ ```bash
526
+ [PD] /Users/User/example.rb:1
527
+ > pd (x=1), footer: true
528
+ => "1"
529
+ ********************************************************************************
530
+ ```
531
+
532
+ Global Option Example:
533
+
320
534
  ```ruby
321
535
  PutsDebuggerer.footer = true
322
536
  pd (x=1)
537
+ pd (x=2)
323
538
  ```
324
539
 
325
540
  Prints out:
326
541
 
327
542
  ```bash
328
543
  [PD] /Users/User/example.rb:2
329
- > pd x=1
544
+ > pd (x=1)
330
545
  => "1"
331
546
  ********************************************************************************
547
+ [PD] /Users/User/example.rb:3
548
+ > pd (x=2)
549
+ => "2"
550
+ ********************************************************************************
332
551
  ```
333
552
 
334
553
  #### `PutsDebuggerer.wrapper`
@@ -342,9 +561,26 @@ Wrapper to include at the top and bottom of every print out (both header and foo
342
561
 
343
562
  Example:
344
563
 
564
+ ```ruby
565
+ pd (x=1), wrapper: true
566
+ ```
567
+
568
+ Prints out:
569
+
570
+ ```bash
571
+ ********************************************************************************
572
+ [PD] /Users/User/example.rb:1
573
+ > pd x=1, wrapper: true
574
+ => "1"
575
+ ********************************************************************************
576
+ ```
577
+
578
+ Global Option Example:
579
+
345
580
  ```ruby
346
581
  PutsDebuggerer.wrapper = true
347
582
  pd (x=1)
583
+ pd (x=2)
348
584
  ```
349
585
 
350
586
  Prints out:
@@ -352,14 +588,21 @@ Prints out:
352
588
  ```bash
353
589
  ********************************************************************************
354
590
  [PD] /Users/User/example.rb:2
355
- > pd x=1
591
+ > pd (x=1)
356
592
  => "1"
357
593
  ********************************************************************************
594
+ ********************************************************************************
595
+ [PD] /Users/User/example.rb:3
596
+ > pd (x=2)
597
+ => "2"
598
+ ********************************************************************************
358
599
  ```
359
600
 
360
601
  #### `PutsDebuggerer.source_line_count`
361
602
  (default = `1`)
362
603
 
604
+ Prints multiple source code lines as per count specified. Useful when a statement is broken down on multiple lines or when there is a need to get more context around the line printed.
605
+
363
606
  Example:
364
607
 
365
608
  ```ruby
@@ -370,7 +613,7 @@ pd (true ||
370
613
  Prints out:
371
614
 
372
615
  ```
373
- [PD] /Users/User/example.rb:2
616
+ [PD] /Users/User/example.rb:1
374
617
  > pd (true ||
375
618
  false), source_line_count: 2
376
619
  => "true"
@@ -396,9 +639,17 @@ Prints out:
396
639
  #### `PutsDebuggerer.printer`
397
640
  (default = `:puts`)
398
641
 
399
- Printer is a global method symbol or lambda expression to use in printing to the user.
400
- Examples of global methods are `:puts` and `:print`.
642
+ Printer is a global method symbol, lambda expression, or logger to use in printing to the user.
643
+
644
+ Examples of a global method are `:puts` and `:print`.
401
645
  An example of a lambda expression is `lambda {|output| Rails.logger.info(output)}`
646
+ Examples of a logger are a Ruby `Logger` instance or `Logging::Logger` instance
647
+
648
+ When a logger is supplied, it is automatically enhanced with a PutsDebuggerer formatter to use
649
+ when calling logger methods outside of PutsDebuggerer (e.g. `logger.error('msg')` will use `pd`)
650
+
651
+ Printer may be set to `false` to avoid printing and only return the formatted string.
652
+ It is equivalent of just calling `.pd_inspect` (or alias `.pdi`) on the object
402
653
 
403
654
  Defaults to `:puts`
404
655
  In Rails, it defaults to:
@@ -450,7 +701,7 @@ pd array
450
701
  Prints out:
451
702
 
452
703
  ```bash
453
- [PD] /Users/User/example.rb:5
704
+ [PD] /Users/User/example.rb:4
454
705
  > pd array
455
706
  => [1, [2, 3]]
456
707
  ```
@@ -555,6 +806,34 @@ Prints out:
555
806
  /Users/User/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/irb/context.rb:381:in \`evaluate\'
556
807
  ```
557
808
 
809
+ Global Option Example:
810
+
811
+ ```ruby
812
+ # File Name: /Users/User/sample_app/lib/sample.rb
813
+ PutsDebuggerer.caller = 3 # always print 3 lines only of the stack trace
814
+ pd (x=1)
815
+ pd (x=2)
816
+ ```
817
+
818
+ Prints out:
819
+
820
+ ```bash
821
+ [PD] /Users/User/sample_app/lib/sample.rb:2
822
+ > pd (x=1)
823
+ => "1"
824
+ /Users/User/sample_app/lib/master_samples.rb:368:in \`block (3 levels) in <top (required)>\'
825
+ /Users/User/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/irb/workspace.rb:87:in \`eval\'
826
+ /Users/User/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/irb/workspace.rb:87:in \`evaluate\'
827
+ /Users/User/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/irb/context.rb:381:in \`evaluate\'
828
+ [PD] /Users/User/sample_app/lib/sample.rb:3
829
+ > pd (x=2)
830
+ => "2"
831
+ /Users/User/sample_app/lib/master_samples.rb:368:in \`block (3 levels) in <top (required)>\'
832
+ /Users/User/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/irb/workspace.rb:87:in \`eval\'
833
+ /Users/User/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/irb/workspace.rb:87:in \`evaluate\'
834
+ /Users/User/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/irb/context.rb:381:in \`evaluate\'
835
+ ```
836
+
558
837
  #### `PutsDebuggerer.run_at`
559
838
  (default = nil)
560
839
 
@@ -678,7 +957,7 @@ Prints out `puts __caller_source_line__`
678
957
  - IRB
679
958
  - Rails Console.
680
959
 
681
- It has partial-compatibility with [Opal Ruby](https://opalrb.com/) with everything working except these features:
960
+ It provides partial-compatibility for [Opal Ruby](https://opalrb.com/), with everything working except these features:
682
961
  - File name display
683
962
  - Line number display
684
963
  - Source code call display
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.9.0
1
+ 0.10.0
@@ -0,0 +1 @@
1
+ require 'puts_debuggerer'
@@ -1,18 +1,58 @@
1
- require 'awesome_print' unless RUBY_PLATFORM == 'opal'
2
1
  require 'stringio'
3
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
16
+
4
17
  module PutsDebuggerer
5
18
  SOURCE_LINE_COUNT_DEFAULT = 1
6
19
  HEADER_DEFAULT = '*'*80
7
20
  WRAPPER_DEFAULT = '*'*80
8
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
9
49
  PRINTER_DEFAULT = :puts
10
50
  PRINTER_RAILS = lambda do |output|
11
51
  puts output if Rails.env.test?
12
52
  Rails.logger.debug(output)
13
53
  end
14
54
  PRINT_ENGINE_DEFAULT = :ap
15
- 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'
16
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'
17
57
  ANNOUNCER_DEFAULT = '[PD]'
18
58
  FORMATTER_DEFAULT = -> (data) {
@@ -25,7 +65,6 @@ module PutsDebuggerer
25
65
  puts data[:wrapper] if data[:wrapper]
26
66
  }
27
67
  CALLER_DEPTH_ZERO = 4 #depth includes pd + with_options method + nested block + build_pd_data method
28
- OBJECT_RUN_AT = {}
29
68
  STACK_TRACE_CALL_LINE_NUMBER_REGEX = /\:(\d+)\:in /
30
69
  STACK_TRACE_CALL_SOURCE_FILE_REGEX = /[ ]*([^:]+)\:\d+\:in /
31
70
 
@@ -90,20 +129,6 @@ module PutsDebuggerer
90
129
  # => "1"
91
130
  attr_reader :header
92
131
 
93
- def header=(value)
94
- if value.equal?(true)
95
- @header = HEADER_DEFAULT
96
- elsif value == ''
97
- @header = nil
98
- else
99
- @header = value
100
- end
101
- end
102
-
103
- def header?
104
- !!@header
105
- end
106
-
107
132
  # Wrapper to include at the top and bottom of every print out (both header and footer).
108
133
  # * Default value is `nil`
109
134
  # * Value `true` enables wrapper as `'*'*80`
@@ -123,20 +148,6 @@ module PutsDebuggerer
123
148
  # ********************************************************************************
124
149
  attr_reader :wrapper
125
150
 
126
- def wrapper=(value)
127
- if value.equal?(true)
128
- @wrapper = WRAPPER_DEFAULT
129
- elsif value == ''
130
- @wrapper = nil
131
- else
132
- @wrapper = value
133
- end
134
- end
135
-
136
- def wrapper?
137
- !!@wrapper
138
- end
139
-
140
151
  # Footer to include at the bottom of every print out.
141
152
  # * Default value is `nil`
142
153
  # * Value `true` enables footer as `'*'*80`
@@ -155,24 +166,27 @@ module PutsDebuggerer
155
166
  # => "1"
156
167
  # ********************************************************************************
157
168
  attr_reader :footer
158
-
159
- def footer=(value)
160
- if value.equal?(true)
161
- @footer = FOOTER_DEFAULT
162
- elsif value == ''
163
- @footer = nil
164
- else
165
- @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}")
166
183
  end
167
184
  end
168
185
 
169
- def footer?
170
- !!@footer
171
- end
172
-
173
- # Printer is a global method symbol or lambda expression to use in printing to the user.
174
- # 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`.
175
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
176
190
  #
177
191
  # Defaults to `:puts`
178
192
  # In Rails, it defaults to: `lambda {|output| Rails.logger.ap(output)}`
@@ -193,17 +207,37 @@ module PutsDebuggerer
193
207
 
194
208
  def printer=(printer)
195
209
  if printer.nil?
196
- if Object.const_defined?(:Rails)
197
- @printer = PRINTER_RAILS
198
- else
199
- @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)
219
+ end
220
+ printer.appenders.each do |appender|
221
+ appender.layout = LOGGING_LAYOUT_DECORATOR.call(appender.layout)
200
222
  end
201
- elsif printer.is_a?(Proc)
223
+ elsif printer == false || printer.is_a?(Proc) || printer.respond_to?(:log) # a logger
202
224
  @printer = printer
203
225
  else
204
226
  @printer = method(printer).name rescue raise(PRINTER_MESSAGE_INVALID)
205
227
  end
206
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
207
241
 
208
242
  # Print engine is similar to `printer`, except it is focused on the scope of formatting
209
243
  # the data object being printed (excluding metadata such as file name, line number,
@@ -232,13 +266,17 @@ module PutsDebuggerer
232
266
 
233
267
  def print_engine=(engine)
234
268
  if engine.nil?
235
- @print_engine = Object.const_defined?(:AwesomePrint) ? PRINT_ENGINE_DEFAULT : :p
269
+ @print_engine = print_engine_default
236
270
  elsif engine.is_a?(Proc)
237
271
  @print_engine = engine
238
272
  else
239
273
  @print_engine = method(engine).name rescue raise(PRINT_ENGINE_MESSAGE_INVALID)
240
274
  end
241
275
  end
276
+
277
+ def print_engine_default
278
+ Object.const_defined?(:AwesomePrint) ? PRINT_ENGINE_DEFAULT : :p
279
+ end
242
280
 
243
281
  # Announcer (e.g. [PD]) to announce every print out with (default: "[PD]")
244
282
  #
@@ -430,44 +468,25 @@ module PutsDebuggerer
430
468
  !!@run_at
431
469
  end
432
470
 
433
- attr_reader :run_at_global_number
434
-
435
- def run_at_global_number=(value)
436
- @run_at_global_number = value
437
- end
438
-
439
- def init_run_at_global_number
440
- @run_at_global_number = 1
441
- end
442
-
443
- def increment_run_at_global_number
444
- @run_at_global_number += 1
445
- end
446
-
447
- def reset_run_at_global_number
448
- @run_at_global_number = nil
449
- end
450
-
451
- def run_at_number(object, run_at)
452
- PutsDebuggerer::OBJECT_RUN_AT[[object,run_at]]
471
+ def determine_options(objects)
472
+ objects.delete_at(-1) if objects.size > 1 && objects.last.is_a?(Hash)
453
473
  end
454
474
 
455
- def init_run_at_number(object, run_at)
456
- PutsDebuggerer::OBJECT_RUN_AT[[object,run_at]] = 1
475
+ def determine_object(objects)
476
+ objects.compact.size > 1 ? objects : objects.first
457
477
  end
458
478
 
459
- def increment_run_at_number(object, run_at)
460
- PutsDebuggerer::OBJECT_RUN_AT[[object,run_at]] += 1
479
+ def determine_run_at(options)
480
+ ((options && options[:run_at]) || PutsDebuggerer.run_at)
461
481
  end
462
482
 
463
- def reset_run_at_number(object, run_at)
464
- PutsDebuggerer::OBJECT_RUN_AT.delete([object, run_at])
465
- end
466
-
467
- def reset_run_at_numbers
468
- PutsDebuggerer::OBJECT_RUN_AT.clear
483
+ def determine_printer(options)
484
+ if options && options.has_key?(:printer)
485
+ options[:printer]
486
+ else
487
+ PutsDebuggerer.printer
488
+ end
469
489
  end
470
-
471
490
  end
472
491
  end
473
492
 
@@ -511,58 +530,56 @@ PutsDebuggerer.source_line_count = nil
511
530
  # => "Show me the source of the bug: beattle"
512
531
  # [PD] /Users/User/finance_calculator_app/pd_test.rb:4 "What line number am I?"
513
532
  def pd(*objects)
514
- options = objects.delete_at(-1) if objects.size > 1 && objects.last.is_a?(Hash)
515
- object = objects.compact.size > 1 ? objects : objects.first
516
- run_at = ((options && options[:run_at]) || PutsDebuggerer.run_at)
517
-
518
- if __run_pd__(object, run_at)
533
+ require 'awesome_print' if ['awesome_print', 'ap'].include?(PutsDebuggerer.print_engine.to_s) && RUBY_PLATFORM != 'opal'
534
+ options = PutsDebuggerer.determine_options(objects) || {}
535
+ object = PutsDebuggerer.determine_object(objects)
536
+ run_at = PutsDebuggerer.determine_run_at(options)
537
+ printer = PutsDebuggerer.determine_printer(options)
538
+ pd_inspect = options.delete(:pd_inspect)
539
+ logger_formatter_decorated = PutsDebuggerer.printer.is_a?(Logger) && PutsDebuggerer.printer.formatter != PutsDebuggerer.logger_original_formatter
540
+ logging_layouts_decorated = PutsDebuggerer.printer.is_a?(Logging::Logger) && PutsDebuggerer.printer.appenders.map(&:layout) != (PutsDebuggerer.logging_original_layouts.values)
541
+
542
+ string = nil
543
+ if PutsDebuggerer::RunDeterminer.run_pd?(object, run_at)
519
544
  __with_pd_options__(options) do |print_engine_options|
520
- run_number = PutsDebuggerer.run_at_global_number || PutsDebuggerer.run_at_number(object, run_at)
521
- formatter_pd_data = __build_pd_data__(object, print_engine_options, PutsDebuggerer.source_line_count, run_number) #depth adds build method
545
+ run_number = PutsDebuggerer::RunDeterminer.run_number(object, run_at)
546
+ 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
522
547
  stdout = $stdout
523
548
  $stdout = sio = StringIO.new
524
549
  PutsDebuggerer.formatter.call(formatter_pd_data)
525
550
  $stdout = stdout
551
+ string = sio.string
526
552
  if PutsDebuggerer.printer.is_a?(Proc)
527
- PutsDebuggerer.printer.call(sio.string)
528
- else
529
- send(PutsDebuggerer.send(:printer), sio.string)
553
+ PutsDebuggerer.printer.call(string)
554
+ elsif PutsDebuggerer.printer.is_a?(Logger)
555
+ logger_formatter = PutsDebuggerer.printer.formatter
556
+ begin
557
+ PutsDebuggerer.printer.formatter = PutsDebuggerer.logger_original_formatter
558
+ PutsDebuggerer.printer.debug(string)
559
+ ensure
560
+ PutsDebuggerer.printer.formatter = logger_formatter
561
+ end
562
+ elsif PutsDebuggerer.printer.is_a?(Logging::Logger)
563
+ logging_layouts = PutsDebuggerer.printer.appenders.reduce({}) do |hash, appender|
564
+ hash.merge(appender => appender.layout)
565
+ end
566
+ begin
567
+ PutsDebuggerer.logging_original_layouts.each do |appender, original_layout|
568
+ appender.layout = original_layout
569
+ end
570
+ PutsDebuggerer.printer.debug(string)
571
+ ensure
572
+ PutsDebuggerer.logging_original_layouts.each do |appender, original_layout|
573
+ appender.layout = logging_layouts[appender]
574
+ end
575
+ end
576
+ elsif PutsDebuggerer.printer != false
577
+ send(PutsDebuggerer.send(:printer), string)
530
578
  end
531
579
  end
532
580
  end
533
581
 
534
- object
535
- end
536
-
537
- def __run_pd__(object, run_at)
538
- run_pd = false
539
- if run_at.nil?
540
- run_pd = true
541
- else
542
- if PutsDebuggerer.run_at?
543
- if PutsDebuggerer.run_at_global_number.nil?
544
- PutsDebuggerer.init_run_at_global_number
545
- else
546
- PutsDebuggerer.increment_run_at_global_number
547
- end
548
- run_number = PutsDebuggerer.run_at_global_number
549
- else
550
- if PutsDebuggerer.run_at_number(object, run_at).nil?
551
- PutsDebuggerer.init_run_at_number(object, run_at)
552
- else
553
- PutsDebuggerer.increment_run_at_number(object, run_at)
554
- end
555
- run_number = PutsDebuggerer.run_at_number(object, run_at)
556
- end
557
- if run_at.is_a?(Integer)
558
- run_pd = true if run_at == run_number
559
- elsif run_at.is_a?(Array)
560
- run_pd = true if run_at.include?(run_number)
561
- elsif run_at.is_a?(Range)
562
- run_pd = true if run_at.cover?(run_number) || (run_at.end == -1 && run_number >= run_at.begin)
563
- end
564
- end
565
- run_pd
582
+ printer ? object : string
566
583
  end
567
584
 
568
585
  # Provides caller line number starting 1 level above caller of
@@ -589,7 +606,7 @@ end
589
606
  #
590
607
  # prints out `lib/example.rb`
591
608
  def __caller_file__(caller_depth=0)
592
- caller[caller_depth] && caller[caller_depth][PutsDebuggerer::STACK_TRACE_CALL_SOURCE_FILE_REGEX, 1]
609
+ result = caller[caller_depth] && caller[caller_depth][PutsDebuggerer::STACK_TRACE_CALL_SOURCE_FILE_REGEX, 1]
593
610
  end
594
611
 
595
612
 
@@ -606,24 +623,9 @@ def __caller_source_line__(caller_depth=0, source_line_count=nil, source_file=ni
606
623
  source_file ||= __caller_file__(caller_depth+1)
607
624
  source_line = ''
608
625
  if source_file == '(irb)'
609
- source_line = conf.io.line(source_line_number)
626
+ source_line = conf.io.line(source_line_number) # TODO handle multi-lines in source_line_count
610
627
  else
611
- f = File.new(source_file)
612
- if f.respond_to?(:readline) # Opal Ruby Compatibility
613
- source_lines = []
614
- begin
615
- while f.lineno < source_line_number + source_line_count
616
- file_line_number = f.lineno + 1
617
- file_line = f.readline
618
- if file_line_number >= source_line_number && file_line_number < source_line_number + source_line_count
619
- source_lines << file_line
620
- end
621
- end
622
- rescue EOFError
623
- # Done
624
- end
625
- source_line = source_lines.join(' '*5)
626
- end
628
+ source_line = PutsDebuggerer::SourceFile.new(source_file).source(source_line_count, source_line_number)
627
629
  end
628
630
  source_line
629
631
  end
@@ -639,8 +641,11 @@ def __with_pd_options__(options=nil)
639
641
  PutsDebuggerer.options = permanent_options
640
642
  end
641
643
 
642
- def __build_pd_data__(object, print_engine_options=nil, source_line_count=nil, run_number=nil)
644
+ 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)
643
645
  depth = PutsDebuggerer::CALLER_DEPTH_ZERO
646
+ depth += 1 if pd_inspect
647
+ depth += 4 if pd_inspect && logger_formatter_decorated
648
+ depth += 8 if pd_inspect && logging_layouts_decorated
644
649
  pd_data = {
645
650
  announcer: PutsDebuggerer.announcer,
646
651
  file: __caller_file__(depth)&.sub(PutsDebuggerer.app_path.to_s, ''),
@@ -648,31 +653,23 @@ def __build_pd_data__(object, print_engine_options=nil, source_line_count=nil, r
648
653
  pd_expression: __caller_pd_expression__(depth, source_line_count),
649
654
  run_number: run_number,
650
655
  object: object,
651
- object_printer: lambda do
652
- if object.is_a?(Exception) && object.respond_to?(:full_message)
653
- puts object.full_message
654
- elsif PutsDebuggerer.print_engine.is_a?(Proc)
655
- PutsDebuggerer.print_engine.call(object)
656
- else
657
- if print_engine_options.to_h.empty?
658
- send(PutsDebuggerer.print_engine, object)
659
- else
660
- send(PutsDebuggerer.print_engine, object, print_engine_options) rescue send(PutsDebuggerer.print_engine, object)
661
- end
662
- end
663
- end
656
+ object_printer: PutsDebuggerer::OBJECT_PRINTER_DEFAULT.call(object, print_engine_options, source_line_count, run_number)
664
657
  }
665
- if PutsDebuggerer.caller?
666
- start_depth = depth.to_i
667
- caller_depth = PutsDebuggerer.caller == -1 ? -1 : (start_depth + PutsDebuggerer.caller)
668
- pd_data[:caller] = caller[start_depth..caller_depth].to_a
658
+ pd_data[:caller] = __caller_caller__(depth)
659
+ ['header', 'wrapper', 'footer'].each do |boundary_option|
660
+ pd_data[boundary_option.to_sym] = PutsDebuggerer.send(boundary_option) if PutsDebuggerer.send("#{boundary_option}?")
669
661
  end
670
- pd_data[:header] = PutsDebuggerer.header if PutsDebuggerer.header?
671
- pd_data[:wrapper] = PutsDebuggerer.wrapper if PutsDebuggerer.wrapper?
672
- pd_data[:footer] = PutsDebuggerer.footer if PutsDebuggerer.footer?
673
662
  pd_data
674
663
  end
675
664
 
665
+ # Returns the caller stack trace of the caller of pd
666
+ def __caller_caller__(depth)
667
+ return unless PutsDebuggerer.caller?
668
+ start_depth = depth.to_i + 1
669
+ caller_depth = PutsDebuggerer.caller == -1 ? -1 : (start_depth + PutsDebuggerer.caller)
670
+ caller[start_depth..caller_depth].to_a
671
+ end
672
+
676
673
  def __format_pd_expression__(expression, object)
677
674
  "\n > #{expression}\n =>"
678
675
  end
@@ -0,0 +1,6 @@
1
+ module Kernel
2
+ def pd_inspect
3
+ pd self, printer: false, pd_inspect: true
4
+ end
5
+ alias pdi pd_inspect
6
+ end
@@ -0,0 +1,109 @@
1
+ module PutsDebuggerer
2
+ module RunDeterminer
3
+ OBJECT_RUN_AT = {}
4
+
5
+ class << self
6
+ attr_reader :run_at_global_number
7
+
8
+ def run_at_global_number=(value)
9
+ @run_at_global_number = value
10
+ end
11
+
12
+ def init_run_at_global_number
13
+ @run_at_global_number = 1
14
+ end
15
+
16
+ def increment_run_at_global_number
17
+ @run_at_global_number += 1
18
+ end
19
+
20
+ def reset_run_at_global_number
21
+ @run_at_global_number = nil
22
+ end
23
+
24
+ def run_at_number(object, run_at)
25
+ OBJECT_RUN_AT[[object,run_at]]
26
+ end
27
+
28
+ def init_run_at_number(object, run_at)
29
+ OBJECT_RUN_AT[[object,run_at]] = 1
30
+ end
31
+
32
+ def increment_run_at_number(object, run_at)
33
+ OBJECT_RUN_AT[[object,run_at]] += 1
34
+ end
35
+
36
+ def reset_run_at_number(object, run_at)
37
+ OBJECT_RUN_AT.delete([object, run_at])
38
+ end
39
+
40
+ def reset_run_at_numbers
41
+ OBJECT_RUN_AT.clear
42
+ end
43
+
44
+ def run_number(object, run_at)
45
+ run_at_global_number || run_at_number(object, run_at)
46
+ end
47
+
48
+ def run_pd?(object, run_at)
49
+ run_pd = false
50
+ if run_at.nil?
51
+ run_pd = true
52
+ else
53
+ run_number = determine_run_number(object, run_at)
54
+ run_pd = determine_run_pd(run_at, run_number)
55
+ end
56
+ run_pd
57
+ end
58
+
59
+ def determine_run_number(object, run_at)
60
+ if PutsDebuggerer.run_at? # check if global option is set
61
+ determine_global_run_number
62
+ else
63
+ determine_local_run_number(object, run_at)
64
+ end
65
+ end
66
+
67
+ def determine_global_run_number
68
+ if PutsDebuggerer::RunDeterminer.run_at_global_number.nil?
69
+ PutsDebuggerer::RunDeterminer.init_run_at_global_number
70
+ else
71
+ PutsDebuggerer::RunDeterminer.increment_run_at_global_number
72
+ end
73
+ PutsDebuggerer::RunDeterminer.run_at_global_number
74
+ end
75
+
76
+ def determine_local_run_number(object, run_at)
77
+ if PutsDebuggerer::RunDeterminer.run_at_number(object, run_at).nil?
78
+ PutsDebuggerer::RunDeterminer.init_run_at_number(object, run_at)
79
+ else
80
+ PutsDebuggerer::RunDeterminer.increment_run_at_number(object, run_at)
81
+ end
82
+ PutsDebuggerer::RunDeterminer.run_at_number(object, run_at)
83
+ end
84
+
85
+ def determine_run_pd(run_at, run_number)
86
+ if run_at.is_a?(Integer)
87
+ determine_run_pd_integer(run_at, run_number)
88
+ elsif run_at.is_a?(Array)
89
+ determine_run_pd_array(run_at, run_number)
90
+ elsif run_at.is_a?(Range)
91
+ determine_run_pd_range(run_at, run_number)
92
+ end
93
+ end
94
+
95
+ def determine_run_pd_integer(run_at, run_number)
96
+ run_pd = true if run_at == run_number
97
+ end
98
+
99
+ def determine_run_pd_array(run_at, run_number)
100
+ run_pd = true if run_at.include?(run_number)
101
+ end
102
+
103
+ def determine_run_pd_range(run_at, run_number)
104
+ run_pd = true if run_at.cover?(run_number) || (run_at.end == -1 && run_number >= run_at.begin)
105
+ end
106
+
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,31 @@
1
+ module PutsDebuggerer
2
+ class SourceFile
3
+ def initialize(file_path)
4
+ @file = File.new(file_path)
5
+ end
6
+
7
+ def source(source_line_count, source_line_number)
8
+ @source = ''
9
+ # For Opal Ruby compatibility, skip source lines if file does not respond to readline (as in Opal)
10
+ lines = source_lines(source_line_count, source_line_number)
11
+ @source = lines.join(' '*5) if @file.respond_to?(:readline)
12
+ @source
13
+ end
14
+
15
+ def source_lines(source_line_count, source_line_number)
16
+ lines = []
17
+ begin
18
+ while @file.lineno < source_line_number + source_line_count
19
+ file_line_number = @file.lineno + 1
20
+ file_line = @file.readline
21
+ if file_line_number >= source_line_number && file_line_number < source_line_number + source_line_count
22
+ lines << file_line
23
+ end
24
+ end
25
+ rescue EOFError
26
+ # Done
27
+ end
28
+ lines
29
+ end
30
+ end
31
+ end
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.9.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Maleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-24 00:00:00.000000000 Z
11
+ date: 2020-08-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: awesome_print
@@ -150,6 +150,20 @@ dependencies:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
152
  version: 0.3.4
153
+ - !ruby/object:Gem::Dependency
154
+ name: logging
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: 2.3.0
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: 2.3.0
153
167
  description: |
154
168
  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
169
  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.
@@ -166,7 +180,11 @@ files:
166
180
  - LICENSE.txt
167
181
  - README.md
168
182
  - VERSION
183
+ - lib/pd.rb
169
184
  - lib/puts_debuggerer.rb
185
+ - lib/puts_debuggerer/core_ext/kernel.rb
186
+ - lib/puts_debuggerer/run_determiner.rb
187
+ - lib/puts_debuggerer/source_file.rb
170
188
  homepage: http://github.com/AndyObtiva/puts_debuggerer
171
189
  licenses:
172
190
  - MIT
@@ -186,7 +204,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
186
204
  - !ruby/object:Gem::Version
187
205
  version: '0'
188
206
  requirements: []
189
- rubygems_version: 3.1.2
207
+ rubygems_version: 3.1.4
190
208
  signing_key:
191
209
  specification_version: 4
192
210
  summary: Ruby library for improved puts debugging, automatically displaying bonus