chore: release 0.1.0 — rename to turbo-debug.nvim

Rename from tiny-debugger to turbo-debug — inspired by Turbo Pascal,
the first IDE with a real visual debugger. This thing isn't tiny,
it's turbo charged.

CHANGELOG for 0.1.0:

Features:
- Zero-config debugging — one line install, everything works
- Modal keybindings (c/s/d/r/q/x/X/D/W/K/E/R/?), active only
  during debug mode, cleanly removed on exit
- Persistent breakpoints via persistent-breakpoints.nvim
- Inline virtual text — variable values in source code
- Hover (K), watch (W), REPL eval (E) from the code window
- Help splash (3s auto-dismiss) + manual help (?)
- Debug mode chrome — winbar indicator, cursor highlight
- dapui integration — controls toolbar, labeled panels
- which-key support — <leader>d debug group auto-registered
- quit_exits_mode option

Adapters (12 languages):
- Python (debugpy + venv detection)
- Rust (codelldb + cargo build + vim.ui.select picker)
- Go (delve), C/C++/Swift (codelldb)
- JavaScript/TypeScript (js-debug-adapter)
- C# (netcoredbg), Java, Kotlin, PHP, Ruby, Lua (osv)

Keybindings:
- <leader>dd — toggle debug mode
- <leader>dx / <leader>dX / <leader>dD — breakpoints (always)
- c s d r C x X D W K E q R ? — modal (debug mode only)
This commit is contained in:
swaits committed 2026-04-11 20:09:29 -06:00
1 parent d5331800b4
commit e9089b63a2
23 files changed
+197 -149

No files matched your search

+39
View File
@@ -0,0 +1,39 @@
# Changelog
## 0.1.0 — 2026-04-11
Initial release.
### Features
- **Zero-config debugging** — one line install, everything works
- **Modal keybindings** — single-key debug controls (`c`/`s`/`d`/`r`/`q`), active only during debug mode, cleanly removed on exit
- **Persistent breakpoints** — survive Neovim restarts via persistent-breakpoints.nvim
- **Inline virtual text** — variable values shown in source code during stepping
- **Hover inspection** (`K`) and **watch expressions** (`W`) from the code window
- **REPL eval** (`E`) — floating REPL for expression evaluation
- **Help splash** — centered keybinding reference on debug mode entry (3s auto-dismiss), re-openable with `?`
- **Debug mode chrome** — winbar indicator, cursor highlight, dapui panel titles
- **dapui integration** — opinionated layout with controls toolbar, labeled panels (Scopes, Watches, Call Stack, Console, REPL)
- **which-key support** — `<leader>d` debug group registered automatically if which-key is installed
- **`quit_exits_mode`** option — control whether `q` terminates only or also exits debug mode
### Adapters (12 languages)
- **Python** — debugpy with virtualenv auto-detection (VIRTUAL_ENV, CONDA_PREFIX, .venv)
- **Rust** — codelldb with `cargo build` integration and `vim.ui.select` binary picker
- **Go** — delve with auto-launch (file and package configs)
- **C / C++ / Swift** — codelldb with executable prompt
- **JavaScript / TypeScript** — js-debug-adapter (pwa-node, launch + attach)
- **C#** — netcoredbg
- **Java** — java-debug-adapter
- **Kotlin** — kotlin-debug-adapter
- **PHP** — php-debug (Xdebug listener)
- **Ruby** — rdbg (launch + attach)
- **Lua (Neovim)** — osv (optional, graceful skip if not installed)
### Keybinding scheme
- `<leader>dd` — toggle debug mode
- `<leader>dx` / `<leader>dX` / `<leader>dD` — breakpoints (always available)
- `c s d r C x X D W K E q R ?` — modal keys (debug mode only)
+1 -1
View File
@@ -4,7 +4,7 @@ We use **jj** (Jujutsu) for source control, not git.
## Adding a new adapter
1. Create `lua/tiny-debugger/adapters/<language>.lua` (see `go.lua` for reference)
1. Create `lua/turbo-debug/adapters/<language>.lua` (see `go.lua` for reference)
2. Add the module name to the loader list in `adapters/init.lua`
3. Add the language to vimdoc
+3 -3
View File
@@ -1,4 +1,4 @@
# tiny-debugger.nvim
# turbo-debug.nvim
A zero-config debugging experience for Neovim 0.12+. One plugin install, full
IDE-class debugging: inline variable values, hover inspection, persistent
@@ -7,10 +7,10 @@ breakpoints, watch expressions, and modal keybindings that just work.
## Install
```lua
vim.pack.add("swaits/tiny-debugger.nvim")
vim.pack.add("swaits/turbo-debug.nvim")
```
That's it. No other config needed. See `:help tiny-debugger` for customization.
That's it. No other config needed. See `:help turbo-debug` for customization.
## Usage
+56 -47
View File
@@ -1,23 +1,23 @@
*tiny-debugger.txt* A zero-config debugging experience for Neovim 0.12+
*turbo-debug.txt* A zero-config debugging experience for Neovim 0.12+
==============================================================================
CONTENTS *tiny-debugger-contents*
CONTENTS *turbo-debug-contents*
1. Introduction .......................... |tiny-debugger-introduction|
2. Installation .......................... |tiny-debugger-installation|
3. Setup ................................. |tiny-debugger.setup|
4. Debug Mode ............................ |tiny-debugger-debug-mode|
5. Keybindings ........................... |tiny-debugger.keys|
6. Breakpoints ........................... |tiny-debugger-breakpoints|
7. UI Layout ............................. |tiny-debugger-layout|
8. Adapters .............................. |tiny-debugger.adapters|
9. API ................................... |tiny-debugger-api|
10. Troubleshooting ....................... |tiny-debugger-troubleshooting|
1. Introduction .......................... |turbo-debug-introduction|
2. Installation .......................... |turbo-debug-installation|
3. Setup ................................. |turbo-debug.setup|
4. Debug Mode ............................ |turbo-debug-debug-mode|
5. Keybindings ........................... |turbo-debug.keys|
6. Breakpoints ........................... |turbo-debug-breakpoints|
7. UI Layout ............................. |turbo-debug-layout|
8. Adapters .............................. |turbo-debug.adapters|
9. API ................................... |turbo-debug-api|
10. Troubleshooting ....................... |turbo-debug-troubleshooting|
==============================================================================
1. Introduction *tiny-debugger-introduction*
1. Introduction *turbo-debug-introduction*
tiny-debugger.nvim gives you a fully-featured, beautiful debugging experience
turbo-debug.nvim gives you a fully-featured, beautiful debugging experience
out of one line of config. Under the hood it wires together nvim-dap,
nvim-dap-ui, nvim-dap-virtual-text, and persistent-breakpoints into a single
cohesive experience with modal keybindings.
@@ -33,60 +33,61 @@ Features:
- Zero-config adapters for 10+ languages
==============================================================================
2. Installation *tiny-debugger-installation*
2. Installation *turbo-debug-installation*
Add one line to your init.lua: >lua
vim.pack.add("swaits/tiny-debugger.nvim")
vim.pack.add("swaits/turbo-debug.nvim")
<
That's it. All dependencies are managed automatically.
Requires Neovim >= 0.12.
==============================================================================
3. Setup *tiny-debugger.setup*
3. Setup *turbo-debug.setup*
Setup is optional. The plugin works with no configuration. To customize: >lua
require("tiny-debugger").setup({
help_on_enter = true, -- show help box when entering debug mode
require("turbo-debug").setup({
help_on_enter = true, -- show help splash on debug mode entry
quit_exits_mode = true, -- q terminates AND exits debug mode
builtin_adapters = true, -- register built-in language adapters
keys = { ... }, -- override keybindings
keys = { ... }, -- override modal keybindings
global_keys = { ... }, -- override always-available keybindings
adapters = { ... }, -- override or add language adapters
dapui = { ... }, -- override nvim-dap-ui layout/settings
virtual_text = { ... }, -- override nvim-dap-virtual-text settings
})
<
*tiny-debugger.setup.help_on_enter*
*turbo-debug.setup.help_on_enter*
help_on_enter ~
Type: boolean, Default: `true`
Show the help box automatically when entering debug mode.
*tiny-debugger.setup.builtin_adapters*
*turbo-debug.setup.builtin_adapters*
builtin_adapters ~
Type: boolean, Default: `true`
Register built-in adapters for supported languages. Set to `false` to
disable all built-in adapter registration.
==============================================================================
4. Debug Mode *tiny-debugger-debug-mode*
4. Debug Mode *turbo-debug-debug-mode*
Press `<leader>d` to toggle debug mode.
Press `<leader>dd` to toggle debug mode.
Entering debug mode:
1. Opens nvim-dap-ui with the configured layout
2. Enables inline virtual text for variable values
3. Activates modal keybindings (buffer-local)
4. Changes cursor highlight to indicate debug mode
5. Shows help box (if `help_on_enter` is true)
4. Shows winbar indicator and help splash (3s)
Exiting debug mode (any of):
- `<leader>d` again (manual toggle)
- `q` (terminate session — auto-exits debug mode)
- `<leader>dd` again (manual toggle)
- `q` (terminate session — exits debug mode if `quit_exits_mode`)
- DAP session ends naturally
On exit, everything is restored: keymaps, UI, virtual text, cursor.
==============================================================================
5. Keybindings *tiny-debugger.keys*
5. Keybindings *turbo-debug.keys*
Modal keybindings are active only during debug mode. They shadow editing
keys you don't need while debugging, but preserve all navigation keys.
@@ -99,6 +100,9 @@ Default keymap:
`d` Step into Descend into the function
`r` Step out Return from the function
`C` Run to cursor Continue to cursor
`x` Toggle breakpoint X marks the spot
`X` Conditional breakpoint Shift variant of x
`D` Clear all breakpoints Delete all
`W` Watch expr under cursor Watch
`K` Hover / inspect Matches LSP hover convention
`E` Eval in REPL Evaluate
@@ -114,7 +118,7 @@ Always available (under `<leader>d` prefix, with which-key support):
`<leader>dD` Clear all breakpoints Delete all
Override any key: >lua
require("tiny-debugger").setup({
require("turbo-debug").setup({
keys = { -- modal keys (debug mode only)
continue = "g",
step_over = false, -- set to false to disable
@@ -131,19 +135,24 @@ Preserved keys (not shadowed):
- Visual/yank: `v V y p u`
- All Ctrl/leader combos
*turbo-debug.setup.quit_exits_mode*
quit_exits_mode ~
Type: boolean, Default: `true`
Whether `q` (terminate) also exits debug mode. Set to `false` if you
want `q` to terminate the process but keep the debug UI open.
==============================================================================
6. Breakpoints *tiny-debugger-breakpoints*
6. Breakpoints *turbo-debug-breakpoints*
Breakpoints are managed by persistent-breakpoints.nvim. They persist across
Neovim restarts and are visible in the sign column at all times.
`x` toggles a breakpoint on the current line.
`X` prompts for a condition and sets a conditional breakpoint.
Both work outside debug mode — no need to enter debug mode first.
`<leader>dx` toggles a breakpoint (always available).
`<leader>dX` sets a conditional breakpoint (always available).
`x`, `X`, `D` also work as shortcuts during debug mode.
==============================================================================
7. UI Layout *tiny-debugger-layout*
7. UI Layout *turbo-debug-layout*
Default layout:
@@ -157,14 +166,14 @@ Default layout:
- Console (50%) — program stdout/stderr
Override the layout: >lua
require("tiny-debugger").setup({
require("turbo-debug").setup({
dapui = {
layouts = { ... }, -- see nvim-dap-ui docs for format
},
})
<
==============================================================================
8. Adapters *tiny-debugger.adapters*
8. Adapters *turbo-debug.adapters*
Built-in adapter support (adapter binary must be installed):
@@ -190,7 +199,7 @@ Path resolution order:
Adapter binaries are the user's responsibility to install.
Override or add adapters: >lua
require("tiny-debugger").setup({
require("turbo-debug").setup({
adapters = {
python = { ... }, -- override built-in
zig = { ... }, -- add new language
@@ -201,23 +210,23 @@ Override or add adapters: >lua
Existing user nvim-dap configurations are never overridden.
==============================================================================
9. API *tiny-debugger-api*
9. API *turbo-debug-api*
*tiny-debugger.toggle()*
require("tiny-debugger").toggle()
*turbo-debug.toggle()*
require("turbo-debug").toggle()
Toggle debug mode on/off.
*tiny-debugger.active()*
require("tiny-debugger").active()
*turbo-debug.active()*
require("turbo-debug").active()
Returns `true` if debug mode is currently active, `false` otherwise.
Useful for statusline integration.
==============================================================================
10. Troubleshooting *tiny-debugger-troubleshooting*
10. Troubleshooting *turbo-debug-troubleshooting*
No adapter found ~
Ensure the adapter binary is installed and on your PATH, or installed
via mason.nvim. tiny-debugger configures adapters, it does not install
via mason.nvim. turbo-debug configures adapters, it does not install
them.
Breakpoints not persisting ~
@@ -230,7 +239,7 @@ Virtual text not appearing ~
`:lua print(require("nvim-dap-virtual-text") and "ok")`
Version error ~
tiny-debugger.nvim requires Neovim >= 0.12 for vim.pack support.
turbo-debug.nvim requires Neovim >= 0.12 for vim.pack support.
==============================================================================
vim:tw=78:ts=8:ft=help:norl:
@@ -1,4 +1,4 @@
local loader = require("tiny-debugger.adapters.init")
local loader = require("turbo-debug.adapters.init")
local M = {}
@@ -1,4 +1,4 @@
local loader = require("tiny-debugger.adapters.init")
local loader = require("turbo-debug.adapters.init")
local M = {}
@@ -1,4 +1,4 @@
local config = require("tiny-debugger.config")
local config = require("turbo-debug.config")
local M = {}
@@ -92,7 +92,7 @@ function M.setup()
-- load adapters with non-trivial logic from separate files
for _, name in ipairs({ "python", "go", "c", "javascript" }) do
local ok, adapter_mod = pcall(require, "tiny-debugger.adapters." .. name)
local ok, adapter_mod = pcall(require, "turbo-debug.adapters." .. name)
if ok and adapter_mod.register then
adapter_mod.register(dap)
end
@@ -1,4 +1,4 @@
local loader = require("tiny-debugger.adapters.init")
local loader = require("turbo-debug.adapters.init")
local M = {}
@@ -1,4 +1,4 @@
local loader = require("tiny-debugger.adapters.init")
local loader = require("turbo-debug.adapters.init")
local M = {}
@@ -1,4 +1,4 @@
local config = require("tiny-debugger.config")
local config = require("turbo-debug.config")
local M = {}
File renamed without changes.
@@ -1,4 +1,4 @@
local config = require("tiny-debugger.config")
local config = require("turbo-debug.config")
local M = {}
@@ -30,7 +30,7 @@ local global_info = {
}
local function build_content()
local lines = { " tiny-debugger", "" }
local lines = { " turbo-debug", "" }
local width = #lines[1]
local function add(key, label)
@@ -1,12 +1,12 @@
local config = require("tiny-debugger.config")
local mode = require("tiny-debugger.mode")
local config = require("turbo-debug.config")
local mode = require("turbo-debug.mode")
local M = {}
function M.setup(opts)
config.merge(opts)
require("tiny-debugger.breakpoints").setup()
require("tiny-debugger.adapters").setup()
require("turbo-debug.breakpoints").setup()
require("turbo-debug.adapters").setup()
-- global toggle keybinding
local toggle_key = config.opts.global_keys.toggle
@@ -1,5 +1,5 @@
local config = require("tiny-debugger.config")
local help = require("tiny-debugger.help")
local config = require("turbo-debug.config")
local help = require("turbo-debug.help")
local M = {}
@@ -20,10 +20,10 @@ local function ensure_dapui()
require("dapui").setup(config.opts.dapui)
local dap = require("dap")
dap.listeners.after.event_terminated["tiny-debugger"] = function()
dap.listeners.after.event_terminated["turbo-debug"] = function()
if active then M.exit() end
end
dap.listeners.after.event_exited["tiny-debugger"] = function()
dap.listeners.after.event_exited["turbo-debug"] = function()
if active then M.exit() end
end
@@ -139,9 +139,9 @@ local function set_keymaps(buf)
for name, key in pairs(keys) do
if key and actions[name] then
stash_mapping(buf, key)
vim.keymap.set("n", key, actions[name], { buffer = buf, silent = true, desc = "tiny-debugger: " .. name })
vim.keymap.set("n", key, actions[name], { buffer = buf, silent = true, desc = "turbo-debug: " .. name })
if visual_actions[name] then
vim.keymap.set("v", key, actions[name], { buffer = buf, silent = true, desc = "tiny-debugger: " .. name })
vim.keymap.set("v", key, actions[name], { buffer = buf, silent = true, desc = "turbo-debug: " .. name })
end
mapped_keys[#mapped_keys + 1] = { name = name, key = key }
end
@@ -1,7 +1,7 @@
-- tiny-debugger.nvim — entry point
-- turbo-debug.nvim — entry point
if vim.fn.has("nvim-0.12") ~= 1 then
vim.notify("tiny-debugger.nvim requires Neovim >= 0.12", vim.log.levels.ERROR)
vim.notify("turbo-debug.nvim requires Neovim >= 0.12", vim.log.levels.ERROR)
return
end
@@ -17,4 +17,4 @@ pcall(function()
end)
-- setup immediately (idempotent — user can call setup() again with overrides)
require("tiny-debugger").setup()
require("turbo-debug").setup()
+1 -1
View File
@@ -1,3 +1,3 @@
-- Minimal init for testing tiny-debugger.nvim
-- Minimal init for testing turbo-debug.nvim
vim.opt.runtimepath:prepend(vim.fn.getcwd())
package.path = vim.fn.getcwd() .. "/tests/?.lua;" .. package.path
+2 -2
View File
@@ -1,5 +1,5 @@
local assert_eq = require("helpers").assert_eq
local loader = require("tiny-debugger.adapters.init")
local loader = require("turbo-debug.adapters.init")
local dap = require("dap")
-- find_executable returns nil for non-existent binaries
@@ -10,7 +10,7 @@ assert_eq(loader.find_executable({ "sh" }) ~= nil, true, "find_executable finds
-- all adapter modules load and have register()
for _, name in ipairs({ "python", "go", "c", "javascript" }) do
assert_eq(type(require("tiny-debugger.adapters." .. name).register), "function", name .. " has register()")
assert_eq(type(require("turbo-debug.adapters." .. name).register), "function", name .. " has register()")
end
-- register doesn't override existing adapter
+1 -1
View File
@@ -1,5 +1,5 @@
local assert_eq = require("helpers").assert_eq
local td = require("tiny-debugger")
local td = require("turbo-debug")
td.setup()
-- global breakpoint mappings exist under <leader>d prefix
+1 -1
View File
@@ -1,5 +1,5 @@
local assert_eq = require("helpers").assert_eq
local config = require("tiny-debugger.config")
local config = require("turbo-debug.config")
-- defaults unchanged after empty merge
local opts = config.merge({})
+2 -2
View File
@@ -1,6 +1,6 @@
local assert_eq = require("helpers").assert_eq
local help = require("tiny-debugger.help")
local config = require("tiny-debugger.config")
local help = require("turbo-debug.help")
local config = require("turbo-debug.config")
-- open creates a valid window
help.open()
+2 -2
View File
@@ -1,5 +1,5 @@
local assert_eq = require("helpers").assert_eq
local td = require("tiny-debugger")
local td = require("turbo-debug")
-- set a custom mapping for 'c'
vim.keymap.set("n", "c", function() end, { buffer = 0, desc = "custom c" })
@@ -11,7 +11,7 @@ assert_eq(maparg.desc, "custom c", "custom mapping exists before enter")
-- enter debug mode — should override 'c'
td.toggle()
maparg = vim.fn.maparg("c", "n", false, true)
assert_eq(maparg.desc, "tiny-debugger: continue", "c overridden in debug mode")
assert_eq(maparg.desc, "turbo-debug: continue", "c overridden in debug mode")
-- exit debug mode — should restore custom 'c'
td.toggle()
+1 -1
View File
@@ -1,5 +1,5 @@
local assert_eq = require("helpers").assert_eq
local td = require("tiny-debugger")
local td = require("turbo-debug")
local function has_buf_map(key)
for _, m in ipairs(vim.api.nvim_buf_get_keymap(0, "n")) do
+66 -66
View File
@@ -1,4 +1,4 @@
# tiny-debugger.nvim — Product Specification
# turbo-debug.nvim — Product Specification
## What Is This?
@@ -14,7 +14,7 @@ and persistent-breakpoints into a single cohesive experience with modal
keybindings. The user installs one plugin and gets everything.
```lua
vim.pack.add("swaits/tiny-debugger.nvim")
vim.pack.add("swaits/turbo-debug.nvim")
```
That's it. That's the whole setup.
@@ -81,7 +81,7 @@ One plugin install. Zero configuration. All of this:
## Dependencies (Managed Automatically)
The user never sees or declares these. tiny-debugger calls `vim.pack.add` for
The user never sees or declares these. turbo-debug calls `vim.pack.add` for
each one internally:
| Dependency | What it provides |
@@ -132,7 +132,7 @@ C/C++/Rust only). Out of scope.
```lua
-- init.lua
vim.pack.add("swaits/tiny-debugger.nvim")
vim.pack.add("swaits/turbo-debug.nvim")
```
One line. One plugin. Everything works.
@@ -140,7 +140,7 @@ One line. One plugin. Everything works.
### Configuration (optional)
```lua
require("tiny-debugger").setup({
require("turbo-debug").setup({
-- all fields optional, these are the defaults
help_on_enter = true, -- show help box when entering debug mode
keys = { ... }, -- override any keybinding
@@ -293,7 +293,7 @@ use the standard nvim-dap-ui element keybindings.
## UI Layout
tiny-debugger configures nvim-dap-ui with a clean, purposeful layout:
turbo-debug configures nvim-dap-ui with a clean, purposeful layout:
```
┌──────────────────────────────────┬──────────────────┐
@@ -428,16 +428,16 @@ For every adapter, we check paths in this order:
### Behavior
- On first `c` (continue), if no `dap.configurations` exist for the current
filetype, tiny-debugger installs its built-in config automatically.
filetype, turbo-debug installs its built-in config automatically.
- If the user has already configured adapters for a filetype via nvim-dap
directly, tiny-debugger does not override them.
directly, turbo-debug does not override them.
- Adapter binary installation is the user's responsibility (mason, system
package manager, or manual). tiny-debugger configures, it doesn't install.
package manager, or manual). turbo-debug configures, it doesn't install.
### Configuration
```lua
require("tiny-debugger").setup({
require("turbo-debug").setup({
adapters = {
python = { ... }, -- override built-in
zig = { ... }, -- add new language
@@ -500,16 +500,16 @@ This is a canonical Neovim plugin with proper help docs, license, and
everything a user or contributor expects.
```
tiny-debugger.nvim/
turbo-debug.nvim/
├── LICENSE -- MIT
├── README.md -- install, quick start, screenshots
├── CONTRIBUTING.md -- how to add adapters, run tests
├── doc/
│ └── tiny-debugger.txt -- :help tiny-debugger (vimdoc format)
│ └── turbo-debug.txt -- :help turbo-debug (vimdoc format)
├── plugin/
│ └── tiny-debugger.lua -- vim.pack.add deps, global x/X maps, setup
│ └── turbo-debug.lua -- vim.pack.add deps, global x/X maps, setup
├── lua/
│ └── tiny-debugger/
│ └── turbo-debug/
│ ├── init.lua -- public API (setup, toggle, active)
│ ├── config.lua -- default opts, deep merge with user opts
│ ├── mode.lua -- enter/exit debug mode, keybinding mgmt
@@ -541,10 +541,10 @@ tiny-debugger.nvim/
### Key Mechanisms
**Dependency management:** `plugin/tiny-debugger.lua` calls `vim.pack.add`
**Dependency management:** `plugin/turbo-debug.lua` calls `vim.pack.add`
for each of the five dependencies. The user never sees or manages them.
**Plugin wiring:** tiny-debugger calls `setup()` on nvim-dap-ui,
**Plugin wiring:** turbo-debug calls `setup()` on nvim-dap-ui,
nvim-dap-virtual-text, and persistent-breakpoints with its opinionated
defaults, deep-merged with any user overrides from `opts`.
@@ -569,7 +569,7 @@ Autocmd to close on any keypress. Content built from the keys table.
### What We Don't Do
- No custom UI widgets. nvim-dap-ui handles that.
- No statusline integration beyond exposing `require("tiny-debugger").active()`.
- No statusline integration beyond exposing `require("turbo-debug").active()`.
- No telescope/fzf integration. Out of scope.
- No reverse debugging built-in. Users can remap keys.
- No test runner integration (debug nearest test). Out of scope.
@@ -582,7 +582,7 @@ Autocmd to close on any keypress. Content built from the keys table.
A user who has never configured DAP should be able to:
1. Add one line to their init.lua: `vim.pack.add("swaits/tiny-debugger.nvim")`
1. Add one line to their init.lua: `vim.pack.add("swaits/turbo-debug.nvim")`
2. Open a file in any of the world's top 10 languages.
3. Press `x` on a line to set a breakpoint (visible immediately in gutter).
4. Press `<leader>d` to enter debug mode. See the help box. See the UI.
@@ -622,7 +622,7 @@ All source control uses **jj** (Jujutsu), never git.
### Task 1: Scaffold — canonical plugin structure
**What:** Create the repo with all directories, empty files, LICENSE (MIT),
empty README.md, CONTRIBUTING.md stub, and `doc/tiny-debugger.txt` with
empty README.md, CONTRIBUTING.md stub, and `doc/turbo-debug.txt` with
the vimdoc header and a skeleton table of contents.
**Files:**
@@ -630,17 +630,17 @@ the vimdoc header and a skeleton table of contents.
LICENSE
README.md
CONTRIBUTING.md
doc/tiny-debugger.txt
plugin/tiny-debugger.lua (empty, just a header comment)
lua/tiny-debugger/init.lua (returns empty table)
lua/tiny-debugger/config.lua (returns default opts table)
doc/turbo-debug.txt
plugin/turbo-debug.lua (empty, just a header comment)
lua/turbo-debug/init.lua (returns empty table)
lua/turbo-debug/config.lua (returns default opts table)
tests/minimal_init.lua (minimal nvim init for testing)
```
**Acceptance criteria:**
- `nvim --clean -u tests/minimal_init.lua` starts without errors
- `:help tiny-debugger` opens the help file (even if sparse)
- `:lua print(type(require("tiny-debugger")))` prints `table`
- `:help turbo-debug` opens the help file (even if sparse)
- `:lua print(type(require("turbo-debug")))` prints `table`
- `jj log` shows exactly one clean commit
**Test:** Manual smoke test in Neovim.
@@ -651,13 +651,13 @@ tests/minimal_init.lua (minimal nvim init for testing)
### Task 2: Dependency management via vim.pack
**What:** `plugin/tiny-debugger.lua` calls `vim.pack.add` for all five
**What:** `plugin/turbo-debug.lua` calls `vim.pack.add` for all five
dependencies. Validates Neovim >= 0.12. Prints a clear error and returns
if version check fails.
**Files:**
```
plugin/tiny-debugger.lua
plugin/turbo-debug.lua
```
**Acceptance criteria:**
@@ -675,18 +675,18 @@ should not error. Test version gate by temporarily faking `vim.version()`.
### Task 3: Config module — defaults and deep merge
**What:** `lua/tiny-debugger/config.lua` defines the full default options
**What:** `lua/turbo-debug/config.lua` defines the full default options
table (keys, help_on_enter, dapui layout, virtual_text settings, etc.)
and exports a `merge(user_opts)` function that deep-merges user overrides.
**Files:**
```
lua/tiny-debugger/config.lua
lua/turbo-debug/config.lua
tests/test_config.lua
```
**Acceptance criteria:**
- `require("tiny-debugger.config").defaults` returns the full table
- `require("turbo-debug.config").defaults` returns the full table
- Merging `{ keys = { continue = "g" } }` overrides only that key
- Merging `{ keys = { continue = false } }` disables that key
- Merging `{}` returns defaults unchanged
@@ -701,17 +701,17 @@ outputs. Run with `nvim --headless -u tests/minimal_init.lua -c 'luafile tests/t
### Task 4: Debug mode — enter, exit, keybinding lifecycle
**What:** `lua/tiny-debugger/mode.lua` implements enter/exit debug mode.
**What:** `lua/turbo-debug/mode.lua` implements enter/exit debug mode.
On enter: sets buffer-local keymaps (stashing conflicts), sets `dCursor`
highlight. On exit: removes keymaps (restoring originals), clears highlight.
`lua/tiny-debugger/init.lua` exposes `toggle()` and `active()`.
`lua/turbo-debug/init.lua` exposes `toggle()` and `active()`.
`plugin/tiny-debugger.lua` maps `<leader>d` to `toggle()`.
`plugin/turbo-debug.lua` maps `<leader>d` to `toggle()`.
**Files:**
```
lua/tiny-debugger/init.lua
lua/tiny-debugger/mode.lua
lua/turbo-debug/init.lua
lua/turbo-debug/mode.lua
tests/test_mode.lua
tests/test_keys.lua
```
@@ -721,7 +721,7 @@ tests/test_keys.lua
- `<leader>d` again exits; all keys are removed
- A pre-existing user mapping for `c` is stashed on enter and restored on
exit (verified by checking `vim.fn.maparg`)
- `require("tiny-debugger").active()` returns `true`/`false` correctly
- `require("turbo-debug").active()` returns `true`/`false` correctly
- Navigation keys (`h`, `j`, `w`, `b`, `/`, `n`, etc.) still work in
debug mode
- `dCursor` highlight group is set on enter, cleared on exit
@@ -737,13 +737,13 @@ debug mode, verifies it's overridden, exits, verifies it's restored.
### Task 5: Help box
**What:** `lua/tiny-debugger/help.lua` implements the floating help window.
**What:** `lua/turbo-debug/help.lua` implements the floating help window.
Reads from the active keys config to build content dynamically. Opens
anchored to bottom-right. Closes on any keypress via autocmd.
**Files:**
```
lua/tiny-debugger/help.lua
lua/turbo-debug/help.lua
tests/test_help.lua
```
@@ -766,13 +766,13 @@ Tests with a remapped key to verify dynamic content.
### Task 6: UI wiring — nvim-dap-ui layout
**What:** `lua/tiny-debugger/ui.lua` calls `dapui.setup()` with our
**What:** `lua/turbo-debug/ui.lua` calls `dapui.setup()` with our
opinionated layout. Wires dap listeners to open/close UI on session
start/end. Integrates with mode enter/exit.
**Files:**
```
lua/tiny-debugger/ui.lua
lua/turbo-debug/ui.lua
```
**Acceptance criteria:**
@@ -793,14 +793,14 @@ layout in opts, verify override takes effect.
### Task 7: Virtual text wiring
**What:** `lua/tiny-debugger/virtual_text.lua` calls
**What:** `lua/turbo-debug/virtual_text.lua` calls
`require("nvim-dap-virtual-text").setup()` with our defaults (commented
style, highlight changed variables, current frame only). Integrates with
mode enter/exit (enable on enter, disable on exit).
**Files:**
```
lua/tiny-debugger/virtual_text.lua
lua/turbo-debug/virtual_text.lua
```
**Acceptance criteria:**
@@ -819,13 +819,13 @@ appears next to variable definitions. Exit debug mode, verify text clears.
### Task 8: Persistent breakpoints wiring
**What:** `lua/tiny-debugger/breakpoints.lua` calls
**What:** `lua/turbo-debug/breakpoints.lua` calls
`require("persistent-breakpoints").setup()` and maps `x`/`X` globally
(outside debug mode) to toggle/conditional breakpoint.
**Files:**
```
lua/tiny-debugger/breakpoints.lua
lua/turbo-debug/breakpoints.lua
tests/test_breakpoints.lua
```
@@ -853,7 +853,7 @@ element programmatically.
**Files:**
```
lua/tiny-debugger/mode.lua (add watch action)
lua/turbo-debug/mode.lua (add watch action)
```
**Acceptance criteria:**
@@ -880,7 +880,7 @@ evaluation).
**Files:**
```
lua/tiny-debugger/mode.lua (add hover + eval actions)
lua/turbo-debug/mode.lua (add hover + eval actions)
```
**Acceptance criteria:**
@@ -902,14 +902,14 @@ result. Press `E`, type an expression in the REPL, verify output.
**What:** First two adapter configs. Python includes venv auto-detection.
Go includes delve auto-launch. Adapter loader in
`lua/tiny-debugger/adapters/init.lua` handles registration and path
`lua/turbo-debug/adapters/init.lua` handles registration and path
resolution.
**Files:**
```
lua/tiny-debugger/adapters/init.lua
lua/tiny-debugger/adapters/python.lua
lua/tiny-debugger/adapters/go.lua
lua/turbo-debug/adapters/init.lua
lua/turbo-debug/adapters/python.lua
lua/turbo-debug/adapters/go.lua
tests/test_adapters.lua
```
@@ -936,7 +936,7 @@ Uses codelldb. Program picker via `vim.fn.input`.
**Files:**
```
lua/tiny-debugger/adapters/c.lua
lua/turbo-debug/adapters/c.lua
```
**Acceptance criteria:**
@@ -958,7 +958,7 @@ breakpoints and stepping work.
**Files:**
```
lua/tiny-debugger/adapters/javascript.lua
lua/turbo-debug/adapters/javascript.lua
```
**Acceptance criteria:**
@@ -979,9 +979,9 @@ kotlin-debug-adapter.
**Files:**
```
lua/tiny-debugger/adapters/cs.lua
lua/tiny-debugger/adapters/java.lua
lua/tiny-debugger/adapters/kotlin.lua
lua/turbo-debug/adapters/cs.lua
lua/turbo-debug/adapters/java.lua
lua/turbo-debug/adapters/kotlin.lua
```
**Acceptance criteria:**
@@ -1003,9 +1003,9 @@ Lua via osv (optional, only if one-small-step-for-vimkind is available).
**Files:**
```
lua/tiny-debugger/adapters/php.lua
lua/tiny-debugger/adapters/ruby.lua
lua/tiny-debugger/adapters/lua.lua
lua/turbo-debug/adapters/php.lua
lua/turbo-debug/adapters/ruby.lua
lua/turbo-debug/adapters/lua.lua
```
**Acceptance criteria:**
@@ -1023,25 +1023,25 @@ skip when osv is not installed.
### Task 16: Vimdoc — complete help file
**What:** Write the full `doc/tiny-debugger.txt` in vimdoc format. Covers
**What:** Write the full `doc/turbo-debug.txt` in vimdoc format. Covers
installation, configuration, all keybindings, all options, adapter
customization, and troubleshooting. Generate helptags.
**Files:**
```
doc/tiny-debugger.txt
doc/turbo-debug.txt
doc/tags (generated)
```
**Acceptance criteria:**
- `:help tiny-debugger` opens the help file
- `:help tiny-debugger.setup` jumps to the setup section
- `:help tiny-debugger.keys` jumps to the keybindings section
- `:help tiny-debugger.adapters` jumps to the adapters section
- `:help turbo-debug` opens the help file
- `:help turbo-debug.setup` jumps to the setup section
- `:help turbo-debug.keys` jumps to the keybindings section
- `:help turbo-debug.adapters` jumps to the adapters section
- Every public function and option is documented
- All tag references resolve correctly
**Test:** Open Neovim, run `:helptags doc/`, then `:help tiny-debugger`
**Test:** Open Neovim, run `:helptags doc/`, then `:help turbo-debug`
and verify all sections and tags work.
**jj commit:** `docs: complete vimdoc help file with all tags`
@@ -1084,7 +1084,7 @@ discovered.
- All 11 success criteria steps pass for Python
- All 11 success criteria steps pass for C or Go
- No errors in `:messages` after a full debug session lifecycle
- Clean startup: no errors on `nvim --clean` with only tiny-debugger
- Clean startup: no errors on `nvim --clean` with only turbo-debug
**Test:** Manual walkthrough of the full success criteria. Document results.