10 Commits
Author SHA1 Message Date
swaits d062ac27ff chore: release 0.2.0
Major UI rework and stability release. Two floating chrome bars replace the
old single toolbar, every resize/tabline-toggle edge case is handled, and
every highlight now derives from the user's colorscheme.

BREAKING CHANGES
- `quit_exits_mode` option removed — `q` is now context-aware: if a DAP
  session is running, `q` terminates the session but keeps debug mode
  active so you can read the Console / inspect post-mortem state. Press
  `q` again to exit debug mode.
- `help_on_enter` default is now `false` (was `true`). Control bar always
  shows `(?) help`, so the auto-popup is no longer needed.
- Default layout changed: sidebar is Call Stack → Scopes → Watches →
  Breakpoints (all 25%). REPL is no longer in the default layout — press
  `E` during debug mode to open it as a floating window.
- Console pane sizing: bottom Console is `max(8 rows, 20% of editor
  lines)` (previously hardcoded). Configurable via `console_height`.

ADDED
- Two-bar floating chrome, independent of any statusline plugin:
  status bar (top, 2 rows, brand + live dap.status text + state chip),
  control bar (bottom, 2 rows, clickable flow buttons + `(?) help`
  right-anchored). Italic qualifiers on step controls auto-drop at
  narrow widths.
- Keymap-aware control bar — legend reflects user's actual remapped
  keys; disabled actions are omitted entirely.
- IP arrow markers on stopped lines: 👉 gutter sign (priority 500) +
  👈 REASON virtual text at EOL.
- Optional debug-mode colorscheme via `colorscheme` option.
- Theme-agnostic separator color (derives from WinBar.fg); global
  WinSeparator override during debug mode for consistent edge color.
- `clear_console_on_start` (default true) — wipe Console scrollback on
  session start while preserving the terminal channel.
- `collapsed_scopes` (default {"Registers"}) — auto-collapse noisy
  scopes that adapters don't flag expensive.
- `max_value_width` (default 2000) — per-line truncation for values in
  Scopes/Watches.
- `console_refresh_ms` (default 50) — trailing-edge Console repaint
  throttle.
- `sidebar` option — "left" (default) or "right".
- `active_window_highlight` (default true) — dim inactive dapui pane
  borders.
- `W` and `K` now work in visual mode (operate on the selection).
- Source window focused before DAP jumps on event_stopped.

CHANGED
- Bars are real splits (not overlapping floats).
- pin_dapui_sizes() only re-pins on external geometry changes (tabline
  toggle); user manual pane drags survive.
- ensure_dapui() runs ONCE per plugin lifetime, avoiding "Debug adapter
  didn't respond" timeouts on toggle.
- Bars clamp to exactly 2 rows on every resize (no stray EOB `~`).
- setup() is fully idempotent; plugin/turbo-debug.lua's deferred
  auto-setup yields to explicit user setup({...}).
- Copyright holder: Stephen Waits <steve@waits.net>.

FIXED
- Bars recreate if killed by shrink-below-minimum resize or tabline
  appear/disappear.
- Inherited winbar cleared on bar windows (no phantom separator rows).
- Layout re-asserts after `wincmd =`.
- Sidebar proportions stable across re-entry.
- Bar separators bright on both outward edges.
- Deferred dependency loading waits for vim.pack.add to finalize.

INTERNAL
- Extracted 10+ helper functions in mode.lua; deduped ~25 call sites.
- Data-driven sign definitions and Python interpreter probing.
- Dead code removed: unused reposition_bars, vestigial sbar_zones/
  handle_sbar_click.
- Added regression tests: test_render_bars, test_highlights_cs,
  test_helpers.
- stylua.toml added; all Lua code formatted.

See CHANGELOG.md for the full 0.2.0 entry.
2026-04-12 20:00:59 -06:00
swaits 98c943885a feat: keymap-aware legend, live dap.status, debug-mode colorscheme
Three things the user caught in testing:

1. **Legend keymap-aware.** The cbar labels used hardcoded tails
   ("tep", "escend", "eturn") that assumed the default first-letter
   keys. If a user configured `keys.step_over = "n"` it would render
   as "(n)tep" — garbage. And disabled keys (`false` in config) still
   showed up because `keyof` fell back to the default letter.

   Now `keyof` returns nil for disabled actions (caller SKIPS rendering
   the entry) and `build_control_text` auto-picks between inline form
   "(s)tep" when the actual key matches the label's first letter and
   prefix form "(n) step" when it doesn't. Controls carry their full
   label ("step") plus the canonical default key — the render figures
   out which form fits the user's current keymap.

2. **dap.status() lag.** `dap.status()` polls a message queue one at
   a time per call (nvim-dap/lua/dap/progress.lua:50). We were only
   polling on event_stopped/continued/terminated/etc., so queued
   state strings drained behind reality — user saw "Running" when
   already paused, "All threads stopped" one step late, etc. Now we
   also subscribe to the `User DapProgressUpdate` autocmd that dap
   fires on EVERY status update, keeping the bar in sync.

3. **Debug-mode colorscheme.** New `config.opts.colorscheme` option
   (default nil). If set to a string, M.enter switches to it BEFORE
   define_highlights (so our TurboDebug* groups derive from the new
   theme's colors); M.exit restores the previous `vim.g.colors_name`.
2026-04-12 17:38:20 -06:00
swaitsandClaude Opus 4.6 32c7e465c8 fix: bar blends with dapui bg, console capped at 5 rows, restart clears
Three refinements driven by the latest screenshot:

- TurboDebugBar highlight now links to Normal (was StatusLine). The
  StatusLine bg is usually darker than Normal in most colorschemes,
  which created a visible seam between our bar and the surrounding
  dapui pane headers (which inherit Normal/WinBar bg). Linking to
  Normal makes the bar blend so the overall UI reads as one unified
  surface rather than two mismatched strips.

- Console height now `min(5, 15% of avail)` with a 3-row absolute
  floor. Previously used `max(5, 15%)` which let Console balloon on
  tall terminals — misread the user's "minimum of 15% OR 5 rows"
  direction. Console is ancillary; caps at 5 to give the sidebar and
  source the vertical space they deserve.

- Clear-on-restart actually works now. Previous attempt deleted the
  entire console buffer on start/restart so dapui would create a fresh
  one — this worked on `(c)` start (new terminal opens) but broke on
  `(R)estart` because the adapter reuses the terminal channel, and
  deleting the buffer orphaned the channel (Console went unresponsive).
  New approach: KEEP the buffer, briefly toggle modifiable=true, and
  call nvim_buf_set_lines with empty content to wipe the scrollback.
  The PTY state and output stream stay intact; only the visible lines
  are gone. Default `clear_console_on_start = true` again.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 14:24:59 -06:00
swaitsandClaude Opus 4.6 c7e9fb799d fix: adapter timeouts + bars now span full editor width
Regression fixes from the previous commit:

1. Debug adapter timing out / general slowness — root cause was calling
   dapui.setup() on every M.enter() to "refresh layouts". setup is
   heavy (tears down windows, re-registers listeners, rebuilds state)
   and running it while the adapter handshake is in flight caused
   "Debug adapter didn't respond" timeouts. Reverted to one-time setup;
   layouts are computed once per nvim session. Trade-off: Console/
   sidebar proportions may drift slightly if the terminal is resized
   between toggles, but that's vastly preferable to a broken adapter.

2. Console broken / unreachable — clear_console was calling buf_set_lines
   on a terminal buffer after dapui had made it a terminal, which leaves
   the terminal in an inconsistent state. Kept the config option but
   disabled by default (clear_console_on_start = false). Users who want
   it can opt in; the feature remains risky on terminal-backed Console
   buffers. Better design pending.

3. Bars not spanning full editor width — :topleft split and :botright
   split create full-width splits only when no competing vertical
   splits exist. dapui's sidebar creates a full-height vertical split
   AFTER our bars, which squeezes the bars into the non-sidebar column.
   Added force_bars_full_width() which runs `wincmd K` (on sbar) and
   `wincmd J` (on cbar) AFTER dapui.open(). These commands re-layout
   the window tree with the bar window spanning full editor width,
   pushing sidebar + source + tray into the middle rows.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 14:18:28 -06:00
swaitsandClaude Opus 4.6 988bd06d54 feat: 2-row bars, console clear, registers collapse, fix re-entry layout
Cluster of UX refinements + one real bug:

Bar chrome:
- Shrunk both bars from 3 rows to 2 rows. dapui's own pane borders act
  as the visual separation between the bar and the main content area,
  so the inner-facing separator lines on each bar were redundant.
    Top bar:    sep / content       (no bottom line)
    Bottom bar: content / sep       (no top line)
- Sidebar/Console sizing recalculated: 2-row bars instead of 3 frees
  up 2 extra rows for content.

Smarter legend:
- (R)estart is now conditionally rendered — only shown when a dap
  session is active. When there's no session, "restart" is meaningless
  (there's nothing to restart), so the button hides and the remaining
  controls re-center around the smaller set.

Console clear on start/restart:
- New config.opts.clear_console_on_start (default true). Fires on
  dap.listeners.before.event_initialized — wipes the Console buffer
  so output from a previous run doesn't linger when a new session
  begins.

Registers default-collapsed:
- dapui's own scopes component auto-collapses any scope the adapter
  marks `expensive = true` (see dapui/components/scopes.lua:22-24).
  codelldb (Rust/C++) doesn't mark Registers expensive even though it
  dumps hundreds of entries. We intercept the scopes response via
  dap.listeners.before.scopes and inject `expensive = true` on any
  scope name in config.opts.collapsed_scopes (default `{"Registers"}`).
  Reuses dapui's existing collapse mechanism, so no monkey-patching.

Re-entry layout fix:
- The Console "balloon" bug on second ,dd toggle was dapui caching
  first-call layout dimensions. ensure_dapui() now re-runs dapui.setup
  with freshly computed layouts on EVERY M.enter, so the 25% / 25% /
  25% / 25% sidebar split and 15%-of-available Console all recompute
  against current terminal + current bar heights.
- Bars are now opened BEFORE dapui.open() so dapui's layout algorithm
  sees the reduced available space from the start rather than computing
  against full screen and then getting squished.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 14:08:17 -06:00
swaitsandClaude Opus 4.6 8d1ddc9c78 feat: 3-row control bar with key hints, box lines, help in bar
UX refinement per design feedback:

- Bar is now 3 rows tall: ─ top separator, content row, ─ bottom separator.
  The separator chars were invisible before because TurboDebugBarSeparator
  linked to WinSeparator (muted in most themes). Switched to FloatBorder.
- Bottom tray default shrunk 12→9 rows so the 3-row bar doesn't overlap
  REPL/Console. Net vertical footprint unchanged (12 tray = 9 tray + 3 bar).
- Action labels now teach the keyboard shortcut inline:
    ▶️ (c)ontinue   ⏭️ (s)tep   ⬇️ (d)escend   ⬆️ (r)eturn
    🔄 (R)estart   🛑 (q)uit   ❓ (?)help
  The (k) letter is highlighted with TurboDebugBarKey → Special so the
  shortcut pops. The entire label is a click zone.
- help_on_enter default flipped true → false. The (?)help label in the bar
  is always visible, so new users discover help via the bar instead of an
  auto-popup on every debug-mode entry.
- No top bar added. The source file winbar already shows 🐛 DEBUG · <file>,
  so a second chrome row would just duplicate context and eat screen space.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 12:51:27 -06:00
swaitsandClaude Opus 4.6 a728450607 feat: buffer-rendered control bar, emoji icons, fix IP sign leak
Addresses live-feedback issues that persisted after v3:

- Control bar now uses buffer content + extmarks instead of winbar —
  winbar doesn't render in minimal-style floats, which is why the bar
  was empty. Two rows: ─ separator on top, state chip + controls below.
  Click dispatch via buffer-local <LeftMouse> keymap + cursor-column
  lookup against a zones table.
- Bar auto-refreshes on every dap event (initialized/stopped/continued/
  terminated/exited) so the READY/RUNNING/PAUSED chip and dap.status()
  text stay live.
- Colorful emoji throughout for instant recognition:
    Signs:    🔴 BP, 🟡 conditional, ⭕ rejected, 👉 stopped, 📝 logpoint
    Titles:   🔎 Scopes, 👁️ Watches, 📚 Call Stack, 🔴 Breakpoints,
              💻 Console, 💬 REPL
    Badge:    🐛 DEBUG · <file>
    Controls: ▶️ ⏭️ ⬇️ ⬆️ 🔄 🛑 ❌
- Modal key install no longer skips buffers that already have entries —
  every BufEnter/FileType force-reinstalls the keymaps so dapui's own
  render pass can't leave them in a broken state.
- IP sign leak fixed: clear_ip() now unplaces lingering DapStopped signs
  via sign_getplaced + sign_unplace, so restart no longer leaves a stale
  👉 in the gutter of the previously-paused line.
- IP reason text (STEP/BREAKPOINT/EXCEPTION) now uses bold + reverse for
  an inverted-color badge that really demands attention.
- dapui.expand_lines = false — this was spawning a cursor-pinned float
  when a line was wider than its pane, causing the "hover text bleeds
  across the screen" bug. With wrap+breakindent inside the pane, the
  hover-float is redundant and destructive.
- Control-bar buffer is marked filetype=TurboDebugBar and explicitly
  skipped by the modal key installer, so clicking a button doesn't
  accidentally fire modal actions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 12:38:38 -06:00
swaitsandClaude Opus 4.6 8d8dd23b3a feat: floating control bar, throttled console, wrapped values, Codicon icons
Major v3 fixes driven by live-debugging feedback:

- Control bar: replace vim.o.statusline override (lualine fights it) with
  a 1-row floating window pinned above the statusline. Shows state chip
  (READY/RUNNING/PAUSED) + seven clickable Codicon controls + dap.status().
  Survives resize via VimResized autocmd. Fully independent of lualine.
- Console refresh: trailing-edge throttle at config.console_refresh_ms
  (default 50ms = 20 Hz ceiling). Targets console windows via nvim_win_call
  + redraw! to avoid screen-cache miss. Chatty programs can't DOS the editor.
- Modal keys in dapui panes: install synchronously on FileType (drop inner
  vim.schedule); all modal keys get nowait=true (was continue-only) so
  single-key presses aren't swallowed by <leader>d* prefix matching.
- Wrap in dapui panes: wrap=true + breakindent + showbreak="  ↳ " so long
  register values stay visible inside the pane without bleeding into the
  source window. Safety valve at config.max_value_width (default 2000,
  set 0 to disable) truncates only pathological multi-KB dumps with "…".
- Smart q: context-aware terminate. If a session is running, q calls
  dap.terminate() and stays in debug mode (so user can read the console
  postmortem). If no session, q exits debug mode. Removes quit_exits_mode.
- Icons: full Nerd Font Codicon set for signs, control bar buttons, pane
  titles, and debug badge. 👈 emoji in the paused-line vtext pairs with
  👉 in the gutter — fingers literally point at the paused line from both
  sides.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 12:22:00 -06:00
swaits be628194ec WIP: aesthetics! 2026-04-12 11:35:15 -06:00
swaits e9089b63a2 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)
2026-04-11 20:09:29 -06:00