Skip to content

Commit f494633

Browse files
committed
rewrite: lightbulb
1 parent 4ce44df commit f494633

File tree

2 files changed

+82
-98
lines changed

2 files changed

+82
-98
lines changed

lua/lspsaga/codeaction/lightbulb.lua

Lines changed: 80 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,30 @@
1-
local api, lsp, fn = vim.api, vim.lsp, vim.fn
2-
---@diagnostic disable-next-line: deprecated
3-
local uv = vim.version().minor >= 10 and vim.uv or vim.loop
4-
local config = require('lspsaga').config
5-
local nvim_buf_set_extmark = api.nvim_buf_set_extmark
6-
local inrender_row = -1
7-
local inrender_buf = nil
8-
9-
local function get_name()
10-
return 'SagaLightBulb'
11-
end
12-
13-
local namespace = api.nvim_create_namespace(get_name())
14-
local defined = false
15-
16-
if not defined then
17-
fn.sign_define(get_name(), { text = config.ui.code_action, texthl = get_name() })
18-
defined = true
19-
end
20-
21-
local function update_lightbulb(bufnr, row)
22-
if not bufnr or not api.nvim_buf_is_valid(bufnr) then
1+
local api, lsp = vim.api, vim.lsp
2+
local uv, create_autocmd, buf_clear_ns =
3+
vim.uv, api.nvim_create_autocmd, api.nvim_buf_clear_namespace
4+
local config = require('lspsaga').config.lightbulb
5+
local ui = require('lspsaga').config.ui
6+
local buf_set_extmark = api.nvim_buf_set_extmark
7+
local ns = api.nvim_create_namespace('SagaLightBulb')
8+
9+
local function clean_in_buf(bufnr)
10+
bufnr = bufnr or api.nvim_get_current_buf()
11+
if not api.nvim_buf_is_valid(bufnr) then
2312
return
2413
end
25-
api.nvim_buf_clear_namespace(bufnr, namespace, 0, -1)
26-
local name = get_name()
27-
pcall(fn.sign_unplace, name, { id = inrender_row, buffer = bufnr })
14+
buf_clear_ns(bufnr, ns, 0, -1)
15+
end
2816

29-
if not row then
17+
local function update_lightbulb(bufnr, row)
18+
if not config.sign and not config.virtual_text then
3019
return
3120
end
32-
33-
if config.lightbulb.sign then
34-
fn.sign_place(
35-
row + 1,
36-
name,
37-
name,
38-
bufnr,
39-
{ lnum = row + 1, priority = config.lightbulb.sign_priority }
40-
)
41-
end
42-
43-
if config.lightbulb.virtual_text then
44-
nvim_buf_set_extmark(bufnr, namespace, row, -1, {
45-
virt_text = { { config.ui.code_action, name } },
46-
virt_text_pos = 'overlay',
47-
hl_mode = 'combine',
48-
})
49-
end
50-
51-
inrender_row = row + 1
52-
inrender_buf = bufnr
21+
buf_set_extmark(bufnr, ns, row, -1, {
22+
virt_text = config.virtual_text and { { ui.code_action, 'SagaLightBulb' } } or nil,
23+
virt_text_pos = config.virtual_text and 'overlay' or nil,
24+
sign_text = config.sign and ui.code_action or nil,
25+
sign_hl_group = 'SagaLightBulb',
26+
priority = config.priority,
27+
})
5328
end
5429

5530
local function severity_vim_to_lsp(severity)
@@ -105,96 +80,105 @@ local function diagnostic_vim_to_lsp(diagnostics)
10580
end
10681

10782
local function render(bufnr)
108-
local row = api.nvim_win_get_cursor(0)[1] - 1
83+
local lnum = api.nvim_win_get_cursor(0)[1]
10984
local params = lsp.util.make_range_params()
11085
params.context = {
111-
diagnostics = diagnostic_vim_to_lsp(vim.diagnostic.get(bufnr, { lnum = row })),
86+
diagnostics = diagnostic_vim_to_lsp(vim.diagnostic.get(bufnr, { lnum = lnum - 1 })),
11287
}
11388

11489
lsp.buf_request(bufnr, 'textDocument/codeAction', params, function(_, result, _)
115-
if api.nvim_get_current_buf() ~= bufnr then
90+
if
91+
api.nvim_get_current_buf() ~= bufnr
92+
or not result
93+
or #result == 0
94+
or api.nvim_win_get_cursor(0)[1] ~= lnum
95+
or not api.nvim_buf_is_valid(bufnr)
96+
then
97+
clean_in_buf(bufnr)
11698
return
11799
end
118-
119-
if result and #result > 0 then
120-
update_lightbulb(bufnr, row)
121-
else
122-
update_lightbulb(bufnr, nil)
123-
end
100+
update_lightbulb(bufnr, lnum - 1)
124101
end)
125102
end
126103

127-
local timer = assert(uv.new_timer())
104+
local function debounce()
105+
local timer = nil ---[[uv_timer_t]]
106+
local function safe_close()
107+
if timer and timer:is_active() and not timer:is_closing() then
108+
timer:close()
109+
timer:stop()
110+
timer = nil
111+
end
112+
end
128113

129-
local function update(buf)
130-
timer:stop()
131-
update_lightbulb(inrender_buf)
132-
timer:start(config.lightbulb.debounce, 0, function()
133-
timer:stop()
134-
vim.schedule(function()
135-
if api.nvim_buf_is_valid(buf) and api.nvim_get_current_buf() == buf then
136-
render(buf)
137-
end
114+
return function(bufnr)
115+
safe_close()
116+
clean_in_buf(bufnr)
117+
local line = api.nvim_win_get_cursor(0)[1]
118+
timer = assert(uv.new_timer())
119+
timer:start(config.debounce, 0, function()
120+
safe_close()
121+
vim.schedule(function()
122+
if
123+
api.nvim_get_current_buf() ~= bufnr
124+
or not api.nvim_buf_is_valid(bufnr)
125+
or line ~= api.nvim_win_get_cursor(0)[1]
126+
then
127+
return
128+
end
129+
render(bufnr)
130+
end)
138131
end)
139-
end)
132+
end
140133
end
141134

142135
local function lb_autocmd()
143-
local name = 'SagaLightBulb'
144-
local g = api.nvim_create_augroup(name, { clear = true })
145-
api.nvim_create_autocmd('LspAttach', {
136+
local g = api.nvim_create_augroup('SagaLightBulb', { clear = true })
137+
create_autocmd('LspAttach', {
146138
group = g,
147139
callback = function(opt)
148140
local client = lsp.get_client_by_id(opt.data.client_id)
149-
if not client then
141+
if
142+
not client
143+
or not client.supports_method('textDocument/codeAction')
144+
or vim.list_contains(config.ignore.clients, client.name)
145+
or vim.list_contains(config.ignore.ft, vim.bo.filetype)
146+
then
150147
return
151148
end
152-
if not client.supports_method('textDocument/codeAction') then
149+
if #api.nvim_get_autocmds({ group = g, buffer = opt.buf, event = 'CursorMoved' }) > 0 then
153150
return
154151
end
155-
if vim.tbl_contains(config.lightbulb.ignore.clients, client.name) then
156-
return
157-
end
158-
if vim.tbl_contains(config.lightbulb.ignore.ft, vim.bo.filetype) then
159-
return
160-
end
161-
162152
local buf = opt.buf
163-
local group_name = name .. tostring(buf)
164-
local ok = pcall(api.nvim_get_autocmds, { group = group_name })
165-
if ok then
166-
return
167-
end
168-
local group = api.nvim_create_augroup(group_name, { clear = true })
169-
api.nvim_create_autocmd('CursorMoved', {
170-
group = group,
153+
create_autocmd('CursorMoved', {
154+
group = g,
171155
buffer = buf,
172156
callback = function(args)
173-
update(args.buf)
157+
debounce()(args.buf)
174158
end,
175159
})
176160

177-
if not config.lightbulb.enable_in_insert then
178-
api.nvim_create_autocmd('InsertEnter', {
179-
group = group,
161+
if not config.enable_in_insert then
162+
create_autocmd('InsertEnter', {
163+
group = g,
180164
buffer = buf,
181165
callback = function(args)
182-
update_lightbulb(args.buf, nil)
166+
clean_in_buf(args.buf)
183167
end,
184168
})
185169
end
186170

187-
api.nvim_create_autocmd('BufLeave', {
188-
group = group,
171+
create_autocmd('BufLeave', {
172+
group = g,
189173
buffer = buf,
190174
callback = function(args)
191-
update_lightbulb(args.buf, nil)
175+
clean_in_buf(args.buf)
192176
end,
193177
})
194178
end,
195179
})
196180

197-
api.nvim_create_autocmd('LspDetach', {
181+
create_autocmd('LspDetach', {
198182
group = g,
199183
callback = function(args)
200184
pcall(api.nvim_del_augroup_by_name, 'SagaLightBulb' .. tostring(args.buf))

lua/lspsaga/init.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ local default_config = {
5858
lightbulb = {
5959
enable = true,
6060
sign = true,
61-
debounce = 10,
62-
sign_priority = 40,
61+
debounce = 200,
62+
priority = 100,
6363
virtual_text = true,
6464
enable_in_insert = true,
6565
ignore = {

0 commit comments

Comments
 (0)