Using LSP without nvim-lspconfig
I'm not a fan of lspconfig because I think it abstracts too much of how neovim functions behind obscure lua code. Imo, you really don't need to be that proficient in lua before you can figure out what's happening behind the scenes with your editor.
If your goal is to be proficient in neovim and lua such that you can write your own scripts when the need rises, you should imo try to do without lspconfig.
All that happens really is that neovim launches a particular binary, with particular settings when a particular filetype is opened.
This is all you need to have in your init.lua
to set up lua language server:
vim.api.nvim_create_autocmd('FileType', {
pattern = 'lua',
callback = function(ev)
vim.lsp.start({
name = "lua_ls",
cmd = { 'lua-language-server' },
root_dir = vim.fs.root(ev.buf, { '.luarc.json', '.luarc.jsonc' }),
settings = {
Lua = {
runtime = {
version = "LuaJIT",
},
workspace = {
library = {
"/usr/share/nvim/runtime",
}
},
},
},
})
end,
})
Its so obvious what's going on right? We just create an autocommand. Whenever a
filetype lua is opened, the function in callback gets executed. All that
function does is launches the binary of language server. Now, if you've ever
looked into the differences between treesitter and lsp, you might know that
unlike treesitter the lsp is aware of your project as a whole. It knows what
you should import from another file so that the variables in the current file
you're editing is in scope. For that to happen, you need to let the lsp know
which directory is the root of the project. This is why there's a root_dir
argument.
You can find out what goes into settings
argument by reading the
documentation of the specific language server and by checking out server-configurations
page in nvim-lspconfig:
https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md
In lua for example, this section reveals what the settings should be:
client.config.settings.Lua = vim.tbl_deep_extend('force', client.config.settings.Lua, {
runtime = {
-- Tell the language server which version of Lua you're using
-- (most likely LuaJIT in the case of Neovim)
version = 'LuaJIT'
},
-- Make the server aware of Neovim runtime files
workspace = {
checkThirdParty = false,
library = {
vim.env.VIMRUNTIME
-- Depending on the usage, you might want to add additional paths here.
-- "${3rd}/luv/library"
-- "${3rd}/busted/library",
}
-- or pull in all of 'runtimepath'. NOTE: this is a lot slower
-- library = vim.api.nvim_get_runtime_file("", true)
}
})
Additional example (dart language server):
vim.api.nvim_create_autocmd('FileType', {
pattern = 'dart',
callback = function(ev)
vim.lsp.start({
name = "dartls",
cmd = { 'dart', 'language-server', '--protocol=lsp' },
root_dir = vim.fs.root(ev.buf, { 'pubspec.yaml' }),
init_options = {
closingLabels = true,
flutterOutline = true,
onlyAnalyzeProjectsWithOpenFiles = true,
outline = true,
suggestFromUnimportedLibraries = true
},
settings = {
dart = {
completeFunctionCalls = true,
showTodos = true,
},
},
})
end,
})