Skip to content

Commit

Permalink
feat: add the ability to hotpatch mason-lspconfig.nvim with more ls…
Browse files Browse the repository at this point in the history
…p/package mappings
  • Loading branch information
mehalter committed Jan 30, 2025
1 parent 60e6c83 commit 0787a50
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 6 deletions.
31 changes: 25 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,21 @@ local opts = {
},
},
},
-- Extra configuration for the `mason-lspconfig.nvim` plugin
mason_lspconfig = {
-- Allow registering more Mason packages as language servers for autodetection/setup
servers = {
-- The key is the lspconfig server name to register a package for
nextflow_ls = {
-- The Mason package name to register to the language server
package = "nextflow-language-server",
-- The filetypes that apply to the package and language server
filetypes = { "nextflow" },
-- (Optional) any default configuration changes that may need to happen (can be a table or a function that returns a table)
config = { cmd = { "nextflow-language-server" } }
}
}
}
-- A list like table of servers that should be setup, useful for enabling language servers not installed with Mason.
servers = { "dartls" },
-- A custom `on_attach` function to be run after the default `on_attach` function, takes two parameters `client` and `bufnr` (`:h lspconfig-setup`)
Expand Down Expand Up @@ -217,12 +232,16 @@ local opts = {
{
"williamboman/mason-lspconfig.nvim", -- MUST be set up before `nvim-lspconfig`
dependencies = { "williamboman/mason.nvim" },
opts = function()
return {
-- use AstroLSP setup for mason-lspconfig
handlers = { function(server) require("astrolsp").lsp_setup(server) end },
}
end,
opts = {
-- use AstroLSP setup for mason-lspconfig
handlers = { function(server) require("astrolsp").lsp_setup(server) end },
},
config = function(_, opts)
-- Optionally tell AstroLSP to register new language servers before calling the `setup` function
-- this enables the `mason-lspconfig.servers` option in the AstroLSP configuration
require("astrolsp.mason-lspconfig").register_servers()
require("mason-lspconfig").setup(opts)
end
},
},
config = function()
Expand Down
26 changes: 26 additions & 0 deletions lua/astrolsp/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@
---@field hover vim.lsp.buf.hover.Opts? control the default options for `vim.lsp.buf.hover()` (`:h vim.lsp.buf.hover.Opts`)
---@field signature_help vim.lsp.buf.signature_help.Opts? control the default options for `vim.lsp.buf.signature_help()` (`:h vim.lsp.buf.signature_help.Opts`)

---@class AstroLSPMasonLspconfigServer
---@field public package string the Mason package name
---@field filetypes string|string[] the filetype(s) that the server applies to
---@field config? table|(fun(): table) extensions tothe default language server configuration

---@alias AstroLSPMasonLspconfigServers { [string]: AstroLSPMasonLspconfigServer }

---@class AstroLSPMasonLspconfigOpts
---@field servers AstroLSPMasonLspconfigServers? a table of servers to register with mason-lspconfig.nvim

---@class AstroLSPOpts
---Configuration of auto commands
---The key into the table is the group name for the auto commands (`:h augroup`) and the value
Expand Down Expand Up @@ -253,6 +263,21 @@
---}
---```
---@field mappings AstroLSPMappings?
---Extra options for the `mason-lspconfig.nvim` plugin such as registering new packages as language servers.
---Example:
--
---```lua
---mason_lspconfig = {
--- servers = {
--- nextflow_ls = {
--- package = "nextflow-language-server",
--- filetypes = "nextflow",
--- config = { cmd = { "nextflow-language-server" } }
--- }
--- }
---}
---```
---@field mason_lspconfig AstroLSPMasonLspconfigOpts?
---A list like table of servers that should be setup, useful for enabling language servers not installed with Mason.
---Example:
--
Expand Down Expand Up @@ -292,6 +317,7 @@ local M = {
handlers = {},
lsp_handlers = {},
mappings = {},
mason_lspconfig = {},
servers = {},
on_attach = nil,
}
Expand Down
60 changes: 60 additions & 0 deletions lua/astrolsp/mason-lspconfig.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
---AstroNvim mason-lspconfig Utilities
---
---Utilities for working with mason-lspconfig.nvim
---
---This module can be loaded with `local astro_mason_lspconfig = require "astrocore.mason-lspconfig"`
---
---copyright 2025
---license GNU General Public License v3.0
---@class astrocore.mason-lspconfig
local M = {}

local function resolve_config() return require("astrolsp").config.mason_lspconfig or {} end

--- Register a new language server with mason-lspconfig
---@param server string the server name in lspconfig
---@param spec AstroLSPMasonLspconfigServer the details for registering the server
function M.register_server(server, spec)
local filetype_mappings_avail, filetype_mappings = pcall(require, "mason-lspconfig.mappings.filetype")
local server_mappings_avail, server_mappings = pcall(require, "mason-lspconfig.mappings.server")

if not (filetype_mappings_avail and server_mappings_avail) then
vim.notify("Unable to properly load required `mason-lspconfig` modules", vim.log.levels.ERROR)
end

-- register server in the filetype maps
local filetypes = spec.filetypes
if type(filetypes) ~= "table" then filetypes = { filetypes } end
for _, filetype in ipairs(filetypes) do
if not filetype_mappings[filetype] then filetype_mappings[filetype] = {} end
table.insert(filetype_mappings, server)
end
-- register the mappings between lspconfig server name and mason package name
server_mappings.lspconfig_to_package[server] = spec.package
server_mappings.package_to_lspconfig[spec.package] = server
-- if a config is provided, set up a mason-lspconfig server configuration module
if spec.config then
local module = spec.config
if type(module) == "table" then
local orig_function = module
module = function() return orig_function end
end
local module_name = "mason-lspconfig.server_configurations." .. server
if package.loaded[module_name] == nil then
package.preload[module_name] = function() return module end
else
package.loaded[module_name] = module
end
end
end

--- Register multiple new language servers with mason-lspconfig
---@param server_specs? AstroLSPMasonLspconfigServers
function M.register_servers(server_specs)
if not server_specs then server_specs = resolve_config().servers or {} end
for server, spec in pairs(server_specs) do
M.register_server(server, spec)
end
end

return M

0 comments on commit 0787a50

Please sign in to comment.