Skip to content

Latest commit

 

History

History
254 lines (199 loc) · 8.84 KB

File metadata and controls

254 lines (199 loc) · 8.84 KB

Keymaps

nvim-dapper ships two layers of keymaps:

Layer Where it lives Default policy
View-local Each panel view's scratch buffer Always on
Global Your normal-mode (and visual) maps Opt-in only

The single module lua/nvim-dapper/keymaps/ owns every vim.keymap.set call in the plugin (enforced by the keymap-isolation lint). All bindings carry nowait = true, silent = true, noremap = true, and a self-documenting desc field — so :map <key> inside any panel buffer tells you what the key does.


View-local defaults

These bindings are installed on the view's scratch buffer at mount time. They follow Neovim list-view idiom (<CR> / o to go-to, l / h to expand / collapse).

Variables, Watches, Breakpoints, Stack, Console (universal)

Key Action
<CR>, o, <2-LeftMouse> jump-to-source
<Tab>, l expand
h collapse
zR expand-all-children
zM collapse-all-children
r retry
]p load-more
L cycle-view-next
H cycle-view-prev

Stack view (extras)

Key Action Notes
<CR> jump-to-frame Falls through to jump-to-source when not on a frame row.

The previous <C-]> secondary binding was removed because it shadowed Neovim's built-in tag jump. Restore it via setup({ keymaps = { stack = { ["jump-to-frame"] = { "<CR>", "<C-]>" } } } }) if you want it back.

Breakpoints view (extras)

Key Action
t toggle-enabled
dd remove
e edit-condition

Watches view (extras)

Key Action
a add-watch
dd remove-watch
e edit-watch-expression

Console view (extras)

Key Mode Action
<CR> i submit

The console view registers three more actions that ship without a default key because every plausible Ctrl-binding shadows a built-in Neovim shortcut:

  • clear-console — previously <C-l> (collided with redraw / window navigation).
  • recall-previous (insert mode) — previously <C-p> (collided with keyword completion).
  • recall-next (insert mode) — previously <C-n> (collided with keyword completion).

Restore the prior bindings (or pick your own) with:

require("nvim-dapper").setup({
  keymaps = {
    console = {
      ["clear-console"]   = "<C-l>",
      ["recall-previous"] = { mode = "i", lhs = "<C-p>" },
      ["recall-next"]     = { mode = "i", lhs = "<C-n>" },
    },
  },
})

The view-local defaults never bind anything in the <leader>d… namespace (reserved for the AI feature surface) or any function key (reserved for the opt-in global layer). A runtime check (_assert_namespace_safe) enforces this every time the defaults table loads.


Global defaults (opt-in)

These bindings are installed in your normal-mode (and, for evaluate, visual-mode) keymap table — but only when you opt in.

Key Mode Operation
<F5> n continue
<F10> n step_over
<F11> n step_into
<S-F11> n step_out
<F9> n toggle_breakpoint
<leader>dB n set_conditional_breakpoint (prompts)
<leader>dL n set_logpoint (prompts)
<leader>de n evaluate — word under cursor
<leader>de x evaluate — visual selection
<leader>dr n restart
<leader>dt n terminate
<leader>dC n run_to_cursor
<leader>du n toggle_panel

Enable with:

require("nvim-dapper").setup({
  keymaps = { global = { enabled = true } },
})

Recommended with panel-focused stepping:

require("nvim-dapper").setup({
  stopped_frame_source_targeting = true,
  keymaps = { global = { enabled = true } },
})

continue, step_over, step_into, and step_out remain thin calls to nvim-dap. The protection comes from Dapper's opt-in managed switchbuf policy. It reuses an eligible editing window for stopped source, including unopened source buffers, and opens a split only when no editing window is available. The managed policy covers dap.defaults.fallback.switchbuf and adapter-specific dap.defaults.<type>.switchbuf values for active sessions, then restores the prior values when disabled. If nvim-dap loads after setup(), Dapper keeps the opt-in pending and installs once dap is available.

Plain setup({}) does not change dap.defaults.fallback.switchbuf, so custom nvim-dap switchbuf strings or functions are preserved unless you explicitly enable stopped_frame_source_targeting.


Customising view-local keymaps

Pass per-view overrides under each view's existing options table:

require("nvim-dapper").setup({
  variables = {
    keymaps = {
      ["jump-to-source"] = "gd",                     -- replace default
      ["expand"]         = { "<Tab>", "l", "<Right>" }, -- multiple keys
      ["retry"]          = false,                    -- disable
      -- ["collapse"]    = true                      -- keep default (no-op)
    },
  },
  watches = {
    keymaps = false,  -- disable the entire view-local layer for watches
  },
})

Value grammar (identical for view-local and global):

Value Meaning
string Replace the default key for this action.
string[] Bind multiple keys to this action.
false Disable this action's default key(s); install nothing.
true Keep the default (no-op).

For REPL mode-aware bindings, pass a record:

repl = { keymaps = { submit = { mode = "i", lhs = "<C-j>" } } },

Unknown action names raise a clear error at setup() time naming both the offender and the actions the view actually registers.


Customising global keymaps

require("nvim-dapper").setup({
  keymaps = {
    global = {
      enabled  = true,
      prefix   = "<leader>x",                  -- rewrites <leader>d* defaults
      overrides = {
        continue   = "<F8>",                   -- replace default
        terminate  = false,                    -- disable
        evaluate   = { "<leader>k", { mode = "x", lhs = "<leader>k" } },
      },
    },
  },
})

prefix is a string substitution that runs over the default table before merging. It only rewrites defaults whose key starts with <leader>d; function-key defaults and any literal override keys you supply are untouched.

apply_global_keymaps is idempotent: re-calling setup() with new overrides cleanly removes the previous installation and installs the new set — safe to wire into lazy-loaders.


Building your own bindings

require("nvim-dapper.keymaps").actions() returns a frozen named table of stable debugger operation names — the documented contract you build your own keymaps against without depending on nvim-dap's API surface directly:

local actions = require("nvim-dapper.keymaps").actions()

vim.keymap.set("n", "<leader>kk", actions.continue)
vim.keymap.set("n", "<leader>kj", actions.step_into)
vim.keymap.set("n", "<leader>kl", function() actions.evaluate("foo.bar") end)
vim.keymap.set("n", "<leader>kw", function() actions.focus_view("watches") end)

Available operations: continue, step_over, step_into, step_out, toggle_breakpoint, set_conditional_breakpoint, set_logpoint, clear_breakpoint, evaluate, restart, terminate, run_to_cursor, toggle_panel, focus_view.


Rule of thumb

  • View-local maps live in the plugin's own scratch buffers — no collision risk, so they ship on by default.
  • Global maps live in your namespace — high collision risk, so the opt-in flag is the only way to get them.