From c257c2adc42543a856b13d75258b4c8c1ee7512f Mon Sep 17 00:00:00 2001 From: Jannik Donker Date: Fri, 10 Jul 2026 07:56:15 +0200 Subject: [PATCH] more debugging stuff --- lua/debugging.lua | 52 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/lua/debugging.lua b/lua/debugging.lua index ef5c5c6..8a2097d 100644 --- a/lua/debugging.lua +++ b/lua/debugging.lua @@ -2,11 +2,14 @@ local dap, dapui = require("dap"), require("dapui") -- Install debug adapters via Mason (same pattern as the LSP tool loop in -- plugins.lua). codelldb -> c/cpp/rust, debugpy -> python, --- js-debug-adapter -> node/ts. java-debug-adapter is installed by the LSP --- ensure loop and wired through jdtls (see lua/lsp.lua). +-- js-debug-adapter -> node/ts, haskell-debug-adapter -> haskell. +-- java-debug-adapter is installed by the LSP ensure loop and wired through +-- jdtls (see lua/lsp.lua). +-- Note: haskell-debug-adapter builds from source via cabal on first install +-- (needs ghc/cabal on PATH) so it can take a few minutes to appear. local registry = require("mason-registry") registry.refresh(function() - for _, tool in ipairs({ "debugpy", "codelldb", "js-debug-adapter" }) do + for _, tool in ipairs({ "debugpy", "codelldb", "js-debug-adapter", "haskell-debug-adapter" }) do local ok, pkg = pcall(registry.get_package, tool) if ok and not pkg:is_installed() then pkg:install() end end @@ -60,6 +63,49 @@ for _, ft in ipairs({ "javascript", "typescript" }) do } end +-- Haskell (plain ghc): mason-nvim-dap's default handler auto-wires the +-- haskell-debug-adapter, but its default launch config assumes `stack ghci` +-- (with a literal "TARGET" placeholder). Override it to drive ghci-dap +-- directly so a bare `.hs` file debugs with — no cabal/stack project +-- required. ghci-dap resolves via PATH (mason bin). Switch ghciCmd to +-- `cabal exec -- ghci-dap ...` or `stack ghci --with-ghc=ghci-dap ...` if you +-- later move to a build tool. Verified end-to-end: loads ${file}, stops at +-- entry, hits breakpoints. +dap.configurations.haskell = { + { + type = "haskell", + request = "launch", + name = "Debug (ghc)", + workspace = "${workspaceFolder}", + startup = "${file}", + stopOnEntry = true, + logFile = vim.fs.joinpath(vim.fn.stdpath("data"), "haskell-dap.log"), + logLevel = "WARNING", + ghciEnv = vim.empty_dict(), + ghciPrompt = "H>>= ", + ghciInitialPrompt = "ghci> ", + ghciCmd = "ghci-dap --interactive -i${workspaceFolder} ${startup}", + }, +} + +-- Run debuggees in dap-ui's Console terminal so programs that read user input +-- work. Without this, nvim-dap uses an output-only internal console with no +-- stdin (the program just hangs on input()/getLine/scanf). dap-ui registers its +-- Console as dap.defaults.fallback.terminal_win_cmd, so any adapter that runs +-- the program in an integrated terminal is routed there. Adapters disagree on +-- the key -- debugpy/pwa-node use `console`, codelldb uses `terminal` -- and +-- each ignores the other, so set both on every launch config. Applies to the +-- mason-auto-generated configs (python/cpp/rust) too, since it runs after their +-- setup. To type: focus the Console window and press `i` (terminal insert). +for _, configs in pairs(dap.configurations) do + for _, cfg in ipairs(configs) do + if cfg.request == "launch" then + if cfg.console == nil then cfg.console = "integratedTerminal" end + if cfg.terminal == nil then cfg.terminal = "integrated" end + end + end +end + -- Open/close the dap-ui panels automatically with the session. dap.listeners.before.attach.dapui_config = function() dapui.open() end dap.listeners.before.launch.dapui_config = function() dapui.open() end