puts_debuggerer 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +144 -21
  3. data/lib/puts_debuggerer.rb +191 -36
  4. metadata +14 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 74eb84d4e3c40ce1f68dd0142da2e4579a7cf2a7
4
- data.tar.gz: 658504f16ce3f3522a4dba972701fb05907a5088
3
+ metadata.gz: a76ad1423ec2f3a99ddc81f5180ff557bbef1a8b
4
+ data.tar.gz: 86c7f3bec6285fa098500f7135da7b3cefd3df0f
5
5
  SHA512:
6
- metadata.gz: 25fc5da47a71afcae5d14ce8270761ddc7a637147722c778f0a18598f5b9c8a215b595c85415516e3877c6a51ba16468727d45138c024a508023a08111282a12
7
- data.tar.gz: 9617fe34c02aee117c6a3741fab8edfc6700549da37d7e582d73c02be1b769072c4c36b57c761f06c097f7ea5033d4aca108a3d0d173f8f97c8ce77ab7a2748f
6
+ metadata.gz: c9e6a0d82247b43c84370708b98629ba19da1eaef472ae0980940e04ac4b6e4a1785fbe010aa14026ce35a63de95cb14160c62d9c9b89782eb0b1276519592f7
7
+ data.tar.gz: 236fd33a65d78794613d5a0de3e26afcf784cf88c9592773eba76e9ee4ceb17020a6eb2176c6a8e793d71b05e75933a596447f00ce3d86bb468514d330e9af01
data/README.md CHANGED
@@ -1,11 +1,18 @@
1
- # puts_debuggerer v0.4.0
1
+ # puts_debuggerer v0.5.0
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
- Ruby tools for improved puts debugging, automatically displaying bonus useful information such as file, line number and source code.
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?!!
7
10
 
8
- Partially inspired by this blog post:
11
+ And thus, puts_debuggerer was born. A guilt-free puts debugger Ruby gem FTW!
12
+
13
+ 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.
14
+
15
+ Partially inspired (only partially ;) by this blog post:
9
16
  https://tenderlovemaking.com/2016/02/05/i-am-a-puts-debuggerer.html
10
17
  (Credit to Tenderlove.)
11
18
 
@@ -16,7 +23,7 @@ https://tenderlovemaking.com/2016/02/05/i-am-a-puts-debuggerer.html
16
23
  Add the following to bundler's `Gemfile`.
17
24
 
18
25
  ```ruby
19
- gem 'puts_debuggerer', '~> 0.4.0'
26
+ gem 'puts_debuggerer', '~> 0.5.0'
20
27
  ```
21
28
 
22
29
  ### Manual
@@ -24,7 +31,7 @@ gem 'puts_debuggerer', '~> 0.4.0'
24
31
  Or manually install and require library.
25
32
 
26
33
  ```bash
27
- gem install puts_debuggerer -v0.4.0
34
+ gem install puts_debuggerer -v0.5.0
28
35
  ```
29
36
 
30
37
  ```ruby
@@ -33,8 +40,8 @@ require 'puts_debuggerer'
33
40
 
34
41
  ### Usage
35
42
 
36
- Simply invoke global `pd` method anywhere and it prints file, line number,
37
- source code in addition to output (works even in IRB).
43
+ Simply invoke global `pd` method anywhere and it prints source file, line
44
+ number, and source code in addition to output (works even in IRB).
38
45
  If the argument is a literal value with no interpolation, the print out is
39
46
  simplified by not showing source code matching output.
40
47
 
@@ -46,7 +53,7 @@ Quickly locate printed lines using Find feature (e.g. CTRL+F) by looking for:
46
53
  This gives you the added benefit of easily removing your `pd` statements later
47
54
  on.
48
55
 
49
- This can easily be augmented with a print engine like `awesome_print` and
56
+ This can easily be augmented with a print engine like [awesome_print](https://github.com/awesome-print/awesome_print) and
50
57
  customized to format output differently as per options below.
51
58
 
52
59
  Happy puts_debuggerering!
@@ -64,14 +71,45 @@ Example Printout:
64
71
 
65
72
  ```bash
66
73
  [PD] /Users/User/finance_calculator_app/pd_test.rb:3
67
- > ("Show me the source of the bug: #{bug}").inspect
74
+ > pd "Show me the source of the bug: #{bug}"
68
75
  => "Show me the source of the bug: beattle"
69
76
  [PD] /Users/User/finance_calculator_app/pd_test.rb:4 "What line number am I?"
70
77
  ```
71
78
 
72
79
  ### Options
73
80
 
74
- #### `PutsDebuggerer.app_path` (default = `nil`)
81
+ Options enable more data to be displayed with puts_debuggerer, such as the caller
82
+ backtrace, header, and footer. They also allow customization of output format.
83
+
84
+ Options can be set as a global configuration or piecemeal per puts statement.
85
+
86
+ Global configuration is done via `PutsDebuggerer` module attribute writers.
87
+ On the other hand, piecemeal options can be passed to the `pd` global method as
88
+ the second argument.
89
+
90
+ Example:
91
+
92
+ ```ruby
93
+ # File Name: /Users/User/project/piecemeal.rb
94
+ data = [1, [2, 3]]
95
+ pd data, header: '>'*80, footer: '<'*80, announcer: " -<[PD]>-\n "
96
+ ```
97
+
98
+ Prints out:
99
+
100
+ ```bash
101
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
102
+ -<[PD]>-
103
+ /Users/User/project/piecemeal.rb:3
104
+ > pd data
105
+ => [1, [2, 3]]
106
+ <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
107
+ ```
108
+
109
+ Details about all the available options are included below.
110
+
111
+ #### `PutsDebuggerer.app_path`
112
+ (default = `nil`)
75
113
 
76
114
  Sets absolute application path. Makes `pd` file output relative to it.
77
115
  If [Rails](rubyonrails.org) was detected, it is automatically defaulted to `Rails.root.to_s`
@@ -88,12 +126,13 @@ Example Printout:
88
126
 
89
127
  ```bash
90
128
  [PD] pd_test.rb:4
91
- > ("Show me the source of the bug: #{bug}").inspect
129
+ > pd "Show me the source of the bug: #{bug}"
92
130
  => "Show me the source of the bug: beattle"
93
131
  [PD] pd_test.rb:5 "What line number am I?"
94
132
  ```
95
133
 
96
- #### `PutsDebuggerer.header` (default = `nil`)
134
+ #### `PutsDebuggerer.header`
135
+ (default = `'*'*80`)
97
136
 
98
137
  Header to include at the top of every print out.
99
138
  * Default value is `nil`
@@ -113,11 +152,12 @@ Prints out:
113
152
  ```bash
114
153
  ********************************************************************************
115
154
  [PD] /Users/User/example.rb:2
116
- > (x=1).inspect
155
+ > pd x=1
117
156
  => "1"
118
157
  ```
119
158
 
120
- #### `PutsDebuggerer.footer` (default = `nil`)
159
+ #### `PutsDebuggerer.footer`
160
+ (default = `'*'*80`)
121
161
 
122
162
  Footer to include at the bottom of every print out.
123
163
  * Default value is `nil`
@@ -136,17 +176,19 @@ Prints out:
136
176
 
137
177
  ```bash
138
178
  [PD] /Users/User/example.rb:2
139
- > (x=1).inspect
179
+ > pd x=1
140
180
  => "1"
141
181
  ********************************************************************************
142
182
  ```
143
183
 
144
- #### `PutsDebuggerer.print_engine` (default = `:p`)
184
+ #### `PutsDebuggerer.print_engine`
185
+ (default = `:p`)
145
186
 
146
187
  Print engine to use in object printout (e.g. `p`, `ap`, `pp`).
147
188
  It is represented by the print engine's global method name as a symbol
148
- (e.g. `:ap` for awesome_print).
189
+ (e.g. `:ap` for [awesome_print](https://github.com/awesome-print/awesome_print)).
149
190
  Defaults to Ruby's built-in `p` method identified by the symbol `:p`.
191
+ If it finds [awesome_print](https://github.com/awesome-print/awesome_print) loaded, it defaults to `ap` as `:ap` instead.
150
192
 
151
193
  Example:
152
194
 
@@ -162,7 +204,7 @@ Prints out:
162
204
 
163
205
  ```bash
164
206
  [PD] /Users/User/example.rb:5
165
- > (array).inspect
207
+ > pd array
166
208
  => [
167
209
  [0] 1,
168
210
  [1] [
@@ -172,7 +214,8 @@ Prints out:
172
214
  ]
173
215
  ```
174
216
 
175
- #### `PutsDebuggerer.announcer` (default = `"[PD]"`)
217
+ #### `PutsDebuggerer.announcer`
218
+ (default = `"[PD]"`)
176
219
 
177
220
  Announcer (e.g. `[PD]`) to announce every print out with (default: `"[PD]"`)
178
221
 
@@ -188,10 +231,89 @@ Prints out:
188
231
  ```bash
189
232
  *** PD ***
190
233
  /Users/User/example.rb:2
191
- > (x=1).inspect
234
+ > pd x=1
192
235
  => "1"
193
236
  ```
194
237
 
238
+ #### `PutsDebuggerer.formatter`
239
+ (default = `PutsDebuggerer::FORMATTER_DEFAULT`)
240
+
241
+ Formatter used in every print out
242
+ Passed a data argument with the following keys:
243
+ * :announcer (string)
244
+ * :caller (array)
245
+ * :file (string)
246
+ * :footer (string)
247
+ * :header (string)
248
+ * :line_number (string)
249
+ * :pd_expression (string)
250
+ * :object (object)
251
+ * :object_printer (proc)
252
+
253
+ NOTE: data for :object_printer is not a string, yet a proc that must
254
+ be called to output value. It is a proc as it automatically handles usage
255
+ of print_engine and encapsulates its details. In any case, data for :object
256
+ is available should one want to avoid altogether.
257
+
258
+ Example:
259
+
260
+ ```ruby
261
+ PutsDebuggerer.formatter = -> (data) {
262
+ puts "-<#{data[:announcer]}>-"
263
+ puts "HEADER: #{data[:header]}"
264
+ puts "FILE: #{data[:file]}"
265
+ puts "LINE: #{data[:line_number]}"
266
+ puts "EXPRESSION: #{data[:pd_expression]}"
267
+ print "PRINT OUT: "
268
+ data[:object_printer].call
269
+ puts "CALLER: #{data[:caller].to_a.first}"
270
+ puts "FOOTER: #{data[:footer]}"
271
+ }
272
+ pd (x=1)
273
+ ```
274
+
275
+ Prints out:
276
+
277
+ ```bash
278
+ -<[PD]>-
279
+ FILE: /Users/User/example.rb
280
+ HEADER: ********************************************************************************
281
+ LINE: 9
282
+ EXPRESSION: x=1
283
+ PRINT OUT: 1
284
+ CALLER: #/Users/User/master_examples.rb:83:in `block (3 levels) in <top (required)>'
285
+ FOOTER: ********************************************************************************
286
+ ```
287
+
288
+ #### `PutsDebuggerer.caller`
289
+ (default = nil)
290
+
291
+ Caller backtrace included at the end of every print out
292
+ Passed an argument of true/false, nil, or depth as an integer.
293
+ * true and -1 means include full caller backtrace
294
+ * false and nil means do not include caller backtrace
295
+ * depth (0-based) means include limited caller backtrace depth
296
+
297
+ Example:
298
+
299
+ ```ruby
300
+ # File Name: /Users/User/sample_app/lib/sample.rb
301
+ PutsDebuggerer.caller = 3
302
+ pd (x=1)
303
+ ```
304
+
305
+ Prints out:
306
+
307
+ ```bash
308
+ [PD] /Users/User/sample_app/lib/sample.rb:3
309
+ > pd x=1
310
+ => "1"
311
+ /Users/User/sample_app/lib/master_samples.rb:368:in \`block (3 levels) in <top (required)>\'
312
+ /Users/User/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/irb/workspace.rb:87:in \`eval\'
313
+ /Users/User/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/irb/workspace.rb:87:in \`evaluate\'
314
+ /Users/User/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/irb/context.rb:381:in \`evaluate\'
315
+ ```
316
+
195
317
  ### Bonus
196
318
 
197
319
  puts_debuggerer comes with the following bonus utility methods:
@@ -238,7 +360,8 @@ Prints out `puts __caller_source_line__`
238
360
 
239
361
  ## Release Notes
240
362
 
241
- * v0.4.0: custom print engine (e.g. ap), custom announcer, IRB support
363
+ * v0.5.0: custom formatter, caller backtrace, per-puts piecemeal options, and multi-line support
364
+ * v0.4.0: custom print engine (e.g. ap), custom announcer, and IRB support
242
365
  * v0.3.0: header/footer support, multi-line printout, improved format
243
366
  * v0.2.0: App path exclusion support, Rails root support, improved format
244
367
  * v0.1.0: File/line/expression print out
@@ -1,9 +1,20 @@
1
+ require 'ripper'
2
+
1
3
  module PutsDebuggerer
2
4
  HEADER_DEFAULT = '*'*80
3
5
  FOOTER_DEFAULT = '*'*80
4
6
  PRINT_ENGINE_DEFAULT = :p
5
7
  PRINT_ENGINE_MESSAGE_INVALID = 'print_engine must be a valid global method symbol (e.g. :p or :puts)'
6
8
  ANNOUNCER_DEFAULT = '[PD]'
9
+ FORMATTER_DEFAULT = -> (data) {
10
+ puts data[:header] if data[:header]
11
+ print "#{data[:announcer]} #{data[:file]}:#{data[:line_number]}#{__format_pd_expression__(data[:pd_expression], data[:object])} "
12
+ data[:object_printer].call
13
+ puts data[:caller].map {|l| ' ' + l} unless data[:caller].to_a.empty?
14
+ puts data[:footer] if data[:footer]
15
+ }
16
+ CALLER_DEPTH_ZERO = 4 #depth includes pd + with_options method + nested block + build_pd_data method
17
+
7
18
  class << self
8
19
  # Application root path to exclude when printing out file path
9
20
  #
@@ -16,13 +27,13 @@ module PutsDebuggerer
16
27
  # Prints out:
17
28
  #
18
29
  # [PD] lib/sample.rb:3
19
- # > (x=1).inspect
30
+ # > pd x=1
20
31
  # => "1"
21
- def app_path
22
- (@app_path || Rails.root.to_s) rescue nil
23
- end
32
+ attr_reader :app_path
24
33
 
25
- attr_writer :app_path
34
+ def app_path=(path)
35
+ @app_path = (path || Rails.root.to_s) rescue nil
36
+ end
26
37
 
27
38
  # Header to include at the top of every print out.
28
39
  # * Default value is `nil`
@@ -39,7 +50,7 @@ module PutsDebuggerer
39
50
  #
40
51
  # ********************************************************************************
41
52
  # [PD] /Users/User/example.rb:2
42
- # > (x=1).inspect
53
+ # > pd x=1
43
54
  # => "1"
44
55
  attr_reader :header
45
56
 
@@ -68,10 +79,10 @@ module PutsDebuggerer
68
79
  # PutsDebuggerer.footer = true
69
80
  # pd (x=1)
70
81
  #
71
- # Prints out
82
+ # Prints out:
72
83
  #
73
84
  # [PD] /Users/User/example.rb:2
74
- # > (x=1).inspect
85
+ # > pd x=1
75
86
  # => "1"
76
87
  # ********************************************************************************
77
88
  attr_reader :footer
@@ -94,6 +105,7 @@ module PutsDebuggerer
94
105
  # It is represented by the print engine's global method name as a symbol
95
106
  # (e.g. `:ap` for awesome_print).
96
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.
97
109
  #
98
110
  # Example:
99
111
  #
@@ -103,10 +115,10 @@ module PutsDebuggerer
103
115
  # array = [1, [2, 3]]
104
116
  # pd array
105
117
  #
106
- # Prints out
118
+ # Prints out:
107
119
  #
108
120
  # [PD] /Users/User/example.rb:5
109
- # > (array).inspect
121
+ # > pd array
110
122
  # => [
111
123
  # [0] 1,
112
124
  # [1] [
@@ -118,7 +130,7 @@ module PutsDebuggerer
118
130
 
119
131
  def print_engine=(engine)
120
132
  if engine.nil?
121
- @print_engine = PRINT_ENGINE_DEFAULT
133
+ @print_engine = method(:ap).name rescue PRINT_ENGINE_DEFAULT
122
134
  else
123
135
  @print_engine = method(engine).name rescue raise(PRINT_ENGINE_MESSAGE_INVALID)
124
136
  end
@@ -131,22 +143,130 @@ module PutsDebuggerer
131
143
  # PutsDebuggerer.announcer = "*** PD ***\n "
132
144
  # pd (x=1)
133
145
  #
134
- # Prints out
146
+ # Prints out:
135
147
  #
136
148
  # *** PD ***
137
149
  # /Users/User/example.rb:2
138
- # > (x=1).inspect
139
- # => "1"
150
+ # > pd x=1
151
+ # => 1
140
152
  attr_reader :announcer
141
153
 
142
154
  def announcer=(text)
143
155
  @announcer = text.nil? ? ANNOUNCER_DEFAULT : text
144
156
  end
157
+
158
+ # Formatter used in every print out
159
+ # Passed a data argument with the following keys:
160
+ # * :announcer (string)
161
+ # * :caller (array)
162
+ # * :file (string)
163
+ # * :footer (string)
164
+ # * :header (string)
165
+ # * :line_number (string)
166
+ # * :pd_expression (string)
167
+ # * :object (object)
168
+ # * :object_printer (proc)
169
+ #
170
+ # NOTE: data for :object_printer is not a string, yet a proc that must
171
+ # be called to output value. It is a proc as it automatically handles usage
172
+ # of print_engine and encapsulates its details. In any case, data for :object
173
+ # is available should one want to avoid altogether.
174
+ #
175
+ # Example:
176
+ #
177
+ # PutsDebuggerer.formatter = -> (data) {
178
+ # puts "-<#{data[:announcer]}>-"
179
+ # puts "HEADER: #{data[:header]}"
180
+ # puts "FILE: #{data[:file]}"
181
+ # puts "LINE: #{data[:line_number]}"
182
+ # puts "EXPRESSION: #{data[:pd_expression]}"
183
+ # print "PRINT OUT: "
184
+ # data[:object_printer].call
185
+ # puts "CALLER: #{data[:caller].to_a.first}"
186
+ # puts "FOOTER: #{data[:footer]}"
187
+ # }
188
+ # pd (x=1)
189
+ #
190
+ # Prints out:
191
+ #
192
+ # -<[PD]>-
193
+ # FILE: /Users/User/example.rb
194
+ # HEADER: ********************************************************************************
195
+ # LINE: 9
196
+ # EXPRESSION: x=1
197
+ # PRINT OUT: 1
198
+ # CALLER: #/Users/User/master_examples.rb:83:in `block (3 levels) in <top (required)>'
199
+ # FOOTER: ********************************************************************************
200
+ attr_reader :formatter
201
+
202
+ def formatter=(formatter_proc)
203
+ @formatter = formatter_proc.nil? ? FORMATTER_DEFAULT : formatter_proc
204
+ end
205
+
206
+ # Caller backtrace included at the end of every print out
207
+ # Passed an argument of true/false, nil, or depth as an integer.
208
+ # * true and -1 means include full caller backtrace
209
+ # * false and nil means do not include caller backtrace
210
+ # * depth (0-based) means include limited caller backtrace depth
211
+ #
212
+ # Example:
213
+ #
214
+ # # File Name: /Users/User/sample_app/lib/sample.rb
215
+ # PutsDebuggerer.caller = 3
216
+ # pd (x=1)
217
+ #
218
+ # Prints out:
219
+ #
220
+ # [PD] /Users/User/sample_app/lib/sample.rb:3
221
+ # > pd x=1
222
+ # => "1"
223
+ # /Users/User/sample_app/lib/master_samples.rb:368:in `block (3 levels) in <top (required)>'
224
+ # /Users/User/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/irb/workspace.rb:87:in `eval'
225
+ # /Users/User/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/irb/workspace.rb:87:in `evaluate'
226
+ # /Users/User/.rvm/rubies/ruby-2.4.0/lib/ruby/2.4.0/irb/context.rb:381:in `evaluate'
227
+ attr_reader :caller
228
+
229
+ def caller=(value)
230
+ if value.equal?(true)
231
+ @caller = -1 #needed for upper bound in pd method
232
+ else
233
+ @caller = value
234
+ end
235
+ end
236
+
237
+ def caller?
238
+ !!caller
239
+ end
240
+
241
+
242
+ # Options as a hash. Useful for reading and backing up options
243
+ def options
244
+ {
245
+ header: header,
246
+ footer: footer,
247
+ print_engine: print_engine,
248
+ app_path: app_path,
249
+ announcer: announcer,
250
+ formatter: formatter,
251
+ caller: caller
252
+ }
253
+ end
254
+
255
+ # Sets options included in hash
256
+ def options=(hash)
257
+ hash.each do |option, value|
258
+ send("#{option}=", value)
259
+ end
260
+ end
261
+
145
262
  end
146
263
  end
147
264
 
148
265
  PutsDebuggerer.print_engine = PutsDebuggerer::PRINT_ENGINE_DEFAULT
149
266
  PutsDebuggerer.announcer = PutsDebuggerer::ANNOUNCER_DEFAULT
267
+ PutsDebuggerer.formatter = PutsDebuggerer::FORMATTER_DEFAULT
268
+ PutsDebuggerer.app_path = nil
269
+ PutsDebuggerer.caller = nil
150
270
 
151
271
  # Prints object with bonus info such as file name, line number and source
152
272
  # expression. Optionally prints out header and footer.
@@ -174,22 +294,15 @@ PutsDebuggerer.announcer = PutsDebuggerer::ANNOUNCER_DEFAULT
174
294
  # Example Printout:
175
295
  #
176
296
  # [PD] /Users/User/finance_calculator_app/pd_test.rb:3
177
- # > ("Show me the source of the bug: #{bug}").inspect
297
+ # > pd "Show me the source of the bug: #{bug}"
178
298
  # => "Show me the source of the bug: beattle"
179
299
  # [PD] /Users/User/finance_calculator_app/pd_test.rb:4 "What line number am I?"
180
300
  def pd(object, options=nil)
181
- header = PutsDebuggerer.header? ? "#{PutsDebuggerer.header}\n" : ''
182
- announcer = PutsDebuggerer.announcer
183
- file = __caller_file__(1).sub(PutsDebuggerer.app_path.to_s, '')
184
- line_number = __caller_line_number__(1)
185
- pd_expression = __caller_pd_expression__(object)
186
- print "#{header}#{announcer} #{file}:#{line_number}#{pd_expression} "
187
- if options.nil? || options == {}
188
- send(PutsDebuggerer.print_engine, object)
189
- else
190
- send(PutsDebuggerer.print_engine, object, options) rescue send(PutsDebuggerer.print_engine, object)
301
+ __with_pd_options__(options) do |print_engine_options|
302
+ formatter_pd_data = __build_pd_data__(object, print_engine_options) #depth adds build method
303
+ PutsDebuggerer.formatter.call(formatter_pd_data)
191
304
  end
192
- puts PutsDebuggerer.footer if PutsDebuggerer.footer?
305
+ nil
193
306
  end
194
307
 
195
308
 
@@ -239,9 +352,15 @@ def __caller_source_line__(caller_depth=0)
239
352
  if source_file == '(irb)'
240
353
  source_line = conf.io.line(source_line_number)
241
354
  else
242
- File.open(source_file, 'r') do |f|
243
- lines = f.readlines
244
- source_line = lines[source_line_number-1]
355
+ f = File.new(source_file)
356
+ source_line = ''
357
+ done = false
358
+ f.each_line do |line|
359
+ if !done && f.lineno == source_line_number
360
+ source_line << line
361
+ done = true if Ripper.sexp_raw(source_line)
362
+ source_line_number+=1
363
+ end
245
364
  end
246
365
  end
247
366
  source_line
@@ -249,17 +368,53 @@ end
249
368
 
250
369
  private
251
370
 
252
- def __caller_pd_expression__(object)
371
+ def __with_pd_options__(options=nil)
372
+ options ||= {}
373
+ permanent_options = PutsDebuggerer.options
374
+ PutsDebuggerer.options = options.select {|option, _| PutsDebuggerer.options.keys.include?(option)}
375
+ print_engine_options = options.delete_if {|option, _| PutsDebuggerer.options.keys.include?(option)}
376
+ yield print_engine_options
377
+ PutsDebuggerer.options = permanent_options
378
+ end
379
+
380
+ def __build_pd_data__(object, print_engine_options=nil)
381
+ depth = PutsDebuggerer::CALLER_DEPTH_ZERO
382
+ pd_data = {
383
+ announcer: PutsDebuggerer.announcer,
384
+ file: __caller_file__(depth).sub(PutsDebuggerer.app_path.to_s, ''),
385
+ line_number: __caller_line_number__(depth),
386
+ pd_expression: __caller_pd_expression__(depth),
387
+ object: object,
388
+ object_printer: lambda do
389
+ if print_engine_options.to_h.empty?
390
+ send(PutsDebuggerer.print_engine, object)
391
+ else
392
+ send(PutsDebuggerer.print_engine, object, print_engine_options) rescue send(PutsDebuggerer.print_engine, object)
393
+ end
394
+ end
395
+ }
396
+ if PutsDebuggerer.caller?
397
+ start_depth = depth.to_i
398
+ caller_depth = PutsDebuggerer.caller == -1 ? -1 : (start_depth + PutsDebuggerer.caller)
399
+ pd_data[:caller] = caller[start_depth..caller_depth].to_a
400
+ end
401
+ pd_data[:header] = PutsDebuggerer.header if PutsDebuggerer.header?
402
+ pd_data[:footer] = PutsDebuggerer.footer if PutsDebuggerer.footer?
403
+ pd_data
404
+ end
405
+
406
+ def __format_pd_expression__(expression, object)
407
+ # avoid printing expression if it matches object inspection to prevent redundancy
408
+ expression == object.inspect.sub("\n$", '') ? "" : "\n > pd #{expression}\n =>"
409
+ end
410
+
411
+ def __caller_pd_expression__(depth=0)
253
412
  # Caller Source Line Depth 2 = 1 to pd method + 1 to caller
254
- source_line = __caller_source_line__(2)
413
+ source_line = __caller_source_line__(depth+1)
255
414
  source_line = __extract_pd_expression__(source_line)
256
415
  source_line = source_line.gsub(/(^'|'$)/, '"') if source_line.start_with?("'") && source_line.end_with?("'")
257
416
  source_line = source_line.gsub(/(^\(|\)$)/, '') if source_line.start_with?("(") && source_line.end_with?(")")
258
- if source_line == object.inspect.sub("\n$", '')
259
- ""
260
- else
261
- "\n > (#{source_line}).inspect\n =>"
262
- end
417
+ source_line
263
418
  end
264
419
 
265
420
  # Extracts pd source line expression.
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.0
4
+ version: 0.5.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: 2017-03-05 00:00:00.000000000 Z
11
+ date: 2017-03-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -122,8 +122,16 @@ dependencies:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
124
  version: 0.10.0
125
- description: Ruby tools for improved puts debugging, automatically displaying bonus
126
- useful information such as line number and source code
125
+ 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
+ And thus, puts_debuggerer was born. 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.)
127
135
  email: andy.am@gmail.com
128
136
  executables: []
129
137
  extensions: []
@@ -157,5 +165,6 @@ rubyforge_project:
157
165
  rubygems_version: 2.6.10
158
166
  signing_key:
159
167
  specification_version: 4
160
- summary: Ruby tools for improved puts debugging
168
+ summary: Ruby library for improved puts debugging, automatically displaying bonus
169
+ useful information such as source line number and source code.
161
170
  test_files: []