Skip to content

igorlfs/nvim-dap-view

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GitHub Workflow Status Lua

nvim-dap-view

minimalistic nvim-dap-ui alternative

dap-view-demo2.mp4

Warning

Currently requires a neovim nightly (0.11+)

Installation

Via lazy.nvim

return {
    {
        "igorlfs/nvim-dap-view",
        opts = {},
    },
}

For a better experience, consider adding nvim-dap-view as a dependency for nvim-dap (instead of declaring it as a standalone plugin)

Why?

By default, when launching a session, nvim-dap's terminal window takes half the screen. As a saner default, nvim-dap-view hijacks the terminal window (even if not invoked), making the split take only 12 (configurable) lines.

-- Your nvim-dap config
return {
    {
        "mfussenegger/nvim-dap",
        dependencies = {
            { "igorlfs/nvim-dap-view", opts = {} },
            ...,
        },
        ...,
    },
}

Features

The plugin provides 4 "views" that share the same window (so there's clutter)

  • Watches view
    • Shows a list of (user defined) expressions, that are evaluated by the debug adapter
    • Add, edit and delete expressions from the watch list
      • Including adding the variable under the cursor

watches view

  • Exceptions view
    • Control when the debugger should stop, outside of breakpoints (e.g., whenever an exception is thrown, or when an exception is caught1).
    • Toggle filter with <CR>

exceptions view

  • Breakpoints view
    • List all breakpoints
      • Uses syntax highlighting2
      • Shows filename and number line
    • Jump to a breakpoint with <CR>

breakpoints view

  • REPL view
    • Use REPL provided by nvim-dap

repl view

You can also interact with the console provided by nvim-dap (though, arguably, that's not a feature from nvim-dap-view). The console has its own window. However, its default size (height) is resized to match your nvim-dap-view configuration. You can also completely hide it, if it's not being used.

console

Documentation

Configuration

Default options
return {
    winbar = {
        show = true,
        sections = { "watches", "exceptions", "breakpoints", "repl" },
        -- Must be one of the sections declared above
        default_section = "watches",
    },
    windows = {
        height = 12,
        terminal = {
            -- List of adapters for which the terminal should be hidden
            hide = {},
        },
    },
}

Usage

Start a regular debugging session. When desired, you can use :DapViewOpen to start the plugin. You can switch to a view (section) using the letter outlined in the 'winbar' (e.g., B for the breakpoints view).

Both the breakpoints view and the exceptions view have only 1 mapping: <CR>. It jumps to a breakpoint and toggles an exception filter, respectively. The watches view comes with 3 mappings:

  • i to insert a new expression
  • e to edit an expression
  • d to delete an expression

Though, the preferred way of adding a new expression is using the :DapViewWatch command. In normal mode, it adds the variable under the cursor to the watch list.

When you finish your session, you can use :DapViewClose to close the nvim-dap-view window.

In total, there are 4 commands:

  • DapViewOpen
  • DapViewClose
  • DapViewToggle
  • DapViewWatch

If you prefer using lua functions, I got you covered! The following provide the same functionality as above:

require("dap-view").open()
require("dap-view").close()
require("dap-view").toggle()
require("dap-view").add_expr()

nvim-dap-view doesn't define any keybindings (outside its own buffer, of course). An example for the toggle functionality, using the lua API:

vim.keymap.set("n", "<leader>v", function()
    require("dap-view").toggle()
end, { desc = "Toggle nvim-dap-view" })

Recommended Setup

Hide Terminal

Some debug adapters don't use the integrated terminal (console). To avoid having a useless window lying around, you can completely hide the terminal for them. To achieve that, add the following snippet to your nvim-dap-view setup:

-- Goes into your opts table (if using lazy.nvim), otherwise goes into the setup function
-- No need to include the "return" statement (or the outer curly braces)
return {
    windows = {
        terminal = {
            -- NOTE Don't copy paste this snippet
            -- Use the actual names for the adapters you want to hide
            -- `delve` is known to not use the terminal
            hide = { "delve", "some-other-adapter" },
        },
    },
}

Highlight Groups

nvim-dap-view defines 8 highlight groups:

NvimDapViewMissingData
NvimDapViewWatchText
NvimDapViewWatchTextChanged
NvimDapViewExceptionFilterEnabled
NvimDapViewExceptionFilterDisabled
NvimDapViewBreakpointFileName
NvimDapViewBreakpointLineNumber
NvimDapViewBreakpointSeparator

They are linked to (somewhat) reasonable defaults, but they may look odd with your colorscheme. Consider contributing to your colorscheme by sending a PR to add support to nvim-dap-view.

Filetypes and autocommands

nvim-dap-view sets buffer filetypes for the following Views

Window Filetype
watches, exceptions, breakpoints dap-view
terminal dap-view-term

These filetypes can be used to override buffer and window options set by nvim-dap-view

Example autocommand

Map q to quit in nvim-dap-view filetypes:

vim.api.nvim_create_autocmd({ "FileType" }, {
    pattern = { "dap-view", "dap-view-term", "dap-repl" }, -- dap-repl is set by `nvim-dap`
    callback = function(evt)
        vim.keymap.set("n", "q", "<C-w>q", { silent = true, buffer = evt.buf })
    end,
})

Roadmap

  • Watches
    • Actions
      • Expanding variables
      • Yank expression's value
  • Threads and Stacks view

Missing something? Create an issue with a feature request!

Non-goals

Implement every feature from nvim-dap-ui. More specifically,

  • There will be no "scopes" view (i.e., list all variables in scope). The rationale is that nvim-dap already provides a very nice UI for that, using widgets (see :h dap-widgets). The TLDR is that you can use
function()
    local widgets = require("dap.ui.widgets")
    widgets.centered_float(widgets.scopes, { border = "rounded" })
end

to create a nice, centered floating window, where you can navigate and explore variables. A major advantage from this approach is that you're not limited to a small window at the bottom of your screen (which can be troublesome in noisy environments or languages).

  • Likewise, there will be no "hover" view, since it's also perfectly handled by nvim-dap's widgets. You can use
function() require("dap.ui.widgets").hover(nil, { border = "rounded" }) end

Known Issues

  • Breakpoints view doesn't show breakpoint conditions
    • That's a limitation with the current breakpoints API from nvim-dap. We could use a workaround, but a new API is planned

Acknowledgements

  • Code to inject treesitter highlights into line is taken from quicker.nvim;
  • Some snippets are directly extracted from nvim-dap:
    • Currently, there's no API to extract breakpoint information (see issue), so we resort to using nvim-dap internal mechanism, that tracks extmarks;
    • The magic to extract expressions from visual mode is also a courtesy of nvim-dap.
  • lucaSartore for the inspiration for handling breakpoint exceptions;
  • Kulala for the creative usage of neovim's 'winbar' to handle multiple views.
  • blink.cmp for the config validation (which is partialy taken from a PR to indent-blankline)

Footnotes

  1. Filters depend on the debug adapter's capabilities

  2. From treesitter and extmarks (e.g., semantic highlighting from LSP)

Releases

No releases published

Packages

No packages published

Languages