lsp.lua 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  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('gopls')
  75. vim.lsp.config('ruby_lsp', {
  76. init_options = {
  77. enabledFeatures = {
  78. formatting = false,
  79. },
  80. }
  81. })
  82. vim.lsp.enable('ruby_lsp')
  83. vim.lsp.enable('nil_ls')
  84. vim.lsp.config('jdtls', {
  85. handlers = {
  86. ['$/progress'] = function()
  87. -- this is quite noisy so just disable it
  88. end
  89. },
  90. })
  91. vim.lsp.enable('jdtls')
  92. vim.lsp.enable('lua_ls')
  93. -- custom LSP servers
  94. vim.lsp.config('elvish', {
  95. cmd = { 'elvish', '--lsp' },
  96. filetypes = { 'elvish' },
  97. settings = {},
  98. })
  99. vim.lsp.enable('elvish')
  100. -- diagnostics
  101. vim.keymap.set('n', '<space>e', function() vim.diagnostic.open_float() end)
  102. vim.keymap.set('n', '[d',
  103. function() vim.diagnostic.jump({ count = -1, float = true, severity = vim.diagnostic.severity.ERROR }) end)
  104. vim.keymap.set('n', ']d',
  105. function() vim.diagnostic.jump({ count = 1, float = true, severity = vim.diagnostic.severity.ERROR }) end)
  106. vim.keymap.set('n', '[D', function() vim.diagnostic.jump({ count = -1, float = true }) end)
  107. vim.keymap.set('n', ']D', function() vim.diagnostic.jump({ count = 1, float = true }) end)
  108. vim.keymap.set('n', '<space>qe', function() vim.diagnostic.setqflist({ severity = vim.diagnostic.severity.ERROR }) end)
  109. vim.keymap.set('n', '<space>qw',
  110. function() vim.diagnostic.setqflist({ severity = { min = vim.diagnostic.severity.WARN } }) end)
  111. vim.keymap.set('n', '<space>qd', function() vim.diagnostic.setqflist({}) end)
  112. vim.keymap.set('n', '<space>qc', '<cmd>cclose<CR>')
  113. -- LSP-specific
  114. vim.api.nvim_create_autocmd('LspAttach', {
  115. callback = function(args)
  116. local client = vim.lsp.get_client_by_id(args.data.client_id)
  117. if client.name == 'dprint' or client.name == 'eslint' then
  118. -- mappings should have been attached by typescript and re-attaching can
  119. -- overwrite the typescript specific overrides
  120. return
  121. end
  122. local opts = { buffer = args.buf }
  123. vim.keymap.set('n', 'gD', '<cmd>lua vim.lsp.buf.declaration()<CR>', opts)
  124. vim.keymap.set('n', 'gd', '<cmd>Telescope lsp_definitions<CR>', opts)
  125. vim.keymap.set('n', '<space>D', '<cmd>Telescope lsp_type_definitions<CR>', opts)
  126. -- as much as possible we try to use the default bindings, replacing them
  127. -- with Telescope if appropriate
  128. vim.keymap.set('n', 'gri', '<cmd>Telescope lsp_implementations<CR>', opts)
  129. vim.keymap.set('n', 'grr', '<cmd>Telescope lsp_references<CR>', opts)
  130. vim.keymap.set('n', 'gO', '<cmd>Telescope lsp_document_symbols<CR>', opts)
  131. if client.name == 'ts_ls' then
  132. -- exclude import statements from reference search (may have false positives)
  133. vim.keymap.set('n', 'grr', '<cmd>Telescope lsp_references default_text=!import\\ <CR>', opts)
  134. vim.keymap.set('n', 'grA', '<cmd>LspTypescriptSourceAction<CR>', opts)
  135. end
  136. end,
  137. })
  138. -- handle file renames
  139. vim.api.nvim_create_autocmd('User', {
  140. pattern = 'MiniFilesActionRename',
  141. callback = function(opts)
  142. local params = {
  143. files = { {
  144. oldUri = vim.uri_from_fname(opts.data.from),
  145. newUri = vim.uri_from_fname(opts.data.to),
  146. } }
  147. }
  148. local bufnr = vim.fn.bufadd(opts.data.to)
  149. local clients = vim.lsp.get_clients({ bufnr = bufnr })
  150. for _, client in ipairs(clients) do
  151. if client:supports_method('workspace/willRenameFiles') then
  152. local resp = client:request_sync('workspace/willRenameFiles', params, 5000, bufnr)
  153. if resp and resp.result ~= nil then
  154. vim.lsp.util.apply_workspace_edit(resp.result, client.offset_encoding)
  155. end
  156. end
  157. end
  158. for _, client in ipairs(clients) do
  159. if client:supports_method('workspace/didRenameFiles') then
  160. client:notify('workspace/didRenameFiles', params)
  161. end
  162. end
  163. end,
  164. nested = true,
  165. })