byebug 3.5.1 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|