diff --git a/flake.nix b/flake.nix index ddbb493..eda7cf3 100644 --- a/flake.nix +++ b/flake.nix @@ -62,6 +62,7 @@ "nvim_plugin-tpope/vim-sleuth" = vim-sleuth; "nvim_plugin-mfussenegger/nvim-lint" = nvim-lint; "nvim_plugin-stevearc/conform.nvim" = conform-nvim; + "nvim_plugin-neovim/nvim-lspconfig" = nvim-lspconfig; }; # This will be how we put any nix related stuff into our lua config luaNixGlobal = "NIX=" + lib.generators.toLua { multiline = false; indent = false; } ({ @@ -92,6 +93,10 @@ # formatters stylua nodePackages.prettier + # LSPs + lua-language-server + nodePackages.typescript-language-server + # curl # http requests TODO # nodePackages.cspell TODO ]; diff --git a/init.lua b/init.lua index b221cb9..6a947c4 100644 --- a/init.lua +++ b/init.lua @@ -44,6 +44,9 @@ local function getSpec() -- Convert plugins to use nix store, this auto sets the `dir` property for us on all plugins. function convertPluginToNixStore(plugin) local p = ensure_table(plugin) + if p.enabled == false then + return plugin + end local nixName = "nvim_plugin-" .. p[1] if not NIX.pluginPaths[nixName] then error("Plugin is missing in the nix store, ensure it is in the nix flake inputs: " .. p[1]) diff --git a/lua/plugins/editor_noice.lua b/lua/plugins/editor_noice.lua index 76622e5..9c54035 100644 --- a/lua/plugins/editor_noice.lua +++ b/lua/plugins/editor_noice.lua @@ -1,7 +1,16 @@ return { "folke/noice.nvim", + dependencies = { + "MunifTanjim/nui.nvim", + "rcarriga/nvim-notify", + { "nvim-telescope/telescope.nvim", optional = true }, + }, event = "VeryLazy", opts = { + routes = { + -- I want telescope-ui-select to trigger here not noice + { filter = { event = "lsp", kind = "search_count" }, opts = { skip = true } }, + }, messages = { view = "mini", -- default view for messages view_error = "notify", -- view for errors @@ -20,13 +29,8 @@ return { }, config = function(_, opts) require("noice").setup(opts) + U.safeRequire("telescope", function(t) + t.load_extension("noice") + end) end, - dependencies = { - -- if you lazy-load any plugin below, make sure to add proper `module="..."` entries - "MunifTanjim/nui.nvim", - -- OPTIONAL: - -- `nvim-notify` is only needed, if you want to use the notification view. - -- If not available, we use `mini` as the fallback - "rcarriga/nvim-notify", - }, } diff --git a/lua/plugins/lsp.lua b/lua/plugins/lsp.lua new file mode 100644 index 0000000..18cc4c1 --- /dev/null +++ b/lua/plugins/lsp.lua @@ -0,0 +1,139 @@ +return { + "neovim/nvim-lspconfig", + event = "BufEnter", + dependencies = { + -- Automatically install LSPs and related tools to stdpath for Neovim + { "williamboman/mason.nvim", enabled = not NIX, config = true }, -- NOTE: Must be loaded before dependants + { "williamboman/mason-lspconfig.nvim", enabled = not NIX }, + { "WhoIsSethDaniel/mason-tool-installer.nvim", enabled = not NIX }, + + -- Useful status updates for LSP. + -- NOTE: `opts = {}` is the same as calling `require('fidget').setup({})` + -- { "j-hui/fidget.nvim", opts = {} }, + + -- `neodev` configures Lua LSP for your Neovim config, runtime and plugins + -- used for completion, annotations and signatures of Neovim apis + -- { "folke/neodev.nvim", opts = {} }, + }, + config = function() + vim.api.nvim_create_autocmd("LspAttach", { + group = vim.api.nvim_create_augroup("myconfig-lsp-attach", { clear = true }), + callback = function(event) + local map = function(keys, func, desc) + vim.keymap.set("n", keys, func, { buffer = event.buf, desc = "LSP: " .. desc }) + end + map("gd", require("telescope.builtin").lsp_definitions, "Goto Definition") + map("gr", require("telescope.builtin").lsp_references, "Goto References") + map("gI", require("telescope.builtin").lsp_implementations, "Goto Implementation") + -- TODO do I want these? + -- map("D", require("telescope.builtin").lsp_type_definitions, "Type Definition") + -- map("ds", require("telescope.builtin").lsp_document_symbols, "Document Symbols") + -- map("ws", require("telescope.builtin").lsp_dynamic_workspace_symbols, "Workspace Symbols") + map("lr", vim.lsp.buf.rename, "Rename") + map("la", vim.lsp.buf.code_action, "Code Action") + map("K", vim.lsp.buf.hover, "Hover Documentation") + map("gD", vim.lsp.buf.declaration, "Goto Declaration") + + local client = vim.lsp.get_client_by_id(event.data.client_id) + -- The following autocommand is used to enable inlay hints in your + -- code, if the language server you are using supports them + -- + -- This may be unwanted, since they displace some of your code + if client and client.server_capabilities.inlayHintProvider and vim.lsp.inlay_hint then + map("lth", function() + vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled()) + end, "Toggle Inlay Hints") + end + end, + }) + + vim.api.nvim_create_autocmd("LspDetach", { + group = vim.api.nvim_create_augroup("myconfig-lsp-detach", { clear = true }), + callback = function(event) + vim.lsp.buf.clear_references() + vim.api.nvim_clear_autocmds({ group = "myconfig-lsp-highlight", buffer = event.buf }) + end, + }) + + local capabilities = vim.lsp.protocol.make_client_capabilities() + -- TODO + -- capabilities = vim.tbl_deep_extend("force", capabilities, require("cmp_nvim_lsp").default_capabilities()) + + local servers = { + -- clangd = {}, + -- gopls = {}, + -- pyright = {}, + -- rust_analyzer = {}, + -- ... etc. See `:help lspconfig-all` for a list of all the pre-configured LSPs + -- + -- Some languages (like typescript) have entire language plugins that can be useful: + -- https://github.com/pmizio/typescript-tools.nvim + -- + -- But for many setups, the LSP (`tsserver`) will work just fine + tsserver = {}, + + lua_ls = { + -- cmd = { ... }, + -- filetypes = { ...}, + -- capabilities = {}, + settings = { + Lua = { + runtime = { + -- Tell the language server which version of Lua you're using + -- (most likely LuaJIT in the case of Neovim) + version = "LuaJIT", + }, + completion = { + callSnippet = "Replace", + }, + workspace = { + checkThirdParty = false, + library = { + vim.env.VIMRUNTIME, + vim.api.nvim_get_runtime_file("", true), + vim.fn.expand("$VIMRUNTIME/lua"), + vim.fn.expand("$VIMRUNTIME/lua/vim/lsp"), + }, + telemetry = { enable = false }, + diagnostics = { + globals = { + "vim", + "require", + "NIX", + "U", + -- Hammerspoon + "hs", + }, + }, + }, + -- You can toggle below to ignore Lua_LS's noisy `missing-fields` warnings + -- diagnostics = { disable = { 'missing-fields' } }, + }, + }, + }, + } + if NIX then + local servers = vim.tbl_keys(servers or {}) + for _, server_name in ipairs(servers) do + local server_opts = servers[server_name] or {} + require("lspconfig")[server_name].setup(server_opts) + end + else + require("mason").setup() + local ensure_installed = vim.tbl_keys(servers or {}) + vim.list_extend(ensure_installed, { + "stylua", -- Used to format Lua code TODO come back to this, more about linter/formatter configs + }) + require("mason-tool-installer").setup({ ensure_installed = ensure_installed }) + require("mason-lspconfig").setup({ + handlers = { + function(server_name) + local server = servers[server_name] or {} + server.capabilities = vim.tbl_deep_extend("force", {}, capabilities, server.capabilities or {}) + require("lspconfig")[server_name].setup(server) + end, + }, + }) + end + end, +}