williamboman / mason-lspconfig.nvim

Extension to mason.nvim that makes it easier to use lspconfig with mason.nvim.
Apache License 2.0
2.77k stars 170 forks source link

Add in function/example for automatically using installed servers with lspconfig #84

Closed xyven1 closed 2 years ago

xyven1 commented 2 years ago

Is your feature request related to a problem? Please describe.

It seems as though Mason could be a "one source of truth" so to speak about what lsp servers are installed and configured. Mason-lspconfig has all the framework needed to do this without much work. A function and/or an example in the docs of an implantation such as the one I have created would be nice.

Describe the solution you'd like

local lspconfig = require('lspconfig')
local coq = require("coq")

local function on_attach() 
   -- abbreviated
end

local registry = require "mason-registry"
local server_mapping = require "mason-lspconfig.mappings.server"

local servers = {}

-- Any lsp server which is installed by mason will automatically be added to serverlist
for _, package in ipairs(registry.get_installed_packages()) do
  local name = server_mapping.package_to_lspconfig[package.name]
  if name then
    table.insert(servers, name)
  end
end

for _, lsp in pairs(servers) do
  lspconfig[lsp].setup(coq.lsp_ensure_capabilities({
    on_attach = on_attach,
    settings = {
      Lua = {
        diagnostics = {
          globals = { 'vim' },
        },
      },
    }
  }))
end

Describe potential alternatives you've considered

With the current system one needs to statically define the servers in servers list above. This can be paired with automatic installs (which is a poor solution as its makes the one source of truth a text file, and the installed servers can't be independent of system for those of us who use one nvim config across many machines), or have a very long list of servers in your lspconfig setup so that if you happen to install a server with mason it will already be in the list (also a bad solution, for obvious reasons).

Additional context

I may be missing something very obvious, so let me know if this is all overkill.

nyngwang commented 2 years ago

[...] "one source of truth" [...] [...]

for _, lsp in pairs(servers) do
  lspconfig[lsp].setup(coq.lsp_ensure_capabilities({

When you are holding a hammer called "React", then everything looks like a "single/the source of truth". Joke aside. I don't think that is a good example because not everyone are using "coq".


According to your OP, while not sure whether this is what you meant, the following is how I did it currently, which turns out to be the simplest one since I had read through all threads in Discussion trying to find an example to copy-paste during migration from nvim-lsp-installer to mason:

require('mason-lspconfig').setup_handlers {
  -- fallback handler.
  function (server_name)
    local has_config, config = pcall(require, 'lsp_config.'..server_name)
    if not has_config then
      require('lspconfig')[server_name].setup(require('lsp_config.default'))
      return
    end
    require('lspconfig')[server_name].setup(config)
  end,
}
williamboman commented 2 years ago

If I understand you correctly this is already supported! See :h mason-lspconfig-dynamic-server-setup

xyven1 commented 2 years ago

haha, figured it was. My bad for not scanning the docs more thoroughly

pmyjavec commented 2 years ago

@williamboman I just want to say that it's very non-obvious that users need to run :h mason-lspconfig-dynamic-server-setupand then basically copy and paste the snippet:

    require("mason").setup()                                                                                                                                                 
    require("mason-lspconfig").setup()                                                                                                                                       
    require("mason-lspconfig").setup_handlers {                                                                                                                              
        -- The first entry (without a key) will be the default handler                                                                                                       
        -- and will be called for each installed server that doesn't have                                                                                                    
        -- a dedicated handler.                                                                                                                                              
        function (server_name) -- default handler (optional)                                                                                                                 
            require("lspconfig")[server_name].setup {}                                                                                                                       
        end,                                                                                                                                                                 
        -- Next, you can provide targeted overrides for specific servers.                                                                                                    
        -- For example, a handler override for the rust_analyzer:                                                                                                            
        ["rust_analyzer"] = function ()                                                                                                                                      
            require("rust-tools").setup {}                                                                                                                                   
        end                                                                                                                                                                  
    }  

Into their nvim configuration, It took me quite a while to realize this was missing before this plugin does anything, should I send a PR adding this to the README?

xyven1 commented 2 years ago

Honestly, it definitely makes sense to put that in the main readme. Seems reasonable to make a PR.

williamboman commented 1 year ago

@williamboman I just want to say that it's very non-obvious that users need to run :h mason-lspconfig-dynamic-server-setupand then basically copy and paste the snippet:

This is opt-in behaviour, the recommended method is to set up servers the "normal" way as suggested by lspconfig. I think vim helpfiles are heavily underutilized in Lua-based plugins, it's a very effective medium for documenting plugins, which is why I keep the READMEs slim and try to nudge people to consult the helpfile. :h <plugin> should be a natural thing to do, imho.

I've pushed some changes and additions to both the README as well as the vim helpfile, wdyt?