byebug 11.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +897 -0
  3. data/CONTRIBUTING.md +58 -0
  4. data/GUIDE.md +1806 -0
  5. data/LICENSE +23 -0
  6. data/README.md +199 -0
  7. data/exe/byebug +6 -0
  8. data/ext/byebug/breakpoint.c +517 -0
  9. data/ext/byebug/byebug.c +905 -0
  10. data/ext/byebug/byebug.h +143 -0
  11. data/ext/byebug/context.c +673 -0
  12. data/ext/byebug/extconf.rb +12 -0
  13. data/ext/byebug/locker.c +96 -0
  14. data/ext/byebug/threads.c +230 -0
  15. data/lib/byebug.rb +3 -0
  16. data/lib/byebug/attacher.rb +48 -0
  17. data/lib/byebug/breakpoint.rb +111 -0
  18. data/lib/byebug/command.rb +111 -0
  19. data/lib/byebug/command_list.rb +34 -0
  20. data/lib/byebug/commands.rb +40 -0
  21. data/lib/byebug/commands/break.rb +112 -0
  22. data/lib/byebug/commands/catch.rb +78 -0
  23. data/lib/byebug/commands/condition.rb +55 -0
  24. data/lib/byebug/commands/continue.rb +68 -0
  25. data/lib/byebug/commands/debug.rb +38 -0
  26. data/lib/byebug/commands/delete.rb +55 -0
  27. data/lib/byebug/commands/disable.rb +33 -0
  28. data/lib/byebug/commands/disable/breakpoints.rb +42 -0
  29. data/lib/byebug/commands/disable/display.rb +43 -0
  30. data/lib/byebug/commands/display.rb +66 -0
  31. data/lib/byebug/commands/down.rb +45 -0
  32. data/lib/byebug/commands/edit.rb +69 -0
  33. data/lib/byebug/commands/enable.rb +33 -0
  34. data/lib/byebug/commands/enable/breakpoints.rb +42 -0
  35. data/lib/byebug/commands/enable/display.rb +43 -0
  36. data/lib/byebug/commands/finish.rb +57 -0
  37. data/lib/byebug/commands/frame.rb +57 -0
  38. data/lib/byebug/commands/help.rb +64 -0
  39. data/lib/byebug/commands/history.rb +39 -0
  40. data/lib/byebug/commands/info.rb +37 -0
  41. data/lib/byebug/commands/info/breakpoints.rb +65 -0
  42. data/lib/byebug/commands/info/display.rb +49 -0
  43. data/lib/byebug/commands/info/file.rb +80 -0
  44. data/lib/byebug/commands/info/line.rb +35 -0
  45. data/lib/byebug/commands/info/program.rb +49 -0
  46. data/lib/byebug/commands/interrupt.rb +34 -0
  47. data/lib/byebug/commands/irb.rb +50 -0
  48. data/lib/byebug/commands/kill.rb +45 -0
  49. data/lib/byebug/commands/list.rb +159 -0
  50. data/lib/byebug/commands/method.rb +53 -0
  51. data/lib/byebug/commands/next.rb +40 -0
  52. data/lib/byebug/commands/pry.rb +41 -0
  53. data/lib/byebug/commands/quit.rb +42 -0
  54. data/lib/byebug/commands/restart.rb +64 -0
  55. data/lib/byebug/commands/save.rb +72 -0
  56. data/lib/byebug/commands/set.rb +79 -0
  57. data/lib/byebug/commands/show.rb +45 -0
  58. data/lib/byebug/commands/skip.rb +85 -0
  59. data/lib/byebug/commands/source.rb +40 -0
  60. data/lib/byebug/commands/step.rb +40 -0
  61. data/lib/byebug/commands/thread.rb +34 -0
  62. data/lib/byebug/commands/thread/current.rb +37 -0
  63. data/lib/byebug/commands/thread/list.rb +43 -0
  64. data/lib/byebug/commands/thread/resume.rb +45 -0
  65. data/lib/byebug/commands/thread/stop.rb +43 -0
  66. data/lib/byebug/commands/thread/switch.rb +46 -0
  67. data/lib/byebug/commands/tracevar.rb +54 -0
  68. data/lib/byebug/commands/undisplay.rb +51 -0
  69. data/lib/byebug/commands/untracevar.rb +36 -0
  70. data/lib/byebug/commands/up.rb +45 -0
  71. data/lib/byebug/commands/var.rb +37 -0
  72. data/lib/byebug/commands/var/all.rb +41 -0
  73. data/lib/byebug/commands/var/args.rb +39 -0
  74. data/lib/byebug/commands/var/const.rb +49 -0
  75. data/lib/byebug/commands/var/global.rb +37 -0
  76. data/lib/byebug/commands/var/instance.rb +39 -0
  77. data/lib/byebug/commands/var/local.rb +39 -0
  78. data/lib/byebug/commands/where.rb +53 -0
  79. data/lib/byebug/context.rb +157 -0
  80. data/lib/byebug/core.rb +115 -0
  81. data/lib/byebug/errors.rb +29 -0
  82. data/lib/byebug/frame.rb +185 -0
  83. data/lib/byebug/helpers/bin.rb +47 -0
  84. data/lib/byebug/helpers/eval.rb +126 -0
  85. data/lib/byebug/helpers/file.rb +63 -0
  86. data/lib/byebug/helpers/frame.rb +75 -0
  87. data/lib/byebug/helpers/parse.rb +75 -0
  88. data/lib/byebug/helpers/path.rb +40 -0
  89. data/lib/byebug/helpers/reflection.rb +19 -0
  90. data/lib/byebug/helpers/string.rb +33 -0
  91. data/lib/byebug/helpers/thread.rb +67 -0
  92. data/lib/byebug/helpers/toggle.rb +62 -0
  93. data/lib/byebug/helpers/var.rb +54 -0
  94. data/lib/byebug/history.rb +130 -0
  95. data/lib/byebug/interface.rb +146 -0
  96. data/lib/byebug/interfaces/local_interface.rb +44 -0
  97. data/lib/byebug/interfaces/remote_interface.rb +50 -0
  98. data/lib/byebug/interfaces/script_interface.rb +33 -0
  99. data/lib/byebug/interfaces/test_interface.rb +67 -0
  100. data/lib/byebug/option_setter.rb +95 -0
  101. data/lib/byebug/printers/base.rb +68 -0
  102. data/lib/byebug/printers/plain.rb +44 -0
  103. data/lib/byebug/printers/texts/base.yml +115 -0
  104. data/lib/byebug/printers/texts/plain.yml +33 -0
  105. data/lib/byebug/processors/command_processor.rb +173 -0
  106. data/lib/byebug/processors/control_processor.rb +24 -0
  107. data/lib/byebug/processors/post_mortem_processor.rb +18 -0
  108. data/lib/byebug/processors/script_processor.rb +49 -0
  109. data/lib/byebug/remote.rb +85 -0
  110. data/lib/byebug/remote/client.rb +57 -0
  111. data/lib/byebug/remote/server.rb +47 -0
  112. data/lib/byebug/runner.rb +198 -0
  113. data/lib/byebug/setting.rb +79 -0
  114. data/lib/byebug/settings/autoirb.rb +29 -0
  115. data/lib/byebug/settings/autolist.rb +29 -0
  116. data/lib/byebug/settings/autopry.rb +29 -0
  117. data/lib/byebug/settings/autosave.rb +17 -0
  118. data/lib/byebug/settings/basename.rb +16 -0
  119. data/lib/byebug/settings/callstyle.rb +20 -0
  120. data/lib/byebug/settings/fullpath.rb +16 -0
  121. data/lib/byebug/settings/histfile.rb +20 -0
  122. data/lib/byebug/settings/histsize.rb +20 -0
  123. data/lib/byebug/settings/linetrace.rb +22 -0
  124. data/lib/byebug/settings/listsize.rb +21 -0
  125. data/lib/byebug/settings/post_mortem.rb +27 -0
  126. data/lib/byebug/settings/savefile.rb +20 -0
  127. data/lib/byebug/settings/stack_on_error.rb +15 -0
  128. data/lib/byebug/settings/width.rb +20 -0
  129. data/lib/byebug/source_file_formatter.rb +71 -0
  130. data/lib/byebug/subcommands.rb +54 -0
  131. data/lib/byebug/version.rb +8 -0
  132. metadata +199 -0
@@ -0,0 +1,58 @@
1
+ # CONTRIBUTING
2
+
3
+ Please note that this project is released with a [Contributor Code of
4
+ Conduct](code_of_conduct.md). By participating in this project you agree to
5
+ abide by its terms.
6
+
7
+ ## Bug Reports
8
+
9
+ * Try to reproduce the issue against the latest revision. There might be
10
+ unrealeased work that fixes your problem!
11
+ * Ensure that your issue has not already been reported.
12
+ * Include the steps you carried out to produce the problem. If we can't
13
+ reproduce it, we can't fix it.
14
+ * Include the behavior you observed along with the behavior you expected,
15
+ and why you expected it.
16
+
17
+ ## Development dependencies
18
+
19
+ * `Byebug` depends on Ruby's TracePoint API provided by `ruby-core`. This is a
20
+ young API and a lot of bugs have been recently corrected, so make sure you
21
+ always have the lastest patch level release installed.
22
+ * The recommended tool to manage development dependencies is `bundler`. Run
23
+ `gem install bundler` to install it.
24
+ * Running `bin/bundle install` inside a local clone of `byebug` will get
25
+ development dependencies installed.
26
+
27
+ ## Running the test suite
28
+
29
+ * Make sure you compile the C-extension using `bin/rake compile`.
30
+ Otherwise you won't be able to use `byebug`.
31
+ * Run the test suite using the default rake task (`bin/rake`). This task is
32
+ composed of 3 subtasks: `bin/rake compile`, `bin/rake test` & `bin/rake lint`.
33
+ * If you want to run specific tests, use the provided test runner, like so:
34
+ * Specific test files. For example, `bin/minitest test/commands/break_test.rb`
35
+ * Specific test classes. For example, `bin/minitest BreakAtLinesTest`
36
+ * Specific tests. For example,
37
+ `bin/minitest test_catch_removes_specific_catchpoint`
38
+ * Specific fully qualified tests. For example,
39
+ `bin/minitest BreakAtLinesTest#test_setting_breakpoint_sets_correct_fields`
40
+ * You can combine any of them and you will get the union of all filters. For
41
+ example: `bin/minitest BreakAtLinesTest
42
+ test_catch_removes_specific_catchpoint`
43
+
44
+ ## Code style
45
+
46
+ * Byebug uses several style checks to check code style consistent. You can run
47
+ those using `bin/rake lint`.
48
+
49
+ ## Byebug as a C-extension
50
+
51
+ Byebug is a gem developed as a C-extension. The debugger internal's
52
+ functionality is implemented in C (the interaction with the TracePoint API).
53
+ The rest of the gem is implemented in Ruby. Normally you won't need to touch
54
+ the C-extension, but it will obviously depended on the bug you're trying to fix
55
+ or the feature you are willing to add. You can learn more about C-extensions
56
+ [here](https://tenderlovemaking.com/2009/12/18/writing-ruby-c-extensions-part-1.html)
57
+ or
58
+ [here](https://tenderlovemaking.com/2010/12/11/writing-ruby-c-extensions-part-2.html).
@@ -0,0 +1,1806 @@
1
+ # GUIDE
2
+
3
+ ## Introduction
4
+
5
+ ### First Steps
6
+
7
+ A handful of commands are enough to get started using `byebug`. The following
8
+ session illustrates these commands. Take the following sample file:
9
+
10
+ ```ruby
11
+ #
12
+ # The n'th triangle number: triangle(n) = n*(n+1)/2 = 1 + 2 + ... + n
13
+ #
14
+ def triangle(n)
15
+ tri = 0
16
+
17
+ 0.upto(n) { |i| tri += i }
18
+
19
+ tri
20
+ end
21
+
22
+ t = triangle(3)
23
+ puts t
24
+
25
+ ```
26
+
27
+ Let's debug it.
28
+
29
+ ```bash
30
+ $ byebug /path/to/triangle.rb
31
+
32
+ [1, 10] in /path/to/triangle.rb
33
+ 1: #
34
+ 2: # The n'th triangle number: triangle(n) = n*(n+1)/2 = 1 + 2 + ... + n
35
+ 3: #
36
+ => 4: def triangle(n)
37
+ 5: tri = 0
38
+ 6:
39
+ 7: 0.upto(n) { |i| tri += i }
40
+ 8:
41
+ 9: tri
42
+ 10: end
43
+ (byebug)
44
+ ```
45
+
46
+ We are currently stopped before the first executable line of the program: line 4
47
+ of `triangle.rb`. If you are used to less dynamic languages and have used
48
+ debuggers for more statically compiled languages like C, C++, or Java, it may
49
+ seem odd to be stopped before a function definition but in Ruby line 4 is
50
+ executed.
51
+
52
+ Byebug's prompt is `(byebug)`. If the program has died and you are in
53
+ post-mortem debugging, `(byebug:post-mortem)` is used instead. If the program
54
+ has terminated normally and the `--no-quit` option has been specified in the
55
+ command line, the prompt will be `(byebug:ctrl)` instead. The commands available
56
+ change depending on the program's state.
57
+
58
+ Byebug automatically lists 10 lines of code centered around the current line
59
+ every time it is stopped. The current line is marked with `=>`. If the range
60
+ would overflow the beggining or the end of the file, byebug will move it
61
+ accordingly so that only actual real lines of code are displayed.
62
+
63
+ Now let us step through the program.
64
+
65
+ ```bash
66
+ (byebug) step
67
+
68
+ [5, 14] in /path/to/triangle.rb
69
+ 5: tri = 0
70
+ 6:
71
+ 7: 0.upto(n) { |i| tri += i }
72
+ 8:
73
+ 9: tri
74
+ 10: end
75
+ 11:
76
+ => 12: t = triangle(3)
77
+ 13: puts t
78
+ (byebug) <RET> # hit enter
79
+
80
+ [1, 10] in /path/to/triangle.rb
81
+ 1: #
82
+ 2: # The n'th triangle number: triangle(n) = n*(n+1)/2 = 1 + 2 + ... + n
83
+ 3: #
84
+ 4: def triangle(n)
85
+ => 5: tri = 0
86
+ 6:
87
+ 7: 0.upto(n) { |i| tri += i }
88
+ 8:
89
+ 9: tri
90
+ 10: end
91
+ (byebug) eval tri
92
+ nil
93
+ (byebug) step
94
+
95
+ [2, 11] in /path/to/triangle.rb
96
+ 2: # The n'th triangle number: triangle(n) = n*(n+1)/2 = 1 + 2 + ... + n
97
+ 3: #
98
+ 4: def triangle(n)
99
+ 5: tri = 0
100
+ 6:
101
+ => 7: 0.upto(n) { |i| tri += i }
102
+ 8:
103
+ 9: tri
104
+ 10: end
105
+ 11:
106
+ (byebug) eval tri
107
+ 0
108
+ ```
109
+
110
+ The first `step` command runs the script one executable unit. The second command
111
+ we entered was just hitting the return key: `byebug` remembers the last command
112
+ you entered was `step` and runs it again.
113
+
114
+ One way to print the values of variables is `eval` (there are other ways). When we
115
+ look at the value of `tri` the first time, we see it is `nil`. Again we are
116
+ stopped _before_ the assignment on line 5, and this variable hadn't been set
117
+ previously. However after issuing another `step` command we see that the value
118
+ is 0 as expected. If every time we stop we want to see the value of `tri` to see
119
+ how things are going, there is a better way by setting a display expression:
120
+
121
+ ```bash
122
+ (byebug) display tri
123
+ 1: tri = 0
124
+ ```
125
+
126
+ Now let us run the program until right before we return from the function. We'll
127
+ want to see which lines get run, so we turn on _line tracing_. If we don't want
128
+ whole paths to be displayed when tracing, we can turn on _basename_.
129
+
130
+ ```bash
131
+ (byebug) set linetrace
132
+ linetrace is on
133
+ (byebug) set basename
134
+ basename is on
135
+ (byebug) finish 0
136
+ Tracing: triangle.rb:7 0.upto(n) { |i| tri += i }
137
+ 1: tri = 0
138
+ Tracing: triangle.rb:7 0.upto(n) { |i| tri += i }
139
+ 1: tri = 0
140
+ Tracing: triangle.rb:7 0.upto(n) { |i| tri += i }
141
+ 1: tri = 1
142
+ Tracing: triangle.rb:7 0.upto(n) { |i| tri += i }
143
+ 1: tri = 3
144
+ Tracing: triangle.rb:9 tri
145
+ 1: tri = 6
146
+ 1: tri = 6
147
+
148
+ [4, 13] in /home/davidr/Proyectos/byebug/triangle.rb
149
+ 4: def triangle(n)
150
+ 5: tri = 0
151
+ 6:
152
+ 7: 0.upto(n) { |i| tri += i }
153
+ 8:
154
+ 9: tri
155
+ => 10: end
156
+ 11:
157
+ 12: t = triangle(3)
158
+ 13: puts t
159
+ (byebug) quit
160
+ Really quit? (y/n)
161
+ y
162
+ ```
163
+
164
+ So far, so good. As you can see from the above, to get out of `byebug`, one
165
+ can issue a `quit` command (or the abbreviation `q`). If you want to quit
166
+ without being prompted, suffix the command with an exclamation mark, e.g., `q!`.
167
+
168
+ ### Second Sample Session: Delving Deeper
169
+
170
+ In this section we'll introduce breakpoints, the call stack and restarting.
171
+ Below we will debug a simple Ruby program to solve the classic Towers of Hanoi
172
+ puzzle. It is augmented by the bane of programming: some command-parameter
173
+ processing with error checking.
174
+
175
+ ```ruby
176
+ #
177
+ # Solves the classic Towers of Hanoi puzzle.
178
+ #
179
+ def hanoi(n, a, b, c)
180
+ hanoi(n - 1, a, c, b) if n - 1 > 0
181
+
182
+ puts "Move disk #{a} to #{b}"
183
+
184
+ hanoi(n - 1, c, b, a) if n - 1 > 0
185
+ end
186
+
187
+ n_args = $ARGV.length
188
+
189
+ raise("*** Need number of disks or no parameter") if n_args > 1
190
+
191
+ n = 3
192
+
193
+ if n_args > 0
194
+ begin
195
+ n = $ARGV[0].to_i
196
+ rescue ValueError
197
+ raise("*** Expecting an integer, got: #{$ARGV[0]}")
198
+ end
199
+ end
200
+
201
+ raise("*** Number of disks should be between 1 and 100") if n < 1 || n > 100
202
+
203
+ hanoi(n, :a, :b, :c)
204
+ ```
205
+
206
+ Recall in the first section it was stated that before the `def` is run, the
207
+ method it names is undefined. Let's check that out. First let's see what
208
+ private methods we can call before running `def hanoi`.
209
+
210
+ ```bash
211
+ $ byebug path/to/hanoi.rb
212
+
213
+ 1: #
214
+ 2: # Solves the classic Towers of Hanoi puzzle.
215
+ 3: #
216
+ 4: def hanoi(n, a, b, c)
217
+ 5: hanoi(n - 1, a, c, b) if n - 1 > 0
218
+ 6:
219
+ 7: puts "Move disk #{a} to #{b}"
220
+ 8:
221
+ 9: hanoi(n - 1, c, b, a) if n - 1 > 0
222
+ 10: end
223
+ (byebug) private_methods
224
+ public
225
+ private
226
+ include
227
+ using
228
+ define_method
229
+ default_src_encoding
230
+ DelegateClass
231
+ Digest
232
+ timeout
233
+ initialize_copy
234
+ initialize_dup
235
+ initialize_clone
236
+ sprintf
237
+ format
238
+ Integer
239
+ Float
240
+ String
241
+ Array
242
+ Hash
243
+ warn
244
+ raise
245
+ fail
246
+ global_variables
247
+ __method__
248
+ __callee__
249
+ __dir__
250
+ eval
251
+ local_variables
252
+ iterator?
253
+ block_given?
254
+ catch
255
+ throw
256
+ loop
257
+ respond_to_missing?
258
+ trace_var
259
+ untrace_var
260
+ at_exit
261
+ syscall
262
+ open
263
+ printf
264
+ print
265
+ putc
266
+ puts
267
+ gets
268
+ readline
269
+ select
270
+ readlines
271
+ `
272
+ p
273
+ test
274
+ srand
275
+ rand
276
+ trap
277
+ load
278
+ require
279
+ require_relative
280
+ autoload
281
+ autoload?
282
+ proc
283
+ lambda
284
+ binding
285
+ caller
286
+ caller_locations
287
+ exec
288
+ fork
289
+ exit!
290
+ system
291
+ spawn
292
+ sleep
293
+ exit
294
+ abort
295
+ Rational
296
+ Complex
297
+ set_trace_func
298
+ gem_original_require
299
+ Pathname
300
+ pp
301
+ y
302
+ URI
303
+ rubygems_require
304
+ initialize
305
+ singleton_method_added
306
+ singleton_method_removed
307
+ singleton_method_undefined
308
+ method_missing
309
+ (byebug) private_methods.member?(:hanoi)
310
+ false
311
+ ```
312
+
313
+ `private_methods` is not a byebug command but a Ruby feature. By default, when
314
+ `byebug` doesn't understand a command, it will evaluate it as if it was a Ruby
315
+ command. You can use any Ruby to inspect your program's state at the place it
316
+ is stopped.
317
+
318
+ Now let's see what happens after stepping:
319
+
320
+ ```bash
321
+ (byebug) step
322
+
323
+ [5, 14] in /path/to/hanoi.rb
324
+ 5: hanoi(n - 1, a, c, b) if n - 1 > 0
325
+ 6:
326
+ 7: puts "Move disk #{a} to #{b}"
327
+ 8:
328
+ 9: hanoi(n - 1, c, b, a) if n - 1 > 0
329
+ 10: end
330
+ 11:
331
+ => 12: n_args = $ARGV.length
332
+ 13:
333
+ 14: raise("*** Need number of disks or no parameter") if n_args > 1
334
+ (byebug) private_methods.member?(:hanoi)
335
+ true
336
+ (byebug)
337
+ ```
338
+
339
+ Okay, lets go on and talk about program arguments.
340
+
341
+ ```bash
342
+ (byebug) $ARGV
343
+ []
344
+ ```
345
+
346
+ Oops. We forgot to specify any parameters to this program. Let's try again. We
347
+ can use the `restart` command here.
348
+
349
+ ```bash
350
+ (byebug) restart 3
351
+ Re exec'ing:
352
+ /path/to/exe/byebug /path/to/hanoi.rb 3
353
+
354
+ [1, 10] in /path/to/hanoi.rb
355
+ 1: #
356
+ 2: # Solves the classic Towers of Hanoi puzzle.
357
+ 3: #
358
+ => 4: def hanoi(n, a, b, c)
359
+ 5: hanoi(n - 1, a, c, b) if n - 1 > 0
360
+ 6:
361
+ 7: puts "Move disk #{a} to #{b}"
362
+ 8:
363
+ 9: hanoi(n - 1, c, b, a) if n - 1 > 0
364
+ 10: end
365
+ (byebug) break 5
366
+ Created breakpoint 1 at /path/to/hanoi.rb:5
367
+ (byebug) continue
368
+ Stopped by breakpoint 1 at /path/to/hanoi.rb:5
369
+
370
+ [1, 10] in /path/to/hanoi.rb
371
+ 1: #
372
+ 2: # Solves the classic Towers of Hanoi puzzle.
373
+ 3: #
374
+ 4: def hanoi(n, a, b, c)
375
+ => 5: hanoi(n - 1, a, c, b) if n - 1 > 0
376
+ 6:
377
+ 7: puts "Move disk #{a} to #{b}"
378
+ 8:
379
+ 9: hanoi(n - 1, c, b, a) if n - 1 > 0
380
+ 10: end
381
+ (byebug) display n
382
+ 1: n = 3
383
+ (byebug) display a
384
+ 2: a = :a
385
+ (byebug) display b
386
+ 3: b = :b
387
+ (byebug) undisplay 3
388
+ (byebug) continue
389
+ Stopped by breakpoint 1 at /path/to/hanoi.rb:5
390
+ 1: n = 2
391
+ 2: a = :a
392
+ [1, 10] in /path/to/hanoi.rb
393
+ 1: #
394
+ 2: # Solves the classic Towers of Hanoi puzzle.
395
+ 3: #
396
+ 4: def hanoi(n, a, b, c)
397
+ => 5: hanoi(n - 1, a, c, b) if n - 1 > 0
398
+ 6:
399
+ 7: puts "Move disk #{a} to #{b}"
400
+ 8:
401
+ 9: hanoi(n - 1, c, b, a) if n - 1 > 0
402
+ 10: end
403
+
404
+ (byebug) c
405
+ Stopped by breakpoint 1 at /path/to/hanoi.rb:5
406
+ 1: n = 1
407
+ 2: a = :a
408
+
409
+ [1, 10] in /path/to/hanoi.rb
410
+ 1: #
411
+ 2: # Solves the classic Towers of Hanoi puzzle.
412
+ 3: #
413
+ 4: def hanoi(n, a, b, c)
414
+ => 5: hanoi(n - 1, a, c, b) if n - 1 > 0
415
+ 6:
416
+ 7: puts "Move disk #{a} to #{b}"
417
+ 8:
418
+ 9: hanoi(n - 1, c, b, a) if n - 1 > 0
419
+ 10: end
420
+ (byebug) set nofullpath
421
+ fullpath is off
422
+ (byebug) where
423
+ --> #0 Object.hanoi(n#Fixnum, a#Symbol, b#Symbol, c#Symbol) at .../shortpath/to/hanoi.rb:5
424
+ #1 Object.hanoi(n#Fixnum, a#Symbol, b#Symbol, c#Symbol) at .../shortpath/to/hanoi.rb:5
425
+ #2 <top (required)> at .../Proyectos/byebug/hanoi.rb:28
426
+ (byebug)
427
+ ```
428
+
429
+ In the above we added new commands: `break` (see [breakpoints]()), which
430
+ indicates to stop just before that line of code is run, and `continue`, which
431
+ resumes execution. To remove a display expression `undisplay` is used. If we
432
+ give a display number, just that display expression is removed.
433
+
434
+ We also used a new command `where`(see [backtrace]()) to show the callstack. In
435
+ the above situation, starting from the bottom line we see we called the `hanoi`
436
+ method from line 28 of the file `hanoi.rb` and the `hanoi` method called itself
437
+ two more times at line 5.
438
+
439
+ In the callstack we show a _current frame_ mark, the frame number, the method
440
+ being called, the names of the parameters, the types those parameters
441
+ _currently_ have and the file-line position. Remember it's possible that when
442
+ the program was called the parameters had different types, since the types of
443
+ variables can change dynamically. You can alter the style of what to show in the
444
+ trace (see [callstyle]()).
445
+
446
+ Now let's move around the callstack.
447
+
448
+ ```bash
449
+ (byebug) undisplay
450
+ Clear all expressions? (y/n) y
451
+ (byebug) n_args
452
+ NameError Exception: undefined local variable or method `n_args' for main:Object
453
+ (byebug) frame 2
454
+
455
+ [19, 28] in /path/to/hanoi.rb
456
+ 19: begin
457
+ 20: n = $ARGV[0].to_i
458
+ 21: rescue ValueError
459
+ 22: raise("*** Expecting an integer, got: #{$ARGV[0]}")
460
+ 23: end
461
+ 24: end
462
+ 25:
463
+ 26: raise("*** Number of disks should be between 1 and 100") if n < 1 || n > 100
464
+ 27:
465
+ => 28: hanoi(n, :a, :b, :c)
466
+ (byebug) n_args
467
+ 1
468
+ (byebug) eval n
469
+ 3
470
+ (byebug) down 2
471
+
472
+ [1, 10] in /path/to/hanoi.rb
473
+ 1: #
474
+ 2: # Solves the classic Towers of Hanoi puzzle.
475
+ 3: #
476
+ 4: def hanoi(n, a, b, c)
477
+ => 5: hanoi(n - 1, a, c, b) if n - 1 > 0
478
+ 6:
479
+ 7: puts "Move disk #{a} to #{b}"
480
+ 8:
481
+ 9: hanoi(n - 1, c, b, a) if n - 1 > 0
482
+ 10: end
483
+ (byebug) eval n
484
+ 2
485
+ ```
486
+
487
+ Notice in the above to get the value of variable `n` we had to use a print
488
+ command like `eval n`. If we entered just `n`, that would be taken to mean byebug
489
+ command `next`. In the current scope, variable `n_args` is not defined. However
490
+ I can change to the top-most frame by using the `frame 2` command. Notice that
491
+ inside frame #2, the value of `n_args` can be shown. Also note that the value of
492
+ variable `n` is different.
493
+
494
+ ### Attaching to a running program with `byebug`
495
+
496
+ In the previous sessions we've been calling byebug right at the outset, but
497
+ there is another mode of operation you might use. If there's a lot of code that
498
+ needs to be run before the part you want to inspect, it might not be efficient
499
+ or convenient to run byebug from the outset.
500
+
501
+ In this section we'll show how to enter the code in the middle of your program,
502
+ while delving more into byebug's operation. We will also use unit testing. Using
503
+ unit tests will greatly reduce the amount of debugging needed, while at the same
504
+ time, will increase the quality of your program.
505
+
506
+ What we'll do is take the `triangle` code from the first session and write a
507
+ unit test for that. In a sense we did write a tiny test for the program which
508
+ was basically the last line where we printed the value of `triangle(3)`. This
509
+ test however wasn't automated: the expectation is that someone would look at the
510
+ output and verify that what was printed is what was expected.
511
+
512
+ Before we can turn that into something that can be `required`, we probably want
513
+ to remove that output. However I like to keep in that line so that when I
514
+ look at the file, I have an example of how to run it. Therefore we will
515
+ conditionally run this line if that file is invoked directly, but skip it if it
516
+ is not. _NOTE: `byebug` resets `$0` to try to make things like this work._
517
+
518
+ ```ruby
519
+ if __FILE__ == $PROGRAM_NAME
520
+ t = triangle(3)
521
+ puts t
522
+ end
523
+ ```
524
+
525
+ Okay, we're now ready to write our unit test and we'll use the `minitest`
526
+ framework for that. Here's the test code, it should be placed in the same
527
+ directory as `triangle.rb`.
528
+
529
+ ```ruby
530
+ require "minitest/autorun"
531
+ require_relative "triangle.rb"
532
+
533
+ class TestTriangle < Minitest::Test
534
+ def test_basic
535
+ solutions = []
536
+
537
+ 0.upto(5) { |i| solutions << triangle(i) }
538
+
539
+ assert_equal([0, 1, 3, 6, 10, 15], solutions, "First 5 triangle numbers")
540
+ end
541
+ end
542
+ ```
543
+
544
+ Let's say we want to stop before the first statement in our test method, we'll
545
+ add the following:
546
+
547
+ ```ruby
548
+ ...
549
+ def test_basic
550
+ byebug
551
+ solutions = []
552
+ ...
553
+ ```
554
+
555
+ Now we run the program, requiring `byebug`
556
+
557
+ ```bash
558
+ $ ruby -rbyebug test_triangle.rb
559
+ Run options: --seed 31679
560
+
561
+ # Running:
562
+
563
+ [2, 11] in test_triangle.rb
564
+ 2: require_relative "triangle.rb"
565
+ 3:
566
+ 4: class TestTriangle < Minitest::Test
567
+ 5: def test_basic
568
+ 6: byebug
569
+ => 7: solutions = []
570
+ 8:
571
+ 9: 0.upto(5) { |i| solutions << triangle(i) }
572
+ 10:
573
+ 11: assert_equal([0, 1, 3, 6, 10, 15], solutions, "First 5 triangle numbers")
574
+ (byebug)
575
+ ```
576
+
577
+ and we see that we are stopped at line 7 just before the initialization of the
578
+ list `solutions`.
579
+
580
+ Now let's see where we are...
581
+
582
+ ```bash
583
+ (byebug) set nofullpath
584
+ Displaying frame's full file names is off.
585
+ (byebug) bt
586
+ --> #0 TestTriangle.test_basic at .../Proyectos/byebug/test_triangle.rb:7
587
+ #1 block (3 levels) in Minitest::Test.run at .../lib/minitest/test.rb:108
588
+ #2 Minitest::Test.capture_exceptions at .../lib/minitest/test.rb:206
589
+ #3 block (2 levels) in Minitest::Test.run at .../lib/minitest/test.rb:105
590
+ #4 Minitest::Test.time_it at .../lib/minitest/test.rb:258
591
+ #5 block in Minitest::Test.run at .../lib/minitest/test.rb:104
592
+ #6 #<Class:Minitest::Runnable>.on_signal(name#String, action#Proc) at .../minitest-5.5.0/lib/minitest.rb:321
593
+ #7 Minitest::Test.with_info_handler(&block#Proc) at .../lib/minitest/test.rb:278
594
+ #8 Minitest::Test.run at .../lib/minitest/test.rb:103
595
+ #9 #<Class:Minitest>.run_one_method(klass#Class, method_name#String) at .../minitest-5.5.0/lib/minitest.rb:768
596
+ #10 #<Class:Minitest::Runnable>.run_one_method(klass#Class, method_name#String, reporter#Minitest::CompositeReporter) at .../minitest-5.5.0/lib/minitest.rb:295
597
+ #11 block (2 levels) in #<Class:Minitest::Runnable>.run(reporter#Minitest::CompositeReporter, options#Hash) at .../minitest-5.5.0/lib/minitest.rb:289
598
+ ͱ-- #12 Array.each at .../minitest-5.5.0/lib/minitest.rb:288
599
+ #13 block in #<Class:Minitest::Runnable>.run(reporter#Minitest::CompositeReporter, options#Hash) at .../minitest-5.5.0/lib/minitest.rb:288
600
+ #14 #<Class:Minitest::Runnable>.on_signal(name#String, action#Proc) at .../minitest-5.5.0/lib/minitest.rb:321
601
+ #15 #<Class:Minitest::Runnable>.with_info_handler(reporter#Minitest::CompositeReporter, &block#Proc) at .../minitest-5.5.0/lib/minitest.rb:308
602
+ #16 #<Class:Minitest::Runnable>.run(reporter#Minitest::CompositeReporter, options#Hash) at .../minitest-5.5.0/lib/minitest.rb:287
603
+ #17 block in #<Class:Minitest>.__run(reporter#Minitest::CompositeReporter, options#Hash) at .../minitest-5.5.0/lib/minitest.rb:150
604
+ ͱ-- #18 Array.map at .../minitest-5.5.0/lib/minitest.rb:150
605
+ #19 #<Class:Minitest>.__run(reporter#Minitest::CompositeReporter, options#Hash) at .../minitest-5.5.0/lib/minitest.rb:150
606
+ #20 #<Class:Minitest>.run(args#Array) at .../minitest-5.5.0/lib/minitest.rb:127
607
+ #21 block in #<Class:Minitest>.autorun at .../minitest-5.5.0/lib/minitest.rb:56
608
+ (byebug)
609
+ ```
610
+
611
+ We get the same result as if we had run byebug from the outset.
612
+
613
+ ### Debugging Oddities: How debugging Ruby may be different from other languages
614
+
615
+ If you are used to debugging in other languages like C, C++, Perl, Java or even
616
+ Bash (see [bashdb](http://bashdb.sourceforge.net)), there may be a number of things that
617
+ seem or feel a little bit different and may confuse you. A number of these
618
+ things aren't oddities of the debugger per se but differences in how Ruby works
619
+ compared to those other languages. Because Ruby works a little differently from
620
+ those other languages, writing a debugger has to also be a little different as
621
+ well if it is to be useful. In this respect, using Byebug may help you
622
+ understand Ruby better.
623
+
624
+ We've already seen one such difference: the fact that we stop on method
625
+ definitions or `def`'s and that is because these are in fact executable
626
+ statements. In other compiled languages this would not happen because that's
627
+ already been done when you compile the program (or in Perl when it scans in the
628
+ program). In this section we'll consider some other things that might throw off
629
+ new users to Ruby who are familiar with other languages and debugging in them.
630
+
631
+ #### Bouncing Around in Blocks (iterators)
632
+
633
+ When debugging languages with coroutines like Python and Ruby, a method call may
634
+ not necessarily go to the first statement after the method header. It's possible
635
+ that the call will continue after a `yield` statement from a prior call.
636
+
637
+ ```ruby
638
+ #
639
+ # Enumerator for primes
640
+ #
641
+ class SievePrime
642
+ def initialize
643
+ @odd_primes = []
644
+ end
645
+
646
+ def next_prime
647
+ candidate = 2
648
+ yield candidate
649
+ not_prime = false
650
+ candidate += 1
651
+
652
+ loop do
653
+ @odd_primes.each do |p|
654
+ not_prime = (0 == (candidate % p))
655
+ break if not_prime
656
+ end
657
+
658
+ unless not_prime
659
+ @odd_primes << candidate
660
+ yield candidate
661
+ end
662
+
663
+ candidate += 2
664
+ end
665
+ end
666
+ end
667
+
668
+ SievePrime.new.next_prime do |prime|
669
+ puts prime
670
+ break if prime > 10
671
+ end
672
+ ```
673
+
674
+ ```bash
675
+ $ byebug primes.rb
676
+ [1, 10] in /path/to/primes.rb
677
+ 1: #
678
+ 2: # Enumerator for primes
679
+ 3: #
680
+ => 4: class SievePrime
681
+ 5: def initialize
682
+ 6: @odd_primes = []
683
+ 7: end
684
+ 8:
685
+ 9: def self.next_prime(&block)
686
+ 10: candidate = 2
687
+ (byebug) set linetrace
688
+ line tracing is on.
689
+ (byebug) set basename
690
+ basename in on.
691
+ (byebug) step 9
692
+ Tracing: primes.rb:5 def initialize
693
+ Tracing: primes.rb:9 def next_prime
694
+ Tracing: primes.rb:31 SievePrime.new.next_prime do |prime|
695
+ Tracing: primes.rb:6 @odd_primes = []
696
+ Tracing: primes.rb:10 candidate = 2
697
+ Tracing: primes.rb:11 yield candidate
698
+ Tracing: primes.rb:32 puts prime
699
+ 2
700
+ Tracing: primes.rb:33 break if prime > 10
701
+ Tracing: primes.rb:12 not_prime = false
702
+
703
+ [7, 16] in /path/to/primes.rb
704
+ 7: end
705
+ 8:
706
+ 9: def next_prime
707
+ 10: candidate = 2
708
+ 11: yield candidate
709
+ => 12: not_prime = false
710
+ 13: candidate += 1
711
+ 14:
712
+ 15: loop do
713
+ 16: @odd_primes.each do |p|
714
+ 17: not_prime = (0 == (candidate % p))
715
+ (byebug)
716
+ ```
717
+
718
+ The loop between lines 31-34 gets interleaved between those of
719
+ `SievePrime#next_prime`, lines 9-28 above.
720
+
721
+ #### No Parameter Values in a Call Stack
722
+
723
+ In traditional debuggers, in a call stack you can generally see the names of the
724
+ parameters and the values that were passed in.
725
+
726
+ Ruby is a very dynamic language and it tries to be efficient within the confines
727
+ of the language definition. Values generally aren't taken out of a variable or
728
+ expression and pushed onto a stack. Instead a new scope is created and the
729
+ parameters are given initial values. Parameter passing is by _reference_ not by
730
+ _value_ as it is say Algol, C, or Perl. During the execution of a method,
731
+ parameter values can change (and often do). In fact even the _class_ of the
732
+ object can change.
733
+
734
+ So at present, the name of the parameter is shown. The call-style setting
735
+ ([callstyle]()) can be used to set whether the name is shown or the name and the
736
+ _current_ class of the object.
737
+
738
+ #### Lines You Can Stop At
739
+
740
+ Consider the following little Ruby program.
741
+
742
+ ```ruby
743
+ "Yes it does" =~ /
744
+ (Yes) \s+
745
+ it \s+
746
+ does
747
+ /ix
748
+ puts $1
749
+ ```
750
+
751
+ The stopping points that Ruby records are the last two lines, lines 5 and 6.
752
+
753
+ Inside `byebug` you can get a list of stoppable lines for a file using the `info
754
+ file` command.
755
+
756
+ ### Threading support
757
+
758
+ Byebug supports debugging Ruby programs making use of multiple threads.
759
+
760
+ Let's consider the following sample program:
761
+
762
+ ```ruby
763
+ class Company
764
+ def initialize(task)
765
+ @tasks, @results = Queue.new, Queue.new
766
+
767
+ @tasks.push(task)
768
+ end
769
+
770
+ def run
771
+ manager = Thread.new { manager_routine }
772
+ employee = Thread.new { employee_routine }
773
+
774
+ sleep 6
775
+
776
+ go_home(manager)
777
+ go_home(employee)
778
+ end
779
+
780
+ #
781
+ # An employee doing his thing
782
+ #
783
+ def employee_routine
784
+ loop do
785
+ if @tasks.empty?
786
+ have_a_break(0.1)
787
+ else
788
+ work_hard(@tasks.pop)
789
+ end
790
+ end
791
+ end
792
+
793
+ #
794
+ # A manager doing his thing
795
+ #
796
+ def manager_routine
797
+ loop do
798
+ if @results.empty?
799
+ have_a_break(1)
800
+ else
801
+ show_off(@results.pop)
802
+ end
803
+ end
804
+ end
805
+
806
+ private
807
+
808
+ def show_off(result)
809
+ puts result
810
+ end
811
+
812
+ def work_hard(task)
813
+ task ** task
814
+ end
815
+
816
+ def have_a_break(amount)
817
+ sleep amount
818
+ end
819
+
820
+ def go_home(person)
821
+ person.kill
822
+ end
823
+ end
824
+
825
+ Company.new(10).run
826
+ ```
827
+
828
+ The `Company` class simulates a real company. The company has a manager and an
829
+ employee represented by 2 threads: they work concurrently to achieve the
830
+ company's targets.
831
+
832
+ * The employee looks for tasks to complete. If there are tasks, it works hard to
833
+ complete them. Otherwise he has a quick break.
834
+
835
+ ```ruby
836
+ #
837
+ # An employee doing his thing
838
+ #
839
+ def employee_routine
840
+ loop do
841
+ if @tasks.empty?
842
+ have_a_break(0.1)
843
+ else
844
+ work_hard(@tasks.pop)
845
+ end
846
+ end
847
+ end
848
+ ```
849
+
850
+ * The manager, on the other hand, sits there all day and sporadically checks
851
+ whether there are any results to show off.
852
+
853
+ ```ruby
854
+ #
855
+ # A manager doing his thing
856
+ #
857
+ def manager_routine
858
+ loop do
859
+ if @results.empty?
860
+ have_a_break(1)
861
+ else
862
+ show_off(@results.pop)
863
+ end
864
+ end
865
+ end
866
+ ```
867
+
868
+ We do some abstractions easily readable in the code. Our tasks are just a
869
+ `Queue` of numbers, so are our results. What our employer does when he works is
870
+ some calculation with those numbers and what the manager does with the results
871
+ is printing them to the screen.
872
+
873
+ We instantiate a new company with an initial task and after running that
874
+ company we expect the result to be printed in the screen, but it is not. Lets
875
+ debug our sample program:
876
+
877
+ ```bash
878
+ [1, 10] in /path/to/company.rb
879
+ => 1: class Company
880
+ 2: def initialize(task)
881
+ 3: @tasks, @results = Queue.new, Queue.new
882
+ 4:
883
+ 5: @tasks.push(task)
884
+ 6: end
885
+ 7:
886
+ 8: def run
887
+ 9: manager = Thread.new { manager_routine }
888
+ 10: employee = Thread.new { employee_routine }
889
+ (byebug) l
890
+
891
+ [11, 20] in /path/to/company.rb
892
+ 11:
893
+ 12: sleep 6
894
+ 13:
895
+ 14: go_home(manager)
896
+ 15: go_home(employee)
897
+ 16: end
898
+ 17:
899
+ 18: #
900
+ 19: # An employee doing his thing
901
+ 20: #
902
+
903
+ (byebug) c 12
904
+ Stopped by breakpoint 1 at /path/to/company.rb:12
905
+
906
+ [7, 16] in /path/to/company.rb
907
+ 7:
908
+ 8: def run
909
+ 9: manager = Thread.new { manager_routine }
910
+ 10: employee = Thread.new { employee_routine }
911
+ 11:
912
+ => 12: sleep 6
913
+ 13:
914
+ 14: go_home(manager)
915
+ 15: go_home(employee)
916
+ 16: end
917
+ (byebug) th l
918
+ + 1 #<Thread:0x0000000192f328 run> /path/to/company.rb:12
919
+ 2 #<Thread:0x00000001ff9870@/path/to/company.rb:9 sleep>
920
+ 3 #<Thread:0x00000001ff80d8@/path/to/company.rb:10 sleep>
921
+ ```
922
+
923
+ What we have done here is just start our program and advance to the point
924
+ inmediately after our `employee` and `manager` threads have been created. We
925
+ can then check that the threads are there using the `thread list` command. Now
926
+ we want to debug both of this threads to check what's happening and look for the
927
+ bug.
928
+
929
+ ```bash
930
+ (byebug) th switch 3
931
+
932
+ [5, 14] in /path/to/company.rb
933
+ 5: @tasks.push(task)
934
+ 6: end
935
+ 7:
936
+ 8: def run
937
+ 9: manager = Thread.new { manager_routine }
938
+ => 10: employee = Thread.new { employee_routine }
939
+ 11:
940
+ 12: sleep 6
941
+ 13:
942
+ 14: go_home(manager)
943
+ (byebug) th stop 1; th stop 2
944
+ $ 1 #<Thread:0x00000001307310 sleep> /path/to/company.rb:12
945
+ $ 2 #<Thread:0x000000018bf438 sleep> /path/to/company.rb:9
946
+ (byebug) th l
947
+ $ 1 #<Thread:0x00000001307310 sleep> /path/to/company.rb:12
948
+ $ 2 #<Thread:0x000000018bf438@/path/to/company.rb:9 sleep> /path/to/company.rb:55
949
+ + 3 #<Thread:0x00000001ff80d8@/path/to/company.rb:10 sleep> /path/to/company.rb:10
950
+ ```
951
+
952
+ We have started by debugging the `employee` thread. To do that, we switch to
953
+ that thread using the `thread switch 3` command. The thread number is the one
954
+ specified by `thread list`, we know this is our worker thread because `thread
955
+ list` specifies where the thread is defined in the file (and its current
956
+ position if the thread is currently running).
957
+
958
+ After that we stopped the main thread and the worker thread, using the command
959
+ `thread stop`. We do this because we want to focus on the employee thread first
960
+ and don't want the program to finish while we are debugging. Notice that stopped
961
+ threads are marked with the "$" symbol whereas the current thread is marked with
962
+ the "+" symbol.
963
+
964
+ ```bash
965
+ (byebug) s
966
+
967
+ [17, 26] in /path/to/company.rb
968
+ 17:
969
+ 18: #
970
+ 19: # An employee doing his thing
971
+ 20: #
972
+ 21: def employee_routine
973
+ => 22: loop do
974
+ 23: if @tasks.empty?
975
+ 24: have_a_break(0.1)
976
+ 25: else
977
+ 26: work_hard(@tasks.pop)
978
+ (byebug) s
979
+
980
+ [18, 27] in /path/to/company.rb
981
+ 18: #
982
+ 19: # An employee doing his thing
983
+ 20: #
984
+ 21: def employee_routine
985
+ 22: loop do
986
+ => 23: if @tasks.empty?
987
+ 24: have_a_break(0.1)
988
+ 25: else
989
+ 26: work_hard(@tasks.pop)
990
+ 27: end
991
+ (byebug) n
992
+
993
+ [21, 30] in /path/to/company.rb
994
+ 21: def employee_routine
995
+ 22: loop do
996
+ 23: if @tasks.empty?
997
+ 24: have_a_break(0.1)
998
+ 25: else
999
+ => 26: work_hard(@tasks.pop)
1000
+ 27: end
1001
+ 28: end
1002
+ 29: end
1003
+ 30:
1004
+ (byebug) s
1005
+
1006
+ [49, 58] in /path/to/company.rb
1007
+ 49: def show_off(result)
1008
+ 50: puts result
1009
+ 51: end
1010
+ 52:
1011
+ 53: def work_hard(task)
1012
+ => 54: task ** task
1013
+ 55: end
1014
+ 56:
1015
+ 57: def have_a_break(amount)
1016
+ 58: sleep amount
1017
+ (byebug) s
1018
+
1019
+ [21, 30] in /path/to/company.rb
1020
+ 21: #
1021
+ 22: # An employee doing his thing
1022
+ 23: #
1023
+ 24: def employee_routine
1024
+ 25: loop do
1025
+ => 26: if @tasks.empty?
1026
+ 27: have_a_break(0.1)
1027
+ 28: else
1028
+ 29: work_hard(@tasks.pop)
1029
+ 30: end
1030
+ (byebug) n
1031
+
1032
+ [22, 31] in /path/to/company.rb
1033
+ 22: # An employee doing his thing
1034
+ 23: #
1035
+ 24: def employee_routine
1036
+ 25: loop do
1037
+ 26: if @tasks.empty?
1038
+ => 27: have_a_break(0.1)
1039
+ 28: else
1040
+ 29: work_hard(@tasks.pop)
1041
+ 30: end
1042
+ 31: end
1043
+ (byebug) n
1044
+
1045
+ [21, 30] in /path/to/company.rb
1046
+ 21: #
1047
+ 22: # An employee doing his thing
1048
+ 23: #
1049
+ 24: def employee_routine
1050
+ 25: loop do
1051
+ => 26: if @tasks.empty?
1052
+ 27: have_a_break(0.1)
1053
+ 28: else
1054
+ 29: work_hard(@tasks.pop)
1055
+ 30: end
1056
+ 31: end
1057
+ (byebug)
1058
+ ```
1059
+
1060
+ Everything seems fine in this thread. The first iteration the employee will do
1061
+ his job, and after that it will just check for new tasks and sleep. Let's debug
1062
+ the manager task now:
1063
+
1064
+ ```bash
1065
+ (byebug) th resume 2
1066
+ 2 #<Thread:0x000000019892d8@/path/to/company.rb:12 run> /path/to/company.rb:12
1067
+ (byebug) th switch 2
1068
+ 2 #<Thread:0x000000019892d8@/path/to/company.rb:12 sleep> /path/to/company.rb:12
1069
+
1070
+ [7, 16] in /path/to/company.rb
1071
+ 7:
1072
+ 8: #
1073
+ 9: # A CEO running his company
1074
+ 10: #
1075
+ 11: def run
1076
+ => 12: manager = Thread.new { manager_routine }
1077
+ 13: employee = Thread.new { employee_routine }
1078
+ 14:
1079
+ 15: sleep 6
1080
+ 16:
1081
+ (byebug)
1082
+ ```
1083
+
1084
+ We used the command `thread resume` to restart the manager's thread and then
1085
+ switch to it using `thread switch`. It's important to resume the thread's
1086
+ execution before switching to it, otherwise we'll get a hang because we cannot
1087
+ run a sleeping thread.
1088
+
1089
+ Now we can investigate the problem in the employer's side:
1090
+
1091
+ ```bash
1092
+ (byebug) s
1093
+ [30, 39] in /path/to/company.rb
1094
+ 30:
1095
+ 31: #
1096
+ 32: # A manager doing his thing
1097
+ 33: #
1098
+ 34: def manager_routine
1099
+ => 35: loop do
1100
+ 36: if @results.empty?
1101
+ 37: have_a_break(1)
1102
+ 38: else
1103
+ 39: show_off(@results.pop)
1104
+ (byebug) s
1105
+
1106
+ [31, 40] in /path/to/company.rb
1107
+ 31: #
1108
+ 32: # A manager doing his thing
1109
+ 33: #
1110
+ 34: def manager_routine
1111
+ 35: loop do
1112
+ => 36: if @results.empty?
1113
+ 37: have_a_break(1)
1114
+ 38: else
1115
+ 39: show_off(@results.pop)
1116
+ 40: end
1117
+ (byebug) n
1118
+
1119
+ [32, 41] in /path/to/company.rb
1120
+ 32: # A manager doing his thing
1121
+ 33: #
1122
+ 34: def manager_routine
1123
+ 35: loop do
1124
+ 36: if @results.empty?
1125
+ => 37: have_a_break(1)
1126
+ 38: else
1127
+ 39: show_off(@results.pop)
1128
+ 40: end
1129
+ 41: end
1130
+ (byebug) n
1131
+
1132
+ [31, 40] in /path/to/company.rb
1133
+ 31: #
1134
+ 32: # A manager doing his thing
1135
+ 33: #
1136
+ 34: def manager_routine
1137
+ 35: loop do
1138
+ => 36: if @results.empty?
1139
+ 37: have_a_break(1)
1140
+ 38: else
1141
+ 39: show_off(@results.pop)
1142
+ 40: end
1143
+ (byebug)
1144
+ ```
1145
+
1146
+ Now we can see the problem, the `@results` variable is always empty! The
1147
+ employee forgot to leave the results in his manager's deck. We fix it by
1148
+ changing the line
1149
+
1150
+ ```ruby
1151
+ work_hard(@tasks.pop)
1152
+ ```
1153
+
1154
+ in the `employee_routine` method with the line
1155
+
1156
+ ```ruby
1157
+ @results << work_hard(@tasks.pop)
1158
+ ```
1159
+
1160
+ To be continued...
1161
+
1162
+ * More complex examples with objects, pretty printing and irb.
1163
+ * Line tracing and non-interactive tracing.
1164
+ * Post-mortem debugging.
1165
+
1166
+ ## Getting in & out
1167
+
1168
+ ### Starting byebug
1169
+
1170
+ There is a wrapper script called `byebug` which basically `require`'s the gem
1171
+ then loads `byebug` before its argument (the program to be debugged) is started.
1172
+ If you don't need to pass dash options to your program, which might be confused
1173
+ with byebug options, then you don't need to add the `--`. To get a brief list of
1174
+ options and descriptions, use the `--help` option.
1175
+
1176
+ ```bash
1177
+ $ byebug --help
1178
+
1179
+ byebug 3.5.1
1180
+
1181
+ Usage: byebug [options] <script.rb> -- <script.rb parameters>
1182
+
1183
+ -d, --debug Set $DEBUG=true
1184
+ -I, --include list Add to paths to $LOAD_PATH
1185
+ -m, --[no-]post-mortem Use post-mortem mode
1186
+ -q, --[no-]quit Quit when script finishes
1187
+ -x, --[no-]rc Run byebug initialization file
1188
+ -s, --[no-]stop Stop when script is loaded
1189
+ -r, --require file Require library before script
1190
+ -R, --remote [host:]port Remote debug [host:]port
1191
+ -t, --[no-]trace Turn on line tracing
1192
+ -v, --version Print program version
1193
+ -h, --help Display this message
1194
+
1195
+ ```
1196
+
1197
+ Many options appear as a long option name, such as `--help` and a short one
1198
+ letter option name, such as `-h`. The list of options is detailed below:
1199
+
1200
+ #### -h | --help
1201
+
1202
+ It causes `byebug` to print some basic help and exit.
1203
+
1204
+ #### -v | --version
1205
+
1206
+ It causes `byebug` to print its version number and exit.
1207
+
1208
+ #### -d | --debug
1209
+
1210
+ Sets `$DEBUG` to `true`. Compatible with Ruby's flag.
1211
+
1212
+ #### -I | --include path
1213
+
1214
+ Adds `path` to load path. `path` can be a single path or a colon separated path
1215
+ list.
1216
+
1217
+ #### -m | --post-mortem
1218
+
1219
+ If your program raises an exception that isn't caught you can enter byebug for
1220
+ inspection of what went wrong. You may also want to use this option in
1221
+ conjunction with `--no-stop`. See also [Post-Mortem Debugging]().
1222
+
1223
+ #### --no-quit
1224
+
1225
+ Keep inside `byebug` after your program terminates normally.
1226
+
1227
+ #### --no-stop
1228
+
1229
+ Normally `byebug` stops before executing the first statement. If instead you
1230
+ want it to start running initially and perhaps break it later in the execution,
1231
+ use this option.
1232
+
1233
+ #### -r | --require lib
1234
+
1235
+ Requires the library before executing the script. This option is compatible
1236
+ with Ruby's.
1237
+
1238
+ #### -t | --trace
1239
+
1240
+ Turns on line tracing. Running `byebug --trace <rubyscript>.rb` is pretty much
1241
+ like running `ruby -rtracer <rubyscript>.rb`. If all you want to do however is
1242
+ get a line trace, `tracer` is most likely faster than `byebug`.
1243
+
1244
+ ```bash
1245
+ $ time byebug --trace --no-stop hanoi.rb > /dev/null
1246
+
1247
+ real 0m0.743s
1248
+ user 0m0.668s
1249
+ sys 0m0.068s
1250
+ $ time ruby -rtracer hanoi.rb > /dev/null
1251
+
1252
+ real 0m0.077s
1253
+ user 0m0.072s
1254
+ sys 0m0.004s
1255
+ ```
1256
+
1257
+ ### Byebug default options
1258
+
1259
+ Byebug has many command-line options,; it seems that some people want to set
1260
+ them differently from the defaults. For example, some people may want
1261
+ `--no-quit` to be the default behavior. One could write a wrapper script or set
1262
+ a shell alias to handle this.
1263
+
1264
+ ### Command Files
1265
+
1266
+ A command file is a file of lines that are `byebug` commands. Comments (lines
1267
+ starting with `#`) may also be included. An empty line in a command file does
1268
+ nothing; it does not mean to repeat the last command, as it would from the
1269
+ terminal.
1270
+
1271
+ When you start `byebug`, it automatically executes commands from its
1272
+ _init file_, called `.byebugrc`. During startup, `byebug` does the following:
1273
+
1274
+ * __Processes command line options and operands.__ Reads the init file in your
1275
+ current directory, if any, and then checks your home directory. The home
1276
+ directory is the directory named in the `$HOME` or `$HOMEPATH` environment
1277
+ variable. Thus, you can have more than one init file, one generic in your home
1278
+ directory, and another, specific to the program you are debugging, in the
1279
+ directory where you invoke `byebug`.
1280
+
1281
+ You can also request the execution of a command file with the `source` command
1282
+ (see [Source]()).
1283
+
1284
+ ### Quitting byebug
1285
+
1286
+ To exit `byebug`, use the `quit` command (abbreviated to `q`). Normally, if you
1287
+ are in an interactive session, this command will prompt to ask if you really
1288
+ want to quit. If you want to quit without being prompted, enter `quit
1289
+ unconditionally` (abbreviated to `q!`).
1290
+
1291
+ Another way to terminate byebug is to use the `kill` command. This does the
1292
+ more forceful `kill -9`. It can be used in cases where `quit` doesn't work (I
1293
+ haven't seen those yet).
1294
+
1295
+ ### Calling byebug from inside your program
1296
+
1297
+ Running a program from byebug adds a bit of overhead and slows it down a little.
1298
+ Furthermore, by necessity, debuggers change the operation of the program they
1299
+ are debugging. And this can lead to unexpected and unwanted differences. It has
1300
+ happened so often that the term
1301
+ [Heisenbugs](https://en.wikipedia.org/wiki/Heisenbug) was coined to describe the
1302
+ situation where using a debugger (among other possibilities) changes the
1303
+ behavior of the program so that the bug doesn't manifest itself anymore.
1304
+
1305
+ There is another way to get into byebug which adds no overhead or slowdown until
1306
+ you reach the point at which you want to start debugging. However here you must
1307
+ change the script and make an explicit call to byebug. Because byebug isn't
1308
+ involved before the first call, there is no overhead and the script will run
1309
+ at the same speed as if there were no byebug.
1310
+
1311
+ To enter byebug this way, just drop `byebug` in whichever line you want to start
1312
+ debugging at. You also have to require byebug somehow. If using bundler, it will
1313
+ take care of that for you, otherwise you can use the ruby `-r` flag or add
1314
+ `require "byebug"` in the line previous to the `byebug` call.
1315
+
1316
+ If speed is crucial, you may want to start and stop this around certain sections
1317
+ of code, using `Byebug.start` and `Byebug.stop`. Alternatively, instead of
1318
+ issuing an explicit `Byebug.stop` you can add a block to the `Byebug.start` and
1319
+ debugging is turned on for that block. If the block of code raises an uncaught
1320
+ exception that would cause the block to terminate, the `stop` will occur. See
1321
+ [Byebug.start with a block]().
1322
+
1323
+ When `byebug`is run, `.byebugrc` is read.
1324
+
1325
+ You may want to enter byebug at several points in the program where there is a
1326
+ problem you want to investigate. And since `byebug` is just a method call it's
1327
+ possible to enclose it in a conditional expression, for example
1328
+
1329
+ ```ruby
1330
+ byebug if "bar" == foo and 20 == iter_count
1331
+ ```
1332
+
1333
+ ### Restarting Byebug
1334
+
1335
+ You can restart the program using `restart [program args]`. This is a re-exec -
1336
+ all byebug state is lost. If command arguments are passed, those are used.
1337
+ Otherwise program arguments from the last invocation are used.
1338
+
1339
+ You won't be able to restart your program in all cases. First, the program
1340
+ should have been invoked at the outset rather than having been called from
1341
+ inside your program or invoked as a result of post-mortem handling.
1342
+
1343
+ Also, since this relies on the OS `exec` call, this command is available only if
1344
+ your OS supports `exec`.
1345
+
1346
+ ## Debugging remote programs
1347
+
1348
+ It is possible to set up debugging so that you can issue byebug commands from
1349
+ outside the process running the Ruby code. In fact, you might even be on a
1350
+ different computer than the one running the Ruby program.
1351
+
1352
+ To setup remote debugging, drop the following somewhere before the point in the
1353
+ program that you want to debug (In Rails, the
1354
+ `config/environments/development.rb` could be a good candidate).
1355
+
1356
+ ```ruby
1357
+ require "byebug/core"
1358
+ Byebug.wait_connection = true
1359
+ Byebug.start_server("localhost", <port>)
1360
+ ```
1361
+
1362
+ Once this piece gets executed, you can connect to the remote debugger from your
1363
+ local machine, by running: `byebug -R localhost:<port>`.
1364
+
1365
+ Next, at a place of program execution which gets run just before the code you
1366
+ want to debug, add a call to `byebug` as was done without remote execution:
1367
+
1368
+ ```ruby
1369
+ # work, work, work...
1370
+ byebug
1371
+ some ruby code # byebug will stop before this line is run
1372
+ ```
1373
+
1374
+ ## Byebug Command Reference
1375
+
1376
+ ### Command Syntax
1377
+
1378
+ Usually a command is put on a single line. There is no limit on how long it can
1379
+ be. It starts with a command name, which is followed by arguments whose meaning
1380
+ depends on the command name. For example, the command `step` accepts an
1381
+ argument which is the number of times to step, as in `step 5`. You can also use
1382
+ the `step` command with no arguments. Some commands do not allow any arguments.
1383
+
1384
+ Multiple commands can be put on a line by separating each with a semicolon `;`.
1385
+ You can disable the meaning of a semicolon to separate commands by escaping it
1386
+ with a backslash.
1387
+
1388
+ For example, you might want to enter the following code to compute the 5th
1389
+ Fibonacci number.
1390
+
1391
+ ```bash
1392
+ (byebug) fib1=0; fib2=1; 5.times {|temp| temp=fib1; fib1=fib2; fib2 += temp }
1393
+ 0
1394
+ 1
1395
+ SyntaxError Exception: /home/davidr/Proyectos/sample_app/trace.rb:1: syntax
1396
+ error, unexpected end-of-input, expecting '}'
1397
+ 5.times { |temp| temp=fib1
1398
+ ^
1399
+ nil
1400
+ 1
1401
+ SyntaxError Exception: /home/davidr/Proyectos/sample_app/trace.rb:1: syntax
1402
+ error, unexpected tSTRING_DEND, expecting end-of-input
1403
+ fib2 += temp }
1404
+ ^
1405
+ nil
1406
+ (byebug) fib1=0\; fib2=1\; 5.times {|temp| temp=fib1\; fib1=fib2\; fib2 += temp }
1407
+ 5
1408
+ (byebug) fib2
1409
+ 8
1410
+ ```
1411
+
1412
+ You might also consider using the [irb]() or [pry]() commands and then you
1413
+ won't have to escape semicolons.
1414
+
1415
+ A blank line as input (typing just `<RET>`) means to repeat the previous
1416
+ command.
1417
+
1418
+ Byebug uses readline, which handles line editing and retrieval of previous
1419
+ commands. Up arrow, for example, moves to the previous byebug command; down
1420
+ arrow moves to the next more recent command (provided you are not already at
1421
+ the last command). Command history is saved in file `.byebug_history`. A limit
1422
+ is put on the history size. You can see this with the `show history size`
1423
+ command. See [history]() for history parameters.
1424
+
1425
+ ### Command Output
1426
+
1427
+ In the command-line interface, when `byebug` is waiting for input it presents a
1428
+ prompt of the form `(byebug)`. If the program has terminated normally the prompt
1429
+ will be `(byebug:ctrl)` and in post-mortem debugging it will be
1430
+ `(byebug:post-mortem)`.
1431
+
1432
+ Whenever `byebug` gives an error message such as for an invalid command or an
1433
+ invalid location position, it will generally preface the message with `***`.
1434
+
1435
+ ### Command Help
1436
+
1437
+ Once inside `byebug` you can always ask it for information on its commands using
1438
+ the `help` command. You can use `help` (abbreviated `h`) with no arguments to
1439
+ display a short list of named classes of commands
1440
+
1441
+ ```bash
1442
+ (byebug) help
1443
+
1444
+ break -- Sets breakpoints in the source code
1445
+ catch -- Handles exception catchpoints
1446
+ condition -- Sets conditions on breakpoints
1447
+ continue -- Runs until program ends, hits a breakpoint or reaches a line
1448
+ delete -- Deletes breakpoints
1449
+ disable -- Disables breakpoints or displays
1450
+ display -- Evaluates expressions every time the debugger stops
1451
+ down -- Moves to a lower frame in the stack trace
1452
+ edit -- Edits source files
1453
+ enable -- Enables breakpoints or displays
1454
+ finish -- Runs the program until frame returns
1455
+ frame -- Moves to a frame in the call stack
1456
+ help -- Helps you using byebug
1457
+ history -- Shows byebug's history of commands
1458
+ info -- Shows several informations about the program being debugged
1459
+ interrupt -- Interrupts the program
1460
+ irb -- Starts an IRB session
1461
+ kill -- Sends a signal to the current process
1462
+ list -- Lists lines of source code
1463
+ method -- Shows methods of an object, class or module
1464
+ next -- Runs one or more lines of code
1465
+ pry -- Starts a Pry session
1466
+ quit -- Exits byebug
1467
+ restart -- Restarts the debugged program
1468
+ save -- Saves current byebug session to a file
1469
+ set -- Modifies byebug settings
1470
+ show -- Shows byebug settings
1471
+ skip -- Runs until the next breakpoint as long as it is different from the current one
1472
+ source -- Restores a previously saved byebug session
1473
+ step -- Steps into blocks or methods one or more times
1474
+ thread -- Commands to manipulate threads
1475
+ tracevar -- Enables tracing of a global variable
1476
+ undisplay -- Stops displaying all or some expressions when program stops
1477
+ untracevar -- Stops tracing a global variable
1478
+ up -- Moves to a higher frame in the stack trace
1479
+ var -- Shows variables and its values
1480
+ where -- Displays the backtrace
1481
+
1482
+ ```
1483
+
1484
+ With a command name, `help` displays information on how to use the command.
1485
+
1486
+ ```bash
1487
+ (byebug) help list
1488
+
1489
+ l[ist][[-=]][ nn-mm]
1490
+
1491
+ Lists lines of source code
1492
+
1493
+ Lists lines forward from current line or from the place where code was
1494
+ last listed. If "list-" is specified, lists backwards instead. If
1495
+ "list=" is specified, lists from current line regardless of where code
1496
+ was last listed. A line range can also be specified to list specific
1497
+ sections of code.
1498
+ (byebug)
1499
+ ```
1500
+
1501
+ A number of commands, namely `info`, `set`, `show`, `enable` and `disable`, have
1502
+ many sub-parameters or _subcommands_. When you ask for help for one of these
1503
+ commands, you will get help for all of the subcommands that command offers.
1504
+ Sometimes you may want help only on a subcommand and to do this just follow the
1505
+ command with its subcommand name. For example, `help info breakpoints`will just
1506
+ give help about the `info breakpoints` command. Furthermore it will give longer
1507
+ help than the summary information that appears when you ask for help. You don't
1508
+ need to list the full subcommand name, just enough of the letters to make that
1509
+ subcommand distinct from others will do. For example, `help info b` is the same
1510
+ as `help info breakpoints`.
1511
+
1512
+ Some examples follow.
1513
+
1514
+ ```bash
1515
+ (byebug) help info
1516
+ info[ subcommand]
1517
+
1518
+ Generic command for showing things about the program being debugged.
1519
+
1520
+ --
1521
+ List of "info" subcommands:
1522
+ --
1523
+ info args -- Argument variables of current stack frame
1524
+ info breakpoints -- Status of user-settable breakpoints
1525
+ info catch -- Exceptions that can be caught in the current stack frame
1526
+ info display -- Expressions to display when program stops
1527
+ info file -- Info about a particular file read in
1528
+ info files -- File names and timestamps of files read in
1529
+ info line -- Line number and filename of current position in source file
1530
+ info program -- Execution status of the program
1531
+ ```
1532
+
1533
+ ```bash
1534
+ (byebug) help info breakpoints
1535
+ Status of user-settable breakpoints.
1536
+ Without argument, list info about all breakpoints.
1537
+ With an integer argument, list info on that breakpoint.
1538
+ ```
1539
+
1540
+ ```bash
1541
+ (byebug) help info b
1542
+ Status of user-settable breakpoints.
1543
+ Without argument, list info about all breakpoints.
1544
+ With an integer argument, list info on that breakpoint.
1545
+ ```
1546
+
1547
+ ### Control Commands: quit, restart, source
1548
+
1549
+ #### Quit
1550
+
1551
+ To exit `byebug`, type `quit` (abbreviated to `q`). Normally, if you are in an
1552
+ interactive session, this command will prompt you to confirm you really want to
1553
+ quit. If you want to quit without being prompted, enter `quit unconditionally`
1554
+ (abbreviated to `q!`).
1555
+
1556
+ #### Restart
1557
+
1558
+ To restart the program, use the `restart|r` command. This is a re-exec - all
1559
+ `byebug` state is lost. If command arguments are passed, those are used.
1560
+ Otherwise program arguments from the last invocation are used.
1561
+
1562
+ You won't be able to restart your program in all cases. First, the program
1563
+ should have been invoked at the outset rather than having been called from
1564
+ inside your program or invoked as a result of post-mortem handling.
1565
+
1566
+ #### Source
1567
+
1568
+ You can run `byebug` commands inside a file, using the command `source <file>`.
1569
+ The lines in a command file are executed sequentially. They are not printed as
1570
+ they are executed. If there is an error, execution proceeds to the next command
1571
+ in the file. For information about command files that get run automatically on
1572
+ startup see [Command Files]().
1573
+
1574
+ ### Display Commands: display, undisplay
1575
+
1576
+ #### Display
1577
+
1578
+ If you find that you want to print the value of an expression frequently (to see
1579
+ how it changes), you might want to add it to the *automatic display list** so
1580
+ that `byebug` evaluates it each time your program stops or after a line is
1581
+ printed if line tracing is enabled. Each expression added to the list is given a
1582
+ number to identify it; to remove an expression from the list, you specify that
1583
+ number. The automatic display looks like this:
1584
+
1585
+ ```bash
1586
+ (byebug) display n
1587
+ 1: n = 3
1588
+ ```
1589
+
1590
+ This display shows item numbers, expressions and their current values. If the
1591
+ expression is undefined or illegal the expression will be printed but no value
1592
+ will appear.
1593
+
1594
+ ```bash
1595
+ (byebug) display undefined_variable
1596
+ 2: undefined_variable =
1597
+ (byebug) display 1/0
1598
+ 3: 1/0 =
1599
+ ```
1600
+
1601
+ If you use `display` with no argument, `byebug` will display the current values
1602
+ of the expressions in the list, just as it is done when your program stops.
1603
+ Using `info display` has the same effect.
1604
+
1605
+ #### Undisplay
1606
+
1607
+ To remove an item from the list, use `undisplay` followed by the number
1608
+ identifying the expression you want to remove. `undisplay` does not repeat if
1609
+ you press `<RET>`after using it (otherwise you would just get the error _No
1610
+ display number n_)
1611
+
1612
+ You can also temporarily disable or enable display expressions, so that the will
1613
+ not be printed but they won't be forgotten either, so you can toggle them again
1614
+ later. To do that, use `disable display` or `enable display` followed by the
1615
+ expression number.
1616
+
1617
+ ### Evaluation of expressions: irb, pry
1618
+
1619
+ To examine and change data in your script you can just evaluate any Ruby code
1620
+ from `byebug`'s prompt. Any input that is not recognized as a command will be
1621
+ evaluated, so `byebug` essentially works as a REPL. If you want to evaluate
1622
+ something that conflicts with a `byebug` command, just use Ruby's `eval`. For
1623
+ example, if you want to print a variable called `n`, type `eval n` because
1624
+ typing just `n` will execute `byebug`'s command `next`.
1625
+
1626
+ Finally, if you need more advanced functionality from REPL's, you can enter
1627
+ `irb` or `pry` using `irb` or `pry` commands. The binding's environment will be
1628
+ set to the current state in the program. When you leave the repl and go back to
1629
+ `byebug`'s command prompt we show the file, line and text position of the
1630
+ program. If you issue a `list` without location information, the default
1631
+ location used is the current line rather than the current position that may have
1632
+ got updated via a prior `list` command.
1633
+
1634
+ ```
1635
+ $ byebug triangle.rb
1636
+ [1, 10] in /path/to/triangle.rb
1637
+ 1: # Compute the n'th triangle number, the hard way: triangle(n) == (n*(n+1))/2
1638
+ => 2: def triangle(n)
1639
+ 3: tri = 0
1640
+ 4: 0.upto(n) do |i|
1641
+ 5: tri += i
1642
+ 6: end
1643
+ 7: tri
1644
+ 8: end
1645
+ 9:
1646
+ 10: if __FILE__ == $0
1647
+ (byebug) irb
1648
+ irb(main):001:0> (0..6).inject { |sum, i| sum += i }
1649
+ => 21
1650
+ irb(main):002:0> exit
1651
+ (byebug)
1652
+ ```
1653
+
1654
+ ### Printing variables: var
1655
+
1656
+ Byebug can print many different information about variables. Such as
1657
+
1658
+ * `var const <object>`. Show the constants of `<object>`. This is basically
1659
+ listing variables and their values in `<object>.constant`.
1660
+ * `var instance <object>`. Show the instance variables of `<object>`. This is
1661
+ basically listing `<object>.instance_variables`.
1662
+ * `var instance`. Show instance_variables of `self`.
1663
+ * `var local`. Show local variables.
1664
+ * `var global`. Show global variables.
1665
+ * `var all`. Show local, global and instance and class variables of `self`.
1666
+ * `method instance <object>`. Show methods of `<object>`. Basically this is the
1667
+ same as running `<object>.instance_methods(false)`.
1668
+ * `method <class-or-module>`. Show methods of the class or module
1669
+ `<class-or-module>`. Basically this is the same as running
1670
+ `<class-or-module>.methods`.
1671
+
1672
+ ### Examining Program Source Files: list
1673
+
1674
+ `byebug` can print parts of your script's source. When your script stops,
1675
+ `byebug` spontaneously lists the source code around the line where it stopped
1676
+ that line. It does that when you change the current stack frame as well.
1677
+ Implicitly there is a default line location. Each time a list command is run
1678
+ that implicit location is updated, so that running several list commands in
1679
+ succession shows a contiguous block of program text.
1680
+
1681
+ If you don't need code context displayed every time, you can issue the `set
1682
+ noautolist` command. Now whenever you want code listed, you can explicitly issue
1683
+ the `list` command or its abbreviation `l`. Notice that when a second listing is
1684
+ displayed, we continue listing from the place we last left off. When the
1685
+ beginning or end of the file is reached, the line range to be shown is adjusted
1686
+ so "it doesn't overflow". You can set the `noautolist` option by default by
1687
+ dropping `set noautolist` in byebug's startup file `.byebugrc`.
1688
+
1689
+ If you want to set how many lines to be printed by default rather than use the
1690
+ initial number of lines, 10, use the `set listsize` command ([listsize()). To
1691
+ see the entire program in one shot, give an explicit starting and ending line
1692
+ number. You can print other portions of source files by giving explicit position
1693
+ as a parameter to the list command.
1694
+
1695
+ There are several ways to specify what part of the file you want to print. `list
1696
+ nnn` prints lines centered around line number `nnn` in the current source file.
1697
+ `l` prints more lines, following the last lines printed. `list -` prints lines
1698
+ just before the lines last printed. `list nnn-mmm` prints lines between `nnn`
1699
+ and `mmm` inclusive. `list =` prints lines centered around where the script is
1700
+ stopped. Repeating a `list` command with `RET` discards the argument, so it is
1701
+ equivalent to typing just `list`. This is more useful than listing the same
1702
+ lines again. An exception is made for an argument of `-`: that argument is
1703
+ preserved in repetition so that each repetition moves up in the source file.
1704
+
1705
+ ### Editing Source files: edit
1706
+
1707
+ To edit a source file, use the `edit` command. The editor of your choice is invoked
1708
+ with the current line set to the active line in the program. Alternatively, you can
1709
+ give a line specification to specify what part of the file you want to edit.
1710
+
1711
+ You can customize `byebug` to use any editor you want by using the `EDITOR`
1712
+ environment variable. The only restriction is that your editor (say `ex`) recognizes
1713
+ the following command-line syntax:
1714
+
1715
+ ```
1716
+ ex +nnn file
1717
+ ```
1718
+
1719
+ The optional numeric value `+nnn` specifies the line number in the file where
1720
+ you want to start editing. For example, to configure `byebug` to use the `vi` editor,
1721
+ you could use these commands with the `sh` shell:
1722
+
1723
+ ```bash
1724
+ EDITOR=/usr/bin/vi
1725
+ export EDITOR
1726
+ byebug ...
1727
+ ```
1728
+
1729
+ or in the `csh` shell,
1730
+
1731
+ ```bash
1732
+ setenv EDITOR /usr/bin/vi
1733
+ byebug ...
1734
+ ```
1735
+
1736
+ ### The stack trace
1737
+
1738
+ When your script has stopped, one thing you'll probably want to know is where
1739
+ it stopped and some idea of how it got there.
1740
+
1741
+ Each time your script calls a method or enters a block, information about this
1742
+ action is saved. This information is what we call a _stack frame_ or just a
1743
+ _frame_. The set of all frames at a certain point in the program's execution is
1744
+ called the _stack trace_ or just the _stack_. Each frame contains a line number
1745
+ and the source-file name that the line refers to. If the frame is the beginning
1746
+ of a method it also contains the method name.
1747
+
1748
+ When your script is started, the stack has only one frame, that of the `main`
1749
+ method. This is called the _initial frame_ or the _outermost frame_. Each time
1750
+ a method is called, a new frame is added to the stack trace. Each time a method
1751
+ returns, the frame for that method invocation is removed. If a method is
1752
+ recursive, there can be many frames for the same method. The frame for the
1753
+ method in which execution is actually occurring is called the _innermost
1754
+ frame_. This is the most recently created of all the stack frames that still
1755
+ exist.
1756
+
1757
+ Every time the debugger stops, one entry in the stack is selected as the
1758
+ current frame. Many byebug commands refer implicitly to the selected block. In
1759
+ particular, whenever you ask Byebug to list lines without giving a line number
1760
+ or location the value is found in the selected frame. There are special
1761
+ commands to select whichever frame you're interested in, such as `up`, `down`
1762
+ and `frame`.
1763
+
1764
+ After switching frames, when you issue a `list` command without any position
1765
+ information, the position used is the location in the frame that you just
1766
+ switched between, rather than a location that got updated via a prior `list`
1767
+ command.
1768
+
1769
+ Byebug assigns numbers to all existing stack frames, starting with zero for the
1770
+ _innermost frame_, one for the frame that called it, and so on upward. These
1771
+ numbers do not really exist in your script, they are assigned by Byebug to give
1772
+ you a way of designating stack frames in commands.
1773
+
1774
+ ### Printing the Stack: `where` command
1775
+
1776
+ The command `where`, aliased to `bt` or `backtrace` prints the call stack., It
1777
+ shows one line per frame, for many frames, starting with the place that you are
1778
+ stopped at (frame zero), followed by its caller (frame one), and on up the
1779
+ stack. Each frame is numbered and can be referred to in the `frame` command.
1780
+ The position of the current frame is marked with `-->`.
1781
+
1782
+ The are some special frames generated for methods that are implemented in C.
1783
+ One such method is `each`. They are marked differently in the call stack to
1784
+ indicate that we cannot switch to those frames. This is because they have no
1785
+ source code in Ruby, so we can not debug them using Byebug.
1786
+
1787
+ ```bash
1788
+ (byebug) where
1789
+ --> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6
1790
+ #1 at line gcd.rb:19
1791
+ ```
1792
+
1793
+ ### Selecting a frame: `up`, `down` and `frame` commands
1794
+
1795
+ * `up <n>`: Move `n` frames up the stack, towards the outermost frame (higher
1796
+ frame numbers, frames that have existed longer). `n` defaults to one.
1797
+
1798
+ * `down <n>`: Move `n` frames down the stack, towards the _innermost frame_
1799
+ (lower frame numbers, frames that were created more recently). `n` defaults to
1800
+ one.
1801
+
1802
+ * `frame <n>`: Allows you to move to an arbitrary frame. `n` is the stack frame
1803
+ number or 0 if no frame number is given. `frame 0` will show the current and
1804
+ most recent stack frame. If a negative number is given, counting is from the
1805
+ other end of the stack frame, so `frame -1` shows the least-recent, outermost
1806
+ stack frame. Without an argument, `frame` prints the current stack frame.