Skip to content

Commit 240f8f9

Browse files
committed
feat: add configurable LSP features
1 parent af72687 commit 240f8f9

File tree

5 files changed

+126
-87
lines changed

5 files changed

+126
-87
lines changed

lua/astrolsp/config/init.lua

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
local schemastore_avail, schemastore = pcall(require, "schemastore")
22

33
return {
4+
features = {
5+
autoformat_enabled = true,
6+
codelens = true,
7+
diagnostics_mode = 3,
8+
inlay_hints = false,
9+
lsp_handlers = true,
10+
semantic_tokens = true,
11+
},
12+
413
diagnostics = {
514
virtual_text = true,
615
signs = {

lua/astrolsp/config/mappings.lua

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,12 @@ M.n["<leader>lf"] =
4646
{ function() vim.lsp.buf.format(M.format_opts) end, desc = "Format buffer", cond = "textDocument/formatting" }
4747
M.v["<leader>lf"] = M.n["<leader>lf"]
4848
M.n["<leader>uf"] = {
49-
function() require("astrolsp.utils").toggle_buffer_autoformat() end,
49+
function() require("astrolsp.toggles").buffer_autoformat() end,
5050
desc = "Toggle autoformatting (buffer)",
5151
cond = "textDocument/formatting",
5252
}
5353
M.n["<leader>uF"] = {
54-
function() require("astrolsp.utils").toggle_autoformat() end,
54+
function() require("astrolsp.toggles").autoformat() end,
5555
desc = "Toggle autoformatting (global)",
5656
cond = "textDocument/formatting",
5757
}
@@ -65,14 +65,7 @@ M.n["gI"] = {
6565
}
6666

6767
M.n["<leader>uH"] = {
68-
function()
69-
vim.b.inlay_hints_enabled = not vim.b.inlay_hints_enabled
70-
-- TODO: remove check after dropping support for Neovim v0.9
71-
if vim.lsp.inlay_hint then
72-
vim.lsp.inlay_hint(0, vim.b.inlay_hints_enabled)
73-
vim.notify(("Inlay hints %s"):format(vim.b.inlay_hints_enabled and "on" or "off"))
74-
end
75-
end,
68+
function() require("astrolsp.toggles").buffer_inlay_hints() end,
7669
desc = "Toggle LSP inlay hints (buffer)",
7770
cond = vim.lsp.inlay_hint and "textDocument/inlayHint" or false,
7871
}
@@ -98,15 +91,7 @@ M.n["<leader>lG"] =
9891
{ function() vim.lsp.buf.workspace_symbol() end, desc = "Search workspace symbols", cond = "workspace/symbol" }
9992

10093
M.n["<leader>uY"] = {
101-
function()
102-
vim.b.semantic_tokens_enabled = not vim.b.semantic_tokens_enabled
103-
for _, client in ipairs((vim.lsp.get_clients or vim.lsp.get_active_clients)()) do
104-
if client.server_capabilities.semanticTokensProvider then
105-
vim.lsp.semantic_tokens[vim.b.semantic_tokens_enabled and "start" or "stop"](0, client.id)
106-
vim.notify(("Buffer lsp semantic highlighting %s"):format(vim.b.semantic_tokens_enabled and "on" or "off"))
107-
end
108-
end
109-
end,
94+
function() require("astrolsp.toggles").buffer_semantic_tokens() end,
11095
desc = "Toggle LSP semantic highlight (buffer)",
11196
cond = "textDocument/semanticTokens/full",
11297
}

lua/astrolsp/init.lua

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
local M = {}
22

3-
local utils = require "astrolsp.utils"
43
local tbl_contains = vim.tbl_contains
54
local tbl_isempty = vim.tbl_isempty
65

76
M.lsp_progress = {}
87

8+
local function event(name)
9+
vim.schedule(function() vim.api.nvim_exec_autocmds("User", { pattern = "AstroLsp" .. name, modeline = false }) end)
10+
end
11+
912
function M.setup(opts)
1013
opts = opts or {}
1114
for section, default in pairs(require "astrolsp.config") do
@@ -44,12 +47,18 @@ function M.setup(opts)
4447
if progress[id].kind == "end" then
4548
vim.defer_fn(function()
4649
progress[id] = nil
47-
utils.event "Progress"
50+
event "Progress"
4851
end, 100)
4952
end
50-
utils.event "Progress"
53+
event "Progress"
5154
orig_handler(_, msg, info)
5255
end
56+
57+
if M.options.features.lsp_handlers then
58+
vim.lsp.handlers["textDocument/hover"] = vim.lsp.with(vim.lsp.handlers.hover, { border = "rounded", silent = true })
59+
vim.lsp.handlers["textDocument/signatureHelp"] =
60+
vim.lsp.with(vim.lsp.handlers.signature_help, { border = "rounded", silent = true })
61+
end
5362
end
5463

5564
M.diagnostics = { [0] = {}, {}, {}, {} }
@@ -73,7 +82,7 @@ function M.setup_diagnostics()
7382
M.options.diagnostics,
7483
}
7584

76-
vim.diagnostic.config(M.diagnostics[vim.g.diagnostics_mode])
85+
vim.diagnostic.config(M.diagnostics[M.options.features.diagnostics_mode])
7786
end
7887

7988
--- Helper function to set up a given server with the Neovim LSP client
@@ -109,6 +118,18 @@ local function add_buffer_autocmd(augroup, bufnr, autocmds)
109118
end
110119
end
111120

121+
local function del_buffer_autocmd(augroup, bufnr)
122+
local cmds_found, cmds = pcall(vim.api.nvim_get_autocmds, { group = augroup, buffer = bufnr })
123+
if cmds_found then vim.tbl_map(function(cmd) vim.api.nvim_del_autocmd(cmd.id) end, cmds) end
124+
end
125+
126+
local function has_capability(capability, filter)
127+
for _, client in ipairs((vim.lsp.get_clients or vim.lsp.get_active_clients)(filter)) do
128+
if client.supports_method(capability) then return true end
129+
end
130+
return false
131+
end
132+
112133
--- The `on_attach` function used by AstroNvim
113134
---@param client table The LSP client details when attaching
114135
---@param bufnr number The buffer that the LSP client is attaching to
@@ -118,14 +139,14 @@ M.on_attach = function(client, bufnr)
118139
events = { "InsertLeave", "BufEnter" },
119140
desc = "Refresh codelens",
120141
callback = function()
121-
if not utils.has_capability("textDocument/codeLens", { bufnr = bufnr }) then
122-
utils.del_buffer_autocmd("lsp_codelens_refresh", bufnr)
142+
if not has_capability("textDocument/codeLens", { bufnr = bufnr }) then
143+
del_buffer_autocmd("lsp_codelens_refresh", bufnr)
123144
return
124145
end
125-
if vim.g.codelens_enabled then vim.lsp.codelens.refresh() end
146+
if M.options.features.codelens then vim.lsp.codelens.refresh() end
126147
end,
127148
})
128-
if vim.g.codelens_enabled then vim.lsp.codelens.refresh() end
149+
if M.options.features.codelens then vim.lsp.codelens.refresh() end
129150
end
130151

131152
if
@@ -148,8 +169,8 @@ M.on_attach = function(client, bufnr)
148169
events = "BufWritePre",
149170
desc = "autoformat on save",
150171
callback = function()
151-
if not utils.has_capability("textDocument/formatting", { bufnr = bufnr }) then
152-
utils.del_buffer_autocmd("lsp_auto_format", bufnr)
172+
if not has_capability("textDocument/formatting", { bufnr = bufnr }) then
173+
del_buffer_autocmd("lsp_auto_format", bufnr)
153174
return
154175
end
155176
local autoformat_enabled = vim.b[bufnr].autoformat_enabled
@@ -167,8 +188,8 @@ M.on_attach = function(client, bufnr)
167188
events = { "CursorHold", "CursorHoldI" },
168189
desc = "highlight references when cursor holds",
169190
callback = function()
170-
if not utils.has_capability("textDocument/documentHighlight", { bufnr = bufnr }) then
171-
utils.del_buffer_autocmd("lsp_document_highlight", bufnr)
191+
if not has_capability("textDocument/documentHighlight", { bufnr = bufnr }) then
192+
del_buffer_autocmd("lsp_document_highlight", bufnr)
172193
return
173194
end
174195
vim.lsp.buf.document_highlight()
@@ -183,16 +204,14 @@ M.on_attach = function(client, bufnr)
183204
end
184205

185206
if client.supports_method "textDocument/inlayHint" then
186-
if vim.b[bufnr].inlay_hints_enabled == nil then vim.b[bufnr].inlay_hints_enabled = vim.g.inlay_hints_enabled end
207+
if vim.b[bufnr].inlay_hints == nil then vim.b[bufnr].inlay_hints = M.options.features.inlay_hints end
187208
-- TODO: remove check after dropping support for Neovim v0.9
188-
if vim.lsp.inlay_hint and vim.b[bufnr].inlay_hints_enabled then vim.lsp.inlay_hint(bufnr, true) end
209+
if vim.lsp.inlay_hint and vim.b[bufnr].inlay_hints then vim.lsp.inlay_hint(bufnr, true) end
189210
end
190211

191212
if client.supports_method and vim.lsp.semantic_tokens then
192-
if vim.b[bufnr].semantic_tokens_enabled == nil then
193-
vim.b[bufnr].semantic_tokens_enabled = vim.g.semantic_tokens_enabled
194-
end
195-
if not vim.g.semantic_tokens_enabled then vim.lsp.semantic_tokens["stop"](bufnr, client.id) end
213+
if vim.b[bufnr].semantic_tokens == nil then vim.b[bufnr].semantic_tokens = M.options.features.semantic_tokens end
214+
if not vim.b[bufnr].semantic_tokens then vim.lsp.semantic_tokens["stop"](bufnr, client.id) end
196215
end
197216

198217
for mode, maps in pairs(M.options.mappings) do
@@ -229,15 +248,15 @@ function M.config(server_name)
229248
local opts = vim.tbl_deep_extend(
230249
"force",
231250
vim.tbl_deep_extend("force", server.document_config.default_config, server),
232-
{ capabilities = M.capabilities, flags = M.flags }
251+
{ capabilities = M.options.capabilities, flags = M.options.flags }
233252
)
234253
-- HACK: add astronvim interoperability, remove after AstroNvim v4
235254
if type(astronvim) == "table" and type(astronvim.user_opts) == "function" then
236255
opts = astronvim.user_opts("lsp.config." .. server_name, opts)
237256
end
238-
if M.options.config[server_name] then
239-
opts = assert(vim.tbl_deep_extend("force", opts, M.options.config[server_name]))
240-
end
257+
if M.options.config[server_name] then opts = vim.tbl_deep_extend("force", opts, M.options.config[server_name]) end
258+
assert(opts)
259+
241260
local old_on_attach = require("lspconfig")[server_name].on_attach
242261
local user_on_attach = opts.on_attach
243262
opts.on_attach = function(client, bufnr)

lua/astrolsp/toggles.lua

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
local M = {}
2+
3+
local options = require("astrolsp").options
4+
local features = options.features
5+
6+
local notify = vim.notify
7+
local function bool2str(bool) return bool and "on" or "off" end
8+
9+
--- Toggle auto format
10+
function M.autoformat()
11+
features.autoformat = not features.autoformat
12+
vim.notify(string.format("Global autoformatting %s", bool2str(features.autoformat)))
13+
end
14+
15+
--- Toggle buffer local auto format
16+
---@param bufnr? number The buffer to toggle the autoformatting of, default the current buffer
17+
function M.buffer_autoformat(bufnr)
18+
bufnr = bufnr or 0
19+
local old_val = vim.b[bufnr].autoformat
20+
if old_val == nil then old_val = features.autoformat end
21+
vim.b[bufnr].autoformat = not old_val
22+
notify(string.format("Buffer autoformatting %s", bool2str(vim.b[bufnr].autoformat)))
23+
end
24+
25+
--- Toggle buffer LSP inlay hints
26+
---@param bufnr? number the buffer to toggle the clients on
27+
function M.buffer_inlay_hints(bufnr)
28+
bufnr = bufnr or 0
29+
vim.b[bufnr].inlay_hints = not vim.b[bufnr].inlay_hints
30+
-- TODO: remove check after dropping support for Neovim v0.9
31+
if vim.lsp.inlay_hint then
32+
vim.lsp.inlay_hint(bufnr, vim.b[bufnr].inlay_hints)
33+
notify(string.format("Inlay hints %s", bool2str(vim.b[bufnr].inlay_hints)))
34+
end
35+
end
36+
37+
--- Toggle buffer semantic token highlighting for all language servers that support it
38+
---@param bufnr? number the buffer to toggle the clients on
39+
function M.buffer_semantic_tokens(bufnr)
40+
bufnr = bufnr or 0
41+
vim.b[bufnr].semantic_tokens = not vim.b[bufnr].semantic_tokens
42+
for _, client in ipairs((vim.lsp.get_clients or vim.lsp.get_active_clients)()) do
43+
if client.server_capabilities.semanticTokensProvider then
44+
vim.lsp.semantic_tokens[vim.b[bufnr].semantic_tokens and "start" or "stop"](bufnr, client.id)
45+
notify(string.format("Buffer lsp semantic highlighting %s", bool2str(vim.b[bufnr].semantic_tokens)))
46+
end
47+
end
48+
end
49+
50+
--- Toggle codelens
51+
function M.codelens()
52+
features.codelens = not features.codelens
53+
if not features.codelens then vim.lsp.codelens.clear() end
54+
notify(string.format("CodeLens %s", bool2str(features.codelens)))
55+
end
56+
57+
--- Toggle diagnostics
58+
function M.diagnostics()
59+
features.diagnostics_mode = (features.diagnostics_mode - 1) % 4
60+
vim.diagnostic.config(require("astrolsp").diagnostics[features.diagnostics_mode])
61+
if features.diagnostics_mode == 0 then
62+
notify "diagnostics off"
63+
elseif features.diagnostics_mode == 1 then
64+
notify "only status diagnostics"
65+
elseif features.diagnostics_mode == 2 then
66+
notify "virtual text off"
67+
else
68+
notify "all diagnostics on"
69+
end
70+
end
71+
72+
return M

lua/astrolsp/utils.lua

Lines changed: 0 additions & 46 deletions
This file was deleted.

0 commit comments

Comments
 (0)