byebug 3.5.1 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +4 -1
- data/.rubocop.yml +18 -1
- data/.travis.yml +21 -1
- data/CHANGELOG.md +356 -308
- data/CONTRIBUTING.md +31 -15
- data/GUIDE.md +859 -475
- data/Gemfile +8 -10
- data/LICENSE +1 -1
- data/README.md +41 -45
- data/Rakefile +30 -28
- data/byebug.gemspec +18 -18
- data/ext/byebug/breakpoint.c +88 -75
- data/ext/byebug/byebug.c +253 -252
- data/ext/byebug/byebug.h +53 -53
- data/ext/byebug/context.c +188 -159
- data/ext/byebug/extconf.rb +9 -6
- data/ext/byebug/locker.c +53 -11
- data/ext/byebug/threads.c +137 -39
- data/lib/byebug/attacher.rb +7 -2
- data/lib/byebug/breakpoint.rb +30 -0
- data/lib/byebug/command.rb +36 -32
- data/lib/byebug/commands/break.rb +49 -48
- data/lib/byebug/commands/catch.rb +64 -0
- data/lib/byebug/commands/condition.rb +13 -9
- data/lib/byebug/commands/continue.rb +8 -4
- data/lib/byebug/commands/delete.rb +10 -4
- data/lib/byebug/commands/display.rb +33 -25
- data/lib/byebug/commands/edit.rb +18 -13
- data/lib/byebug/commands/enable_disable.rb +26 -24
- data/lib/byebug/commands/eval.rb +77 -35
- data/lib/byebug/commands/finish.rb +9 -5
- data/lib/byebug/commands/frame.rb +66 -125
- data/lib/byebug/commands/help.rb +14 -21
- data/lib/byebug/commands/history.rb +5 -1
- data/lib/byebug/commands/info.rb +41 -106
- data/lib/byebug/commands/interrupt.rb +6 -2
- data/lib/byebug/commands/irb.rb +5 -2
- data/lib/byebug/commands/kill.rb +6 -2
- data/lib/byebug/commands/list.rb +21 -14
- data/lib/byebug/commands/method.rb +17 -9
- data/lib/byebug/commands/pry.rb +13 -3
- data/lib/byebug/commands/quit.rb +10 -5
- data/lib/byebug/commands/restart.rb +12 -19
- data/lib/byebug/commands/save.rb +10 -6
- data/lib/byebug/commands/set.rb +15 -14
- data/lib/byebug/commands/show.rb +8 -8
- data/lib/byebug/commands/source.rb +14 -8
- data/lib/byebug/commands/stepping.rb +15 -29
- data/lib/byebug/commands/threads.rb +73 -49
- data/lib/byebug/commands/tracevar.rb +56 -0
- data/lib/byebug/commands/undisplay.rb +8 -4
- data/lib/byebug/commands/untracevar.rb +38 -0
- data/lib/byebug/commands/var.rb +107 -0
- data/lib/byebug/context.rb +78 -42
- data/lib/byebug/core.rb +78 -40
- data/lib/byebug/helper.rb +58 -42
- data/lib/byebug/history.rb +12 -1
- data/lib/byebug/interface.rb +91 -11
- data/lib/byebug/interfaces/local_interface.rb +12 -19
- data/lib/byebug/interfaces/remote_interface.rb +12 -15
- data/lib/byebug/interfaces/script_interface.rb +14 -18
- data/lib/byebug/interfaces/test_interface.rb +54 -0
- data/lib/byebug/printers/base.rb +64 -0
- data/lib/byebug/printers/plain.rb +53 -0
- data/lib/byebug/processor.rb +20 -1
- data/lib/byebug/processors/command_processor.rb +57 -172
- data/lib/byebug/processors/control_command_processor.rb +16 -43
- data/lib/byebug/remote.rb +13 -7
- data/lib/byebug/runner.rb +102 -54
- data/lib/byebug/setting.rb +45 -68
- data/lib/byebug/settings/autoeval.rb +2 -0
- data/lib/byebug/settings/autoirb.rb +3 -0
- data/lib/byebug/settings/autolist.rb +3 -0
- data/lib/byebug/settings/autosave.rb +2 -0
- data/lib/byebug/settings/basename.rb +2 -0
- data/lib/byebug/settings/callstyle.rb +2 -0
- data/lib/byebug/settings/fullpath.rb +2 -0
- data/lib/byebug/settings/histfile.rb +2 -0
- data/lib/byebug/settings/histsize.rb +2 -0
- data/lib/byebug/settings/linetrace.rb +2 -0
- data/lib/byebug/settings/listsize.rb +2 -0
- data/lib/byebug/settings/post_mortem.rb +7 -2
- data/lib/byebug/settings/stack_on_error.rb +2 -0
- data/lib/byebug/settings/verbose.rb +2 -0
- data/lib/byebug/settings/width.rb +2 -0
- data/lib/byebug/state.rb +12 -0
- data/lib/byebug/states/control_state.rb +26 -0
- data/lib/byebug/states/regular_state.rb +178 -0
- data/lib/byebug/version.rb +1 -1
- metadata +24 -109
- data/lib/byebug/commands/catchpoint.rb +0 -53
- data/lib/byebug/commands/reload.rb +0 -29
- data/lib/byebug/commands/trace.rb +0 -50
- data/lib/byebug/commands/variables.rb +0 -206
- data/lib/byebug/options.rb +0 -46
- data/lib/byebug/settings/autoreload.rb +0 -12
- data/lib/byebug/settings/forcestep.rb +0 -14
- data/lib/byebug/settings/testing.rb +0 -12
- data/lib/byebug/settings/tracing_plus.rb +0 -11
- data/test/commands/break_test.rb +0 -364
- data/test/commands/condition_test.rb +0 -85
- data/test/commands/continue_test.rb +0 -47
- data/test/commands/delete_test.rb +0 -26
- data/test/commands/display_test.rb +0 -37
- data/test/commands/edit_test.rb +0 -52
- data/test/commands/eval_test.rb +0 -89
- data/test/commands/finish_test.rb +0 -74
- data/test/commands/frame_test.rb +0 -223
- data/test/commands/help_test.rb +0 -66
- data/test/commands/history_test.rb +0 -61
- data/test/commands/info_test.rb +0 -238
- data/test/commands/interrupt_test.rb +0 -45
- data/test/commands/irb_test.rb +0 -28
- data/test/commands/kill_test.rb +0 -50
- data/test/commands/list_test.rb +0 -174
- data/test/commands/method_test.rb +0 -52
- data/test/commands/post_mortem_test.rb +0 -71
- data/test/commands/pry_test.rb +0 -26
- data/test/commands/quit_test.rb +0 -53
- data/test/commands/reload_test.rb +0 -39
- data/test/commands/restart_test.rb +0 -46
- data/test/commands/save_test.rb +0 -67
- data/test/commands/set_test.rb +0 -140
- data/test/commands/show_test.rb +0 -76
- data/test/commands/source_test.rb +0 -46
- data/test/commands/stepping_test.rb +0 -192
- data/test/commands/thread_test.rb +0 -164
- data/test/commands/trace_test.rb +0 -71
- data/test/commands/undisplay_test.rb +0 -75
- data/test/commands/variables_test.rb +0 -105
- data/test/debugger_alias_test.rb +0 -7
- data/test/runner_test.rb +0 -150
- data/test/support/matchers.rb +0 -65
- data/test/support/test_interface.rb +0 -59
- data/test/support/utils.rb +0 -122
- data/test/test_helper.rb +0 -58
data/CONTRIBUTING.md
CHANGED
@@ -1,20 +1,36 @@
|
|
1
|
-
|
1
|
+
## Byebug as a C-extension
|
2
2
|
|
3
|
-
|
3
|
+
Byebug is a gem developed as a C-extension. The debugger internal's
|
4
|
+
functionality is implemented in C (the interaction with the TracePoint API).
|
5
|
+
The rest of the gem is implemented in Ruby. Normally you won't need to touch
|
6
|
+
the C-extension, but it will obviously depended on the bug you're trying to fix
|
7
|
+
or the feature you are willing to add. You can learn more about C-extensions
|
8
|
+
[here](http://tenderlovemaking.com/2009/12/18/writing-ruby-c-extensions-part-1.html)
|
9
|
+
or
|
10
|
+
[here](http://tenderlovemaking.com/2010/12/11/writing-ruby-c-extensions-part-2.html).
|
4
11
|
|
5
|
-
* [Fork the project](https://help.github.com/fork-a-repo)
|
6
|
-
* Create a topic branch - `git checkout -b my_branch`
|
7
|
-
* Make sure the latest patch level of Ruby 2.0.0 or higher is installed.
|
8
|
-
* Insert awesome code - See below
|
9
|
-
* Push your branch to your forked repo - `git push origin my_branch`
|
10
|
-
* [Make a pull request](https://help.github.com/articles/using-pull-requests)
|
11
12
|
|
12
|
-
|
13
|
-
build the c-extension and then start the tests using `rake test`
|
13
|
+
## Prerequisites
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
`Byebug` depends on the TracePoint API provided by `ruby-core`. This is a young
|
16
|
+
API and a lot of bugs have been recently corrected. Without this fixes,
|
17
|
+
`byebug` will fail to work properly, so make sure you have always the last
|
18
|
+
patch level releases of Ruby installed.
|
19
19
|
|
20
|
-
|
20
|
+
|
21
|
+
## Getting started
|
22
|
+
|
23
|
+
Once you have a local clone of `byebug`, you can start digging in the source
|
24
|
+
code. First run `bundle install` to get development & test dependencies
|
25
|
+
installed. Also make sure you compile the C-extension using `bundle exec rake
|
26
|
+
compile`, otherwise you won't be able to use your local clone. You can also run
|
27
|
+
the test suite as the default rake task (`bundle exec rake`). This task is
|
28
|
+
composed of 4 subtasks:
|
29
|
+
|
30
|
+
bundle exec rake compile # compiles the C-extension
|
31
|
+
bundle exec rake test # Run the test suite
|
32
|
+
bundle exec rake rubocop # Run RuboCop's checks on the Ruby files
|
33
|
+
bundle exec rake ccop # Run `indent`'s checks on the C files
|
34
|
+
|
35
|
+
After having done this, just read the code and improve it! Your contribution is
|
36
|
+
appreciated a lot!
|
data/GUIDE.md
CHANGED
@@ -1,147 +1,160 @@
|
|
1
1
|
### First Steps
|
2
2
|
|
3
3
|
A handful of commands are enough to get started using `byebug`. The following
|
4
|
-
session illustrates these commands.
|
4
|
+
session illustrates these commands. Take the following sample file:
|
5
|
+
|
6
|
+
```ruby
|
7
|
+
#
|
8
|
+
# The n'th triangle number: triangle(n) = n*(n+1)/2 = 1 + 2 + ... + n
|
9
|
+
#
|
10
|
+
def triangle(n)
|
11
|
+
tri = 0
|
12
|
+
|
13
|
+
0.upto(n) { |i| tri += i }
|
14
|
+
|
15
|
+
tri
|
16
|
+
end
|
17
|
+
|
18
|
+
t = triangle(3)
|
19
|
+
puts t
|
5
20
|
|
6
21
|
```
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
22
|
+
|
23
|
+
Let's debug it.
|
24
|
+
|
25
|
+
```bash
|
26
|
+
$ byebug /path/to/triangle.rb
|
27
|
+
|
28
|
+
[1, 10] in /path/to/triangle.rb
|
29
|
+
1: #
|
30
|
+
2: # The n'th triangle number: triangle(n) = n*(n+1)/2 = 1 + 2 + ... + n
|
31
|
+
3: #
|
32
|
+
=> 4: def triangle(n)
|
33
|
+
5: tri = 0
|
34
|
+
6:
|
35
|
+
7: 0.upto(n) { |i| tri += i }
|
36
|
+
8:
|
37
|
+
9: tri
|
38
|
+
10: end
|
19
39
|
(byebug)
|
20
40
|
```
|
21
41
|
|
22
|
-
We are currently stopped before the first executable line of the program: line
|
42
|
+
We are currently stopped before the first executable line of the program: line 4
|
23
43
|
of `triangle.rb`. If you are used to less dynamic languages and have used
|
24
44
|
debuggers for more statically compiled languages like C, C++, or Java, it may
|
25
|
-
seem odd to be stopped before a function definition but in Ruby line
|
45
|
+
seem odd to be stopped before a function definition but in Ruby line 4 is
|
26
46
|
executed.
|
27
47
|
|
28
48
|
Byebug's prompt is `(byebug)`. If the program has died and you are in
|
29
49
|
post-mortem debugging, `(byebug:post-mortem)` is used instead. If the program
|
30
|
-
has terminated normally
|
31
|
-
|
50
|
+
has terminated normally and the `--no-quit` option has been specified in the
|
51
|
+
command line, the prompt will be `(byebug:ctrl)` instead. The commands available
|
52
|
+
change depending on the program's state.
|
32
53
|
|
33
54
|
Byebug automatically lists 10 lines of code centered around the current line
|
34
|
-
every time it is stopped. The current line is marked with
|
35
|
-
|
36
|
-
|
37
|
-
of code.
|
55
|
+
every time it is stopped. The current line is marked with `=>`. If the range
|
56
|
+
would overflow the beggining or the end of the file, byebug will move it
|
57
|
+
accordingly so that only actual real lines of code are displayed.
|
38
58
|
|
39
59
|
Now let us step through the program.
|
40
60
|
|
41
|
-
```
|
61
|
+
```bash
|
42
62
|
(byebug) step
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
63
|
+
|
64
|
+
[5, 14] in /path/to/triangle.rb
|
65
|
+
5: tri = 0
|
66
|
+
6:
|
67
|
+
7: 0.upto(n) { |i| tri += i }
|
68
|
+
9: end
|
69
|
+
10:
|
70
|
+
11: tri
|
71
|
+
12: end
|
72
|
+
13:
|
73
|
+
=> 14: triangle(3)
|
54
74
|
(byebug) <RET> # hit enter
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
75
|
+
|
76
|
+
[1, 10] in /path/to/triangle.rb
|
77
|
+
1: #
|
78
|
+
2: # The n'th triangle number: triangle(n) = n*(n+1)/2 = 1 + 2 + ... + n
|
79
|
+
3: #
|
80
|
+
4: def triangle(n)
|
81
|
+
=> 5: tri = 0
|
82
|
+
6:
|
83
|
+
7: 0.upto(n) { |i| tri += i }
|
84
|
+
8:
|
85
|
+
9: tri
|
86
|
+
10: end
|
66
87
|
(byebug) p tri
|
67
88
|
nil
|
68
89
|
(byebug) step
|
69
|
-
|
70
|
-
|
71
|
-
2:
|
72
|
-
3:
|
73
|
-
|
74
|
-
5:
|
75
|
-
6:
|
76
|
-
|
77
|
-
8:
|
78
|
-
9:
|
79
|
-
10:
|
90
|
+
|
91
|
+
[2, 11] in /path/to/triangle.rb
|
92
|
+
2: # The n'th triangle number: triangle(n) = n*(n+1)/2 = 1 + 2 + ... + n
|
93
|
+
3: #
|
94
|
+
4: def triangle(n)
|
95
|
+
5: tri = 0
|
96
|
+
6:
|
97
|
+
=> 7: 0.upto(n) { |i| tri += i }
|
98
|
+
8:
|
99
|
+
9: tri
|
100
|
+
10: end
|
101
|
+
11:
|
80
102
|
(byebug) p tri
|
81
103
|
0
|
82
104
|
```
|
83
105
|
|
84
106
|
The first `step` command runs the script one executable unit. The second command
|
85
|
-
we entered was just hitting the return key
|
86
|
-
you entered was `step` and
|
107
|
+
we entered was just hitting the return key: `byebug` remembers the last command
|
108
|
+
you entered was `step` and runs it again.
|
87
109
|
|
88
110
|
One way to print the values of variables is `p` (there are other ways). When we
|
89
111
|
look at the value of `tri` the first time, we see it is `nil`. Again we are
|
90
|
-
stopped _before_ the assignment on line
|
112
|
+
stopped _before_ the assignment on line 5, and this variable hadn't been set
|
91
113
|
previously. However after issuing another `step` command we see that the value
|
92
114
|
is 0 as expected. If every time we stop we want to see the value of `tri` to see
|
93
115
|
how things are going, there is a better way by setting a display expression:
|
94
116
|
|
95
|
-
```
|
117
|
+
```bash
|
96
118
|
(byebug) display tri
|
97
119
|
1: tri = 0
|
98
120
|
```
|
99
121
|
|
100
|
-
Now let us run the program until we return from the function. We'll
|
101
|
-
which lines get run, so we turn on _line tracing_. If we don't want
|
102
|
-
to be displayed when tracing, we can turn on _basename_.
|
122
|
+
Now let us run the program until right before we return from the function. We'll
|
123
|
+
want to see which lines get run, so we turn on _line tracing_. If we don't want
|
124
|
+
whole paths to be displayed when tracing, we can turn on _basename_.
|
103
125
|
|
104
|
-
```
|
105
|
-
(byebug)
|
106
|
-
|
107
|
-
(byebug) set
|
108
|
-
|
109
|
-
(byebug)
|
110
|
-
|
111
|
-
(byebug) finish
|
112
|
-
Tracing: triangle.rb:5 tri += i
|
126
|
+
```bash
|
127
|
+
(byebug) set linetrace
|
128
|
+
linetrace is on
|
129
|
+
(byebug) set basename
|
130
|
+
basename is on
|
131
|
+
(byebug) finish 0
|
132
|
+
Tracing: triangle.rb:7 0.upto(n) { |i| tri += i }
|
113
133
|
1: tri = 0
|
114
|
-
|
115
|
-
Tracing: triangle.rb:5 tri += i
|
134
|
+
Tracing: triangle.rb:7 0.upto(n) { |i| tri += i }
|
116
135
|
1: tri = 0
|
117
|
-
|
118
|
-
Tracing: triangle.rb:5 tri += i
|
136
|
+
Tracing: triangle.rb:7 0.upto(n) { |i| tri += i }
|
119
137
|
1: tri = 1
|
120
|
-
|
121
|
-
Tracing: triangle.rb:5 tri += i
|
138
|
+
Tracing: triangle.rb:7 0.upto(n) { |i| tri += i }
|
122
139
|
1: tri = 3
|
123
|
-
|
124
|
-
Tracing: triangle.rb:7 tri
|
140
|
+
Tracing: triangle.rb:9 tri
|
125
141
|
1: tri = 6
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
10: t = triangle(3)
|
140
|
-
=> 11: puts t
|
141
|
-
1: tri =
|
142
|
-
2: i =
|
142
|
+
1: tri = 6
|
143
|
+
|
144
|
+
[4, 13] in /home/davidr/Proyectos/byebug/triangle.rb
|
145
|
+
4: def triangle(n)
|
146
|
+
5: tri = 0
|
147
|
+
6:
|
148
|
+
7: 0.upto(n) { |i| tri += i }
|
149
|
+
8:
|
150
|
+
9: tri
|
151
|
+
=> 10: end
|
152
|
+
11:
|
153
|
+
12: t = triangle(3)
|
154
|
+
13: puts t
|
143
155
|
(byebug) quit
|
144
|
-
Really quit? (y/n)
|
156
|
+
Really quit? (y/n)
|
157
|
+
y
|
145
158
|
```
|
146
159
|
|
147
160
|
So far, so good. As you can see from the above to get out of `byebug`, one
|
@@ -157,67 +170,82 @@ Below we will debug a simple Ruby program to solve the classic Towers of Hanoi
|
|
157
170
|
puzzle. It is augmented by the bane of programming: some command-parameter
|
158
171
|
processing with error checking.
|
159
172
|
|
160
|
-
```
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
173
|
+
```ruby
|
174
|
+
#
|
175
|
+
# Solves the classic Towers of Hanoi puzzle.
|
176
|
+
#
|
177
|
+
def hanoi(n, a, b, c)
|
178
|
+
hanoi(n - 1, a, c, b) if n - 1 > 0
|
179
|
+
|
180
|
+
puts "Move disk #{a} to #{b}"
|
181
|
+
|
182
|
+
hanoi(n - 1, c, b, a) if n - 1 > 0
|
183
|
+
end
|
184
|
+
|
185
|
+
n_args = $ARGV.length
|
186
|
+
|
187
|
+
fail('*** Need number of disks or no parameter') if n_args > 1
|
174
188
|
```
|
175
189
|
|
176
190
|
Recall in the first section it was stated that before the `def` is run, the method it
|
177
191
|
names is undefined. Let's check that out. First let's see what private methods
|
178
192
|
we can call before running `def hanoi`.
|
179
193
|
|
194
|
+
|
180
195
|
```bash
|
196
|
+
$ byebug path/to/hanoi.rb
|
197
|
+
|
198
|
+
1: #
|
199
|
+
2: # Solves the classic Towers of Hanoi puzzle.
|
200
|
+
3: #
|
201
|
+
4: def hanoi(n, a, b, c)
|
202
|
+
5: hanoi(n - 1, a, c, b) if n - 1 > 0
|
203
|
+
6:
|
204
|
+
7: puts "Move disk #{a} to #{b}"
|
205
|
+
8:
|
206
|
+
9: hanoi(n - 1, c, b, a) if n - 1 > 0
|
207
|
+
10: end
|
181
208
|
(byebug) private_methods
|
182
209
|
[:public, :private, :include, :using, :define_method, :default_src_encoding, ...
|
183
210
|
```
|
184
211
|
|
185
212
|
`private_methods` is not a byebug command but a Ruby feature. By default, when
|
186
|
-
byebug doesn't understand a command, it will evaluate it as if it was a Ruby
|
187
|
-
command. If you don't want this behaviour, you can use `set
|
213
|
+
`byebug` doesn't understand a command, it will evaluate it as if it was a Ruby
|
214
|
+
command. If you don't want this behaviour, you can use `set noautoeval` or
|
188
215
|
even drop it in your `.byebugrc` file if you want that behaviour permanently.
|
189
216
|
The output of `private_methods`, thought, is unwieldy for our purpose: check
|
190
217
|
whether `hanoi` method is in the list. Fortunately, byebug has nice formatting
|
191
218
|
features: we can sort the output and put it into columns list using the print
|
192
|
-
command `ps`.
|
219
|
+
command `ps`. It also has a `width` setting that let's us adapt the width of
|
220
|
+
the output so that it nicely fits our screen.
|
193
221
|
|
194
222
|
```bash
|
223
|
+
(byebug) set width 80
|
224
|
+
Maximum width of byebug's output is 80
|
195
225
|
(byebug) ps private_methods
|
196
|
-
Array
|
197
|
-
Complex
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
__callee__
|
207
|
-
__dir__
|
208
|
-
__method__
|
209
|
-
`
|
210
|
-
abort
|
211
|
-
at_exit
|
212
|
-
autoload
|
213
|
-
autoload?
|
214
|
-
binding
|
215
|
-
block_given?
|
216
|
-
caller
|
217
|
-
caller_locations
|
218
|
-
catch
|
219
|
-
dbg_print loop sleep
|
220
|
-
dbg_puts method_missing spawn
|
226
|
+
Array default_src_encoding open sleep
|
227
|
+
Complex define_method p spawn
|
228
|
+
Digest eval pp sprintf
|
229
|
+
Float exec print srand
|
230
|
+
Hash exit printf syscall
|
231
|
+
Integer exit! private system
|
232
|
+
Pathname fail proc test
|
233
|
+
Rational fork public throw
|
234
|
+
String format putc timeout
|
235
|
+
URI gem_original_require puts trace_var
|
236
|
+
__callee__ gets raise trap
|
237
|
+
__dir__ global_variables rand untrace_var
|
238
|
+
__method__ include readline using
|
239
|
+
` initialize readlines warn
|
240
|
+
abort initialize_clone require y
|
241
|
+
at_exit initialize_copy require_relative
|
242
|
+
autoload initialize_dup respond_to_missing?
|
243
|
+
autoload? iterator? rubygems_require
|
244
|
+
binding lambda select
|
245
|
+
block_given? load set_trace_func
|
246
|
+
caller local_variables singleton_method_added
|
247
|
+
caller_locations loop singleton_method_removed
|
248
|
+
catch method_missing singleton_method_undefined
|
221
249
|
(byebug)
|
222
250
|
```
|
223
251
|
|
@@ -226,18 +254,19 @@ Now let's see what happens after stepping:
|
|
226
254
|
```bash
|
227
255
|
(byebug) private_methods.member?(:hanoi)
|
228
256
|
false
|
229
|
-
(byebug
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
257
|
+
(byebug) step
|
258
|
+
|
259
|
+
[5, 14] in /path/to/hanoi.rb
|
260
|
+
5: hanoi(n - 1, a, c, b) if n - 1 > 0
|
261
|
+
6:
|
262
|
+
7: puts "Move disk #{a} to #{b}"
|
263
|
+
8:
|
264
|
+
9: hanoi(n - 1, c, b, a) if n - 1 > 0
|
234
265
|
10: end
|
235
266
|
11:
|
236
|
-
=> 12:
|
237
|
-
13:
|
238
|
-
14:
|
239
|
-
15: exit 1
|
240
|
-
16: end
|
267
|
+
=> 12: n_args = $ARGV.length
|
268
|
+
13:
|
269
|
+
14: fail('*** Need number of disks or no parameter') if n_args > 1
|
241
270
|
(byebug) private_methods.member?(:hanoi)
|
242
271
|
true
|
243
272
|
(byebug)
|
@@ -246,104 +275,102 @@ true
|
|
246
275
|
Okay, lets go on and talk about program arguments.
|
247
276
|
|
248
277
|
```bash
|
249
|
-
(byebug) ARGV
|
278
|
+
(byebug) $ARGV
|
250
279
|
[]
|
251
280
|
```
|
252
281
|
|
253
|
-
|
282
|
+
Oops. We forgot to specify any parameters to this program. Let's try again. We
|
254
283
|
can use the `restart` command here.
|
255
284
|
|
256
285
|
```bash
|
257
286
|
(byebug) restart 3
|
258
287
|
Re exec'ing:
|
259
|
-
/
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
288
|
+
/path/to/bin/byebug /path/to/hanoi.rb 3
|
289
|
+
|
290
|
+
[1, 10] in /path/to/hanoi.rb
|
291
|
+
1: #
|
292
|
+
2: # Solves the classic Towers of Hanoi puzzle.
|
293
|
+
3: #
|
294
|
+
=> 4: def hanoi(n, a, b, c)
|
295
|
+
5: hanoi(n - 1, a, c, b) if n - 1 > 0
|
296
|
+
6:
|
297
|
+
7: puts "Move disk #{a} to #{b}"
|
298
|
+
8:
|
299
|
+
9: hanoi(n - 1, c, b, a) if n - 1 > 0
|
270
300
|
10: end
|
271
|
-
(byebug) break
|
272
|
-
Created breakpoint 1 at /
|
301
|
+
(byebug) break 5
|
302
|
+
Created breakpoint 1 at /path/to/hanoi.rb:5
|
273
303
|
(byebug) continue
|
274
|
-
Stopped by breakpoint 1 at /
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
304
|
+
Stopped by breakpoint 1 at /path/to/hanoi.rb:5
|
305
|
+
|
306
|
+
[1, 10] in /path/to/hanoi.rb
|
307
|
+
1: #
|
308
|
+
2: # Solves the classic Towers of Hanoi puzzle.
|
309
|
+
3: #
|
310
|
+
4: def hanoi(n, a, b, c)
|
311
|
+
=> 5: hanoi(n - 1, a, c, b) if n - 1 > 0
|
312
|
+
6:
|
313
|
+
7: puts "Move disk #{a} to #{b}"
|
314
|
+
8:
|
315
|
+
9: hanoi(n - 1, c, b, a) if n - 1 > 0
|
285
316
|
10: end
|
286
317
|
(byebug) display n
|
287
318
|
1: n = 3
|
288
319
|
(byebug) display a
|
289
|
-
2: a = a
|
290
|
-
(byebug)
|
291
|
-
|
292
|
-
|
293
|
-
(byebug) display b.inspect
|
294
|
-
4: b.inspect = :b
|
320
|
+
2: a = :a
|
321
|
+
(byebug) display b
|
322
|
+
3: b = :b
|
323
|
+
(byebug) undisplay 3
|
295
324
|
(byebug) continue
|
296
|
-
Stopped by breakpoint 1 at /
|
297
|
-
[1, 10] in /home/davidr/Proyectos/byebug/old_doc/hanoi.rb
|
298
|
-
1: # Solves the classic Towers of Hanoi puzzle.
|
299
|
-
2: def hanoi(n,a,b,c)
|
300
|
-
=> 3: if n-1 > 0
|
301
|
-
4: hanoi(n-1, a, c, b)
|
302
|
-
5: end
|
303
|
-
6: puts "Move disk %s to %s" % [a, b]
|
304
|
-
7: if n-1 > 0
|
305
|
-
8: hanoi(n-1, c, b, a)
|
306
|
-
9: end
|
307
|
-
10: end
|
325
|
+
Stopped by breakpoint 1 at /path/to/hanoi.rb:5
|
308
326
|
1: n = 2
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
7: if n-1 > 0
|
321
|
-
8: hanoi(n-1, c, b, a)
|
322
|
-
9: end
|
327
|
+
2: a = :a
|
328
|
+
[1, 10] in /path/to/hanoi.rb
|
329
|
+
1: #
|
330
|
+
2: # Solves the classic Towers of Hanoi puzzle.
|
331
|
+
3: #
|
332
|
+
4: def hanoi(n, a, b, c)
|
333
|
+
=> 5: hanoi(n - 1, a, c, b) if n - 1 > 0
|
334
|
+
6:
|
335
|
+
7: puts "Move disk #{a} to #{b}"
|
336
|
+
8:
|
337
|
+
9: hanoi(n - 1, c, b, a) if n - 1 > 0
|
323
338
|
10: end
|
339
|
+
|
340
|
+
(byebug) c
|
341
|
+
Stopped by breakpoint 1 at /path/to/hanoi.rb:5
|
324
342
|
1: n = 1
|
325
|
-
|
326
|
-
|
343
|
+
2: a = :a
|
344
|
+
|
345
|
+
[1, 10] in /path/to/hanoi.rb
|
346
|
+
1: #
|
347
|
+
2: # Solves the classic Towers of Hanoi puzzle.
|
348
|
+
3: #
|
349
|
+
4: def hanoi(n, a, b, c)
|
350
|
+
=> 5: hanoi(n - 1, a, c, b) if n - 1 > 0
|
351
|
+
6:
|
352
|
+
7: puts "Move disk #{a} to #{b}"
|
353
|
+
8:
|
354
|
+
9: hanoi(n - 1, c, b, a) if n - 1 > 0
|
355
|
+
10: end
|
327
356
|
(byebug) set nofullpath
|
328
|
-
|
357
|
+
fullpath is off
|
329
358
|
(byebug) where
|
330
|
-
--> #0 Object.hanoi(n#Fixnum, a#Symbol, b#Symbol, c#Symbol) at .../
|
331
|
-
#1 Object.hanoi(n#Fixnum, a#Symbol, b#Symbol, c#Symbol) at .../
|
332
|
-
#2 <top (required)> at .../byebug/
|
359
|
+
--> #0 Object.hanoi(n#Fixnum, a#Symbol, b#Symbol, c#Symbol) at .../shortpath/to/hanoi.rb:5
|
360
|
+
#1 Object.hanoi(n#Fixnum, a#Symbol, b#Symbol, c#Symbol) at .../shortpath/to/hanoi.rb:5
|
361
|
+
#2 <top (required)> at .../Proyectos/byebug/hanoi.rb:28
|
333
362
|
(byebug)
|
334
363
|
```
|
335
364
|
|
336
365
|
In the above we added new commands: `break` (see [breakpoints]()), which
|
337
366
|
indicates to stop just before that line of code is run, and `continue`, which
|
338
|
-
resumes execution.
|
339
|
-
`display a.inspect`. An implied string conversion is performed on the expression
|
340
|
-
after it is evaluated. To remove a display expression `undisplay` is used. If we
|
367
|
+
resumes execution. To remove a display expression `undisplay` is used. If we
|
341
368
|
give a display number, just that display expression is removed.
|
342
369
|
|
343
370
|
We also used a new command `where`(see [backtrace]()) to show the callstack. In
|
344
371
|
the above situation, starting from the bottom line we see we called the `hanoi`
|
345
|
-
method from line
|
346
|
-
two more times at line
|
372
|
+
method from line 28 of the file `hanoi.rb` and the `hanoi` method called itself
|
373
|
+
two more times at line 5.
|
347
374
|
|
348
375
|
In the callstack we show a _current frame_ mark, the frame number, the method
|
349
376
|
being called, the names of the parameters, the types those parameters
|
@@ -357,47 +384,47 @@ Now let's move around the callstack.
|
|
357
384
|
```bash
|
358
385
|
(byebug) undisplay
|
359
386
|
Clear all expressions? (y/n) y
|
360
|
-
(byebug)
|
361
|
-
NameError Exception: undefined local variable or method `
|
362
|
-
(byebug) frame
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
(
|
387
|
+
(byebug) n_args
|
388
|
+
NameError Exception: undefined local variable or method `n_args' for main:Object
|
389
|
+
(byebug) frame 2
|
390
|
+
|
391
|
+
[19, 28] in /path/to/hanoi.rb
|
392
|
+
19: begin
|
393
|
+
20: n = $ARGV[0].to_i
|
394
|
+
21: rescue ValueError
|
395
|
+
22: raise("** Expecting an integer, got: #{$ARGV[0]}")
|
396
|
+
23: end
|
397
|
+
24: end
|
398
|
+
25:
|
399
|
+
26: fail('*** Number of disks should be between 1 and 100') if n < 1 || n > 100
|
400
|
+
27:
|
401
|
+
=> 28: hanoi(n, :a, :b, :c)
|
402
|
+
(byebug) n_args
|
375
403
|
0
|
376
404
|
(byebug) p n
|
377
405
|
3
|
378
406
|
(byebug) down 2
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
407
|
+
|
408
|
+
[1, 10] in /path/to/hanoi.rb
|
409
|
+
1: #
|
410
|
+
2: # Solves the classic Towers of Hanoi puzzle.
|
411
|
+
3: #
|
412
|
+
4: def hanoi(n, a, b, c)
|
413
|
+
=> 5: hanoi(n - 1, a, c, b) if n - 1 > 0
|
414
|
+
6:
|
415
|
+
7: puts "Move disk #{a} to #{b}"
|
416
|
+
8:
|
417
|
+
9: hanoi(n - 1, c, b, a) if n - 1 > 0
|
389
418
|
10: end
|
390
|
-
(byebug
|
419
|
+
(byebug) p n
|
391
420
|
2
|
392
421
|
```
|
393
422
|
|
394
423
|
Notice in the above to get the value of variable `n` we had to use a print
|
395
424
|
command like `p n`. If we entered just `n`, that would be taken to mean byebug
|
396
|
-
command `next`. In the current scope, variable `
|
397
|
-
|
398
|
-
|
399
|
-
have been the same thing; so would issuing `up 3`. Note that in the outside
|
400
|
-
frame #3, the value of `i_args` can be shown. Also note that the value of
|
425
|
+
command `next`. In the current scope, variable `n_args` is not defined. However
|
426
|
+
I can change to the top-most frame by using the `frame 2` command. Notice that
|
427
|
+
inside frame #2, the value of `n_args` can be shown. Also note that the value of
|
401
428
|
variable `n` is different.
|
402
429
|
|
403
430
|
|
@@ -426,28 +453,27 @@ conditionally run this line if that file is invoked directly, but skip it if it
|
|
426
453
|
is not. _NOTE: `byebug` resets `$0` to try to make things like this work._
|
427
454
|
|
428
455
|
```ruby
|
429
|
-
if __FILE__ == $
|
456
|
+
if __FILE__ == $PROGRAM_NAME
|
430
457
|
t = triangle(3)
|
431
458
|
puts t
|
432
459
|
end
|
433
460
|
```
|
434
461
|
|
435
|
-
Okay, we're now ready to write our unit test
|
436
|
-
|
437
|
-
|
462
|
+
Okay, we're now ready to write our unit test and we'll use the `minitest`
|
463
|
+
framework for that. Here's the test code, it should be placed in the same
|
464
|
+
directory as `triangle.rb`.
|
438
465
|
|
439
466
|
```ruby
|
440
467
|
require 'minitest/autorun'
|
441
468
|
require_relative 'triangle.rb'
|
442
469
|
|
443
|
-
class
|
470
|
+
class TestTriangle < Minitest::Test
|
444
471
|
def test_basic
|
445
472
|
solutions = []
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
assert_equal([0, 1, 3, 6, 10, 15], solutions,
|
450
|
-
'Testing the first 5 triangle numbers')
|
473
|
+
|
474
|
+
0.upto(5) { |i| solutions << triangle(i) }
|
475
|
+
|
476
|
+
assert_equal([0, 1, 3, 6, 10, 15], solutions, 'First 5 triangle numbers')
|
451
477
|
end
|
452
478
|
end
|
453
479
|
```
|
@@ -466,22 +492,23 @@ def test_basic
|
|
466
492
|
Now we run the program, requiring `byebug`
|
467
493
|
|
468
494
|
```bash
|
469
|
-
$ ruby -rbyebug
|
470
|
-
Run options: --seed
|
495
|
+
$ ruby -rbyebug test_triangle.rb
|
496
|
+
Run options: --seed 31679
|
471
497
|
|
472
|
-
# Running
|
498
|
+
# Running:
|
473
499
|
|
474
|
-
|
500
|
+
|
501
|
+
[2, 11] in test_triangle.rb
|
475
502
|
2: require_relative 'triangle.rb'
|
476
503
|
3:
|
477
|
-
4: class
|
504
|
+
4: class TestTriangle < Minitest::Test
|
478
505
|
5: def test_basic
|
479
506
|
6: byebug
|
480
507
|
=> 7: solutions = []
|
481
|
-
8:
|
482
|
-
9:
|
483
|
-
10:
|
484
|
-
11: assert_equal([0, 1, 3, 6, 10, 15], solutions,
|
508
|
+
8:
|
509
|
+
9: 0.upto(5) { |i| solutions << triangle(i) }
|
510
|
+
10:
|
511
|
+
11: assert_equal([0, 1, 3, 6, 10, 15], solutions, 'First 5 triangle numbers')
|
485
512
|
(byebug)
|
486
513
|
```
|
487
514
|
|
@@ -494,79 +521,32 @@ Now let's see where we are...
|
|
494
521
|
(byebug) set nofullpath
|
495
522
|
Displaying frame's full file names is off.
|
496
523
|
(byebug) bt
|
497
|
-
--> #0
|
498
|
-
#1 Minitest::
|
499
|
-
#2 Minitest::
|
500
|
-
|
501
|
-
#4 Minitest::
|
502
|
-
#5
|
503
|
-
|
504
|
-
#7 Minitest::
|
505
|
-
#8 Minitest::
|
506
|
-
#9 Minitest
|
507
|
-
#10 Minitest::
|
508
|
-
|
509
|
-
#12
|
510
|
-
#13 Minitest::
|
511
|
-
#14 #<Class:Minitest::
|
524
|
+
--> #0 TestTriangle.test_basic at .../Proyectos/byebug/test_triangle.rb:7
|
525
|
+
#1 block (3 levels) in Minitest::Test.run at .../lib/minitest/test.rb:108
|
526
|
+
#2 Minitest::Test.capture_exceptions at .../lib/minitest/test.rb:206
|
527
|
+
#3 block (2 levels) in Minitest::Test.run at .../lib/minitest/test.rb:105
|
528
|
+
#4 Minitest::Test.time_it at .../lib/minitest/test.rb:258
|
529
|
+
#5 block in Minitest::Test.run at .../lib/minitest/test.rb:104
|
530
|
+
#6 #<Class:Minitest::Runnable>.on_signal(name#String, action#Proc) at .../minitest-5.5.0/lib/minitest.rb:321
|
531
|
+
#7 Minitest::Test.with_info_handler(&block#Proc) at .../lib/minitest/test.rb:278
|
532
|
+
#8 Minitest::Test.run at .../lib/minitest/test.rb:103
|
533
|
+
#9 #<Class:Minitest>.run_one_method(klass#Class, method_name#String) at .../minitest-5.5.0/lib/minitest.rb:768
|
534
|
+
#10 #<Class:Minitest::Runnable>.run_one_method(klass#Class, method_name#String, reporter#Minitest::CompositeReporter) at .../minitest-5.5.0/lib/minitest.rb:295
|
535
|
+
#11 block (2 levels) in #<Class:Minitest::Runnable>.run(reporter#Minitest::CompositeReporter, options#Hash) at .../minitest-5.5.0/lib/minitest.rb:289
|
536
|
+
ͱ-- #12 Array.each at .../minitest-5.5.0/lib/minitest.rb:288
|
537
|
+
#13 block in #<Class:Minitest::Runnable>.run(reporter#Minitest::CompositeReporter, options#Hash) at .../minitest-5.5.0/lib/minitest.rb:288
|
538
|
+
#14 #<Class:Minitest::Runnable>.on_signal(name#String, action#Proc) at .../minitest-5.5.0/lib/minitest.rb:321
|
539
|
+
#15 #<Class:Minitest::Runnable>.with_info_handler(reporter#Minitest::CompositeReporter, &block#Proc) at .../minitest-5.5.0/lib/minitest.rb:308
|
540
|
+
#16 #<Class:Minitest::Runnable>.run(reporter#Minitest::CompositeReporter, options#Hash) at .../minitest-5.5.0/lib/minitest.rb:287
|
541
|
+
#17 block in #<Class:Minitest>.__run(reporter#Minitest::CompositeReporter, options#Hash) at .../minitest-5.5.0/lib/minitest.rb:150
|
542
|
+
ͱ-- #18 Array.map at .../minitest-5.5.0/lib/minitest.rb:150
|
543
|
+
#19 #<Class:Minitest>.__run(reporter#Minitest::CompositeReporter, options#Hash) at .../minitest-5.5.0/lib/minitest.rb:150
|
544
|
+
#20 #<Class:Minitest>.run(args#Array) at .../minitest-5.5.0/lib/minitest.rb:127
|
545
|
+
#21 block in #<Class:Minitest>.autorun at .../minitest-5.5.0/lib/minitest.rb:56
|
512
546
|
(byebug)
|
513
547
|
```
|
514
548
|
|
515
|
-
We get the same result as if we had run byebug from the outset
|
516
|
-
|
517
|
-
__NOTICE: In ruby-debug, debugger and older versions of byebug, this would not
|
518
|
-
work as expected. If you are having issues, please upgrade to byebug >= 1.5.0__
|
519
|
-
|
520
|
-
|
521
|
-
### Byebug.start with a block
|
522
|
-
|
523
|
-
We saw that `Byebug.start()` and `Byebug.stop()` allow fine-grain control over
|
524
|
-
where byebug tracking should occur.
|
525
|
-
|
526
|
-
Rather than use an explicit `stop()`, you can also pass a block to the `start()`
|
527
|
-
method. This causes `start()` to run and then `yield` to that block. When the
|
528
|
-
block is finished, `stop()` is run. In other words, this wraps a
|
529
|
-
`Byebug.start()` and `Byebug.stop()` around the block of code. But it also has a
|
530
|
-
side benefit of ensuring that in the presence of an uncaught exception `stop` is
|
531
|
-
run, without having to explicitly use `begin ... ensure Byebug.stop() end`.
|
532
|
-
|
533
|
-
For example, in Ruby on Rails you might want to debug code in one of the
|
534
|
-
controllers without causing any slowdown to any other code. And this can be done
|
535
|
-
by wrapping the controller in a `start()` with a block; when the method wrapped
|
536
|
-
this way finishes, byebug is turned off and the application proceeds at regular
|
537
|
-
speed.
|
538
|
-
|
539
|
-
Of course, inside the block you will probably want to enter the byebug using
|
540
|
-
`Byebug.byebug`, otherwise there would be little point in using the `start`.
|
541
|
-
For example, you can do this in `irb`:
|
542
|
-
|
543
|
-
```bash
|
544
|
-
$ irb
|
545
|
-
2.0.0p195 :001 > require 'byebug'
|
546
|
-
=> true
|
547
|
-
2.0.0p195 :002 > def foo
|
548
|
-
2.0.0p195 :003?> x=1
|
549
|
-
2.0.0p195 :004?> puts 'foo'
|
550
|
-
2.0.0p195 :005?> end
|
551
|
-
=> nil
|
552
|
-
2.0.0p195 :006 > Byebug.start{byebug; foo}
|
553
|
-
(irb) @ 6
|
554
|
-
(byebug) s
|
555
|
-
(irb) @ 3
|
556
|
-
(byebug) s
|
557
|
-
(irb) @ 4
|
558
|
-
(byebug) p x
|
559
|
-
1
|
560
|
-
(byebug) s
|
561
|
-
foo
|
562
|
-
=> true
|
563
|
-
2.0.0p195 :007 >
|
564
|
-
```
|
565
|
-
|
566
|
-
There is a counter inside of `Byebug.start` method to make sure that this works
|
567
|
-
when another `Byebug.start` method is called inside of the outer one. However,
|
568
|
-
if you are stopped inside byebug, issuing another `byebug` call will not have
|
569
|
-
any effect even if it is nested inside another `Byebug.start`.
|
549
|
+
We get the same result as if we had run byebug from the outset.
|
570
550
|
|
571
551
|
|
572
552
|
### Debugging Oddities: How debugging Ruby may be different from other languages
|
@@ -577,7 +557,7 @@ seem or feel a little bit different and may confuse you. A number of these
|
|
577
557
|
things aren't oddities of the debugger per se but differences in how Ruby works
|
578
558
|
compared to those other languages. Because Ruby works a little differently from
|
579
559
|
those other languages, writing a debugger has to also be a little different as
|
580
|
-
well if it is to be useful. In this respect, using
|
560
|
+
well if it is to be useful. In this respect, using Byebug may help you
|
581
561
|
understand Ruby better.
|
582
562
|
|
583
563
|
We've already seen one such difference: the fact that we stop on method
|
@@ -598,28 +578,37 @@ not necessarily go to the first statement after the method header. It's possible
|
|
598
578
|
that the call will continue after a `yield` statement from a prior call.
|
599
579
|
|
600
580
|
```ruby
|
581
|
+
#
|
601
582
|
# Enumerator for primes
|
583
|
+
#
|
602
584
|
class SievePrime
|
603
|
-
|
604
|
-
|
585
|
+
def initialize
|
586
|
+
@odd_primes = []
|
587
|
+
end
|
588
|
+
|
589
|
+
def next_prime
|
605
590
|
candidate = 2
|
606
591
|
yield candidate
|
607
592
|
not_prime = false
|
608
593
|
candidate += 1
|
609
|
-
|
610
|
-
|
594
|
+
|
595
|
+
loop do
|
596
|
+
@odd_primes.each do |p|
|
611
597
|
not_prime = (0 == (candidate % p))
|
612
598
|
break if not_prime
|
613
599
|
end
|
600
|
+
|
614
601
|
unless not_prime
|
615
|
-
|
602
|
+
@odd_primes << candidate
|
616
603
|
yield candidate
|
617
604
|
end
|
605
|
+
|
618
606
|
candidate += 2
|
619
607
|
end
|
620
608
|
end
|
621
609
|
end
|
622
|
-
|
610
|
+
|
611
|
+
SievePrime.new.next_prime do |prime|
|
623
612
|
puts prime
|
624
613
|
break if prime > 10
|
625
614
|
end
|
@@ -627,48 +616,50 @@ end
|
|
627
616
|
|
628
617
|
```bash
|
629
618
|
$ byebug primes.rb
|
630
|
-
[1, 10] in /
|
631
|
-
1: #
|
632
|
-
|
633
|
-
3:
|
634
|
-
|
635
|
-
5:
|
636
|
-
6:
|
637
|
-
7:
|
638
|
-
8:
|
639
|
-
9:
|
640
|
-
10:
|
619
|
+
[1, 10] in /path/to/primes.rb
|
620
|
+
1: #
|
621
|
+
2: # Enumerator for primes
|
622
|
+
3: #
|
623
|
+
=> 4: class SievePrime
|
624
|
+
5: def initialize
|
625
|
+
6: @odd_primes = []
|
626
|
+
7: end
|
627
|
+
8:
|
628
|
+
9: def self.next_prime(&block)
|
629
|
+
10: candidate = 2
|
641
630
|
(byebug) set tracing
|
642
631
|
line tracing is on.
|
643
632
|
(byebug) set basename
|
644
633
|
basename in on.
|
645
634
|
(byebug) step 9
|
646
|
-
Tracing: primes.rb:
|
647
|
-
Tracing: primes.rb:
|
648
|
-
Tracing: primes.rb:
|
649
|
-
Tracing: primes.rb:
|
650
|
-
Tracing: primes.rb:
|
651
|
-
Tracing: primes.rb:
|
635
|
+
Tracing: primes.rb:5 def initialize
|
636
|
+
Tracing: primes.rb:9 def next_prime
|
637
|
+
Tracing: primes.rb:31 SievePrime.new.next_prime do |prime|
|
638
|
+
Tracing: primes.rb:6 @odd_primes = []
|
639
|
+
Tracing: primes.rb:10 candidate = 2
|
640
|
+
Tracing: primes.rb:11 yield candidate
|
641
|
+
Tracing: primes.rb:32 puts prime
|
652
642
|
2
|
653
|
-
Tracing: primes.rb:
|
654
|
-
Tracing: primes.rb:
|
655
|
-
|
656
|
-
[
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
=>
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
643
|
+
Tracing: primes.rb:33 break if prime > 10
|
644
|
+
Tracing: primes.rb:12 not_prime = false
|
645
|
+
|
646
|
+
[7, 16] in /path/to/primes.rb
|
647
|
+
7: end
|
648
|
+
8:
|
649
|
+
9: def next_prime
|
650
|
+
10: candidate = 2
|
651
|
+
11: yield candidate
|
652
|
+
=> 12: not_prime = false
|
653
|
+
13: candidate += 1
|
654
|
+
14:
|
655
|
+
15: loop do
|
656
|
+
16: @odd_primes.each do |p|
|
657
|
+
17: not_prime = (0 == (candidate % p))
|
667
658
|
(byebug)
|
668
659
|
```
|
669
660
|
|
670
|
-
The loop between lines
|
671
|
-
`
|
661
|
+
The loop between lines 31-34 gets interleaved between those of
|
662
|
+
`SievePrime#next_prime`, lines 9-28 above.
|
672
663
|
|
673
664
|
|
674
665
|
#### No Parameter Values in a Call Stack
|
@@ -686,17 +677,11 @@ object can change.
|
|
686
677
|
|
687
678
|
So at present, the name of the parameter is shown. The call-style setting
|
688
679
|
([callstyle]()) can be used to set whether the name is shown or the name and the
|
689
|
-
_current_ class of the object.
|
690
|
-
added which saves on call shorter "scalar" types of values and the class name.
|
680
|
+
_current_ class of the object.
|
691
681
|
|
692
682
|
|
693
683
|
#### Lines You Can Stop At
|
694
684
|
|
695
|
-
As with the duplicate stops per control (e.g. `if` statement), until tools like
|
696
|
-
debuggers get more traction among core ruby developers there are going to be
|
697
|
-
weirdness. Here we describe the stopping locations which effects the breakpoint
|
698
|
-
line numbers you can stop at.
|
699
|
-
|
700
685
|
Consider the following little Ruby program.
|
701
686
|
|
702
687
|
```ruby
|
@@ -711,13 +696,418 @@ puts $1
|
|
711
696
|
The stopping points that Ruby records are the last two lines, lines 5 and 6.
|
712
697
|
|
713
698
|
Inside `byebug` you can get a list of stoppable lines for a file using the `info
|
714
|
-
file` command
|
699
|
+
file` command.
|
700
|
+
|
701
|
+
|
702
|
+
### Threading support
|
703
|
+
|
704
|
+
Byebug supports debugging Ruby programs making use of multiple threads.
|
705
|
+
|
706
|
+
Let's consider the following sample program:
|
707
|
+
|
708
|
+
```ruby
|
709
|
+
class Company
|
710
|
+
def initialize(task)
|
711
|
+
@tasks, @results = Queue.new, Queue.new
|
712
|
+
|
713
|
+
@tasks.push(task)
|
714
|
+
end
|
715
|
+
|
716
|
+
def run
|
717
|
+
manager = Thread.new { manager_routine }
|
718
|
+
employee = Thread.new { employee_routine }
|
719
|
+
|
720
|
+
sleep 6
|
721
|
+
|
722
|
+
go_home(manager)
|
723
|
+
go_home(employee)
|
724
|
+
end
|
725
|
+
|
726
|
+
#
|
727
|
+
# An employee doing his thing
|
728
|
+
#
|
729
|
+
def employee_routine
|
730
|
+
loop do
|
731
|
+
if @tasks.empty?
|
732
|
+
have_a_break(0.1)
|
733
|
+
else
|
734
|
+
work_hard(@tasks.pop)
|
735
|
+
end
|
736
|
+
end
|
737
|
+
end
|
738
|
+
|
739
|
+
#
|
740
|
+
# A manager doing his thing
|
741
|
+
#
|
742
|
+
def manager_routine
|
743
|
+
loop do
|
744
|
+
if @results.empty?
|
745
|
+
have_a_break(1)
|
746
|
+
else
|
747
|
+
show_off(@results.pop)
|
748
|
+
end
|
749
|
+
end
|
750
|
+
end
|
751
|
+
|
752
|
+
private
|
753
|
+
|
754
|
+
def show_off(result)
|
755
|
+
puts result
|
756
|
+
end
|
757
|
+
|
758
|
+
def work_hard(task)
|
759
|
+
task ** task
|
760
|
+
end
|
761
|
+
|
762
|
+
def have_a_break(amount)
|
763
|
+
sleep amount
|
764
|
+
end
|
765
|
+
|
766
|
+
def go_home(person)
|
767
|
+
person.kill
|
768
|
+
end
|
769
|
+
end
|
770
|
+
|
771
|
+
Company.new(10).run
|
772
|
+
```
|
773
|
+
|
774
|
+
The `Company` class simulates a real company. The company has a manager and an
|
775
|
+
employee represented by 2 threads: they work concurrently to achieve the
|
776
|
+
company's targets.
|
777
|
+
|
778
|
+
* The employee looks for tasks to complete. If there are tasks, it works hard to
|
779
|
+
complete them. Otherwise he has a quick break.
|
780
|
+
|
781
|
+
```ruby
|
782
|
+
#
|
783
|
+
# An employee doing his thing
|
784
|
+
#
|
785
|
+
def employee_routine
|
786
|
+
loop do
|
787
|
+
if @tasks.empty?
|
788
|
+
have_a_break(0.1)
|
789
|
+
else
|
790
|
+
work_hard(@tasks.pop)
|
791
|
+
end
|
792
|
+
end
|
793
|
+
end
|
794
|
+
```
|
795
|
+
|
796
|
+
* The manager, on the other hand, sits there all day and sporadically checks
|
797
|
+
whether there are any results to show off.
|
798
|
+
|
799
|
+
```ruby
|
800
|
+
#
|
801
|
+
# A manager doing his thing
|
802
|
+
#
|
803
|
+
def manager_routine
|
804
|
+
loop do
|
805
|
+
if @results.empty?
|
806
|
+
have_a_break(1)
|
807
|
+
else
|
808
|
+
show_off(@results.pop)
|
809
|
+
end
|
810
|
+
end
|
811
|
+
end
|
812
|
+
```
|
813
|
+
|
814
|
+
We do some abstractions easily readable in the code. Our tasks are just a
|
815
|
+
`Queue` of numbers, so are our results. What our employer does when he works is
|
816
|
+
some calculation with those numbers and what the manager does with the results
|
817
|
+
is printing them to the screen.
|
818
|
+
|
819
|
+
We instantiate a new company with an initial task and after running that
|
820
|
+
company we expect the result to be printed in the screen, but it is not. Lets
|
821
|
+
debug our sample program:
|
822
|
+
|
823
|
+
```bash
|
824
|
+
[1, 10] in /path/to/company.rb
|
825
|
+
=> 1: class Company
|
826
|
+
2: def initialize(task)
|
827
|
+
3: @tasks, @results = Queue.new, Queue.new
|
828
|
+
4:
|
829
|
+
5: @tasks.push(task)
|
830
|
+
6: end
|
831
|
+
7:
|
832
|
+
8: def run
|
833
|
+
9: manager = Thread.new { manager_routine }
|
834
|
+
10: employee = Thread.new { employee_routine }
|
835
|
+
(byebug) l
|
836
|
+
|
837
|
+
[11, 20] in /path/to/company.rb
|
838
|
+
11:
|
839
|
+
12: sleep 6
|
840
|
+
13:
|
841
|
+
14: go_home(manager)
|
842
|
+
15: go_home(employee)
|
843
|
+
16: end
|
844
|
+
17:
|
845
|
+
18: #
|
846
|
+
19: # An employee doing his thing
|
847
|
+
20: #
|
848
|
+
|
849
|
+
(byebug) c 12
|
850
|
+
Stopped by breakpoint 1 at /path/to/company.rb:12
|
851
|
+
|
852
|
+
[7, 16] in /path/to/company.rb
|
853
|
+
7:
|
854
|
+
8: def run
|
855
|
+
9: manager = Thread.new { manager_routine }
|
856
|
+
10: employee = Thread.new { employee_routine }
|
857
|
+
11:
|
858
|
+
=> 12: sleep 6
|
859
|
+
13:
|
860
|
+
14: go_home(manager)
|
861
|
+
15: go_home(employee)
|
862
|
+
16: end
|
863
|
+
(byebug) th l
|
864
|
+
+ 1 #<Thread:0x0000000192f328 run> /path/to/company.rb:12
|
865
|
+
2 #<Thread:0x00000001ff9870@/path/to/company.rb:9 sleep>
|
866
|
+
3 #<Thread:0x00000001ff80d8@/path/to/company.rb:10 sleep>
|
867
|
+
```
|
868
|
+
|
869
|
+
What we have done here is just start our program and advance to the point
|
870
|
+
inmediately after our `employee` and `manager` threads have been created. We
|
871
|
+
can then check that the threads are there using the `thread list` command. Now
|
872
|
+
we want to debug both of this threads to check what's happening and look for the
|
873
|
+
bug.
|
874
|
+
|
875
|
+
```bash
|
876
|
+
(byebug) th switch 3
|
877
|
+
|
878
|
+
[5, 14] in /path/to/company.rb
|
879
|
+
5: @tasks.push(task)
|
880
|
+
6: end
|
881
|
+
7:
|
882
|
+
8: def run
|
883
|
+
9: manager = Thread.new { manager_routine }
|
884
|
+
=> 10: employee = Thread.new { employee_routine }
|
885
|
+
11:
|
886
|
+
12: sleep 6
|
887
|
+
13:
|
888
|
+
14: go_home(manager)
|
889
|
+
(byebug) th stop 1; th stop 2
|
890
|
+
$ 1 #<Thread:0x00000001307310 sleep> /path/to/company.rb:12
|
891
|
+
$ 2 #<Thread:0x000000018bf438 sleep> /path/to/company.rb:9
|
892
|
+
(byebug) th l
|
893
|
+
$ 1 #<Thread:0x00000001307310 sleep> /path/to/company.rb:12
|
894
|
+
$ 2 #<Thread:0x000000018bf438@/path/to/company.rb:9 sleep> /path/to/company.rb:55
|
895
|
+
+ 3 #<Thread:0x00000001ff80d8@/path/to/company.rb:10 sleep> /path/to/company.rb:10
|
896
|
+
```
|
897
|
+
|
898
|
+
We have started by debugging the `employee` thread. To do that, we switch to
|
899
|
+
that thread using the `thread switch 3` command. The thread number is the one
|
900
|
+
specified by `thread list`, we know this is our worker thread because `thread
|
901
|
+
list` specifies where the thread is defined in the file (and its current
|
902
|
+
position if the thread is currently running, although this is only available
|
903
|
+
since Ruby 2.2.1).
|
904
|
+
|
905
|
+
After that we stopped the main thread and the worker thread, using the command
|
906
|
+
`thread stop`. We do this because we want to focus on the employee thread first
|
907
|
+
and don't want the program to finish while we are debugging. Notice that stopped
|
908
|
+
threads are marked with the "$" symbol whereas the current thread is marked with
|
909
|
+
the "+" symbol.
|
910
|
+
|
911
|
+
```bash
|
912
|
+
(byebug) s
|
913
|
+
|
914
|
+
[17, 26] in /path/to/company.rb
|
915
|
+
17:
|
916
|
+
18: #
|
917
|
+
19: # An employee doing his thing
|
918
|
+
20: #
|
919
|
+
21: def employee_routine
|
920
|
+
=> 22: loop do
|
921
|
+
23: if @tasks.empty?
|
922
|
+
24: have_a_break(0.1)
|
923
|
+
25: else
|
924
|
+
26: work_hard(@tasks.pop)
|
925
|
+
(byebug) s
|
926
|
+
|
927
|
+
[18, 27] in /path/to/company.rb
|
928
|
+
18: #
|
929
|
+
19: # An employee doing his thing
|
930
|
+
20: #
|
931
|
+
21: def employee_routine
|
932
|
+
22: loop do
|
933
|
+
=> 23: if @tasks.empty?
|
934
|
+
24: have_a_break(0.1)
|
935
|
+
25: else
|
936
|
+
26: work_hard(@tasks.pop)
|
937
|
+
27: end
|
938
|
+
(byebug) n
|
939
|
+
|
940
|
+
[21, 30] in /path/to/company.rb
|
941
|
+
21: def employee_routine
|
942
|
+
22: loop do
|
943
|
+
23: if @tasks.empty?
|
944
|
+
24: have_a_break(0.1)
|
945
|
+
25: else
|
946
|
+
=> 26: work_hard(@tasks.pop)
|
947
|
+
27: end
|
948
|
+
28: end
|
949
|
+
29: end
|
950
|
+
30:
|
951
|
+
(byebug) s
|
952
|
+
|
953
|
+
[49, 58] in /path/to/company.rb
|
954
|
+
49: def show_off(result)
|
955
|
+
50: puts result
|
956
|
+
51: end
|
957
|
+
52:
|
958
|
+
53: def work_hard(task)
|
959
|
+
=> 54: task ** task
|
960
|
+
55: end
|
961
|
+
56:
|
962
|
+
57: def have_a_break(amount)
|
963
|
+
58: sleep amount
|
964
|
+
(byebug) s
|
965
|
+
|
966
|
+
[21, 30] in /path/to/company.rb
|
967
|
+
21: #
|
968
|
+
22: # An employee doing his thing
|
969
|
+
23: #
|
970
|
+
24: def employee_routine
|
971
|
+
25: loop do
|
972
|
+
=> 26: if @tasks.empty?
|
973
|
+
27: have_a_break(0.1)
|
974
|
+
28: else
|
975
|
+
29: work_hard(@tasks.pop)
|
976
|
+
30: end
|
977
|
+
(byebug) n
|
978
|
+
|
979
|
+
[22, 31] in /path/to/company.rb
|
980
|
+
22: # An employee doing his thing
|
981
|
+
23: #
|
982
|
+
24: def employee_routine
|
983
|
+
25: loop do
|
984
|
+
26: if @tasks.empty?
|
985
|
+
=> 27: have_a_break(0.1)
|
986
|
+
28: else
|
987
|
+
29: work_hard(@tasks.pop)
|
988
|
+
30: end
|
989
|
+
31: end
|
990
|
+
(byebug) n
|
991
|
+
|
992
|
+
[21, 30] in /path/to/company.rb
|
993
|
+
21: #
|
994
|
+
22: # An employee doing his thing
|
995
|
+
23: #
|
996
|
+
24: def employee_routine
|
997
|
+
25: loop do
|
998
|
+
=> 26: if @tasks.empty?
|
999
|
+
27: have_a_break(0.1)
|
1000
|
+
28: else
|
1001
|
+
29: work_hard(@tasks.pop)
|
1002
|
+
30: end
|
1003
|
+
31: end
|
1004
|
+
(byebug)
|
1005
|
+
```
|
1006
|
+
|
1007
|
+
Everything seems fine in this thread. The first iteration the employee will do
|
1008
|
+
his job, and after that it will just check for new tasks and sleep. Let's debug
|
1009
|
+
the manager task now:
|
1010
|
+
|
1011
|
+
```bash
|
1012
|
+
(byebug) th resume 2
|
1013
|
+
2 #<Thread:0x000000019892d8@/path/to/company.rb:12 run> /path/to/company.rb:12
|
1014
|
+
(byebug) th switch 2
|
1015
|
+
2 #<Thread:0x000000019892d8@/path/to/company.rb:12 sleep> /path/to/company.rb:12
|
1016
|
+
|
1017
|
+
[7, 16] in /path/to/company.rb
|
1018
|
+
7:
|
1019
|
+
8: #
|
1020
|
+
9: # A CEO running his company
|
1021
|
+
10: #
|
1022
|
+
11: def run
|
1023
|
+
=> 12: manager = Thread.new { manager_routine }
|
1024
|
+
13: employee = Thread.new { employee_routine }
|
1025
|
+
14:
|
1026
|
+
15: sleep 6
|
1027
|
+
16:
|
1028
|
+
(byebug)
|
1029
|
+
```
|
1030
|
+
|
1031
|
+
We used the command `thread resume` to restart the manager's thread and then
|
1032
|
+
switch to it using `thread switch`. It's important to resume the thread's
|
1033
|
+
execution before switching to it, otherwise we'll get a hang because we cannot
|
1034
|
+
run a sleeping thread.
|
1035
|
+
|
1036
|
+
Now we can investigate the problem in the employer's side:
|
1037
|
+
|
1038
|
+
``bash
|
1039
|
+
(byebug) s
|
1040
|
+
[30, 39] in /path/to/company.rb
|
1041
|
+
30:
|
1042
|
+
31: #
|
1043
|
+
32: # A manager doing his thing
|
1044
|
+
33: #
|
1045
|
+
34: def manager_routine
|
1046
|
+
=> 35: loop do
|
1047
|
+
36: if @results.empty?
|
1048
|
+
37: have_a_break(1)
|
1049
|
+
38: else
|
1050
|
+
39: show_off(@results.pop)
|
1051
|
+
(byebug) s
|
1052
|
+
|
1053
|
+
[31, 40] in /path/to/company.rb
|
1054
|
+
31: #
|
1055
|
+
32: # A manager doing his thing
|
1056
|
+
33: #
|
1057
|
+
34: def manager_routine
|
1058
|
+
35: loop do
|
1059
|
+
=> 36: if @results.empty?
|
1060
|
+
37: have_a_break(1)
|
1061
|
+
38: else
|
1062
|
+
39: show_off(@results.pop)
|
1063
|
+
40: end
|
1064
|
+
(byebug) n
|
1065
|
+
|
1066
|
+
[32, 41] in /path/to/company.rb
|
1067
|
+
32: # A manager doing his thing
|
1068
|
+
33: #
|
1069
|
+
34: def manager_routine
|
1070
|
+
35: loop do
|
1071
|
+
36: if @results.empty?
|
1072
|
+
=> 37: have_a_break(1)
|
1073
|
+
38: else
|
1074
|
+
39: show_off(@results.pop)
|
1075
|
+
40: end
|
1076
|
+
41: end
|
1077
|
+
(byebug) n
|
1078
|
+
|
1079
|
+
[31, 40] in /path/to/company.rb
|
1080
|
+
31: #
|
1081
|
+
32: # A manager doing his thing
|
1082
|
+
33: #
|
1083
|
+
34: def manager_routine
|
1084
|
+
35: loop do
|
1085
|
+
=> 36: if @results.empty?
|
1086
|
+
37: have_a_break(1)
|
1087
|
+
38: else
|
1088
|
+
39: show_off(@results.pop)
|
1089
|
+
40: end
|
1090
|
+
(byebug)
|
1091
|
+
``
|
1092
|
+
|
1093
|
+
Now we can see the problem, the `@results` variable is always empty! The
|
1094
|
+
employee forgot to leave the results in his manager's deck. We fix it by
|
1095
|
+
changing the line
|
1096
|
+
|
1097
|
+
```ruby
|
1098
|
+
work_hard(@tasks.pop)
|
1099
|
+
```
|
1100
|
+
|
1101
|
+
in the `employee_routine` method with the line
|
1102
|
+
|
1103
|
+
```ruby
|
1104
|
+
@results << work_hard(@tasks.pop)
|
1105
|
+
```
|
715
1106
|
|
716
1107
|
To be continued...
|
717
|
-
*
|
718
|
-
*
|
719
|
-
*
|
720
|
-
* post-mortem debugging and setting up for that
|
1108
|
+
* More complex examples with objects, pretty printing and irb.
|
1109
|
+
* Line tracing and non-interactive tracing.
|
1110
|
+
* Post-mortem debugging.
|
721
1111
|
|
722
1112
|
|
723
1113
|
## Getting in & out
|
@@ -726,75 +1116,91 @@ To be continued...
|
|
726
1116
|
|
727
1117
|
There is a wrapper script called `byebug` which basically `require`'s the gem
|
728
1118
|
then loads `byebug` before its argument (the program to be debugged) is started.
|
729
|
-
|
730
|
-
```bash
|
731
|
-
byebug [byebug-options] [--] ruby-script ruby-script-arguments
|
732
|
-
```
|
733
|
-
|
734
1119
|
If you don't need to pass dash options to your program, which might be confused
|
735
1120
|
with byebug options, then you don't need to add the `--`. To get a brief list of
|
736
1121
|
options and descriptions, use the `--help` option.
|
737
1122
|
|
738
1123
|
```bash
|
739
1124
|
$ byebug --help
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
--version Print program version
|
758
|
-
-v Print version number, then turn on verbose mode
|
1125
|
+
|
1126
|
+
byebug 3.5.1
|
1127
|
+
|
1128
|
+
Usage: byebug [options] <script.rb> -- <script.rb parameters>
|
1129
|
+
|
1130
|
+
-d, --debug Set $DEBUG=true
|
1131
|
+
-I, --include list Add to paths to $LOAD_PATH
|
1132
|
+
-m, --[no-]post-mortem Use post-mortem mode
|
1133
|
+
-q, --[no-]quit Quit when script finishes
|
1134
|
+
-x, --[no-]rc Run byebug initialization file
|
1135
|
+
-s, --[no-]stop Stop when script is loaded
|
1136
|
+
-r, --require file Require library before script
|
1137
|
+
-R, --remote [host:]port Remote debug [host:]port
|
1138
|
+
-t, --[no-]trace Turn on line tracing
|
1139
|
+
-v, --version Print program version
|
1140
|
+
-h, --help Display this message
|
1141
|
+
|
759
1142
|
```
|
760
1143
|
|
761
1144
|
Many options appear as a long option name, such as `--help` and a short one
|
762
1145
|
letter option name, such as `-h`. The list of options is detailed below:
|
763
1146
|
|
764
|
-
|
765
|
-
* **-v | --version**. It causes `byebug` to print its version number and
|
766
|
-
exit.
|
767
|
-
* **-d | --debug**. Set `$DEBUG` to `true`. Compatible with Ruby's.
|
768
|
-
* **-I | --include <path>**. Add `path` to load path. `path` can be a single
|
769
|
-
path ar a colon separated path list.
|
770
|
-
* **--post-mortem**. If your program raises an exception that isn't caught you
|
771
|
-
can enter byebug for inspection of what went wrong. You may also want to use
|
772
|
-
this option in conjunction with `--no-stop`. See also [Post-Mortem Debugging]().
|
773
|
-
* **--no-quit**. Restart `byebug` when your program terminates normally.
|
774
|
-
* **--no-stop**. Normally `byebug` stops before executing the first statement.
|
775
|
-
If instead you want it to start running initially and perhaps break it later in
|
776
|
-
the execution, use this option.
|
777
|
-
* **--require | -r**. Require the library before executing the script. However,
|
778
|
-
if the library happened to be `debug`, we'll just ignore the require since we're
|
779
|
-
already a debugger. This option is compatible with Ruby's.
|
780
|
-
* **--script <file>**. Script to run before byebug's execution.
|
781
|
-
* **-x | --trace**. Turn on line tracing. Running `byebug --trace
|
782
|
-
<rubyscript>.rb` is pretty much like running `ruby -rtracer
|
783
|
-
<rubyscript>.rb`. If all you want to do however is get a linetrace, `tracer` is
|
784
|
-
most likely faster than `byebug`
|
1147
|
+
#### -h | --help
|
785
1148
|
|
786
|
-
|
787
|
-
|
1149
|
+
It causes `byebug` to print some basic help and exit
|
1150
|
+
|
1151
|
+
|
1152
|
+
#### -v | --version
|
1153
|
+
|
1154
|
+
It causes `byebug` to print its version number and exit.
|
1155
|
+
|
1156
|
+
|
1157
|
+
#### -d | --debug
|
1158
|
+
|
1159
|
+
Sets `$DEBUG` to `true`. Compatible with Ruby's flag.
|
1160
|
+
|
1161
|
+
#### -I | --include <path>
|
1162
|
+
|
1163
|
+
Adds `path` to load path. `path` can be a single path or a colon separated path
|
1164
|
+
list.
|
1165
|
+
|
1166
|
+
#### -m | --post-mortem
|
1167
|
+
|
1168
|
+
If your program raises an exception that isn't caught you can enter byebug for
|
1169
|
+
inspection of what went wrong. You may also want to use this option in
|
1170
|
+
conjunction with `--no-stop`. See also [Post-Mortem Debugging]().
|
1171
|
+
|
1172
|
+
#### --no-quit
|
1173
|
+
|
1174
|
+
Keep inside `byebug` after your program terminates normally.
|
788
1175
|
|
789
|
-
|
790
|
-
user 0m0.048s
|
791
|
-
sys 0m0.016s
|
1176
|
+
#### --no-stop
|
792
1177
|
|
793
|
-
|
1178
|
+
Normally `byebug` stops before executing the first statement. If instead you
|
1179
|
+
want it to start running initially and perhaps break it later in the execution,
|
1180
|
+
use this option.
|
794
1181
|
|
795
|
-
|
796
|
-
|
797
|
-
|
1182
|
+
#### -r | --require <lib>
|
1183
|
+
|
1184
|
+
Requires the library before executing the script. This option is compatible
|
1185
|
+
with Ruby's.
|
1186
|
+
|
1187
|
+
#### -t | --trace
|
1188
|
+
|
1189
|
+
Turns on line tracing. Running `byebug --trace <rubyscript>.rb` is pretty much
|
1190
|
+
like running `ruby -rtracer <rubyscript>.rb`. If all you want to do however is
|
1191
|
+
get a line trace, `tracer` is most likely faster than `byebug`.
|
1192
|
+
|
1193
|
+
```bash
|
1194
|
+
$ time byebug --trace --no-stop hanoi.rb > /dev/null
|
1195
|
+
|
1196
|
+
real 0m0.743s
|
1197
|
+
user 0m0.668s
|
1198
|
+
sys 0m0.068s
|
1199
|
+
$ time ruby -rtracer hanoi.rb > /dev/null
|
1200
|
+
|
1201
|
+
real 0m0.077s
|
1202
|
+
user 0m0.072s
|
1203
|
+
sys 0m0.004s
|
798
1204
|
```
|
799
1205
|
|
800
1206
|
### Byebug default options
|
@@ -802,27 +1208,7 @@ sys 0m0.056s
|
|
802
1208
|
Byebug has many command-line options,; it seems that some people want to set
|
803
1209
|
them differently from the defaults. For example, some people may want
|
804
1210
|
`--no-quit` to be the default behavior. One could write a wrapper script or set
|
805
|
-
a shell alias to handle this.
|
806
|
-
processing command options, if the file `$HOME/.byebugoptrc` is found, it is
|
807
|
-
loaded. If you want to set the defaults in some other way, you can put Ruby code
|
808
|
-
here and set variable `options` which is an OpenStruct. For example here's how
|
809
|
-
you'd set `-no-quit` and a personal message.
|
810
|
-
|
811
|
-
```ruby
|
812
|
-
# This file contains how you want the default options to byebug to be set. Any
|
813
|
-
# Ruby code can be put here.
|
814
|
-
#
|
815
|
-
# byebug # Uncomment if you want to debug byebug!
|
816
|
-
options.control = false
|
817
|
-
puts "rocky's byebugrc run"
|
818
|
-
```
|
819
|
-
|
820
|
-
Here are the default values in `options`
|
821
|
-
|
822
|
-
```
|
823
|
-
#<OpenStruct nx=false, quit=true, restart_script=nil, script=nil, stop=true,
|
824
|
-
tracing=false, verbose=false>
|
825
|
-
```
|
1211
|
+
a shell alias to handle this.
|
826
1212
|
|
827
1213
|
### Command Files
|
828
1214
|
|
@@ -841,8 +1227,6 @@ variable. Thus, you can have more than one init file, one generic in your home
|
|
841
1227
|
directory, and another, specific to the program you are debugging, in the
|
842
1228
|
directory where you invoke `byebug`.
|
843
1229
|
|
844
|
-
* __Reads command files specified by the `--script` option.__
|
845
|
-
|
846
1230
|
You can also request the execution of a command file with the `source` command
|
847
1231
|
(see [Source]()).
|
848
1232
|
|
@@ -917,7 +1301,7 @@ different computer than the one running the Ruby program.
|
|
917
1301
|
|
918
1302
|
To setup remote debugging, drop the following somewhere before the point in the
|
919
1303
|
program that you want to debug (In Rails, the
|
920
|
-
`config/environments/development.rb` could be a good
|
1304
|
+
`config/environments/development.rb` could be a good candidate).
|
921
1305
|
|
922
1306
|
```ruby
|
923
1307
|
require 'byebug'
|
@@ -1008,11 +1392,11 @@ short list of named classes of commands
|
|
1008
1392
|
Type "help <command-name>" for help on a specific command
|
1009
1393
|
|
1010
1394
|
Available commands:
|
1011
|
-
backtrace delete enable help method ps
|
1012
|
-
break disable eval info next putl
|
1013
|
-
|
1014
|
-
|
1015
|
-
|
1395
|
+
backtrace delete enable help method ps save step where
|
1396
|
+
break disable eval info next putl set trace catch
|
1397
|
+
display exit irb p quit show undisplay condition down
|
1398
|
+
finish kill pp skip up continue edit frame list
|
1399
|
+
pry restart source var
|
1016
1400
|
```
|
1017
1401
|
|
1018
1402
|
With a command name as `help` argument, `byebug` displays short information on how to
|
@@ -1261,7 +1645,7 @@ got updated via a prior `list` command.
|
|
1261
1645
|
|
1262
1646
|
```
|
1263
1647
|
$ byebug triangle.rb
|
1264
|
-
[1, 10] in /
|
1648
|
+
[1, 10] in /path/to/triangle.rb
|
1265
1649
|
1: # Compute the n'th triangle number, the hard way: triangle(n) == (n*(n+1))/2
|
1266
1650
|
=> 2: def triangle(n)
|
1267
1651
|
3: tri = 0
|
@@ -1279,7 +1663,7 @@ $ byebug triangle.rb
|
|
1279
1663
|
/home/davidr/Proyectos/byebug/old_doc/triangle.rb @ 2
|
1280
1664
|
def triangle(n)
|
1281
1665
|
(byebug) list # same line range as before going into irb
|
1282
|
-
[1, 10] in /
|
1666
|
+
[1, 10] in /path/to/triangle.rb
|
1283
1667
|
1: # Compute the n'th triangle number, the hard way: triangle(n) == (n*(n+1))/2
|
1284
1668
|
=> 2: def triangle(n)
|
1285
1669
|
3: tri = 0
|