|
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 |
23 | 12 | return
|
24 | 13 | 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 |
28 | 16 |
|
29 |
| - if not row then |
| 17 | +local function update_lightbulb(bufnr, row) |
| 18 | + if not config.sign and not config.virtual_text then |
30 | 19 | return
|
31 | 20 | 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 | + }) |
53 | 28 | end
|
54 | 29 |
|
55 | 30 | local function severity_vim_to_lsp(severity)
|
@@ -105,96 +80,105 @@ local function diagnostic_vim_to_lsp(diagnostics)
|
105 | 80 | end
|
106 | 81 |
|
107 | 82 | 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] |
109 | 84 | local params = lsp.util.make_range_params()
|
110 | 85 | 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 })), |
112 | 87 | }
|
113 | 88 |
|
114 | 89 | 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) |
116 | 98 | return
|
117 | 99 | 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) |
124 | 101 | end)
|
125 | 102 | end
|
126 | 103 |
|
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 |
128 | 113 |
|
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) |
138 | 131 | end)
|
139 |
| - end) |
| 132 | + end |
140 | 133 | end
|
141 | 134 |
|
142 | 135 | 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', { |
146 | 138 | group = g,
|
147 | 139 | callback = function(opt)
|
148 | 140 | 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 |
150 | 147 | return
|
151 | 148 | 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 |
153 | 150 | return
|
154 | 151 | 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 |
| - |
162 | 152 | 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, |
171 | 155 | buffer = buf,
|
172 | 156 | callback = function(args)
|
173 |
| - update(args.buf) |
| 157 | + debounce()(args.buf) |
174 | 158 | end,
|
175 | 159 | })
|
176 | 160 |
|
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, |
180 | 164 | buffer = buf,
|
181 | 165 | callback = function(args)
|
182 |
| - update_lightbulb(args.buf, nil) |
| 166 | + clean_in_buf(args.buf) |
183 | 167 | end,
|
184 | 168 | })
|
185 | 169 | end
|
186 | 170 |
|
187 |
| - api.nvim_create_autocmd('BufLeave', { |
188 |
| - group = group, |
| 171 | + create_autocmd('BufLeave', { |
| 172 | + group = g, |
189 | 173 | buffer = buf,
|
190 | 174 | callback = function(args)
|
191 |
| - update_lightbulb(args.buf, nil) |
| 175 | + clean_in_buf(args.buf) |
192 | 176 | end,
|
193 | 177 | })
|
194 | 178 | end,
|
195 | 179 | })
|
196 | 180 |
|
197 |
| - api.nvim_create_autocmd('LspDetach', { |
| 181 | + create_autocmd('LspDetach', { |
198 | 182 | group = g,
|
199 | 183 | callback = function(args)
|
200 | 184 | pcall(api.nvim_del_augroup_by_name, 'SagaLightBulb' .. tostring(args.buf))
|
|
0 commit comments