Sanchayan Maity
068dfcd4b9
vim.diagnostic framework is now available and can be used outside of LSP. This means the same functions can now work for plugins providing diagnostics via this framework like nvim-lint and null-ls.
309 lines
10 KiB
Lua
309 lines
10 KiB
Lua
local nvim_lsp = require 'lspconfig'
|
|
local protocol = require 'vim.lsp.protocol'
|
|
local signature = require 'lsp_signature'
|
|
local ts_utils = require 'nvim-lsp-ts-utils'
|
|
local null_ls = require 'null-ls'
|
|
local util = require 'lspconfig/util'
|
|
local cmp = require 'cmp_nvim_lsp'
|
|
|
|
-- https://github.com/neovim/nvim-lspconfig/wiki/User-contributed-tips
|
|
function format_range_operator()
|
|
local old_func = vim.go.operatorfunc
|
|
_G.op_func_formatting = function()
|
|
local start = vim.api.nvim_buf_get_mark(0, '[')
|
|
local finish = vim.api.nvim_buf_get_mark(0, ']')
|
|
vim.lsp.buf.range_formatting({}, start, finish)
|
|
vim.go.operatorfunc = old_func
|
|
_G.op_func_formatting = nil
|
|
end
|
|
vim.go.operatorfunc = 'v:lua.op_func_formatting'
|
|
vim.api.nvim_feedkeys('g@', 'n', false)
|
|
end
|
|
|
|
local function preview_location_callback(_, result)
|
|
if result == nil or vim.tbl_isempty(result) then
|
|
return nil
|
|
end
|
|
vim.lsp.util.preview_location(result[1])
|
|
end
|
|
|
|
function PeekDefinition()
|
|
local params = vim.lsp.util.make_position_params()
|
|
return vim.lsp.buf_request(0, 'textDocument/definition', params, preview_location_callback)
|
|
end
|
|
|
|
-- This should be called only once, so cannot be in on_attach as earlier.
|
|
-- See https://github.com/jose-elias-alvarez/null-ls.nvim/issues/38
|
|
-- Required by nvim-lsp-ts-utils to provide ESLint code actions, diagnostics
|
|
-- and formatting.
|
|
null_ls.config {}
|
|
nvim_lsp["null-ls"].setup {}
|
|
|
|
local ts_utils_setup = function(client, bufnr, opts)
|
|
if client.name == 'tsserver' then
|
|
-- Disable tsserver formatting as we plan on formatting via null-ls
|
|
client.resolved_capabilities.document_formatting = false
|
|
client.resolved_capabilities.document_range_formatting = false
|
|
|
|
ts_utils.setup {
|
|
debug = false,
|
|
disable_commands = false,
|
|
enable_import_on_completion = false,
|
|
|
|
import_all_timeout = 5000,
|
|
import_all_scan_buffers = 100,
|
|
import_all_select_source = false,
|
|
import_all_priorities = {
|
|
buffers = 4, -- loaded buffer names
|
|
buffer_content = 3, -- loaded buffer content
|
|
local_files = 2, -- git files or files with relative path markers
|
|
same_file = 1, -- add to existing import statement
|
|
},
|
|
|
|
eslint_enable_code_actions = true,
|
|
eslint_bin = "eslint",
|
|
eslint_enable_disable_comments = true,
|
|
eslint_enable_diagnostics = true,
|
|
eslint_config_fallback = nil,
|
|
eslint_show_rule_id = false,
|
|
|
|
enable_formatting = true,
|
|
formatter = "prettier",
|
|
formatter_config_fallback = nil,
|
|
|
|
update_imports_on_move = false,
|
|
require_confirmation_on_move = false,
|
|
watch_dir = nil,
|
|
|
|
filter_out_diagnostics_by_severity = {},
|
|
filter_out_diagnostics_by_code = {},
|
|
}
|
|
|
|
ts_utils.setup_client(client)
|
|
|
|
vim.api.nvim_buf_set_keymap(bufnr, 'n', 'go', ':TSLspOrganize<CR>' , opts)
|
|
vim.api.nvim_buf_set_keymap(bufnr, 'n', 'gf', ':TSLspFixCurrent<CR>', opts)
|
|
vim.api.nvim_buf_set_keymap(bufnr, 'n', 'gI', ':TSLspImportAll<CR>' , opts)
|
|
end
|
|
end
|
|
|
|
local on_attach = function(client, bufnr)
|
|
signature.on_attach({
|
|
bind = true,
|
|
hint_enable = true,
|
|
hint_prefix = "🐼 ",
|
|
hint_scheme = "String",
|
|
handler_opts = { border = "single" },
|
|
decorator = {"`", "`"}
|
|
})
|
|
vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc')
|
|
vim.lsp.set_log_level('warn')
|
|
|
|
if client.config.flags then
|
|
client.config.flags.allow_incremental_sync = true
|
|
client.config.flags.debounce_text_changes = 500
|
|
end
|
|
|
|
local opts = { noremap=true, silent=true }
|
|
|
|
vim.api.nvim_buf_set_keymap(bufnr, 'n', 'gd' , '<cmd>lua vim.lsp.buf.definition()<CR>' , opts)
|
|
vim.api.nvim_buf_set_keymap(bufnr, 'n', 'gD' , '<cmd>lua vim.lsp.buf.declaration()<CR>' , opts)
|
|
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<Leader>k', '<cmd>lua vim.lsp.buf.hover()<CR>' , opts)
|
|
vim.api.nvim_buf_set_keymap(bufnr, 'n', 'gr' , '<cmd>lua vim.lsp.buf.references()<CR>' , opts)
|
|
vim.api.nvim_buf_set_keymap(bufnr, 'n', 'ga' , '<cmd>lua vim.lsp.buf.code_action()<CR>' , opts)
|
|
vim.api.nvim_buf_set_keymap(bufnr, 'n', 'gi' , '<cmd>lua vim.lsp.buf.implementation()<CR>' , opts)
|
|
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<C-k>' , '<cmd>lua vim.lsp.buf.type_definition()<CR>' , opts)
|
|
vim.api.nvim_buf_set_keymap(bufnr, 'n', '1gd' , '<cmd>lua vim.lsp.buf.document_symbol()<CR>' , opts)
|
|
vim.api.nvim_buf_set_keymap(bufnr, 'n', '1gD' , '<cmd>lua vim.lsp.buf.workspace_symbol()<CR>', opts)
|
|
vim.api.nvim_buf_set_keymap(bufnr, 'n', 'gR' , '<cmd>lua vim.lsp.buf.rename()<CR>' , opts)
|
|
vim.api.nvim_buf_set_keymap(bufnr, 'n', 'pd' , '<cmd>lua PeekDefinition()<CR>' , opts)
|
|
|
|
if client.resolved_capabilities.document_range_formatting then
|
|
vim.api.nvim_buf_set_keymap(bufnr, 'x', 'gq', '<cmd>lua format_range_operator()<CR>', opts)
|
|
end
|
|
if client.resolved_capabilities.document_formatting then
|
|
vim.api.nvim_buf_set_keymap(bufnr, 'n', 'gq', '<cmd>lua vim.lsp.buf.formatting()<CR>', opts)
|
|
end
|
|
|
|
if client.resolved_capabilities.code_lens then
|
|
vim.api.nvim_buf_set_keymap(bufnr, "n", "gl", "<cmd>lua vim.lsp.codelens.run()<CR>", opts)
|
|
vim.api.nvim_command [[autocmd CursorHold,CursorHoldI,InsertLeave <buffer> lua vim.lsp.codelens.refresh()]]
|
|
end
|
|
|
|
protocol.CompletionItemKind = {
|
|
' '; -- text
|
|
' '; -- method
|
|
' '; -- function
|
|
'全'; -- ctor
|
|
' '; -- field
|
|
' '; -- variable
|
|
' '; -- class
|
|
' '; -- interface
|
|
' '; -- module
|
|
' '; -- property
|
|
' '; -- unit
|
|
' '; -- value
|
|
'螺'; -- enum
|
|
' '; -- keyword
|
|
' '; -- snippet
|
|
' '; -- color
|
|
' '; -- file
|
|
' '; -- reference
|
|
' '; -- folder
|
|
' '; -- enum member
|
|
' '; -- constant
|
|
' '; -- struct
|
|
' '; -- event
|
|
'璉'; -- operator
|
|
' '; -- type parameter
|
|
}
|
|
|
|
ts_utils_setup(client, bufnr, opts)
|
|
|
|
vim.cmd [[autocmd CursorHold,CursorHoldI <buffer> lua require'nvim-lightbulb'.update_lightbulb()]]
|
|
end
|
|
|
|
-- See https://github.com/sumneko/lua-language-server/wiki/Setting-without-VSCode#neovim-with-built-in-lsp-client
|
|
-- on why we do this library thing
|
|
-- Idea taken from https://gist.github.com/folke/fe5d28423ea5380929c3f7ce674c41d8
|
|
local determine_setup_lua = function ()
|
|
local library = {}
|
|
local cwd = vim.fn.getcwd()
|
|
|
|
local add_to_library = function(lib_path)
|
|
for _, p in pairs(vim.fn.expand(lib_path, false, true)) do
|
|
p = vim.loop.fs_realpath(p)
|
|
library[p] = true
|
|
end
|
|
end
|
|
|
|
if string.find(cwd, "neovim") then
|
|
add_to_library("$VIMRUNTIME")
|
|
elseif string.find(cwd, "dotfiles") then
|
|
add_to_library("$VIMRUNTIME")
|
|
add_to_library("~/.config/nvim")
|
|
add_to_library("~/.local/share/nvim/site/pack/packer/opt/*")
|
|
add_to_library("~/.local/share/nvim/site/pack/packer/start/*")
|
|
else
|
|
add_to_library(cwd .. "/*")
|
|
end
|
|
|
|
local runtime_path = vim.split(package.path, ';')
|
|
table.insert(runtime_path, "lua/?.lua")
|
|
table.insert(runtime_path, "lua/?/init.lua")
|
|
|
|
local lua_version = function()
|
|
if string.find(cwd, "neovim") or string.find(cwd, "dotfiles") then
|
|
return "LuaJIT"
|
|
else
|
|
return "Lua 5.4"
|
|
end
|
|
end
|
|
|
|
return library, runtime_path, lua_version()
|
|
end
|
|
|
|
local get_snippet_capabilities = function()
|
|
local capabilities = vim.lsp.protocol.make_client_capabilities()
|
|
|
|
capabilities.textDocument.completion.completionItem.snippetSupport = true
|
|
capabilities.textDocument.completion.completionItem.resolveSupport = {
|
|
properties = {
|
|
'documentation',
|
|
'detail',
|
|
'additionalTextEdits',
|
|
}
|
|
}
|
|
return cmp.update_capabilities(capabilities)
|
|
end
|
|
|
|
local rust_tool_opts = {
|
|
tools = {
|
|
autoSetHints = true,
|
|
hover_with_actions = false,
|
|
runnables = { use_telescope = false },
|
|
debuggables = { use_telescope = false },
|
|
inlay_hints = {
|
|
only_current_line = false,
|
|
only_current_line_autocmd = "CursorHold",
|
|
show_parameter_hints = true,
|
|
parameter_hints_prefix = "<- ",
|
|
other_hints_prefix = "=> ",
|
|
other_hints_prefix = "",
|
|
highlight = "Hint",
|
|
},
|
|
hover_actions = {
|
|
auto_focus = true
|
|
},
|
|
crate_graph = {
|
|
backend = "svg",
|
|
output = "crates_graph.svg",
|
|
full = false,
|
|
}
|
|
},
|
|
server = {
|
|
on_attach = on_attach,
|
|
capabilities = get_snippet_capabilities(),
|
|
settings = {
|
|
["rust-analyzer"] = {
|
|
checkOnSave = {
|
|
command = "clippy"
|
|
},
|
|
}
|
|
}
|
|
},
|
|
}
|
|
|
|
local servers = { 'hls', 'pylsp', 'tsserver' }
|
|
for _, lsp in ipairs(servers) do
|
|
nvim_lsp[lsp].setup {
|
|
on_attach = on_attach,
|
|
capabilities = get_snippet_capabilities(),
|
|
}
|
|
end
|
|
|
|
nvim_lsp.clangd.setup {
|
|
on_attach = on_attach,
|
|
capabilities = get_snippet_capabilities(),
|
|
default_config = {
|
|
cmd = { "clangd", "--background-index", "--pch-storage=memory", "--clang-tidy", "--suggest-missing-includes" },
|
|
filetypes = { 'c', 'cpp' },
|
|
root_dir = function(fname)
|
|
-- We specify build/compile_commands.json as that is where the compile_commands.json
|
|
-- gets generated automatically for meson projects.
|
|
local root_pattern = util.root_pattern('build/compile_commands.json', 'compile_commands.json', 'compile_flags.txt', '.git')
|
|
local filename = util.path.is_absolute(fname) and fname or util.path.join(vim.loop.cwd(), fname)
|
|
return root_pattern(filename) or util.path.dirname(filename)
|
|
end,
|
|
}
|
|
}
|
|
|
|
require('rust-tools').setup(rust_tool_opts)
|
|
|
|
library, runtime_path, lua_version = determine_setup_lua()
|
|
nvim_lsp.sumneko_lua.setup {
|
|
cmd = { "/usr/bin/lua-language-server" };
|
|
on_attach = on_attach,
|
|
capabilities = get_snippet_capabilities(),
|
|
settings = {
|
|
Lua = {
|
|
runtime = {
|
|
version = lua_version,
|
|
path = runtime_path,
|
|
},
|
|
completion = { callSnippet = "Both" },
|
|
diagnostics = {
|
|
globals = {'vim'},
|
|
},
|
|
workspace = {
|
|
library = library,
|
|
maxPreload = 2000,
|
|
preloadFileSize = 50000
|
|
},
|
|
telemetry = {
|
|
enable = false,
|
|
},
|
|
},
|
|
},
|
|
}
|