Skip to content

Commit f77e382

Browse files
committed
feat(mason)!: migrate to v2.x
1 parent f6a4d36 commit f77e382

File tree

6 files changed

+126
-78
lines changed

6 files changed

+126
-78
lines changed
Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,25 @@
11
return function()
2-
local nvim_lsp = require("lspconfig")
32
require("completion.mason").setup()
43
require("completion.mason-lspconfig").setup()
54

65
local capabilities = vim.lsp.protocol.make_client_capabilities()
76
local opts = {
87
capabilities = vim.tbl_deep_extend("force", capabilities, require("blink.cmp").get_lsp_capabilities({}, false)),
98
}
10-
-- Setup lsps that are not supported by `mason.nvim` but supported by `nvim-lspconfig` here.
9+
-- Configure LSPs that are not supported by `mason.nvim` but are available in `nvim-lspconfig`.
10+
-- First call |vim.lsp.config()|, then |vim.lsp.enable()| (or use `register_server`, see below)
11+
-- to ensure the language server is properly configured and starts automatically.
1112
if vim.fn.executable("dart") == 1 then
1213
local ok, _opts = pcall(require, "user.configs.lsp-servers.dartls")
1314
if not ok then
1415
_opts = require("completion.servers.dartls")
1516
end
1617
local final_opts = vim.tbl_deep_extend("keep", _opts, opts)
17-
nvim_lsp.dartls.setup(final_opts)
18+
require("modules.utils").register_server("dartls", final_opts)
1819
end
1920

2021
pcall(require, "user.configs.lsp")
22+
23+
-- Start LSPs
24+
pcall(vim.cmd.LspStart)
2125
end

lua/modules/configs/completion/mason-lspconfig.lua

Lines changed: 103 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
local M = {}
22

33
M.setup = function()
4+
local is_windows = require("core.global").is_windows
5+
46
local lsp_deps = require("core.settings").lsp_deps
7+
local mason_registry = require("mason-registry")
8+
local mason_lspconfig = require("mason-lspconfig")
59

610
require("lspconfig.ui.windows").default_options.border = "rounded"
711
require("modules.utils").load_plugin("mason-lspconfig", {
812
ensure_installed = lsp_deps,
13+
-- Skip auto enable because we are loading language servers lazily
14+
automatic_enable = false,
915
})
1016

1117
vim.diagnostic.config({
@@ -48,16 +54,16 @@ please REMOVE your LSP configuration (rust_analyzer.lua) from the `servers` dire
4854

4955
if not ok then
5056
-- Default to use factory config for server(s) that doesn't include a spec
51-
vim.lsp.config(lsp_name, opts)
52-
vim.lsp.enable(lsp_name)
57+
require("modules.utils").register_server(lsp_name, opts)
5358
elseif type(custom_handler) == "function" then
54-
--- Case where language server requires its own setup
55-
--- Make sure to call require("lspconfig")[lsp_name].setup() in the function
56-
--- See `clangd.lua` for example.
59+
-- Case where language server requires its own setup
60+
-- Be sure to call `vim.lsp.config()` within the setup function.
61+
-- Refer to |vim.lsp.config()| for documentation.
62+
-- For an example, see `clangd.lua`.
5763
custom_handler(opts)
5864
vim.lsp.enable(lsp_name)
5965
elseif type(custom_handler) == "table" then
60-
vim.lsp.config(
66+
require("modules.utils").register_server(
6167
lsp_name,
6268
vim.tbl_deep_extend(
6369
"force",
@@ -80,9 +86,98 @@ please REMOVE your LSP configuration (rust_analyzer.lua) from the `servers` dire
8086
end
8187
end
8288

83-
for _, lsp in ipairs(lsp_deps) do
84-
mason_lsp_handler(lsp)
89+
---A simplified mimic of <mason-lspconfig 1.x>'s `setup_handlers` callback.
90+
---Invoked for each Mason package (name or `Package` object) to configure its language server.
91+
---@param pkg string|{name: string} Either the package name (string) or a Package object
92+
local function setup_lsp_for_package(pkg)
93+
-- First try to grab the builtin mappings
94+
local mappings = mason_lspconfig.get_mappings().package_to_lspconfig
95+
-- If empty or nil, build it by hand
96+
if not mappings or vim.tbl_isempty(mappings) then
97+
mappings = {}
98+
for _, spec in ipairs(mason_registry.get_all_package_specs()) do
99+
local lspconfig = vim.tbl_get(spec, "neovim", "lspconfig")
100+
if lspconfig then
101+
mappings[spec.name] = lspconfig
102+
end
103+
end
104+
end
105+
106+
-- Figure out the package name and lookup
107+
local name = type(pkg) == "string" and pkg or pkg.name
108+
local srv = mappings[name]
109+
if not srv then
110+
return
111+
end
112+
113+
-- Invoke the handler
114+
mason_lsp_handler(srv)
115+
end
116+
117+
for _, pkg in ipairs(mason_registry.get_installed_package_names()) do
118+
setup_lsp_for_package(pkg)
85119
end
120+
121+
-- Hook into Mason's package install event to install extra plugins for pylsp (black, ruff, rope),
122+
-- then configure the installed package's LSP using setup_lsp_for_package.
123+
mason_registry:on(
124+
"package:install:success",
125+
vim.schedule_wrap(function(pkg)
126+
if pkg.name == "python-lsp-server" then
127+
local venv = vim.fn.stdpath("data") .. "/mason/packages/python-lsp-server/venv"
128+
local python = is_windows and venv .. "/Scripts/python.exe" or venv .. "/bin/python"
129+
local black = is_windows and venv .. "/Scripts/black.exe" or venv .. "/bin/black"
130+
local ruff = is_windows and venv .. "/Scripts/ruff.exe" or venv .. "/bin/ruff"
131+
132+
require("plenary.job")
133+
:new({
134+
command = python,
135+
args = {
136+
"-m",
137+
"pip",
138+
"install",
139+
"-U",
140+
"--disable-pip-version-check",
141+
"python-lsp-black",
142+
"python-lsp-ruff",
143+
"pylsp-rope",
144+
},
145+
cwd = venv,
146+
env = { VIRTUAL_ENV = venv },
147+
on_exit = function()
148+
if vim.fn.executable(black) == 1 and vim.fn.executable(ruff) == 1 then
149+
vim.notify(
150+
"Finished installing pylsp plugins",
151+
vim.log.levels.INFO,
152+
{ title = "[lsp] Install Status" }
153+
)
154+
else
155+
vim.notify(
156+
"Failed to install pylsp plugins. [Executable not found]",
157+
vim.log.levels.ERROR,
158+
{ title = "[lsp] Install Failure" }
159+
)
160+
end
161+
end,
162+
on_start = function()
163+
vim.notify(
164+
"Now installing pylsp plugins...",
165+
vim.log.levels.INFO,
166+
{ title = "[lsp] Install Status", timeout = 6000 }
167+
)
168+
end,
169+
on_stderr = function(_, msg_stream)
170+
if msg_stream then
171+
vim.notify(msg_stream, vim.log.levels.ERROR, { title = "[lsp] Install Failure" })
172+
end
173+
end,
174+
})
175+
:start()
176+
end
177+
178+
setup_lsp_for_package(pkg)
179+
end)
180+
)
86181
end
87182

88183
return M
Lines changed: 0 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
local M = {}
22

33
M.setup = function()
4-
local is_windows = require("core.global").is_windows
5-
6-
local mason_registry = require("mason-registry")
7-
require("lspconfig.ui.windows").default_options.border = "rounded"
8-
94
local icons = {
105
ui = require("modules.utils.icons").get("ui", true),
116
misc = require("modules.utils.icons").get("misc", true),
@@ -31,66 +26,6 @@ M.setup = function()
3126
},
3227
},
3328
})
34-
35-
-- Additional plugins for pylsp
36-
mason_registry:on(
37-
"package:install:success",
38-
vim.schedule_wrap(function(pkg)
39-
if pkg.name ~= "python-lsp-server" then
40-
return
41-
end
42-
43-
local venv = vim.fn.stdpath("data") .. "/mason/packages/python-lsp-server/venv"
44-
local python = is_windows and venv .. "/Scripts/python.exe" or venv .. "/bin/python"
45-
local black = is_windows and venv .. "/Scripts/black.exe" or venv .. "/bin/black"
46-
local ruff = is_windows and venv .. "/Scripts/ruff.exe" or venv .. "/bin/ruff"
47-
48-
require("plenary.job")
49-
:new({
50-
command = python,
51-
args = {
52-
"-m",
53-
"pip",
54-
"install",
55-
"-U",
56-
"--disable-pip-version-check",
57-
"python-lsp-black",
58-
"python-lsp-ruff",
59-
"pylsp-rope",
60-
},
61-
cwd = venv,
62-
env = { VIRTUAL_ENV = venv },
63-
on_exit = function()
64-
if vim.fn.executable(black) == 1 and vim.fn.executable(ruff) == 1 then
65-
vim.notify(
66-
"Finished installing pylsp plugins",
67-
vim.log.levels.INFO,
68-
{ title = "[lsp] Install Status" }
69-
)
70-
else
71-
vim.notify(
72-
"Failed to install pylsp plugins. [Executable not found]",
73-
vim.log.levels.ERROR,
74-
{ title = "[lsp] Install Failure" }
75-
)
76-
end
77-
end,
78-
on_start = function()
79-
vim.notify(
80-
"Now installing pylsp plugins...",
81-
vim.log.levels.INFO,
82-
{ title = "[lsp] Install Status", timeout = 6000 }
83-
)
84-
end,
85-
on_stderr = function(_, msg_stream)
86-
if msg_stream then
87-
vim.notify(msg_stream, vim.log.levels.ERROR, { title = "[lsp] Install Failure" })
88-
end
89-
end,
90-
})
91-
:start()
92-
end)
93-
)
9429
end
9530

9631
return M

lua/modules/configs/completion/servers/clangd.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ end
3535

3636
-- https://github.com/neovim/nvim-lspconfig/blob/master/lua/lspconfig/configs/clangd.lua
3737
return function(defaults)
38-
require("lspconfig").clangd.setup({
38+
vim.lsp.config("clangd", {
3939
on_attach = defaults.on_attach,
4040
capabilities = vim.tbl_deep_extend("keep", { offsetEncoding = { "utf-16", "utf-8" } }, defaults.capabilities),
4141
single_file_support = true,

lua/modules/plugins/completion.lua

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ local completion = {}
22

33
completion["neovim/nvim-lspconfig"] = {
44
lazy = true,
5-
event = { "BufReadPre", "BufNewFile" },
5+
-- event = { "BufReadPre", "BufNewFile" },
6+
event = { "CursorHold", "CursorHoldI" },
67
config = require("completion.lsp"),
78
dependencies = {
89
{ "mason-org/mason.nvim" },

lua/modules/utils/init.lua

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,19 @@ function M.gen_cursorword_hl()
263263
set_global_hl("MiniCursorwordCurrent", nil)
264264
end
265265

266+
---Setup and enable a language server in one call.
267+
---@param server string @Name of the language server
268+
---@param config? vim.lsp.Config @Optional config to apply
269+
function M.register_server(server, config)
270+
vim.validate("server", server, "string", false)
271+
vim.validate("config", config, "table", true)
272+
273+
if config then
274+
vim.lsp.config(server, config)
275+
end
276+
vim.lsp.enable(server)
277+
end
278+
266279
---Convert number (0/1) to boolean
267280
---@param value number @The value to check
268281
---@return boolean|nil @Returns nil if failed

0 commit comments

Comments
 (0)