Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Community curated list of preferred servers? #23

Open
dundalek opened this issue Jun 12, 2023 · 12 comments
Open

Community curated list of preferred servers? #23

dundalek opened this issue Jun 12, 2023 · 12 comments

Comments

@dundalek
Copy link
Owner

The philosophy of this plugin is to have as much as possible to work automatically without configuration and only correct when few misbehaving instances. Based on discussion in #17 people might prefer to sacrifice some lsps if it means being exposed to less potential issues.

Should we curate a list of recommended servers, e.g. pick one server when there are multiple alternatives or exclude known misbehaving ones to reduce number of issues people can run into?

For example I recall nvim-treesitter having ensure_installed that could take value "all" or "maintained" to restrict available grammars. Would it make sense to have something similar? We could have by default a "recommended" selection while providing the option to opt-in to all servers (which is the current default).

@dundalek
Copy link
Owner Author

A possible next step would be to auto-generate list of servers similarly to servers.md but grouped by the filetype that would provide a better overview of which ones can be chosen.

@jkmdn-dev
Copy link

jkmdn-dev commented Mar 15, 2024

An approach would be to have like a priority queue of LSPs for each ft. If one fails for some reason, try next available one.

Could also cache the LSP that worked and start with that LSP next time.

Pros:

  • Only one LSP will load making stuff behave better out of the box, such as formatting or double inlay hints.
  • Not a lot of work initially, and we could have community feedback on the priority queues.
  • A more sound approach than just launching all the LSPs
  • Detecting and caching the LSP per ft might let users build up a database of LSPs that works well which in turn would make it easier to fine-tune lspconfig if the user requires that without sacrificing user friendliness out of box.
  • Anything else?

Cons:

  • Possiblity of a slower startup experience if many LSPs fails before one works
  • Users might not agree with the priority of the LSPs
  • Anything else?

@dundalek
Copy link
Owner Author

I've created a script to generate a list of filetypes associated with multiple servers to serve as candidates for curation.

I would be interested for people to share (we already have some examples):

  • their configured values for excluded_servers and preferred_servers options.
  • comments like I am Foo developer and everyone uses Y-lsp over X-lsp, because X is deprecated

@dundalek
Copy link
Owner Author

I'm thinking next step could be to add the recommended options as a starting point to the configuration example in the README.

@fdietze
Copy link
Contributor

fdietze commented Mar 21, 2024

Just opened a typescript file and was overwhelmed by all those language servers that started up 😆 . It made me realize that language-servers and formatters are project specific. No community curated list will work for actively developing a project. In some project I want to have specific ones in another project I need others. For example npm vs deno typscript projects. Having all language servers or a list of community generated ones is wrong for projects one actively works on, instead the lsps should be already in scope using tools like nix-shell/flakes/devbox/flox etc .

On the other hand, browsing unknown projects is an important use-case as well. And in this case, a community curated list of lsps lazily started in a nix-shell would be great. So one probably wants to start language-servers for out-of-project files on demand: Have a keybinding/commad, which fires up the community curated language-servers for the current file.

@dundalek
Copy link
Owner Author

Just opened a typescript file and was overwhelmed by all those language servers that started up 😆 .

Yeah, JS/TS is a bit wild by default, but it is also an exception because the ecosystem is so large and diverse.

Having all language servers or a list of community generated ones is wrong for projects one actively works on, instead the lsps should be already in scope using tools like nix-shell/flakes/devbox/flox etc .

This gives me an idea that it would be possible to automatically enable only LSPs that are installed. But on the second thought if that is desired one can just write a for loop in config so there is no need to have a plugin for that.


In conclusion, after running the stats I see these patterns:

  1. modern languages (like Go, Rust, Kotlin, Elixir, Zig) have one official implementation - no issue here
  2. previous generation languages (like Python, Java, PHP, Ruby) have multiple efforts, but over time some get deprecated and will likely also consolidate towards one - we can run multiple ones for redundancy and in the future reduce suggestion
  3. JS/TS is a special category, but suggesting eslint and tsserver should work for majority by default. If not it can be configured based on specific needs.

@dundalek
Copy link
Owner Author

dundalek commented Mar 22, 2024

I've created an initial curated configuration: https://github.com/dundalek/lazy-lsp.nvim/blob/master/servers.md#curated-servers

The downside is one needs to copy it to their config. I think I would be comfortable by enabling this subset by default.

However, the challenge is then how to expose the options to override these in case someone wants a server that was excluded. And how not to make it confusing how to find out which servers are enabled and which are not.

@zoriya I would be curious if you have any thoughts?

@zoriya
Copy link
Contributor

zoriya commented Mar 22, 2024

I think excluding archived servers by default is a sane default, I don't like the idea of excluding lps to prefer another one.
So

{
    "ccls",                            -- prefer clangd
    "denols",                          -- prefer eslint and tsserver
    "docker_compose_language_service", -- yamlls should be enough?
    "flow",                            -- prefer eslint and tsserver
}

feels wrong to me. I would think that having those in preferred_servers would be better. Users could then override the preferred_servers section in their own config if they want to use something else instead.

For reference, this is my exclude/preferred config:

excluded_servers = {
	-- Disable generic purpose LSP that I don't care about.
	"efm",
	"diagnosticls",
	-- Bugged servers
	"sqls",
	"rome",
},
prefer_local = true,
preferred_servers = {
	haskell = { "hls" },
	rust = { "rust_analyzer" },
	c = { "clangd" },
	cpp = { "clangd" },
	cs = { "omnisharp" },
	python = { "pyright" },
	nix = { "nil_ls" },
	typescript = { "tsserver" },
	javascript = { "tsserver" },
	jsx = { "tsserver" },
	tsx = { "tsserver" },
	javascriptreact = { "tsserver" },
	typescriptreact = { "tsserver" },
	go = { "gopls" },
	json = { "jsonls" },
	yaml = { "yamlls" },
},

@dundalek
Copy link
Owner Author

That's a good point, if the default curation is only done using preferred_servers than it is straighforward to override just by merging tables.

The thing I don't like is the duplication since js/ts is spread over 6 filetypes and for example ccls is part of 5 filetypes.

-- Bugged servers
"sqls",
"rome",

BTW these were dropped from nixpkgs, you can remove them for a cleaner config.

@zoriya
Copy link
Contributor

zoriya commented Mar 23, 2024

I think it is okay to have multiples file types for the same lsp. For the case of ccls, I could want to override the objc lsp while keeping the cpp's lsp to the community curated one.

I do agree that JS cases is weird, but that's just to show how much the JS community is split. I see two ways of handling that:

  • either by creating a meta filetype that would apply this logic to typescript, javascript, jsx, tsx and all the other variants
  • or by simply not doing anything special and specifying every js variant as its own entry.

I do think the second one is both simpler to write and simpler to understand, as you do not need to know lazy-lsp does some kind of magic for js.

@fdietze
Copy link
Contributor

fdietze commented Mar 24, 2024

This gives me an idea that it would be possible to automatically enable only LSPs that are installed. But on the second thought if that is desired one can just write a for loop in config so there is no need to have a plugin for that.

I even implemented this quickly for myself, so that every installed server is automatically picked up. This felt good at first because I was working on my own project, where I know the tooling.

But opening another project sent me into this rabbit hole of deciding which language server to install. And here, the community curated preferences would be awesome.

So somehow I want community curated lsps everywhere except for projects where I explicitly want to make a choice. VSCode has some project-local configs, where they list recommended extensions. Maybe a similar standard for vim makes sense. Or even better an editor-independent standard for defining, lsps, formatters, linters etc for the project.

@dundalek
Copy link
Owner Author

I recently learned about the lspconfig autostart options (which is by default true).

Another idea for curation would be to not exclude some servers from setup completely, but instead set autostart to false, so they are not started automatically (which solves the problem of being overwhelmed with too many servers), but the user could start them manually using :LspStart when being inside a specific file.

An example is ltex (grammar checking for markdown), which is quite heavy on CPU, but it is still useful to have ability to start it manually.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants