From e408a538582b2c66e8cab56dc6f7171f643a42d9 Mon Sep 17 00:00:00 2001 From: Adam Poniatowski Date: Thu, 7 May 2026 17:09:35 +0200 Subject: [PATCH] massive cleanup, shaved off quite a bit on startup, now roughly 50ms --- lua/core/keymaps.lua | 539 -------------------------------- lua/core/keymaps/core.lua | 36 +++ lua/core/keymaps/diagnostic.lua | 13 + lua/core/keymaps/git.lua | 37 +++ lua/core/keymaps/init.lua | 122 ++++++++ lua/core/keymaps/lsp.lua | 70 +++++ lua/core/keymaps/plugins.lua | 120 +++++++ lua/core/keymaps/telescope.lua | 32 ++ lua/options/autocmds.lua | 48 ++- lua/options/settings.lua | 7 +- lua/plugins/better-hover.lua | 58 ---- lua/plugins/doc-test.lua | 76 ----- lua/plugins/leap.lua | 4 +- lua/plugins/lsp/setup.lua | 11 +- lua/plugins/mini-surround.lua | 2 +- lua/plugins/nvim-autopairs.lua | 2 +- lua/plugins/nvim-lspconfig.lua | 2 +- lua/plugins/session.lua | 48 +-- 18 files changed, 475 insertions(+), 752 deletions(-) delete mode 100644 lua/core/keymaps.lua create mode 100644 lua/core/keymaps/core.lua create mode 100644 lua/core/keymaps/diagnostic.lua create mode 100644 lua/core/keymaps/git.lua create mode 100644 lua/core/keymaps/init.lua create mode 100644 lua/core/keymaps/lsp.lua create mode 100644 lua/core/keymaps/plugins.lua create mode 100644 lua/core/keymaps/telescope.lua delete mode 100644 lua/plugins/better-hover.lua delete mode 100644 lua/plugins/doc-test.lua diff --git a/lua/core/keymaps.lua b/lua/core/keymaps.lua deleted file mode 100644 index 9d92904f..00000000 --- a/lua/core/keymaps.lua +++ /dev/null @@ -1,539 +0,0 @@ ----@diagnostic disable: undefined-global --- Set as the leader key --- See `:help mapleader` --- NOTE: Must happen before plugins are loaded (otherwise wrong leader will be used) -vim.g.mapleader = ' ' -vim.g.maplocalleader = ' ' - --- Core Neovim keymaps (non-plugin) --- These are basic Neovim operations like: --- - Window navigation (Ctrl + hjkl) --- - Window resizing (Ctrl + Arrow keys) --- - Line/selection movement (Alt + jk) --- - Quick save and quit (w, W, Q) -local core_keymaps = { - -- Quick access to find files by content (shortcut for sg) - { mode = 'n', lhs = '', rhs = function() require('telescope.builtin').live_grep() end, opts = { desc = 'Search text in all files' } }, - - -- Clear highlights on search when pressing in normal mode - { mode = 'n', lhs = '', rhs = 'nohlsearch', opts = { desc = 'Clear search highlights' } }, - - -- Exit terminal mode with a more discoverable shortcut - { mode = 't', lhs = '', rhs = '', opts = { desc = 'Exit terminal mode' } }, - - -- Window navigation (Ctrl + hjkl) - { mode = 'n', lhs = '', rhs = '', opts = { desc = 'Focus: Window left' } }, - { mode = 'n', lhs = '', rhs = '', opts = { desc = 'Focus: Window right' } }, - { mode = 'n', lhs = '', rhs = '', opts = { desc = 'Focus: Window down' } }, - { mode = 'n', lhs = '', rhs = '', opts = { desc = 'Focus: Window up' } }, - - -- Window resizing (Ctrl + Arrow keys) - { mode = 'n', lhs = '', rhs = 'resize +2', opts = { desc = 'Window: Increase height' } }, - { mode = 'n', lhs = '', rhs = 'resize -2', opts = { desc = 'Window: Decrease height' } }, - { mode = 'n', lhs = '', rhs = 'vertical resize -2', opts = { desc = 'Window: Decrease width' } }, - { mode = 'n', lhs = '', rhs = 'vertical resize +2', opts = { desc = 'Window: Increase width' } }, - - -- Move lines up and down (Alt + jk) - { mode = 'n', lhs = '', rhs = ':m .+1==', opts = { desc = 'Move line down', silent = true } }, - { mode = 'n', lhs = '', rhs = ':m .-2==', opts = { desc = 'Move line up', silent = true } }, - { mode = 'v', lhs = '', rhs = ":m '>+1gv=gv", opts = { desc = 'Move selection down', silent = true } }, - { mode = 'v', lhs = '', rhs = ":m '<-2gv=gv", opts = { desc = 'Move selection up', silent = true } }, - - -- Quick save and quit - { mode = 'n', lhs = 'w', rhs = 'w', opts = { desc = 'Save file' } }, - { mode = 'n', lhs = 'W', rhs = 'wa', opts = { desc = 'Save all files' } }, - { mode = 'n', lhs = 'Q', rhs = 'qa', opts = { desc = 'Quit all' } }, -} - --- LSP keymaps - these will be set up when LSP attaches to a buffer --- Navigation: --- - gd: Go to definition --- - gr: Find references --- - gI: Go to implementation --- - gy: Go to type definition --- --- Workspace: --- - ls: Document symbols --- - lS: Workspace symbols --- --- Code Actions: --- - lr: Rename symbol --- - la: Code action --- - lf: Format code --- --- Documentation: --- - K: Show documentation -local M = {} -function M.setup_lsp_keymaps(bufnr) - local keymaps = { - -- Go to definitions - { mode = 'n', lhs = 'gd', rhs = function() require('telescope.builtin').lsp_definitions() end, opts = { desc = 'LSP: Go to definition' } }, - { mode = 'n', lhs = 'gr', rhs = function() require('telescope.builtin').lsp_references() end, opts = { desc = 'LSP: Find references' } }, - { mode = 'n', lhs = 'gI', rhs = function() require('telescope.builtin').lsp_implementations() end, opts = { desc = 'LSP: Go to implementation' } }, - { mode = 'n', lhs = 'gy', rhs = function() require('telescope.builtin').lsp_type_definitions() end, opts = { desc = 'LSP: Go to type definition' } }, - - -- Symbol navigation - { mode = 'n', lhs = 'ls', rhs = function() - -- Explicitly add position_encoding to fix symbols_to_items error - require('telescope.builtin').lsp_document_symbols({ position_encoding = 'utf-16' }) - end, opts = { desc = 'LSP: Document symbols' } }, - { mode = 'n', lhs = 'lS', rhs = function() - -- Use a safe wrapper to avoid nil indexing errors - local status_ok, _ = pcall(function() - require('telescope.builtin').lsp_dynamic_workspace_symbols({ - position_encoding = 'utf-16', - show_line = true, - fname_width = 50, - symbol_width = 35, - attach_mappings = function(prompt_bufnr) - -- This prevents errors when no results are found - require("telescope.actions").select_default:replace(function() - local entry = require("telescope.actions.state").get_selected_entry() - if not entry then return end - require("telescope.actions").close(prompt_bufnr) - if entry.value and entry.value.filename then - vim.cmd(string.format('edit %s', entry.value.filename)) - vim.api.nvim_win_set_cursor(0, {entry.value.lnum, entry.value.col}) - end - end) - return true - end - }) - end) - - if not status_ok then - vim.notify("Workspace symbols not available for this language server", vim.log.levels.INFO) - end - end, opts = { desc = 'LSP: Workspace symbols' } }, - - -- Code actions - { mode = 'n', lhs = 'lr', rhs = vim.lsp.buf.rename, opts = { desc = 'LSP: Rename symbol' } }, - { mode = 'n', lhs = 'la', rhs = vim.lsp.buf.code_action, opts = { desc = 'LSP: Code action' } }, - { mode = 'n', lhs = 'lf', rhs = function() vim.lsp.buf.format({ async = true }) end, opts = { desc = 'LSP: Format code' } }, - - -- Documentation - { mode = 'n', lhs = 'K', rhs = function() require('hover').hover() end, opts = { desc = 'Enhanced documentation (hover.nvim)' } }, - } - - -- First clear any existing LSP keymaps for this buffer - local lsp_maps = { 'gd', 'gr', 'gI', 'gy', 'K', - 'ls', 'lS', 'lr', 'la', 'lf' } - for _, lhs in ipairs(lsp_maps) do - pcall(vim.keymap.del, 'n', lhs, { buffer = bufnr }) - end - - -- Then set our keymaps with buffer local - for _, mapping in ipairs(keymaps) do - vim.keymap.set(mapping.mode, mapping.lhs, mapping.rhs, vim.tbl_extend('force', mapping.opts, { - buffer = bufnr, - replace_keycodes = false, - nowait = true, - silent = true, - })) - end -end - --- Telescope keymaps (all under s for Search) --- Help: --- - sh: Search help tags --- - sk: Search keymaps --- --- Files: --- - sf: Find files --- - sr: Recent files --- --- Text Search: --- - sg: Live grep in workspace --- - sw: Search word under cursor --- - /: Fuzzy find in current buffer --- - s/: Live grep in open files --- --- Workspace: --- - sd: Search diagnostics --- - sb: Search buffers -M.telescope_keymaps = { - -- Help - { mode = 'n', lhs = 'sh', rhs = function() require('telescope.builtin').help_tags() end, opts = { desc = 'Search: Help' } }, - { mode = 'n', lhs = 'sk', rhs = function() require('telescope.builtin').keymaps() end, opts = { desc = 'Search: Keymaps' } }, - - -- Files - { mode = 'n', lhs = 'sf', rhs = function() require('telescope.builtin').find_files() end, opts = { desc = 'Search: Files' } }, - { mode = 'n', lhs = 'sr', rhs = function() require('telescope.builtin').oldfiles() end, opts = { desc = 'Search: Recent files' } }, - - -- Text - { mode = 'n', lhs = 'sg', rhs = function() require('telescope.builtin').live_grep() end, opts = { desc = 'Search: Text in workspace' } }, - { mode = 'n', lhs = 'sw', rhs = function() require('telescope.builtin').grep_string() end, opts = { desc = 'Search: Word under cursor' } }, - { mode = 'n', lhs = '/', rhs = function() - require('telescope.builtin').current_buffer_fuzzy_find(require('telescope.themes').get_dropdown { - winblend = 10, - previewer = false, - }) - end, opts = { desc = 'Search: Text in buffer' } }, - { mode = 'n', lhs = 's/', rhs = function() - require('telescope.builtin').live_grep { - grep_open_files = true, - prompt_title = 'Live Grep in Open Files', - } - end, opts = { desc = 'Search: Text in open files' } }, - - -- Workspace - { mode = 'n', lhs = 'sd', rhs = function() require('telescope.builtin').diagnostics() end, opts = { desc = 'Search: Diagnostics' } }, - { mode = 'n', lhs = 'sb', rhs = function() require('telescope.builtin').buffers() end, opts = { desc = 'Search: Buffers' } }, -} - --- Diagnostic keymaps --- Navigation: --- - [d: Previous diagnostic --- - ]d: Next diagnostic --- --- Viewing: --- - tt: Show diagnostic details in float --- - tl: Show diagnostics in location list -M.diagnostic_keymaps = { - -- Navigation - { mode = 'n', lhs = '[d', rhs = vim.diagnostic.goto_prev, opts = { desc = 'Diagnostic: Previous' } }, - { mode = 'n', lhs = ']d', rhs = vim.diagnostic.goto_next, opts = { desc = 'Diagnostic: Next' } }, - - -- Viewing diagnostics - { mode = 'n', lhs = 'tt', rhs = vim.diagnostic.open_float, opts = { desc = 'Diagnostic: Show details in float' } }, - { mode = 'n', lhs = 'tl', rhs = vim.diagnostic.setloclist, opts = { desc = 'Diagnostic: Show list' } }, - { mode = 'n', lhs = 'td', rhs = function() require('telescope.builtin').diagnostics() end, opts = { desc = 'Diagnostic: Search all diagnostics' } }, -} - --- Database keymaps (all under D for Database) --- UI: --- - Dt: Toggle database UI --- - Df: Find database buffer --- - Dr: Rename database buffer --- - Dl: Show last query info -M.dadbod_keymaps = { - { mode = 'n', lhs = 'Dt', rhs = 'DBUIToggle', opts = { desc = 'Database: Toggle UI' } }, - { mode = 'n', lhs = 'Df', rhs = 'DBUIFindBuffer', opts = { desc = 'Database: Find buffer' } }, - { mode = 'n', lhs = 'Dr', rhs = 'DBUIRenameBuffer', opts = { desc = 'Database: Rename buffer' } }, - { mode = 'n', lhs = 'Dl', rhs = 'DBUILastQueryInfo', opts = { desc = 'Database: Last query' } }, -} - --- Session management keymaps (all under m for Memory) --- Session Operations: --- - mw: Write/save current session --- - mr: Read/restore saved session --- - md: Delete saved session -M.session_keymaps = { - { mode = 'n', lhs = 'mw', rhs = function() - local name = vim.fn.fnamemodify(vim.fn.getcwd(), ':t') - require('mini.sessions').write(name, { force = true }) - end, opts = { desc = 'Memory: Write session' } }, - { mode = 'n', lhs = 'mr', rhs = function() - local name = vim.fn.fnamemodify(vim.fn.getcwd(), ':t') - require('mini.sessions').read(name) - end, opts = { desc = 'Memory: Read session' } }, - { mode = 'n', lhs = 'md', rhs = function() - local name = vim.fn.fnamemodify(vim.fn.getcwd(), ':t') - require('mini.sessions').delete(name) - end, opts = { desc = 'Memory: Delete session' } }, -} - --- Scratch buffer keymaps --- Buffer Operations: --- - .: Toggle scratch buffer --- - S: Select scratch buffer --- - nh: Show notification history -M.scratch_keymaps = { - { mode = 'n', lhs = '.', rhs = function() require("snacks").scratch() end, - opts = { desc = 'Toggle scratch buffer' } }, - { mode = 'n', lhs = 'S', rhs = function() require("snacks").scratch.select() end, - opts = { desc = 'Select scratch buffer' } }, - { mode = 'n', lhs = 'nh', rhs = function() require("snacks.notifier").show_history() end, - opts = { desc = 'Show notification history' } }, -} - --- Snacks keymaps (explorer and other features) --- File Explorer: --- - e: Toggle explorer --- - E: Focus current file in explorer --- - o: Alternative key to focus current file --- --- Terminal: --- - : Toggle terminal in float window -M.snacks_keymaps = { - -- Explorer - { mode = 'n', lhs = 'e', rhs = function() - -- Open explorer in current window - require('snacks').explorer.open() - end, opts = { desc = 'Explorer: Toggle' } }, - - { mode = 'n', lhs = 'E', rhs = function() - -- Reveal current file in explorer - require('snacks').explorer.reveal() - end, opts = { desc = 'Explorer: Focus current file' } }, - - { mode = 'n', lhs = 'o', rhs = function() - -- Open current file in a new tab and focus it - vim.cmd('tab split %') - end, opts = { desc = 'Open current file in new tab' } }, - - -- Custom function to open explorer files in new tabs - { mode = 'n', lhs = 'f', rhs = function() - -- Open explorer in a new tab - vim.cmd('tabnew') - require('snacks').explorer.open() - end, opts = { desc = 'Explorer: Open in new tab' } }, - - -- Terminal - { mode = 'n', lhs = '', rhs = function() require('snacks').terminal.toggle() end, opts = { desc = 'Terminal: Toggle float window' } }, - { mode = 'n', lhs = 'tc', rhs = function() require('snacks').terminal.toggle() end, opts = { desc = 'Terminal: Toggle console' } }, -} - --- Git signs keymaps (all under g for Git) --- Navigation: --- - ]c: Next hunk --- - [c: Previous hunk --- --- Actions: --- - gh: Preview hunk --- - gs: Stage hunk --- - gu: Undo stage hunk --- - gr: Reset hunk --- - gS: Stage buffer --- - gR: Reset buffer --- - gb: Blame line --- - gd: Diff this -M.gitsigns_keymaps = { - -- Navigation - { mode = 'n', lhs = ']c', rhs = function() - if vim.wo.diff then return ']c' end - vim.schedule(function() require('gitsigns').next_hunk() end) - return '' - end, opts = { desc = 'Git: Next hunk', expr = true } }, - - { mode = 'n', lhs = '[c', rhs = function() - if vim.wo.diff then return '[c' end - vim.schedule(function() require('gitsigns').prev_hunk() end) - return '' - end, opts = { desc = 'Git: Previous hunk', expr = true } }, - - -- Actions - { mode = 'n', lhs = 'gh', rhs = function() require('gitsigns').preview_hunk() end, opts = { desc = 'Git: Preview hunk' } }, - { mode = 'n', lhs = 'gb', rhs = function() require('gitsigns').blame_line() end, opts = { desc = 'Git: Blame line' } }, - { mode = 'n', lhs = 'gd', rhs = function() require('gitsigns').diffthis() end, opts = { desc = 'Git: Show diff' } }, - { mode = { 'n', 'v' }, lhs = 'gs', rhs = function() require('gitsigns').stage_hunk() end, opts = { desc = 'Git: Stage hunk' } }, - { mode = { 'n', 'v' }, lhs = 'gr', rhs = function() require('gitsigns').reset_hunk() end, opts = { desc = 'Git: Reset hunk' } }, - { mode = 'n', lhs = 'gS', rhs = function() require('gitsigns').stage_buffer() end, opts = { desc = 'Git: Stage buffer' } }, - { mode = 'n', lhs = 'gu', rhs = function() require('gitsigns').undo_stage_hunk() end, opts = { desc = 'Git: Undo stage' } }, - { mode = 'n', lhs = 'gR', rhs = function() require('gitsigns').reset_buffer() end, opts = { desc = 'Git: Reset buffer' } }, -} - --- Setup function for git signs keymaps -function M.setup_gitsigns_keymaps() - for _, mapping in ipairs(M.gitsigns_keymaps or {}) do - vim.keymap.set(mapping.mode, mapping.lhs, mapping.rhs, mapping.opts) - end -end - --- Elixir keymaps (using 'x' as the prefix - mnemonic for 'eXlixir') -M.elixir_keymaps = { - { mode = 'n', lhs = 'xt', - rhs = function() - require('elixir').run_test_file() - end, - opts = { desc = 'Elixir: Test file' } - }, - { mode = 'n', lhs = 'xn', - rhs = function() - require('elixir').run_nearest_test() - end, - opts = { desc = 'Elixir: Test nearest' } - }, - { mode = 'n', lhs = 'xm', - rhs = function() - vim.cmd('Telescope elixir mix') - end, - opts = { desc = 'Elixir: Mix tasks' } - }, -} - --- Set up Elixir keymaps -function M.setup_elixir_keymaps() - for _, mapping in ipairs(M.elixir_keymaps or {}) do - vim.keymap.set(mapping.mode, mapping.lhs, mapping.rhs, mapping.opts) - end -end - --- Leap keymaps --- 's' for bidirectional search (both forward and backward) --- 'S' for searching in all windows -M.leap_keymaps = { - -- 's' for bidirectional search (both forward and backward) - { mode = { 'n', 'x', 'o' }, lhs = 's', rhs = function() require('leap').leap {} end, - opts = { desc = 'Leap: Search bidirectional' } }, - - -- 'S' for searching in all windows - { mode = { 'n', 'x', 'o' }, lhs = 'S', rhs = function() - require('leap').leap { target_windows = vim.tbl_filter( - function (win) return vim.api.nvim_win_get_config(win).focusable end, - vim.api.nvim_tabpage_list_wins(0) - )} - end, opts = { desc = 'Leap: Search across windows' } }, -} - --- Setup function for leap keymaps -function M.setup_leap_keymaps() - for _, mapping in ipairs(M.leap_keymaps) do - vim.keymap.set(mapping.mode, mapping.lhs, mapping.rhs, mapping.opts) - end -end - --- Setup functions for keymaps -function M.setup_dadbod_keymaps() - local keymaps = M.dadbod_keymaps or {} - for _, mapping in ipairs(keymaps) do - vim.keymap.set(mapping.mode, mapping.lhs, mapping.rhs, mapping.opts) - end -end - -function M.setup_session_keymaps() - local keymaps = M.session_keymaps or {} - for _, mapping in ipairs(keymaps) do - vim.keymap.set(mapping.mode, mapping.lhs, mapping.rhs, mapping.opts) - end -end - --- Initialize keymaps -local function init_keymaps() - -- Create an autocmd group for our keymaps - local keymap_group = vim.api.nvim_create_augroup('custom_keymaps', { clear = true }) - - -- Handle snacks explorer during buffer writes - vim.api.nvim_create_autocmd({ 'BufWritePre' }, { - group = keymap_group, - callback = function() - -- Pause snacks explorer updates during write - pcall(function() - local picker = require('plugins.snacks.picker') - if picker.is_open() then - picker.pause_updates() - vim.schedule(function() - picker.resume_updates() - end) - end - end) - end, - }) - - -- Function to set up snacks explorer keymaps - local function setup_explorer_keymaps() - -- First remove any existing mappings - for _, key in ipairs({ 'e', 'E' }) do - pcall(vim.keymap.del, 'n', key) - pcall(vim.keymap.del, 'n', key, { buffer = true }) - end - - -- Set our mappings with high priority - for _, mapping in ipairs(M.snacks_keymaps or {}) do - if mapping.lhs == 'e' or mapping.lhs == 'E' then - vim.keymap.set(mapping.mode, mapping.lhs, mapping.rhs, vim.tbl_extend('force', mapping.opts, { - replace_keycodes = false, - nowait = true, - silent = true, - })) - end - end - end - - -- Set up autocmds to maintain our keymaps - vim.api.nvim_create_autocmd({ 'VimEnter', 'BufEnter' }, { - group = keymap_group, - callback = setup_explorer_keymaps, - }) - - -- Set up LSP keymaps on attach - vim.api.nvim_create_autocmd('LspAttach', { - group = keymap_group, - callback = function(args) - M.setup_lsp_keymaps(args.buf) - end, - }) - - -- Set up core keymaps - for _, mapping in ipairs(core_keymaps) do - vim.keymap.set(mapping.mode, mapping.lhs, mapping.rhs, mapping.opts) - end - - -- Set up plugin keymaps - for _, mapping in ipairs(M.telescope_keymaps or {}) do - vim.keymap.set(mapping.mode, mapping.lhs, mapping.rhs, mapping.opts) - end - - for _, mapping in ipairs(M.diagnostic_keymaps or {}) do - vim.keymap.set(mapping.mode, mapping.lhs, mapping.rhs, mapping.opts) - end - - for _, mapping in ipairs(M.buffer_keymaps or {}) do - vim.keymap.set(mapping.mode, mapping.lhs, mapping.rhs, mapping.opts) - end - - -- Set up snacks keymaps - for _, mapping in ipairs(M.snacks_keymaps or {}) do - -- Skip explorer keymaps as they're handled by setup_explorer_keymaps - if mapping.lhs ~= 'e' and mapping.lhs ~= 'E' then - vim.keymap.set(mapping.mode, mapping.lhs, mapping.rhs, mapping.opts) - end - end - - -- Set up scratch buffer keymaps - for _, mapping in ipairs(M.scratch_keymaps or {}) do - vim.keymap.set(mapping.mode, mapping.lhs, mapping.rhs, mapping.opts) - end - - -- Set up database keymaps - M.setup_dadbod_keymaps() - - -- Set up default tab navigation - vim.keymap.set('n', 'gt', ':tabnext', { silent = true, desc = 'Next tab' }) - vim.keymap.set('n', 'gT', ':tabprevious', { silent = true, desc = 'Previous tab' }) - - -- Set up session keymaps - M.setup_session_keymaps() - - -- Set up git signs keymaps - M.setup_gitsigns_keymaps() - - -- Set up Elixir keymaps - M.setup_elixir_keymaps() - - -- Set up leap keymaps - M.setup_leap_keymaps() -end - --- Initialize all keymaps -init_keymaps() - --- Export `init_keymaps` as `M.setup` so `require('core.keymaps').setup()` works -M.setup = init_keymaps - --- Mini-surround keymaps --- These define how mini.surround plugin works with text objects --- sa - add surroundings (visual mode or with motion like saiw) --- sd - delete surroundings --- sr - replace surroundings --- sn - Find next surrounding --- sN - Find previous surrounding --- sh - Highlight surrounding --- sf - Find surrounding (to use with textobject) --- ss - Go to left surrounding --- sS - Go to right surrounding -M.mini_surround_keymaps = { - add = 'sa', -- Add surrounding in Normal and Visual modes - delete = 'sd', -- Delete surrounding - find = 'sf', -- Find surrounding (to the right) - find_left = 'sF', -- Find surrounding (to the left) - highlight = 'sh', -- Highlight surrounding - replace = 'sr', -- Replace surrounding - update_n_lines = '', -- Update `n_lines` - - suffix_last = 'l', -- Suffix to search with 'prev' method - suffix_next = 'n', -- Suffix to search with 'next' method -} - --- Return the module -return M diff --git a/lua/core/keymaps/core.lua b/lua/core/keymaps/core.lua new file mode 100644 index 00000000..643fc8d0 --- /dev/null +++ b/lua/core/keymaps/core.lua @@ -0,0 +1,36 @@ +---@diagnostic disable: undefined-global +-- Core Neovim keymaps (non-plugin) + +return { + -- Quick access to find files by content + { mode = 'n', lhs = '', rhs = function() require('telescope.builtin').live_grep() end, opts = { desc = 'Search text in all files' } }, + + -- Clear highlights on search + { mode = 'n', lhs = '', rhs = 'nohlsearch', opts = { desc = 'Clear search highlights' } }, + + -- Exit terminal mode + { mode = 't', lhs = '', rhs = '', opts = { desc = 'Exit terminal mode' } }, + + -- Window navigation (Ctrl + hjkl) + { mode = 'n', lhs = '', rhs = '', opts = { desc = 'Focus: Window left' } }, + { mode = 'n', lhs = '', rhs = '', opts = { desc = 'Focus: Window right' } }, + { mode = 'n', lhs = '', rhs = '', opts = { desc = 'Focus: Window down' } }, + { mode = 'n', lhs = '', rhs = '', opts = { desc = 'Focus: Window up' } }, + + -- Window resizing (Ctrl + Arrow keys) + { mode = 'n', lhs = '', rhs = 'resize +2', opts = { desc = 'Window: Increase height' } }, + { mode = 'n', lhs = '', rhs = 'resize -2', opts = { desc = 'Window: Decrease height' } }, + { mode = 'n', lhs = '', rhs = 'vertical resize -2', opts = { desc = 'Window: Decrease width' } }, + { mode = 'n', lhs = '', rhs = 'vertical resize +2', opts = { desc = 'Window: Increase width' } }, + + -- Move lines up and down (Alt + jk) + { mode = 'n', lhs = '', rhs = ':m .+1==', opts = { desc = 'Move line down', silent = true } }, + { mode = 'n', lhs = '', rhs = ':m .-2==', opts = { desc = 'Move line up', silent = true } }, + { mode = 'v', lhs = '', rhs = ":m '>+1gv=gv", opts = { desc = 'Move selection down', silent = true } }, + { mode = 'v', lhs = '', rhs = ":m '<-2gv=gv", opts = { desc = 'Move selection up', silent = true } }, + + -- Quick save and quit + { mode = 'n', lhs = 'w', rhs = 'w', opts = { desc = 'Save file' } }, + { mode = 'n', lhs = 'W', rhs = 'wa', opts = { desc = 'Save all files' } }, + { mode = 'n', lhs = 'Q', rhs = 'qa', opts = { desc = 'Quit all' } }, +} diff --git a/lua/core/keymaps/diagnostic.lua b/lua/core/keymaps/diagnostic.lua new file mode 100644 index 00000000..c561cd23 --- /dev/null +++ b/lua/core/keymaps/diagnostic.lua @@ -0,0 +1,13 @@ +---@diagnostic disable: undefined-global +-- Diagnostic keymaps + +return { + -- Navigation + { mode = 'n', lhs = '[d', rhs = vim.diagnostic.goto_prev, opts = { desc = 'Diagnostic: Previous' } }, + { mode = 'n', lhs = ']d', rhs = vim.diagnostic.goto_next, opts = { desc = 'Diagnostic: Next' } }, + + -- Viewing diagnostics + { mode = 'n', lhs = 'tt', rhs = vim.diagnostic.open_float, opts = { desc = 'Diagnostic: Show details in float' } }, + { mode = 'n', lhs = 'tl', rhs = vim.diagnostic.setloclist, opts = { desc = 'Diagnostic: Show list' } }, + { mode = 'n', lhs = 'td', rhs = function() require('telescope.builtin').diagnostics() end, opts = { desc = 'Diagnostic: Search all diagnostics' } }, +} diff --git a/lua/core/keymaps/git.lua b/lua/core/keymaps/git.lua new file mode 100644 index 00000000..a269fa12 --- /dev/null +++ b/lua/core/keymaps/git.lua @@ -0,0 +1,37 @@ +---@diagnostic disable: undefined-global +-- Git keymaps + +local M = {} + +M.keymaps = { + -- Navigation + { mode = 'n', lhs = ']c', rhs = function() + if vim.wo.diff then return ']c' end + vim.schedule(function() require('gitsigns').next_hunk() end) + return '' + end, opts = { desc = 'Git: Next hunk', expr = true } }, + + { mode = 'n', lhs = '[c', rhs = function() + if vim.wo.diff then return '[c' end + vim.schedule(function() require('gitsigns').prev_hunk() end) + return '' + end, opts = { desc = 'Git: Previous hunk', expr = true } }, + + -- Actions + { mode = 'n', lhs = 'gh', rhs = function() require('gitsigns').preview_hunk() end, opts = { desc = 'Git: Preview hunk' } }, + { mode = 'n', lhs = 'gb', rhs = function() require('gitsigns').blame_line() end, opts = { desc = 'Git: Blame line' } }, + { mode = 'n', lhs = 'gd', rhs = function() require('gitsigns').diffthis() end, opts = { desc = 'Git: Show diff' } }, + { mode = { 'n', 'v' }, lhs = 'gs', rhs = function() require('gitsigns').stage_hunk() end, opts = { desc = 'Git: Stage hunk' } }, + { mode = { 'n', 'v' }, lhs = 'gr', rhs = function() require('gitsigns').reset_hunk() end, opts = { desc = 'Git: Reset hunk' } }, + { mode = 'n', lhs = 'gS', rhs = function() require('gitsigns').stage_buffer() end, opts = { desc = 'Git: Stage buffer' } }, + { mode = 'n', lhs = 'gu', rhs = function() require('gitsigns').undo_stage_hunk() end, opts = { desc = 'Git: Undo stage' } }, + { mode = 'n', lhs = 'gR', rhs = function() require('gitsigns').reset_buffer() end, opts = { desc = 'Git: Reset buffer' } }, +} + +function M.setup() + for _, mapping in ipairs(M.keymaps) do + vim.keymap.set(mapping.mode, mapping.lhs, mapping.rhs, mapping.opts) + end +end + +return M diff --git a/lua/core/keymaps/init.lua b/lua/core/keymaps/init.lua new file mode 100644 index 00000000..06a117fd --- /dev/null +++ b/lua/core/keymaps/init.lua @@ -0,0 +1,122 @@ +---@diagnostic disable: undefined-global +-- Keymaps init - loads all keymap modules + +vim.g.mapleader = ' ' +vim.g.maplocalleader = ' ' + +local M = {} + +-- Import keymap modules +local core = require('core.keymaps.core') +local lsp = require('core.keymaps.lsp') +local telescope = require('core.keymaps.telescope') +local diagnostic = require('core.keymaps.diagnostic') +local git = require('core.keymaps.git') +local plugins = require('core.keymaps.plugins') + +-- Export for external use +M.setup_lsp_keymaps = lsp.setup +M.telescope_keymaps = telescope +M.diagnostic_keymaps = diagnostic +M.gitsigns_keymaps = git.keymaps +M.dadbod_keymaps = plugins.dadbod +M.session_keymaps = plugins.session +M.scratch_keymaps = plugins.scratch +M.snacks_keymaps = plugins.snacks +M.leap_keymaps = plugins.leap +M.elixir_keymaps = plugins.elixir +M.mini_surround_keymaps = plugins.mini_surround + +-- Setup functions +M.setup_gitsigns_keymaps = git.setup +M.setup_dadbod_keymaps = plugins.setup_dadbod +M.setup_session_keymaps = plugins.setup_session +M.setup_elixir_keymaps = plugins.setup_elixir +M.setup_leap_keymaps = plugins.setup_leap + +-- Default on_attach for LSP (used by lsp/setup.lua) +M.default_on_attach = nil + +local explorer_keymaps_set = false +local function setup_explorer_keymaps() + if explorer_keymaps_set then return end + explorer_keymaps_set = true + + for _, key in ipairs({ 'e', 'E' }) do + pcall(vim.keymap.del, 'n', key) + end + + for _, mapping in ipairs(plugins.snacks) do + if mapping.lhs == 'e' or mapping.lhs == 'E' then + vim.keymap.set(mapping.mode, mapping.lhs, mapping.rhs, vim.tbl_extend('force', mapping.opts, { + replace_keycodes = false, + nowait = true, + silent = true, + })) + end + end +end + +local function init_keymaps() + local keymap_group = vim.api.nvim_create_augroup('custom_keymaps', { clear = true }) + + -- Handle snacks explorer during buffer writes + vim.api.nvim_create_autocmd({ 'BufWritePre' }, { + group = keymap_group, + callback = function() + pcall(function() + local picker = require('plugins.snacks.picker') + if picker.is_open() then + picker.pause_updates() + vim.schedule(function() picker.resume_updates() end) + end + end) + end, + }) + + -- Set up autocmds to maintain explorer keymaps + vim.api.nvim_create_autocmd({ 'VimEnter', 'BufEnter' }, { + group = keymap_group, + callback = setup_explorer_keymaps, + }) + + -- Set up LSP keymaps on attach + vim.api.nvim_create_autocmd('LspAttach', { + group = keymap_group, + callback = function(args) M.setup_lsp_keymaps(args.buf) end, + }) + + -- Core keymaps + for _, mapping in ipairs(core) do + vim.keymap.set(mapping.mode, mapping.lhs, mapping.rhs, mapping.opts) + end + + -- Telescope keymaps + for _, mapping in ipairs(telescope) do + vim.keymap.set(mapping.mode, mapping.lhs, mapping.rhs, mapping.opts) + end + + -- Diagnostic keymaps + for _, mapping in ipairs(diagnostic) do + vim.keymap.set(mapping.mode, mapping.lhs, mapping.rhs, mapping.opts) + end + + -- Plugin keymaps + plugins.setup_snacks() + plugins.setup_scratch() + plugins.setup_dadbod() + plugins.setup_session() + plugins.setup_leap() + plugins.setup_elixir() + git.setup() + + -- Tab navigation + vim.keymap.set('n', 'gt', ':tabnext', { silent = true, desc = 'Next tab' }) + vim.keymap.set('n', 'gT', ':tabprevious', { silent = true, desc = 'Previous tab' }) +end + +init_keymaps() + +M.setup = init_keymaps + +return M diff --git a/lua/core/keymaps/lsp.lua b/lua/core/keymaps/lsp.lua new file mode 100644 index 00000000..76e0af31 --- /dev/null +++ b/lua/core/keymaps/lsp.lua @@ -0,0 +1,70 @@ +---@diagnostic disable: undefined-global +-- LSP keymaps + +local M = {} + +function M.setup(bufnr) + local keymaps = { + -- Go to definitions + { mode = 'n', lhs = 'gd', rhs = function() require('telescope.builtin').lsp_definitions() end, opts = { desc = 'LSP: Go to definition' } }, + { mode = 'n', lhs = 'gr', rhs = function() require('telescope.builtin').lsp_references() end, opts = { desc = 'LSP: Find references' } }, + { mode = 'n', lhs = 'gI', rhs = function() require('telescope.builtin').lsp_implementations() end, opts = { desc = 'LSP: Go to implementation' } }, + { mode = 'n', lhs = 'gy', rhs = function() require('telescope.builtin').lsp_type_definitions() end, opts = { desc = 'LSP: Go to type definition' } }, + + -- Symbol navigation + { mode = 'n', lhs = 'ls', rhs = function() + require('telescope.builtin').lsp_document_symbols({ position_encoding = 'utf-16' }) + end, opts = { desc = 'LSP: Document symbols' } }, + { mode = 'n', lhs = 'lS', rhs = function() + local status_ok, _ = pcall(function() + require('telescope.builtin').lsp_dynamic_workspace_symbols({ + position_encoding = 'utf-16', + show_line = true, + fname_width = 50, + symbol_width = 35, + attach_mappings = function(prompt_bufnr) + require("telescope.actions").select_default:replace(function() + local entry = require("telescope.actions.state").get_selected_entry() + if not entry then return end + require("telescope.actions").close(prompt_bufnr) + if entry.value and entry.value.filename then + vim.cmd(string.format('edit %s', entry.value.filename)) + vim.api.nvim_win_set_cursor(0, {entry.value.lnum, entry.value.col}) + end + end) + return true + end + }) + end) + if not status_ok then + vim.notify("Workspace symbols not available for this language server", vim.log.levels.INFO) + end + end, opts = { desc = 'LSP: Workspace symbols' } }, + + -- Code actions + { mode = 'n', lhs = 'lr', rhs = vim.lsp.buf.rename, opts = { desc = 'LSP: Rename symbol' } }, + { mode = 'n', lhs = 'la', rhs = vim.lsp.buf.code_action, opts = { desc = 'LSP: Code action' } }, + { mode = 'n', lhs = 'lf', rhs = function() vim.lsp.buf.format({ async = true }) end, opts = { desc = 'LSP: Format code' } }, + + -- Documentation + { mode = 'n', lhs = 'K', rhs = function() require('hover').hover() end, opts = { desc = 'Enhanced documentation (hover.nvim)' } }, + } + + -- Clear existing LSP keymaps for this buffer + local lsp_maps = { 'gd', 'gr', 'gI', 'gy', 'K', 'ls', 'lS', 'lr', 'la', 'lf' } + for _, lhs in ipairs(lsp_maps) do + pcall(vim.keymap.del, 'n', lhs, { buffer = bufnr }) + end + + -- Set keymaps with buffer local + for _, mapping in ipairs(keymaps) do + vim.keymap.set(mapping.mode, mapping.lhs, mapping.rhs, vim.tbl_extend('force', mapping.opts, { + buffer = bufnr, + replace_keycodes = false, + nowait = true, + silent = true, + })) + end +end + +return M diff --git a/lua/core/keymaps/plugins.lua b/lua/core/keymaps/plugins.lua new file mode 100644 index 00000000..800c2db4 --- /dev/null +++ b/lua/core/keymaps/plugins.lua @@ -0,0 +1,120 @@ +---@diagnostic disable: undefined-global +-- Plugin keymaps (dadbod, session, scratch, snacks, leap, elixir, mini-surround) + +local M = {} + +-- Database keymaps +M.dadbod = { + { mode = 'n', lhs = 'Dt', rhs = 'DBUIToggle', opts = { desc = 'Database: Toggle UI' } }, + { mode = 'n', lhs = 'Df', rhs = 'DBUIFindBuffer', opts = { desc = 'Database: Find buffer' } }, + { mode = 'n', lhs = 'Dr', rhs = 'DBUIRenameBuffer', opts = { desc = 'Database: Rename buffer' } }, + { mode = 'n', lhs = 'Dl', rhs = 'DBUILastQueryInfo', opts = { desc = 'Database: Last query' } }, +} + +-- Session keymaps +M.session = { + { mode = 'n', lhs = 'mw', rhs = function() + local name = vim.fn.fnamemodify(vim.fn.getcwd(), ':t') + require('mini.sessions').write(name, { force = true }) + end, opts = { desc = 'Memory: Write session' } }, + { mode = 'n', lhs = 'mr', rhs = function() + local name = vim.fn.fnamemodify(vim.fn.getcwd(), ':t') + require('mini.sessions').read(name) + end, opts = { desc = 'Memory: Read session' } }, + { mode = 'n', lhs = 'md', rhs = function() + local name = vim.fn.fnamemodify(vim.fn.getcwd(), ':t') + require('mini.sessions').delete(name) + end, opts = { desc = 'Memory: Delete session' } }, +} + +-- Scratch buffer keymaps +M.scratch = { + { mode = 'n', lhs = '.', rhs = function() require("snacks").scratch() end, opts = { desc = 'Toggle scratch buffer' } }, + { mode = 'n', lhs = 'S', rhs = function() require("snacks").scratch.select() end, opts = { desc = 'Select scratch buffer' } }, + { mode = 'n', lhs = 'nh', rhs = function() require("snacks.notifier").show_history() end, opts = { desc = 'Show notification history' } }, +} + +-- Snacks keymaps (explorer and terminal) +M.snacks = { + { mode = 'n', lhs = 'e', rhs = function() require('snacks').explorer.open() end, opts = { desc = 'Explorer: Toggle' } }, + { mode = 'n', lhs = 'E', rhs = function() require('snacks').explorer.reveal() end, opts = { desc = 'Explorer: Focus current file' } }, + { mode = 'n', lhs = 'o', rhs = function() vim.cmd('tab split %') end, opts = { desc = 'Open current file in new tab' } }, + { mode = 'n', lhs = 'f', rhs = function() + vim.cmd('tabnew') + require('snacks').explorer.open() + end, opts = { desc = 'Explorer: Open in new tab' } }, + { mode = 'n', lhs = '', rhs = function() require('snacks').terminal.toggle() end, opts = { desc = 'Terminal: Toggle float window' } }, + { mode = 'n', lhs = 'tc', rhs = function() require('snacks').terminal.toggle() end, opts = { desc = 'Terminal: Toggle console' } }, +} + +-- Leap keymaps +M.leap = { + { mode = { 'n', 'x', 'o' }, lhs = 's', rhs = function() require('leap').leap {} end, opts = { desc = 'Leap: Search bidirectional' } }, + { mode = { 'n', 'x', 'o' }, lhs = 'S', rhs = function() + require('leap').leap { target_windows = vim.tbl_filter( + function (win) return vim.api.nvim_win_get_config(win).focusable end, + vim.api.nvim_tabpage_list_wins(0) + )} + end, opts = { desc = 'Leap: Search across windows' } }, +} + +-- Elixir keymaps +M.elixir = { + { mode = 'n', lhs = 'xt', rhs = function() require('elixir').run_test_file() end, opts = { desc = 'Elixir: Test file' } }, + { mode = 'n', lhs = 'xn', rhs = function() require('elixir').run_nearest_test() end, opts = { desc = 'Elixir: Test nearest' } }, + { mode = 'n', lhs = 'xm', rhs = function() vim.cmd('Telescope elixir mix') end, opts = { desc = 'Elixir: Mix tasks' } }, +} + +-- Mini-surround keymaps (used by mini.surround config) +M.mini_surround = { + add = 'sa', + delete = 'sd', + find = 'sf', + find_left = 'sF', + highlight = 'sh', + replace = 'sr', + update_n_lines = '', + suffix_last = 'l', + suffix_next = 'n', +} + +-- Setup functions +function M.setup_dadbod() + for _, mapping in ipairs(M.dadbod) do + vim.keymap.set(mapping.mode, mapping.lhs, mapping.rhs, mapping.opts) + end +end + +function M.setup_session() + for _, mapping in ipairs(M.session) do + vim.keymap.set(mapping.mode, mapping.lhs, mapping.rhs, mapping.opts) + end +end + +function M.setup_scratch() + for _, mapping in ipairs(M.scratch) do + vim.keymap.set(mapping.mode, mapping.lhs, mapping.rhs, mapping.opts) + end +end + +function M.setup_snacks() + for _, mapping in ipairs(M.snacks) do + if mapping.lhs ~= 'e' and mapping.lhs ~= 'E' then + vim.keymap.set(mapping.mode, mapping.lhs, mapping.rhs, mapping.opts) + end + end +end + +function M.setup_leap() + for _, mapping in ipairs(M.leap) do + vim.keymap.set(mapping.mode, mapping.lhs, mapping.rhs, mapping.opts) + end +end + +function M.setup_elixir() + for _, mapping in ipairs(M.elixir) do + vim.keymap.set(mapping.mode, mapping.lhs, mapping.rhs, mapping.opts) + end +end + +return M diff --git a/lua/core/keymaps/telescope.lua b/lua/core/keymaps/telescope.lua new file mode 100644 index 00000000..4ee6f44f --- /dev/null +++ b/lua/core/keymaps/telescope.lua @@ -0,0 +1,32 @@ +---@diagnostic disable: undefined-global +-- Telescope keymaps + +return { + -- Help + { mode = 'n', lhs = 'sh', rhs = function() require('telescope.builtin').help_tags() end, opts = { desc = 'Search: Help' } }, + { mode = 'n', lhs = 'sk', rhs = function() require('telescope.builtin').keymaps() end, opts = { desc = 'Search: Keymaps' } }, + + -- Files + { mode = 'n', lhs = 'sf', rhs = function() require('telescope.builtin').find_files() end, opts = { desc = 'Search: Files' } }, + { mode = 'n', lhs = 'sr', rhs = function() require('telescope.builtin').oldfiles() end, opts = { desc = 'Search: Recent files' } }, + + -- Text + { mode = 'n', lhs = 'sg', rhs = function() require('telescope.builtin').live_grep() end, opts = { desc = 'Search: Text in workspace' } }, + { mode = 'n', lhs = 'sw', rhs = function() require('telescope.builtin').grep_string() end, opts = { desc = 'Search: Word under cursor' } }, + { mode = 'n', lhs = '/', rhs = function() + require('telescope.builtin').current_buffer_fuzzy_find(require('telescope.themes').get_dropdown { + winblend = 10, + previewer = false, + }) + end, opts = { desc = 'Search: Text in buffer' } }, + { mode = 'n', lhs = 's/', rhs = function() + require('telescope.builtin').live_grep { + grep_open_files = true, + prompt_title = 'Live Grep in Open Files', + } + end, opts = { desc = 'Search: Text in open files' } }, + + -- Workspace + { mode = 'n', lhs = 'sd', rhs = function() require('telescope.builtin').diagnostics() end, opts = { desc = 'Search: Diagnostics' } }, + { mode = 'n', lhs = 'sb', rhs = function() require('telescope.builtin').buffers() end, opts = { desc = 'Search: Buffers' } }, +} diff --git a/lua/options/autocmds.lua b/lua/options/autocmds.lua index ebe0c0ca..c641ff30 100644 --- a/lua/options/autocmds.lua +++ b/lua/options/autocmds.lua @@ -12,41 +12,31 @@ function M.setup() }) - -- Add a smart format-on-save command that only uses null-ls - -- Fix for zig.vim ftplugin error - handles both JSON and struct output + -- Fix for zig.vim ftplugin error - cache zig env result vim.api.nvim_create_autocmd('FileType', { pattern = 'zig', group = vim.api.nvim_create_augroup('user-zig-fix', { clear = true }), callback = function() if vim.fn.executable('zig') ~= 1 or vim.g.zig_std_dir then return end - - -- First try with --json flag - local handle = io.popen('zig env --json 2>/dev/null') - if handle then - local result = handle:read('*a') - handle:close() - - -- Try to parse as JSON first - local success, env = pcall(vim.fn.json_decode, result) - if success and type(env) == 'table' and env.std_dir then - vim.g.zig_std_dir = env.std_dir - vim.opt_local.path:prepend(env.std_dir) - return - end + + -- Single popen call - try JSON first (newer zig), fallback to struct parsing + local handle = io.popen('zig env 2>/dev/null') + if not handle then return end + + local result = handle:read('*a') + handle:close() + + -- Try JSON parse first + local success, env = pcall(vim.fn.json_decode, result) + if success and type(env) == 'table' and env.std_dir then + vim.g.zig_std_dir = env.std_dir + else + -- Fallback: extract from struct output + vim.g.zig_std_dir = result:match('%.std_dir%s*=%s*"([^"]+)"') end - - -- If JSON parsing failed, try to parse the struct output - handle = io.popen('zig env 2>/dev/null') - if handle then - local result = handle:read('*a') - handle:close() - - -- Extract std_dir from struct output - local std_dir = result:match('%.std_dir%s*=%s*"([^"]+)"') - if std_dir then - vim.g.zig_std_dir = std_dir - vim.opt_local.path:prepend(std_dir) - end + + if vim.g.zig_std_dir then + vim.opt_local.path:prepend(vim.g.zig_std_dir) end end, }) diff --git a/lua/options/settings.lua b/lua/options/settings.lua index 0faa11df..270e4515 100644 --- a/lua/options/settings.lua +++ b/lua/options/settings.lua @@ -6,7 +6,7 @@ ---@diagnostic disable: undefined-global -- Make line numbers default vim.opt.number = true -vim.o.relativenumber = true +vim.opt.relativenumber = true -- You can also add relative line numbers, to help with jumping. -- Experiment for yourself to see if you like it! -- vim.opt.relativenumber = true @@ -99,10 +99,6 @@ vim.diagnostic.config({ local M = {} function M.setup() - -- Leader keys - vim.g.mapleader = ' ' - vim.g.maplocalleader = ' ' - -- Ensure swapfile directory exists and configure swapfile settings local swap_dir = vim.fn.stdpath('data') .. '/swapfiles' if vim.fn.isdirectory(swap_dir) == 0 then @@ -110,7 +106,6 @@ function M.setup() end vim.opt.directory = swap_dir vim.opt.swapfile = true - vim.opt.updatetime = 300 vim.opt.updatecount = 100 end diff --git a/lua/plugins/better-hover.lua b/lua/plugins/better-hover.lua deleted file mode 100644 index d79004b6..00000000 --- a/lua/plugins/better-hover.lua +++ /dev/null @@ -1,58 +0,0 @@ ----@diagnostic disable: undefined-global --- Direct approach to fix hover documentation with custom function -return { - "neovim/nvim-lspconfig", - config = function() - -- Create a direct standalone hover function - local function better_hover() - -- Save original functions we'll temporarily override - local orig_open_floating = vim.lsp.util.open_floating_preview - - -- Replace the floating preview function temporarily - vim.lsp.util.open_floating_preview = function(contents, syntax, opts) - opts = opts or {} - -- Force nicer styling - opts.border = "rounded" - opts.max_width = math.min(math.floor(vim.o.columns * 0.7), 80) - opts.max_height = math.floor(vim.o.lines * 0.3) - - -- Process contents to remove separator lines and improve formatting - local cleaned_contents = {} - for _, line in ipairs(contents) do - -- Skip separator lines - if not line:match("^%-%-%-%-+$") then - table.insert(cleaned_contents, line) - end - end - - -- Call original with improved options and cleaned content - local bufnr, winnr = orig_open_floating(cleaned_contents, syntax, opts) - - -- Enhance the created buffer - if bufnr and winnr then - -- Set better options for the window - vim.api.nvim_win_set_option(winnr, "conceallevel", 2) - vim.api.nvim_win_set_option(winnr, "foldenable", false) - - -- If it's markdown, ensure proper highlighting - if syntax == "markdown" then - vim.api.nvim_buf_set_option(bufnr, "filetype", "markdown") - end - end - - return bufnr, winnr - end - - -- Call the regular hover function with our temporary override - vim.lsp.buf.hover() - - -- Restore original function - vim.lsp.util.open_floating_preview = orig_open_floating - end - - -- Directly override the K keymap - this bypasses any conflicts - vim.keymap.set("n", "K", better_hover, { noremap = true, silent = true, desc = "LSP: Better hover docs" }) - end, - -- Run this after all other LSP configs are loaded - priority = 999, -} diff --git a/lua/plugins/doc-test.lua b/lua/plugins/doc-test.lua deleted file mode 100644 index 596b4715..00000000 --- a/lua/plugins/doc-test.lua +++ /dev/null @@ -1,76 +0,0 @@ ----@diagnostic disable: undefined-global --- Test doc window plugin -return { - "neovim/nvim-lspconfig", - config = function() - -- Create a test function that shows a styled floating window - local function test_doc_window() - local contents = { - "## Documentation Test", - "", - "This is a test documentation window to see how styling works.", - "", - "**Important**: This shows what documentation *should* look like.", - "", - "```lua", - "function example(param)", - " -- This is a code sample", - " return param + 1", - "end", - "```", - } - - -- Create a nicely styled window - local opts = { - border = "rounded", - width = 60, - height = 12, - wrap = true, - pad_left = 1, - pad_right = 1, - } - - local bufnr = vim.api.nvim_create_buf(false, true) - vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, contents) - vim.api.nvim_buf_set_option(bufnr, "filetype", "markdown") - - -- Position the window near the cursor - local cursor_pos = vim.api.nvim_win_get_cursor(0) - local row = cursor_pos[1] - local col = cursor_pos[2] - - -- Calculate position - local ui = vim.api.nvim_list_uis()[1] - local width = opts.width or 60 - local height = opts.height or 12 - local anchor = "NW" - local col_offset = 0 - - -- Open the window - local winnr = vim.api.nvim_open_win(bufnr, false, { - relative = "cursor", - row = 1, - col = col_offset, - width = width, - height = height, - style = "minimal", - border = opts.border, - anchor = anchor, - }) - - -- Set window options - vim.api.nvim_win_set_option(winnr, "conceallevel", 2) - vim.api.nvim_win_set_option(winnr, "concealcursor", "n") - vim.api.nvim_win_set_option(winnr, "winblend", 0) - - -- Return window and buffer numbers - return bufnr, winnr - end - - -- Add a command to test the documentation window - vim.api.nvim_create_user_command("TestDocWindow", test_doc_window, {}) - - -- Also map it to a key for easy testing - vim.keymap.set("n", "td", test_doc_window, { desc = "Test doc window styling" }) - end -} diff --git a/lua/plugins/leap.lua b/lua/plugins/leap.lua index ec0a15d9..f61c9bf2 100644 --- a/lua/plugins/leap.lua +++ b/lua/plugins/leap.lua @@ -1,7 +1,7 @@ ---@diagnostic disable: undefined-global -- Quick navigation plugin return { - 'ggandor/leap.nvim', + url = "https://codeberg.org/andyg/leap.nvim", dependencies = { 'tpope/vim-repeat', -- For dot-repeat support }, @@ -20,7 +20,7 @@ return { -- Set highlight colors for better visibility vim.api.nvim_set_hl(0, 'LeapMatch', { fg = '#89B4FA', bold = true, nocombine = true }) - vim.api.nvim_set_hl(0, 'LeapLabelPrimary', { fg = '#F38BA8', bold = true, nocombine = true }) + vim.api.nvim_set_hl(0, 'LeapLabelPrimary', { fg = '#cfa369', bold = true, nocombine = true }) vim.api.nvim_set_hl(0, 'LeapLabelSecondary', { fg = '#94E2D5', bold = true, nocombine = true }) end, } diff --git a/lua/plugins/lsp/setup.lua b/lua/plugins/lsp/setup.lua index 4ea1960e..c5014867 100644 --- a/lua/plugins/lsp/setup.lua +++ b/lua/plugins/lsp/setup.lua @@ -50,12 +50,12 @@ function M.setup() } capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities) - -- Setup mason-lspconfig + -- Setup mason-lspconfig with handlers local mason_lspconfig = require('mason-lspconfig') - mason_lspconfig.setup { ensure_installed = vim.tbl_keys(servers) } - - mason_lspconfig.setup_handlers { - function(server_name) + mason_lspconfig.setup { + ensure_installed = vim.tbl_keys(servers), + handlers = { + function(server_name) local config = servers[server_name] or {} config.capabilities = capabilities @@ -134,6 +134,7 @@ function M.setup() require('lspconfig')[server_name].setup(config) end, + }, } -- Hover handler will now be provided by Blink diff --git a/lua/plugins/mini-surround.lua b/lua/plugins/mini-surround.lua index 0050bc37..26ea8741 100644 --- a/lua/plugins/mini-surround.lua +++ b/lua/plugins/mini-surround.lua @@ -1,7 +1,7 @@ return { 'echasnovski/mini.surround', version = '*', - event = "VeryLazy", + event = 'VeryLazy', config = function() require('mini.surround').setup({ -- Use mappings from centralized keymaps diff --git a/lua/plugins/nvim-autopairs.lua b/lua/plugins/nvim-autopairs.lua index aa6ea965..dd9fdbb8 100644 --- a/lua/plugins/nvim-autopairs.lua +++ b/lua/plugins/nvim-autopairs.lua @@ -1,6 +1,6 @@ return { 'windwp/nvim-autopairs', - event = "InsertEnter", -- Only load in insert mode + event = 'InsertEnter', opts = nil, config = function() require('plugins.nvim-autopairs.setup').setup(require('plugins.nvim-autopairs.setup').opts) diff --git a/lua/plugins/nvim-lspconfig.lua b/lua/plugins/nvim-lspconfig.lua index e672a006..88ae0cf2 100644 --- a/lua/plugins/nvim-lspconfig.lua +++ b/lua/plugins/nvim-lspconfig.lua @@ -39,7 +39,7 @@ return { -- 'folke/neodev.nvim', -- Adds support for Neovim Lua API -- No longer needed with lazydev { 'WhoIsSethDaniel/mason-tool-installer.nvim', - event = "VeryLazy", + event = 'VeryLazy', config = function() require('mason-tool-installer').setup { ensure_installed = { diff --git a/lua/plugins/session.lua b/lua/plugins/session.lua index 21addca8..5ec46cf9 100644 --- a/lua/plugins/session.lua +++ b/lua/plugins/session.lua @@ -2,53 +2,33 @@ return { 'echasnovski/mini.sessions', version = '*', - event = "VimEnter", + event = 'VimEnter', config = function() - -- Function to get current directory name local function get_session_name() + return vim.fn.fnamemodify(vim.fn.getcwd(), ':t') + end + + -- Cache Go project check per directory + local go_project_cache = {} + local function is_go_project() local cwd = vim.fn.getcwd() - return vim.fn.fnamemodify(cwd, ':t') + if go_project_cache[cwd] == nil then + -- Single glob with brace expansion + go_project_cache[cwd] = vim.fn.glob(cwd .. '/{*.go,go.mod,go.work}') ~= '' + end + return go_project_cache[cwd] end require('mini.sessions').setup({ - -- Whether to read latest session if Neovim opened without file arguments autoread = false, - -- Whether to write current session before quitting Neovim autowrite = true, - -- Directory where global sessions are stored (use `''` to disable) directory = vim.fn.stdpath('data') .. '/sessions', - -- File for local session (use `''` to disable) file = '', - -- Whether to force possibly harmful actions (meaning depends on function) force = { read = false, write = true, delete = false }, - -- Hook functions for actions. Default `nil` means 'do nothing'. hooks = { - -- Before successful action pre = { - read = function() - -- Skip session operations for Go projects - local current_dir = vim.fn.getcwd() - local has_go_files = vim.fn.glob(current_dir .. "/*.go") ~= "" or - vim.fn.glob(current_dir .. "/go.mod") ~= "" or - vim.fn.glob(current_dir .. "/go.work") ~= "" - - if has_go_files then - return false -- Skip for Go projects - end - return true - end, - write = function() - -- Skip session operations for Go projects - local current_dir = vim.fn.getcwd() - local has_go_files = vim.fn.glob(current_dir .. "/*.go") ~= "" or - vim.fn.glob(current_dir .. "/go.mod") ~= "" or - vim.fn.glob(current_dir .. "/go.work") ~= "" - - if has_go_files then - return false -- Skip for Go projects - end - return true - end, + read = function() return not is_go_project() end, + write = function() return not is_go_project() end, }, -- After successful action post = { read = nil, write = nil, delete = nil },