diff --git a/.config/nvim/init.lua b/.config/nvim/init.lua index 79ff5085..249221c1 100644 --- a/.config/nvim/init.lua +++ b/.config/nvim/init.lua @@ -4,5 +4,6 @@ require("lazy-init") require("config.autocmds") require("config.filetypes") require("funcs").set_title() -require("funcs").set_maps(require("config.keymaps").maps()) require("funcs").set_cwd() +require("funcs").set_maps(require("config.keymaps").standard_maps()) +require("funcs").diagnostic_setup(require("config.diagnostic")) diff --git a/.config/nvim/lua/config/diagnostic.lua b/.config/nvim/lua/config/diagnostic.lua new file mode 100644 index 00000000..ad3f7163 --- /dev/null +++ b/.config/nvim/lua/config/diagnostic.lua @@ -0,0 +1,40 @@ +local M = {} +local icons = require("config.icons") + +M.signs = { + { name = "DapStopped", text = icons.DapStopped, texthl = "DiagnosticWarn" }, + { name = "DapBreakpoint", text = icons.DapBreakpoint, texthl = "DiagnosticInfo" }, + { name = "DapBreakpointRejected", text = icons.DapBreakpointRejected, texthl = "DiagnosticError" }, + { name = "DapBreakpointCondition", text = icons.DapBreakpointCondition, texthl = "DiagnosticInfo" }, + { name = "DapLogPoint", text = icons.DapLogPoint, texthl = "DiagnosticInfo" }, + { name = "DiagnosticSignError", text = icons.Error, texthl = "DiagnosticSignError" }, + { name = "DiagnosticSignWarn", text = icons.Warn, texthl = "DiagnosticSignWarn" }, + { name = "DiagnosticSignHint", text = icons.Hint, texthl = "DiagnosticSignHint" }, + { name = "DiagnosticSignInfo", text = icons.Info, texthl = "DiagnosticSignInfo" }, +} + +M.diagnostic = { + virtual_text = true, + signs = { + text = { + [vim.diagnostic.severity.ERROR] = icons.Error, + [vim.diagnostic.severity.HINT] = icons.Hint, + [vim.diagnostic.severity.WARN] = icons.Warn, + [vim.diagnostic.severity.INFO] = icons.Info, + }, + active = M.signs, + }, + update_in_insert = true, + underline = true, + severity_sort = true, + float = { + focused = false, + style = "minimal", + border = "rounded", + source = "always", + header = "", + prefix = "", + }, +} + +return M diff --git a/.config/nvim/lua/config/keymaps.lua b/.config/nvim/lua/config/keymaps.lua index d203961b..71ad07ea 100644 --- a/.config/nvim/lua/config/keymaps.lua +++ b/.config/nvim/lua/config/keymaps.lua @@ -2,8 +2,6 @@ local M = {} local f = require("funcs") local icons = require("config.icons") -local maps = f.empty_map_table() - M.sections = { p = { desc = icons.Package .. " Packages" }, b = { desc = icons.Buffer .. " Buffers" }, @@ -18,7 +16,8 @@ M.sections = { e = { desc = icons.FileTree .. " File Manager" }, } -M.maps = function() +M.standard_maps = function() + local maps = f.empty_map_table() -- Standard -- maps.n["j"] = { "v:count == 0 ? 'gj' : 'j'", expr = true, desc = "Move cursor down" } maps.n["k"] = { "v:count == 0 ? 'gk' : 'k'", expr = true, desc = "Move cursor up" } @@ -565,8 +564,11 @@ M.maps = function() end, desc = "Debugger: Stop", } - maps.n["<S-F9>"] = { conditional_breakpoint, desc = "Debugger: Conditional Breakpoint" } - maps.n["<C-F5>"] = { + + -- S-F9 + maps.n["<F21>"] = { conditional_breakpoint, desc = "Debugger: Conditional Breakpoint" } + -- C-F5 + maps.n["<F29>"] = { function() require("dap").restart_frame() end, @@ -596,7 +598,8 @@ M.maps = function() end, desc = "Debugger: Step Into", } - maps.n["<S-F11>"] = { + -- S-F11 + maps.n["<F23>"] = { function() require("dap").step_out() end, @@ -744,6 +747,278 @@ M.maps = function() return maps end +M.lsp_maps = function(client, bufnr) + local maps = f.empty_map_table() + + maps.n["<Leader>ld"] = { + function() + vim.diagnostic.open_float() + end, + desc = "Hover diagnostics", + } + maps.n["[d"] = { + function() + vim.diagnostic.goto_prev() + end, + desc = "Previous diagnostic", + } + maps.n["]d"] = { + function() + vim.diagnostic.goto_next() + end, + desc = "Next diagnostic", + } + maps.n["gl"] = { + function() + vim.diagnostic.open_float() + end, + desc = "Hover diagnostics", + } + + if f.is_available("telescope.nvim") then + maps.n["<Leader>lD"] = { + function() + require("telescope.builtin").diagnostics() + end, + desc = "Search diagnostics", + } + end + + if f.is_available("mason-lspconfig.nvim") then + maps.n["<Leader>li"] = { "<cmd>LspInfo<cr>", desc = "LSP information" } + end + + if f.is_available("none-ls.nvim") then + maps.n["<Leader>lI"] = { "<cmd>NullLsInfo<cr>", desc = "Null-ls information" } + end + + if client.supports_method("textDocument/codeAction") then + maps.n["<Leader>la"] = { + function() + vim.lsp.buf.code_action() + end, + desc = "Code action", + } + maps.v["<Leader>la"] = maps.n["<Leader>la"] + end + + if client.supports_method("textDocument/codeLens") then + vim.lsp.codelens.refresh() + maps.n["<Leader>ll"] = { + function() + vim.lsp.codelens.refresh() + end, + desc = "Refresh CodeLens", + } + maps.n["<Leader>lL"] = { + function() + vim.lsp.codelens.run() + end, + desc = "Run CodeLens", + } + maps.n["<Leader>u"] = { desc = icons.Gear .. " Utility" } + maps.n["<Leader>uL"] = { + function() + vim.lsp.codelens.clear() + end, + desc = "Toggle CodeLens", + } + end + + if client.supports_method("textDocument/definition") then + maps.n["gd"] = { + function() + vim.lsp.buf.definition() + end, + desc = "Go to definition", + } + end + + if client.supports_method("textDocument/typeDefinition") then + maps.n["gy"] = { + function() + vim.lsp.buf.type_definition() + end, + desc = "Go to type definition", + } + end + + if client.supports_method("textDocument/declaration") then + maps.n["gD"] = { + function() + vim.lsp.buf.declaration() + end, + desc = "Go to declaration", + } + end + + if client.supports_method("textDocument/implementation") then + maps.n["gI"] = { + function() + vim.lsp.buf.implementation() + end, + desc = "List implementations", + } + end + + if client.supports_method("textDocument/references") then + maps.n["gr"] = { + function() + vim.lsp.buf.references() + end, + desc = "List references", + } + end + + if client.supports_method("workspace/symbol") then + maps.n["<Leader>lG"] = { + function() + vim.lsp.buf.workspace_symbol("") + end, + desc = "List symbols", + } + end + + if client.supports_method("textDocument/rename") then + maps.n["<Leader>lr"] = { + function() + vim.lsp.buf.rename() + end, + desc = "Rename symbol", + } + end + + -- TODO: Check this on 0.10.0 release + if client.supports_method("textDocument/semanticTokens/full") and vim.lsp.semantic_tokens then + maps.n["<Leader>u"] = { desc = icons.Gear .. " Utility" } + maps.n["<Leader>uY"] = { + function() + vim.b[bufnr].semantic_tokens_enabled = not vim.b[bufnr].semantic_tokens_enabled + for _, active_client in ipairs(vim.lsp.get_active_clients({ bufnr = bufnr })) do + if active_client.server_capabilities.semanticTokensProvider then + vim.lsp.semantic_tokens[vim.b[bufnr].semantic_tokens_enabled and "start" or "stop"]( + bufnr, + active_client.id + ) + end + end + end, + desc = "Toggle LSP semantic highlight (buffer)", + } + end + + if client.supports_method("textDocument/formatting") then + maps.n["<Leader>lf"] = { + function() + vim.lsp.buf.format({ + filter = function(c) + local filetype = vim.bo.filetype + local n = require("null-ls") + local s = require("null-ls.sources") + local method = n.methods.FORMATTING + local available_formatters = s.get_available(filetype, method) + if #available_formatters > 0 then + return c.name == "null-ls" + end + return true + end, + }) + end, + desc = "Format buffer", + } + maps.v["<Leader>lf"] = maps.n["<Leader>lf"] + end + + if client.supports_method("textDocument/hover") then + -- TODO: Check this on 0.10.0 release + if vim.fn.has("nvim-0.10") == 0 then + maps.n["K"] = { + function() + vim.lsp.buf.hover() + end, + desc = "Hover symbol", + } + end + end + + if client.supports_method("textDocument/inlayHint") then + if vim.lsp.inlay_hint then + maps.n["<Leader>u"] = { desc = icons.Gear .. " Utility" } + -- TODO: Check this on 0.10.0 release + maps.n["<Leader>uH"] = { + function() + vim.b[bufnr].inlay_hints_enabled = not vim.b[bufnr].inlay_hints_enabled + if vim.lsp.inlay_hint then + vim.lsp.inlay_hint.enable(bufnr, vim.b[bufnr].inlay_hints_enabled) + end + end, + desc = "Toggle inlay hints", + } + end + end + + if client.supports_method("textDocument/signatureHelp") then + maps.n["<Leader>lh"] = { + function() + vim.lsp.buf.signature_help() + end, + desc = "Signature help", + } + end + + if f.is_available("telescope.nvim") then + if maps.n.gd then + maps.n.gd[1] = function() + require("telescope.builtin").lsp_definitions() + end + end + if maps.n.gI then + maps.n.gI[1] = function() + require("telescope.builtin").lsp_implementations() + end + end + if maps.n.gr then + maps.n.gr[1] = function() + require("telescope.builtin").lsp_references() + end + end + if maps.n["<Leader>lR"] then + maps.n["<Leader>lR"][1] = function() + require("telescope.builtin").lsp_references() + end + end + if maps.n.gy then + maps.n.gy[1] = function() + require("telescope.builtin").lsp_type_definitions() + end + end + if maps.n["<Leader>lG"] then + maps.n["<Leader>lG"][1] = function() + vim.ui.input({ prompt = "Symbol Query: (leave empty for word under cursor)" }, function(query) + if query then + -- word under cursor if given query is empty + if query == "" then + query = vim.fn.expand("<cword>") + end + require("telescope.builtin").lsp_workspace_symbols({ + query = query, + prompt_title = ("Find word (%s)"):format(query), + }) + end + end) + end + end + end + + if not vim.tbl_isempty(maps.v) then + if maps.v["<Leader>la"] or maps.v["<Leader>lf"] then + maps.v["<Leader>l"] = { desc = icons.Code .. " LSP" } + end + end + + return maps +end + M.surround = { insert = false, insert_line = false, @@ -769,4 +1044,174 @@ M.aerial = { ["]]"] = false, } +M.treesitter = { + select = { + ["ak"] = { query = "@block.outer", desc = "around block" }, + ["ik"] = { query = "@block.inner", desc = "inside block" }, + ["ac"] = { query = "@class.outer", desc = "around class" }, + ["ic"] = { query = "@class.inner", desc = "inside class" }, + ["a?"] = { query = "@conditional.outer", desc = "around conditional" }, + ["i?"] = { query = "@conditional.inner", desc = "inside conditional" }, + ["af"] = { query = "@function.outer", desc = "around function " }, + ["if"] = { query = "@function.inner", desc = "inside function " }, + ["al"] = { query = "@loop.outer", desc = "around loop" }, + ["il"] = { query = "@loop.inner", desc = "inside loop" }, + ["aa"] = { query = "@parameter.outer", desc = "around argument" }, + ["ia"] = { query = "@parameter.inner", desc = "inside argument" }, + }, + move = { + goto_next_start = { + ["]k"] = { query = "@block.outer", desc = "Next block start" }, + ["]f"] = { query = "@function.outer", desc = "Next function start" }, + ["]a"] = { query = "@parameter.inner", desc = "Next argument start" }, + }, + goto_next_end = { + ["]K"] = { query = "@block.outer", desc = "Next block end" }, + ["]F"] = { query = "@function.outer", desc = "Next function end" }, + ["]A"] = { query = "@parameter.inner", desc = "Next argument end" }, + }, + goto_previous_start = { + ["[k"] = { query = "@block.outer", desc = "Previous block start" }, + ["[f"] = { query = "@function.outer", desc = "Previous function start" }, + ["[a"] = { query = "@parameter.inner", desc = "Previous argument start" }, + }, + goto_previous_end = { + ["[K"] = { query = "@block.outer", desc = "Previous block end" }, + ["[F"] = { query = "@function.outer", desc = "Previous function end" }, + ["[A"] = { query = "@parameter.inner", desc = "Previous argument end" }, + }, + }, + swap = { + -- TODO: Move to config.keymaps + swap_next = { + [">K"] = { query = "@block.outer", desc = "Swap next block" }, + [">F"] = { query = "@function.outer", desc = "Swap next function" }, + [">A"] = { query = "@parameter.inner", desc = "Swap next argument" }, + }, + -- TODO: Move to config.keymaps + swap_previous = { + ["<K"] = { query = "@block.outer", desc = "Swap previous block" }, + ["<F"] = { query = "@function.outer", desc = "Swap previous function" }, + ["<A"] = { query = "@parameter.inner", desc = "Swap previous argument" }, + }, + }, +} +M.telescope = function(actions) + return { + i = { + ["<C-n>"] = actions.cycle_history_next, + ["<C-p>"] = actions.cycle_history_prev, + ["<C-c>"] = actions.close, + ["<Down>"] = actions.move_selection_next, + ["<Up>"] = actions.move_selection_previous, + ["<CR>"] = actions.select_default, + ["<C-x>"] = actions.select_horizontal, + ["<C-v>"] = actions.select_vertical, + ["<C-t>"] = actions.select_tab, + ["<C-u>"] = actions.preview_scrolling_up, + ["<C-d>"] = actions.preview_scrolling_down, + ["<C-f>"] = actions.preview_scrolling_left, + ["<C-k>"] = actions.preview_scrolling_right, + ["<PageUp>"] = actions.results_scrolling_up, + ["<PageDown>"] = actions.results_scrolling_down, + ["<M-f>"] = actions.results_scrolling_left, + ["<M-k>"] = actions.results_scrolling_right, + ["<Tab>"] = actions.toggle_selection + actions.move_selection_worse, + ["<S-Tab>"] = actions.toggle_selection + actions.move_selection_better, + ["<C-q>"] = actions.send_to_qflist + actions.open_qflist, + ["<M-q>"] = actions.send_selected_to_qflist + actions.open_qflist, + ["<C-l>"] = actions.complete_tag, + ["<C-/>"] = actions.which_key, + ["<C-_>"] = actions.which_key, -- keys from pressing <C-/> + ["<C-w>"] = { "<c-s-w>", type = "command" }, + ["<C-r><C-w>"] = actions.insert_original_cword, + ["<C-j>"] = actions.nop, + }, + n = { + ["<esc>"] = actions.close, + ["q"] = actions.close, + ["<CR>"] = actions.select_default, + ["<C-x>"] = actions.select_horizontal, + ["<C-v>"] = actions.select_vertical, + ["<C-t>"] = actions.select_tab, + ["<Tab>"] = actions.toggle_selection + actions.move_selection_worse, + ["<S-Tab>"] = actions.toggle_selection + actions.move_selection_better, + ["<C-q>"] = actions.send_to_qflist + actions.open_qflist, + ["<M-q>"] = actions.send_selected_to_qflist + actions.open_qflist, + ["j"] = actions.move_selection_next, + ["k"] = actions.move_selection_previous, + ["H"] = actions.move_to_top, + ["M"] = actions.move_to_middle, + ["L"] = actions.move_to_bottom, + ["<Down>"] = actions.move_selection_next, + ["<Up>"] = actions.move_selection_previous, + ["gg"] = actions.move_to_top, + ["G"] = actions.move_to_bottom, + ["<C-u>"] = actions.preview_scrolling_up, + ["<C-d>"] = actions.preview_scrolling_down, + ["<C-f>"] = actions.preview_scrolling_left, + ["<C-k>"] = actions.preview_scrolling_right, + ["<PageUp>"] = actions.results_scrolling_up, + ["<PageDown>"] = actions.results_scrolling_down, + ["<M-f>"] = actions.results_scrolling_left, + ["<M-k>"] = actions.results_scrolling_right, + ["?"] = actions.which_key, + }, + } +end + +M.cmp = { + ["<Up>"] = require("cmp").mapping.select_prev_item({ behavior = require("cmp").SelectBehavior.Select }), + ["<Down>"] = require("cmp").mapping.select_next_item({ behavior = require("cmp").SelectBehavior.Select }), + ["<C-p>"] = require("cmp").mapping.select_prev_item({ behavior = require("cmp").SelectBehavior.Insert }), + ["<C-n>"] = require("cmp").mapping.select_next_item({ behavior = require("cmp").SelectBehavior.Insert }), + ["<C-k>"] = require("cmp").mapping.select_prev_item({ behavior = require("cmp").SelectBehavior.Insert }), + ["<C-j>"] = require("cmp").mapping.select_next_item({ behavior = require("cmp").SelectBehavior.Insert }), + ["<C-u>"] = require("cmp").mapping(require("cmp").mapping.scroll_docs(-4), { "i", "c" }), + ["<C-d>"] = require("cmp").mapping(require("cmp").mapping.scroll_docs(4), { "i", "c" }), + ["<C-Space>"] = require("cmp").mapping(require("cmp").mapping.complete(), { "i", "c" }), + ["<C-y>"] = require("cmp").config.disable, + ["<C-e>"] = require("cmp").mapping({ i = require("cmp").mapping.abort(), c = require("cmp").mapping.close() }), + ["<CR>"] = require("cmp").mapping.confirm({ select = false }), + ["<Tab>"] = require("cmp").mapping(function(fallback) + local function has_words_before() + local line, col = (unpack or table.unpack)(vim.api.nvim_win_get_cursor(0)) + return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil + end + if require("cmp").visible() then + require("cmp").select_next_item() + elseif require("luasnip").expand_or_locally_jumpable() then + require("luasnip").expand_or_jump() + elseif has_words_before() then + require("cmp").complete() + else + fallback() + end + end, { "i", "s" }), + ["<S-Tab>"] = require("cmp").mapping( + function(fallback) + if require("cmp").visible() then + require("cmp").select_prev_item() + elseif require("luasnip").jumpable(-1) then + require("luasnip").jump(-1) + else + fallback() + end + end, + { "i", "s" } + ), +} + +M.ufo = { + scrollB = "<C-b>", + scrollF = "<C-f>", + scrollU = "<C-u>", + scrollD = "<C-d>", +} + +M.tabnine = { + accept_keymap = "<Tab>", + dismiss_keymap = "<C-]>", +} + return M diff --git a/.config/nvim/lua/funcs.lua b/.config/nvim/lua/funcs.lua index 48b564af..efeca7fd 100644 --- a/.config/nvim/lua/funcs.lua +++ b/.config/nvim/lua/funcs.lua @@ -1,5 +1,52 @@ local M = {} -local icons = require("config.icons") + +function M.lsp_on_attach(client, bufnr) + -- TODO: Check this on 0.10.0 release + if client.supports_method("textDocument/semanticTokens/full") and vim.lsp.semantic_tokens then + vim.b[bufnr].semantic_tokens_enabled = true + end + + if client.supports_method("textDocument/documentHighlight") then + M.add_buffer_autocmd("lsp_document_highlight", bufnr, { + { + events = { "CursorHold", "CursorHoldI" }, + desc = "highlight references when cursor holds", + callback = function() + if not M.has_capability("textDocument/documentHighlight", { bufnr = bufnr }) then + M.del_buffer_autocmd("lsp_document_highlight", bufnr) + return + end + vim.lsp.buf.document_highlight() + end, + }, + { + events = { "CursorMoved", "CursorMovedI", "BufLeave" }, + desc = "clear references when cursor moves", + callback = function() + vim.lsp.buf.clear_references() + end, + }, + }) + end + + if client.supports_method("textDocument/inlayHint") then + if vim.b[bufnr].inlay_hints_enabled == nil then + vim.b[bufnr].inlay_hints_enabled = true + end + -- TODO: Check this on 0.10.0 release + if vim.lsp.inlay_hint and vim.b[bufnr].inlay_hints_enabled then + vim.lsp.inlay_hint.enable(bufnr, true) + end + end + + -- TODO: Check this on 0.10.0 release + if vim.lsp.inlay_hint and vim.b[bufnr].inlay_hints_enabled then + vim.lsp.inlay_hint.enable(bufnr, true) + end + + local maps = require("config.keymaps").lsp_maps(client, bufnr) + M.set_maps(maps, { buffer = bufnr }) +end function M.set_title() local title = " %t" @@ -213,7 +260,7 @@ function M.set_maps(map_table, base) end end -local function del_buffer_autocmd(augroup, bufnr) +function M.del_buffer_autocmd(augroup, bufnr) local cmds_found, cmds = pcall(vim.api.nvim_get_autocmds, { group = augroup, buffer = bufnr }) if cmds_found then vim.tbl_map(function(cmd) @@ -222,7 +269,7 @@ local function del_buffer_autocmd(augroup, bufnr) end end -local function add_buffer_autocmd(augroup, bufnr, autocmds) +function M.add_buffer_autocmd(augroup, bufnr, autocmds) if not vim.tbl_islist(autocmds) then autocmds = { autocmds } end @@ -239,7 +286,7 @@ local function add_buffer_autocmd(augroup, bufnr, autocmds) end end -local function has_capability(capability, filter) +function M.has_capability(capability, filter) for _, client in ipairs(vim.lsp.get_active_clients(filter)) do if client.supports_method(capability) then return true @@ -248,311 +295,11 @@ local function has_capability(capability, filter) return false end --- NOTE: LSP Keymaps here --- TODO: Move to config.keymaps -function M.lsp_on_attach(client, bufnr) - local lsp_mappings = M.empty_map_table() - - lsp_mappings.n["<Leader>ld"] = { - function() - vim.diagnostic.open_float() - end, - desc = "Hover diagnostics", - } - lsp_mappings.n["[d"] = { - function() - vim.diagnostic.goto_prev() - end, - desc = "Previous diagnostic", - } - lsp_mappings.n["]d"] = { - function() - vim.diagnostic.goto_next() - end, - desc = "Next diagnostic", - } - lsp_mappings.n["gl"] = { - function() - vim.diagnostic.open_float() - end, - desc = "Hover diagnostics", - } - - if M.is_available("telescope.nvim") then - lsp_mappings.n["<Leader>lD"] = { - function() - require("telescope.builtin").diagnostics() - end, - desc = "Search diagnostics", - } +function M.diagnostic_setup(conf) + for _, sign in ipairs(conf.signs) do + vim.fn.sign_define(sign.name, sign) end - - if M.is_available("mason-lspconfig.nvim") then - lsp_mappings.n["<Leader>li"] = { "<cmd>LspInfo<cr>", desc = "LSP information" } - end - - if M.is_available("none-ls.nvim") then - lsp_mappings.n["<Leader>lI"] = { "<cmd>NullLsInfo<cr>", desc = "Null-ls information" } - end - - if client.supports_method("textDocument/codeAction") then - lsp_mappings.n["<Leader>la"] = { - function() - vim.lsp.buf.code_action() - end, - desc = "Code action", - } - lsp_mappings.v["<Leader>la"] = lsp_mappings.n["<Leader>la"] - end - - if client.supports_method("textDocument/codeLens") then - vim.lsp.codelens.refresh() - lsp_mappings.n["<Leader>ll"] = { - function() - vim.lsp.codelens.refresh() - end, - desc = "Refresh CodeLens", - } - lsp_mappings.n["<Leader>lL"] = { - function() - vim.lsp.codelens.run() - end, - desc = "Run CodeLens", - } - lsp_mappings.n["<Leader>u"] = { desc = icons.Gear .. " Utility" } - lsp_mappings.n["<Leader>uL"] = { - function() - vim.lsp.codelens.clear() - end, - desc = "Toggle CodeLens", - } - end - - if client.supports_method("textDocument/definition") then - lsp_mappings.n["gd"] = { - function() - vim.lsp.buf.definition() - end, - desc = "Go to definition", - } - end - - if client.supports_method("textDocument/typeDefinition") then - lsp_mappings.n["gy"] = { - function() - vim.lsp.buf.type_definition() - end, - desc = "Go to type definition", - } - end - - if client.supports_method("textDocument/declaration") then - lsp_mappings.n["gD"] = { - function() - vim.lsp.buf.declaration() - end, - desc = "Go to declaration", - } - end - - if client.supports_method("textDocument/implementation") then - lsp_mappings.n["gI"] = { - function() - vim.lsp.buf.implementation() - end, - desc = "List implementations", - } - end - - if client.supports_method("textDocument/references") then - lsp_mappings.n["gr"] = { - function() - vim.lsp.buf.references() - end, - desc = "List references", - } - end - - if client.supports_method("workspace/symbol") then - lsp_mappings.n["<Leader>lG"] = { - function() - vim.lsp.buf.workspace_symbol() - end, - desc = "List symbols", - } - end - - if client.supports_method("textDocument/rename") then - lsp_mappings.n["<Leader>lr"] = { - function() - vim.lsp.buf.rename() - end, - desc = "Rename symbol", - } - end - - -- TODO: Check this on 0.10.0 release - if client.supports_method("textDocument/semanticTokens/full") and vim.lsp.semantic_tokens then - vim.b[bufnr].semantic_tokens_enabled = true - lsp_mappings.n["<Leader>u"] = { desc = icons.Gear .. " Utility" } - lsp_mappings.n["<Leader>uY"] = { - function() - vim.b[bufnr].semantic_tokens_enabled = not vim.b[bufnr].semantic_tokens_enabled - for _, active_client in ipairs(vim.lsp.get_active_clients({ bufnr = bufnr })) do - if active_client.server_capabilities.semanticTokensProvider then - vim.lsp.semantic_tokens[vim.b[bufnr].semantic_tokens_enabled and "start" or "stop"]( - bufnr, - active_client.id - ) - end - end - end, - desc = "Toggle LSP semantic highlight (buffer)", - } - end - - if client.supports_method("textDocument/formatting") then - lsp_mappings.n["<Leader>lf"] = { - function() - vim.lsp.buf.format({ - filter = function(c) - local filetype = vim.bo.filetype - local n = require("null-ls") - local s = require("null-ls.sources") - local method = n.methods.FORMATTING - local available_formatters = s.get_available(filetype, method) - if #available_formatters > 0 then - return c.name == "null-ls" - end - return true - end, - }) - end, - desc = "Format buffer", - } - lsp_mappings.v["<Leader>lf"] = lsp_mappings.n["<Leader>lf"] - end - - if client.supports_method("textDocument/documentHighlight") then - add_buffer_autocmd("lsp_document_highlight", bufnr, { - { - events = { "CursorHold", "CursorHoldI" }, - desc = "highlight references when cursor holds", - callback = function() - if not has_capability("textDocument/documentHighlight", { bufnr = bufnr }) then - del_buffer_autocmd("lsp_document_highlight", bufnr) - return - end - vim.lsp.buf.document_highlight() - end, - }, - { - events = { "CursorMoved", "CursorMovedI", "BufLeave" }, - desc = "clear references when cursor moves", - callback = function() - vim.lsp.buf.clear_references() - end, - }, - }) - end - - if client.supports_method("textDocument/hover") then - -- TODO: Check this on 0.10.0 release - if vim.fn.has("nvim-0.10") == 0 then - lsp_mappings.n["K"] = { - function() - vim.lsp.buf.hover() - end, - desc = "Hover symbol", - } - end - end - - if client.supports_method("textDocument/inlayHint") then - if vim.b.inlay_hints_enabled == nil then - vim.b.inlay_hints_enabled = true - end - -- TODO: Check this on 0.10.0 release - if vim.lsp.inlay_hint then - if vim.b.inlay_hints_enabled then - vim.lsp.inlay_hint.enable(bufnr, true) - end - lsp_mappings.n["<Leader>u"] = { desc = icons.Gear .. " Utility" } - lsp_mappings.n["<Leader>uH"] = { - function() - vim.b[bufnr].inlay_hints_enabled = not vim.b[bufnr].inlay_hints_enabled - if vim.lsp.inlay_hint then - vim.lsp.inlay_hint.enable(bufnr, vim.b[bufnr].inlay_hints_enabled) - end - end, - desc = "Toggle inlay hints", - } - end - end - - if client.supports_method("textDocument/signatureHelp") then - lsp_mappings.n["<Leader>lh"] = { - function() - vim.lsp.buf.signature_help() - end, - desc = "Signature help", - } - end - - if M.is_available("telescope.nvim") then - if lsp_mappings.n.gd then - lsp_mappings.n.gd[1] = function() - require("telescope.builtin").lsp_definitions() - end - end - if lsp_mappings.n.gI then - lsp_mappings.n.gI[1] = function() - require("telescope.builtin").lsp_implementations() - end - end - if lsp_mappings.n.gr then - lsp_mappings.n.gr[1] = function() - require("telescope.builtin").lsp_references() - end - end - if lsp_mappings.n["<Leader>lR"] then - lsp_mappings.n["<Leader>lR"][1] = function() - require("telescope.builtin").lsp_references() - end - end - if lsp_mappings.n.gy then - lsp_mappings.n.gy[1] = function() - require("telescope.builtin").lsp_type_definitions() - end - end - if lsp_mappings.n["<Leader>lG"] then - lsp_mappings.n["<Leader>lG"][1] = function() - vim.ui.input({ prompt = "Symbol Query: (leave empty for word under cursor)" }, function(query) - if query then - -- word under cursor if given query is empty - if query == "" then - query = vim.fn.expand("<cword>") - end - require("telescope.builtin").lsp_workspace_symbols({ - query = query, - prompt_title = ("Find word (%s)"):format(query), - }) - end - end) - end - end - end - - if not vim.tbl_isempty(lsp_mappings.v) then - if lsp_mappings.v["<Leader>l"] then - lsp_mappings.v["<Leader>l"] = { desc = icons.Code .. " LSP" } - end - if lsp_mappings.v["<Leader>u"] then - lsp_mappings.v["<Leader>u"] = { desc = icons.Code .. " LSP" } - end - end - - M.set_maps(lsp_mappings, { buffer = bufnr }) + vim.diagnostic.config(conf.diagnostic) end function M.has_value(table, value) diff --git a/.config/nvim/lua/plugins/cmp/cmp.lua b/.config/nvim/lua/plugins/cmp/cmp.lua index 523e1a1a..0b6edb52 100644 --- a/.config/nvim/lua/plugins/cmp/cmp.lua +++ b/.config/nvim/lua/plugins/cmp/cmp.lua @@ -22,11 +22,6 @@ M.opts = function() winhighlight = "Normal:NormalFloat,FloatBorder:FloatBorder,CursorLine:PmenuSel,Search:None", } - local function has_words_before() - local line, col = (unpack or table.unpack)(vim.api.nvim_win_get_cursor(0)) - return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil - end - return { enabled = function() local dap_prompt = require("funcs").is_available("cmp-dap") @@ -64,41 +59,7 @@ M.opts = function() completion = cmp.config.window.bordered(border_opts), documentation = cmp.config.window.bordered(border_opts), }, - -- TODO: Move to config.keymaps - mapping = { - ["<Up>"] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Select }), - ["<Down>"] = cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Select }), - ["<C-p>"] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Insert }), - ["<C-n>"] = cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Insert }), - ["<C-k>"] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Insert }), - ["<C-j>"] = cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Insert }), - ["<C-u>"] = cmp.mapping(cmp.mapping.scroll_docs(-4), { "i", "c" }), - ["<C-d>"] = cmp.mapping(cmp.mapping.scroll_docs(4), { "i", "c" }), - ["<C-Space>"] = cmp.mapping(cmp.mapping.complete(), { "i", "c" }), - ["<C-y>"] = cmp.config.disable, - ["<C-e>"] = cmp.mapping({ i = cmp.mapping.abort(), c = cmp.mapping.close() }), - ["<CR>"] = cmp.mapping.confirm({ select = false }), - ["<Tab>"] = cmp.mapping(function(fallback) - if cmp.visible() then - cmp.select_next_item() - elseif luasnip.expand_or_locally_jumpable() then - luasnip.expand_or_jump() - elseif has_words_before() then - cmp.complete() - else - fallback() - end - end, { "i", "s" }), - ["<S-Tab>"] = cmp.mapping(function(fallback) - if cmp.visible() then - cmp.select_prev_item() - elseif luasnip.jumpable(-1) then - luasnip.jump(-1) - else - fallback() - end - end, { "i", "s" }), - }, + mapping = require("config.keymaps").cmp, sources = cmp.config.sources({ { name = "nvim_lsp", priority = 1000 }, { name = "luasnip", priority = 750 }, diff --git a/.config/nvim/lua/plugins/dap/dap.lua b/.config/nvim/lua/plugins/dap/dap.lua new file mode 100644 index 00000000..c567c28f --- /dev/null +++ b/.config/nvim/lua/plugins/dap/dap.lua @@ -0,0 +1,12 @@ +local icons = require("config.icons") +local signs = { + { name = "DapStopped", text = icons.DapStopped, texthl = "DiagnosticWarn" }, + { name = "DapBreakpoint", text = icons.DapBreakpoint, texthl = "DiagnosticInfo" }, + { name = "DapBreakpointRejected", text = icons.DapBreakpointRejected, texthl = "DiagnosticError" }, + { name = "DapBreakpointCondition", text = icons.DapBreakpointCondition, texthl = "DiagnosticInfo" }, + { name = "DapLogPoint", text = icons.DapLogPoint, texthl = "DiagnosticInfo" }, +} + +for _, sign in ipairs(signs) do + vim.fn.sign_define(sign.name, sign) +end diff --git a/.config/nvim/lua/plugins/lsp/mason-lspconfig.lua b/.config/nvim/lua/plugins/lsp/mason-lspconfig.lua index 856a3ab8..b82a0625 100644 --- a/.config/nvim/lua/plugins/lsp/mason-lspconfig.lua +++ b/.config/nvim/lua/plugins/lsp/mason-lspconfig.lua @@ -28,46 +28,6 @@ M.event = { "BufReadPost", "BufNewFile", "BufNew" } M.cmd = { "LspInstall", "LspUninstall" } M.config = function() - local icons = require("config.icons") - local signs = { - { name = "DiagnosticSignError", text = icons.Error, texthl = "DiagnosticSignError" }, - { name = "DiagnosticSignWarn", text = icons.Warn, texthl = "DiagnosticSignWarn" }, - { name = "DiagnosticSignHint", text = icons.Hint, texthl = "DiagnosticSignHint" }, - { name = "DiagnosticSignInfo", text = icons.Info, texthl = "DiagnosticSignInfo" }, - { name = "DapStopped", text = icons.DapStopped, texthl = "DiagnosticWarn" }, - { name = "DapBreakpoint", text = icons.DapBreakpoint, texthl = "DiagnosticInfo" }, - { name = "DapBreakpointRejected", text = icons.DapBreakpointRejected, texthl = "DiagnosticError" }, - { name = "DapBreakpointCondition", text = icons.DapBreakpointCondition, texthl = "DiagnosticInfo" }, - { name = "DapLogPoint", text = icons.DapLogPoint, texthl = "DiagnosticInfo" }, - } - for _, sign in ipairs(signs) do - vim.fn.sign_define(sign.name, sign) - end - - vim.diagnostic.config({ - virtual_text = true, - signs = { - text = { - [vim.diagnostic.severity.ERROR] = icons.Error, - [vim.diagnostic.severity.HINT] = icons.Hint, - [vim.diagnostic.severity.WARN] = icons.Warn, - [vim.diagnostic.severity.INFO] = icons.Info, - }, - active = signs, - }, - update_in_insert = true, - underline = true, - severity_sort = true, - float = { - focused = false, - style = "minimal", - border = "rounded", - source = "always", - header = "", - prefix = "", - }, - }) - vim.lsp.handlers["textDocument/hover"] = vim.lsp.with(vim.lsp.handlers.hover, { border = "rounded", silent = true }) vim.lsp.handlers["textDocument/signatureHelp"] = vim.lsp.with(vim.lsp.handlers.signature_help, { border = "rounded", silent = true }) diff --git a/.config/nvim/lua/plugins/misc/tabnine.lua b/.config/nvim/lua/plugins/misc/tabnine.lua index 439de931..1f4be3c8 100644 --- a/.config/nvim/lua/plugins/misc/tabnine.lua +++ b/.config/nvim/lua/plugins/misc/tabnine.lua @@ -8,10 +8,11 @@ M.main = "tabnine" M.opts = function() local colors = require("tokyonight.colors").setup({ transform = true }) + local maps = require("config.keymaps").tabnine return { disable_auto_comment = true, - accept_keymap = "<Tab>", - dismiss_keymap = "<C-]>", + accept_keymap = maps.accept_keymap, + dismiss_keymap = maps.dismiss_keymap, debounce_ms = 800, suggestion_color = { gui = colors.fg_gutter, cterm = 244 }, exclude_filetypes = { "TelescopePrompt", "NvimTree" }, diff --git a/.config/nvim/lua/plugins/misc/telescope.lua b/.config/nvim/lua/plugins/misc/telescope.lua index 78350c9b..f6daa886 100644 --- a/.config/nvim/lua/plugins/misc/telescope.lua +++ b/.config/nvim/lua/plugins/misc/telescope.lua @@ -1,12 +1,11 @@ local M = { "nvim-telescope/telescope.nvim" } local icons = require("config.icons") -M.dependencies = { "telescope-fzf-native.nvim" } +M.dependencies = { "telescope-fzf-native.nvim", "aerial.nvim" } M.cmd = "Telescope" -local opts = function() - local actions = require("telescope.actions") +M.opts = function() return { defaults = { git_worktrees = vim.g.git_worktrees, @@ -20,29 +19,18 @@ local opts = function() height = 0.80, preview_cutoff = 120, }, - -- TODO: Move to config.keymaps - mappings = { - i = { - ["<C-n>"] = actions.cycle_history_next, - ["<C-p>"] = actions.cycle_history_prev, - ["<C-j>"] = actions.move_selection_next, - ["<C-k>"] = actions.move_selection_previous, - }, - n = { q = actions.close }, - }, }, } end -M.config = function() - local telescope = require("telescope") - telescope.setup(opts()) - if pcall(require, "aerial") then - telescope.load_extension("aerial") - end - if require("funcs").is_available("telescope-fzf-native.nvim") then - telescope.load_extension("fzf") - end +M.config = function(plug, opts) + local name = require("lazy.core.loader").get_main(plug) + local m = require(name) + local actions = require(name .. ".actions") + opts.mappings = require("config.keymaps").telescope(actions) + m.setup(opts) + m.load_extension("aerial") + m.load_extension("fzf") end return M diff --git a/.config/nvim/lua/plugins/misc/treesitter.lua b/.config/nvim/lua/plugins/misc/treesitter.lua index 4e370042..fcb40a34 100644 --- a/.config/nvim/lua/plugins/misc/treesitter.lua +++ b/.config/nvim/lua/plugins/misc/treesitter.lua @@ -25,6 +25,7 @@ M.init = function(plugin) require("nvim-treesitter.query_predicates") end +local maps = require("config.keymaps").treesitter M.opts = { ensure_installed = { "lua", "yaml", "json", "bash" }, autotag = { enable = true }, @@ -41,64 +42,20 @@ M.opts = { select = { enable = true, lookahead = true, - -- TODO: Move to config.keymaps - keymaps = { - ["ak"] = { query = "@block.outer", desc = "around block" }, - ["ik"] = { query = "@block.inner", desc = "inside block" }, - ["ac"] = { query = "@class.outer", desc = "around class" }, - ["ic"] = { query = "@class.inner", desc = "inside class" }, - ["a?"] = { query = "@conditional.outer", desc = "around conditional" }, - ["i?"] = { query = "@conditional.inner", desc = "inside conditional" }, - ["af"] = { query = "@function.outer", desc = "around function " }, - ["if"] = { query = "@function.inner", desc = "inside function " }, - ["al"] = { query = "@loop.outer", desc = "around loop" }, - ["il"] = { query = "@loop.inner", desc = "inside loop" }, - ["aa"] = { query = "@parameter.outer", desc = "around argument" }, - ["ia"] = { query = "@parameter.inner", desc = "inside argument" }, - }, + keymaps = maps.select, }, move = { enable = true, set_jumps = true, - -- TODO: Move to config.keymaps - goto_next_start = { - ["]k"] = { query = "@block.outer", desc = "Next block start" }, - ["]f"] = { query = "@function.outer", desc = "Next function start" }, - ["]a"] = { query = "@parameter.inner", desc = "Next argument start" }, - }, - -- TODO: Move to config.keymaps - goto_next_end = { - ["]K"] = { query = "@block.outer", desc = "Next block end" }, - ["]F"] = { query = "@function.outer", desc = "Next function end" }, - ["]A"] = { query = "@parameter.inner", desc = "Next argument end" }, - }, - -- TODO: Move to config.keymaps - goto_previous_start = { - ["[k"] = { query = "@block.outer", desc = "Previous block start" }, - ["[f"] = { query = "@function.outer", desc = "Previous function start" }, - ["[a"] = { query = "@parameter.inner", desc = "Previous argument start" }, - }, - -- TODO: Move to config.keymaps - goto_previous_end = { - ["[K"] = { query = "@block.outer", desc = "Previous block end" }, - ["[F"] = { query = "@function.outer", desc = "Previous function end" }, - ["[A"] = { query = "@parameter.inner", desc = "Previous argument end" }, - }, + goto_next_start = maps.move.goto_next_start, + goto_next_end = maps.move.goto_next_end, + goto_previous_start = maps.move.goto_previous_start, + goto_previous_end = maps.move.goto_previous_end, }, swap = { enable = true, - -- TODO: Move to config.keymaps - swap_next = { - [">K"] = { query = "@block.outer", desc = "Swap next block" }, - [">F"] = { query = "@function.outer", desc = "Swap next function" }, - [">A"] = { query = "@parameter.inner", desc = "Swap next argument" }, - }, - -- TODO: Move to config.keymaps - swap_previous = { - ["<K"] = { query = "@block.outer", desc = "Swap previous block" }, - ["<F"] = { query = "@function.outer", desc = "Swap previous function" }, - ["<A"] = { query = "@parameter.inner", desc = "Swap previous argument" }, - }, + swap_next = maps.swap.swap_next, + swap_previous = maps.swap.swap_previous, }, }, } diff --git a/.config/nvim/lua/plugins/misc/ufo.lua b/.config/nvim/lua/plugins/misc/ufo.lua index 26dceccb..3121f75d 100644 --- a/.config/nvim/lua/plugins/misc/ufo.lua +++ b/.config/nvim/lua/plugins/misc/ufo.lua @@ -1,17 +1,12 @@ -local M = { "nvim-treesitter/nvim-treesitter" } +local M = { "kevinhwang91/nvim-ufo" } M.event = { "InsertEnter" } -M.dependencies = { "kevinhwang91/promise-async" } +M.dependencies = { "kevinhwang91/promise-async", "nvim-treesitter" } M.opts = { preview = { - mappings = { - scrollB = "<C-b>", - scrollF = "<C-f>", - scrollU = "<C-u>", - scrollD = "<C-d>", - }, + mappings = require("config.keymaps").ufo, }, provider_selector = function(_, filetype, buftype) local function handleFallbackException(bufnr, err, providerName)