lsp.lua 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. local util = require('user.util')
  2. vim.diagnostic.config({
  3. -- only show virtual text for WARN and higher
  4. virtual_text = { severity = { min = vim.diagnostic.severity.WARN } },
  5. })
  6. vim.lsp.config('*', {
  7. flags = {
  8. debounce_text_changes = 250,
  9. }
  10. })
  11. vim.lsp.enable('bashls');
  12. vim.lsp.enable('eslint');
  13. if vim.fn.executable('dprint') == 1 then
  14. local version = vim.version.parse(vim.fn.system('dprint --version'))
  15. if vim.version.cmp(version, { 0, 45, 0 }) >= 0 then
  16. vim.lsp.enable('dprint')
  17. end
  18. end
  19. if vim.fn.executable('deno') == 1 then
  20. vim.lsp.enable('deno');
  21. else
  22. local preferences = {
  23. importModuleSpecifierPreference = 'non-relative',
  24. -- this prevents renames from aliasing when destructuring
  25. providePrefixAndSuffixTextForRename = false,
  26. }
  27. local helix_preferences = vim.tbl_get(
  28. util.read_helix_config(),
  29. 'language-server',
  30. 'typescript-language-server',
  31. 'config',
  32. 'preferences'
  33. )
  34. if helix_preferences ~= nil then
  35. preferences = vim.tbl_deep_extend('force', preferences, helix_preferences)
  36. end
  37. local function make_settings()
  38. -- we disable formatting but these are still used when performing some code
  39. -- actions
  40. local format = {
  41. indentSize = vim.bo.shiftwidth,
  42. convertTabsToSpaces = vim.o.expandtab,
  43. }
  44. return {
  45. javascript = { format = format },
  46. typescript = { format = format },
  47. }
  48. end
  49. vim.lsp.config('ts_ls', {
  50. init_options = {
  51. completionDisableFilterText = true,
  52. preferences = preferences,
  53. },
  54. settings = make_settings(),
  55. handlers = {
  56. ['$/typescriptVersion'] = function(err, result, ctx, config)
  57. vim.notify(string.format('Typescript %s', result.version))
  58. end,
  59. },
  60. on_init = function(client)
  61. -- mark tsserver as not having formatting available as we rely on
  62. -- eslint and dprint for that
  63. client.server_capabilities.documentFormattingProvider = false
  64. client.server_capabilities.documentRangeFormattingProvider = false
  65. -- we only really know our settings once we've opened a file so report
  66. -- the new formatting settings
  67. client:notify(vim.lsp.protocol.Methods.workspace_didChangeConfiguration, {
  68. settings = make_settings(),
  69. })
  70. end,
  71. })
  72. vim.lsp.enable('ts_ls')
  73. end
  74. vim.lsp.enable('svelte')
  75. vim.lsp.enable('gopls')
  76. vim.lsp.config('ruby_lsp', {
  77. init_options = {
  78. enabledFeatures = {
  79. formatting = false,
  80. },
  81. }
  82. })
  83. vim.lsp.enable('ruby_lsp')
  84. vim.lsp.enable('pyright')
  85. vim.lsp.config('nil_ls', {
  86. on_init = function(client)
  87. -- disable formatting
  88. client.server_capabilities.documentFormattingProvider = false
  89. client.server_capabilities.documentRangeFormattingProvider = false
  90. end,
  91. })
  92. vim.lsp.enable('nil_ls')
  93. vim.lsp.config('jdtls', {
  94. handlers = {
  95. ['$/progress'] = function()
  96. -- this is quite noisy so just disable it
  97. end
  98. },
  99. })
  100. vim.lsp.enable('jdtls')
  101. vim.lsp.enable('lua_ls')
  102. -- custom LSP servers
  103. vim.lsp.config('elvish', {
  104. cmd = { 'elvish', '--lsp' },
  105. filetypes = { 'elvish' },
  106. settings = {},
  107. })
  108. vim.lsp.enable('elvish')
  109. -- diagnostics
  110. vim.keymap.set('n', '<space>e', function() vim.diagnostic.open_float() end)
  111. vim.keymap.set('n', '[d',
  112. function() vim.diagnostic.jump({ count = -1, float = true, severity = vim.diagnostic.severity.ERROR }) end)
  113. vim.keymap.set('n', ']d',
  114. function() vim.diagnostic.jump({ count = 1, float = true, severity = vim.diagnostic.severity.ERROR }) end)
  115. vim.keymap.set('n', '[D', function() vim.diagnostic.jump({ count = -1, float = true }) end)
  116. vim.keymap.set('n', ']D', function() vim.diagnostic.jump({ count = 1, float = true }) end)
  117. vim.keymap.set('n', '<space>qe', function() vim.diagnostic.setqflist({ severity = vim.diagnostic.severity.ERROR }) end)
  118. vim.keymap.set('n', '<space>qw',
  119. function() vim.diagnostic.setqflist({ severity = { min = vim.diagnostic.severity.WARN } }) end)
  120. vim.keymap.set('n', '<space>qd', function() vim.diagnostic.setqflist({}) end)
  121. vim.keymap.set('n', '<space>qc', '<cmd>cclose<CR>')
  122. -- LSP-specific
  123. vim.api.nvim_create_autocmd('LspAttach', {
  124. callback = function(args)
  125. local client = vim.lsp.get_client_by_id(args.data.client_id)
  126. if client.name == 'dprint' or client.name == 'eslint' then
  127. -- mappings should have been attached by typescript and re-attaching can
  128. -- overwrite the typescript specific overrides
  129. return
  130. end
  131. local opts = { buffer = args.buf }
  132. vim.keymap.set('n', 'gD', '<cmd>lua vim.lsp.buf.declaration()<CR>', opts)
  133. vim.keymap.set('n', 'gd', '<cmd>Telescope lsp_definitions<CR>', opts)
  134. vim.keymap.set('n', '<space>D', '<cmd>Telescope lsp_type_definitions<CR>', opts)
  135. -- as much as possible we try to use the default bindings, replacing them
  136. -- with Telescope if appropriate
  137. vim.keymap.set('n', 'gri', '<cmd>Telescope lsp_implementations<CR>', opts)
  138. vim.keymap.set('n', 'grr', '<cmd>Telescope lsp_references<CR>', opts)
  139. vim.keymap.set('n', 'gO', '<cmd>Telescope lsp_document_symbols<CR>', opts)
  140. if client.name == 'ts_ls' then
  141. -- exclude import statements from reference search (may have false positives)
  142. vim.keymap.set('n', 'grr', '<cmd>Telescope lsp_references default_text=!import\\ <CR>', opts)
  143. vim.keymap.set('n', 'grA', '<cmd>LspTypescriptSourceAction<CR>', opts)
  144. end
  145. end,
  146. })
  147. -- handle file renames
  148. vim.api.nvim_create_autocmd('User', {
  149. pattern = 'MiniFilesActionRename',
  150. callback = function(opts)
  151. local params = {
  152. files = { {
  153. oldUri = vim.uri_from_fname(opts.data.from),
  154. newUri = vim.uri_from_fname(opts.data.to),
  155. } }
  156. }
  157. local bufnr = vim.fn.bufadd(opts.data.to)
  158. -- delay a bit to allow LSP clients to attach
  159. vim.defer_fn(function()
  160. local clients = vim.lsp.get_clients({ bufnr = bufnr })
  161. for _, client in ipairs(clients) do
  162. vim.notify(client.name)
  163. if client.name == 'dprint' then
  164. goto continue
  165. end
  166. if client:supports_method('workspace/willRenameFiles') then
  167. vim.notify('lsp rename')
  168. local resp = client:request_sync('workspace/willRenameFiles', params, 5000, bufnr)
  169. if resp and resp.result ~= nil then
  170. vim.lsp.util.apply_workspace_edit(resp.result, client.offset_encoding)
  171. end
  172. end
  173. ::continue::
  174. end
  175. for _, client in ipairs(clients) do
  176. if client:supports_method('workspace/didRenameFiles') then
  177. client:notify('workspace/didRenameFiles', params)
  178. end
  179. end
  180. end, 100)
  181. end,
  182. nested = true,
  183. })