add debugger support

This commit is contained in:
2026-10-15 11:18:36 -09:00
parent f6115bc048
commit 24392b0e5b
3 changed files with 118 additions and 2 deletions
+101 -1
View File
@@ -114,7 +114,107 @@
{lhs "<leader>h" :group "hunk"}
{lhs "<leader>t" :group "toggle"}
{lhs "<leader>l" :group "log"}
{lhs "<leader>a" :group "AI/Claude"}]))}
{lhs "<leader>a" :group "AI/Claude"}
{lhs "<leader>d" :group "debug"}]))}
;; nvim-dap + nvim-dap-ui - Debugging via the Debug Adapter Protocol
;; Adapters: lldb-dap (LLVM) for Rust, C and compiled rust-mal .clj
;; executables, and gdb (-i dap) for .clj too. rust-mal's executables
;; carry their gdb script (mal_Value variables shown as Clojure prints
;; them); gdb runs it once auto-loading is allowed for their directory.
;; The lldb one is imported when the cwd has debug/rust_mal_lldb.py.
{repo "rcarriga/nvim-dap-ui"
:dependencies ["mfussenegger/nvim-dap" "nvim-neotest/nvim-nio"]
:keys [{lhs "<F5>" rhs #((. (require :dap) :continue)) :desc "Debug: start/continue"}
{lhs "<F6>" rhs #((. (require :dap) :terminate)) :desc "Debug: stop"}
{lhs "<F7>" rhs #((. (require :dapui) :toggle)) :desc "Debug: toggle UI"}
{lhs "<F8>" rhs #((. (require :dap) :run_to_cursor)) :desc "Debug: run to cursor"}
{lhs "<F9>" rhs #((. (require :dap) :toggle_breakpoint)) :desc "Debug: toggle breakpoint"}
{lhs "<F10>" rhs #((. (require :dap) :step_over)) :desc "Debug: step over"}
{lhs "<F11>" rhs #((. (require :dap) :step_into)) :desc "Debug: step into"}
{lhs "<F12>" rhs #((. (require :dap) :step_out)) :desc "Debug: step out"}
{lhs "<leader>db" rhs #((. (require :dap) :set_breakpoint) (vim.fn.input "Condition: "))
:desc "Conditional breakpoint"}
{lhs "<leader>dl" rhs #((. (require :dap) :set_breakpoint) nil nil (vim.fn.input "Log message: "))
:desc "Log point"}
{lhs "<leader>dB" rhs #((. (require :dap) :clear_breakpoints)) :desc "Clear breakpoints"}
{lhs "<leader>dr" rhs #((. (require :dap) :run_last)) :desc "Re-run last session"}
{lhs "<leader>dR" rhs #((. (require :dap) :restart)) :desc "Restart session"}
{lhs "<leader>dk" rhs #((. (require :dap) :up)) :desc "Frame up"}
{lhs "<leader>dj" rhs #((. (require :dap) :down)) :desc "Frame down"}
{lhs "<leader>de" rhs #((. (require :dapui) :eval)) :mode [:n :v] :desc "Eval expression"}
{lhs "<leader>dE" rhs #((. (require :dapui) :eval) (vim.fn.input "Expression: "))
:desc "Eval prompt"}
{lhs "<leader>do" rhs #((. (require :dap) :repl :toggle)) :desc "Toggle debug REPL"}]
:config (fn []
(local dap (require :dap))
(local dapui (require :dapui))
(dapui.setup)
;; Open/close the UI with the session
(set dap.listeners.after.event_initialized.dapui #(dapui.open))
(set dap.listeners.before.event_terminated.dapui #(dapui.close))
(set dap.listeners.before.event_exited.dapui #(dapui.close))
(vim.fn.sign_define "DapBreakpoint" {:text "●" :texthl "DiagnosticError"})
(vim.fn.sign_define "DapBreakpointCondition" {:text "◆" :texthl "DiagnosticWarn"})
(vim.fn.sign_define "DapLogPoint" {:text "◉" :texthl "DiagnosticInfo"})
(vim.fn.sign_define "DapStopped" {:text "▶" :texthl "DiagnosticOk"
:linehl "Visual"})
(set dap.adapters.lldb {:type "executable"
:command "lldb-dap"
:name "lldb"})
;; Import rust-mal's lldb formatters when debugging from a rust-mal checkout
(fn init-commands []
(let [script (.. (vim.fn.getcwd) "/debug/rust_mal_lldb.py")]
(if (= 1 (vim.fn.filereadable script))
[(.. "command script import " script)]
[])))
(fn launch [default-program]
{:name "Launch executable"
:type "lldb"
:request "launch"
:program #(vim.fn.input "Executable: " (default-program) "file")
:args #(vim.split (vim.fn.input "Args: ") " " {:trimempty true})
:cwd "${workspaceFolder}"
:stopOnEntry false
:initCommands init-commands})
;; gdb's own DAP server (gdb 14+), allowed to auto-load the scripts of
;; the program's directory (rust-mal's pretty-printers are in the
;; executable). Unlike lldb-dap, in .clj files its watches and
;; breakpoint conditions are Clojure (built with --debug)
(set dap.adapters.gdb
(fn [callback config]
(let [program (or config.program "")
dir (if (= program "")
(vim.fn.getcwd)
(vim.fn.fnamemodify program ":p:h"))]
(callback {:type "executable"
:command "gdb"
:args ["-q" "-i" "dap"
"-iex" (.. "add-auto-load-safe-path " dir)]}))))
(fn gdb-launch [default-program]
{:name "Launch executable (gdb)"
:type "gdb"
:request "launch"
:program #(vim.fn.input "Executable: " (default-program) "file")
:args #(vim.split (vim.fn.input "Args: ") " " {:trimempty true})
:cwd "${workspaceFolder}"
:stopAtBeginningOfMainSubprogram false})
;; rust-mal: `rust-mal -O0 foo.clj` writes ./foo next to foo.clj
(set dap.configurations.clojure
[(gdb-launch #(vim.fn.expand "%:p:r"))
(launch #(vim.fn.expand "%:p:r"))])
(set dap.configurations.rust
[(launch #(.. (vim.fn.getcwd) "/target/debug/"))])
(set dap.configurations.c
[(launch #(.. (vim.fn.getcwd) "/"))]))}
;; claudecode.nvim - Claude Code AI assistant integration
{repo "coder/claudecode.nvim"