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 ## 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` 2. Add the module name to the loader list in `adapters/init.lua`
3. Add the language to vimdoc 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 A zero-config debugging experience for Neovim 0.12+. One plugin install, full
IDE-class debugging: inline variable values, hover inspection, persistent IDE-class debugging: inline variable values, hover inspection, persistent
@@ -7,10 +7,10 @@ breakpoints, watch expressions, and modal keybindings that just work.
## Install ## Install
```lua ```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 ## 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| 1. Introduction .......................... |turbo-debug-introduction|
2. Installation .......................... |tiny-debugger-installation| 2. Installation .......................... |turbo-debug-installation|
3. Setup ................................. |tiny-debugger.setup| 3. Setup ................................. |turbo-debug.setup|
4. Debug Mode ............................ |tiny-debugger-debug-mode| 4. Debug Mode ............................ |turbo-debug-debug-mode|
5. Keybindings ........................... |tiny-debugger.keys| 5. Keybindings ........................... |turbo-debug.keys|
6. Breakpoints ........................... |tiny-debugger-breakpoints| 6. Breakpoints ........................... |turbo-debug-breakpoints|
7. UI Layout ............................. |tiny-debugger-layout| 7. UI Layout ............................. |turbo-debug-layout|
8. Adapters .............................. |tiny-debugger.adapters| 8. Adapters .............................. |turbo-debug.adapters|
9. API ................................... |tiny-debugger-api| 9. API ................................... |turbo-debug-api|
10. Troubleshooting ....................... |tiny-debugger-troubleshooting| 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, 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 nvim-dap-ui, nvim-dap-virtual-text, and persistent-breakpoints into a single
cohesive experience with modal keybindings. cohesive experience with modal keybindings.
@@ -33,60 +33,61 @@ Features:
- Zero-config adapters for 10+ languages - Zero-config adapters for 10+ languages
============================================================================== ==============================================================================
2. Installation *tiny-debugger-installation* 2. Installation *turbo-debug-installation*
Add one line to your init.lua: >lua 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. That's it. All dependencies are managed automatically.
Requires Neovim >= 0.12. 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 Setup is optional. The plugin works with no configuration. To customize: >lua
require("tiny-debugger").setup({ require("turbo-debug").setup({
help_on_enter = true, -- show help box when entering debug mode 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 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 adapters = { ... }, -- override or add language adapters
dapui = { ... }, -- override nvim-dap-ui layout/settings dapui = { ... }, -- override nvim-dap-ui layout/settings
virtual_text = { ... }, -- override nvim-dap-virtual-text settings virtual_text = { ... }, -- override nvim-dap-virtual-text settings
}) })
< <
*tiny-debugger.setup.help_on_enter* *turbo-debug.setup.help_on_enter*
help_on_enter ~ help_on_enter ~
Type: boolean, Default: `true` Type: boolean, Default: `true`
Show the help box automatically when entering debug mode. Show the help box automatically when entering debug mode.
*tiny-debugger.setup.builtin_adapters* *turbo-debug.setup.builtin_adapters*
builtin_adapters ~ builtin_adapters ~
Type: boolean, Default: `true` Type: boolean, Default: `true`
Register built-in adapters for supported languages. Set to `false` to Register built-in adapters for supported languages. Set to `false` to
disable all built-in adapter registration. 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: Entering debug mode:
1. Opens nvim-dap-ui with the configured layout 1. Opens nvim-dap-ui with the configured layout
2. Enables inline virtual text for variable values 2. Enables inline virtual text for variable values
3. Activates modal keybindings (buffer-local) 3. Activates modal keybindings (buffer-local)
4. Changes cursor highlight to indicate debug mode 4. Shows winbar indicator and help splash (3s)
5. Shows help box (if `help_on_enter` is true)
Exiting debug mode (any of): Exiting debug mode (any of):
- `<leader>d` again (manual toggle) - `<leader>dd` again (manual toggle)
- `q` (terminate session — auto-exits debug mode) - `q` (terminate session — exits debug mode if `quit_exits_mode`)
- DAP session ends naturally - DAP session ends naturally
On exit, everything is restored: keymaps, UI, virtual text, cursor. 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 Modal keybindings are active only during debug mode. They shadow editing
keys you don't need while debugging, but preserve all navigation keys. 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 `d` Step into Descend into the function
`r` Step out Return from the function `r` Step out Return from the function
`C` Run to cursor Continue to cursor `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 `W` Watch expr under cursor Watch
`K` Hover / inspect Matches LSP hover convention `K` Hover / inspect Matches LSP hover convention
`E` Eval in REPL Evaluate `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 `<leader>dD` Clear all breakpoints Delete all
Override any key: >lua Override any key: >lua
require("tiny-debugger").setup({ require("turbo-debug").setup({
keys = { -- modal keys (debug mode only) keys = { -- modal keys (debug mode only)
continue = "g", continue = "g",
step_over = false, -- set to false to disable step_over = false, -- set to false to disable
@@ -131,19 +135,24 @@ Preserved keys (not shadowed):
- Visual/yank: `v V y p u` - Visual/yank: `v V y p u`
- All Ctrl/leader combos - 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 Breakpoints are managed by persistent-breakpoints.nvim. They persist across
Neovim restarts and are visible in the sign column at all times. Neovim restarts and are visible in the sign column at all times.
`x` toggles a breakpoint on the current line. `<leader>dx` toggles a breakpoint (always available).
`X` prompts for a condition and sets a conditional breakpoint. `<leader>dX` sets a conditional breakpoint (always available).
`x`, `X`, `D` also work as shortcuts during debug mode.
Both work outside debug mode — no need to enter debug mode first.
============================================================================== ==============================================================================
7. UI Layout *tiny-debugger-layout* 7. UI Layout *turbo-debug-layout*
Default layout: Default layout:
@@ -157,14 +166,14 @@ Default layout:
- Console (50%) — program stdout/stderr - Console (50%) — program stdout/stderr
Override the layout: >lua Override the layout: >lua
require("tiny-debugger").setup({ require("turbo-debug").setup({
dapui = { dapui = {
layouts = { ... }, -- see nvim-dap-ui docs for format 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): 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. Adapter binaries are the user's responsibility to install.
Override or add adapters: >lua Override or add adapters: >lua
require("tiny-debugger").setup({ require("turbo-debug").setup({
adapters = { adapters = {
python = { ... }, -- override built-in python = { ... }, -- override built-in
zig = { ... }, -- add new language zig = { ... }, -- add new language
@@ -201,23 +210,23 @@ Override or add adapters: >lua
Existing user nvim-dap configurations are never overridden. Existing user nvim-dap configurations are never overridden.
============================================================================== ==============================================================================
9. API *tiny-debugger-api* 9. API *turbo-debug-api*
*tiny-debugger.toggle()* *turbo-debug.toggle()*
require("tiny-debugger").toggle() require("turbo-debug").toggle()
Toggle debug mode on/off. Toggle debug mode on/off.
*tiny-debugger.active()* *turbo-debug.active()*
require("tiny-debugger").active() require("turbo-debug").active()
Returns `true` if debug mode is currently active, `false` otherwise. Returns `true` if debug mode is currently active, `false` otherwise.
Useful for statusline integration. Useful for statusline integration.
============================================================================== ==============================================================================
10. Troubleshooting *tiny-debugger-troubleshooting* 10. Troubleshooting *turbo-debug-troubleshooting*
No adapter found ~ No adapter found ~
Ensure the adapter binary is installed and on your PATH, or installed 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. them.
Breakpoints not persisting ~ Breakpoints not persisting ~
@@ -230,7 +239,7 @@ Virtual text not appearing ~
`:lua print(require("nvim-dap-virtual-text") and "ok")` `:lua print(require("nvim-dap-virtual-text") and "ok")`
Version error ~ 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: 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 = {} local M = {}
@@ -1,4 +1,4 @@
local loader = require("tiny-debugger.adapters.init") local loader = require("turbo-debug.adapters.init")
local M = {} local M = {}
@@ -1,4 +1,4 @@
local config = require("tiny-debugger.config") local config = require("turbo-debug.config")
local M = {} local M = {}
@@ -92,7 +92,7 @@ function M.setup()
-- load adapters with non-trivial logic from separate files -- load adapters with non-trivial logic from separate files
for _, name in ipairs({ "python", "go", "c", "javascript" }) do 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 if ok and adapter_mod.register then
adapter_mod.register(dap) adapter_mod.register(dap)
end end
@@ -1,4 +1,4 @@
local loader = require("tiny-debugger.adapters.init") local loader = require("turbo-debug.adapters.init")
local M = {} local M = {}
@@ -1,4 +1,4 @@
local loader = require("tiny-debugger.adapters.init") local loader = require("turbo-debug.adapters.init")
local M = {} local M = {}
@@ -1,4 +1,4 @@
local config = require("tiny-debugger.config") local config = require("turbo-debug.config")
local M = {} local M = {}
File renamed without changes.
@@ -1,4 +1,4 @@
local config = require("tiny-debugger.config") local config = require("turbo-debug.config")
local M = {} local M = {}
@@ -30,7 +30,7 @@ local global_info = {
} }
local function build_content() local function build_content()
local lines = { " tiny-debugger", "" } local lines = { " turbo-debug", "" }
local width = #lines[1] local width = #lines[1]
local function add(key, label) local function add(key, label)
@@ -1,12 +1,12 @@
local config = require("tiny-debugger.config") local config = require("turbo-debug.config")
local mode = require("tiny-debugger.mode") local mode = require("turbo-debug.mode")
local M = {} local M = {}
function M.setup(opts) function M.setup(opts)
config.merge(opts) config.merge(opts)
require("tiny-debugger.breakpoints").setup() require("turbo-debug.breakpoints").setup()
require("tiny-debugger.adapters").setup() require("turbo-debug.adapters").setup()
-- global toggle keybinding -- global toggle keybinding
local toggle_key = config.opts.global_keys.toggle local toggle_key = config.opts.global_keys.toggle
@@ -1,5 +1,5 @@
local config = require("tiny-debugger.config") local config = require("turbo-debug.config")
local help = require("tiny-debugger.help") local help = require("turbo-debug.help")
local M = {} local M = {}
@@ -20,10 +20,10 @@ local function ensure_dapui()
require("dapui").setup(config.opts.dapui) require("dapui").setup(config.opts.dapui)
local dap = require("dap") 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 if active then M.exit() end
end end
dap.listeners.after.event_exited["tiny-debugger"] = function() dap.listeners.after.event_exited["turbo-debug"] = function()
if active then M.exit() end if active then M.exit() end
end end
@@ -139,9 +139,9 @@ local function set_keymaps(buf)
for name, key in pairs(keys) do for name, key in pairs(keys) do
if key and actions[name] then if key and actions[name] then
stash_mapping(buf, key) 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 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 end
mapped_keys[#mapped_keys + 1] = { name = name, key = key } mapped_keys[#mapped_keys + 1] = { name = name, key = key }
end end
@@ -1,7 +1,7 @@
-- tiny-debugger.nvim — entry point -- turbo-debug.nvim — entry point
if vim.fn.has("nvim-0.12") ~= 1 then 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 return
end end
@@ -17,4 +17,4 @@ pcall(function()
end) end)
-- setup immediately (idempotent — user can call setup() again with overrides) -- 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()) vim.opt.runtimepath:prepend(vim.fn.getcwd())
package.path = vim.fn.getcwd() .. "/tests/?.lua;" .. package.path 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 assert_eq = require("helpers").assert_eq
local loader = require("tiny-debugger.adapters.init") local loader = require("turbo-debug.adapters.init")
local dap = require("dap") local dap = require("dap")
-- find_executable returns nil for non-existent binaries -- 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() -- all adapter modules load and have register()
for _, name in ipairs({ "python", "go", "c", "javascript" }) do 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 end
-- register doesn't override existing adapter -- register doesn't override existing adapter
+1 -1
View File
@@ -1,5 +1,5 @@
local assert_eq = require("helpers").assert_eq local assert_eq = require("helpers").assert_eq
local td = require("tiny-debugger") local td = require("turbo-debug")
td.setup() td.setup()
-- global breakpoint mappings exist under <leader>d prefix -- global breakpoint mappings exist under <leader>d prefix
+1 -1
View File
@@ -1,5 +1,5 @@
local assert_eq = require("helpers").assert_eq local assert_eq = require("helpers").assert_eq
local config = require("tiny-debugger.config") local config = require("turbo-debug.config")
-- defaults unchanged after empty merge -- defaults unchanged after empty merge
local opts = config.merge({}) local opts = config.merge({})
+2 -2
View File
@@ -1,6 +1,6 @@
local assert_eq = require("helpers").assert_eq local assert_eq = require("helpers").assert_eq
local help = require("tiny-debugger.help") local help = require("turbo-debug.help")
local config = require("tiny-debugger.config") local config = require("turbo-debug.config")
-- open creates a valid window -- open creates a valid window
help.open() help.open()
+2 -2
View File
@@ -1,5 +1,5 @@
local assert_eq = require("helpers").assert_eq local assert_eq = require("helpers").assert_eq
local td = require("tiny-debugger") local td = require("turbo-debug")
-- set a custom mapping for 'c' -- set a custom mapping for 'c'
vim.keymap.set("n", "c", function() end, { buffer = 0, desc = "custom 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' -- enter debug mode — should override 'c'
td.toggle() td.toggle()
maparg = vim.fn.maparg("c", "n", false, true) 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' -- exit debug mode — should restore custom 'c'
td.toggle() td.toggle()
+1 -1
View File
@@ -1,5 +1,5 @@
local assert_eq = require("helpers").assert_eq local assert_eq = require("helpers").assert_eq
local td = require("tiny-debugger") local td = require("turbo-debug")
local function has_buf_map(key) local function has_buf_map(key)
for _, m in ipairs(vim.api.nvim_buf_get_keymap(0, "n")) do 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? ## 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. keybindings. The user installs one plugin and gets everything.
```lua ```lua
vim.pack.add("swaits/tiny-debugger.nvim") vim.pack.add("swaits/turbo-debug.nvim")
``` ```
That's it. That's the whole setup. That's it. That's the whole setup.
@@ -81,7 +81,7 @@ One plugin install. Zero configuration. All of this:
## Dependencies (Managed Automatically) ## 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: each one internally:
| Dependency | What it provides | | Dependency | What it provides |
@@ -132,7 +132,7 @@ C/C++/Rust only). Out of scope.
```lua ```lua
-- init.lua -- init.lua
vim.pack.add("swaits/tiny-debugger.nvim") vim.pack.add("swaits/turbo-debug.nvim")
``` ```
One line. One plugin. Everything works. One line. One plugin. Everything works.
@@ -140,7 +140,7 @@ One line. One plugin. Everything works.
### Configuration (optional) ### Configuration (optional)
```lua ```lua
require("tiny-debugger").setup({ require("turbo-debug").setup({
-- all fields optional, these are the defaults -- all fields optional, these are the defaults
help_on_enter = true, -- show help box when entering debug mode help_on_enter = true, -- show help box when entering debug mode
keys = { ... }, -- override any keybinding keys = { ... }, -- override any keybinding
@@ -293,7 +293,7 @@ use the standard nvim-dap-ui element keybindings.
## UI Layout ## 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 ### Behavior
- On first `c` (continue), if no `dap.configurations` exist for the current - 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 - 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 - 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 ### Configuration
```lua ```lua
require("tiny-debugger").setup({ require("turbo-debug").setup({
adapters = { adapters = {
python = { ... }, -- override built-in python = { ... }, -- override built-in
zig = { ... }, -- add new language 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. everything a user or contributor expects.
``` ```
tiny-debugger.nvim/ turbo-debug.nvim/
├── LICENSE -- MIT ├── LICENSE -- MIT
├── README.md -- install, quick start, screenshots ├── README.md -- install, quick start, screenshots
├── CONTRIBUTING.md -- how to add adapters, run tests ├── CONTRIBUTING.md -- how to add adapters, run tests
├── doc/ ├── doc/
│ └── tiny-debugger.txt -- :help tiny-debugger (vimdoc format) │ └── turbo-debug.txt -- :help turbo-debug (vimdoc format)
├── plugin/ ├── 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/ ├── lua/
│ └── tiny-debugger/ │ └── turbo-debug/
│ ├── init.lua -- public API (setup, toggle, active) │ ├── init.lua -- public API (setup, toggle, active)
│ ├── config.lua -- default opts, deep merge with user opts │ ├── config.lua -- default opts, deep merge with user opts
│ ├── mode.lua -- enter/exit debug mode, keybinding mgmt │ ├── mode.lua -- enter/exit debug mode, keybinding mgmt
@@ -541,10 +541,10 @@ tiny-debugger.nvim/
### Key Mechanisms ### 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. 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 nvim-dap-virtual-text, and persistent-breakpoints with its opinionated
defaults, deep-merged with any user overrides from `opts`. 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 ### What We Don't Do
- No custom UI widgets. nvim-dap-ui handles that. - 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 telescope/fzf integration. Out of scope.
- No reverse debugging built-in. Users can remap keys. - No reverse debugging built-in. Users can remap keys.
- No test runner integration (debug nearest test). Out of scope. - 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: 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. 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). 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. 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 ### Task 1: Scaffold — canonical plugin structure
**What:** Create the repo with all directories, empty files, LICENSE (MIT), **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. the vimdoc header and a skeleton table of contents.
**Files:** **Files:**
@@ -630,17 +630,17 @@ the vimdoc header and a skeleton table of contents.
LICENSE LICENSE
README.md README.md
CONTRIBUTING.md CONTRIBUTING.md
doc/tiny-debugger.txt doc/turbo-debug.txt
plugin/tiny-debugger.lua (empty, just a header comment) plugin/turbo-debug.lua (empty, just a header comment)
lua/tiny-debugger/init.lua (returns empty table) lua/turbo-debug/init.lua (returns empty table)
lua/tiny-debugger/config.lua (returns default opts table) lua/turbo-debug/config.lua (returns default opts table)
tests/minimal_init.lua (minimal nvim init for testing) tests/minimal_init.lua (minimal nvim init for testing)
``` ```
**Acceptance criteria:** **Acceptance criteria:**
- `nvim --clean -u tests/minimal_init.lua` starts without errors - `nvim --clean -u tests/minimal_init.lua` starts without errors
- `:help tiny-debugger` opens the help file (even if sparse) - `:help turbo-debug` opens the help file (even if sparse)
- `:lua print(type(require("tiny-debugger")))` prints `table` - `:lua print(type(require("turbo-debug")))` prints `table`
- `jj log` shows exactly one clean commit - `jj log` shows exactly one clean commit
**Test:** Manual smoke test in Neovim. **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 ### 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 dependencies. Validates Neovim >= 0.12. Prints a clear error and returns
if version check fails. if version check fails.
**Files:** **Files:**
``` ```
plugin/tiny-debugger.lua plugin/turbo-debug.lua
``` ```
**Acceptance criteria:** **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 ### 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.) table (keys, help_on_enter, dapui layout, virtual_text settings, etc.)
and exports a `merge(user_opts)` function that deep-merges user overrides. and exports a `merge(user_opts)` function that deep-merges user overrides.
**Files:** **Files:**
``` ```
lua/tiny-debugger/config.lua lua/turbo-debug/config.lua
tests/test_config.lua tests/test_config.lua
``` ```
**Acceptance criteria:** **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 = "g" } }` overrides only that key
- Merging `{ keys = { continue = false } }` disables that key - Merging `{ keys = { continue = false } }` disables that key
- Merging `{}` returns defaults unchanged - 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 ### 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` On enter: sets buffer-local keymaps (stashing conflicts), sets `dCursor`
highlight. On exit: removes keymaps (restoring originals), clears highlight. 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:** **Files:**
``` ```
lua/tiny-debugger/init.lua lua/turbo-debug/init.lua
lua/tiny-debugger/mode.lua lua/turbo-debug/mode.lua
tests/test_mode.lua tests/test_mode.lua
tests/test_keys.lua tests/test_keys.lua
``` ```
@@ -721,7 +721,7 @@ tests/test_keys.lua
- `<leader>d` again exits; all keys are removed - `<leader>d` again exits; all keys are removed
- A pre-existing user mapping for `c` is stashed on enter and restored on - A pre-existing user mapping for `c` is stashed on enter and restored on
exit (verified by checking `vim.fn.maparg`) 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 - Navigation keys (`h`, `j`, `w`, `b`, `/`, `n`, etc.) still work in
debug mode debug mode
- `dCursor` highlight group is set on enter, cleared on exit - `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 ### 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 Reads from the active keys config to build content dynamically. Opens
anchored to bottom-right. Closes on any keypress via autocmd. anchored to bottom-right. Closes on any keypress via autocmd.
**Files:** **Files:**
``` ```
lua/tiny-debugger/help.lua lua/turbo-debug/help.lua
tests/test_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 ### 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 opinionated layout. Wires dap listeners to open/close UI on session
start/end. Integrates with mode enter/exit. start/end. Integrates with mode enter/exit.
**Files:** **Files:**
``` ```
lua/tiny-debugger/ui.lua lua/turbo-debug/ui.lua
``` ```
**Acceptance criteria:** **Acceptance criteria:**
@@ -793,14 +793,14 @@ layout in opts, verify override takes effect.
### Task 7: Virtual text wiring ### 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 `require("nvim-dap-virtual-text").setup()` with our defaults (commented
style, highlight changed variables, current frame only). Integrates with style, highlight changed variables, current frame only). Integrates with
mode enter/exit (enable on enter, disable on exit). mode enter/exit (enable on enter, disable on exit).
**Files:** **Files:**
``` ```
lua/tiny-debugger/virtual_text.lua lua/turbo-debug/virtual_text.lua
``` ```
**Acceptance criteria:** **Acceptance criteria:**
@@ -819,13 +819,13 @@ appears next to variable definitions. Exit debug mode, verify text clears.
### Task 8: Persistent breakpoints wiring ### 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 `require("persistent-breakpoints").setup()` and maps `x`/`X` globally
(outside debug mode) to toggle/conditional breakpoint. (outside debug mode) to toggle/conditional breakpoint.
**Files:** **Files:**
``` ```
lua/tiny-debugger/breakpoints.lua lua/turbo-debug/breakpoints.lua
tests/test_breakpoints.lua tests/test_breakpoints.lua
``` ```
@@ -853,7 +853,7 @@ element programmatically.
**Files:** **Files:**
``` ```
lua/tiny-debugger/mode.lua (add watch action) lua/turbo-debug/mode.lua (add watch action)
``` ```
**Acceptance criteria:** **Acceptance criteria:**
@@ -880,7 +880,7 @@ evaluation).
**Files:** **Files:**
``` ```
lua/tiny-debugger/mode.lua (add hover + eval actions) lua/turbo-debug/mode.lua (add hover + eval actions)
``` ```
**Acceptance criteria:** **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. **What:** First two adapter configs. Python includes venv auto-detection.
Go includes delve auto-launch. Adapter loader in 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. resolution.
**Files:** **Files:**
``` ```
lua/tiny-debugger/adapters/init.lua lua/turbo-debug/adapters/init.lua
lua/tiny-debugger/adapters/python.lua lua/turbo-debug/adapters/python.lua
lua/tiny-debugger/adapters/go.lua lua/turbo-debug/adapters/go.lua
tests/test_adapters.lua tests/test_adapters.lua
``` ```
@@ -936,7 +936,7 @@ Uses codelldb. Program picker via `vim.fn.input`.
**Files:** **Files:**
``` ```
lua/tiny-debugger/adapters/c.lua lua/turbo-debug/adapters/c.lua
``` ```
**Acceptance criteria:** **Acceptance criteria:**
@@ -958,7 +958,7 @@ breakpoints and stepping work.
**Files:** **Files:**
``` ```
lua/tiny-debugger/adapters/javascript.lua lua/turbo-debug/adapters/javascript.lua
``` ```
**Acceptance criteria:** **Acceptance criteria:**
@@ -979,9 +979,9 @@ kotlin-debug-adapter.
**Files:** **Files:**
``` ```
lua/tiny-debugger/adapters/cs.lua lua/turbo-debug/adapters/cs.lua
lua/tiny-debugger/adapters/java.lua lua/turbo-debug/adapters/java.lua
lua/tiny-debugger/adapters/kotlin.lua lua/turbo-debug/adapters/kotlin.lua
``` ```
**Acceptance criteria:** **Acceptance criteria:**
@@ -1003,9 +1003,9 @@ Lua via osv (optional, only if one-small-step-for-vimkind is available).
**Files:** **Files:**
``` ```
lua/tiny-debugger/adapters/php.lua lua/turbo-debug/adapters/php.lua
lua/tiny-debugger/adapters/ruby.lua lua/turbo-debug/adapters/ruby.lua
lua/tiny-debugger/adapters/lua.lua lua/turbo-debug/adapters/lua.lua
``` ```
**Acceptance criteria:** **Acceptance criteria:**
@@ -1023,25 +1023,25 @@ skip when osv is not installed.
### Task 16: Vimdoc — complete help file ### 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 installation, configuration, all keybindings, all options, adapter
customization, and troubleshooting. Generate helptags. customization, and troubleshooting. Generate helptags.
**Files:** **Files:**
``` ```
doc/tiny-debugger.txt doc/turbo-debug.txt
doc/tags (generated) doc/tags (generated)
``` ```
**Acceptance criteria:** **Acceptance criteria:**
- `:help tiny-debugger` opens the help file - `:help turbo-debug` opens the help file
- `:help tiny-debugger.setup` jumps to the setup section - `:help turbo-debug.setup` jumps to the setup section
- `:help tiny-debugger.keys` jumps to the keybindings section - `:help turbo-debug.keys` jumps to the keybindings section
- `:help tiny-debugger.adapters` jumps to the adapters section - `:help turbo-debug.adapters` jumps to the adapters section
- Every public function and option is documented - Every public function and option is documented
- All tag references resolve correctly - 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. and verify all sections and tags work.
**jj commit:** `docs: complete vimdoc help file with all tags` **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 Python
- All 11 success criteria steps pass for C or Go - All 11 success criteria steps pass for C or Go
- No errors in `:messages` after a full debug session lifecycle - 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. **Test:** Manual walkthrough of the full success criteria. Document results.