18

I am very new in crystal language. I would like to know if a debugger like Ruby's Pry exists in Crystal?

It means that you can put in code something like 'binding.pry' at program stop execution at this line and let you control of variables.

andrewdotnich
  • 16,195
  • 7
  • 38
  • 57
Voldemar Duletskiy
  • 981
  • 1
  • 11
  • 30

2 Answers2

28

Although very incomplete, there is support for LLDB.

You may add debugger anywhere in your code to initiate a breakpoint for LLDB to stop at. You should (must?) build a binary with the -d or --debug flag, then run it using LLDB:

$ crystal build -d foo.cr
$ lldb ./foo
(lldb) run

See https://groups.google.com/forum/m/#!topic/crystal-lang/gRf-yDNdZ-Y for a more detailed example.

Julien Portalier
  • 2,959
  • 1
  • 20
  • 22
4

Update (2023): the Crystal interpreter (see original answer below) is now functional to a point that it support interactive debugging:

  • Run the code with crystal i
  • Set breakpoints in the code with debugger

For instance, this is a debugging session:

def bar(str, val)
  debugger
  puts "***\n#{str}\n***"
end

def foo(dummy)
  bar("test", dummy)
end

foo(42)
puts "Finished"
$ crystal i example.cr
From: example.cr:3:8 <Program>#bar:

    1: def bar(str, val)
    2:   debugger
 => 3:   puts "***\n#{str}\n***"
    4: end
    5: 
    6: def foo(dummy)
    7:   bar("test", dummy)
    8: end

pry(bar)> str
 => "test"
pry(bar)> str += " (changed with debugger)"
 => "test (changed with debugger)"
pry(bar)> next
***
test (changed with debugger)
***
From: example.cr:4:3 <Program>#bar:

    1: def bar(str, val)
    2:   debugger
    3:   puts "***\n#{str}\n***"
 => 4: end
    5: 
    6: def foo(dummy)
    7:   bar("test", dummy)
    8: end
    9: 

pry(bar)> continue
Finished

(The rest is the original answer from 2021. It is obsolete now, but contains some historic background of the development of the Crystal interpreter mode.)

At the time of writing this, there is only Julien's answer with compiling in debug mode, putting a debugger statement to create a breakpoint, and then running it with lldb. Yet there is a new trick on the horizon:

In his great talk Crystal on demand at the Crystal 1.0 Conference, Ary revealed a Crystal interpreter that he had been working on. It includes a REPL, but he also implemented a Pry-like debugger for Crystal on top of that.

It is not released yet, but you can see it in action in this talk. The section on the interactive debugger starts at 9:41.

It also uses the debugger statement to trigger a breakpoint. If you run the code with crystal i in interpreted mode, hitting the breakpoint will enter an interactive debug session like in Pry. The details might change, as it is was only a preview, but you can see the potential already.

If you want to follow the development, the pull request is #10910: crystal i (now reopened as #11159: crystal i).

Philipp Claßen
  • 41,306
  • 31
  • 146
  • 239
  • https://crystal-lang.org/2021/12/29/crystal-i/ explains more about crystal `debugger`, may have to compile from source to get interpreter; crystal devs do not compile distributed versions w/ interpreter. – Nick Dec 18 '22 at 17:45
  • 1
    @Nick It is merged but disabled by default. To enable it, you have to compile with the "interpreter" flag https://github.com/crystal-lang/crystal/blob/f4ae5f033b379fb96c00b04e344e6c17994b50e7/Makefile#L27 – Philipp Claßen Dec 18 '22 at 18:02
  • 1
    I updated the answer: the interpreter mode is now enabled by default and works very well in my tests. – Philipp Claßen Mar 09 '23 at 01:34