Fix which-key not seeing gitsigns maps, add diagnostic maps

The gitsigns keymaps were defined in on_attach, so they were
buffer-local and created asynchronously - gitsigns shells out to git
before attaching. which-key had already built its keymap tree for the
buffer by then, and it only invalidates that cache on BufReadPost,
BufNew and LspAttach, so maps added afterwards stayed invisible.
Buf:get() returns cached mode state unless explicitly passed `update`,
which is why re-entering the buffer didn't help either.

Mapping globally instead means the maps exist before which-key builds
any tree. The gitsigns API no-ops in buffers it hasn't attached to
(checked stage/reset/preview/blame/nav in a non-git directory), so the
only change is that the maps now exist everywhere rather than just in
git-tracked buffers.

Also puts the diagnostic float and quickfix list on <leader>d. Nvim
already binds <C-W>d and ]d/[d for these, so this is a rebinding for
discoverability rather than new capability.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jonny Barnes 2026-08-08 17:27:37 +01:00
commit e8e9bf0663
No known key found for this signature in database
3 changed files with 63 additions and 54 deletions

View file

@ -16,3 +16,8 @@ vim.diagnostic.config({
}, },
}, },
}) })
-- Nvim already binds ]d / [d to jump and <C-W>d to show the diagnostic under
-- the cursor; these put the same actions on <leader> so which-key lists them.
vim.keymap.set('n', '<leader>dd', vim.diagnostic.open_float, { desc = 'Show diagnostic' })
vim.keymap.set('n', '<leader>dq', vim.diagnostic.setqflist, { desc = 'Diagnostics to quickfix' })

View file

@ -1,55 +1,58 @@
vim.pack.add({ 'https://github.com/lewis6991/gitsigns.nvim' }) vim.pack.add({ 'https://github.com/lewis6991/gitsigns.nvim' })
require('gitsigns').setup({ local gitsigns = require('gitsigns')
on_attach = function(bufnr)
local gitsigns = require('gitsigns')
local function map(mode, lhs, rhs, desc) gitsigns.setup()
vim.keymap.set(mode, lhs, rhs, { buffer = bufnr, desc = desc })
end
-- Navigation, falling back to vim's own diff motions in diff mode -- Mapped globally rather than from on_attach. Gitsigns attaches asynchronously,
map('n', ']c', function() -- after which-key has already built its keymap tree for the buffer, and
if vim.wo.diff then -- which-key only rebuilds that on BufReadPost/BufNew/LspAttach - so
vim.cmd.normal({ ']c', bang = true }) -- buffer-local maps added later never show up in its popup. The gitsigns API
else -- no-ops in buffers it hasn't attached to, so global maps are safe.
gitsigns.nav_hunk('next') local function map(mode, lhs, rhs, desc)
end vim.keymap.set(mode, lhs, rhs, { desc = desc })
end, 'Next git hunk') end
map('n', '[c', function() -- Navigation, falling back to vim's own diff motions in diff mode
if vim.wo.diff then map('n', ']c', function()
vim.cmd.normal({ '[c', bang = true }) if vim.wo.diff then
else vim.cmd.normal({ ']c', bang = true })
gitsigns.nav_hunk('prev') else
end gitsigns.nav_hunk('next')
end, 'Previous git hunk') end
end, 'Next git hunk')
-- Actions map('n', '[c', function()
map('n', '<leader>hs', gitsigns.stage_hunk, 'Stage hunk') if vim.wo.diff then
map('n', '<leader>hr', gitsigns.reset_hunk, 'Reset hunk') vim.cmd.normal({ '[c', bang = true })
else
gitsigns.nav_hunk('prev')
end
end, 'Previous git hunk')
map('v', '<leader>hs', function() -- Actions
gitsigns.stage_hunk({ vim.fn.line('.'), vim.fn.line('v') }) map('n', '<leader>hs', gitsigns.stage_hunk, 'Stage hunk')
end, 'Stage selected hunk') map('n', '<leader>hr', gitsigns.reset_hunk, 'Reset hunk')
map('v', '<leader>hr', function() map('v', '<leader>hs', function()
gitsigns.reset_hunk({ vim.fn.line('.'), vim.fn.line('v') }) gitsigns.stage_hunk({ vim.fn.line('.'), vim.fn.line('v') })
end, 'Reset selected hunk') end, 'Stage selected hunk')
map('n', '<leader>hS', gitsigns.stage_buffer, 'Stage buffer') map('v', '<leader>hr', function()
map('n', '<leader>hR', gitsigns.reset_buffer, 'Reset buffer') gitsigns.reset_hunk({ vim.fn.line('.'), vim.fn.line('v') })
map('n', '<leader>hp', gitsigns.preview_hunk, 'Preview hunk') end, 'Reset selected hunk')
map('n', '<leader>hd', gitsigns.diffthis, 'Diff against index')
map('n', '<leader>hb', function() map('n', '<leader>hS', gitsigns.stage_buffer, 'Stage buffer')
gitsigns.blame_line({ full = true }) map('n', '<leader>hR', gitsigns.reset_buffer, 'Reset buffer')
end, 'Blame line') map('n', '<leader>hp', gitsigns.preview_hunk, 'Preview hunk')
map('n', '<leader>hd', gitsigns.diffthis, 'Diff against index')
map('n', '<leader>hq', gitsigns.setqflist, 'Hunks to quickfix') map('n', '<leader>hb', function()
gitsigns.blame_line({ full = true })
end, 'Blame line')
-- Toggles map('n', '<leader>hq', gitsigns.setqflist, 'Hunks to quickfix')
map('n', '<leader>tb', gitsigns.toggle_current_line_blame, 'Toggle line blame')
map('n', '<leader>td', gitsigns.toggle_deleted, 'Toggle deleted lines') -- Toggles
end, map('n', '<leader>tb', gitsigns.toggle_current_line_blame, 'Toggle line blame')
}) map('n', '<leader>td', gitsigns.toggle_deleted, 'Toggle deleted lines')

View file

@ -4,8 +4,9 @@ local wk = require('which-key')
wk.setup() wk.setup()
-- Names for the gitsigns prefixes, so the popup groups them sensibly -- Names for the <leader> prefixes, so the popup groups them sensibly
wk.add({ wk.add({
{ '<leader>d', group = 'diagnostics' },
{ '<leader>h', group = 'hunks' }, { '<leader>h', group = 'hunks' },
{ '<leader>t', group = 'toggles' }, { '<leader>t', group = 'toggles' },
}) })