feat(lsp): add vim.lsp.config and vim.lsp.enable#31031
feat(lsp): add vim.lsp.config and vim.lsp.enable#31031lewis6991 merged 1 commit intoneovim:masterfrom
vim.lsp.config and vim.lsp.enable#31031Conversation
e7af78e to
1d5d540
Compare
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
|
I'm happy to hear the sorts of stuff you want to configure. From my config there isn't much. From the work I've done on the handlers recently, there isn't a huge amount other than floating borders which can be done with something like Is there anything else we need to consider? For reference this is all I have in my config: local function with(f, config)
return function(c)
return f(vim.tbl_deep_extend('force', config, c or {}))
end
end
vim.lsp.buf.signature_help = with(vim.lsp.buf.signature_help, {
border = 'rounded',
title_pos = 'left',
})
local have_cmp, cmp_nvim_lsp = pcall(require, 'cmp_nvim_lsp')
if have_cmp then
local f = lsp.protocol.make_client_capabilities
lsp.protocol.make_client_capabilities = function()
return vim.tbl_deep_extend(
'force',
f(),
cmp_nvim_lsp.default_capabilities()
)
end
end |
There was a problem hiding this comment.
Maybe I've only mentioned this in chat, but I think it would be really great if a root_dir_marker ends up being a general project construct and not tied to lsp.
E.g. it could be a filetype option so one could use it with vim.filetype.get_option("lua", "root_dir_markers"). E.g. in nvim-lint this came up too and I've so far told people that they can query lsp.get_clients() and then use that root_dir. Would be nice if there were a more direct way to do that.
Other than that, this seems simple enough - I like it.
|
Ah yes, I do recall that. At least with this, markers are optional so it leaves room to retrofit a buffer option in the future. I can draft up a PR to at least see what such an option could look like. |
|
How would this work if I wanted to configure my LSP client differently for a single project? I would want to have a "main" Since each call to I mentioned in chat a while ago that I've been using my own implementation of "user-friendly LSP configuration" that uses "passive discovery" (by finding files on the user's runtimepath) rather than "active registration" (i.e. explicitly calling |
Fair question. What would you want to configure that isn't possible via Another way would to to use something like: client.notify('workspace/didChangeConfiguration', { settings = client.settings })in a LspAttach autocmd. So I guess the details matter. Note that currently the client name is used as a sort of key to prevent multiple clients attaching to the same buffer. I can't quite figure where the exact logic for this is, but the way I've been testing my multi-client handler changes is by calling
I don't think this means we can't also have and rtp based approach as well. Just like we have Does your rtp based approach have any significant differences to having something like |
Do you mean neovim/runtime/lua/vim/lsp.lua Line 265 in 0da4d89 Update: Nevermind, that's already there
Do you have a small example how that would look like? |
Maybe this is possible using only
I think the only significant difference is the fact that the rtp approach "merges" all of the files found in the rtp for a given server before calling
The user creates Lua files under an This extends well to project-local configuration. A user can create a |
d079736 to
2cfdd5a
Compare
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
"Non-server specific" means something like "global defaults"? I don't see why they would have different interfaces, in fact it would be strange if they did. |
No it does not. It means things like border hovers, quickfix handling and settings that have nothing to do with a server. Basically defaults for configs that may pass to |
|
If it's about global options, shouldn't they just use the option system? Relating to #31074 (comment) And if it's for options that are client/server specific, putting them under the same |
|
I think a big part of "API pressure" here comes from the fact that we (still) don't have table options; there is (understandable) reticence to add a bucketful of new options for different LSP (and diagnostics and treesitter and...) aspects. (And I like |
Maybe, but that then puts the existence of
Yes. I'm only suggesting we reserve It might look something like this: vim.lsp.config({
hover = {
silent = true
},
declaration = {
reuse_win = true
},
signature_help = {
silent = false
},
format = {
filter = function(client) ... end
timeout_ms = 100,
},
rename = {
filter = function() ... end
},
references = {
loclist = true,
},
code_action = {
apply = true,
}
})
Note this example includes options we already support. The schema for this config can be semi-autoamtically derived by coupling it with the functions in |
Unless options started to support namespace indexing
Fair, but I don't think the handler changes add much pressure to add these options now. Before one had to monkey patch handlers, now one could monkey patch the
Still unclear if all these aspects warrant global configuration.
But assuming global options for these is warranted - if options supported tables nicely, and these don't need client/server namespacing - this could be But independent of this aspect. I'd probably still favour |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
80f7b4b to
d0a35ad
Compare
|
@lithammer this is a formalization (and improvement) of the "lsp config" concept. nvim-lspconfig will define its configs using |
e753e41 to
04e98d9
Compare
| pcall(chunk) | ||
| end | ||
| end | ||
| pcall(vim.cmd.runtime, { ('lsp/%s.lua'):format(name), bang = true }) |
There was a problem hiding this comment.
There's also nvim__get_runtime (doesn't support globs or modelines yet, hence not used extensively so far).
1aef67a to
deee441
Compare
90eda71 to
6cbfca0
Compare
|
MacOS failures are consistent, unfortunately. |
|
I'd be really surprised if it was because of this change since I've pretty much only added new functions. EDIT: actually there is one line of code that might have caused the failures. |
|
Yep, and macOS is special since that's not where we disable file watching. |
Design goals/requirements:
- Default configuration of a server can be distributed across multiple sources.
- And via RTP discovery.
- Default configuration can be specified for all servers.
- Configuration _can_ be project specific.
Solution:
- Two new API's:
- `vim.lsp.config(name, cfg)`:
- Used to define default configurations for servers of name.
- Can be used like a table or called as a function.
- Use `vim.lsp.confg('*', cfg)` to specify default config for all
servers.
- `vim.lsp.enable(name)`
- Used to enable servers of name. Uses configuration defined
via `vim.lsp.config()`.
6cbfca0 to
d26ebab
Compare
|
@mfussenegger can you just double-check your happy with the changes to TLDR is that we now always use If that isn't acceptable, then maybe we can add an |
Sounds okay to me. |
|
Friendly reminder that any new features merged into master should be considered unstable until they are included in an official release, which will be 0.11. Until then, the API introduced with this PR is subject to changes. If there are any unresolved issues raised with the design, then we may prefix the API with |
Problem
Solution
Add
vim.lsp.enable()andvim.lsp.config().Design goals/requirements:
Proposal:
vim.lsp.config(name, cfg):vim.lsp.config(name, cfg)to extend a configurationvim.lsp.config[name] = cfgto define a configurationvim.lsp.confg('*', cfg)to specify default config for allservers.
vim.lsp.enable(name)vim.lsp.config().lsp/<name>.luato resolve configurations.vim.lsp.config[name]is accessed (read or modified).Notes:
Instead of adding
vim.lsp.config(name, cfg)I consideredvim.lsp.enable(name, cfg, config_only)wherevim.lsp.enable(name, cfg, true) === vim.lsp.config(name, cfg).I decided against this since I felt a
config_onlyfield is slightly more confusing, harder to explain and less generally appealing than havingvim.lsp.config. There is also some parallel tovim.diagnostic.enableandvim.diagnostic.config.If there is pushback to this, then I can remove that from this PR, and add it to a separate future PR for further consideration.
This PR doesn't provide a full solution for project specific config, but I'm pretty sure doesn't inhibit it. Though I think for most cases using things like
workspace/didChangeConfigurationinon_attachorLspAttachshould be sufficient.This PR is not intended to be the final end goal of LSP configuration but just a medium term stepping stone that moves us forward in the right direction.
Going forward I'd expect us to add some options into the native option system to complement (or replace) what is added here:
Buffer local options:
:setlocal lsp+=clangd:setlocal root_marker+=compile_commands.jsonLSP namespaced specific options:
:set lsp_servers.clangd.cmd=['clangd']Continuation of feat(lsp): add vim.lsp.config #18506
Todo:
Future considerations
lsp/*.lua.