# Debug in Skink: breakpoints, stepping and variables (DAP)

> Debug Rust, C, C++, Zig, Python and Go in Skink with gdb, lldb-dap, CodeLLDB, debugpy or delve: F5 to start, F9 for breakpoints, conditions, logpoints and launch.json.

Source: https://skink.cc/code/debugger/

Press F9 on a line to set a breakpoint, then F5 to start. Skink picks a configuration for you, or asks when there are several. When the program stops, step with F10, F11 and Shift+F11.

Skink speaks the Debug Adapter Protocol, so it drives the same debuggers VS Code uses.

## Debug keys

| Key | Typed command | Does |
|---|---|---|
| F5 | `:continue` | Start (the last configuration, else pick one), or continue |
| Shift+F5 | `:debug stop` | Stop the program (press again to kill the adapter) |
| F10 | `:step` | Step over |
| F11 | `:stepin` | Step into |
| Shift+F11 | `:stepout` | Step out |
| F6 | `:pause` | Pause the running program |
| F9 | `:breakpoint` | Breakpoint on the cursor line, on or off |
| Alt+F9 | `:condition` | Condition, hit count or log message for that breakpoint |
| Alt+L | `:debug panel` | The debug panel |
| Alt+K | `:hover` | While paused: the value at the cursor |

Outside a debug session, F10, F11, Shift+F11 and F6 keep their usual jobs: the menu bar, close the terminal, terminal history and next problem.

Clicking the sign column also toggles a breakpoint.

## Install a debug adapter

Skink finds the adapter on your `PATH`:

| Adapter | For | `type` in launch.json |
|---|---|---|
| gdb 14 or newer (`gdb -i dap`) | C, C++, Rust, Zig | `gdb` |
| `lldb-dap` | C, C++, Rust (LLVM) | `lldb-dap` |
| `codelldb` | C, C++, Rust (CodeLLDB) | `lldb` |
| debugpy (`pip install debugpy`) | Python | `debugpy` |
| `dlv` (`dlv dap`) | Go | `go` |

JavaScript debugging (js-debug) is not supported yet.

## While the program is paused

- The stopped line is highlighted.
- Local values show at the ends of the lines above it.
- Alt+K on a name shows its value.

The panel (Alt+L) holds the rest:

| Part | Keys |
|---|---|
| Call stack | Enter shows a frame |
| Variables | Enter or Space expands |
| Watch | w adds, d removes |
| Breakpoints | Enter jumps, d removes |
| Console | e evaluates an expression |

Programs that the adapter runs "in a terminal" open in a terminal tab, so you can type into them.

## Conditions and logpoints

Put the cursor on a breakpoint's line and press Alt+F9, or type one of:

| Command | Does |
|---|---|
| `:breakpoint if i > 3` | Stop only when the condition holds |
| `:breakpoint hits 5` | Stop on the fifth hit |
| `:breakpoint log x={x}` | Print a message instead of stopping |
| `:breakpoint clear` | Remove every breakpoint in this file |
| `:breakpoint clearall` | Remove every breakpoint |
| `:breakpoint list` | List them |

Breakpoints move with your edits, and the session remembers them and your watches.

## Configurations

With no config file, F5 offers what it can find:

- each cargo binary
- the Python file or pytest test at the cursor
- the Go package or test at the cursor
- a native program built next to the file (`cc -g x.c -o x`)

For more control, write `.skink/launch.json`. An existing `.vscode/launch.json` works too.

```jsonc
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "server",
      "type": "gdb",
      "request": "launch",
      "program": "${workspaceFolder}/target/debug/server",
      "args": ["--port", "8080"],
      "preLaunchTask": "build"
    }
  ]
}
```

Skink reads this subset of VS Code's format:

- `name`, `type`, `request` (`launch` or `attach`)
- `preLaunchTask`: a task label from [tasks.json](https://skink.cc/code/tasks/), run before the program starts
- per-OS overrides under `linux`, `osx` and `windows`

Every other field goes to the adapter as written, with `${workspaceFolder}`, `${file}` and the other variables expanded.

| Command | Does |
|---|---|
| `:debug` | Pick a configuration |
| `:debug NAME` | Start one by name |
| `:debug restart` / `:debug pause` / `:debug stop` | Control the session |
| `:debug eval EXPR` | Evaluate an expression |
| `:debug watch EXPR` | Add a watch |

**Note:**
The debugger has been tested most with gdb. If an adapter misbehaves, `:debug stop` twice kills it.
