## Debugging

This is a simple tutorial using the top-level processing Qt events:

      $ eql5 -qtpl

### Example 1: Error on REPL (trivial)

      EQL-USER[1]> (/ 0)

      Condition of type: DIVISION-BY-ZERO

      Available restarts:

      1. (RESTART-TOPLEVEL) Go back to Top-Level REPL.
      2. (RESTART-QT-EVENTS) Restart Qt event processing.

      ** BREAK [LEVEL 2]>

Note that all debug input is handled in a debug dialog, not in the console window.

So, either type the restart number in the dialog

      :r1

or just click Cancel / hit Escape, which will always choose `:r1`.

Type `:h` for all available debug options.

Both restarts will have the same effect here, see note at bottom.

### Example 2: Error during Qt event processing

Start calculator example:

      $ eql5 -qtpl examples/X-extras/calculator

Let's run this function:

      EQL-USER[1]> (clc:auto "42 ? blah")

This will output 2 errors, without breaking into the debugger:

      [EQL:err] QFIND-CHILD #<QDialog "" 0x39737d0 [1]> "?"

      [EQL:err] QINVOKE-METHOD NIL NIL "animateClick" (400)

Note: After eventual print output (like the above), you won't see a fresh top-level prompt.
Don't get confused by this, as you can continue to enter commands.

Now make EQL errors break into the debugger:

      EQL-USER[2]> (setf eql:*break-on-errors* t)

Run our function again:

      EQL-USER[3]> (clc:auto "42 ? blah")

      Condition of type: SIMPLE-CONDITION

      [EQL:err] QFIND-CHILD #<QDialog "" 0x39737d0 [1]> "?"

      Available restarts:

      1. (CONTINUE) Return from BREAK.
      2. (RESTART-QT-EVENTS) Restart Qt event processing.

      ** BREAK [LEVEL 1]>

Now there are 2 possible restarts:

      :r1

`(CONTINUE)` will continue execution, which will break on the next error, then finish our function.

      :r2

`(RESTART-QT-EVENTS)` will abort execution, returning to the REPL immediately.

### Notes

There is one situation where interactive debugging won't work, and this is in code inside an (overridden)

      "paintEvent(QPaintEvent*)"

function, as this may cause recursive paint events and segfaults.
To exit instantly from EQL during debugging (on nasty errors), just type

      :qq / :exit

in the debug dialog (or REPL).

Optionally you can also directly abort (see respective C function) by typing:

      :qa / :abort

On simple `read` errors on the REPL (e.g. non-existing packages, non-external symbols), the debugger will not be entered (as this would cause an unrecoverable `break`, since `read` runs in its own thread here); instead, the erroneous input string will be returned as-is.

The conflicting case

      (RESTART-TOPLEVEL)
      (RESTART-QT-EVENTS)

is resolved automatically (`RESTART-QT-EVENTS` would block the REPL in this case).

### Tips

You might want to put this in your `~/.eclrc` file:

      #+eql
      (setf eql:*qtpl*            t  ; same as -qtpl
            eql:*break-on-errors* t)

For running ECL / EQL through `gdb` (debugger), put this in your `~/.gdbinit` file:

      handle SIGPWR nostop noprint
      handle SIGXCPU nostop noprint

You may find

      (qproperties object &optional (depth 1))

very convenient for debugging, as it prints the current state of the interesting object.

In order to automatically switch the REPL to a given package after loading a file, add this line:

      (qlater (lambda () (in-package :my-package)))

If you use ECL readline (see `~/.eql5/lib/ecl-readline.lisp`, to be compiled manually after running EQL5 for the first time / updating ECL):
After entering `:qq` (quitting the top-level), the console/shell should always be reset (but you won't probably see the command while typing it; an `alias` might help):

      $ reset