Skip to content

Commit 5b0e9bd

Browse files
committed
feat!: move autocommand configuration to opts similar to mappings
1 parent 2cae1a9 commit 5b0e9bd

File tree

3 files changed

+106
-96
lines changed

3 files changed

+106
-96
lines changed

README.md

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ Install the plugin with your plugin manager of choice:
3232
[**packer.nvim**](https://github.com/wbthomason/packer.nvim)
3333

3434
```lua
35-
use({
35+
use {
3636
"AstroNvim/astrolsp",
37-
})
37+
}
3838

39-
require("astrolsp").setup({
39+
require("astrolsp").setup {
4040
-- set configuration options as described below
41-
})
41+
}
4242
```
4343

4444
## ⚙️ Configuration
@@ -47,7 +47,7 @@ require("astrolsp").setup({
4747

4848
```lua
4949
---@type AstroLSPConfig
50-
{
50+
local opts = {
5151
-- Configuration table of features provided by AstroLSP
5252
features = {
5353
autoformat = true, -- enable or disable auto formatting on start
@@ -57,6 +57,30 @@ require("astrolsp").setup({
5757
lsp_handlers = true, -- enable/disable setting of lsp_handlers
5858
semantic_tokens = true, -- enable/disable semantic token highlighting
5959
},
60+
-- Configure buffer local auto commands to add when attaching a language server
61+
autocmds = {
62+
-- first key is the `augroup` (:h augroup)
63+
lsp_document_highlight = {
64+
-- condition to create/delete auto command group
65+
-- can either be a string of a client capability or a function of `fun(client, bufnr): boolean`
66+
-- condition will be resolved for each client on each execution and if it ever fails for all clients,
67+
-- the auto commands will be deleted for that buffer
68+
cond = "textDocument/documentHighlight",
69+
-- list of auto commands to set
70+
{
71+
-- events to trigger
72+
event = { "CursorHold", "CursorHoldI" },
73+
-- the rest of the autocmd options (:h nvim_create_autocmd)
74+
desc = "Document Highlighting",
75+
callback = function() vim.lsp.buf.document_highlight() end,
76+
},
77+
{
78+
event = { "CursorMoved", "CursorMovedI", "BufLeave" },
79+
desc = "Document Highlighting Clear",
80+
callback = function() vim.lsp.buf.clear_references() end,
81+
},
82+
},
83+
},
6084
-- Configure default capabilities for language servers (`:h vim.lsp.protocol.make_client.capabilities()`)
6185
capabilities = {
6286
textDocument = {
@@ -108,20 +132,14 @@ require("astrolsp").setup({
108132
-- default format timeout
109133
timeout_ms = 1000,
110134
-- fully override the default formatting function
111-
filter = function(client)
112-
return true
113-
end,
135+
filter = function(client) return true end,
114136
},
115137
-- Configure how language servers get set up
116138
handlers = {
117139
-- default handler, first entry with no key
118-
function(server, opts)
119-
require("lspconfig")[server].setup(opts)
120-
end,
140+
function(server, opts) require("lspconfig")[server].setup(opts) end,
121141
-- custom function handler for pyright
122-
pyright = function(_, opts)
123-
require("lspconfig").pyright.setup(opts)
124-
end,
142+
pyright = function(_, opts) require("lspconfig").pyright.setup(opts) end,
125143
-- set to false to disable the setup of a language server
126144
rust_analyzer = false,
127145
},
@@ -157,9 +175,7 @@ require("astrolsp").setup({
157175
-- A list like table of servers that should be setup, useful for enabling language servers not installed with Mason.
158176
servers = { "dartls" },
159177
-- A custom `on_attach` function to be run after the default `on_attach` function, takes two parameters `client` and `bufnr` (`:h lspconfig-setup`)
160-
on_attach = function(client, bufnr)
161-
client.server_capabilities.semanticTokensProvider = nil
162-
end,
178+
on_attach = function(client, bufnr) client.server_capabilities.semanticTokensProvider = nil end,
163179
}
164180
```
165181

lua/astrolsp/config.lua

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,41 @@
3131
---@field timeout_ms integer? configure the timeout length for formatting
3232
---@field filter (fun(client):boolean)? fully override the default formatting filter function
3333

34+
---@class AstroLSPAutocmds
35+
---@field cond string|(fun(client,bufnr):boolean)? condition for the auto commands
36+
---@field [integer] table an autocommand definition
37+
3438
---@class AstroLSPOpts
39+
---Configuration of auto commands
40+
---The key into the table is the group name for the auto commands (`:h augroup`) and the value
41+
---is a list of autocmd tables where `event` key is the event(s) that trigger the auto command
42+
---and the rest are auto command options (`:h nvim_create_autocmd`). A `cond` key can also be
43+
---added to the list to control when an `augroup` should be added as well as deleted if it's never matching
44+
---Example:
45+
---
46+
---```lua
47+
---autocmds = {
48+
--- -- first key is the `augroup` (:h augroup)
49+
--- lsp_document_highlight = {
50+
--- -- condition to create/delete auto command group
51+
--- cond = "textDocument/documentHighlight",
52+
--- -- list of auto commands to set
53+
--- {
54+
--- -- events to trigger
55+
--- event = { "CursorHold", "CursorHoldI" },
56+
--- -- the rest of the autocmd options (:h nvim_create_autocmd)
57+
--- desc = "Document Highlighting",
58+
--- callback = function() vim.lsp.buf.document_highlight() end
59+
--- },
60+
--- {
61+
--- event = { "CursorMoved", "CursorMovedI", "BufLeave" },
62+
--- desc = "Document Highlighting Clear",
63+
--- callback = function() vim.lsp.buf.clear_references() end
64+
--- }
65+
--- }
66+
---}
67+
---```
68+
---@field autocmds table<string,AstroLSPAutocmds|false>?
3569
---Configuration table of features provided by AstroLSP
3670
---Example:
3771
--
@@ -199,6 +233,7 @@
199233

200234
---@type AstroLSPOpts
201235
local M = {
236+
autocmds = {},
202237
features = {
203238
codelens = true,
204239
diagnostics_mode = 3,

lua/astrolsp/init.lua

Lines changed: 38 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -65,53 +65,11 @@ function M.lsp_setup(server)
6565
end
6666
end
6767

68-
local function add_buffer_autocmd(augroup, bufnr, autocmds)
69-
if not vim.tbl_islist(autocmds) then autocmds = { autocmds } end
70-
local cmds_found, cmds = pcall(vim.api.nvim_get_autocmds, { group = augroup, buffer = bufnr })
71-
if not cmds_found or vim.tbl_isempty(cmds) then
72-
vim.api.nvim_create_augroup(augroup, { clear = false })
73-
for _, autocmd in ipairs(autocmds) do
74-
local events = autocmd.events
75-
autocmd.events = nil
76-
autocmd.group = augroup
77-
autocmd.buffer = bufnr
78-
vim.api.nvim_create_autocmd(events, autocmd)
79-
end
80-
end
81-
end
82-
83-
local function del_buffer_autocmd(augroup, bufnr)
84-
local cmds_found, cmds = pcall(vim.api.nvim_get_autocmds, { group = augroup, buffer = bufnr })
85-
if cmds_found then vim.tbl_map(function(cmd) vim.api.nvim_del_autocmd(cmd.id) end, cmds) end
86-
end
87-
88-
local function has_capability(capability, filter)
89-
-- TODO: remove check after dropping support for Neovim v0.9
90-
---@diagnostic disable-next-line: deprecated
91-
for _, client in ipairs((vim.lsp.get_clients or vim.lsp.get_active_clients)(filter)) do
92-
if client.supports_method(capability) then return true end
93-
end
94-
return false
95-
end
96-
9768
--- The `on_attach` function used by AstroNvim
9869
---@param client table The LSP client details when attaching
9970
---@param bufnr integer The buffer that the LSP client is attaching to
10071
M.on_attach = function(client, bufnr)
101-
if client.supports_method "textDocument/codeLens" then
102-
add_buffer_autocmd("lsp_codelens_refresh", bufnr, {
103-
events = { "InsertLeave", "BufEnter" },
104-
desc = "Refresh codelens",
105-
callback = function()
106-
if not has_capability("textDocument/codeLens", { bufnr = bufnr }) then
107-
del_buffer_autocmd("lsp_codelens_refresh", bufnr)
108-
return
109-
end
110-
if M.config.features.codelens then vim.lsp.codelens.refresh() end
111-
end,
112-
})
113-
if M.config.features.codelens then vim.lsp.codelens.refresh() end
114-
end
72+
if client.supports_method "textDocument/codeLens" and M.config.features.codelens then vim.lsp.codelens.refresh() end
11573

11674
if
11775
client.supports_method "textDocument/formatting"
@@ -131,42 +89,6 @@ M.on_attach = function(client, bufnr)
13189
and (tbl_isempty(autoformat.allow_filetypes or {}) or tbl_contains(autoformat.allow_filetypes, filetype))
13290
and (tbl_isempty(autoformat.ignore_filetypes or {}) or not tbl_contains(autoformat.ignore_filetypes, filetype))
13391
end
134-
add_buffer_autocmd("lsp_auto_format", bufnr, {
135-
events = "BufWritePre",
136-
desc = "autoformat on save",
137-
callback = function()
138-
if not has_capability("textDocument/formatting", { bufnr = bufnr }) then
139-
del_buffer_autocmd("lsp_auto_format", bufnr)
140-
return
141-
end
142-
local buffer_autoformat = vim.b[bufnr].autoformat
143-
if buffer_autoformat == nil then buffer_autoformat = autoformat.enabled end
144-
if buffer_autoformat and ((not autoformat.filter) or autoformat.filter(bufnr)) then
145-
vim.lsp.buf.format(vim.tbl_deep_extend("force", M.format_opts, { bufnr = bufnr }))
146-
end
147-
end,
148-
})
149-
end
150-
151-
if client.supports_method "textDocument/documentHighlight" then
152-
add_buffer_autocmd("lsp_document_highlight", bufnr, {
153-
{
154-
events = { "CursorHold", "CursorHoldI" },
155-
desc = "highlight references when cursor holds",
156-
callback = function()
157-
if not has_capability("textDocument/documentHighlight", { bufnr = bufnr }) then
158-
del_buffer_autocmd("lsp_document_highlight", bufnr)
159-
return
160-
end
161-
vim.lsp.buf.document_highlight()
162-
end,
163-
},
164-
{
165-
events = { "CursorMoved", "CursorMovedI", "BufLeave" },
166-
desc = "clear references when cursor moves",
167-
callback = function() vim.lsp.buf.clear_references() end,
168-
},
169-
})
17092
end
17193

17294
if client.supports_method "textDocument/inlayHint" then
@@ -183,6 +105,43 @@ M.on_attach = function(client, bufnr)
183105
end
184106
end
185107

108+
for augroup, autocmds in pairs(M.config.autocmds) do
109+
if autocmds then
110+
local cmds_found, cmds = pcall(vim.api.nvim_get_autocmds, { group = augroup, buffer = bufnr })
111+
if not cmds_found or vim.tbl_isempty(cmds) then
112+
local cond = autocmds.cond
113+
local cond_func = type(cond) == "string" and function(c) return c.supports_method(cond) end or cond
114+
if cond_func == nil or cond_func(client, bufnr) then
115+
vim.api.nvim_create_augroup(augroup, { clear = false })
116+
for _, autocmd in ipairs(autocmds) do
117+
local opts = vim.deepcopy(autocmd)
118+
opts.command, opts.event = nil, nil
119+
opts.group, opts.buffer = augroup, bufnr
120+
local callback = autocmd.callback
121+
if autocmd.command and not callback then callback = function() vim.cmd(autocmd.command) end end
122+
opts.callback = function(args)
123+
local valid = false
124+
for _, cb_client in ipairs((vim.lsp.get_clients or vim.lsp.get_active_clients) { buffer = bufnr }) do
125+
if cond_func == nil or cond_func(cb_client, bufnr) then
126+
valid = true
127+
break
128+
end
129+
end
130+
if not valid then
131+
local cb_cmds_found, cb_cmds = pcall(vim.api.nvim_get_autocmds, { group = augroup, buffer = bufnr })
132+
if cb_cmds_found then vim.tbl_map(function(cmd) vim.api.nvim_del_autocmd(cmd.id) end, cb_cmds) end
133+
return
134+
end
135+
---@diagnostic disable-next-line: redundant-parameter
136+
return callback(args, client, bufnr)
137+
end
138+
vim.api.nvim_create_autocmd(autocmd.event, opts)
139+
end
140+
end
141+
end
142+
end
143+
end
144+
186145
local wk_avail, wk = pcall(require, "which-key")
187146
for mode, maps in pairs(M.config.mappings) do
188147
for lhs, map_opts in pairs(maps) do

0 commit comments

Comments
 (0)