|
| 1 | +-- lua/plugins/lsp.lua |
1 | 2 | return { |
2 | | - 'neovim/nvim-lspconfig', |
3 | | - dependencies = { |
4 | | - 'williamboman/mason.nvim', |
5 | | - 'williamboman/mason-lspconfig.nvim', |
6 | | - 'WhoIsSethDaniel/mason-tool-installer.nvim', |
7 | | - { |
8 | | - 'j-hui/fidget.nvim', |
9 | | - tag = 'v1.4.0', |
10 | | - opts = { |
11 | | - progress = { |
12 | | - display = { done_icon = '✓' }, |
13 | | - }, |
14 | | - notification = { |
15 | | - window = { winblend = 0 }, |
16 | | - }, |
17 | | - }, |
18 | | - }, |
19 | | - { |
20 | | - 'glepnir/lspsaga.nvim', |
21 | | - event = 'LspAttach', |
22 | | - config = function() |
23 | | - require('lspsaga').setup { |
24 | | - ui = { border = 'rounded', title = true }, |
25 | | - hover = { max_width = 0.6 }, |
26 | | - rename = { in_select = false }, |
27 | | - } |
28 | | - end, |
29 | | - }, |
30 | | - }, |
31 | | - config = function() |
32 | | - vim.api.nvim_create_autocmd('LspAttach', { |
33 | | - group = vim.api.nvim_create_augroup('lsp-attach', { clear = true }), |
34 | | - callback = function(event) |
35 | | - local map = function(keys, func, desc) |
36 | | - vim.keymap.set('n', keys, func, { buffer = event.buf, desc = 'LSP: ' .. desc }) |
37 | | - end |
38 | | - local telescope_ok, telescope = pcall(require, 'telescope.builtin') |
39 | | - if not telescope_ok then return end |
40 | | - map('gd', telescope.lsp_definitions, 'Go to Definition') |
41 | | - map('gr', telescope.lsp_references, 'Go to References') |
42 | | - map('gI', telescope.lsp_implementations, 'Go to Implementation') |
43 | | - map('<leader>D', telescope.lsp_type_definitions, 'Type Definition') |
44 | | - map('<leader>ds', telescope.lsp_document_symbols, 'Document Symbols') |
45 | | - map('<leader>ws', telescope.lsp_dynamic_workspace_symbols, 'Workspace Symbols') |
46 | | - map('<leader>rn', vim.lsp.buf.rename, 'Rename') |
47 | | - map('<leader>ca', vim.lsp.buf.code_action, 'Code Action') |
48 | | - map('gD', vim.lsp.buf.declaration, 'Go to Declaration') |
49 | | - map('K', function() |
50 | | - local lspsaga_hover_ok, lspsaga_hover = pcall(require, 'lspsaga.hover') |
51 | | - if lspsaga_hover_ok then |
52 | | - lspsaga_hover:render_hover_doc() |
53 | | - end |
54 | | - end, 'Show Hover') |
55 | | - local client = vim.lsp.get_client_by_id(event.data.client_id) |
56 | | - if client and client.server_capabilities.documentHighlightProvider then |
57 | | - vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, { |
58 | | - buffer = event.buf, |
59 | | - callback = vim.lsp.buf.document_highlight, |
60 | | - }) |
61 | | - vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI' }, { |
62 | | - buffer = event.buf, |
63 | | - callback = vim.lsp.buf.clear_references, |
64 | | - }) |
65 | | - end |
66 | | - end, |
67 | | - }) |
| 3 | + { |
| 4 | + "neovim/nvim-lspconfig", |
| 5 | + config = function() |
| 6 | + local lspconfig = require("lspconfig") |
| 7 | + local util = require("lspconfig.util") |
| 8 | + |
| 9 | + -- Ensure *.templ is recognized as 'templ' |
| 10 | + vim.filetype.add({ |
| 11 | + extension = { templ = "templ" }, |
| 12 | + }) |
68 | 13 |
|
69 | | - -- LSP Server Configurations |
70 | | - local servers = { |
71 | | - gopls = { |
72 | | - settings = { |
73 | | - gopls = { |
74 | | - experimentalPostfixCompletions = true, |
75 | | - gofumpt = true, |
76 | | - staticcheck = true, |
77 | | - analyses = { unusedparams = true }, |
78 | | - directoryFilters = { '-node_modules' }, |
79 | | - templ = { |
80 | | - format = false, -- DISABLED for debugging |
81 | | - lint = true, |
82 | | - }, |
83 | | - }, |
84 | | - }, |
85 | | - filetypes = { 'go', 'templ' }, |
86 | | - }, |
87 | | - astro = { |
88 | | - filetypes = { "astro" }, |
89 | | - init_options = { |
90 | | - typescript = { |
91 | | - tsdk = vim.fn.stdpath("data") .. "/mason/packages/typescript-language-server/node_modules/typescript/lib", |
92 | | - }, |
93 | | - }, |
94 | | - }, |
95 | | - eslint = {}, |
96 | | - html = { filetypes = { 'html', 'twig', 'hbs' } }, |
97 | | - -- templ = { -- DISABLED for debugging |
98 | | - -- cmd = { vim.fn.stdpath("data") .. "/mason/bin/templ", "lsp" }, |
99 | | - -- filetypes = { "templ" }, |
100 | | - -- root_dir = require("lspconfig").util.root_pattern("go.mod", ".git"), |
101 | | - -- }, |
102 | | - lua_ls = { |
103 | | - settings = { |
104 | | - Lua = { |
105 | | - runtime = { version = 'LuaJIT' }, |
106 | | - workspace = { |
107 | | - checkThirdParty = false, |
108 | | - library = { |
109 | | - '${3rd}/luv/library', |
110 | | - unpack(vim.api.nvim_get_runtime_file('', true)), |
111 | | - }, |
112 | | - }, |
113 | | - completion = { callSnippet = 'Replace' }, |
114 | | - telemetry = { enable = false }, |
115 | | - diagnostics = { disable = { 'missing-fields' } }, |
116 | | - }, |
117 | | - }, |
118 | | - }, |
119 | | - dockerls = {}, |
120 | | - docker_compose_language_service = {}, |
121 | | - rust_analyzer = { |
122 | | - ['rust-analyzer'] = { |
123 | | - cargo = { features = 'all' }, |
124 | | - checkOnSave = true, |
125 | | - check = { command = 'clippy' }, |
126 | | - }, |
127 | | - }, |
128 | | - tailwindcss = {}, |
129 | | - jsonls = {}, |
130 | | - yamlls = {}, |
131 | | - bashls = {}, |
132 | | - graphql = {}, |
133 | | - cssls = {}, |
134 | | - } |
| 14 | + -- Example setup for Go, TS, etc. |
| 15 | + lspconfig.gopls.setup({}) |
135 | 16 |
|
136 | | - require('mason').setup() |
| 17 | + -- TypeScript (make sure you don't also set this up elsewhere to avoid duplicates) |
| 18 | + lspconfig.ts_ls.setup({}) |
137 | 19 |
|
138 | | - local capabilities = vim.tbl_deep_extend( |
139 | | - 'force', |
140 | | - {}, |
141 | | - vim.lsp.protocol.make_client_capabilities(), |
142 | | - require('cmp_nvim_lsp').default_capabilities() |
143 | | - ) |
| 20 | + -- ✅ Templ LSP: auto-start when in a repo with go.mod or .git |
| 21 | + lspconfig.templ.setup({ |
| 22 | + cmd = { "templ", "lsp" }, -- or absolute path if needed |
| 23 | + filetypes = { "templ" }, |
| 24 | + root_dir = util.root_pattern("go.mod", ".git"), |
| 25 | + single_file_support = true, |
| 26 | + }) |
144 | 27 |
|
145 | | - require('mason-lspconfig').setup { |
146 | | - ensure_installed = vim.tbl_keys(servers), |
147 | | - } |
| 28 | + -- Safe hover helper |
| 29 | + local function has_hover(bufnr) |
| 30 | + for _, c in pairs(vim.lsp.get_active_clients({ bufnr = bufnr })) do |
| 31 | + if c.server_capabilities and c.server_capabilities.hoverProvider then |
| 32 | + return true |
| 33 | + end |
| 34 | + end |
| 35 | + return false |
| 36 | + end |
148 | 37 |
|
149 | | - -- Setup servers manually |
150 | | - for name, config in pairs(servers) do |
151 | | - config.capabilities = vim.tbl_deep_extend('force', {}, capabilities, config.capabilities or {}) |
152 | | - require('lspconfig')[name].setup(config) |
153 | | - end |
| 38 | + -- Keymaps |
| 39 | + vim.api.nvim_create_autocmd("LspAttach", { |
| 40 | + callback = function(args) |
| 41 | + local bufnr = args.buf |
| 42 | + local function buf_map(mode, lhs, rhs, desc) |
| 43 | + vim.keymap.set(mode, lhs, rhs, { buffer = bufnr, desc = desc }) |
| 44 | + end |
154 | 45 |
|
155 | | - vim.api.nvim_create_autocmd("BufWritePre", { |
156 | | - pattern = "*.astro", |
157 | | - callback = function() |
158 | | - vim.lsp.buf.format({ async = false }) |
159 | | - end, |
160 | | - }) |
| 46 | + -- SAFE Hover |
| 47 | + buf_map("n", "K", function() |
| 48 | + if not has_hover(bufnr) then |
| 49 | + return |
| 50 | + end |
| 51 | + local ok, saga_hover = pcall(require, "lspsaga.hover") |
| 52 | + if ok and saga_hover and saga_hover.render_hover_doc then |
| 53 | + pcall(function() saga_hover:render_hover_doc() end) |
| 54 | + else |
| 55 | + pcall(vim.lsp.buf.hover) |
| 56 | + end |
| 57 | + end, "LSP: Hover (safe)") |
161 | 58 |
|
162 | | - -- Auto-format and organize imports on save for Go |
163 | | - vim.api.nvim_create_autocmd("BufWritePre", { |
164 | | - pattern = "*.go", |
165 | | - callback = function() |
166 | | - vim.lsp.buf.format({ async = false }) |
167 | | - vim.lsp.buf.code_action({ |
168 | | - context = { only = { "source.organizeImports" } }, |
169 | | - apply = true, |
170 | | - }) |
171 | | - end, |
172 | | - }) |
173 | | - end, |
| 59 | + -- Usual LSP keymaps |
| 60 | + buf_map("n", "gd", vim.lsp.buf.definition, "Goto Definition") |
| 61 | + buf_map("n", "gr", vim.lsp.buf.references, "Goto References") |
| 62 | + buf_map("n", "gi", vim.lsp.buf.implementation, "Goto Implementation") |
| 63 | + buf_map("n", "<leader>rn", vim.lsp.buf.rename, "Rename Symbol") |
| 64 | + end, |
| 65 | + }) |
| 66 | + end, |
| 67 | + }, |
174 | 68 | } |
| 69 | + |
0 commit comments