lsp.lua (8626B)
1 -- LSP settings. 2 -- This function gets run when an LSP connects to a particular buffer. 3 local on_attach = function(_, bufnr) 4 -- Enable inlay hints for current buffer 5 vim.lsp.inlay_hint.enable(true, { bufnr = bufnr }) 6 7 -- NOTE: Remember that lua is a real programming language, and as such it is possible 8 -- to define small helper and utility functions so you don't have to repeat yourself 9 -- many times. 10 -- 11 -- In this case, we create a function that lets us more easily define mappings specific 12 -- for LSP related items. It sets the mode, buffer and description for us each time. 13 local nmap = function(keys, func, desc) 14 if desc then 15 desc = "LSP: " .. desc 16 end 17 18 vim.keymap.set("n", keys, func, { buffer = bufnr, desc = desc }) 19 end 20 21 nmap("<leader>rn", vim.lsp.buf.rename, "[R]e[n]ame") 22 nmap("<leader>ra", vim.lsp.buf.code_action, "[C]ode [A]ction") 23 vim.keymap.set("v", "<leader>ra", vim.lsp.buf.code_action, { buffer = bufnr, desc = "[C]ode [A]ction" }) 24 25 nmap("gd", vim.lsp.buf.definition, "[G]oto [D]efinition") 26 nmap("gI", vim.lsp.buf.implementation, "[G]oto [I]mplementation") 27 nmap("<leader>D", vim.lsp.buf.type_definition, "Type [D]efinition") 28 29 -- See `:help K` for why this keymap 30 nmap("K", vim.lsp.buf.hover, "Hover Documentation") 31 nmap("<leader>K", vim.lsp.buf.signature_help, "Signature Documentation") 32 33 -- Lesser used LSP functionality 34 nmap("gD", vim.lsp.buf.declaration, "[G]oto [D]eclaration") 35 nmap("<leader>wa", vim.lsp.buf.add_workspace_folder, "[W]orkspace [A]dd Folder") 36 nmap("<leader>wr", vim.lsp.buf.remove_workspace_folder, "[W]orkspace [R]emove Folder") 37 nmap("<leader>wl", function() 38 print(vim.inspect(vim.lsp.buf.list_workspace_folders())) 39 end, "[W]orkspace [L]ist Folders") 40 41 -- Create a command `:Format` local to the LSP buffer 42 vim.api.nvim_buf_create_user_command(bufnr, "Format", function(_) 43 vim.lsp.buf.format() 44 end, { desc = "Format current buffer with LSP" }) 45 46 vim.api.nvim_buf_create_user_command(bufnr, "LspInspect", function(_) 47 vim.ui.input({ prompt = "Enter LSP Client name: " }, function(client_name) 48 if client_name then 49 local client = vim.lsp.get_clients({ name = client_name }) 50 51 if #client == 0 then 52 vim.notify("No active LSP clients found with this name: " .. client_name, vim.log.levels.WARN) 53 return 54 end 55 56 -- Create a temporary buffer to show the configuration 57 local buf = vim.api.nvim_create_buf(false, true) 58 local win = vim.api.nvim_open_win(buf, true, { 59 relative = "editor", 60 width = math.floor(vim.o.columns * 0.75), 61 height = math.floor(vim.o.lines * 0.90), 62 col = math.floor(vim.o.columns * 0.125), 63 row = math.floor(vim.o.lines * 0.05), 64 style = "minimal", 65 border = "rounded", 66 title = " " .. (client_name:gsub("^%l", string.upper)) .. ": LSP Configuration ", 67 title_pos = "center", 68 }) 69 70 local lines = {} 71 for i, this_client in ipairs(client) do 72 if i > 1 then 73 table.insert(lines, string.rep("-", 80)) 74 end 75 table.insert(lines, "Client: " .. this_client.name) 76 table.insert(lines, "ID: " .. this_client.id) 77 table.insert(lines, "") 78 table.insert(lines, "Configuration:") 79 80 local config_lines = vim.split(vim.inspect(this_client.config), "\n") 81 vim.list_extend(lines, config_lines) 82 end 83 84 -- Set the lines in the buffer 85 vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines) 86 87 -- Set buffer options 88 vim.bo[buf].modifiable = false 89 vim.bo[buf].filetype = "lua" 90 vim.bo[buf].bh = "delete" 91 92 vim.api.nvim_buf_set_keymap(buf, "n", "q", ":q<CR>", { noremap = true, silent = true }) 93 end 94 end) 95 end, { desc = "Inspect LSP config" }) 96 end 97 98 -- :h lspconfig-all 99 local config = function() 100 vim.lsp.config("rust_analyzer", { 101 on_attach = on_attach, 102 settings = { 103 ["rust-analyzer"] = { 104 workspace = { 105 symbol = { 106 search = { 107 kind = "all_symbols", 108 }, 109 }, 110 }, 111 check = { 112 command = "clippy", 113 features = "all", 114 extraArgs = { 115 "--", 116 "-D", 117 "clippy::pedantic", 118 "-D", 119 "clippy::nursery", 120 "-D", 121 "clippy::restriction", 122 "-A", 123 "clippy::blanket_clippy_restriction_lints", 124 "-A", 125 "clippy::missing_docs_in_private_items", 126 "-A", 127 "clippy::implicit_return", 128 "-A", 129 "clippy::question_mark_used", 130 "-A", 131 "clippy::min_ident_chars", 132 "-A", 133 "clippy::pattern_type_mismatch", 134 "-A", 135 "clippy::single_call_fn", 136 "-A", 137 "clippy::as_conversions", 138 "-A", 139 "clippy::pub_with_shorthand", 140 "-A", 141 "clippy::shadow_reuse", 142 "-A", 143 "clippy::separated_literal_suffix", 144 "-A", 145 "clippy::float_arithmetic", 146 "-A", 147 "clippy::pub_use", 148 "-A", 149 "clippy::single_char_lifetime_names", 150 "-A", 151 "clippy::missing_trait_methods", 152 "-A", 153 "clippy::mod_module_files", 154 "-A", 155 "clippy::std_instead_of_alloc", 156 "-A", 157 "clippy::integer_division_remainder_used", 158 "-D", 159 "rust_2018_idioms", 160 "-D", 161 "missing_docs", 162 "-D", 163 "warnings", 164 "-A", 165 "clippy::too_many_lines", 166 "-A", 167 "clippy::arbitrary_source_item_ordering", 168 "-A", 169 "clippy::redundant_test_prefix", 170 }, 171 }, 172 }, 173 }, 174 }) 175 vim.lsp.enable("rust_analyzer") 176 177 vim.lsp.config("bacon_ls", { 178 on_attach = on_attach, 179 init_options = { 180 updateOnSave = true, 181 updateOnSaveWaitMillis = 3000, 182 updateOnChange = true, 183 }, 184 }) 185 --[[ 186 Some issues I found: 187 - bacon-ls kept running after vim closed 188 - diagnostics did not update, the old ones showed, I had to :e to refresh 189 --]] 190 -- vim.lsp.enable('bacon_ls') 191 192 vim.lsp.config("yamlls", { on_attach = on_attach }) 193 vim.lsp.enable("yamlls") 194 195 vim.lsp.config("nixd", { on_attach = on_attach }) 196 vim.lsp.enable("nixd") 197 198 vim.lsp.config("lua_ls", { 199 on_attach = on_attach, 200 settings = { 201 Lua = { 202 runtime = { 203 -- Tell the language server which version of Lua you're using 204 -- (most likely LuaJIT in the case of Neovim) 205 version = "LuaJIT", 206 }, 207 diagnostics = { 208 -- Get the language server to recognize the `vim` global 209 globals = { 210 "vim", 211 "require", 212 "hs", 213 "spoon", 214 }, 215 }, 216 workspace = { 217 -- Make the server aware of Neovim runtime files 218 library = vim.api.nvim_get_runtime_file("", true), 219 }, 220 -- Do not send telemetry data containing a randomized but unique identifier 221 telemetry = { 222 enable = false, 223 }, 224 }, 225 }, 226 }) 227 vim.lsp.enable("lua_ls") 228 229 vim.lsp.enable("basedpyright") 230 231 vim.lsp.config("vue_ls", { 232 -- add filetypes for typescript, javascript and vue 233 filetypes = { "typescript", "javascript", "javascriptreact", "typescriptreact", "vue" }, 234 }) 235 vim.lsp.enable("vue_ls") 236 237 vim.lsp.enable("terraformls") 238 239 vim.lsp.config("ruby_lsp", { 240 init_options = { 241 formatter = "standard", 242 linters = { "standard" }, 243 }, 244 }) 245 vim.lsp.enable("ruby_lsp") 246 vim.lsp.config("nil_ls", { 247 init_options = { 248 root_markers = { "flake.nix", ".git", "darwin-configuration.nix" }, 249 }, 250 }) 251 vim.lsp.enable("nil_ls") 252 end 253 254 return { 255 { 256 "neovim/nvim-lspconfig", 257 config = config, 258 }, 259 { 260 "mfussenegger/nvim-lint", 261 config = function() 262 local lint = require("lint") 263 lint.linters_by_ft = { 264 sh = { "shellcheck" }, 265 } 266 267 local lint_augroup = vim.api.nvim_create_augroup("lint", { clear = true }) 268 vim.api.nvim_create_autocmd({ "BufEnter", "BufWritePost", "InsertLeave" }, { 269 group = lint_augroup, 270 callback = function() 271 -- Only run the linter in buffers that you can modify in order to 272 -- avoid superfluous noise 273 if vim.bo.modifiable then 274 lint.try_lint() 275 end 276 end, 277 }) 278 end, 279 }, 280 }