diff --git a/README.md b/README.md index 6d237e1..b2c5a6f 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/doc/turbo-debug.txt b/doc/turbo-debug.txt index 80463db..03f7798 100644 --- a/doc/turbo-debug.txt +++ b/doc/turbo-debug.txt @@ -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). diff --git a/lua/turbo-debug/adapters/bash.lua b/lua/turbo-debug/adapters/bash.lua new file mode 100644 index 0000000..a94b917 --- /dev/null +++ b/lua/turbo-debug/adapters/bash.lua @@ -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 diff --git a/lua/turbo-debug/adapters/c.lua b/lua/turbo-debug/adapters/c.lua index 7b90d2b..fb711b0 100644 --- a/lua/turbo-debug/adapters/c.lua +++ b/lua/turbo-debug/adapters/c.lua @@ -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 diff --git a/lua/turbo-debug/adapters/dart.lua b/lua/turbo-debug/adapters/dart.lua new file mode 100644 index 0000000..19690ad --- /dev/null +++ b/lua/turbo-debug/adapters/dart.lua @@ -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 diff --git a/lua/turbo-debug/adapters/init.lua b/lua/turbo-debug/adapters/init.lua index 5c99968..127a434 100644 --- a/lua/turbo-debug/adapters/init.lua +++ b/lua/turbo-debug/adapters/init.lua @@ -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 diff --git a/lua/turbo-debug/adapters/r.lua b/lua/turbo-debug/adapters/r.lua new file mode 100644 index 0000000..6710cb4 --- /dev/null +++ b/lua/turbo-debug/adapters/r.lua @@ -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 diff --git a/tests/test_adapters.lua b/tests/test_adapters.lua index db19785..9cf8523 100644 --- a/tests/test_adapters.lua +++ b/tests/test_adapters.lua @@ -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