Advertisement
Guest User

Dynamically enable/disable some LSP features

a guest
May 1st, 2025
141
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.67 KB | Source Code | 0 0
  1. ---@class _MethodState
  2. ---@field is_enabled boolean
  3. ---@field enable function
  4. ---@field disable function
  5.  
  6. ---@class _BufferState
  7. ---@field document_highlight? _MethodState
  8. ---@field inlay_hint? _MethodState
  9. ---@field codelens? _MethodState
  10.  
  11. ---@type table<integer, _BufferState>
  12. local STATE_PER_ATTACHED_BUFFER = {}
  13.  
  14. -- help functions to aide avoid large levels of indentation
  15. local H = {
  16.   inlay_hint = {},
  17.   codelens = {},
  18.   document_highlight = {},
  19. }
  20.  
  21. local timer = vim.uv.new_timer()
  22. timer:start(
  23.   tonumber(vim.g.lsp_refresh_time) or 1000,
  24.   tonumber(vim.g.lsp_refresh_time) or 1000,
  25.   vim.schedule_wrap(function()
  26.     local function handler(buf, state, kind)
  27.       if not vim.api.nvim_buf_is_valid(buf) or not (state and state[kind]) then
  28.         return
  29.       end
  30.  
  31.       if H.should_be_enabled(buf, kind) then
  32.         state[kind].enable()
  33.       else
  34.         state[kind].disable()
  35.       end
  36.     end
  37.  
  38.     for buf, state in pairs(STATE_PER_ATTACHED_BUFFER) do
  39.       for _, kind in ipairs({ 'document_highlight', 'inlay_hint', 'codelens' }) do
  40.         handler(buf, state, kind)
  41.       end
  42.     end
  43.   end)
  44. )
  45.  
  46. vim.api.nvim_create_augroup('lsp_attach', { clear = true })
  47. vim.api.nvim_create_augroup('lsp_deatach', { clear = true })
  48. vim.api.nvim_create_augroup('lsp_document_highlight_clear', { clear = true })
  49. vim.api.nvim_create_augroup('lsp_document_highlight', { clear = false })
  50. vim.api.nvim_create_augroup('lsp_inlay_hint', { clear = false })
  51. vim.api.nvim_create_augroup('lsp_codelens', { clear = false })
  52.  
  53. vim.api.nvim_create_autocmd('LspAttach', {
  54.   group = 'lsp_attach',
  55.   callback = function(ev)
  56.     local client = vim.lsp.get_client_by_id(ev.data.client_id)
  57.    
  58.     for kind, method in pairs({
  59.       document_highlight = 'textDocument/documentHighlight',
  60.       inlay_hint = 'textDocument/inlayHint',
  61.       codelens = 'textDocument/codeLens',
  62.     }) do
  63.       if client:supports_method(method) then
  64.         STATE_PER_ATTACHED_BUFFER[ev.buf] = STATE_PER_ATTACHED_BUFFER[ev.buf] or {}
  65.         STATE_PER_ATTACHED_BUFFER[ev.buf][kind] = STATE_PER_ATTACHED_BUFFER[ev.buf][kind] or {}
  66.  
  67.         local state = STATE_PER_ATTACHED_BUFFER[ev.buf][kind]
  68.  
  69.         function state.enable()
  70.           H[kind].enable(ev.buf, state)
  71.         end
  72.  
  73.         function state.disable()
  74.           H[kind].disable(ev.buf, state)
  75.         end
  76.  
  77.         if H.should_be_enabled(ev.buf, kind) then
  78.           state.enable()
  79.         else
  80.           state.is_enabled = false
  81.         end
  82.       end
  83.     end
  84.   end,
  85. })
  86.  
  87. vim.api.nvim_create_autocmd('LspDetach', {
  88.   group = 'lsp_deatach',
  89.   callback = function(ev)
  90.     for kind, method in pairs({
  91.       document_highlight = 'textDocument/documentHighlight',
  92.       inlay_hint = 'textDocument/inlayHint',
  93.       codelens = 'textDocument/codeLens',
  94.     }) do
  95.       if
  96.         not vim.iter(vim.lsp.get_clients({ bufnr = ev.buf })):any(function(client)
  97.           return client.id ~= ev.data.client_id and client:supports_method(method)
  98.         end)
  99.       then
  100.         STATE_PER_ATTACHED_BUFFER[ev.buf][kind] = nil
  101.       end
  102.     end
  103.  
  104.     if vim.tbl_isempty(STATE_PER_ATTACHED_BUFFER[ev.buf]) then
  105.       STATE_PER_ATTACHED_BUFFER[ev.buf] = nil
  106.     end
  107.   end,
  108. })
  109.  
  110. function H.should_be_enabled(buf, kind)
  111.   local index = 'lsp_' .. kind .. '_enable'
  112.   local b_var = vim.b[buf][index]
  113.   local g_var = vim.g[index]
  114.  
  115.   return (b_var == nil) and (g_var == true) or (b_var == true)
  116. end
  117.  
  118. function H.document_highlight.enable(buf, state)
  119.   if not state.is_enabled then
  120.     state.is_enabled = true
  121.  
  122.     vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, {
  123.       buffer = buf,
  124.       group = 'lsp_document_highlight',
  125.       callback = vim.lsp.buf.document_highlight,
  126.     })
  127.  
  128.     vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI', 'LspDetach' }, {
  129.       buffer = buf,
  130.       group = 'lsp_document_highlight',
  131.       callback = vim.lsp.buf.clear_references,
  132.     })
  133.  
  134.     vim.api.nvim_create_autocmd('LspDetach', {
  135.       group = 'lsp_document_highlight_clear',
  136.       callback = function(ev)
  137.         -- remove the above autocmds if the buffer does not have any
  138.         -- attached client that supports document highlight
  139.         if
  140.           not vim.iter(vim.lsp.get_clients({ bufnr = buf })):any(function(client)
  141.             return client.id ~= ev.data.client_id
  142.               and client:supports_method('textDocument/documentHighlight')
  143.           end)
  144.         then
  145.           vim.api.nvim_clear_autocmds({
  146.             buffer = buf,
  147.             group = 'lsp_document_highlight',
  148.           })
  149.         end
  150.       end,
  151.     })
  152.   end
  153. end
  154.  
  155. function H.document_highlight.disable(buf, state)
  156.   if state.is_enabled then
  157.     state.is_enabled = false
  158.  
  159.     vim.api.nvim_buf_call(buf, function()
  160.       vim.lsp.buf.clear_references()
  161.     end)
  162.  
  163.     vim.api.nvim_clear_autocmds({
  164.       buffer = buf,
  165.       group = 'lsp_document_highlight',
  166.     })
  167.  
  168.     vim.api.nvim_clear_autocmds({
  169.       buffer = buf,
  170.       group = 'lsp_document_highlight_clear',
  171.     })
  172.   end
  173. end
  174.  
  175. function H.inlay_hint.enable(buf, state)
  176.   if not state.is_enabled then
  177.     state.is_enabled = true
  178.  
  179.     vim.lsp.inlay_hint.enable(true, { bufnr = buf })
  180.  
  181.     vim.api.nvim_create_autocmd('InsertEnter', {
  182.       group = 'lsp_inlay_hint',
  183.       buffer = buf,
  184.       callback = function()
  185.         vim.lsp.inlay_hint.enable(false, { bufnr = buf })
  186.       end,
  187.     })
  188.  
  189.     vim.api.nvim_create_autocmd('InsertLeave', {
  190.       group = 'lsp_inlay_hint',
  191.       buffer = buf,
  192.       callback = function()
  193.         vim.lsp.inlay_hint.enable(true, { bufnr = buf })
  194.       end,
  195.     })
  196.   end
  197. end
  198.  
  199. function H.inlay_hint.disable(buf, state)
  200.   if state.is_enabled then
  201.     state.is_enabled = false
  202.     vim.lsp.inlay_hint.enable(false, { bufnr = buf })
  203.     vim.api.nvim_clear_autocmds({
  204.       group = 'lsp_inlay_hint',
  205.       buffer = buf,
  206.     })
  207.   end
  208. end
  209.  
  210. function H.codelens.enable(buf, state)
  211.   if not state.is_enabled then
  212.     state.is_enabled = true
  213.  
  214.     vim.lsp.codelens.refresh({ bufnr = buf })
  215.  
  216.     vim.api.nvim_create_autocmd({ 'BufEnter', 'CursorHold', 'InsertLeave' }, {
  217.       group = 'lsp_codelens',
  218.       buffer = buf,
  219.       callback = function()
  220.         vim.lsp.codelens.refresh({ bufnr = buf })
  221.       end,
  222.     })
  223.  
  224.     vim.api.nvim_create_autocmd('InsertEnter', {
  225.       group = 'lsp_codelens',
  226.       buffer = buf,
  227.       callback = function()
  228.         vim.lsp.codelens.clear(nil, buf)
  229.       end,
  230.     })
  231.   end
  232. end
  233.  
  234. function H.codelens.disable(buf, state)
  235.   if state.is_enabled then
  236.     state.is_enabled = false
  237.     vim.lsp.codelens.clear(nil, buf)
  238.  
  239.     vim.api.nvim_clear_autocmds({
  240.       group = 'lsp_codelens',
  241.       buffer = buf,
  242.     })
  243.   end
  244. end
Tags: neovim
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement