From 9ee30af870b23ed695708b0e36d35e52b8390cba Mon Sep 17 00:00:00 2001 From: Tovi Jaeschke-Rogers Date: Tue, 26 Jul 2022 20:22:09 +0930 Subject: [PATCH] Tue 26 Jul 2022 20:22:09 ACST --- .config/nvim/lua/config/cmp.lua | 116 ++++++++++++++++++++++++++++ .config/nvim/lua/config/luasnip.lua | 14 ++++ .config/nvim/lua/lsp/init.lua | 52 +++++++++++++ .config/nvim/lua/lsp/installer.lua | 26 +++++++ .config/nvim/lua/lsp/keymaps.lua | 36 +++++++++ .config/nvim/lua/utils/init.lua | 37 +++++++++ 6 files changed, 281 insertions(+) create mode 100644 .config/nvim/lua/config/cmp.lua create mode 100644 .config/nvim/lua/config/luasnip.lua create mode 100644 .config/nvim/lua/lsp/init.lua create mode 100644 .config/nvim/lua/lsp/installer.lua create mode 100644 .config/nvim/lua/lsp/keymaps.lua create mode 100644 .config/nvim/lua/utils/init.lua diff --git a/.config/nvim/lua/config/cmp.lua b/.config/nvim/lua/config/cmp.lua new file mode 100644 index 0000000..cb2beb4 --- /dev/null +++ b/.config/nvim/lua/config/cmp.lua @@ -0,0 +1,116 @@ +local M = {} + +function M.setup() + local has_words_before = function() + local line, col = 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 + + local luasnip = require("luasnip") + local cmp = require("cmp") + + cmp.setup { + completion = { completeopt = "menu,menuone,noinsert", keyword_length = 1 }, + experimental = { native_menu = false, ghost_text = false }, + snippet = { + expand = function(args) + require("luasnip").lsp_expand(args.body) + end, + }, + formatting = { + format = function(entry, vim_item) + vim_item.menu = ({ + nvim_lsp = "[LSP]", + buffer = "[Buffer]", + luasnip = "[Snip]", + nvim_lua = "[Lua]", + treesitter = "[Treesitter]", + path = "[Path]", + })[entry.source.name] + return vim_item + end, + }, + mapping = { + [""] = cmp.mapping(cmp.mapping.select_prev_item(), { "i", "c" }), + [""] = cmp.mapping(cmp.mapping.select_next_item(), { "i", "c" }), + [""] = cmp.mapping(cmp.mapping.scroll_docs(-4), { "i", "c" }), + [""] = cmp.mapping(cmp.mapping.scroll_docs(4), { "i", "c" }), + [""] = cmp.mapping(cmp.mapping.complete(), { "i", "c" }), + [""] = cmp.mapping { i = cmp.mapping.close(), c = cmp.mapping.close() }, + [""] = cmp.mapping { + i = cmp.mapping.confirm { behavior = cmp.ConfirmBehavior.Replace, select = false }, + c = function(fallback) + if cmp.visible() then + cmp.confirm { behavior = cmp.ConfirmBehavior.Replace, select = false } + else + fallback() + end + end, + }, + [""] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_next_item() + elseif luasnip.expand_or_jumpable() then + luasnip.expand_or_jump() + elseif has_words_before() then + cmp.complete() + else + fallback() + end + end, { + "i", + "s", + "c", + }), + [""] = 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", + "c", + }), +}, +sources = { + { name = "nvim_lsp" }, + { name = "treesitter" }, + { name = "buffer" }, + { name = "luasnip" }, + { name = "nvim_lua" }, + { name = "path" }, + -- { name = "spell" }, + -- { name = "emoji" }, + -- { name = "calc" }, +}, +window = { + documentation = { + border = { "╭", "─", "╮", "│", "╯", "─", "╰", "│" }, + winhighlight = "NormalFloat:NormalFloat,FloatBorder:TelescopeBorder", + }, +}, + } + + -- Use buffer source for `/` + cmp.setup.cmdline("/", { + sources = { + { name = "buffer" }, + }, + }) + + -- Use cmdline & path source for ':' + cmp.setup.cmdline(":", { + sources = cmp.config.sources({ + { name = "path" }, + }, { + { name = "cmdline" }, + }), + }) + +end + +return M diff --git a/.config/nvim/lua/config/luasnip.lua b/.config/nvim/lua/config/luasnip.lua new file mode 100644 index 0000000..10ecf74 --- /dev/null +++ b/.config/nvim/lua/config/luasnip.lua @@ -0,0 +1,14 @@ +local M = {} + +function M.setup() + local luasnip = require "luasnip" + + luasnip.config.set_config { + history = false, + updateevents = "TextChanged,TextChangedI", + } + + require("luasnip/loaders/from_vscode").load() +end + +return M diff --git a/.config/nvim/lua/lsp/init.lua b/.config/nvim/lua/lsp/init.lua new file mode 100644 index 0000000..700b0ee --- /dev/null +++ b/.config/nvim/lua/lsp/init.lua @@ -0,0 +1,52 @@ +local M = {} + +local servers = { + gopls = {}, + html = {}, + jsonls = {}, + pyright = {}, + tsserver = {}, + vimls = {}, + dartls = {}, + dockerls = {}, + intelephense = {}, + sqlls = {}, + volar = {}, +} + +local function on_attach(client, bufnr) + -- Enable completion triggered by + -- See `:help omnifunc` and `:help ins-completion` for more information. + vim.api.nvim_buf_set_option(bufnr, "omnifunc", "v:lua.vim.lsp.omnifunc") + + -- Use LSP as the handler for formatexpr. + -- See `:help formatexpr` for more information. + vim.api.nvim_buf_set_option(0, "formatexpr", "v:lua.vim.lsp.formatexpr()") + + -- Configure key mappings + require("lsp.keymaps").setup(client, bufnr) +end + +local lsp_signature = require "lsp_signature" +lsp_signature.setup { + bind = true, + handler_opts = { + border = "rounded", + }, +} + +local capabilities = require("cmp_nvim_lsp").update_capabilities(vim.lsp.protocol.make_client_capabilities()) + +local opts = { + on_attach = on_attach, + capabilities = cababilities, + flags = { + debounce_text_changes = 150, + }, +} + +function M.setup() + require("lsp.installer").setup(servers, opts) +end + +return M diff --git a/.config/nvim/lua/lsp/installer.lua b/.config/nvim/lua/lsp/installer.lua new file mode 100644 index 0000000..012eb69 --- /dev/null +++ b/.config/nvim/lua/lsp/installer.lua @@ -0,0 +1,26 @@ +local lsp_installer_servers = require "nvim-lsp-installer.servers" +local utils = require "utils" + +local M = {} + +function M.setup(servers, options) + for server_name, _ in pairs(servers) do + local server_available, server = lsp_installer_servers.get_server(server_name) + + if server_available then + server:on_ready(function() + local opts = vim.tbl_deep_extend("force", options, servers[server.name] or {}) + server:setup(opts) + end) + + if not server:is_installed() then + utils.info("Installing " .. server.name) + server:install() + end + else + utils.error(server) + end + end +end + +return M diff --git a/.config/nvim/lua/lsp/keymaps.lua b/.config/nvim/lua/lsp/keymaps.lua new file mode 100644 index 0000000..1a641f0 --- /dev/null +++ b/.config/nvim/lua/lsp/keymaps.lua @@ -0,0 +1,36 @@ +local M = {} + +local keymap = vim.api.nvim_set_keymap +local buf_keymap = vim.api.nvim_buf_set_keymap + +local function keymappings(client, bufnr) + local opts = { noremap = true, silent = true } + + -- Key mappings + vim.keymap.set("n", "K", vim.lsp.buf.hover, opts) + vim.keymap.set("n", "[d", vim.diagnostic.goto_prev, opts) + vim.keymap.set("n", "]d", vim.diagnostic.goto_next, opts) + vim.keymap.set("n", "[e", function () vim.diagnostic.goto_prev({severity = vim.diagnostic.severity.ERROR}) end, opts) + vim.keymap.set("n", "]e", function () vim.diagnostic.goto_next({severity = vim.diagnostic.severity.ERROR}) end, opts) + + vim.keymap.set("n", "rn", vim.lsp.buf.rename, opts) + vim.keymap.set("n", "K", vim.lsp.buf.code_action, opts) + vim.keymap.set("n", "of", vim.diagnostic.open_float, opts) + + if client.resolved_capabilities.document_formatting then + vim.keymap.set("n", "ff", vim.lsp.buf.formatting, opts) + end + + vim.keymap.set("n", "d", vim.lsp.buf.definition, opts) + vim.keymap.set("n", "D", vim.lsp.buf.declaration, opts) + vim.keymap.set("n", "h", vim.lsp.buf.signature_help, opts) + vim.keymap.set("n", "i", vim.lsp.buf.implementation, opts) + vim.keymap.set("n", "T", vim.lsp.buf.type_definition, opts) + +end + +function M.setup(client, bufnr) + keymappings(client, bufnr) +end + +return M diff --git a/.config/nvim/lua/utils/init.lua b/.config/nvim/lua/utils/init.lua new file mode 100644 index 0000000..03897f8 --- /dev/null +++ b/.config/nvim/lua/utils/init.lua @@ -0,0 +1,37 @@ +_G.dump = function(...) + print(vim.inspect(...)) +end + +_G.prequire = function(...) + local status, lib = pcall(require, ...) + if status then + return lib + end + return nil +end + +local M = {} + +function M.t(str) + return vim.api.nvim_replace_termcodes(str, true, true, true) +end + +function M.log(msg, hl, name) + name = name or "Neovim" + hl = hl or "Todo" + vim.api.nvim_echo({ { name .. ": ", hl }, { msg } }, true, {}) +end + +function M.warn(msg, name) + vim.notify(msg, vim.log.levels.WARN, { title = name }) +end + +function M.error(msg, name) + vim.notify(msg, vim.log.levels.ERROR, { title = name }) +end + +function M.info(msg, name) + vim.notify(msg, vim.log.levels.INFO, { title = name }) +end + +return M