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 ({
@@ -51,16 +57,16 @@ please REMOVE your LSP configuration (rust_analyzer.lua) from the `servers` dire
5157
5258 if not ok then
5359 -- Default to use factory config for server(s) that doesn't include a spec
54- vim .lsp .config (lsp_name , opts )
55- vim .lsp .enable (lsp_name )
60+ require (" modules.utils" ).register_server (lsp_name , opts )
5661 elseif type (custom_handler ) == " function" then
57- --- Case where language server requires its own setup
58- --- Make sure to call require("lspconfig")[lsp_name].setup() in the function
59- --- See `clangd.lua` for example.
62+ -- Case where language server requires its own setup
63+ -- Be sure to call `vim.lsp.config()` within the setup function.
64+ -- Refer to |vim.lsp.config()| for documentation.
65+ -- For an example, see `clangd.lua`.
6066 custom_handler (opts )
6167 vim .lsp .enable (lsp_name )
6268 elseif type (custom_handler ) == " table" then
63- vim . lsp . config (
69+ require ( " modules.utils " ). register_server (
6470 lsp_name ,
6571 vim .tbl_deep_extend (
6672 " force" ,
@@ -69,7 +75,6 @@ please REMOVE your LSP configuration (rust_analyzer.lua) from the `servers` dire
6975 custom_handler
7076 )
7177 )
72- vim .lsp .enable (lsp_name )
7378 else
7479 vim .notify (
7580 string.format (
@@ -83,9 +88,98 @@ please REMOVE your LSP configuration (rust_analyzer.lua) from the `servers` dire
8388 end
8489 end
8590
86- for _ , lsp in ipairs (lsp_deps ) do
87- mason_lsp_handler (lsp )
91+ --- A simplified mimic of <mason-lspconfig 1.x>'s `setup_handlers` callback.
92+ --- Invoked for each Mason package (name or `Package` object) to configure its language server.
93+ --- @param pkg string |{ name : string } Either the package name (string ) or a Package object
94+ local function setup_lsp_for_package (pkg )
95+ -- First try to grab the builtin mappings
96+ local mappings = mason_lspconfig .get_mappings ().package_to_lspconfig
97+ -- If empty or nil, build it by hand
98+ if not mappings or vim .tbl_isempty (mappings ) then
99+ mappings = {}
100+ for _ , spec in ipairs (mason_registry .get_all_package_specs ()) do
101+ local lspconfig = vim .tbl_get (spec , " neovim" , " lspconfig" )
102+ if lspconfig then
103+ mappings [spec .name ] = lspconfig
104+ end
105+ end
106+ end
107+
108+ -- Figure out the package name and lookup
109+ local name = type (pkg ) == " string" and pkg or pkg .name
110+ local srv = mappings [name ]
111+ if not srv then
112+ return
113+ end
114+
115+ -- Invoke the handler
116+ mason_lsp_handler (srv )
117+ end
118+
119+ for _ , pkg in ipairs (mason_registry .get_installed_package_names ()) do
120+ setup_lsp_for_package (pkg )
88121 end
122+
123+ -- Hook into Mason's package install event to install extra plugins for pylsp (black, ruff, rope),
124+ -- then configure the installed package's LSP using setup_lsp_for_package.
125+ mason_registry :on (
126+ " package:install:success" ,
127+ vim .schedule_wrap (function (pkg )
128+ if pkg .name == " python-lsp-server" then
129+ local venv = vim .fn .stdpath (" data" ) .. " /mason/packages/python-lsp-server/venv"
130+ local python = is_windows and venv .. " /Scripts/python.exe" or venv .. " /bin/python"
131+ local black = is_windows and venv .. " /Scripts/black.exe" or venv .. " /bin/black"
132+ local ruff = is_windows and venv .. " /Scripts/ruff.exe" or venv .. " /bin/ruff"
133+
134+ require (" plenary.job" )
135+ :new ({
136+ command = python ,
137+ args = {
138+ " -m" ,
139+ " pip" ,
140+ " install" ,
141+ " -U" ,
142+ " --disable-pip-version-check" ,
143+ " python-lsp-black" ,
144+ " python-lsp-ruff" ,
145+ " pylsp-rope" ,
146+ },
147+ cwd = venv ,
148+ env = { VIRTUAL_ENV = venv },
149+ on_exit = function ()
150+ if vim .fn .executable (black ) == 1 and vim .fn .executable (ruff ) == 1 then
151+ vim .notify (
152+ " Finished installing pylsp plugins" ,
153+ vim .log .levels .INFO ,
154+ { title = " [lsp] Install Status" }
155+ )
156+ else
157+ vim .notify (
158+ " Failed to install pylsp plugins. [Executable not found]" ,
159+ vim .log .levels .ERROR ,
160+ { title = " [lsp] Install Failure" }
161+ )
162+ end
163+ end ,
164+ on_start = function ()
165+ vim .notify (
166+ " Now installing pylsp plugins..." ,
167+ vim .log .levels .INFO ,
168+ { title = " [lsp] Install Status" , timeout = 6000 }
169+ )
170+ end ,
171+ on_stderr = function (_ , msg_stream )
172+ if msg_stream then
173+ vim .notify (msg_stream , vim .log .levels .ERROR , { title = " [lsp] Install Failure" })
174+ end
175+ end ,
176+ })
177+ :start ()
178+ end
179+
180+ setup_lsp_for_package (pkg )
181+ end )
182+ )
89183end
90184
91185return M
0 commit comments