Breakpoint synchronization¶
Breakpoints are shared between the editor and the debugger through one file. This page explains how, and what the sharing does and does not guarantee.
One file, two readers¶
<root>/.bugsaur/
├── config.toml the project — shared, committed
├── breakpoints.json your breakpoints — personal, ignored by git
└── .gitignore created on the first write
Neovim writes breakpoints.json; the debugger reads it. That is the whole
mechanism, and it gives three properties:
- They survive a Neovim restart. The set is restored when you next open the file. You do not re-create breakpoints after restarting your editor.
- The terminal and the editor agree.
bugsaur run --project .with no--breakstarts with exactly the breakpoints:DebugStartwould use. - They survive a move. Paths are stored relative to the project root, so moving or renaming the project directory does not invalidate the set.
Personal, not shared¶
On the first write, a .bugsaur/.gitignore is created next to the file, which
hides breakpoints.json from git. config.toml is the project's; breakpoints
are yours.
An existing .gitignore is left alone — if you have your own, add the
breakpoints.json line by hand.
Line numbers are stored as written¶
The line number is stored literally. If a file changes outside the editor — a
rebase, a git checkout, a code formatter run while Neovim is closed — the
breakpoint stays on its old line number and you will have to move it.
Files outside any project¶
A file that is not under any .bugsaur/ root has nowhere to be saved. Its
breakpoints live until the end of the editor session and are then gone. That is
a consequence of the storage being per project, not a bug.
The command line can override the file¶
An explicit --break replaces the saved set entirely, rather than adding to
it. Without --break, the saved set is used as-is.
:DebugTest behaves the same way as an explicit set: a test run uses only the
breakpoints of that request, not the saved ones.
The three states of a breakpoint¶
The sign in the gutter shows what the adapter said:
| Sign | State | Meaning |
|---|---|---|
● |
verified | the adapter accepted it at that line |
○ |
pending | no answer yet |
⊗ |
rejected | the adapter refused it |
The adapter is allowed to move a breakpoint off the line you asked for. When it
does, the requested line gets no confirmation and stays pending — the state
reflects the answer to your request, not the presence of a breakpoint somewhere
nearby.
The same states appear as circles in the window's Breakpoints panel.
Reacting to changes from a plugin¶
Any change to the set fires a User autocommand:
vim.api.nvim_create_autocmd("User", {
pattern = "BugsaurBreakpointsChanged",
callback = function(event)
-- event.data.paths — the affected files
end,
})
This fires for changes from :ToggleBreakpoint, from the Lua API, and from
reading a file's set off disk. Full API: Commands.