-- Non-plugin and global helper keymaps -- -- NOTE: LSP keymaps are primarily handled in lua/plugins/lsp.lua via LspAttach. -- Buffer-local keymaps set there take precedence over these global fallbacks. -- -- These global keymaps provide fallback behavior for buffers without LSP attached, -- ensuring that common navigation keys still work with built-in Vim functionality -- (e.g., ctags, included files, man pages). local map = vim.keymap.set -- Fallback navigation keymaps for non-LSP buffers -- When LSP attaches, buffer-local keymaps in lsp.lua override these map('n', 'gd', function() -- Built-in: jump to definition via tags or included files vim.cmd("normal! gd") end, { desc = 'Vim: Go to definition (built-in fallback)', silent = true }) map('n', 'gD', function() -- Built-in: jump to declaration (global) vim.cmd("normal! gD") end, { desc = 'Vim: Go to declaration (built-in fallback)', silent = true }) -- LSP-only keymaps (no useful fallback for these in non-LSP contexts) map('n', 'gr', '', { desc = 'LSP: References (requires LSP)', silent = true }) map('n', 'gI', '', { desc = 'LSP: Implementation (requires LSP)', silent = true }) -- K: Hover/Help with sensible fallback map('n', 'K', function() -- Built-in K uses 'keywordprg' (defaults to 'man' for shell scripts, etc.) -- LSP buffers override this with vim.lsp.buf.hover() in lsp.lua if vim.bo.keywordprg ~= '' then vim.cmd("normal! K") end end, { desc = 'Vim: Hover/Help (keywordprg fallback)', silent = true }) -- Diagnostic keymaps map('n', 'xx', vim.diagnostic.setloclist, { desc = 'Diagnostics: Buffer diagnostics (location list)', silent = true }) map('n', 'xX', vim.diagnostic.setqflist, { desc = 'Diagnostics: All diagnostics (quickfix)', silent = true }) map('n', 'xe', function() vim.diagnostic.setloclist({ severity = vim.diagnostic.severity.ERROR }) end, { desc = 'Diagnostics: Buffer errors (location list)', silent = true }) map('n', 'xE', function() vim.diagnostic.setqflist({ severity = vim.diagnostic.severity.ERROR }) end, { desc = 'Diagnostics: All errors (quickfix)', silent = true }) map('n', '[d', vim.diagnostic.goto_prev, { desc = 'Diagnostics: Previous diagnostic', silent = true }) map('n', ']d', vim.diagnostic.goto_next, { desc = 'Diagnostics: Next diagnostic', silent = true }) map('n', 'xd', vim.diagnostic.open_float, { desc = 'Diagnostics: Show diagnostic under cursor', silent = true }) map('n', 'xt', function() vim.diagnostic.enable(not vim.diagnostic.is_enabled()) end, { desc = 'Diagnostics: Toggle display', silent = true }) -- Debug: Show highlight group and color under cursor map('n', 'hi', function() local cursor_pos = vim.api.nvim_win_get_cursor(0) local row, col = cursor_pos[1] - 1, cursor_pos[2] -- Get all highlight groups at cursor position local ts_hl = vim.treesitter.get_captures_at_pos(0, row, col) local synID = vim.fn.synID(row + 1, col + 1, 1) local synName = vim.fn.synIDattr(synID, 'name') local synTrans = vim.fn.synIDattr(vim.fn.synIDtrans(synID), 'name') -- Helper to resolve highlight links local function resolve_hl(name) local hl = vim.api.nvim_get_hl(0, { name = name }) local max_depth = 10 local depth = 0 while hl.link and depth < max_depth do name = hl.link hl = vim.api.nvim_get_hl(0, { name = name }) depth = depth + 1 end return hl, name end local lines = { '=== Highlight Info Under Cursor ===', '', 'Position: row=' .. row .. ' col=' .. col, '', } -- TreeSitter captures if #ts_hl > 0 then table.insert(lines, 'TreeSitter Captures:') for _, capture in ipairs(ts_hl) do local cap_name = '@' .. capture.capture local hl, resolved_name = resolve_hl(cap_name) table.insert(lines, string.format(' %s', cap_name)) if resolved_name ~= cap_name then table.insert(lines, string.format(' → resolves to: %s', resolved_name)) end if hl.fg then table.insert(lines, string.format(' fg: #%06x', hl.fg)) end if hl.bg then table.insert(lines, string.format(' bg: #%06x', hl.bg)) end local styles = {} if hl.bold then table.insert(styles, 'bold') end if hl.italic then table.insert(styles, 'italic') end if hl.underline then table.insert(styles, 'underline') end if #styles > 0 then table.insert(lines, ' style: ' .. table.concat(styles, ', ')) end end table.insert(lines, '') end -- Syntax group if synName ~= '' then table.insert(lines, 'Syntax Group: ' .. synName) if synTrans ~= synName and synTrans ~= '' then table.insert(lines, 'Translates to: ' .. synTrans) end local hl, resolved_name = resolve_hl(synTrans ~= '' and synTrans or synName) if hl.fg then table.insert(lines, string.format(' fg: #%06x', hl.fg)) end if hl.bg then table.insert(lines, string.format(' bg: #%06x', hl.bg)) end table.insert(lines, '') end -- Final applied highlight (use TreeSitter if available, otherwise syntax) local final_hl_name = nil if #ts_hl > 0 then final_hl_name = '@' .. ts_hl[1].capture elseif synTrans ~= '' then final_hl_name = synTrans elseif synName ~= '' then final_hl_name = synName end if final_hl_name then local final_hl, final_resolved = resolve_hl(final_hl_name) table.insert(lines, 'Applied Highlight: ' .. final_resolved) if final_hl.fg then table.insert(lines, string.format(' fg: #%06x', final_hl.fg)) else table.insert(lines, ' fg: NONE') end if final_hl.bg then table.insert(lines, string.format(' bg: #%06x', final_hl.bg)) else table.insert(lines, ' bg: NONE') end local styles = {} if final_hl.bold then table.insert(styles, 'bold') end if final_hl.italic then table.insert(styles, 'italic') end if final_hl.underline then table.insert(styles, 'underline') end if final_hl.undercurl then table.insert(styles, 'undercurl') end if #styles > 0 then table.insert(lines, ' style: ' .. table.concat(styles, ', ')) end end -- Show in a floating window local buf = vim.api.nvim_create_buf(false, true) vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines) local width = 0 for _, line in ipairs(lines) do width = math.max(width, #line) end width = math.min(width + 2, vim.o.columns - 4) local height = #lines local opts = { relative = 'cursor', width = width, height = height, row = 1, col = 0, style = 'minimal', border = 'rounded', } vim.api.nvim_open_win(buf, false, opts) end, { desc = 'Debug: Show highlight group and color under cursor', silent = true })