@@ -144,77 +144,81 @@ If running `./x check` on save is inconvenient, in VS Code you can use a [Build
144144
145145### Neovim
146146
147- For Neovim users, there are a few options.
148- The easiest way is by using [ neoconf.nvim] ( https://github.com/folke/neoconf.nvim/ ) ,
149- which allows for project-local configuration files with the native LSP.
150- The steps for how to use it are below.
151- Note that they require rust-analyzer to already be configured with Neovim.
152- Steps for this can be [ found here] ( https://rust-analyzer.github.io/manual.html#nvim-lsp ) .
147+ For Neovim users, there are a few options:
148+
149+ 1 . The easiest way is using [ neoconf.nvim] ( https://github.com/folke/neoconf.nvim/ ) but it uses the
150+ deprecated ` require('lspconfig') ` API which displays a warning on neovim 0.11+.
151+ 2 . Using ` coc.nvim ` is another option but it requires node.js to be installed.
152+ 3 . Using a custom script to load rust-analyzer settings.
153+
154+ #### neoconf.nvim
155+
156+ [ neoconf.nvim] ( https://github.com/folke/neoconf.nvim/ ) allows for project-local configuration
157+ files with the native LSP. The steps for how to use it are below. Note that they require
158+ rust-analyzer to already be configured with Neovim. Steps for this can be
159+ [ found here] ( https://rust-analyzer.github.io/book/other_editors.html#nvim-lsp ) .
153160
1541611 . First install the plugin.
155162 This can be done by following the steps in the README.
1561632 . Run ` ./x setup editor ` , and select ` vscode ` to create a ` .vscode/settings.json ` file.
157164 ` neoconf ` is able to read and update
158165 rust-analyzer settings automatically when the project is opened when this file is detected.
159166
167+ #### coc.nvim
168+
160169If you're using ` coc.nvim ` , you can run ` ./x setup editor ` and select ` vim ` to
161170create a ` .vim/coc-settings.json ` .
162171The settings can be edited with ` :CocLocalConfig ` .
163172The recommended settings live at [ ` src/etc/rust_analyzer_settings.json ` ] .
164173
165- Another way is without a plugin, and creating your own logic in your configuration.
166- The following code will work for any checkout of rust-lang/rust (newer than February 2025):
174+ #### Custom LSP settings
175+
176+ If you're running neovim 0.11+, you can configure rust-analyzer with just
177+ [ nvim-lspconfig] ( https://github.com/neovim/nvim-lspconfig ) and a custom script.
178+
179+ 1 . Make sure rust-analyzer LSP is set up
180+ < https://rust-analyzer.github.io/book/other_editors.html#nvim-lsp >
181+ 2 . Create ` $HOME/.config/nvim/after/plugged/rust_analyzer.lua ` with the following content:
167182
168183``` lua
169- local function expand_config_variables (option )
170- local var_placeholders = {
171- [' ${workspaceFolder}' ] = function (_ )
172- return vim .lsp .buf .list_workspace_folders ()[1 ]
173- end ,
174- }
175-
176- if type (option ) == " table" then
177- local mt = getmetatable (option )
178- local result = {}
179- for k , v in pairs (option ) do
180- result [expand_config_variables (k )] = expand_config_variables (v )
181- end
182- return setmetatable (result , mt )
183- end
184- if type (option ) ~= " string" then
185- return option
186- end
187- local ret = option
188- for key , fn in pairs (var_placeholders ) do
189- ret = ret :gsub (key , fn )
190- end
191- return ret
192- end
193- lspconfig .rust_analyzer .setup {
194- root_dir = function ()
195- local default = lspconfig .rust_analyzer .config_def .default_config .root_dir ()
196- -- the default root detection uses the cargo workspace root.
197- -- but for rust-lang/rust, the standard library is in its own workspace.
198- -- use the git root instead.
199- local compiler_config = vim .fs .joinpath (default , " ../src/bootstrap/defaults/config.compiler.toml" )
200- if vim .fs .basename (default ) == " library" and vim .uv .fs_stat (compiler_config ) then
201- return vim .fs .dirname (default )
184+ -- Capture the default functions from nvim-lspconfig/lsp/rust_analyzer.lua before overriding it.
185+ -- This file is in after/plugin to guarantee nvim-lspconfig has been initialised already.
186+ local default_root_dir = vim .lsp .config [' rust_analyzer' ].root_dir
187+ local default_before_init = vim .lsp .config [' rust_analyzer' ].before_init
188+
189+ vim .lsp .config (' rust_analyzer' , {
190+ cmd = { ' rust-analyzer' },
191+ filetypes = { ' rust' },
192+ -- To support rust_lang/rust, we need to detect when we're in the rust repo and use the git root
193+ -- instead of cargo project root.
194+ root_dir = function (bufnr , on_dir )
195+ local git_root = vim .fs .root (bufnr , { ' .git' })
196+ if git_root then
197+ if vim .uv .fs_stat (vim .fs .joinpath (git_root , " src/etc/rust_analyzer_zed.json" )) then
198+ on_dir (git_root )
199+ return
200+ end
202201 end
203- return default
202+ -- For anything that doesn't match rust-lang/rust, fallback to default root_dir
203+ default_root_dir (bufnr , on_dir )
204204 end ,
205- on_init = function (client )
206- local path = client .workspace_folders [1 ].name
207- local config = vim .fs .joinpath (path , " src/etc/rust_analyzer_zed.json" )
208- if vim .uv .fs_stat (config ) then
209- -- load rust-lang/rust settings
210- local file = io.open (config )
211- local json = vim .json .decode (file :read (" *a" ))
212- client .config .settings [" rust-analyzer" ] = expand_config_variables (json .lsp [" rust-analyzer" ].initialization_options )
213- client .notify (" workspace/didChangeConfiguration" , { settings = client .config .settings })
205+ before_init = function (init_params , config )
206+ -- When inside rust_lang/rust, we need to use the special rust_analyzer settings.
207+ local settings = vim .fs .joinpath (config .root_dir , " src/etc/rust_analyzer_zed.json" )
208+ if vim .uv .fs_stat (settings ) then
209+ local file = io.open (settings )
210+ local content = file :read (" *a" )
211+ file :close ()
212+ -- vim.json.decode doesn't support JSONC so we need strip out comments.
213+ content = content :gsub (" //[^\n ]*" , " " )
214+ local json = vim .json .decode (content )
215+ config .settings [" rust-analyzer" ] = json .lsp [" rust-analyzer" ].initialization_options
214216 end
215- return true
216- end
217- }
217+ default_before_init (init_params , config )
218+ end ,
219+ })
220+
221+ vim .lsp .enable (' rust_analyzer' )
218222```
219223
220224If you would like to use the build task that is described above, you may either
0 commit comments