@@ -144,77 +144,82 @@ 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] [ 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] [ 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] [ r-a 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] [ r-a nvim lsp ] is set up
180+ 2 . Create ` $HOME/.config/nvim/after/plugged/rust_analyzer.lua ` with the following content:
167181
168182``` 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 )
183+ -- Capture the default functions from nvim-lspconfig/lsp/rust_analyzer.lua before overriding it.
184+ -- This file is in after/plugin to guarantee nvim-lspconfig has been initialised already.
185+ local default_root_dir = vim .lsp .config [" rust_analyzer" ].root_dir
186+ local default_before_init = vim .lsp .config [" rust_analyzer" ].before_init
187+
188+ vim .lsp .config (" rust_analyzer" , {
189+ cmd = { " rust-analyzer" },
190+ filetypes = { " rust" },
191+ -- To support rust-lang/rust, we need to detect when we're in the rust repo and use the git root
192+ -- instead of cargo project root.
193+ root_dir = function (bufnr , on_dir )
194+ local git_root = vim .fs .root (bufnr , { " .git" })
195+ if git_root then
196+ if vim .uv .fs_stat (vim .fs .joinpath (git_root , " src/etc/rust_analyzer_zed.json" )) then
197+ on_dir (git_root )
198+ return
199+ end
181200 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 )
202- end
203- return default
201+ -- For anything that doesn't match rust-lang/rust, fallback to default root_dir
202+ default_root_dir (bufnr , on_dir )
204203 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 })
204+ before_init = function (init_params , config )
205+ -- When inside rust-lang/rust, we need to use the special rust-analyzer settings.
206+ local settings = vim .fs .joinpath (config .root_dir , " src/etc/rust_analyzer_zed.json" )
207+ if vim .uv .fs_stat (settings ) then
208+ local file = io.open (settings )
209+ -- nvim 0.12+ supports comments otherwise you'll need content:gsub("//[^\n]*", "").
210+ local json = vim .json .decode (file :read (" *a" ), { skip_comments = true })
211+ file :close ()
212+ config .settings [" rust-analyzer" ] = vim .tbl_deep_extend (
213+ " force" , -- Overwrite with the special settings when there is a conflict.
214+ config .settings [" rust-analyzer" ] or {},
215+ json .lsp [" rust-analyzer" ].initialization_options
216+ )
214217 end
215- return true
216- end
217- }
218+ default_before_init (init_params , config )
219+ end ,
220+ })
221+
222+ vim .lsp .enable (" rust_analyzer" )
218223```
219224
220225If you would like to use the build task that is described above, you may either
@@ -223,6 +228,9 @@ make your own command in your config, or you can install a plugin such as
223228files] ( https://github.com/stevearc/overseer.nvim/blob/master/doc/guides.md#vs-code-tasks ) ,
224229and follow the same instructions as above.
225230
231+ [ neoconf.nvim ] : https://github.com/folke/neoconf.nvim/
232+ [ r-a nvim lsp ] : https://rust-analyzer.github.io/book/other_editors.html#nvim-lsp
233+
226234### Emacs
227235
228236Emacs provides support for rust-analyzer with project-local configuration
0 commit comments