Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
20dec9bc7b
|
||
|
|
5118c03f83
|
||
|
|
31daa1582c
|
||
|
|
f8cce8da37
|
No files matched your search
@@ -1,5 +1,64 @@
|
||||
# Changelog
|
||||
|
||||
## 0.2.2 — 2026-04-12
|
||||
|
||||
Bug-fix release: Python program output now shows in the Console pane, and
|
||||
breakpoints restore for files opened on the command line.
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Python `print()` output appears in the Console pane.** The debugpy
|
||||
launch config now sets `console = "integratedTerminal"`, so debugpy
|
||||
routes stdout/stderr via `RunInTerminalRequest` into dapui's Console
|
||||
buffer (which is already registered as
|
||||
`dap.defaults.fallback.terminal_win_cmd`). Previously debugpy defaulted
|
||||
to `internalConsole` and emitted `OutputEvent`s that nvim-dap forwards
|
||||
to the REPL buffer — which turbo-debug's layout deliberately omits, so
|
||||
program output vanished. Interactive `input()` now also works.
|
||||
- **Breakpoints restore for files opened on the command line.** `nvim
|
||||
foo.py` fires `BufReadPost` for `foo.py` before turbo-debug's deferred
|
||||
`setup()` runs, so `persistent-breakpoints.nvim`'s `BufReadPost`
|
||||
autocmd missed the startup buffer and saved breakpoints never came
|
||||
back. After setup, turbo-debug now sweeps already-loaded buffers once
|
||||
via `load_breakpoints()` (idempotent; placed after `sign_define` so
|
||||
the first paint uses turbo-debug's emoji signs instead of dap's
|
||||
default `B`).
|
||||
|
||||
## 0.2.1 — 2026-04-12
|
||||
|
||||
Language coverage release. 10 new DAP adapters bring built-in support from
|
||||
12 to 22 languages, prioritized by language popularity and DAP adapter
|
||||
maturity.
|
||||
|
||||
### Added
|
||||
|
||||
- **Dart** (with optional **Flutter**) — auto-detects `flutter` on PATH and
|
||||
adds a "Launch Flutter app" configuration alongside the plain Dart file
|
||||
launch. Uses `dart debug_adapter` / `flutter debug_adapter`.
|
||||
- **Bash / Sh** — `bash-debug-adapter` with automatic `bashdb_dir` probing
|
||||
from the mason package path.
|
||||
- **R** — `vscDebugger` R-package integration. Preflights the package via
|
||||
`Rscript` and silently skips registration if it's missing.
|
||||
- **Elixir** — `elixir-ls-debugger` with `mix_task` launch (default task
|
||||
`test`). Falls back to the mason package `debugger.sh` if the wrapper
|
||||
binary isn't on PATH.
|
||||
- **Haskell** — `haskell-debug-adapter`.
|
||||
- **OCaml** — `ocamlearlybird`.
|
||||
- **Zig / Nim / Crystal** — routed through the existing `codelldb` adapter
|
||||
via filetype extension (no new adapter; just added filetypes to the
|
||||
existing codelldb configuration).
|
||||
- **F#** — routed through the existing `netcoredbg` adapter (same
|
||||
`.dll`-launch flow as C#).
|
||||
|
||||
### Internal
|
||||
|
||||
- Extended `tests/test_adapters.lua` to cover the three new modular adapter
|
||||
modules (`dart`, `bash`, `r`).
|
||||
- All new registrations follow the existing `find_executable` +
|
||||
`loader.register` pattern and silently skip when the required binary
|
||||
isn't found — matches the "no noise when prereqs missing" invariant of
|
||||
the previously-shipped adapters.
|
||||
|
||||
## 0.2.0 — 2026-04-12
|
||||
|
||||
Major UI rework and stability release. Two floating chrome bars replace the
|
||||
|
||||
@@ -180,21 +180,33 @@ Both bars:
|
||||
|
||||
## Supported Languages
|
||||
|
||||
turbo-debug ships adapter configs for 12 languages. You install the adapter
|
||||
turbo-debug ships adapter configs for 22 languages. You install the adapter
|
||||
binary (via [mason.nvim](https://github.com/williamboman/mason.nvim), your
|
||||
package manager, or manually) — turbo-debug handles all the configuration.
|
||||
|
||||
| Language | Adapter | Language | Adapter |
|
||||
|----------|---------|----------|---------|
|
||||
| Python | debugpy | C# | netcoredbg |
|
||||
| JavaScript / TS | js-debug | Java | java-debug-adapter |
|
||||
| Go | delve | Kotlin | kotlin-debug |
|
||||
| C / C++ | codelldb | PHP | php-debug |
|
||||
| Rust | codelldb | Ruby | rdbg |
|
||||
| Swift | codelldb | Lua (Neovim) | osv |
|
||||
| JavaScript / TS | js-debug | F# | netcoredbg |
|
||||
| Go | delve | Java | java-debug-adapter |
|
||||
| C / C++ | codelldb | Kotlin | kotlin-debug |
|
||||
| Rust | codelldb | PHP | php-debug |
|
||||
| Swift | codelldb | Ruby | rdbg |
|
||||
| Zig | codelldb | Elixir | elixir-ls |
|
||||
| Nim | codelldb | Haskell | haskell-debug-adapter |
|
||||
| Crystal | codelldb | OCaml | ocamlearlybird |
|
||||
| Dart / Flutter | dart-debug | R | vscDebugger |
|
||||
| Bash / Sh | bash-debug-adapter | Lua (Neovim) | osv |
|
||||
|
||||
Rust gets special treatment: pressing `c` runs `cargo build` automatically
|
||||
and picks the binary via `vim.ui.select`.
|
||||
Special treatment:
|
||||
- **Rust**: pressing `c` runs `cargo build` automatically and picks the
|
||||
binary via `vim.ui.select`.
|
||||
- **Python**: auto-detects virtualenvs (`VIRTUAL_ENV`, `CONDA_PREFIX`,
|
||||
`.venv`, `venv`, `env`, `.env`).
|
||||
- **Dart**: if `flutter` is on PATH, a "Launch Flutter app" configuration
|
||||
is added alongside the plain Dart file launch.
|
||||
- **R**: preflights that the `vscDebugger` R package is installed; silently
|
||||
skips registration if missing.
|
||||
|
||||
## What This Plugin Actually Does
|
||||
|
||||
|
||||
+21
-1
@@ -32,7 +32,7 @@ Features:
|
||||
- Floating REPL eval (|E|)
|
||||
- Floating status bar + control bar chrome (independent of any statusline
|
||||
plugin)
|
||||
- Zero-config adapters for 12 languages
|
||||
- Zero-config adapters for 22 languages
|
||||
- Theme-agnostic colors (every highlight links to a standard group)
|
||||
|
||||
==============================================================================
|
||||
@@ -332,11 +332,22 @@ Built-in adapter support (adapter binary must be installed):
|
||||
C/C++ codelldb codelldb
|
||||
Rust codelldb codelldb
|
||||
Swift codelldb codelldb
|
||||
Zig codelldb codelldb
|
||||
Nim codelldb codelldb
|
||||
Crystal codelldb codelldb
|
||||
C# netcoredbg netcoredbg
|
||||
F# netcoredbg netcoredbg
|
||||
Java java-debug java-debug-adapter
|
||||
Kotlin kotlin-debug kotlin-debug-adapter
|
||||
PHP php-debug php-debug-adapter
|
||||
Ruby rdbg rdbg
|
||||
Dart dart-debug dart debug_adapter
|
||||
Flutter flutter-debug flutter debug_adapter
|
||||
Bash / Sh bash-debug bash-debug-adapter
|
||||
Elixir elixir-ls elixir-ls-debugger
|
||||
Haskell haskell-debug haskell-debug-adapter
|
||||
OCaml earlybird ocamlearlybird
|
||||
R vscDebugger R (with vscDebugger pkg)
|
||||
Lua (Neovim) osv one-small-step-for-vimkind
|
||||
|
||||
Path resolution order:
|
||||
@@ -350,6 +361,15 @@ and picks the binary via `vim.ui.select` if multiple artifacts exist.
|
||||
Python auto-detects virtualenvs: `VIRTUAL_ENV`, `CONDA_PREFIX`, then the
|
||||
common directories `.venv`, `venv`, `env`, `.env` relative to `cwd`.
|
||||
|
||||
Dart auto-detects Flutter: if `flutter` is on PATH alongside `dart`, a
|
||||
"Launch Flutter app" configuration is added to the `dart` filetype in
|
||||
addition to the plain Dart file launch.
|
||||
|
||||
R requires the `vscDebugger` R package. turbo-debug preflights it via
|
||||
`Rscript` and silently skips registration if the package is missing. Install
|
||||
with `install.packages("vscDebugger")` or
|
||||
`remotes::install_github("ManuelHentschel/vscDebugger")`.
|
||||
|
||||
Adapter binaries are the user's responsibility to install (mason.nvim is
|
||||
the easiest route).
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
local loader = require("turbo-debug.adapters.init")
|
||||
|
||||
local M = {}
|
||||
|
||||
function M.register(dap)
|
||||
local exe = loader.find_executable({ "bash-debug-adapter" })
|
||||
if not exe then return end
|
||||
|
||||
local bashdb_dir = vim.fn.stdpath("data") .. "/mason/packages/bash-debug-adapter/extension/bashdb_dir"
|
||||
if vim.fn.isdirectory(bashdb_dir) == 0 then bashdb_dir = nil end
|
||||
|
||||
loader.register(dap, "bashdb", {
|
||||
type = "executable",
|
||||
command = exe,
|
||||
name = "bashdb",
|
||||
}, {
|
||||
{
|
||||
type = "bashdb",
|
||||
request = "launch",
|
||||
name = "Launch file",
|
||||
showDebugOutput = true,
|
||||
pathBashdb = bashdb_dir and (bashdb_dir .. "/bashdb") or "bashdb",
|
||||
pathBashdbLib = bashdb_dir,
|
||||
trace = true,
|
||||
file = "${file}",
|
||||
program = "${file}",
|
||||
cwd = "${workspaceFolder}",
|
||||
pathCat = "cat",
|
||||
pathBash = "/bin/bash",
|
||||
pathMkfifo = "mkfifo",
|
||||
pathPkill = "pkill",
|
||||
args = {},
|
||||
env = {},
|
||||
terminalKind = "integrated",
|
||||
},
|
||||
}, { "sh", "bash" })
|
||||
end
|
||||
|
||||
return M
|
||||
@@ -62,7 +62,7 @@ function M.register(dap)
|
||||
cwd = "${workspaceFolder}",
|
||||
},
|
||||
}
|
||||
for _, ft in ipairs({ "c", "cpp", "swift" }) do
|
||||
for _, ft in ipairs({ "c", "cpp", "swift", "zig", "nim", "crystal" }) do
|
||||
dap.configurations[ft] = dap.configurations[ft] or prompt_config
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
local loader = require("turbo-debug.adapters.init")
|
||||
|
||||
local M = {}
|
||||
|
||||
function M.register(dap)
|
||||
local dart = loader.find_executable({ "dart" })
|
||||
if not dart then return end
|
||||
|
||||
local configs = {
|
||||
{
|
||||
type = "dart",
|
||||
request = "launch",
|
||||
name = "Launch Dart file",
|
||||
program = "${file}",
|
||||
cwd = "${workspaceFolder}",
|
||||
toolArgs = { "--enable-vm-service" },
|
||||
},
|
||||
}
|
||||
|
||||
local flutter = loader.find_executable({ "flutter" })
|
||||
if flutter then
|
||||
if not dap.adapters.flutter then
|
||||
dap.adapters.flutter = {
|
||||
type = "executable",
|
||||
command = flutter,
|
||||
args = { "debug_adapter" },
|
||||
}
|
||||
end
|
||||
table.insert(configs, {
|
||||
type = "flutter",
|
||||
request = "launch",
|
||||
name = "Launch Flutter app",
|
||||
program = "lib/main.dart",
|
||||
cwd = "${workspaceFolder}",
|
||||
flutterMode = "debug",
|
||||
})
|
||||
end
|
||||
|
||||
loader.register(dap, "dart", {
|
||||
type = "executable",
|
||||
command = dart,
|
||||
args = { "debug_adapter" },
|
||||
}, configs, { "dart" })
|
||||
end
|
||||
|
||||
return M
|
||||
@@ -38,7 +38,7 @@ local function register_simple_adapters(dap)
|
||||
program = function() return vim.fn.input("Path to DLL: ", vim.fn.getcwd() .. "/bin/Debug/", "file") end,
|
||||
},
|
||||
},
|
||||
{ "cs" },
|
||||
{ "cs", "fsharp" },
|
||||
},
|
||||
|
||||
{
|
||||
@@ -119,6 +119,77 @@ local function register_simple_adapters(dap)
|
||||
},
|
||||
{ "ruby" },
|
||||
},
|
||||
|
||||
{
|
||||
"mix_task",
|
||||
{
|
||||
"elixir-ls-debugger",
|
||||
"elixir-ls-debug-adapter",
|
||||
vim.fn.stdpath("data") .. "/mason/packages/elixir-ls/debugger.sh",
|
||||
},
|
||||
{
|
||||
type = "executable",
|
||||
},
|
||||
{
|
||||
{
|
||||
type = "mix_task",
|
||||
request = "launch",
|
||||
name = "mix test",
|
||||
task = "test",
|
||||
taskArgs = { "--trace" },
|
||||
startApps = true,
|
||||
projectDir = "${workspaceFolder}",
|
||||
requireFiles = { "test/**/test_helper.exs", "test/**/*_test.exs" },
|
||||
},
|
||||
},
|
||||
{ "elixir" },
|
||||
},
|
||||
|
||||
{
|
||||
"haskell",
|
||||
{ "haskell-debug-adapter" },
|
||||
{
|
||||
type = "executable",
|
||||
},
|
||||
{
|
||||
{
|
||||
type = "haskell",
|
||||
request = "launch",
|
||||
name = "Launch file",
|
||||
workspace = "${workspaceFolder}",
|
||||
startup = "${file}",
|
||||
stopOnEntry = true,
|
||||
logFile = vim.fn.stdpath("data") .. "/haskell-dap.log",
|
||||
logLevel = "WARNING",
|
||||
ghciEnv = vim.empty_dict(),
|
||||
ghciPrompt = "H>>= ",
|
||||
ghciInitialPrompt = "Prelude>",
|
||||
ghciCmd = "cabal exec -- ghci-dap --interactive -i -i${workspaceFolder}",
|
||||
},
|
||||
},
|
||||
{ "haskell" },
|
||||
},
|
||||
|
||||
{
|
||||
"ocamlearlybird",
|
||||
{ "ocamlearlybird" },
|
||||
{
|
||||
type = "executable",
|
||||
args = { "debug" },
|
||||
},
|
||||
{
|
||||
{
|
||||
type = "ocamlearlybird",
|
||||
request = "launch",
|
||||
name = "Launch bytecode",
|
||||
program = function()
|
||||
return vim.fn.input("Path to bytecode: ", vim.fn.getcwd() .. "/_build/default/", "file")
|
||||
end,
|
||||
stopOnEntry = false,
|
||||
},
|
||||
},
|
||||
{ "ocaml" },
|
||||
},
|
||||
}
|
||||
|
||||
for _, s in ipairs(simple) do
|
||||
@@ -153,7 +224,7 @@ function M.setup()
|
||||
local dap = require("dap")
|
||||
|
||||
-- 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", "dart", "bash", "r" }) do
|
||||
local ok, adapter_mod = pcall(require, "turbo-debug.adapters." .. name)
|
||||
if ok and adapter_mod.register then adapter_mod.register(dap) end
|
||||
end
|
||||
|
||||
@@ -36,6 +36,14 @@ function M.register(dap)
|
||||
name = "Launch file",
|
||||
program = "${file}",
|
||||
pythonPath = function() return find_python() end,
|
||||
-- integratedTerminal routes the program via RunInTerminalRequest,
|
||||
-- which nvim-dap spawns in a terminal buffer. dapui registers its
|
||||
-- Console element as `dap.defaults.fallback.terminal_win_cmd`, so
|
||||
-- stdout/stderr land in the visible Console pane. Default
|
||||
-- (internalConsole) sends OutputEvents that nvim-dap routes to the
|
||||
-- REPL buffer — which turbo-debug's layout deliberately omits, so
|
||||
-- print() output vanishes. `input()` also works under this mode.
|
||||
console = "integratedTerminal",
|
||||
},
|
||||
}, { "python" })
|
||||
end
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
local loader = require("turbo-debug.adapters.init")
|
||||
|
||||
local M = {}
|
||||
|
||||
-- vscDebugger is an R package, not a standalone binary. It must be installed
|
||||
-- in the user's R library (install.packages("vscDebugger") or remotes::install_github).
|
||||
-- Silently skip registration if it's missing — matches the "no noise when
|
||||
-- prereqs missing" invariant used by the other adapters.
|
||||
local function has_vsc_debugger()
|
||||
if vim.fn.executable("Rscript") ~= 1 then return false end
|
||||
vim.fn.system({
|
||||
"Rscript",
|
||||
"-e",
|
||||
"if (!requireNamespace('vscDebugger', quietly=TRUE)) quit(status=1)",
|
||||
})
|
||||
return vim.v.shell_error == 0
|
||||
end
|
||||
|
||||
function M.register(dap)
|
||||
local R = loader.find_executable({ "R" })
|
||||
if not R then return end
|
||||
if not has_vsc_debugger() then return end
|
||||
|
||||
loader.register(dap, "r", {
|
||||
type = "executable",
|
||||
command = R,
|
||||
args = { "-e", "vscDebugger::.vsc.listenForDAP()" },
|
||||
}, {
|
||||
{
|
||||
type = "r",
|
||||
request = "launch",
|
||||
name = "Launch R file",
|
||||
program = "${file}",
|
||||
cwd = "${workspaceFolder}",
|
||||
},
|
||||
}, { "r", "rmd" })
|
||||
end
|
||||
|
||||
return M
|
||||
@@ -61,6 +61,16 @@ function M.setup()
|
||||
vim.fn.sign_define(s[1], spec)
|
||||
end
|
||||
|
||||
-- persistent-breakpoints.setup() only installs its BufReadPost autocmd —
|
||||
-- for files opened from the command line (`nvim foo.py`), BufReadPost has
|
||||
-- already fired before our deferred plugin/turbo-debug.lua setup runs, so
|
||||
-- the autocmd misses the startup buffer and saved breakpoints never
|
||||
-- reappear. load_breakpoints() iterates all listed buffers and is
|
||||
-- idempotent, so one post-sign_define sweep catches the missed ones
|
||||
-- without a flicker of dap's default 'B' sign. Placed after sign_define
|
||||
-- so the restored breakpoints render with our emoji from the first paint.
|
||||
pcall(require("persistent-breakpoints.api").load_breakpoints)
|
||||
|
||||
-- unobtrusive inline virtual text: italic, comment-colored
|
||||
vim.api.nvim_set_hl(0, "NvimDapVirtualText", { default = true, link = "Comment", italic = true })
|
||||
vim.api.nvim_set_hl(0, "NvimDapVirtualTextChanged", { default = true, link = "DiagnosticWarn", italic = true })
|
||||
|
||||
@@ -9,7 +9,7 @@ assert_eq(loader.find_executable({ "totally-fake-binary-xyz" }), nil, "non-exist
|
||||
assert_eq(loader.find_executable({ "sh" }) ~= nil, true, "find_executable finds sh")
|
||||
|
||||
-- all adapter modules load and have register()
|
||||
for _, name in ipairs({ "python", "go", "c", "javascript" }) do
|
||||
for _, name in ipairs({ "python", "go", "c", "javascript", "dart", "bash", "r" }) do
|
||||
assert_eq(type(require("turbo-debug.adapters." .. name).register), "function", name .. " has register()")
|
||||
end
|
||||
|
||||
|
||||
Reference in new issue
Block a user