forgot to push this... lots of changes to add elixir support and other fixes

This commit is contained in:
Adam Poniatowski 2026-03-05 20:02:43 +01:00
parent f6a19a3a75
commit 06d714c945
No known key found for this signature in database
GPG Key ID: E08510DAEC63C586
20 changed files with 957 additions and 105 deletions

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"stylua.targetReleaseVersion": "latest"
}

View File

@ -12,6 +12,9 @@ vim.g.maplocalleader = ' '
-- - Line/selection movement (Alt + jk) -- - Line/selection movement (Alt + jk)
-- - Quick save and quit (<leader>w, <leader>W, <leader>Q) -- - Quick save and quit (<leader>w, <leader>W, <leader>Q)
local core_keymaps = { local core_keymaps = {
-- Quick access to find files by content (shortcut for <leader>sg)
{ mode = 'n', lhs = '<leader><space>', rhs = function() require('telescope.builtin').live_grep() end, opts = { desc = 'Search text in all files' } },
-- Clear highlights on search when pressing <Esc> in normal mode -- Clear highlights on search when pressing <Esc> in normal mode
{ mode = 'n', lhs = '<Esc>', rhs = '<cmd>nohlsearch<CR>', opts = { desc = 'Clear search highlights' } }, { mode = 'n', lhs = '<Esc>', rhs = '<cmd>nohlsearch<CR>', opts = { desc = 'Clear search highlights' } },
@ -70,8 +73,38 @@ function M.setup_lsp_keymaps(bufnr)
{ mode = 'n', lhs = 'gy', rhs = function() require('telescope.builtin').lsp_type_definitions() end, opts = { desc = 'LSP: Go to type definition' } }, { mode = 'n', lhs = 'gy', rhs = function() require('telescope.builtin').lsp_type_definitions() end, opts = { desc = 'LSP: Go to type definition' } },
-- Symbol navigation -- Symbol navigation
{ mode = 'n', lhs = '<leader>ls', rhs = function() require('telescope.builtin').lsp_document_symbols() end, opts = { desc = 'LSP: Document symbols' } }, { mode = 'n', lhs = '<leader>ls', rhs = function()
{ mode = 'n', lhs = '<leader>lS', rhs = function() require('telescope.builtin').lsp_dynamic_workspace_symbols() end, opts = { desc = 'LSP: Workspace symbols' } }, -- 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 = '<leader>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 -- Code actions
{ mode = 'n', lhs = '<leader>lr', rhs = vim.lsp.buf.rename, opts = { desc = 'LSP: Rename symbol' } }, { mode = 'n', lhs = '<leader>lr', rhs = vim.lsp.buf.rename, opts = { desc = 'LSP: Rename symbol' } },
@ -79,7 +112,7 @@ function M.setup_lsp_keymaps(bufnr)
{ mode = 'n', lhs = '<leader>lf', rhs = function() vim.lsp.buf.format({ async = true }) end, opts = { desc = 'LSP: Format code' } }, { mode = 'n', lhs = '<leader>lf', rhs = function() vim.lsp.buf.format({ async = true }) end, opts = { desc = 'LSP: Format code' } },
-- Documentation -- Documentation
{ mode = 'n', lhs = 'K', rhs = vim.lsp.buf.hover, opts = { desc = 'LSP: Show 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 -- First clear any existing LSP keymaps for this buffer
@ -162,8 +195,9 @@ M.diagnostic_keymaps = {
{ mode = 'n', lhs = ']d', rhs = vim.diagnostic.goto_next, opts = { desc = 'Diagnostic: Next' } }, { mode = 'n', lhs = ']d', rhs = vim.diagnostic.goto_next, opts = { desc = 'Diagnostic: Next' } },
-- Viewing diagnostics -- Viewing diagnostics
{ mode = 'n', lhs = '<leader>tt', rhs = vim.diagnostic.open_float, opts = { desc = 'Diagnostic: Show details' } }, { mode = 'n', lhs = '<leader>tt', rhs = vim.diagnostic.open_float, opts = { desc = 'Diagnostic: Show details in float' } },
{ mode = 'n', lhs = '<leader>tl', rhs = vim.diagnostic.setloclist, opts = { desc = 'Diagnostic: Show list' } }, { mode = 'n', lhs = '<leader>tl', rhs = vim.diagnostic.setloclist, opts = { desc = 'Diagnostic: Show list' } },
{ mode = 'n', lhs = '<leader>td', rhs = function() require('telescope.builtin').diagnostics() end, opts = { desc = 'Diagnostic: Search all diagnostics' } },
} }
-- Database keymaps (all under <leader>D for Database) -- Database keymaps (all under <leader>D for Database)
@ -223,12 +257,31 @@ M.scratch_keymaps = {
-- - <C-/>: Toggle terminal in float window -- - <C-/>: Toggle terminal in float window
M.snacks_keymaps = { M.snacks_keymaps = {
-- Explorer -- Explorer
{ mode = 'n', lhs = '<leader>e', rhs = function() require('snacks.picker').explorer() end, opts = { desc = 'Explorer: Toggle' } }, { mode = 'n', lhs = '<leader>e', rhs = function()
{ mode = 'n', lhs = '<leader>E', rhs = function() require('snacks.picker').explorer({ reveal = true }) end, opts = { desc = 'Explorer: Focus current file' } }, -- Open explorer in current window
{ mode = 'n', lhs = '<leader>o', rhs = function() require('snacks.picker').explorer({ reveal = true }) end, opts = { desc = 'Explorer: Focus current file' } }, require('snacks').explorer.open()
end, opts = { desc = 'Explorer: Toggle' } },
{ mode = 'n', lhs = '<leader>E', rhs = function()
-- Reveal current file in explorer
require('snacks').explorer.reveal()
end, opts = { desc = 'Explorer: Focus current file' } },
{ mode = 'n', lhs = '<leader>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 = '<leader>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 -- Terminal
{ mode = 'n', lhs = '<C-/>', rhs = function() require('snacks').terminal.toggle() end, opts = { desc = 'Terminal: Toggle float window' } }, { mode = 'n', lhs = '<C-/>', rhs = function() require('snacks').terminal.toggle() end, opts = { desc = 'Terminal: Toggle float window' } },
{ mode = 'n', lhs = '<leader>tc', rhs = function() require('snacks').terminal.toggle() end, opts = { desc = 'Terminal: Toggle console' } },
} }
-- Git signs keymaps (all under <leader>g for Git) -- Git signs keymaps (all under <leader>g for Git)
@ -277,6 +330,35 @@ function M.setup_gitsigns_keymaps()
end end
end end
-- Elixir keymaps (using 'x' as the prefix - mnemonic for 'eXlixir')
M.elixir_keymaps = {
{ mode = 'n', lhs = '<leader>xt',
rhs = function()
require('elixir').run_test_file()
end,
opts = { desc = 'Elixir: Test file' }
},
{ mode = 'n', lhs = '<leader>xn',
rhs = function()
require('elixir').run_nearest_test()
end,
opts = { desc = 'Elixir: Test nearest' }
},
{ mode = 'n', lhs = '<leader>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 -- Leap keymaps
-- 's' for bidirectional search (both forward and backward) -- 's' for bidirectional search (both forward and backward)
-- 'S' for searching in all windows -- 'S' for searching in all windows
@ -327,7 +409,7 @@ local function init_keymaps()
callback = function() callback = function()
-- Pause snacks explorer updates during write -- Pause snacks explorer updates during write
pcall(function() pcall(function()
local picker = require('snacks.picker') local picker = require('plugins.snacks.picker')
if picker.is_open() then if picker.is_open() then
picker.pause_updates() picker.pause_updates()
vim.schedule(function() vim.schedule(function()
@ -405,12 +487,19 @@ local function init_keymaps()
-- Set up database keymaps -- Set up database keymaps
M.setup_dadbod_keymaps() M.setup_dadbod_keymaps()
-- Set up default tab navigation
vim.keymap.set('n', 'gt', ':tabnext<CR>', { silent = true, desc = 'Next tab' })
vim.keymap.set('n', 'gT', ':tabprevious<CR>', { silent = true, desc = 'Previous tab' })
-- Set up session keymaps -- Set up session keymaps
M.setup_session_keymaps() M.setup_session_keymaps()
-- Set up git signs keymaps -- Set up git signs keymaps
M.setup_gitsigns_keymaps() M.setup_gitsigns_keymaps()
-- Set up Elixir keymaps
M.setup_elixir_keymaps()
-- Set up leap keymaps -- Set up leap keymaps
M.setup_leap_keymaps() M.setup_leap_keymaps()
@ -422,5 +511,29 @@ init_keymaps()
-- Export `init_keymaps` as `M.setup` so `require('core.keymaps').setup()` works -- Export `init_keymaps` as `M.setup` so `require('core.keymaps').setup()` works
M.setup = init_keymaps 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 the module
return M return M

View File

@ -11,19 +11,58 @@ function M.setup()
end, end,
}) })
-- Auto format Go files on save
vim.api.nvim_create_autocmd('BufWritePre', { -- Add a smart format-on-save command that only uses null-ls
pattern = '*.go', -- Fix for zig.vim ftplugin error - handles both JSON and struct output
vim.api.nvim_create_autocmd('FileType', {
pattern = 'zig',
group = vim.api.nvim_create_augroup('user-zig-fix', { clear = true }),
callback = function() callback = function()
vim.lsp.buf.format({ async = false }) 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
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
end
end, end,
}) })
-- Auto format Zig files on save
vim.api.nvim_create_autocmd('BufWritePre', { vim.api.nvim_create_autocmd('BufWritePre', {
pattern = '*.zig', pattern = '*',
callback = function() callback = function(args)
vim.lsp.buf.format({ async = false }) local bufnr = args.buf
-- Check if null-ls is the formatter for this buffer
local client = vim.lsp.get_clients({ name = 'null-ls', bufnr = bufnr })[1]
if not client then
return
end
-- Format the buffer
vim.lsp.buf.format({ bufnr = bufnr, filter = function(c) return c.name == 'null-ls' end, async = false })
end, end,
}) })
end end

View File

@ -0,0 +1,58 @@
---@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,
}

View File

@ -1,12 +0,0 @@
return {
'saghen/blink.cmp',
dependencies = 'rafamadriz/friendly-snippets',
version = '*',
opts = {
keymap = { preset = 'default' },
appearance = {
use_nvim_cmp_as_default = true,
nerd_font_variant = 'mono',
},
},
}

View File

@ -5,6 +5,8 @@ local M = {}
function M.setup() function M.setup()
local cmp = require 'cmp' local cmp = require 'cmp'
local luasnip = require 'luasnip' local luasnip = require 'luasnip'
local types = require 'cmp.types'
local compare = require 'cmp.config.compare'
luasnip.config.setup {} luasnip.config.setup {}
cmp.setup { cmp.setup {
@ -13,13 +15,127 @@ function M.setup()
luasnip.lsp_expand(args.body) luasnip.lsp_expand(args.body)
end, end,
}, },
completion = { completeopt = 'menu,menuone,noinsert' }, -- Improved completion settings - more like VSCode
completion = {
completeopt = 'menu,menuone,noinsert',
keyword_length = 1, -- Show completions after 1 character
autocomplete = { types.cmp.TriggerEvent.TextChanged },
get_trigger_characters = function(trigger_characters)
-- Always add '.' as a trigger character to ensure method/property completions
if not vim.tbl_contains(trigger_characters, '.') then
table.insert(trigger_characters, '.')
end
if not vim.tbl_contains(trigger_characters, ':') then
table.insert(trigger_characters, ':')
end
return trigger_characters
end,
},
-- Custom sorting to prioritize fields and methods over snippets
sorting = {
priority_weight = 10, -- Increase weight to make priority differences more significant
comparators = {
-- Custom comparator that puts snippets at the end
function(entry1, entry2)
local types = require('cmp.types')
-- Extract the kinds
local kind1 = entry1:get_kind()
local kind2 = entry2:get_kind()
-- Define snippet kinds
local snippet_kinds = {
[types.lsp.CompletionItemKind.Snippet] = true
}
-- Check if either is a snippet
local is_snippet1 = snippet_kinds[kind1] or false
local is_snippet2 = snippet_kinds[kind2] or false
-- If one is a snippet and the other isn't, the non-snippet comes first
if is_snippet1 and not is_snippet2 then
return false
elseif not is_snippet1 and is_snippet2 then
return true
end
-- Otherwise fall through to other comparators
return nil
end,
compare.exact, -- Exact match first
compare.kind, -- Sort by kind (functions first, then properties, etc)
compare.sort_text, -- Sort by LSP's sortText
compare.score, -- Score based
compare.offset, -- Closest to cursor
compare.length, -- Shorter first
compare.order, -- Source order
},
},
-- Enhanced VSCode-like icons with more modern symbols
formatting = {
format = function(entry, vim_item)
-- Set icons for completion types
local kind_icons = {
Text = "󰉿", Method = "󰆧", Function = "󰊕", Constructor = "",
Field = "󰜢", Variable = "󰀫", Class = "󰠱", Interface = "",
Module = "", Property = "󰜢", Unit = "", Value = "󰎠",
Enum = "", Keyword = "󰌋", Snippet = "", Color = "󰏘",
File = "󰈙", Reference = "", Folder = "󰉋", EnumMember = "",
Constant = "󰏿", Struct = "", Event = "", Operator = "󰆕",
TypeParameter = "󰊄", TypeAlias = "", Parameter = "", StaticMethod = "",
Macro = "󰁌"
}
-- Enhanced formatting with better icons and spacing
vim_item.kind = string.format('%s %s', kind_icons[vim_item.kind] or '', vim_item.kind)
-- Show more detailed source info
vim_item.menu = ({
buffer = "[Buffer]",
nvim_lsp = "[LSP]",
luasnip = "[Snippet]",
path = "[Path]",
})[entry.source.name]
return vim_item
end,
},
-- Enhanced documentation window
window = {
completion = cmp.config.window.bordered({
winhighlight = "Normal:CmpPmenu,FloatBorder:CmpPmenuBorder,CursorLine:PmenuSel,Search:None",
scrollbar = true,
col_offset = -3,
side_padding = 1,
}),
documentation = cmp.config.window.bordered({
winhighlight = "Normal:CmpDoc",
}),
},
mapping = cmp.mapping.preset.insert { mapping = cmp.mapping.preset.insert {
['<C-n>'] = cmp.mapping.select_next_item(), ['<C-n>'] = cmp.mapping.select_next_item(),
['<C-p>'] = cmp.mapping.select_prev_item(), ['<C-p>'] = cmp.mapping.select_prev_item(),
['<C-b>'] = cmp.mapping.scroll_docs(-4), ['<C-b>'] = cmp.mapping.scroll_docs(-4),
['<C-f>'] = cmp.mapping.scroll_docs(4), ['<C-f>'] = cmp.mapping.scroll_docs(4),
['<C-y>'] = cmp.mapping.confirm { select = true }, ['<C-y>'] = cmp.mapping.confirm { select = true },
['<Tab>'] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_next_item()
elseif luasnip.expand_or_locally_jumpable() then
luasnip.expand_or_jump()
else
fallback()
end
end, { 'i', 's' }),
['<S-Tab>'] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_prev_item()
elseif luasnip.locally_jumpable(-1) then
luasnip.jump(-1)
else
fallback()
end
end, { 'i', 's' }),
['<C-Space>'] = cmp.mapping.complete {}, ['<C-Space>'] = cmp.mapping.complete {},
['<C-l>'] = cmp.mapping(function() ['<C-l>'] = cmp.mapping(function()
if luasnip.expand_or_locally_jumpable() then if luasnip.expand_or_locally_jumpable() then
@ -32,30 +148,112 @@ function M.setup()
end end
end, { 'i', 's' }), end, { 'i', 's' }),
}, },
sources = { -- Configure completion sources by priority with tweaked settings
{ name = 'lazydev', group_index = 0 }, sources = cmp.config.sources(
{ name = 'nvim_lsp' }, {
{ name = 'luasnip' }, { name = 'nvim_lsp', priority = 1000, max_item_count = 50 }, -- LSP comes first with more items
{ name = 'path' }, { name = 'path', priority = 500 }, -- Then paths
{ name = 'buffer' }, { name = 'buffer', priority = 250, keyword_length = 3 }, -- Then current buffer
-- Snippets with extremely low priority and limited visibility
{ name = 'luasnip', priority = 10, max_item_count = 3, keyword_length = 4 },
}
),
-- Enable experimental features for VSCode-like experience
experimental = {
ghost_text = true, -- Shows virtual text as preview
}, },
} }
-- Cmdline completion for search (/, ?) and command (:) -- Cmdline completion for search (/, ?) and command (:)
-- Enhanced commandline completion with better history and formatting
cmp.setup.cmdline({ '/', '?' }, { cmp.setup.cmdline({ '/', '?' }, {
mapping = cmp.mapping.preset.cmdline(), mapping = cmp.mapping.preset.cmdline(),
sources = { sources = {
{ name = 'buffer' } { name = 'buffer', max_item_count = 20 }
},
window = {
completion = cmp.config.window.bordered({
winhighlight = "Normal:CmpPmenu,FloatBorder:CmpPmenuBorder,CursorLine:PmenuSel,Search:None",
scrollbar = true,
})
},
completion = {
completeopt = 'menu,menuone,noinsert',
} }
}) })
cmp.setup.cmdline(':', { cmp.setup.cmdline(':', {
mapping = cmp.mapping.preset.cmdline(), mapping = cmp.mapping.preset.cmdline({
-- Explicit key mappings for command mode completion
['<Tab>'] = {
c = function(fallback)
if cmp.visible() then
cmp.select_next_item()
else
cmp.complete()
cmp.select_next_item()
end
end,
},
['<S-Tab>'] = {
c = function(fallback)
if cmp.visible() then
cmp.select_prev_item()
else
cmp.complete()
cmp.select_prev_item()
end
end,
},
['<C-n>'] = {
c = function(fallback)
if cmp.visible() then
cmp.select_next_item()
else
cmp.complete()
end
end,
},
['<C-p>'] = {
c = function(fallback)
if cmp.visible() then
cmp.select_prev_item()
else
cmp.complete()
end
end,
},
['<C-e>'] = {
c = cmp.mapping.abort(),
},
['<CR>'] = {
c = cmp.mapping.confirm({ select = true }),
},
}),
sources = cmp.config.sources({ sources = cmp.config.sources({
{ name = 'path' } { name = 'path', max_item_count = 20 },
}, { { name = 'cmdline', max_item_count = 30, keyword_length = 1 }
{ name = 'cmdline' } }),
}) window = {
completion = cmp.config.window.bordered({
winhighlight = "Normal:CmpPmenu,FloatBorder:CmpPmenuBorder,CursorLine:PmenuSel,Search:None",
scrollbar = true,
col_offset = -3,
side_padding = 1,
})
},
formatting = {
format = function(entry, vim_item)
-- Only show item kind for cmdline completion
vim_item.kind = ' '
vim_item.menu = ''
return vim_item
end,
},
completion = {
completeopt = 'menu,menuone,noinsert',
autocomplete = { cmp.TriggerEvent.TextChanged },
}
}) })
end end

View File

@ -4,4 +4,5 @@ return {
require('plugins.coding.zig'), require('plugins.coding.zig'),
require('plugins.coding.clangd'), require('plugins.coding.clangd'),
require('plugins.coding.dap'), require('plugins.coding.dap'),
require('plugins.coding.elixir'),
} }

View File

@ -1,6 +1,16 @@
---@diagnostic disable: undefined-global ---@diagnostic disable: undefined-global
return { return {
"mfussenegger/nvim-dap", "mfussenegger/nvim-dap",
keys = {
{ "<leader>pb", desc = "Toggle [B]reakpoint" },
{ "<leader>pc", desc = "[C]ontinue debugging" },
{ "<leader>pn", desc = "Step over ([N]ext)" },
{ "<leader>pi", desc = "Step [I]nto" },
{ "<leader>po", desc = "Step [O]ut" },
{ "<leader>pr", desc = "Open [R]EPL" },
{ "<leader>pl", desc = "Run [L]ast debug session" },
{ "<leader>px", desc = "Toggle debug UI" },
},
dependencies = { dependencies = {
"rcarriga/nvim-dap-ui", "rcarriga/nvim-dap-ui",
"theHamsta/nvim-dap-virtual-text", "theHamsta/nvim-dap-virtual-text",

View File

@ -0,0 +1,38 @@
return {
{
'elixir-tools/elixir-tools.nvim',
version = '*',
ft = { 'ex', 'exs', 'heex', 'eex', 'elixir' },
dependencies = {
'neovim/nvim-lspconfig',
'nvim-lua/plenary.nvim',
},
config = function()
local elixir = require('elixir')
-- Configure elixir-tools with LSP disabled (handled by lspconfig)
elixir.setup({
-- Disable the built-in LSP client to avoid conflicts
elixirls = { enable = false },
-- Enable non-LSP features
credo = { enable = true },
projectionist = { enable = true },
-- Configure the test runner
test_runner = {
enabled = true,
runner = 'exunit', -- or 'exunit_individual' for individual test runs
},
-- Enable mix integration
mix = {
enabled = true,
format_on_save = false, -- Disabled to prevent file changed warnings
},
})
-- Keymaps are now in core/keymaps.lua with <leader>lx prefix
end,
},
}

76
lua/plugins/doc-test.lua Normal file
View File

@ -0,0 +1,76 @@
---@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", "<leader>td", test_doc_window, { desc = "Test doc window styling" })
end
}

44
lua/plugins/hover.lua Normal file
View File

@ -0,0 +1,44 @@
---@diagnostic disable: undefined-global
return {
'lewis6991/hover.nvim',
event = 'VeryLazy',
config = function()
require('hover').setup({
init = function()
-- Required for hover.nvim
require('hover.providers.lsp')
-- Optional additional providers
require('hover.providers.gh')
require('hover.providers.man')
require('hover.providers.dictionary')
end,
preview_opts = {
border = 'rounded',
width = 80,
height = 20,
},
title = true,
-- Key mappings
-- Use the same mapping as before ('K')
mappings = {
toggle_hover = 'K',
-- Scroll option
scroll_up = '<C-u>',
scroll_down = '<C-d>',
},
})
-- Style adjustments
vim.api.nvim_set_hl(0, 'HoverFloat', { link = 'Normal' })
vim.api.nvim_set_hl(0, 'HoverFloatBorder', { link = 'FloatBorder' })
-- Override the LSP hover handler to ensure our hover.nvim is used
vim.api.nvim_create_autocmd('LspAttach', {
callback = function(args)
-- Clear and override the K mapping to ensure it uses hover.nvim
vim.keymap.set('n', 'K', require('hover').hover,
{ buffer = args.buf, desc = 'Enhanced documentation (hover.nvim)' })
end,
})
end,
}

View File

@ -4,41 +4,57 @@
local M = {} local M = {}
function M.setup() function M.setup()
-- Create a wrapper that ensures position_encoding is added to all calls -- Patch the symbols_to_items function to always use utf-16 encoding
local function with_encoding(fn) -- and handle nil values safely
return function(params, ...) local original_symbols_to_items = vim.lsp.util.symbols_to_items
params = params or {}
if not params.position_encoding then
params.position_encoding = 'utf-16'
end
return fn(params, ...)
end
end
-- Override standard LSP buffer functions that may be missing position_encoding
vim.lsp.buf.code_action = with_encoding(vim.lsp.buf.code_action)
vim.lsp.buf.rename = with_encoding(vim.lsp.buf.rename)
vim.lsp.buf.hover = with_encoding(vim.lsp.buf.hover)
vim.lsp.buf.formatting = with_encoding(vim.lsp.buf.formatting)
vim.lsp.buf.range_formatting = with_encoding(vim.lsp.buf.range_formatting)
vim.lsp.buf.format = with_encoding(vim.lsp.buf.format)
-- Patch util functions as well
local orig_make_position_params = vim.lsp.util.make_position_params
vim.lsp.util.make_position_params = function(window, client, position_encoding)
if not position_encoding then
position_encoding = 'utf-16'
end
return orig_make_position_params(window, client, position_encoding)
end
-- Override symbols_to_items to ensure position_encoding is set
local orig_symbols_to_items = vim.lsp.util.symbols_to_items
vim.lsp.util.symbols_to_items = function(symbols, bufnr, position_encoding) vim.lsp.util.symbols_to_items = function(symbols, bufnr, position_encoding)
if not position_encoding then -- Default to utf-16 if not specified
position_encoding = 'utf-16' position_encoding = position_encoding or 'utf-16'
-- Add extra safety checks for nil values
if not symbols or type(symbols) ~= 'table' then
return {}
end
-- Call original with proper encoding
return original_symbols_to_items(symbols, bufnr, position_encoding)
end
-- Patch workspace_symbol handler to be safer
vim.lsp.handlers['workspace/symbol'] = function(err, result, ctx, config)
if err or not result or vim.tbl_isempty(result) then
return {}
end
-- Set a default position_encoding
local position_encoding = 'utf-16'
local client = vim.lsp.get_client_by_id(ctx.client_id)
if client and client.offset_encoding then
position_encoding = client.offset_encoding
end
-- Process safely
local items = vim.lsp.util.symbols_to_items(result, nil, position_encoding) or {}
return items
end
-- Patch all lsp_* functions in telescope.builtin to include position_encoding
local telescope_builtin = require('telescope.builtin')
local telescope_funcs = {
'lsp_references', 'lsp_definitions', 'lsp_implementations',
'lsp_type_definitions', 'lsp_document_symbols', 'lsp_workspace_symbols',
'lsp_dynamic_workspace_symbols'
}
for _, func_name in ipairs(telescope_funcs) do
local original_func = telescope_builtin[func_name]
telescope_builtin[func_name] = function(opts)
opts = opts or {}
if not opts.position_encoding then
opts.position_encoding = 'utf-16'
end
return original_func(opts)
end end
return orig_symbols_to_items(symbols, bufnr, position_encoding)
end end
end end

View File

@ -55,7 +55,72 @@ return {
}, },
}, },
-- C/C++ -- C/C++
clangd = {}, clangd = {
cmd = {
'clangd',
'--background-index',
'--clang-tidy',
'--header-insertion=iwyu',
'--completion-style=detailed',
'--function-arg-placeholders',
'--fallback-style=llvm',
},
init_options = {
usePlaceholders = true,
completeUnimported = true,
clangdFileStatus = true,
},
on_attach = function(client, bufnr)
-- Set the correct standard based on filetype
local filetype = vim.bo[bufnr].filetype
if filetype == 'c' then
client.config.init_options.fallbackFlags = { '-std=c23' }
elseif filetype == 'cpp' then
client.config.init_options.fallbackFlags = { '-std=c++23' }
end
-- Call the default on_attach to setup keymaps and navic
require('plugins.lsp.setup').default_on_attach(client, bufnr)
end,
settings = {
clangd = {
InlayHints = {
Designators = true,
Enabled = true,
ParameterNames = true,
DeducedTypes = true,
},
},
},
},
-- Zig
zls = {
settings = {
zls = {
-- Enable semantic highlighting
enable_semantic_tokens = true,
-- Enable inlay hints for better code understanding
enable_inlay_hints = true,
-- Enable snippets
enable_snippets = true,
-- Enable auto-fixing
enable_autofix = true,
-- Warn about style issues
warn_style = true,
-- Highlight global variables
highlight_global_var_declarations = true,
-- Enable build-on-save for faster feedback
enable_build_on_save = true,
-- Skip std library references for better performance
skip_std_references = false,
-- Prefer ast-check over zig fmt for faster response
prefer_ast_check_as_child_process = true,
-- Enable import embedfile argument completions
enable_import_embedfile_argument_completions = true,
},
},
},
-- SQL -- SQL
sqls = { sqls = {
@ -66,4 +131,17 @@ return {
}, },
}, },
}, },
-- Elixir
elixirls = {
cmd = { 'elixir-ls' },
settings = {
elixirLS = {
dialyzerEnabled = true,
fetchDeps = true,
enableTestLenses = true,
suggestSpecs = true,
}
}
}
} }

View File

@ -4,10 +4,50 @@
local M = {} local M = {}
function M.setup() function M.setup()
-- Apply LSP function overrides for position_encoding
require('plugins.lsp.overrides').setup()
local servers = require('plugins.lsp.servers') local servers = require('plugins.lsp.servers')
-- nvim-cmp capabilities -- Enhanced nvim-cmp capabilities (VSCode-like)
local capabilities = vim.lsp.protocol.make_client_capabilities() local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities.textDocument.completion.completionItem = {
documentationFormat = { 'markdown', 'plaintext' },
snippetSupport = true,
preselectSupport = true,
insertReplaceSupport = true,
labelDetailsSupport = true,
deprecatedSupport = true,
commitCharactersSupport = true,
tagSupport = { valueSet = { 1 } },
resolveSupport = {
properties = {
'documentation',
'detail',
'additionalTextEdits',
},
},
}
-- Complete with all available methods and properties
capabilities.textDocument.completion.completionList = {
itemDefaults = {
'commitCharacters',
'editRange',
'insertTextFormat',
'insertTextMode',
'data',
},
}
-- Add semantic tokens for better syntax highlighting
capabilities.textDocument.semanticTokens = {
tokenTypes = { 'namespace', 'type', 'class', 'enum', 'interface', 'struct', 'typeParameter', 'parameter', 'variable', 'property', 'enumMember', 'event', 'function', 'method', 'macro', 'keyword', 'modifier', 'comment', 'string', 'number', 'regexp', 'operator', 'decorator' },
tokenModifiers = { 'declaration', 'definition', 'readonly', 'static', 'deprecated', 'abstract', 'async', 'modification', 'documentation', 'defaultLibrary' },
formats = { 'relative' },
requests = {
range = true,
full = true,
},
}
capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities) capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities)
-- Setup mason-lspconfig -- Setup mason-lspconfig
@ -20,16 +60,27 @@ function M.setup()
config.capabilities = capabilities config.capabilities = capabilities
-- Default on_attach to setup keymaps & navic -- Default on_attach to setup keymaps & navic
local function on_attach(client, bufnr) M.default_on_attach = function(client, bufnr)
require('core.keymaps').setup_lsp_keymaps(bufnr) require('core.keymaps').setup_lsp_keymaps(bufnr)
-- Attach navic if available
if client.server_capabilities.documentSymbolProvider then -- Only attach navic if:
require('nvim-navic').attach(client, bufnr) -- 1. The client supports document symbols
-- 2. The client isn't elixirls (handled by elixir-tools.nvim)
if client.server_capabilities.documentSymbolProvider
and client.name ~= 'elixirls' then
local status_ok, _ = pcall(require, 'nvim-navic')
if status_ok then
require('nvim-navic').attach(client, bufnr)
end
end end
end end
config.on_attach = on_attach
-- Only set the default on_attach if one isn't already provided
if not config.on_attach then
config.on_attach = M.default_on_attach
end
-- Disable gopls semantic tokens to avoid issues -- Enhance LSP capabilities for specific servers
if server_name == 'gopls' and config.on_attach then if server_name == 'gopls' and config.on_attach then
local orig_on_attach = config.on_attach local orig_on_attach = config.on_attach
config.on_attach = function(client, bufnr) config.on_attach = function(client, bufnr)
@ -37,11 +88,56 @@ function M.setup()
orig_on_attach(client, bufnr) orig_on_attach(client, bufnr)
end end
end end
-- Force all LSP servers to use incremental completions (like VSCode)
if not config.settings then config.settings = {} end
if not config.settings.completions then config.settings.completions = {} end
config.settings.completions.completeFunctionCalls = true
-- Enhanced settings for Lua LSP
if server_name == 'lua_ls' then
if not config.settings.Lua then config.settings.Lua = {} end
config.settings.Lua.completion = {
callSnippet = "Replace",
showWord = "Disable",
workspaceWord = false,
displayContext = 5,
keywordSnippet = "Both",
postfix = ".",
}
-- More comprehensive inferencing
config.settings.Lua.hint = {
enable = true,
setType = true,
paramType = true,
paramName = "Literal",
arrayIndex = "Enable",
}
-- Better type resolution
config.settings.Lua.type = {
castNumberToInteger = true,
}
-- Add standard Lua libraries for better completion
if not config.settings.Lua.workspace then config.settings.Lua.workspace = {} end
if not config.settings.Lua.workspace.library then config.settings.Lua.workspace.library = {} end
-- Include standard libraries
local lua_types = vim.fn.expand('~/.local/share/nvim/mason/packages/lua-language-server/libexec/meta/3rd')
if vim.fn.isdirectory(lua_types) == 1 then
config.settings.Lua.workspace.library[lua_types] = true
end
-- Enable all features
config.settings.Lua.hover = { enable = true, expandAlias = true }
config.settings.Lua.signatureHelp = { enable = true }
config.settings.Lua.diagnostics = { enable = true, globals = { "vim" } }
end
require('lspconfig')[server_name].setup(config) require('lspconfig')[server_name].setup(config)
end, end,
} }
-- Hover handler will now be provided by Blink
-- Override references handler -- Override references handler
vim.lsp.handlers['textDocument/references'] = function(err, result, ctx, config) vim.lsp.handlers['textDocument/references'] = function(err, result, ctx, config)
if not result or vim.tbl_isempty(result) then if not result or vim.tbl_isempty(result) then

View File

@ -1,10 +1,43 @@
return { ---@diagnostic disable: undefined-global
local vim = vim
local M = {
'nvimtools/none-ls.nvim', 'nvimtools/none-ls.nvim',
event = { 'BufReadPre', 'BufNewFile' }, event = { 'BufReadPre', 'BufNewFile' },
dependencies = { dependencies = {
'jay-babu/mason-null-ls.nvim', 'jay-babu/mason-null-ls.nvim',
}, },
config = function() config = function()
require('plugins.null-ls.setup').setup() -- Safely require null-ls
local ok, null_ls = pcall(require, 'null-ls')
if not ok then
vim.notify('Failed to load null-ls', vim.log.levels.ERROR)
return
end
-- Safely require setup
local setup_ok, setup = pcall(require, 'plugins.null-ls.setup')
if not setup_ok or type(setup.setup) ~= 'function' then
vim.notify('Failed to load null-ls setup', vim.log.levels.ERROR)
return
end
-- Initialize null-ls
setup.setup()
-- Additional safety check for sources
vim.defer_fn(function()
if not null_ls or not null_ls.get_sources then
vim.notify('null-ls sources not available', vim.log.levels.WARN)
return
end
local sources = null_ls.get_sources()
if #sources == 0 then
vim.notify('No null-ls sources registered', vim.log.levels.WARN)
end
end, 1000) -- Check after 1 second
end, end,
} }
return M

View File

@ -9,6 +9,7 @@ function M.setup()
local diagnostics = null_ls.builtins.diagnostics local diagnostics = null_ls.builtins.diagnostics
null_ls.setup { null_ls.setup {
root_dir = null_ls_utils.root_pattern('.null-ls-root', 'Makefile', '.git'), root_dir = null_ls_utils.root_pattern('.null-ls-root', 'Makefile', '.git'),
timeout = 10000, timeout = 10000,
debounce = 250, debounce = 250,

View File

@ -19,12 +19,12 @@ return { -- Autocompletion
-- `friendly-snippets` contains a variety of premade snippets. -- `friendly-snippets` contains a variety of premade snippets.
-- See the README about individual language/framework/plugin snippets: -- See the README about individual language/framework/plugin snippets:
-- https://github.com/rafamadriz/friendly-snippets -- https://github.com/rafamadriz/friendly-snippets
-- { {
-- 'rafamadriz/friendly-snippets', 'rafamadriz/friendly-snippets',
-- config = function() config = function()
-- require('luasnip.loaders.from_vscode').lazy_load() require('luasnip.loaders.from_vscode').lazy_load()
-- end, end,
-- }, },
}, },
}, },
'saadparwaiz1/cmp_luasnip', 'saadparwaiz1/cmp_luasnip',

View File

@ -4,13 +4,42 @@ local go_flags = 'integration' -- add the tags here, instead of searching it bel
return { return {
-- Main LSP Configuration -- Main LSP Configuration
'neovim/nvim-lspconfig', 'neovim/nvim-lspconfig',
event = { "BufReadPre", "BufNewFile" },
dependencies = { dependencies = {
-- Automatically install LSPs and related tools to stdpath for Neovim -- Automatically install LSPs and related tools to stdpath for Neovim
{ 'williamboman/mason.nvim', config = true }, -- NOTE: Must be loaded before dependants {
'williamboman/mason-lspconfig.nvim', 'williamboman/mason.nvim',
cmd = { "Mason", "MasonInstall", "MasonUpdate" },
config = function()
require("mason").setup({
ui = {
icons = {
package_installed = "",
package_pending = "",
package_uninstalled = ""
},
border = "rounded",
width = 0.8,
height = 0.9,
},
log_level = vim.log.levels.INFO,
max_concurrent_installers = 4,
})
end
},
{
'williamboman/mason-lspconfig.nvim',
dependencies = { 'williamboman/mason.nvim' },
config = function()
require("mason-lspconfig").setup({
automatic_installation = true
})
end
},
-- 'folke/neodev.nvim', -- Adds support for Neovim Lua API -- No longer needed with lazydev -- 'folke/neodev.nvim', -- Adds support for Neovim Lua API -- No longer needed with lazydev
{ {
'WhoIsSethDaniel/mason-tool-installer.nvim', 'WhoIsSethDaniel/mason-tool-installer.nvim',
event = "VeryLazy",
config = function() config = function()
require('mason-tool-installer').setup { require('mason-tool-installer').setup {
ensure_installed = { ensure_installed = {
@ -35,6 +64,8 @@ return {
'debugpy', -- Python debugger 'debugpy', -- Python debugger
-- SQL tools -- SQL tools
'sqls', -- Advanced SQL LSP 'sqls', -- Advanced SQL LSP
-- Elixir
'elixir-ls' -- Elixir LSP
}, },
auto_update = true, auto_update = true,
run_on_start = true, run_on_start = true,

View File

@ -1,22 +1,49 @@
return { -- Highlight, edit, and navigate code return {
-- Highlight, edit, and navigate code
'nvim-treesitter/nvim-treesitter', 'nvim-treesitter/nvim-treesitter',
build = ':TSUpdate', dependencies = {
'nvim-treesitter/nvim-treesitter-textobjects',
},
build = function()
local ts_update = require('nvim-treesitter.install').update({ with_sync = true })
ts_update()
-- Install C++ parser explicitly to avoid tarball issues
vim.cmd('silent! TSInstall cpp')
end,
main = 'nvim-treesitter.configs', -- Sets main module to use for opts main = 'nvim-treesitter.configs', -- Sets main module to use for opts
-- [[ Configure Treesitter ]] See `:help nvim-treesitter` -- [[ Configure Treesitter ]] See `:help nvim-treesitter`
opts = { opts = {
ensure_installed = { 'bash', 'c', 'diff', 'html', 'lua', 'luadoc', 'markdown', 'markdown_inline', 'query', 'vim', 'vimdoc' }, -- List of languages to ensure are installed
ensure_installed = {
'bash', 'c', 'cpp', 'diff', 'html', 'lua', 'luadoc',
'markdown', 'markdown_inline', 'python', 'rust',
'javascript', 'typescript', 'json', 'yaml', 'query',
'vim', 'vimdoc', 'comment', 'regex'
},
-- Install parsers synchronously (only applied to `ensure_installed`)
sync_install = false, sync_install = false,
-- Automatically install missing parsers when entering buffer
auto_install = true, auto_install = true,
ignore_install = {}, -- List of parsers to ignore installing (for "all")
ignore_install = { 'phpdoc' },
highlight = { highlight = {
enable = true, enable = true,
-- Some languages depend on vim's regex highlighting system (such as Ruby) for indent rules. -- Additional filetypes to enable highlighting for
-- If you are experiencing weird indenting issues, add the language to
-- the list of additional_vim_regex_highlighting and disabled languages for indent.
additional_vim_regex_highlighting = { 'ruby' }, additional_vim_regex_highlighting = { 'ruby' },
-- Disable for large files
disable = function(_, buf)
local max_filesize = 100 * 1024 -- 100 KB
local ok, stats = pcall(vim.loop.fs_stat, vim.api.nvim_buf_get_name(buf))
if ok and stats and stats.size > max_filesize then
return true
end
end,
},
indent = {
enable = true,
disable = { 'ruby', 'yaml' }
}, },
indent = { enable = true, disable = { 'ruby' } },
}, },
-- There are additional nvim-treesitter modules that you can use to interact -- There are additional nvim-treesitter modules that you can use to interact
-- with nvim-treesitter. You should go explore a few and see what interests you: -- with nvim-treesitter. You should go explore a few and see what interests you:

View File

@ -1,3 +1,4 @@
---@diagnostic disable: undefined-global
return { -- Useful plugin to show you pending keybinds. return { -- Useful plugin to show you pending keybinds.
'folke/which-key.nvim', 'folke/which-key.nvim',
event = 'VimEnter', -- Sets the loading event to 'VimEnter' event = 'VimEnter', -- Sets the loading event to 'VimEnter'
@ -63,12 +64,12 @@ return { -- Useful plugin to show you pending keybinds.
{ '<leader>l', group = '[L]SP/Language' }, { '<leader>l', group = '[L]SP/Language' },
{ '<leader>m', group = '[M]emory/Sessions' }, { '<leader>m', group = '[M]emory/Sessions' },
{ '<leader>D', group = '[D]atabase' }, { '<leader>D', group = '[D]atabase' },
{ '<leader>t', group = '[T]oggle', desc = { { '<leader>t', group = '[T]roubleshooting', desc = {
h = 'Toggle inlay [H]ints', d = 'Search all [D]iagnostics',
}}, l = 'Diagnostics in [L]ocation list',
{ '<leader>w', group = '[W]orkspace', desc = { t = 'Diagnostic details in floa[T]',
s = '[S]ymbols',
}}, }},
{ '<leader>w', desc = 'Save file' },
{ '<leader>h', group = 'Git [H]unk', mode = { 'n', 'v' } }, { '<leader>h', group = 'Git [H]unk', mode = { 'n', 'v' } },
{ '<leader>g', group = '[G]it', desc = { { '<leader>g', group = '[G]it', desc = {
s = 'Status', s = 'Status',
@ -105,6 +106,7 @@ return { -- Useful plugin to show you pending keybinds.
{ '<leader>X', desc = 'Force close buffer' }, { '<leader>X', desc = 'Force close buffer' },
{ '<leader>/', desc = 'Search in current buffer' }, { '<leader>/', desc = 'Search in current buffer' },
{ '<leader><leader>', desc = 'Find buffers' }, { '<leader><leader>', desc = 'Find buffers' },
{ '<leader><space>', desc = 'Search text in all files' },
}, },
}, },
} }