Debugging with Byebug

Cecil Coupe edited this page Jul 30, 2016 · 14 revisions
Clone this wiki locally

[update July, 29, 2016]

Shoes has had some byebug capability since 3.2.25 but it was pretty difficult to use and pretty clunky. In Shoes 3.3.2 we have two ways to debug a script. Three ways in try the remote debugger but that adds nothing but confusion so pretend it doesn't exist. all of them require a command line launch so use cshoes.exe on Windows or create a cshoes.sh script in OSX via the Cobbler (maintain shoes from the splash gets to cobbler) or the Linux equivalent.

For example, given a 'foo.rb' that looks like

# check Shoes::VERSION constants. Not pretty
Shoes.app do
  stack do
    clist = []
    Shoes.constants.sort.each do |c|
     if c[/VERSION/] 
       t = "Shoes::#{c}"
       clist << "#{c} = #{eval t}"
     end
    end
    @eb = edit_box  clist.join("\n"), :width => 400, height: 400
    button 'quit' do
      Shoes.quit
    end
  end
end

Then start debugging with cshoes.exe -d foo.rb -- you will get s terminal that looks like

[12, 21] in /home/ccoupe/Projects/shoes3/lib/shoes.rb
   12: else
   13:   # Normal shoes: 
   14:   # redefine quit and exit in Ruby to be Shoes implemented methods.
   15:   secret_exit_hook # maintains backwards compatibility
   16: end
=> 17: ARGV.delete_if { |x| x =~ /-psn_/ }
   18: 
   19: # Probably don't need this
   20: class Encoding
   21:   %w(UTF_7 UTF_16BE UTF_16LE UTF_32BE UTF_32LE).each do |enc|
(byebug) 

This is actually deep inside Shoes.rb. Where you may not want to be. You must set a breakpoint in your script and then continue Shoes until it gets to that breakpoint. Pretend we want to debug that Quit button behavior

(byebug) b foo.rb:13
Successfully created breakpoint with id 1
(byebug) c
Stopped by breakpoint 1 at foo.rb:13

[8, 17] in foo.rb
    8:        clist << "#{c} = #{eval t}"
    9:      end
   10:     end
   11:     @eb = edit_box  clist.join("\n"), :width => 400, height: 400
   12:     button 'quit' do
=> 13:       Shoes.quit
   14:       #exit
   15:     end
   16:   end
   17: end
(byebug) 

Of course that break point won't be reached until you actually click the button. If you set the break point on line 12 then you're just debugging the creation of the button and not the result of a click on the button. At the breakpoint you can do all kinds of byebug things. Also see here

It is strongly suggested to not use byebugs 'irb'. If you do and it complains about exit and quit alias, you can get back to byebug with a ^D keystroke. There is special place in hell if you try 'irb' at the very first byebug prompt when it's deep in Shoes startup. Don't be that person - set a breakpoint and continue.

CAUTION: If your script uses exit or quit methods to terminate Shoes instead of the better Shoes.quit you may find that it doesn't work when debugging. Use the window close button and modify your script to call Shoes.quit.

The other way of debugging is to explicitly ask for byebug in your script and you make it conditional on the command line arguments. If you start your Shoes app with a double click then the only argument is the script name (or perhaps nothing in the args - OSX). That's good for normal. Since you want to debug and that requires a terminal/console then you can add a small amount of Ruby in your script and call it differently.

Add this at the very top of your main Shoes script (myscript.rb for this example)

if ARGV.find_index('-d')
    ARGV.delete_if {|x| true}
    require 'byebug'
    byebug
end
Shoes.app do
# rest of script ....
end

If you launch with cshoes.exe myscript.rb -- -d then you'll get the byebug prompt and you can set a breakpoint and continue. If you launch from the desktop icon or cshoes.exe myscript then there is no -d arg possible. Unless you try really hard with Windows shortcuts or osx open --args which won't really work because it's not a terminal launch and byebug needs a terminal launch.

Remote

NOTE: This is likely to disappear.

For the remote ability you need Ruby installed and you need to have the byebug and rb-readline gems installed in that Ruby. Yes, it can/should be a different Ruby than Shoes is using. For Windows, that means you need to install RubyInstaller and the proper devkit. For OSX 10.9+ you can probably use the Ruby that Apple ships. For Linux, just install rvm and use it to install a ruby that's near current. 2.1.x would be an excellent choice.

Using that ruby from the command line. gem install rb-readline --no-doc and gem install byebug --no-doc

Example: Perhaps you want to debug sample/simple-sphere.rb. You need to put a byebug call in it. Which happens to be done in samples/expert-debug.

Start Shoes. type Alt-; ( ⌘-; for OSX) and you'll get a window telling you what to do

So start up another console and enter that command and you should be rewarded with

byebug -R localhost:8989
Connecting to byebug server...
Connected.

Now you use Shoes (splash screen) load the app that has that byebug command in it. Then the console shows

[1, 10] in expert-debug.rb
    1: Shoes.app :width => 500, :height => 500, :resizable => false do
    2:   byebug # breakpoint here
=>  3:   image 400, 470, :top => 30, :left => 50 do
    4:     nostroke
    5:     fill "#127"
    6:     image :top => 230, :left => 0 do
    7:       oval 70, 130, 260, 40
    8:       blur 30
    9:     end
   10:     oval 10, 10, 380, 380
(byebug) s

Notice how I issued the 's' command (step into) but because image is a Shoes command implemented in C, it just moved to the next Ruby line until I got bored and tried to invoke irb and then I just 'c' (continue - run until a breakpoint)

[13, 22] in expert-debug.rb
   13:       oval 30, 30, 338, 338
   14:       blur 10
   15:     end
   16:     fill gradient(rgb(1.0, 1.0, 1.0, 0.7), rgb(1.0, 1.0, 1.0, 0.0))
   17:     oval 80, 14, 240, 176
=> 18:     image :top => 0, :left => 0 do
   19:       fill "#79F"
   20:       oval 134, 134, 130, 130
   21:       blur 40
   22:     end
(byebug) irb
*** Command is available only in local mode.

(byebug) c

Like I said, remote debugging is a bit clunky. But it works.