### Second Sample Session: Delving Deeper In this section we'll introduce breakpoints, the call stack and restarting. Below we will debug a simple Ruby program to solve the classic Towers of Hanoi puzzle. It is augmented by the bane of programming: some command-parameter processing with error checking. ``` $ byebug hanoi.rb [1, 10] in /home/davidr/Proyectos/byebug/old_doc/hanoi.rb 1: # Solves the classic Towers of Hanoi puzzle. => 2: def hanoi(n,a,b,c) 3: if n-1 > 0 4: hanoi(n-1, a, c, b) 5: end 6: puts "Move disk %s to %s" % [a, b] 7: if n-1 > 0 8: hanoi(n-1, c, b, a) 9: end 10: end (byebug) ``` Recall in the first section iwe said that before the `def` is run, the method it names is undefined. Let's check that out. First let's see what private methods we can call before running `def hanoi`. ``` (byebug) private_methods [:public, :private, :include, :using, :define_method, :default_src_encoding, ... ``` `private_methods` is not a byebug command but a Ruby feature. By default, when byebug doesn't understand a command, it will evaluate it as if it was a Ruby command. If you don't want this behaviour, you can use `set autoeval off` or even drop it in your `.byebugrc` file if you want that behaviour permanently. The output of `private_methods`, thought, is unwieldy for our porpuse: check whether `hanoi` method is in the list. Fortunately, byebug has nice formatting features: we can sort the output and put it into columns list using the print command `ps`. ``` (byebug) ps private_methods Array debug_program open sprintf Complex default_src_encoding p srand DelegateClass define_method pp syscall Digest eval print system Float exec printf test Hash exit private throw Integer exit! proc trace_var Pathname fail process_options trap Rational fork public untrace_var String format putc using __callee__ gem puts warn __dir__ gem_original_require raise whence_file __method__ gets rand ` global_variables readline abort include readlines at_exit initialize require autoload initialize_clone require_relative autoload? initialize_copy respond_to_missing? binding initialize_dup select block_given? iterator? set_trace_func caller lambda singleton_method_added caller_locations load singleton_method_removed catch local_variables singleton_method_undefined dbg_print loop sleep dbg_puts method_missing spawn (byebug) ``` Now let's see what happens after stepping: ``` (byebug) private_methods.member?(:hanoi) false (byebug:1) step [7, 16] in /home/davidr/Proyectos/byebug/old_doc/hanoi.rb 7: if n-1 > 0 8: hanoi(n-1, c, b, a) 9: end 10: end 11: => 12: i_args=ARGV.length 13: if i_args > 1 14: puts "*** Need number of disks or no parameter" 15: exit 1 16: end (byebug) private_methods.member?(:hanoi) true (byebug) ``` Okay, lets go on and talk about program arguments. ``` (byebug) ARGV [] ``` Ooops. We forgot to specify any parameters to this program. Let's try again. We can use the `restart` command here. ``` (byebug) restart 3 Re exec'ing: /home/davidr/.rvm/gems/ruby-2.0.0-p195@byebug/gems/byebug-1.1.1/bin/byebug /home/davidr/Proyectos/byebug/old_doc/hanoi.rb 3 [1, 10] in /home/davidr/Proyectos/byebug/old_doc/hanoi.rb 1: # Solves the classic Towers of Hanoi puzzle. => 2: def hanoi(n,a,b,c) 3: if n-1 > 0 4: hanoi(n-1, a, c, b) 5: end 6: puts "Move disk %s to %s" % [a, b] 7: if n-1 > 0 8: hanoi(n-1, c, b, a) 9: end 10: end (byebug) break 4 Created breakpoint 1 at /home/davidr/Proyectos/byebug/old_doc/hanoi.rb:3 (byebug) continue Stopped by breakpoint 1 at /home/davidr/Proyectos/byebug/old_doc/hanoi.rb:3 [1, 10] in /home/davidr/Proyectos/byebug/old_doc/hanoi.rb 1: # Solves the classic Towers of Hanoi puzzle. 2: def hanoi(n,a,b,c) => 3: if n-1 > 0 4: hanoi(n-1, a, c, b) 5: end 6: puts "Move disk %s to %s" % [a, b] 7: if n-1 > 0 8: hanoi(n-1, c, b, a) 9: end 10: end (byebug) display n 1: n = 3 (byebug) display a 2: a = a (byebug) undisplay 2 (byebug) display a.inspect 3: a.inspect = :a (byebug) display b.inspect 4: b.inspect = :b (byebug) continue Stopped by breakpoint 1 at /home/davidr/Proyectos/byebug/old_doc/hanoi.rb:3 [1, 10] in /home/davidr/Proyectos/byebug/old_doc/hanoi.rb 1: # Solves the classic Towers of Hanoi puzzle. 2: def hanoi(n,a,b,c) => 3: if n-1 > 0 4: hanoi(n-1, a, c, b) 5: end 6: puts "Move disk %s to %s" % [a, b] 7: if n-1 > 0 8: hanoi(n-1, c, b, a) 9: end 10: end 1: n = 2 3: a.inspect = :a 4: b.inspect = :c (byebug) c Stopped by breakpoint 1 at /home/davidr/Proyectos/byebug/old_doc/hanoi.rb:3 [1, 10] in /home/davidr/Proyectos/byebug/old_doc/hanoi.rb 1: # Solves the classic Towers of Hanoi puzzle. 2: def hanoi(n,a,b,c) => 3: if n-1 > 0 4: hanoi(n-1, a, c, b) 5: end 6: puts "Move disk %s to %s" % [a, b] 7: if n-1 > 0 8: hanoi(n-1, c, b, a) 9: end 10: end 1: n = 1 3: a.inspect = :a 4: b.inspect = :b (byebug) set nofullpath Displaying frame's full file names is off. (byebug) where --> #0 Object.hanoi(n#Fixnum, a#Symbol, b#Symbol, c#Symbol) at .../byebug/old_doc/hanoi.rb:4 #1 Object.hanoi(n#Fixnum, a#Symbol, b#Symbol, c#Symbol) at .../byebug/old_doc/hanoi.rb:8 #2 at .../byebug/old_doc/hanoi.rb:34 (byebug) ``` In the above we added new commands: `break` (see [breakpoints]()), which indicates to stop just before that line of code is run, and `continue`, which resumes execution. Notice the difference between `display a` and `display a.inspect`. An implied string conversion is performed on the expression after it is evaluated. To remove a display expression `undisplay` is used. If we give a display number, just that display expression is removed. We also used a new command `where`(see [backtrace]()) to show the call stack. In the above situation, starting from the bottom line we see we called the `hanoi` method from line 34 of the file `hanoi.rb` and the `hanoi` method called itself two more times at line 4. In the call stack we show a _current frame_ mark, the frame number, the method being called, the names of the parameters, the types those parameters _currently_ have and the file-line position. Remember it's possible that when the program was called the parameters had different types, since the types of variables can change dynamically. You can alter the style of what to show in the trace (see [callstyle]()). Now let's move around the callstack. ``` (byebug) undisplay Clear all expressions? (y/n) y (byebug:1) i_args NameError Exception: undefined local variable or method `i_args' for main:Object (byebug:1) frame -1 #3 at hanoi.rb:34 (byebug:1) i_args 1 (byebug:1) p n 3 (byebug:1) down 2 #1 Object.hanoi(n#Fixnum, a#Symbol, b#Symbol, c#Symbol) at hanoi.rb:4 (byebug:1) p n 2 ``` Notice in the above to get the value of variable `n` we had to use a print command like `p n`. If we entered just `n`, that would be taken to mean byebug command `next`. In the current scope, variable `i_args` is not defined. However I can change to the top-most frame by using the `frame` command. Just as with arrays, -1 means the last one. Alternatively using frame number 3 would have been the same thing; so would issuing `up 3`. Note that in the outside frame #3, the value of `i_args` can be shown. Also note that the value of variable `n` is different. ### Unit Testing Session In the previous sessions we've been calling byebug right at the outset, but this is probably not the mode of operation you will use the most. There are a number of situations where calling byebug at the outset is impractical for a couple of reasons: * Byebug just doesn't work when run at the outset. Any debugging changes the behavior or the program in slight and subtle ways, and sometimes this can hinder finding bugs. * There's a lot of code that needs to be run before the part you want to inspect. Running this code takes time and you don't want the overhead of byebug. In this section we'll show how to enter the code in the middle of your program, while delving more into byebug's operation. We will also use unit testing. Using unit tests will greatly reduce the amount of debugging needed, while at the same time, will increase the quality of your program. What we'll do is take the `triangle` code from the first session and write a unit test for that. In a sense we did write a tiny test for the program which was basically the last line where we printed the value of `triangle(3)`. This test however wasn't automated: the expectation is that someone would look at the output and verify that what was printed is what was expected. Before we can turn that into something that can be `required`, we probably want to remove that output. However I like to keep in that line so that when I look at the file, I have an example of how to run it. Therefore we will conditionally run this line if that file is invoked directly, but skip it if it is not. _NOTE: `byebug` resets `$0` to try to make things like this work._ ``` if __FILE__ == $0 t = triangle(3) puts t end ``` Okay, we're now ready to write our unit test. We'll use `test/unit` which comes with the standard Ruby distribution. Here's the test code; it should be in the same directory as `triangle.rb`. ```ruby require 'test/unit' require_relative 'triangle.rb' class TestTri < Test::Unit::TestCase def test_basic solutions = [] 0.upto(5) do |i| solutions << triangle(i) end assert_equal([0, 1, 3, 6, 10, 15], solutions, 'Testing the first 5 triangle numbers') end end ``` Let's say we want to stop before the first statement in our test method, we'll add the following: ```ruby ... def test_basic require 'byebug' byebug solutions = [] ... ``` Now we run the program.. ``` $ ruby test-triangle.rb Run options: # Running tests: [1/1] TestTri#test_basic[5, 14] in test-triangle.rb 5: 6: class TestTri < Test::Unit::TestCase 7: def test_basic 8: require 'byebug' 9: byebug => 10: solutions = [] 11: 0.upto(5) do |i| 12: solutions << triangle(i) 13: end 14: assert_equal([0, 1, 3, 6, 10, 15], solutions, (byebug) ``` and we see that we are stopped at line 10 just before the initialization of the list `solutions`. Now let's see where we are... ``` (byebug) where --> #0 TestTri.test_basic at test-tri2.rb:10 Warning: saved frames may be incomplete; compare with caller(0) (byebug) ``` Something seems wrong here; `TestTri.test_basic` indicates that we are in class `TestTri` in method `test_basic`. However we don't see the call to this like we did in the last example when we used the `where` command. This is because byebug really didn't spring into existence until after we already had entered that method, and Ruby doesn't keep call stack information around in a way that would give the information we show when running `where`. If we want call stack information, we have to turn call-stack tracking on _beforehand_. This is done by adding `Byebug.start`. Here's what our test program looks like after we modify it to start tracking calls from the outset ```ruby require 'test/unit' require_relative 'triangle.rb' require 'byebug' Byebug.start class TestTri < Test::Unit::TestCase def test_basic byebug solutions = [] 0.upto(5) do |i| solutions << triangle(i) end assert_equal([0, 1, 3, 6, 10, 15], solutions, "Testing the first 5 triangle numbers") end end ``` Now when we run this: ``` $ ruby test-triangle.rb Run options: # Running tests: [1/1] TestTri#test_basic[5, 14] in test-triangle.rb 5: 6: class TestTri < Test::Unit::TestCase 7: def test_basic 8: require 'byebug' 9: byebug => 10: solutions = [] 11: 0.upto(5) do |i| 12: solutions << triangle(i) 13: end 14: assert_equal([0, 1, 3, 6, 10, 15], solutions, (byebug) where --> #0 TestTri.test_basic at test-triangle.rb:10 #1 MiniTest::Unit::TestCase.run_test(name#String) at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/test/unit.rb:858 #2 MiniTest::Unit::TestCase.run(runner#Test::Unit::Runner) at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/minitest/unit.rb:1301 #3 Test::Unit::TestCase.run(runner#Test::Unit::Runner) at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/test/unit/testcase.rb:17 #4 MiniTest::Unit._run_suite(suite#Class, type#Symbol) at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/minitest/unit.rb:919 #5 Array.map(suite#Class, type#Symbol) at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/minitest/unit.rb:912 #6 MiniTest::Unit._run_suite(suite#Class, type#Symbol) at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/minitest/unit.rb:912 #7 Test::Unit::Runner._run_suites(suites#Array, type#Symbol) at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/test/unit.rb:657 #8 Array.each(suites#Array, type#Symbol) at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/test/unit.rb:655 #9 Test::Unit::Runner._run_suites(suites#Array, type#Symbol) at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/test/unit.rb:655 #10 MiniTest::Unit._run_anything(type#Symbol) at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/minitest/unit.rb:867 #11 MiniTest::Unit.run_tests at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/minitest/unit.rb:1060 #12 MiniTest::Unit._run(args#Array) at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/minitest/unit.rb:1047 #13 Array.each(args#Array) at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/minitest/unit.rb:1046 #14 MiniTest::Unit._run(args#Array) at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/minitest/unit.rb:1046 #15 MiniTest::Unit._run(args#Array) at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/minitest/unit.rb:1042 #16 MiniTest::Unit.run(args#Array) at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/minitest/unit.rb:1035 #17 Test::Unit::RunCount.run(args#NilClass) at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/test/unit.rb:21 #18 Test::Unit::Runner.run(args#Array) at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/test/unit.rb:774 #19 #.autorun at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/test/unit.rb:366 #20 Test::Unit::RunCount.run_once at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/test/unit.rb:27 #21 #.autorun at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/test/unit.rb:367 #22
at test-triangle.rb:6 (byebug) ``` Much better. But again let me emphasize that the parameter types are those of the corresponding variables that _currently_ exist, and this might have changed since the time when the call was made. ### Byebug.start with a block We saw that `Byebug.start()` and `Byebug.stop()` allow fine-grain control over where byebug tracking should occur. Rather than use an explicit `stop()`, you can also pass a block to the `start()` method. This causes `start()` to run and then `yield` to that block. When the block is finished, `stop()` is run. In other words, this wraps a `Byebug.start()` and `Byebug.stop()` around the block of code. But it also has a side benefit of ensuring that in the presence of an uncaught exception `stop` is run, without having to explicitly use `begin ... ensure Byebug.stop() end`. For example, in Ruby on Rails you might want to debug code in one of the controllers without causing any slowdown to any other code. And this can be done by wrapping the controller in a `start()` with a block; when the method wrapped this way finishes, byebug is turned off and the application proceeds at regular speed. Of course, inside the block you will probably want to enter the byebug using `Byebug.byebug()`, otherwise there would be little point in using the `start`. For example, you can do this in `irb`: ``` $ irb 2.0.0p195 :001 > require 'byebug' => true 2.0.0p195 :002 > def foo 2.0.0p195 :003?> x=1 2.0.0p195 :004?> puts 'foo' 2.0.0p195 :005?> end => nil 2.0.0p195 :006 > Byebug.start{byebug; foo} (irb) @ 6 (byebug) s (irb) @ 3 (byebug) s (irb) @ 4 (byebug) p x 1 (byebug) s foo => true 2.0.0p195 :007 > ``` There is a counter inside of `Byebug.start` method to make sure that this works when another `Byebug.start` method is called inside of the outer one. However, if you are stopped inside byebug, issuing another `byebug` call will not have any effect even if it is nested inside another `Byebug.start`. ### Debugging Oddities: How debugging Ruby may be different from other languages If you are used to debugging in other languages like C, C++, Perl, Java or even Bash (see [bashdb](http://bashdb.sf.net)), there may be a number of things that seem or feel a little bit different and may confuse you. A number of these things aren't oddities of the debugger per se but differences in how Ruby works compared to those other languages. Because Ruby works a little differently from those other languages, writing a debugger has to also be a little different as well if it is to be useful. In this respect, using byebug may help you understand Ruby better. We've already seen two examples of such differences. One difference is the fact that we stop on method definitions or `def`'s and that is because these are in fact executable statements. In other compiled languages this would not happen because that's already been done when you compile the program (or in Perl when it scans in the program). The other difference we saw was our inability to show call stack parameter types without having made arrangements for byebug to track this. In other languages call stack information is usually available without asking assistance of the debugger (in C and C++, however, you generally have to ask the compiler to add such information.). In this section we'll consider some other things that might throw off new users to Ruby who are familiar with other languages and debugging in them. * Bouncing Around in Blocks (iterators) * No Parameter Values in a Call Stack * Lines You Can Stop At #### Bouncing Around in Blocks (iterators) When debugging languages with coroutines like Python and Ruby, a method call may not necessarily go to the first statement after the method header. It's possible that the call will continue after a `yield` statement from a prior call. ```ruby # Enumerator for primes class SievePrime @@odd_primes = [] def self.next_prime(&block) candidate = 2 yield candidate not_prime = false candidate += 1 while true do @@odd_primes.each do |p| not_prime = (0 == (candidate % p)) break if not_prime end unless not_prime @@odd_primes << candidate yield candidate end candidate += 2 end end end SievePrime.next_prime do |prime| puts prime break if prime > 10 end ``` ``` $ byebug primes.rb [1, 10] in /home/davidr/Proyectos/byebug/old_doc/primes.rb 1: # Enumerator for primes => 2: class SievePrime 3: @@odd_primes = [] 4: def self.next_prime(&block) 5: candidate = 2 6: yield candidate 7: not_prime = false 8: candidate += 1 9: while true do 10: @@odd_primes.each do |p| (byebug) set linetrace line tracing is on. (byebug) set basename basename in on. (byebug) step 9 Tracing: primes.rb:3 @@odd_primes = [] Tracing: primes.rb:4 def self.next_prime(&block) Tracing: primes.rb:22 SievePrime.next_prime do |prime| Tracing: primes.rb:5 candidate = 2 Tracing: primes.rb:6 yield candidate Tracing: primes.rb:23 puts prime 2 Tracing: primes.rb:24 break if prime > 10 Tracing: primes.rb:7 not_prime = false Tracing: primes.rb:8 candidate += 1 [3, 12] in /home/davidr/Proyectos/byebug/old_doc/primes.rb 3: @@odd_primes = [] 4: def self.next_prime(&block) 5: candidate = 2 6: yield candidate 7: not_prime = false => 8: candidate += 1 9: while true do 10: @@odd_primes.each do |p| 11: not_prime = (0 == (candidate % p)) 12: break if not_prime (byebug) ``` The loop between lines 23-26 gets interleaved between those of `Sieve::next_prime`, lines 6-19 above. #### No Parameter Values in a Call Stack In traditional debuggers, in a call stack you can generally see the names of the parameters and the values that were passed in. Ruby is a very dynamic language and it tries to be efficient within the confines of the language definition. Values generally aren't taken out of a variable or expression and pushed onto a stack. Instead a new scope is created and the parameters are given initial values. Parameter passing is by _reference_ not by _value_ as it is say Algol, C, or Perl. During the execution of a method, parameter values can change (and often do). In fact even the _class_ of the object can change. So at present, the name of the parameter is shown. The call-style setting ([callstyle]()) can be used to set whether the name is shown or the name and the _current_ class of the object. It has been contemplated that a style might be added which saves on call shorter "scalar" types of values and the class name. #### Lines You Can Stop At As with the duplicate stops per control (e.g. `if` statement), until tools like debuggers get more traction among core ruby developers there are going to be weirdness. Here we describe the stopping locations which effects the breakpoint line numbers you can stop at. Consider the following little Ruby program. ```ruby 'Yes it does' =~ / (Yes) \s+ it \s+ does /ix puts $1 ``` The stopping points that Ruby records are the last two lines, lines 5 and 6. Inside `byebug` you can get a list of stoppable lines for a file using the `info file` command with the attribute `breakpoints`. To be continued... * more complex example with objects, pretty printing and irb. * line tracing and non-interactive tracing. * mixing in Byebug.debug with byebug * post-mortem debugging and setting up for that * references to videos ## Getting in & out ### Starting byebug There is a wrapper script called `byebug` which basically `require`'s the gem then loads `byebug` before its argument (the program to be debugged) is started. ``` byebug [byebug-options] [--] ruby-script ruby-script-arguments ``` If you don't need to pass dash options to your program, which might be confused with byebug options, then you don't need to add the `--`. To get a brief list of options and descriptions, use the `--help` option. ``` $ byebug --help byebug 1.4.0 Usage: byebug [options] -- Options: -A, --annotate LEVEL Set annotation level -d, --debug Set $DEBUG=true -I, --include PATH Add PATH (single or multiple:path:list) to $LOAD_PATH --no-quit Do not quit when script finishes --no-stop Do not stop when script is loaded --nx Don't run any byebug initialization files --post-mortem Enable post-mortem mode for uncaught exceptions -r, --require SCRIPT Require library before script --restart-script FILE Name of the script file to run. Erased after read --script FILE Name of the script file to run -x, --trace Turn on line tracing Common options: --verbose Turn on verbose mode --help Show this message --version Print program version -v Print version number, then turn on verbose mode ``` Many options appear as a long option name, such as `--help` and a short one letter option name, such as `-h`. The list of options is detailed below: * **-h | --help**. It causes `byebug` to print some basic help and exit * **-v | --version**. It causes `byebug` to print its version number and exit. * **-A | --annotate **. Set gdb-style annotation `level`, a number. Additional information is output automatically when program state is changed. This can be used by front-ends such as GNU Emacs to post this updated information without having to poll for it. * **-d | --debug**. Set `$DEBUG` to `true`. Compatible with Ruby's. * **-I | --include **. Add `path` to load path. `path` can be a single path ar a colon separated path list. * **--post-mortem**. If your program raises an exception that isn't caught you can enter byebug for inspection of what went wrong. You may also want to use this option in conjunction with `--no-stop`. See also [Post-Mortem Debugging](). * **--no-quit**. Restart `byebug` when your program terminates normally. * **--no-stop**. Normally `byebug` stops before executing the first statement. If instead you want it to start running initially and perhaps break it later in the execution, use this option. * **--require | -r**. Require the library before executing the script. However, if the library happened to be `debug`, we'll just ignore the require since we're already a debugger. This option is compatible with Ruby's. * **--script **. Script to run before byebug's execution. * **-x | --trace**. Turn on line tracing. Running `byebug --trace .rb` is pretty much like running `ruby -rtracer .rb`. If all you want to do however is get a linetrace, `tracer` is most likely faster than `byebug` ``` $ time ruby -rtracer old_doc/gcd.rb 24 31 >/dev/null real 0m0.066s user 0m0.048s sys 0m0.016s $ time byebug --trace old_doc/gcd.rb 24 31 >/dev/null real 0m0.660s user 0m0.588s sys 0m0.056s ``` ### Byebug default options Byebug has many command-line options,; it seems that some people want to set them differently from the defaults. For example, some people may want `--no-quit` to be the default behavior. One could write a wrapper script or set a shell alias to handle this. But `byebug` has another way to do it. Before processing command options, if the file `$HOME/.byebugoptrc` is found, it is loaded. If you want to set the defaults in some other way, you can put Ruby code here and set variable `options` which is an OpenStruct. For example here's how you'd set `-no-quit` and a personal message. ```ruby # This file contains how you want the default options to byebug to be set. Any # Ruby code can be put here. # # byebug # Uncomment if you want to debug byebug! options.control = false puts "rocky's byebugrc run" ``` Here are the default values in `options` ```ruby # ``` ## Command Files A command file is a file of lines that are `byebug` commands. Comments (lines starting with `#`) may also be included. An empty line in a command file does nothing; it does not mean to repeat the last command, as it would from the terminal. When you start `byebug`, it automatically executes commands from its _init file_, called `.byebugrc`. During startup, `byebug` does the following: * __Processes command line options and operands.__ Reads the init file in your current directory, if any, and then checks your home directory. The home directory is the directory named in the `$HOME` or `$HOMEPATH` environment variable. Thus, you can have more than one init file, one generic in your home directory, and another, specific to the program you are debugging, in the directory where you invoke `byebug`. * __Reads command files specified by the `--script` option.__ You can also request the execution of a command file with the `source` command (see [Source]()). ## Quitting byebug Inside a byebug interpreter, use `quit` command to finish execution. Another way to terminate byebug is to use the `kill` command. This does the more forceful `kill -9`. It can be used in cases where `quit` doesn't work (I haven't seen it yet). ## Calling byebug from inside your program Running a program from byebug adds a bit of overhead and slows it down a little. Furthermore, by necessity, debuggers change the operation of the program they are debugging. And this can lead to unexpected and unwanted differences. It has happened so often that the term [Heisenbugs](http://en.wikipedia.org/wiki/Heisenbug}) was coined to describe the situation where using a debugger (among other possibilities) changes the behavior of the program so that the bug doesn't manifest itself anymore. There is another way to get into byebug which adds no overhead or slowdown until you reach the point at which you want to start debugging. However here you must change the script and make an explicit call to byebug. Because byebug isn't involved before the first call, there is no overhead and the script will run at the same speed as if there were no byebug. There are three parts to calling byebug from inside the script, ``requiring'' the gem, telling byebug to start tracking things and then making an explicit breakpoints. Unless you're using bundler, do this to get byebug class accessible from your Ruby program ```ruby require 'byebug' ``` To tell byebug to start tracking things, do ```ruby Byebug.start ``` There is also a `Byebug.stop` to turn off byebug tracking. If speed is crucial, you may want to start and stop this around certain sections of code. Alternatively, instead of issuing an explicit `Byebug.stop` you can add a block to the `Byebug.start` and debugging is turned on for that block. If the block of code raises an uncaught exception that would cause the block to terminate, the `stop` will occur. See [here](Byebug.start with a block). And finally to enter byebug ```ruby byebug ``` When `byebug`is run, `.byebugrc` is read. You may want to enter byebug at several points in the program where there is a problem you want to investigate. And since `byebug` is just a method call it's possible to enclose it in a conditional expression, for example ```ruby byebug if 'bar' == foo and 20 == iter_count ``` ## Byebug Command Reference ## Command Syntax Usually a command is put on a single line. There is no limit on how long it can be. It starts with a command name, which is followed by arguments whose meaning depends on the command name. For example, the command `step` accepts an argument which is the number of times to step, as in `step 5`. You can also use the `step` command with no arguments. Some commands do not allow any arguments. Multiple commands can be put on a line by separating each with a semicolon `;`. You can disable the meaning of a semicolon to separate commands by escaping it with a backslash. For example, if you have [autoeval]() set, which is the default, you might want to enter the following code to compute the 5th Fibonacci number. ``` (byebug) fib1=0; fib2=1; 5.times {|temp| temp=fib1; fib1=fib2; fib2 += temp } 0 1 SyntaxError Exception: /home/davidr/Proyectos/sample_app/trace.rb:1: syntax error, unexpected end-of-input, expecting '}' 5.times { |temp| temp=fib1 ^ nil 1 SyntaxError Exception: /home/davidr/Proyectos/sample_app/trace.rb:1: syntax error, unexpected tSTRING_DEND, expecting end-of-input fib2 += temp } ^ nil (byebug) fib1=0\; fib2=1\; 5.times {|temp| temp=fib1\; fib1=fib2\; fib2 += temp } 5 (byebug) fib2 8 ``` You might also consider using the [irb]() or [pry]() commands and then you won't have to escape semicolons. A blank line as input (typing just ``) means to repeat the previous command. Byebug uses readline, which handles line editing and retrieval of previous commands. Up arrow, for example, moves to the previous byebug command; down arrow moves to the next more recent command (provided you are not already at the last command). Command history is saved in file `.byebug_hist`. A limit is put on the history size. You can see this with the `show history size` command. See [history]() for history parameters. ### Command Output In the command-line interface, when `byebug` is waiting for input it presents a prompt of the form `(byebug)`. If the program has terminated normally the prompt will be `(byebug:ctrl)` and in post-mortem debugging it will be `(byebug:post-mortem)`. Whenever `byebug` gives an error message such as for an invalid command or an invalid location position, it will generally preface the message with `***`. However if annotation mode is on then the message is put in a `begin-error` annotation and no `***` appears. ### Help Once inside `byebug` you can always ask it for information on its commands using the `help` command. You can use `help` (abbreviated `h`) with no arguments to display a short list of named classes of commands ``` (byebug) `help` Type "help " for help on a specific command Available commands: backtrace catch continue disable down enable exit frame info jump list next pp putl reload save show source trace up where break condition delete display edit eval finish help irb kill method p ps quit restart set skip step undisplay var ``` With a command name as `help` argument, `byebug` displays short information on how to use that command. ``` (byebug) help list l[ist] list forward l[ist] - list backward l[ist] = list current line l[ist] nn-mm list given lines * NOTE - to turn on autolist, use 'set autolist' (byebug) ``` A number of commands, namely `info`, `set`, `show`, `enable` and `disable`, have many sub-parameters or _subcommands_. When you ask for help for one of these commands, you will get help for all of the subcommands that command offers. Sometimes you may want help only on a subcommand and to do this just follow the command with its subcommand name. For example `help set annotate` will just give help about the annotate command. Furthermore it will give longer help than the summary information that appears when you ask for help. You don't need to list the full subcommand name, just enough letters to make that subcommand distinct from others will do. For example, `help set an` is the same as `help set annotate`. Some examples follow. ``` (byebug) help info info[ subcommand] Generic command for showing things about the program being debugged. -- List of "info" subcommands: -- info args -- Argument variables of current stack frame info breakpoints -- Status of user-settable breakpoints info catch -- Exceptions that can be caught in the current stack frame info display -- Expressions to display when program stops info file -- Info about a particular file read in info files -- File names and timestamps of files read in info global_variables -- Global variables info instance_variables -- Instance variables of the current stack frame info line -- Line number and file name of current position in source file info locals -- Local variables of the current stack frame info program -- Execution status of the program info stack -- Backtrace of the stack info variables -- Local and instance variables of the current stack frame ``` ``` (byebug) help info breakpoints Status of user-settable breakpoints. Without argument, list info about all breakpoints. With an integer argument, list info on that breakpoint. ``` ``` (byebug) help info br Status of user-settable breakpoints. Without argument, list info about all breakpoints. With an integer argument, list info on that breakpoint. ```