my dotfiles for arch
1return {
2 -- Mason for installing LSP servers
3 { "mason-org/mason.nvim", opts = {} },
4 "WhoIsSethDaniel/mason-tool-installer.nvim",
5
6 -- Useful status updates for LSP.
7 { "j-hui/fidget.nvim", opts = {} },
8
9 -- Allows extra capabilities provided by blink.cmp
10 {
11 "saghen/blink.cmp",
12 config = function(_, opts)
13 require("blink.cmp").setup(opts)
14 -- Add blink.cmp capabilities to the default LSP client capabilities
15 vim.lsp.config("*", {
16 capabilities = require("blink.cmp").get_lsp_capabilities(),
17 })
18 end,
19 },
20
21 -- LSP Configuration (using native vim.lsp.config for Neovim 0.11+)
22 {
23 "neovim/nvim-lspconfig",
24 config = function()
25 -- This function gets run when an LSP attaches to a particular buffer.
26 vim.api.nvim_create_autocmd("LspAttach", {
27 group = vim.api.nvim_create_augroup("kickstart-lsp-attach", { clear = true }),
28 callback = function(event)
29 local map = function(keys, func, desc, mode)
30 mode = mode or "n"
31 vim.keymap.set(mode, keys, func, { buffer = event.buf, desc = "LSP: " .. desc })
32 end
33
34 -- map("gd", require("telescope.builtin").lsp_definitions, "[G]oto [D]efinition")
35 map("<leader>lr", ":LspRestart<CR>", "Restart LSP")
36
37 map("K", function()
38 vim.lsp.buf.hover({ border = "rounded" })
39 end, "Show documentation for symbol under cursor")
40
41 -- Rename the variable under your cursor.
42 map("<leader>rn", function()
43 vim.api.nvim_create_autocmd({ "CmdlineEnter" }, {
44 callback = function()
45 local key = vim.api.nvim_replace_termcodes("<C-f>", true, false, true)
46 vim.api.nvim_feedkeys(key, "c", false)
47 vim.api.nvim_feedkeys("0", "n", false)
48 return true
49 end,
50 })
51 vim.lsp.buf.rename()
52 end, "[R]e[n]ame")
53
54 -- Execute a code action
55 map("<leader>ca", vim.lsp.buf.code_action, "[C]ode [A]ction", { "n", "x" })
56
57 -- Find references for the word under your cursor.
58 map("gtref", require("telescope.builtin").lsp_references, "[G]oto [R]eferences")
59
60 -- Jump to the implementation of the word under your cursor.
61 -- map("gI", require("telescope.builtin").lsp_implementations, "[G]oto [I]mplementation")
62
63 -- Goto Declaration (e.g., in C this would take you to the header)
64 map("gD", vim.lsp.buf.declaration, "[G]oto [D]eclaration")
65
66 -- Fuzzy find all the symbols in your current document.
67 -- map("<leader>ds", require("telescope.builtin").lsp_document_symbols, "[D]ocument [S]ymbols")
68
69 -- Fuzzy find all the symbols in your current workspace.
70 -- map("gW", require("telescope.builtin").lsp_dynamic_workspace_symbols, "Open Workspace Symbols")
71
72 -- Jump to the type of the word under your cursor.
73 -- map("gt", require("telescope.builtin").lsp_type_definitions, "[G]oto [T]ype Definition")
74
75 map("<leader>vd", function()
76 vim.diagnostic.open_float()
77 end, "[V]iew [D]iagnostics")
78
79 map("[d", function()
80 vim.diagnostic.goto_prev()
81 end, "Prev Diagnostic")
82 map("]d", function()
83 vim.diagnostic.goto_next()
84 end, "Next Diagnostic")
85
86 local client = vim.lsp.get_client_by_id(event.data.client_id)
87
88 -- Highlight references of the word under cursor
89 if
90 client
91 and client:supports_method(vim.lsp.protocol.Methods.textDocument_documentHighlight, event.buf)
92 then
93 local highlight_augroup =
94 vim.api.nvim_create_augroup("kickstart-lsp-highlight", { clear = false })
95 vim.api.nvim_create_autocmd({ "CursorHold", "CursorHoldI" }, {
96 buffer = event.buf,
97 group = highlight_augroup,
98 callback = vim.lsp.buf.document_highlight,
99 })
100
101 vim.api.nvim_create_autocmd({ "CursorMoved", "CursorMovedI" }, {
102 buffer = event.buf,
103 group = highlight_augroup,
104 callback = vim.lsp.buf.clear_references,
105 })
106
107 vim.api.nvim_create_autocmd("LspDetach", {
108 group = vim.api.nvim_create_augroup("kickstart-lsp-detach", { clear = true }),
109 callback = function(event2)
110 vim.lsp.buf.clear_references()
111 vim.api.nvim_clear_autocmds({ group = "kickstart-lsp-highlight", buffer = event2.buf })
112 end,
113 })
114 end
115
116 -- Toggle inlay hints keymap
117 if
118 client and client:supports_method(vim.lsp.protocol.Methods.textDocument_inlayHint, event.buf)
119 then
120 map("<leader>th", function()
121 vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled({ bufnr = event.buf }))
122 end, "[T]oggle Inlay [H]ints")
123 end
124
125 -- Svelte-specific: notify on TS/JS file changes
126 -- https://github.com/sveltejs/language-tools/issues/2008#issuecomment-2351976230
127 if client and client.name == "svelte" then
128 vim.api.nvim_create_autocmd("BufWritePost", {
129 pattern = { "*.js", "*.ts" },
130 group = vim.api.nvim_create_augroup("svelte-on-did-change-ts-or-js-file", { clear = true }),
131 callback = function(args)
132 client:notify("$/onDidChangeTsOrJsFile", {
133 uri = args.match,
134 })
135 end,
136 })
137 end
138 end,
139 })
140
141 -- Extra keymaps
142 vim.keymap.set("n", "<leader>oi", function()
143 vim.lsp.buf.code_action({
144 context = {
145 only = { "source.organizeImports" },
146 diagnostics = {},
147 },
148 apply = true,
149 })
150 end, { desc = "Organize Imports" })
151
152 -- Diagnostic Config
153 vim.diagnostic.config({
154 severity_sort = true,
155 float = { border = "rounded", source = "if_many" },
156 underline = { severity = vim.diagnostic.severity.ERROR },
157 signs = vim.g.have_nerd_font and {
158 text = {
159 [vim.diagnostic.severity.ERROR] = " ",
160 [vim.diagnostic.severity.WARN] = " ",
161 [vim.diagnostic.severity.INFO] = " ",
162 [vim.diagnostic.severity.HINT] = " ",
163 },
164 } or {},
165 virtual_text = {
166 source = "if_many",
167 spacing = 2,
168 format = function(diagnostic)
169 local diagnostic_message = {
170 [vim.diagnostic.severity.ERROR] = diagnostic.message,
171 [vim.diagnostic.severity.WARN] = diagnostic.message,
172 [vim.diagnostic.severity.INFO] = diagnostic.message,
173 [vim.diagnostic.severity.HINT] = diagnostic.message,
174 }
175 return diagnostic_message[diagnostic.severity]
176 end,
177 },
178 })
179
180 -- Install tools via mason-tool-installer
181 require("mason-tool-installer").setup({
182 ensure_installed = {
183 "stylua",
184 "lua-language-server",
185 "pyright",
186 "css-lsp",
187 "eslint-lsp",
188 "vtsls",
189 "tailwindcss-language-server",
190 "biome",
191 },
192 })
193
194 -- Load custom LSP configs from nvim/lsp/*.lua to override nvim-lspconfig defaults
195 local lsp_path = vim.fn.stdpath("config") .. "/lsp"
196 for _, file in ipairs(vim.fn.readdir(lsp_path)) do
197 if file:match("%.lua$") then
198 local name = file:gsub("%.lua$", "")
199 local config = dofile(lsp_path .. "/" .. file)
200 if type(config) == "table" then
201 vim.lsp.config(name, config)
202 end
203 end
204 end
205
206 -- Enable LSP servers (configs are in nvim/lsp/*.lua)
207 vim.lsp.enable({
208 "lua_ls",
209 "pyright",
210 "cssls",
211 "eslint",
212 "gdscript",
213 -- "vtsls",
214 "tsgo",
215 "svelte",
216 "tailwindcss",
217 "biome",
218 })
219 end,
220 },
221}