No description
Find a file
2025-09-09 20:10:39 +00:00
README.md Update README.md 2025-09-09 20:10:39 +00:00

Neovim: Debugging Ergonomics | nvim-dap-ui, dap-scope-walker

The Pragmatic UI

As Always

local dapui = require("dapui")
local dap = require("dap")

-- open the ui as soon as we are debugging
dap.listeners.after.event_initialized["dapui_config"] = function() dapui.open() end
dap.listeners.before.event_terminated["dapui_config"] = function() dapui.close() end
dap.listeners.before.event_exited["dapui_config"] = function() dapui.close() end

Breakpoint Design

-- https://emojipedia.org/en/stickers/search?q=circle
vim.fn.sign_define('DapBreakpoint',
  {
    text = '⚪',
    texthl = 'DapBreakpointSymbol',
    linehl = 'DapBreakpoint',
    numhl = 'DapBreakpoint'
  })

vim.fn.sign_define('DapStopped',
  {
    text = '🔴',
    texthl = 'yellow',
    linehl = 'DapBreakpoint',
    numhl = 'DapBreakpoint'
  })
vim.fn.sign_define('DapBreakpointRejected',
  {
    text = '⭕',
    texthl = 'DapStoppedSymbol',
    linehl = 'DapBreakpoint',
    numhl = 'DapBreakpoint'
  })

dapui.setup() options

https://github.com/rcarriga/nvim-dap-ui?tab=readme-ov-file#variable-scopes

-- more minimal ui
dapui.setup({
  expand_lines = true,
  controls = { enabled = false }, -- no extra play/step buttons
  floating = { border = "rounded" },
  -- Set dapui window
  render = {
    max_type_length = 60,
    max_value_lines = 200,
  },
  -- Only one layout: just the "scopes" (variables) list at the bottom
  layouts = {
    {
      elements = {
        { id = "scopes", size = 1.0 }, -- 100% of this panel is scopes
      },
      size = 15,                       -- height in lines (adjust to taste)
      position = "bottom",             -- "left", "right", "top", "bottom"
    },
  },
})

layouts

https://github.com/rcarriga/nvim-dap-ui?tab=readme-ov-file#configuration

render

basically how things fit into the layout window before they get trimmed

Further information about the dapui config can be found with :h dapui.setup()

custom mappings

local map, opts = vim.keymap.set, { noremap = true, silent = true }

map("n", "<leader>du", function() dapui.toggle() end, { noremap = true, silent = true, desc = "Toggle DAP UI" })

map({ "n", "v" }, "<leader>dw", function() require("dapui").eval(nil, { enter = true }) end,
  { noremap = true, silent = true, desc = "Add word under cursor to Watches" })

map({ "n", "v" }, "Q", function() require("dapui").eval() end,
  {
    noremap = true,
    silent = true,
    desc =
    "Hover/eval a single value (opens a tiny window instead of expanding the full object) "
  })

Pragmatic Debugging of complex types

Don't. Just don't.

Avoid debugging complex types.Debug primitive types instead.

These are the most basic types provided by the language and runtime, such as:

  • int
  • double
  • bool
  • char
  • string (technically not primitive, but its a special built-in reference type)

This requires the code you want to test to be pragmatic as well

If you still have to..

Bring it down to a primitive, or try dap-scope-walker

you can check my latest nvim-dap-ui configuration here: https://git.ramboe.io/configuration/dotfiles-nvim/src/branch/main/lua/configs/nvim-dap-ui.lua