11local M = {}
22
33M .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+ )
86181end
87182
88183return M
0 commit comments