Skip to content

Commit fc82520

Browse files
committed
feat(lsp): configure rust-analyzer on the fly
1 parent b2ab7de commit fc82520

File tree

4 files changed

+62
-8
lines changed

4 files changed

+62
-8
lines changed

README.md

+20
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,26 @@ by setting the rust-analyzer
754754
See also `:h rustaceanvim.ra_multiplex`.
755755

756756
</details>
757+
758+
<details>
759+
<summary>
760+
<b>Configure rust-analyzer on the fly</b>
761+
</summary>
762+
763+
You can configure rust-analyzer on the fly using the `:RustAnalyzer config` subcommand.
764+
The command takes a Lua table as an argument (it does not validate it!).
765+
766+
For example:
767+
768+
```vim
769+
:RustAnalyzer config { checkOnSave = false }
770+
```
771+
```lua
772+
vim.cmd.RustAnalyzer { 'config', '{ checkOnSave = false }' }
773+
```
774+
775+
See also: [`rust-analyzer` configuration](https://rust-analyzer.github.io/book/configuration).
776+
</details>
757777
<!-- markdownlint-restore -->
758778

759779
## :gear: Advanced configuration

doc/rustaceanvim.txt

+4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ Commands:
2525
':RustAnalyzer restart' - Restart the LSP client.
2626
':RustAnalyzer reloadSettings' - Reload settings for the LSP client.
2727
':RustAnalyzer target <target_arch>' - Set the target architecture for the LSP client.
28+
':RustAnalyzer config <lua_table>' - Configure rust-analyzer on the fly.
29+
Takes a Lua table as an argument.
30+
Example: `:RustAnalyzer config { checkOnSave = false }`
31+
WARNING: This command does not validate the Lua config table.
2832
The ':RustAnalyzer target' command can take a valid rustc target,
2933
such as 'wasm32-unknown-unknown', or it can be left empty to set the LSP client
3034
to use the default target architecture for the operating system.

lua/rustaceanvim/init.lua

+4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717
--- ':RustAnalyzer restart' - Restart the LSP client.
1818
--- ':RustAnalyzer reloadSettings' - Reload settings for the LSP client.
1919
--- ':RustAnalyzer target <target_arch>' - Set the target architecture for the LSP client.
20+
--- ':RustAnalyzer config <lua_table>' - Configure rust-analyzer on the fly.
21+
--- Takes a Lua table as an argument.
22+
--- Example: `:RustAnalyzer config { checkOnSave = false }`
23+
--- WARNING: This command does not validate the Lua config table.
2024

2125
--- The ':RustAnalyzer target' command can take a valid rustc target,
2226
--- such as 'wasm32-unknown-unknown', or it can be left empty to set the LSP client

lua/rustaceanvim/lsp/init.lua

+34-8
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,13 @@ M.stop = function(bufnr, filter)
324324
return clients
325325
end
326326

327+
---Restart the LSP client.
328+
---Fails silently if the buffer's filetype is not one of the filetypes specified in the config.
329+
---@return number|nil client_id The LSP client ID after restart
330+
M.restart = function()
331+
return restart()
332+
end
333+
327334
---Reload settings for the LSP client.
328335
---@param bufnr? number The buffer number, defaults to the current buffer
329336
---@return vim.lsp.Client[] clients A list of clients that will be have their settings reloaded
@@ -367,11 +374,20 @@ M.set_target_arch = function(bufnr, target)
367374
end)
368375
end
369376

370-
---Restart the LSP client.
371-
---Fails silently if the buffer's filetype is not one of the filetypes specified in the config.
372-
---@return number|nil client_id The LSP client ID after restart
373-
M.restart = function()
374-
return restart()
377+
---@param ra_settings table
378+
function M.set_config(ra_settings)
379+
local bufnr = vim.api.nvim_get_current_buf()
380+
local clients = rust_analyzer.get_active_rustaceanvim_clients(bufnr)
381+
---@cast clients vim.lsp.Client[]
382+
for _, client in ipairs(clients) do
383+
local settings = get_start_settings(vim.api.nvim_buf_get_name(bufnr), client.config.root_dir, config.server)
384+
---@diagnostic disable-next-line: inject-field
385+
settings['rust-analyzer'] = vim.tbl_deep_extend('force', settings['rust-analyzer'], ra_settings)
386+
client.settings = settings
387+
client:notify('workspace/didChangeConfiguration', {
388+
settings = client.settings,
389+
})
390+
end
375391
end
376392

377393
---@enum RustAnalyzerCmd
@@ -381,11 +397,12 @@ local RustAnalyzerCmd = {
381397
restart = 'restart',
382398
reload_settings = 'reloadSettings',
383399
target = 'target',
400+
config = 'config',
384401
}
385402

386403
local function rust_analyzer_user_cmd(opts)
387404
local fargs = opts.fargs
388-
local cmd = fargs[1]
405+
local cmd = table.remove(fargs, 1)
389406
---@cast cmd RustAnalyzerCmd
390407
if cmd == RustAnalyzerCmd.start then
391408
M.start()
@@ -396,8 +413,17 @@ local function rust_analyzer_user_cmd(opts)
396413
elseif cmd == RustAnalyzerCmd.reload_settings then
397414
M.reload_settings()
398415
elseif cmd == RustAnalyzerCmd.target then
399-
local target_arch = fargs[2]
416+
local target_arch = fargs[1]
400417
M.set_target_arch(nil, target_arch)
418+
elseif cmd == RustAnalyzerCmd.config then
419+
local ra_settings_str = vim.iter(fargs):join(' ')
420+
local f = load('return ' .. ra_settings_str)
421+
---@diagnostic disable-next-line: param-type-mismatch
422+
local ok, ra_settings = pcall(f)
423+
if not ok or type(ra_settings) ~= 'table' then
424+
return vim.notify('RustAnalyzer config: invalid Lua table.\n' .. ra_settings_str, vim.log.levels.ERROR)
425+
end
426+
M.set_config(ra_settings)
401427
end
402428
end
403429

@@ -407,7 +433,7 @@ vim.api.nvim_create_user_command('RustAnalyzer', rust_analyzer_user_cmd, {
407433
complete = function(arg_lead, cmdline, _)
408434
local clients = rust_analyzer.get_active_rustaceanvim_clients()
409435
---@type RustAnalyzerCmd[]
410-
local commands = #clients == 0 and { 'start' } or { 'stop', 'restart', 'reloadSettings', 'target' }
436+
local commands = #clients == 0 and { 'start' } or { 'stop', 'restart', 'reloadSettings', 'target', 'config' }
411437
if cmdline:match('^RustAnalyzer%s+%w*$') then
412438
return vim.tbl_filter(function(command)
413439
return command:find(arg_lead) ~= nil

0 commit comments

Comments
 (0)