1

Refresh generated neovim config

This commit is contained in:
2024-08-15 13:01:03 +02:00
parent 64b51cf53a
commit f5af8e2b28
1836 changed files with 38979 additions and 31094 deletions

View File

@ -1,14 +1,15 @@
==============================================================================
Table of Contents *rustaceanvim.contents*
Introduction ··························································· |intro|
Introduction ·············································· |rustaceanvim.intro|
································································ |rustaceanvim|
plugin configuration ····································· |rustaceanvim.config|
LSP configuration utility ························· |rustaceanvim.config.server|
························································ |rustaceanvim.neotest|
···························································· |rustaceanvim.dap|
==============================================================================
Introduction *intro*
Introduction *rustaceanvim.intro*
This plugin automatically configures the `rust-analyzer` builtin LSP client
and integrates with other rust tools.
@ -41,15 +42,25 @@ It accepts the following subcommands:
'expandMacro' - Expand macros recursively.
'moveItem {up|down}' - Move items up or down.
'hover {actions|range}' - Hover actions, or hover over visually selected range.
'explainError' - Display a hover window with explanations form the Rust error index.
Like |vim.diagnostic.goto_next|, |explainError| will cycle diagnostics,
starting at the cursor position, until it can find a diagnostic with
an error code.
'renderDiagnostic' - Display a hover window with the rendered diagnostic,
as displayed during `cargo build`.
Like |vim.diagnostic.goto_next|, |renderDiagnostic| will cycle diagnostics,
starting at the cursor position, until it can find a diagnostic with
rendered data.
'explainError {cycle?|current?}' - Display a hover window with explanations form the Rust error index.
- If called with |cycle| or no args:
Like |vim.diagnostic.goto_next|,
|explainError| will cycle diagnostics,
starting at the cursor position,
until it can find a diagnostic with an error code.
- If called with |current|:
Searches for diagnostics only in the
current cursor line.
'renderDiagnostic {cycle?|current?}' - Display a hover window with the rendered diagnostic,
as displayed during |cargo build|.
- If called with |cycle| or no args:
Like |vim.diagnostic.goto_next|,
|renderDiagnostic| will cycle diagnostics,
starting at the cursor position,
until it can find a diagnostic with rendered data.
- If called with |current|:
Searches for diagnostics only in the
current cursor line.
'openCargo' - Open the Cargo.toml file for the current package.
'openDocs' - Open docs.rs documentation for the symbol under the cursor.
'parentModule' - Open the current module's parent module.
@ -97,13 +108,13 @@ which is a `RustaceanOpts` table, in your neovim configuration.
Example:
>lua
---@type RustaceanOpts
---@type rustaceanvim.Opts
vim.g.rustaceanvim = {
---@type RustaceanToolsOpts
---@type rustaceanvim.tools.Opts
tools = {
-- ...
},
---@type RustaceanLspClientOpts
---@type rustaceanvim.lsp.ClientOpts
server = {
on_attach = function(client, bufnr)
-- Set keybindings, etc. here.
@ -115,7 +126,7 @@ vim.g.rustaceanvim = {
},
-- ...
},
---@type RustaceanDapOpts
---@type rustaceanvim.dap.Opts
dap = {
-- ...
},
@ -124,51 +135,68 @@ vim.g.rustaceanvim = {
Notes:
- `vim.g.rustaceanvim` can also be a function that returns a `RustaceanOpts` table.
- `vim.g.rustaceanvim` can also be a function that returns a `rustaceanvim.Opts` table.
- `server.settings`, by default, is a function that looks for a `rust-analyzer.json` file
in the project root, to load settings from it. It falls back to an empty table.
RustaceanOpts *RustaceanOpts*
rustaceanvim.Opts *rustaceanvim.Opts*
Fields: ~
{tools?} (RustaceanToolsOpts) Plugin options
{server?} (RustaceanLspClientOpts) Language server client options
{dap?} (RustaceanDapOpts) Debug adapter options
{tools?} (rustaceanvim.tools.Opts) Plugin options
{server?} (rustaceanvim.lsp.ClientOpts) Language server client options
{dap?} (rustaceanvim.dap.Opts) Debug adapter options
RustaceanToolsOpts *RustaceanToolsOpts*
rustaceanvim.tools.Opts *rustaceanvim.tools.Opts*
Fields: ~
{executor?} (RustaceanExecutor|executor_alias) The executor to use for runnables/debuggables
{test_executor?} (RustaceanExecutor|test_executor_alias) The executor to use for runnables that are tests / testables
{crate_test_executor?} (RustaceanExecutor|test_executor_alias) The executor to use for runnables that are crate test suites (--all-targets)
{cargo_override?} (string) Set this to override the 'cargo' command for runnables, debuggables (etc., e.g. to 'cross'). If set, this takes precedence over 'enable_nextest'.
{enable_nextest?} (boolean) Whether to enable nextest. If enabled, `cargo test` commands will be transformed to `cargo nextest run` commands. Defaults to `true` if cargo-nextest is detected. Ignored if `cargo_override` is set.
{enable_clippy?} (boolean) Whether to enable clippy checks on save if a clippy installation is detected. Default: `true`
{on_initialized?} (fun(health:RustAnalyzerInitializedStatus)) Function that is invoked when the LSP server has finished initializing
{reload_workspace_from_cargo_toml?} (boolean) Automatically call `RustReloadWorkspace` when writing to a Cargo.toml file
{hover_actions?} (RustaceanHoverActionsOpts) Options for hover actions
{code_actions?} (RustaceanCodeActionOpts) Options for code actions
{float_win_config?} (FloatWinConfig) Options applied to floating windows. See |api-win_config|.
{create_graph?} (RustaceanCrateGraphConfig) Options for showing the crate graph based on graphviz and the dot
{open_url?} (fun(url:string):nil) If set, overrides how to open URLs
{rustc?} (RustcOpts) Options for `rustc`
{executor?} (rustaceanvim.Executor|rustaceanvim.executor_alias)
The executor to use for runnables/debuggables
{test_executor?} (rustaceanvim.Executor|rustaceanvim.test_executor_alias)
The executor to use for runnables that are tests / testables
{crate_test_executor?} (rustaceanvim.Executor|rustaceanvim.test_executor_alias)
The executor to use for runnables that are crate test suites (--all-targets)
{cargo_override?} (string)
Set this to override the 'cargo' command for runnables, debuggables (etc., e.g. to 'cross').
If set, this takes precedence over 'enable_nextest'.
{enable_nextest?} (boolean)
Whether to enable nextest. If enabled, `cargo test` commands will be transformed to `cargo nextest run` commands.
Defaults to `true` if cargo-nextest is detected. Ignored if `cargo_override` is set.
{enable_clippy?} (boolean)
Whether to enable clippy checks on save if a clippy installation is detected.
Default: `true`
{on_initialized?} (fun(health:rustaceanvim.RAInitializedStatus))
Function that is invoked when the LSP server has finished initializing
{reload_workspace_from_cargo_toml?} (boolean)
Automatically call `RustReloadWorkspace` when writing to a Cargo.toml file
{hover_actions?} (rustaceanvim.hover-actions.Opts) Options for hover actions
{code_actions?} (rustaceanvim.code-action.Opts) Options for code actions
{float_win_config?} (rustaceanvim.FloatWinConfig)
Options applied to floating windows.
See |api-win_config|.
{create_graph?} (rustaceanvim.crate-graph.Opts)
Options for showing the crate graph based on graphviz and the dot
{open_url?} (fun(url:string):nil)
If set, overrides how to open URLs
{rustc?} (rustaceanvim.rustc.Opts)
Options for `rustc`
RustaceanExecutor *RustaceanExecutor*
rustaceanvim.Executor *rustaceanvim.Executor*
Fields: ~
{execute_command} (fun(cmd:string,args:string[],cwd:string|nil,opts?:RustaceanExecutorOpts))
{execute_command} (fun(cmd:string,args:string[],cwd:string|nil,opts?:rustaceanvim.ExecutorOpts))
RustaceanExecutorOpts *RustaceanExecutorOpts*
rustaceanvim.ExecutorOpts *rustaceanvim.ExecutorOpts*
Fields: ~
{bufnr?} (integer) The buffer from which the executor was invoked.
{bufnr?} (integer)
The buffer from which the executor was invoked.
FloatWinConfig *FloatWinConfig*
rustaceanvim.FloatWinConfig *rustaceanvim.FloatWinConfig*
Fields: ~
{auto_focus?} (boolean)
@ -179,162 +207,199 @@ FloatWinConfig *FloatWinConfig*
|vim.api.nvim_open_win|
executor_alias *executor_alias*
rustaceanvim.executor_alias *rustaceanvim.executor_alias*
Type: ~
"termopen"|"quickfix"|"toggleterm"|"vimux"
test_executor_alias *test_executor_alias*
rustaceanvim.test_executor_alias *rustaceanvim.test_executor_alias*
Type: ~
executor_alias|"background"|"neotest"
rustaceanvim.executor_alias|"background"|"neotest"
RustaceanHoverActionsOpts *RustaceanHoverActionsOpts*
rustaceanvim.hover-actions.Opts *rustaceanvim.hover-actions.Opts*
Fields: ~
{replace_builtin_hover?} (boolean) Whether to replace Neovim's built-in `vim.lsp.buf.hover` with hover actions. Default: `true`
{replace_builtin_hover?} (boolean)
Whether to replace Neovim's built-in `vim.lsp.buf.hover` with hover actions.
Default: `true`
RustaceanCodeActionOpts *RustaceanCodeActionOpts*
rustaceanvim.code-action.Opts *rustaceanvim.code-action.Opts*
Fields: ~
{group_icon?} (string) Text appended to a group action
{ui_select_fallback?} (boolean) Whether to fall back to `vim.ui.select` if there are no grouped code actions. Default: `false`
{group_icon?} (string)
Text appended to a group action
{ui_select_fallback?} (boolean)
Whether to fall back to `vim.ui.select` if there are no grouped code actions.
Default: `false`
lsp_server_health_status *lsp_server_health_status*
rustaceanvim.lsp_server_health_status *rustaceanvim.lsp_server_health_status*
Type: ~
"ok"|"warning"|"error"
RustAnalyzerInitializedStatus *RustAnalyzerInitializedStatus*
rustaceanvim.RAInitializedStatus *rustaceanvim.RAInitializedStatus*
Fields: ~
{health} (lsp_server_health_status)
{health} (rustaceanvim.lsp_server_health_status)
RustaceanCrateGraphConfig *RustaceanCrateGraphConfig*
rustaceanvim.crate-graph.Opts *rustaceanvim.crate-graph.Opts*
Fields: ~
{backend?} (string) Backend used for displaying the graph. See: https://graphviz.org/docs/outputs/ Defaults to `"x11"` if unset.
{output?} (string) Where to store the output. No output if unset. Relative path from `cwd`.
{enabled_graphviz_backends?} (string[]) Override the enabled graphviz backends list, used for input validation and autocompletion.
{pipe?} (string) Overide the pipe symbol in the shell command. Useful if using a shell that is not supported by this plugin.
{backend?} (string)
Backend used for displaying the graph.
See: https://graphviz.org/docs/outputs/
Defaults to `"x11"` if unset.
{output?} (string)
Where to store the output. No output if unset.
Relative path from `cwd`.
{enabled_graphviz_backends?} (string[])
Override the enabled graphviz backends list, used for input validation and autocompletion.
{pipe?} (string)
Overide the pipe symbol in the shell command.
Useful if using a shell that is not supported by this plugin.
RustcOpts *RustcOpts*
rustaceanvim.rustc.Opts *rustaceanvim.rustc.Opts*
Fields: ~
{edition} (string) The edition to use. See https://rustc-dev-guide.rust-lang.org/guides/editions.html. Default '2021'.
{default_edition?} (string)
The default edition to use if it cannot be auto-detected.
See https://rustc-dev-guide.rust-lang.org/guides/editions.html.
Default '2021'.
RustaceanLspClientOpts *RustaceanLspClientOpts*
rustaceanvim.lsp.ClientOpts *rustaceanvim.lsp.ClientOpts*
Fields: ~
{auto_attach?} (boolean|fun(bufnr:integer):boolean) Whether to automatically attach the LSP client. Defaults to `true` if the `rust-analyzer` executable is found.
{cmd?} (string[]|fun():string[]) Command and arguments for starting rust-analyzer
{root_dir?} (string|fun(filename:string,default:fun(filename:string):string|nil):string|nil) The directory to use for the attached LSP. Can be a function, which may return nil if no server should attach. The second argument contains the default implementation, which can be used for fallback behavior.
{settings?} (table|fun(project_root:string|nil,default_settings:table):table) Setting passed to rust-analyzer. Defaults to a function that looks for a `rust-analyzer.json` file or returns an empty table. See https://rust-analyzer.github.io/manual.html#configuration.
{standalone?} (boolean) Standalone file support (enabled by default). Disabling it may improve rust-analyzer's startup time.
{logfile?} (string) The path to the rust-analyzer log file.
{load_vscode_settings?} (boolean) Whether to search (upward from the buffer) for rust-analyzer settings in .vscode/settings json. If found, loaded settings will override configured options. Default: false
{auto_attach?} (boolean|fun(bufnr:integer):boolean)
Whether to automatically attach the LSP client.
Defaults to `true` if the `rust-analyzer` executable is found.
{cmd?} (string[]|fun():string[])
Command and arguments for starting rust-analyzer
{root_dir?} (string|fun(filename:string,default:fun(filename:string):string|nil):string|nil)
The directory to use for the attached LSP.
Can be a function, which may return nil if no server should attach.
The second argument contains the default implementation, which can be used for fallback behavior.
{settings?} (table|fun(project_root:string|nil,default_settings:table):table)
Setting passed to rust-analyzer.
Defaults to a function that looks for a `rust-analyzer.json` file or returns an empty table.
See https://rust-analyzer.github.io/manual.html#configuration.
{standalone?} (boolean)
Standalone file support (enabled by default).
Disabling it may improve rust-analyzer's startup time.
{logfile?} (string)
The path to the rust-analyzer log file.
{load_vscode_settings?} (boolean)
Whether to search (upward from the buffer) for rust-analyzer settings in .vscode/settings json.
If found, loaded settings will override configured options.
Default: true
See: ~
|vim.lsp.ClientConfig|
RustaceanDapOpts *RustaceanDapOpts*
rustaceanvim.dap.Opts *rustaceanvim.dap.Opts*
Fields: ~
{adapter?} (DapExecutableConfig|DapServerConfig|disable|fun():DapExecutableConfig|DapServerConfig|disable) @field autoload_configurations boolean Whether to autoload nvim-dap configurations when rust-analyzer has attached? Default: `true`.
{autoload_configurations} (boolean)
Whether to autoload nvim-dap configurations when rust-analyzer has attached?
Default: `true`.
disable *disable*
rustaceanvim.disable *rustaceanvim.disable*
Type: ~
false
DapCommand *DapCommand*
rustaceanvim.dap.Command *rustaceanvim.dap.Command*
Type: ~
string
DapExecutableConfig *DapExecutableConfig*
rustaceanvim.dap.executable.Config *rustaceanvim.dap.executable.Config*
Fields: ~
{type} (dap_adapter_type_executable) The type of debug adapter.
{command} (string) Default: `"lldb-vscode"`.
{args?} (string) Default: unset.
{name?} (string) Default: `"lldb"`.
{type} (rustaceanvim.dap.adapter.types.executable)
The type of debug adapter.
{command} (string) Default: `"lldb-vscode"`.
{args?} (string) Default: unset.
{name?} (string) Default: `"lldb"`.
DapServerConfig *DapServerConfig*
rustaceanvim.dap.server.Config *rustaceanvim.dap.server.Config*
Fields: ~
{type} (dap_adapter_type_server) The type of debug adapter.
{host?} (string) The host to connect to.
{port} (string) The port to connect to.
{executable} (DapExecutable) The executable to run
{type} (rustaceanvim.dap.adapter.types.server) The type of debug adapter.
{host?} (string) The host to connect to.
{port} (string) The port to connect to.
{executable} (rustaceanvim.dap.Executable) The executable to run
{name?} (string)
DapExecutable *DapExecutable*
rustaceanvim.dap.Executable *rustaceanvim.dap.Executable*
Fields: ~
{command} (string) The executable.
{args} (string[]) Its arguments.
dap_adapter_type_executable *dap_adapter_type_executable*
*rustaceanvim.dap.adapter.types.executable*
rustaceanvim.dap.adapter.types.executable
Type: ~
dap_adapter_type_server *dap_adapter_type_server*
rustaceanvim.dap.adapter.types.server *rustaceanvim.dap.adapter.types.server*
Type: ~
DapClientConfig : Configuration *DapClientConfig*
*rustaceanvim.dap.client.Config*
rustaceanvim.dap.client.Config : Configuration
Fields: ~
{type} (string) The dap adapter to use
{type} (string) The dap adapter to use
{name} (string)
{request} (dap_config_request_launch|dap_config_request_attach|dap_config_request_custom) The type of dap session
{cwd?} (string) Current working directory
{program?} (string) Path to executable for most DAP clients
{args?} (string[]) Optional args to DAP client, not valid for all client types
{env?} (EnvironmentMap) Environmental variables
{initCommands?} (string[]) Initial commands to run, `lldb` clients only
{coreConfigs?} (table) Essential config values for `probe-rs` client, see https://probe.rs/docs/tools/debugger/
{request} (rustaceanvim.dap.config.requests.launch|rustaceanvim.dap.config.requests.attach|rustaceanvim.dap.config.requests.custom) The type of dap session
{cwd?} (string) Current working directory
{program?} (string) Path to executable for most DAP clients
{args?} (string[]) Optional args to DAP client, not valid for all client types
{env?} (rustaceanvim.EnvironmentMap) Environmental variables
{initCommands?} (string[]) Initial commands to run, `lldb` clients only
{coreConfigs?} (table)
Essential config values for `probe-rs` client, see https://probe.rs/docs/tools/debugger/
EnvironmentMap *EnvironmentMap*
rustaceanvim.EnvironmentMap *rustaceanvim.EnvironmentMap*
Type: ~
table<string,string[]>
dap_config_request_launch *dap_config_request_launch*
rustaceanvim.dap.config.requests.launch*rustaceanvim.dap.config.requests.launch*
Type: ~
dap_config_request_attach *dap_config_request_attach*
rustaceanvim.dap.config.requests.attach*rustaceanvim.dap.config.requests.attach*
Type: ~
dap_config_request_custom *dap_config_request_custom*
rustaceanvim.dap.config.requests.custom*rustaceanvim.dap.config.requests.custom*
Type: ~
@ -349,13 +414,13 @@ M.get_codelldb_adapter({codelldb_path}, {liblldb_path})
{liblldb_path} (string) Path to the liblldb dynamic library
Returns: ~
(DapServerConfig)
(rustaceanvim.dap.server.Config)
==============================================================================
LSP configuration utility *rustaceanvim.config.server*
LoadRASettingsOpts *LoadRASettingsOpts*
rustaceanvim.LoadRASettingsOpts *rustaceanvim.LoadRASettingsOpts*
Fields: ~
{settings_file_pattern} (string|nil) File name or pattern to search for. Defaults to 'rust-analyzer.json'
@ -368,8 +433,8 @@ server.load_rust_analyzer_settings({project_root}, {opts})
falling back to the default settings if none is found or if it cannot be decoded.
Parameters: ~
{project_root} (string|nil) The project root
{opts} (LoadRASettingsOpts|nil)
{project_root} (string|nil) The project root
{opts} (rustaceanvim.LoadRASettingsOpts|nil)
Returns: ~
(table) server_settings
@ -410,4 +475,31 @@ Note: If you use this adapter, do not add the neotest-rust adapter
(another plugin).
==============================================================================
*rustaceanvim.dap*
The DAP integration requires `nvim-dap` https://github.com/mfussenegger/nvim-dap
(Please read the plugin's documentation, see |dap-adapter|)
and a debug adapter (e.g. `lldb` https://lldb.llvm.org/
or `codelldb` https://github.com/vadimcn/codelldb).
By default, this plugin will silently attempt to autoload |dap-configuration|s
when the LSP client attaches.
You can call them with `require('dap').continue()` or `:DapContinue` once
they have been loaded. The feature can be disabled by setting
`vim.g.rustaceanvim.dap.autoload_configurations = false`.
- `:RustLsp debuggables` will only load debug configurations
created by `rust-analyzer`.
- `require('dap').continue()` will load all Rust debug configurations,
including those specified in a `.vscode/launch.json`
(see |dap-launch.json|)
IMPORTANT: Note that rustaceanvim may only be able to load DAP configurations
when rust-analyzer has finished initializing (which may be after
the client attaches, in large projects). This means that the
DAP configurations may not be loaded immediately upon startup.
vim:tw=78:ts=8:noet:ft=help:norl:

View File

@ -1,38 +1,36 @@
DapClientConfig rustaceanvim.txt /*DapClientConfig*
DapCommand rustaceanvim.txt /*DapCommand*
DapExecutable rustaceanvim.txt /*DapExecutable*
DapExecutableConfig rustaceanvim.txt /*DapExecutableConfig*
DapServerConfig rustaceanvim.txt /*DapServerConfig*
EnvironmentMap rustaceanvim.txt /*EnvironmentMap*
FloatWinConfig rustaceanvim.txt /*FloatWinConfig*
LoadRASettingsOpts rustaceanvim.txt /*LoadRASettingsOpts*
M.get_codelldb_adapter rustaceanvim.txt /*M.get_codelldb_adapter*
RustAnalyzerInitializedStatus rustaceanvim.txt /*RustAnalyzerInitializedStatus*
RustaceanCodeActionOpts rustaceanvim.txt /*RustaceanCodeActionOpts*
RustaceanCrateGraphConfig rustaceanvim.txt /*RustaceanCrateGraphConfig*
RustaceanDapOpts rustaceanvim.txt /*RustaceanDapOpts*
RustaceanExecutor rustaceanvim.txt /*RustaceanExecutor*
RustaceanExecutorOpts rustaceanvim.txt /*RustaceanExecutorOpts*
RustaceanHoverActionsOpts rustaceanvim.txt /*RustaceanHoverActionsOpts*
RustaceanLspClientOpts rustaceanvim.txt /*RustaceanLspClientOpts*
RustaceanOpts rustaceanvim.txt /*RustaceanOpts*
RustaceanToolsOpts rustaceanvim.txt /*RustaceanToolsOpts*
RustcOpts rustaceanvim.txt /*RustcOpts*
dap_adapter_type_executable rustaceanvim.txt /*dap_adapter_type_executable*
dap_adapter_type_server rustaceanvim.txt /*dap_adapter_type_server*
dap_config_request_attach rustaceanvim.txt /*dap_config_request_attach*
dap_config_request_custom rustaceanvim.txt /*dap_config_request_custom*
dap_config_request_launch rustaceanvim.txt /*dap_config_request_launch*
disable rustaceanvim.txt /*disable*
executor_alias rustaceanvim.txt /*executor_alias*
intro rustaceanvim.txt /*intro*
lsp_server_health_status rustaceanvim.txt /*lsp_server_health_status*
rustaceanvim rustaceanvim.txt /*rustaceanvim*
rustaceanvim.EnvironmentMap rustaceanvim.txt /*rustaceanvim.EnvironmentMap*
rustaceanvim.Executor rustaceanvim.txt /*rustaceanvim.Executor*
rustaceanvim.ExecutorOpts rustaceanvim.txt /*rustaceanvim.ExecutorOpts*
rustaceanvim.FloatWinConfig rustaceanvim.txt /*rustaceanvim.FloatWinConfig*
rustaceanvim.LoadRASettingsOpts rustaceanvim.txt /*rustaceanvim.LoadRASettingsOpts*
rustaceanvim.Opts rustaceanvim.txt /*rustaceanvim.Opts*
rustaceanvim.RAInitializedStatus rustaceanvim.txt /*rustaceanvim.RAInitializedStatus*
rustaceanvim.code-action.Opts rustaceanvim.txt /*rustaceanvim.code-action.Opts*
rustaceanvim.config rustaceanvim.txt /*rustaceanvim.config*
rustaceanvim.config.server rustaceanvim.txt /*rustaceanvim.config.server*
rustaceanvim.contents rustaceanvim.txt /*rustaceanvim.contents*
rustaceanvim.crate-graph.Opts rustaceanvim.txt /*rustaceanvim.crate-graph.Opts*
rustaceanvim.dap rustaceanvim.txt /*rustaceanvim.dap*
rustaceanvim.dap.Command rustaceanvim.txt /*rustaceanvim.dap.Command*
rustaceanvim.dap.Executable rustaceanvim.txt /*rustaceanvim.dap.Executable*
rustaceanvim.dap.Opts rustaceanvim.txt /*rustaceanvim.dap.Opts*
rustaceanvim.dap.adapter.types.executable rustaceanvim.txt /*rustaceanvim.dap.adapter.types.executable*
rustaceanvim.dap.adapter.types.server rustaceanvim.txt /*rustaceanvim.dap.adapter.types.server*
rustaceanvim.dap.client.Config rustaceanvim.txt /*rustaceanvim.dap.client.Config*
rustaceanvim.dap.executable.Config rustaceanvim.txt /*rustaceanvim.dap.executable.Config*
rustaceanvim.dap.server.Config rustaceanvim.txt /*rustaceanvim.dap.server.Config*
rustaceanvim.disable rustaceanvim.txt /*rustaceanvim.disable*
rustaceanvim.executor_alias rustaceanvim.txt /*rustaceanvim.executor_alias*
rustaceanvim.hover-actions.Opts rustaceanvim.txt /*rustaceanvim.hover-actions.Opts*
rustaceanvim.intro rustaceanvim.txt /*rustaceanvim.intro*
rustaceanvim.lsp.ClientOpts rustaceanvim.txt /*rustaceanvim.lsp.ClientOpts*
rustaceanvim.lsp_server_health_status rustaceanvim.txt /*rustaceanvim.lsp_server_health_status*
rustaceanvim.mason mason.txt /*rustaceanvim.mason*
rustaceanvim.neotest rustaceanvim.txt /*rustaceanvim.neotest*
rustaceanvim.rustc.Opts rustaceanvim.txt /*rustaceanvim.rustc.Opts*
rustaceanvim.test_executor_alias rustaceanvim.txt /*rustaceanvim.test_executor_alias*
rustaceanvim.tools.Opts rustaceanvim.txt /*rustaceanvim.tools.Opts*
server.create_client_capabilities rustaceanvim.txt /*server.create_client_capabilities*
server.load_rust_analyzer_settings rustaceanvim.txt /*server.load_rust_analyzer_settings*
test_executor_alias rustaceanvim.txt /*test_executor_alias*

View File

@ -1,4 +1,4 @@
---@type RustaceanConfig
---@type rustaceanvim.Config
local config = require('rustaceanvim.config.internal')
if not vim.g.loaded_rustaceanvim then
@ -8,7 +8,7 @@ if not vim.g.loaded_rustaceanvim then
vim.lsp.commands['rust-analyzer.runSingle'] = function(command)
local runnables = require('rustaceanvim.runnables')
local cached_commands = require('rustaceanvim.cached_commands')
---@type RARunnable[]
---@type rustaceanvim.RARunnable[]
local ra_runnables = command.arguments
local runnable = ra_runnables[1]
local cargo_args = runnable.args.cargoArgs

View File

@ -1,19 +1,19 @@
local M = {}
---@alias RARunnablesChoice { choice: integer, runnables: RARunnable[] }
---@alias rustaceanvim.RARunnablesChoice { choice: integer, runnables: rustaceanvim.RARunnable[] }
---@class CommandCache
---@class rustaceanvim.CommandCache
local cache = {
---@type RARunnableArgs | nil
---@type rustaceanvim.RARunnableArgs | nil
last_debuggable = nil,
---@type RARunnablesChoice
---@type rustaceanvim.RARunnablesChoice
last_runnable = nil,
---@type RARunnablesChoice
---@type rustaceanvim.RARunnablesChoice
last_testable = nil,
}
---@param choice integer
---@param runnables RARunnable[]
---@param runnables rustaceanvim.RARunnable[]
M.set_last_runnable = function(choice, runnables)
cache.last_runnable = {
choice = choice,
@ -22,7 +22,7 @@ M.set_last_runnable = function(choice, runnables)
end
---@param choice integer
---@param runnables RARunnable[]
---@param runnables rustaceanvim.RARunnable[]
M.set_last_testable = function(choice, runnables)
cache.last_testable = {
choice = choice,
@ -30,7 +30,7 @@ M.set_last_testable = function(choice, runnables)
}
end
---@param args RARunnableArgs
---@param args rustaceanvim.RARunnableArgs
M.set_last_debuggable = function(args)
cache.last_debuggable = args
end
@ -50,7 +50,7 @@ M.execute_last_debuggable = function(executableArgsOverride)
end
end
---@param choice RARunnablesChoice
---@param choice rustaceanvim.RARunnablesChoice
---@param executableArgsOverride? string[]
local function override_executable_args_if_set(choice, executableArgsOverride)
if type(executableArgsOverride) == 'table' and #executableArgsOverride > 0 then

View File

@ -1,7 +1,5 @@
local compat = require('rustaceanvim.compat')
local rust_analyzer = require('rustaceanvim.rust_analyzer')
local os = require('rustaceanvim.os')
local joinpath = compat.joinpath
local cargo = {}
@ -10,13 +8,13 @@ local cargo = {}
---@return string | nil root_dir The root directory of the active client for file_name (if there is one)
local function get_mb_active_client_root(file_name)
---@diagnostic disable-next-line: missing-parameter
local cargo_home = compat.uv.os_getenv('CARGO_HOME') or joinpath(vim.env.HOME, '.cargo')
local registry = joinpath(cargo_home, 'registry', 'src')
local checkouts = joinpath(cargo_home, 'git', 'checkouts')
local cargo_home = vim.uv.os_getenv('CARGO_HOME') or vim.fs.joinpath(vim.env.HOME, '.cargo')
local registry = vim.fs.joinpath(cargo_home, 'registry', 'src')
local checkouts = vim.fs.joinpath(cargo_home, 'git', 'checkouts')
---@diagnostic disable-next-line: missing-parameter
local rustup_home = compat.uv.os_getenv('RUSTUP_HOME') or joinpath(vim.env.HOME, '.rustup')
local toolchains = joinpath(rustup_home, 'toolchains')
local rustup_home = vim.uv.os_getenv('RUSTUP_HOME') or vim.fs.joinpath(vim.env.HOME, '.rustup')
local toolchains = vim.fs.joinpath(rustup_home, 'toolchains')
for _, item in ipairs { toolchains, registry, checkouts } do
item = os.normalize_path_on_windows(item)
@ -29,7 +27,7 @@ end
---Attempts to find the root for an existing active client. If no existing
---client root is found, returns the result of evaluating `config.root_dir`.
---@param config RustaceanLspClientConfig
---@param config rustaceanvim.lsp.ClientConfig
---@param file_name string
---@return string | nil root_dir
function cargo.get_config_root_dir(config, file_name)
@ -46,6 +44,61 @@ function cargo.get_config_root_dir(config, file_name)
end
end
---@param path string The directory to search upward from
---@return string? cargo_crate_dir
---@return table? cargo_metadata
local function get_cargo_metadata(path)
---@diagnostic disable-next-line: missing-fields
local cargo_crate_dir = vim.fs.dirname(vim.fs.find({ 'Cargo.toml' }, {
upward = true,
path = path,
})[1])
if vim.fn.executable('cargo') ~= 1 then
return cargo_crate_dir
end
local cmd = { 'cargo', 'metadata', '--no-deps', '--format-version', '1' }
if cargo_crate_dir ~= nil then
cmd[#cmd + 1] = '--manifest-path'
cmd[#cmd + 1] = vim.fs.joinpath(cargo_crate_dir, 'Cargo.toml')
end
local sc = vim
.system(cmd, {
cwd = vim.uv.fs_stat(path) and path or cargo_crate_dir or vim.fn.getcwd(),
})
:wait()
if sc.code ~= 0 then
return cargo_crate_dir
end
local ok, cargo_metadata_json = pcall(vim.fn.json_decode, sc.stdout)
if ok and cargo_metadata_json then
return cargo_crate_dir, cargo_metadata_json
end
return cargo_crate_dir
end
---@param buf_name? string
---@return string edition
function cargo.get_rustc_edition(buf_name)
local config = require('rustaceanvim.config.internal')
---@diagnostic disable-next-line: undefined-field
if config.tools.rustc.edition then
vim.deprecate('vim.g.rustaceanvim.config.tools.edition', 'default_edition', '6.0.0', 'rustaceanvim')
---@diagnostic disable-next-line: undefined-field
return config.tools.rustc.edition
end
buf_name = buf_name or vim.api.nvim_buf_get_name(0)
local path = vim.fs.dirname(buf_name)
local _, cargo_metadata = get_cargo_metadata(path)
local default_edition = config.tools.rustc.default_edition
if not cargo_metadata then
return default_edition
end
local package = vim.iter(cargo_metadata.packages or {}):find(function(pkg)
return type(pkg.edition) == 'string'
end)
return package and package.edition or default_edition
end
---The default implementation used for `vim.g.rustaceanvim.server.root_dir`
---@param file_name string
---@return string | nil root_dir
@ -54,40 +107,8 @@ function cargo.get_root_dir(file_name)
if not path then
return nil
end
---@diagnostic disable-next-line: missing-fields
local cargo_crate_dir = vim.fs.dirname(vim.fs.find({ 'Cargo.toml' }, {
upward = true,
path = path,
})[1])
---@type string | nil
local cargo_workspace_dir = nil
if vim.fn.executable('cargo') == 1 then
local cmd = { 'cargo', 'metadata', '--no-deps', '--format-version', '1' }
if cargo_crate_dir ~= nil then
cmd[#cmd + 1] = '--manifest-path'
cmd[#cmd + 1] = joinpath(cargo_crate_dir, 'Cargo.toml')
end
local cargo_metadata = ''
local cm = vim.fn.jobstart(cmd, {
on_stdout = function(_, d, _)
cargo_metadata = table.concat(d, '\n')
end,
stdout_buffered = true,
cwd = compat.uv.fs_stat(path) and path or cargo_crate_dir or vim.fn.getcwd(),
})
if cm > 0 then
cm = vim.fn.jobwait({ cm })[1]
else
cm = -1
end
if cm == 0 then
local ok, cargo_metadata_json = pcall(vim.fn.json_decode, cargo_metadata)
if ok and cargo_metadata_json then
cargo_workspace_dir = cargo_metadata_json['workspace_root']
end
end
end
return cargo_workspace_dir
local cargo_crate_dir, cargo_metadata = get_cargo_metadata(path)
return cargo_metadata and cargo_metadata.workspace_root
or cargo_crate_dir
---@diagnostic disable-next-line: missing-fields
or vim.fs.dirname(vim.fs.find({ 'rust-project.json' }, {

View File

@ -2,19 +2,19 @@ local ui = require('rustaceanvim.ui')
local config = require('rustaceanvim.config.internal')
local M = {}
---@class RACodeAction
---@class rustaceanvim.RACodeAction
---@field kind string
---@field group? string
---@field edit? table
---@field command? { command: string } | string
---@class RACommand
---@class rustaceanvim.RACommand
---@field title string
---@field group? string
---@field command string
---@field arguments? any[]
---@param action RACodeAction | RACommand
---@param action rustaceanvim.RACodeAction | rustaceanvim.RACommand
---@param client lsp.Client
---@param ctx table
function M.apply_action(action, client, ctx)
@ -32,7 +32,7 @@ function M.apply_action(action, client, ctx)
end
end
---@alias action_tuple { [1]: number, [2]: RACodeAction|RACommand }
---@alias action_tuple { [1]: number, [2]: rustaceanvim.RACodeAction|rustaceanvim.RACommand }
---@param action_tuple action_tuple | nil
---@param ctx table
@ -48,7 +48,7 @@ function M.on_user_choice(action_tuple, ctx)
end
if not action.edit and type(code_action_provider) == 'table' and code_action_provider.resolveProvider then
client.request('codeAction/resolve', action, function(err, resolved_action)
---@cast resolved_action RACodeAction|RACommand
---@cast resolved_action rustaceanvim.RACodeAction|rustaceanvim.RACommand
if err then
vim.notify(err.code .. ': ' .. err.message, vim.log.levels.ERROR)
return
@ -60,12 +60,12 @@ function M.on_user_choice(action_tuple, ctx)
end
end
---@class CodeActionWindowGeometry
---@class rustaceanvim.CodeActionWindowGeometry
---@field width integer
---@param action_tuples action_tuple[]
---@param is_group boolean
---@return CodeActionWindowGeometry
---@return rustaceanvim.CodeActionWindowGeometry
local function compute_width(action_tuples, is_group)
local width = 0
@ -106,10 +106,10 @@ local function on_primary_quit()
M.cleanup()
end
---@class RACodeActionResult
---@field result? RACodeAction[] | RACommand[]
---@class rustaceanvim.RACodeActionResult
---@field result? rustaceanvim.RACodeAction[] | rustaceanvim.RACommand[]
---@param results { [number]: RACodeActionResult }
---@param results { [number]: rustaceanvim.RACodeActionResult }
---@param ctx table
local function on_code_action_results(results, ctx)
local cur_win = vim.api.nvim_get_current_win()
@ -129,7 +129,7 @@ local function on_code_action_results(results, ctx)
M.state.primary.geometry = compute_width(action_tuples, true)
---@alias grouped_actions_tbl { actions: action_tuple[], idx: integer | nil }
---@class PartitionedActions
---@class rustaceanvim.PartitionedActions
M.state.actions = {
grouped = {},
ungrouped = {},
@ -332,16 +332,16 @@ function M.on_cursor_move()
end
end
---@class CodeActionWindowState
---@class rustaceanvim.CodeActionWindowState
---@field bufnr integer | nil
---@field winnr integer | nil
---@field geometry CodeActionWindowGeometry | nil
---@field geometry rustaceanvim.CodeActionWindowGeometry | nil
---@field clear fun()
---@class CodeActionInternalState
---@class rustaceanvim.CodeActionInternalState
M.state = {
ctx = {},
---@type PartitionedActions
---@type rustaceanvim.PartitionedActions
actions = {
---@type grouped_actions_tbl[]
grouped = {},
@ -350,7 +350,7 @@ M.state = {
},
---@type number | nil
active_group_index = nil,
---@type CodeActionWindowState
---@type rustaceanvim.CodeActionWindowState
primary = {
bufnr = nil,
winnr = nil,
@ -361,7 +361,7 @@ M.state = {
M.state.primary.winnr = nil
end,
},
---@type CodeActionWindowState
---@type rustaceanvim.CodeActionWindowState
secondary = {
bufnr = nil,
winnr = nil,

View File

@ -1,5 +1,4 @@
local config = require('rustaceanvim.config.internal')
local compat = require('rustaceanvim.compat')
local M = {}
@ -33,7 +32,7 @@ local function handler_factory(backend, output, pipe)
vim.notify('no crate graph backend specified.', vim.log.levels.ERROR)
return
end
if not compat.list_contains(config.tools.crate_graph.enabled_graphviz_backends, backend) then
if not vim.list_contains(config.tools.crate_graph.enabled_graphviz_backends, backend) then
vim.notify('crate graph backend not recognized as valid: ' .. vim.inspect(backend), vim.log.levels.ERROR)
return
end

View File

@ -1,6 +1,5 @@
local M = {}
local compat = require('rustaceanvim.compat')
local ra_runnables = require('rustaceanvim.runnables')
local config = require('rustaceanvim.config.internal')
@ -15,7 +14,7 @@ end
---@type { [string]: boolean? } Used to prevent this plugin from adding the same configuration twice
local _dap_configuration_added = {}
---@param args RARunnableArgs
---@param args rustaceanvim.RARunnableArgs
---@return string
local function build_label(args)
local ret = ''
@ -23,7 +22,7 @@ local function build_label(args)
ret = ret .. value .. ' '
end
for _, value in ipairs(args.cargoExtraArgs) do
for _, value in ipairs(args.cargoExtraArgs or {}) do
ret = ret .. value .. ' '
end
@ -36,7 +35,7 @@ local function build_label(args)
return ret
end
---@param result RARunnable[]
---@param result rustaceanvim.RARunnable[]
---@return string[] option_strings
local function get_options(result)
---@type string[]
@ -54,7 +53,7 @@ local function get_options(result)
return option_strings
end
---@param args RARunnableArgs
---@param args rustaceanvim.RARunnableArgs
---@return boolean
local function is_valid_test(args)
local is_not_cargo_check = args.cargoArgs[1] ~= 'check'
@ -67,11 +66,11 @@ end
-- This function also makes it so that the debuggable commands are more
-- debugging friendly. For example, we move cargo run to cargo build, and cargo
-- test to cargo test --no-run.
---@param result RARunnable[]
---@param result rustaceanvim.RARunnable[]
local function sanitize_results_for_debugging(result)
---@type RARunnable[]
---@type rustaceanvim.RARunnable[]
local ret = vim.tbl_filter(function(value)
---@cast value RARunnable
---@cast value rustaceanvim.RARunnable
return is_valid_test(value.args)
end, result or {})
@ -96,7 +95,7 @@ local function dap_run(args)
end
end
---@param debuggables RARunnable[]
---@param debuggables rustaceanvim.RARunnable[]
---@param executableArgsOverride? string[]
local function ui_select_debuggable(debuggables, executableArgsOverride)
debuggables = ra_runnables.apply_exec_args_override(executableArgsOverride, debuggables)
@ -113,7 +112,7 @@ local function ui_select_debuggable(debuggables, executableArgsOverride)
end)
end
---@param debuggables RARunnable[]
---@param debuggables rustaceanvim.RARunnable[]
local function add_debuggables_to_nvim_dap(debuggables)
local ok, dap = pcall(require, 'dap')
if not ok then
@ -133,7 +132,7 @@ local function add_debuggables_to_nvim_dap(debuggables)
end
end
---@param debuggables RARunnable[]
---@param debuggables rustaceanvim.RARunnable[]
---@param executableArgsOverride? string[]
local function debug_at_cursor_position(debuggables, executableArgsOverride)
if debuggables == nil then
@ -149,10 +148,10 @@ local function debug_at_cursor_position(debuggables, executableArgsOverride)
dap_run(args)
end
---@param callback fun(result:RARunnable[])
---@param callback fun(result:rustaceanvim.RARunnable[])
local function mk_handler(callback)
return function(_, result, _, _)
---@cast result RARunnable[]
---@cast result rustaceanvim.RARunnable[]
if result == nil then
return
end
@ -189,7 +188,7 @@ end
function M.add_dap_debuggables()
-- Defer, because rust-analyzer may not be ready yet
runnables_request(mk_handler(add_debuggables_to_nvim_dap))
local timer = compat.uv.new_timer()
local timer = vim.uv.new_timer()
timer:start(
2000,
0,

View File

@ -1,12 +1,11 @@
local M = {}
local config = require('rustaceanvim.config.internal')
local compat = require('rustaceanvim.compat')
local ui = require('rustaceanvim.ui')
local rustc = 'rustc'
---@class DiagnosticWindowState
---@class rustaceanvim.diagnostic.WindowState
local _window_state = {
---@type integer | nil
float_winnr = nil,
@ -16,8 +15,8 @@ local _window_state = {
---@param bufnr integer
---@param winnr integer
---@param lines string[]
local function set_open_split_keymap(bufnr, winnr, lines)
---@param render_fn function
local function set_split_open_keymap(bufnr, winnr, render_fn)
local function open_split()
-- check if a buffer with the latest id is already open, if it is then
-- delete it and continue
@ -29,11 +28,7 @@ local function set_open_split_keymap(bufnr, winnr, lines)
-- split the window to create a new buffer and set it to our window
local vsplit = config.tools.float_win_config.open_split == 'vertical'
ui.split(vsplit, _window_state.latest_scratch_buf_id)
-- set filetype to rust for syntax highlighting
vim.bo[_window_state.latest_scratch_buf_id].filetype = 'rust'
-- write the expansion content to the buffer
vim.api.nvim_buf_set_lines(_window_state.latest_scratch_buf_id, 0, 0, false, lines)
render_fn()
end
vim.keymap.set('n', '<CR>', function()
local line = vim.api.nvim_win_get_cursor(winnr)[1]
@ -142,7 +137,12 @@ function M.explain_error()
)
_window_state.float_winnr = winnr
set_close_keymaps(bufnr)
set_open_split_keymap(bufnr, winnr, markdown_lines)
set_split_open_keymap(bufnr, winnr, function()
-- set filetype to rust for syntax highlighting
vim.bo[_window_state.latest_scratch_buf_id].filetype = 'rust'
-- write the expansion content to the buffer
vim.api.nvim_buf_set_lines(_window_state.latest_scratch_buf_id, 0, 0, false, markdown_lines)
end)
if config.tools.float_win_config.auto_focus then
vim.api.nvim_set_current_win(winnr)
@ -155,7 +155,77 @@ function M.explain_error()
vim.api.nvim_win_set_cursor(win_id, { diagnostic.lnum + 1, diagnostic.col })
-- Open folds under the cursor
vim.cmd('normal! zv')
compat.system({ rustc, '--explain', tostring(diagnostic.code) }, nil, vim.schedule_wrap(handler))
vim.system({ rustc, '--explain', tostring(diagnostic.code) }, nil, vim.schedule_wrap(handler))
end
function M.explain_error_current_line()
if vim.fn.executable(rustc) ~= 1 then
vim.notify('rustc is needed to explain errors.', vim.log.levels.ERROR)
return
end
local win_id = vim.api.nvim_get_current_win()
local cursor_position = vim.api.nvim_win_get_cursor(win_id)
-- get matching diagnostics from current line
local diagnostics = vim.tbl_filter(
function(diagnostic)
return diagnostic.code ~= nil
and diagnostic.source == 'rustc'
and diagnostic.severity == vim.diagnostic.severity.ERROR
end,
vim.diagnostic.get(0, {
lnum = cursor_position[1] - 1,
})
)
-- no matching diagnostics on current line
if #diagnostics == 0 then
vim.notify('No explainable errors found.', vim.log.levels.INFO)
return
end
local diagnostic = diagnostics[1]
---@param sc vim.SystemCompleted
local function handler(sc)
if sc.code ~= 0 or not sc.stdout then
vim.notify('Error calling rustc --explain' .. (sc.stderr and ': ' .. sc.stderr or ''), vim.log.levels.ERROR)
return
end
local output = sc.stdout:gsub('```', '```rust', 1)
local markdown_lines = vim.lsp.util.convert_input_to_markdown_lines(output, {})
local float_preview_lines = vim.deepcopy(markdown_lines)
table.insert(float_preview_lines, 1, '---')
table.insert(float_preview_lines, 1, '1. Open in split')
vim.schedule(function()
close_hover()
local bufnr, winnr = vim.lsp.util.open_floating_preview(
float_preview_lines,
'markdown',
vim.tbl_extend('keep', config.tools.float_win_config, {
focus = false,
focusable = true,
focus_id = 'rustc-explain-error',
close_events = { 'CursorMoved', 'BufHidden', 'InsertCharPre' },
})
)
_window_state.float_winnr = winnr
set_close_keymaps(bufnr)
set_split_open_keymap(bufnr, winnr, function()
-- set filetype to rust for syntax highlighting
vim.bo[_window_state.latest_scratch_buf_id].filetype = 'rust'
-- write the expansion content to the buffer
vim.api.nvim_buf_set_lines(_window_state.latest_scratch_buf_id, 0, 0, false, markdown_lines)
end)
if config.tools.float_win_config.auto_focus then
vim.api.nvim_set_current_win(winnr)
end
end)
end
vim.system({ rustc, '--explain', tostring(diagnostic.code) }, nil, vim.schedule_wrap(handler))
end
---@param diagnostic table
@ -169,6 +239,73 @@ local function get_rendered_diagnostic(diagnostic)
end
end
---@param rendered_diagnostic string
local function render_ansi_code_diagnostic(rendered_diagnostic)
-- adopted from https://stackoverflow.com/questions/48948630/lua-ansi-escapes-pattern
local lines =
vim.split(rendered_diagnostic:gsub('[\27\155][][()#;?%d]*[A-PRZcf-ntqry=><~]', ''), '\n', { trimempty = true })
local float_preview_lines = vim.deepcopy(lines)
table.insert(float_preview_lines, 1, '---')
table.insert(float_preview_lines, 1, '1. Open in split')
vim.schedule(function()
close_hover()
local bufnr, winnr = vim.lsp.util.open_floating_preview(
float_preview_lines,
'',
vim.tbl_extend('keep', config.tools.float_win_config, {
focus = false,
focusable = true,
focus_id = 'ra-render-diagnostic',
close_events = { 'CursorMoved', 'BufHidden', 'InsertCharPre' },
})
)
vim.api.nvim_create_autocmd('WinEnter', {
callback = function()
vim.api.nvim_feedkeys(
vim.api.nvim_replace_termcodes(
[[<c-\><c-n>]] .. '<cmd>lua vim.api.nvim_win_set_cursor(' .. winnr .. ',{1,0})<CR>',
true,
false,
true
),
'n',
true
)
end,
buffer = bufnr,
})
local chanid = vim.api.nvim_open_term(bufnr, {})
vim.api.nvim_chan_send(chanid, vim.trim('1. Open in split\r\n' .. '---\r\n' .. rendered_diagnostic))
_window_state.float_winnr = winnr
set_close_keymaps(bufnr)
set_split_open_keymap(bufnr, winnr, function()
local chan_id = vim.api.nvim_open_term(_window_state.latest_scratch_buf_id, {})
vim.api.nvim_chan_send(chan_id, vim.trim(rendered_diagnostic))
end)
if config.tools.float_win_config.auto_focus then
vim.api.nvim_set_current_win(winnr)
vim.api.nvim_feedkeys(
vim.api.nvim_replace_termcodes(
'<cmd>lua vim.api.nvim_set_current_win('
.. winnr
.. ')<CR>'
.. [[<c-\><c-n>]]
.. '<cmd>lua vim.api.nvim_win_set_cursor('
.. winnr
.. ',{1,0})<CR>',
true,
false,
true
),
'n',
true
)
end
end)
end
function M.render_diagnostic()
local diagnostics = vim.tbl_filter(function(diagnostic)
return get_rendered_diagnostic(diagnostic) ~= nil
@ -224,29 +361,34 @@ function M.render_diagnostic()
-- Open folds under the cursor
vim.cmd('normal! zv')
local lines = vim.split(rendered_diagnostic, '\n')
local float_preview_lines = vim.deepcopy(lines)
table.insert(float_preview_lines, 1, '---')
table.insert(float_preview_lines, 1, '1. Open in split')
vim.schedule(function()
close_hover()
local bufnr, winnr = vim.lsp.util.open_floating_preview(
float_preview_lines,
'',
vim.tbl_extend('keep', config.tools.float_win_config, {
focus = false,
focusable = true,
focus_id = 'ra-render-diagnostic',
close_events = { 'CursorMoved', 'BufHidden', 'InsertCharPre' },
})
)
_window_state.float_winnr = winnr
set_close_keymaps(bufnr)
set_open_split_keymap(bufnr, winnr, lines)
if config.tools.float_win_config.auto_focus then
vim.api.nvim_set_current_win(winnr)
end
end)
render_ansi_code_diagnostic(rendered_diagnostic)
end
function M.render_diagnostic_current_line()
local win_id = vim.api.nvim_get_current_win()
local cursor_position = vim.api.nvim_win_get_cursor(win_id)
-- get rendered diagnostics from current line
local rendered_diagnostics = vim.tbl_map(
function(diagnostic)
return get_rendered_diagnostic(diagnostic)
end,
vim.diagnostic.get(0, {
lnum = cursor_position[1] - 1,
})
)
rendered_diagnostics = vim.tbl_filter(function(diagnostic)
return diagnostic ~= nil
end, rendered_diagnostics)
-- if no renderable diagnostics on current line
if #rendered_diagnostics == 0 then
vim.notify('No renderable diagnostics found.', vim.log.levels.INFO)
return
end
local rendered_diagnostic = rendered_diagnostics[1]
render_ansi_code_diagnostic(rendered_diagnostic)
end
return M

View File

@ -10,7 +10,7 @@ end
---@type integer | nil
local latest_buf_id = nil
---@class RAMacroExpansionResult
---@class rustaceanvim.RAMacroExpansionResult
---@field name string
---@field expansion string
@ -22,7 +22,7 @@ local latest_buf_id = nil
-- {
-- $crate::io::_eprint(std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(err),std::fmt::Display::fmt),]));
-- }
---@param result RAMacroExpansionResult
---@param result rustaceanvim.RAMacroExpansionResult
---@return string[]
local function parse_lines(result)
local ret = {}
@ -42,7 +42,7 @@ local function parse_lines(result)
return ret
end
---@param result? RAMacroExpansionResult
---@param result? rustaceanvim.RAMacroExpansionResult
local function handler(_, result)
-- echo a message when result is nil (meaning no macro under cursor) and
-- exit

View File

@ -2,9 +2,9 @@ local M = {}
local rl = require('rustaceanvim.rust_analyzer')
---@alias flyCheckCommand 'run' | 'clear' | 'cancel'
---@alias rustaceanvim.flyCheckCommand 'run' | 'clear' | 'cancel'
---@param cmd flyCheckCommand
---@param cmd rustaceanvim.flyCheckCommand
function M.fly_check(cmd)
local params = cmd == 'run' and vim.lsp.util.make_text_document_params() or {}
rl.notify('rust-analyzer/' .. cmd .. 'Flycheck', params)

View File

@ -2,18 +2,18 @@
local config = require('rustaceanvim.config.internal')
---@class RustaceanCommands
---@class rustaceanvim.Commands
local M = {}
local rust_lsp_cmd_name = 'RustLsp'
local rustc_cmd_name = 'Rustc'
---@class command_tbl
---@class rustaceanvim.command_tbl
---@field impl fun(args: string[], opts: vim.api.keyset.user_command) The command implementation
---@field complete? fun(subcmd_arg_lead: string): string[] Command completions callback, taking the lead of the subcommand's arguments
---@field bang? boolean Whether this command supports a bang!
---@type command_tbl[]
---@type rustaceanvim.command_tbl[]
local rustlsp_command_tbl = {
codeAction = {
impl = function(_)
@ -60,13 +60,39 @@ local rustlsp_command_tbl = {
end,
},
explainError = {
impl = function(_)
require('rustaceanvim.commands.diagnostic').explain_error()
impl = function(args)
local subcmd = args[1] or 'cycle'
if subcmd == 'cycle' then
require('rustaceanvim.commands.diagnostic').explain_error()
elseif subcmd == 'current' then
require('rustaceanvim.commands.diagnostic').explain_error_current_line()
else
vim.notify(
'explainError: unknown subcommand: ' .. subcmd .. " expected 'cycle' or 'current'",
vim.log.levels.ERROR
)
end
end,
complete = function()
return { 'cycle', 'current' }
end,
},
renderDiagnostic = {
impl = function(_)
require('rustaceanvim.commands.diagnostic').render_diagnostic()
impl = function(args)
local subcmd = args[1] or 'cycle'
if subcmd == 'cycle' then
require('rustaceanvim.commands.diagnostic').render_diagnostic()
elseif subcmd == 'current' then
require('rustaceanvim.commands.diagnostic').render_diagnostic_current_line()
else
vim.notify(
'renderDiagnostic: unknown subcommand: ' .. subcmd .. " expected 'cycle' or 'current'",
vim.log.levels.ERROR
)
end
end,
complete = function()
return { 'cycle', 'current' }
end,
},
rebuildProcMacros = {
@ -252,7 +278,7 @@ local rustlsp_command_tbl = {
},
}
---@type command_tbl[]
---@type rustaceanvim.command_tbl[]
local rustc_command_tbl = {
unpretty = {
impl = function(args)
@ -283,7 +309,7 @@ local rustc_command_tbl = {
},
}
---@param command_tbl command_tbl
---@param command_tbl rustaceanvim.command_tbl
---@param opts table
---@see vim.api.nvim_create_user_command
local function run_command(command_tbl, cmd_name, opts)

View File

@ -1,7 +1,6 @@
local M = {}
local rl = require('rustaceanvim.rust_analyzer')
local compat = require('rustaceanvim.compat')
local function get_params()
return vim.lsp.util.make_position_params(0, nil)
@ -15,7 +14,7 @@ local function handler(_, result, ctx)
local location = result
if compat.islist(result) then
if vim.islist(result) then
location = result[1]
end

View File

@ -1,7 +1,6 @@
local M = {}
local config = require('rustaceanvim.config.internal')
local compat = require('rustaceanvim.compat')
local cargo = require('rustaceanvim.cargo')
local ui = require('rustaceanvim.ui')
local api = vim.api
local ts = vim.treesitter
@ -27,7 +26,7 @@ M.available_unpretty = {
'stable-mir',
'mir-cfg',
}
---@alias rustcir_level 'normal'| 'identified'| 'expanded'| 'expanded,identified'| 'expanded,hygiene'| 'ast-tree'| 'ast-tree,expanded'| 'hir'| 'hir,identified'| 'hir,typed'| 'hir-tree'| 'thir-tree'| 'thir-flat'| 'mir'| 'stable-mir'| 'mir-cfg'
---@alias rustaceanvim.rustcir.level 'normal'| 'identified'| 'expanded'| 'expanded,identified'| 'expanded,hygiene'| 'ast-tree'| 'ast-tree,expanded'| 'hir'| 'hir,identified'| 'hir,typed'| 'hir-tree'| 'thir-tree'| 'thir-flat'| 'mir'| 'stable-mir'| 'mir-cfg'
---@type integer | nil
local latest_buf_id = nil
@ -93,9 +92,15 @@ local function handler(sc)
vim.api.nvim_buf_set_lines(latest_buf_id, 0, 0, false, lines)
end
---@param level rustcir_level
---@return boolean
local function has_tree_sitter_rust()
return #api.nvim_get_runtime_file('parser/rust.so', true) > 0
or require('rustaceanvim.shell').is_windows() and #api.nvim_get_runtime_file('parser/rust.dll', true) > 0
end
---@param level rustaceanvim.rustcir.level
function M.rustc_unpretty(level)
if #api.nvim_get_runtime_file('parser/rust.so', true) == 0 then
if not has_tree_sitter_rust() then
vim.notify("a treesitter parser for Rust is required for 'rustc unpretty'", vim.log.levels.ERROR)
return
end
@ -129,12 +134,12 @@ function M.rustc_unpretty(level)
end
text = table.concat(b, '\n')
compat.system({
vim.system({
rustc,
'--crate-type',
'lib',
'--edition',
config.tools.rustc.edition,
cargo.get_rustc_edition(),
'-Z',
'unstable-options',
'-Z',

View File

@ -6,7 +6,7 @@ local ui = require('rustaceanvim.ui')
---@type integer | nil
local latest_buf_id = nil
---@alias ir_level 'Hir' | 'Mir'
---@alias rustaceanvim.ir.level 'Hir' | 'Mir'
local function handler(level, err, result)
local requestType = 'view' .. level
@ -39,7 +39,7 @@ local function handler(level, err, result)
vim.api.nvim_buf_set_lines(latest_buf_id, 0, 0, false, lines)
end
---@param level ir_level
---@param level rustaceanvim.ir.level
function M.viewIR(level)
local position_params = vim.lsp.util.make_position_params(0, nil)
rl.buf_request(0, 'rust-analyzer/view' .. level, position_params, function(...)

View File

@ -1,116 +0,0 @@
---@diagnostic disable: deprecated, duplicate-doc-field, duplicate-doc-alias
---@mod rustaceanvim.compat Functions for backward compatibility with older Neovim versions
--- and with compatibility type annotations to make the type checker
--- happy for both stable and nightly neovim versions.
local M = {}
M.joinpath = vim.fs.joinpath or function(...)
return (table.concat({ ... }, '/'):gsub('//+', '/'))
end
---@class vim.lsp.get_clients.Filter
---@field id integer|nil Match clients by id
---@field bufnr integer|nil match clients attached to the given buffer
---@field name string|nil match clients by name
---@field method string|nil match client by supported method name
---@alias vim.lsp.get_active_clients.filter vim.lsp.get_clients.Filter
---@alias lsp.Client vim.lsp.Client
---@alias lsp.ClientConfig vim.lsp.ClientConfig
M.get_clients = vim.lsp.get_clients or vim.lsp.get_active_clients
M.uv = vim.uv or vim.loop
--- @enum vim.diagnostic.Severity
M.severity = {
ERROR = 1,
WARN = 2,
INFO = 3,
HINT = 4,
[1] = 'ERROR',
[2] = 'WARN',
[3] = 'INFO',
[4] = 'HINT',
}
--- @class vim.Diagnostic
--- @field bufnr? integer
--- @field lnum integer 0-indexed
--- @field end_lnum? integer 0-indexed
--- @field col integer 0-indexed
--- @field end_col? integer 0-indexed
--- @field severity? vim.diagnostic.Severity
--- @field message string
--- @field source? string
--- @field code? string
--- @field _tags? { deprecated: boolean, unnecessary: boolean}
--- @field user_data? any arbitrary data plugins can add
--- @field namespace? integer
--- @class vim.api.keyset.user_command
--- @field addr? any
--- @field bang? boolean
--- @field bar? boolean
--- @field complete? any
--- @field count? any
--- @field desc? any
--- @field force? boolean
--- @field keepscript? boolean
--- @field nargs? any
--- @field preview? any
--- @field range? any
--- @field register? boolean
--- @class vim.SystemCompleted
--- @field code integer
--- @field signal integer
--- @field stdout? string
--- @field stderr? string
M.system = vim.system
-- wrapper around vim.fn.system to give it a similar API to vim.system
or function(cmd, opts, on_exit)
---@cast cmd string[]
---@cast opts vim.SystemOpts | nil
---@cast on_exit fun(sc: vim.SystemCompleted) | nil
---@diagnostic disable-next-line: undefined-field
if opts and opts.cwd then
local shell = require('rustaceanvim.shell')
---@diagnostic disable-next-line: undefined-field
cmd = shell.chain_commands { shell.make_cd_command(opts.cwd), table.concat(cmd, ' ') }
---@cast cmd string
end
local output = vim.fn.system(cmd)
local ok = vim.v.shell_error
---@type vim.SystemCompleted
local systemObj = {
signal = 0,
stdout = ok and (output or '') or nil,
stderr = not ok and (output or '') or nil,
code = vim.v.shell_error,
}
if on_exit then
on_exit(systemObj)
end
return systemObj
end
M.list_contains = vim.list_contains
or function(t, value)
vim.validate { t = { t, 't' } }
for _, v in ipairs(t) do
if v == value then
return true
end
end
return false
end
---@alias lsp.Handler fun(err: lsp.ResponseError?, result: any, context: lsp.HandlerContext, config?: table): ...any
M.islist = vim.islist or vim.tbl_islist
return M

View File

@ -23,7 +23,7 @@ local function validate(path, tbl)
end
---Validates the config.
---@param cfg RustaceanConfig
---@param cfg rustaceanvim.Config
---@return boolean is_valid
---@return string|nil error_message
function M.validate(cfg)
@ -65,7 +65,7 @@ function M.validate(cfg)
end
local rustc = tools.rustc
ok, err = validate('tools.rustc', {
edition = { rustc.edition, 'string' },
default_edition = { rustc.default_edition, 'string' },
})
if not ok then
return false, err
@ -107,14 +107,14 @@ function M.validate(cfg)
if adapter == false then
ok = true
elseif adapter.type == 'executable' then
---@cast adapter DapExecutableConfig
---@cast adapter rustaceanvim.dap.executable.Config
ok, err = validate('dap.adapter', {
command = { adapter.command, 'string' },
name = { adapter.name, 'string', true },
args = { adapter.args, 'table', true },
})
elseif adapter.type == 'server' then
---@cast adapter DapServerConfig
---@cast adapter rustaceanvim.dap.server.Config
ok, err = validate('dap.adapter', {
command = { adapter.executable, 'table' },
name = { adapter.name, 'string', true },

View File

@ -11,13 +11,13 @@
---Example:
---
--->lua
------@type RustaceanOpts
------@type rustaceanvim.Opts
---vim.g.rustaceanvim = {
--- ---@type RustaceanToolsOpts
--- ---@type rustaceanvim.tools.Opts
--- tools = {
--- -- ...
--- },
--- ---@type RustaceanLspClientOpts
--- ---@type rustaceanvim.lsp.ClientOpts
--- server = {
--- on_attach = function(client, bufnr)
--- -- Set keybindings, etc. here.
@ -29,7 +29,7 @@
--- },
--- -- ...
--- },
--- ---@type RustaceanDapOpts
--- ---@type rustaceanvim.dap.Opts
--- dap = {
--- -- ...
--- },
@ -38,7 +38,7 @@
---
---Notes:
---
--- - `vim.g.rustaceanvim` can also be a function that returns a `RustaceanOpts` table.
--- - `vim.g.rustaceanvim` can also be a function that returns a `rustaceanvim.Opts` table.
--- - `server.settings`, by default, is a function that looks for a `rust-analyzer.json` file
--- in the project root, to load settings from it. It falls back to an empty table.
---
@ -46,130 +46,229 @@
local M = {}
---@type RustaceanOpts | fun():RustaceanOpts | nil
---@type rustaceanvim.Opts | fun():rustaceanvim.Opts | nil
vim.g.rustaceanvim = vim.g.rustaceanvim
---@class RustaceanOpts
---@field tools? RustaceanToolsOpts Plugin options
---@field server? RustaceanLspClientOpts Language server client options
---@field dap? RustaceanDapOpts Debug adapter options
---@class rustaceanvim.Opts
---@field tools? rustaceanvim.tools.Opts Plugin options
---@field server? rustaceanvim.lsp.ClientOpts Language server client options
---@field dap? rustaceanvim.dap.Opts Debug adapter options
---@class RustaceanToolsOpts
---@field executor? RustaceanExecutor | executor_alias The executor to use for runnables/debuggables
---@field test_executor? RustaceanExecutor | test_executor_alias The executor to use for runnables that are tests / testables
---@field crate_test_executor? RustaceanExecutor | test_executor_alias The executor to use for runnables that are crate test suites (--all-targets)
---@field cargo_override? string Set this to override the 'cargo' command for runnables, debuggables (etc., e.g. to 'cross'). If set, this takes precedence over 'enable_nextest'.
---@field enable_nextest? boolean Whether to enable nextest. If enabled, `cargo test` commands will be transformed to `cargo nextest run` commands. Defaults to `true` if cargo-nextest is detected. Ignored if `cargo_override` is set.
---@field enable_clippy? boolean Whether to enable clippy checks on save if a clippy installation is detected. Default: `true`
---@field on_initialized? fun(health:RustAnalyzerInitializedStatus) Function that is invoked when the LSP server has finished initializing
---@field reload_workspace_from_cargo_toml? boolean Automatically call `RustReloadWorkspace` when writing to a Cargo.toml file
---@field hover_actions? RustaceanHoverActionsOpts Options for hover actions
---@field code_actions? RustaceanCodeActionOpts Options for code actions
---@field float_win_config? FloatWinConfig Options applied to floating windows. See |api-win_config|.
---@field create_graph? RustaceanCrateGraphConfig Options for showing the crate graph based on graphviz and the dot
---@field open_url? fun(url:string):nil If set, overrides how to open URLs
---@field rustc? RustcOpts Options for `rustc`
---@class rustaceanvim.tools.Opts
---
---The executor to use for runnables/debuggables
---@field executor? rustaceanvim.Executor | rustaceanvim.executor_alias
---
---The executor to use for runnables that are tests / testables
---@field test_executor? rustaceanvim.Executor | rustaceanvim.test_executor_alias
---
---The executor to use for runnables that are crate test suites (--all-targets)
---@field crate_test_executor? rustaceanvim.Executor | rustaceanvim.test_executor_alias
---
---Set this to override the 'cargo' command for runnables, debuggables (etc., e.g. to 'cross').
---If set, this takes precedence over 'enable_nextest'.
---@field cargo_override? string
---
---Whether to enable nextest. If enabled, `cargo test` commands will be transformed to `cargo nextest run` commands.
---Defaults to `true` if cargo-nextest is detected. Ignored if `cargo_override` is set.
---@field enable_nextest? boolean
---
---Whether to enable clippy checks on save if a clippy installation is detected.
---Default: `true`
---@field enable_clippy? boolean
---
---Function that is invoked when the LSP server has finished initializing
---@field on_initialized? fun(health:rustaceanvim.RAInitializedStatus)
---
---Automatically call `RustReloadWorkspace` when writing to a Cargo.toml file
---@field reload_workspace_from_cargo_toml? boolean
---@field hover_actions? rustaceanvim.hover-actions.Opts Options for hover actions
---@field code_actions? rustaceanvim.code-action.Opts Options for code actions
---
---Options applied to floating windows.
---See |api-win_config|.
---@field float_win_config? rustaceanvim.FloatWinConfig
---
---Options for showing the crate graph based on graphviz and the dot
---@field create_graph? rustaceanvim.crate-graph.Opts
---
---If set, overrides how to open URLs
---@field open_url? fun(url:string):nil
---
---Options for `rustc`
---@field rustc? rustaceanvim.rustc.Opts
---@class RustaceanExecutor
---@field execute_command fun(cmd:string, args:string[], cwd:string|nil, opts?: RustaceanExecutorOpts)
---@class rustaceanvim.Executor
---@field execute_command fun(cmd:string, args:string[], cwd:string|nil, opts?: rustaceanvim.ExecutorOpts)
---@class RustaceanExecutorOpts
---@field bufnr? integer The buffer from which the executor was invoked.
---@class rustaceanvim.ExecutorOpts
---
---The buffer from which the executor was invoked.
---@field bufnr? integer
---@class FloatWinConfig
---@class rustaceanvim.FloatWinConfig
---@field auto_focus? boolean
---@field open_split? 'horizontal' | 'vertical'
---@see vim.lsp.util.open_floating_preview.Opts
---@see vim.api.nvim_open_win
---@alias executor_alias 'termopen' | 'quickfix' | 'toggleterm' | 'vimux'
---@alias rustaceanvim.executor_alias 'termopen' | 'quickfix' | 'toggleterm' | 'vimux'
---@alias test_executor_alias executor_alias | 'background' | 'neotest'
---@alias rustaceanvim.test_executor_alias rustaceanvim.executor_alias | 'background' | 'neotest'
---@class RustaceanHoverActionsOpts
---@field replace_builtin_hover? boolean Whether to replace Neovim's built-in `vim.lsp.buf.hover` with hover actions. Default: `true`
---@class rustaceanvim.hover-actions.Opts
---
---Whether to replace Neovim's built-in `vim.lsp.buf.hover` with hover actions.
---Default: `true`
---@field replace_builtin_hover? boolean
---@class RustaceanCodeActionOpts
---@field group_icon? string Text appended to a group action
---@field ui_select_fallback? boolean Whether to fall back to `vim.ui.select` if there are no grouped code actions. Default: `false`
---@class rustaceanvim.code-action.Opts
---
---Text appended to a group action
---@field group_icon? string
---
---Whether to fall back to `vim.ui.select` if there are no grouped code actions.
---Default: `false`
---@field ui_select_fallback? boolean
---@alias lsp_server_health_status 'ok' | 'warning' | 'error'
---@alias rustaceanvim.lsp_server_health_status 'ok' | 'warning' | 'error'
---@class RustAnalyzerInitializedStatus
---@field health lsp_server_health_status
---@class rustaceanvim.RAInitializedStatus
---@field health rustaceanvim.lsp_server_health_status
---@class RustaceanCrateGraphConfig
---@field backend? string Backend used for displaying the graph. See: https://graphviz.org/docs/outputs/ Defaults to `"x11"` if unset.
---@field output? string Where to store the output. No output if unset. Relative path from `cwd`.
---@field enabled_graphviz_backends? string[] Override the enabled graphviz backends list, used for input validation and autocompletion.
---@field pipe? string Overide the pipe symbol in the shell command. Useful if using a shell that is not supported by this plugin.
---@class rustaceanvim.crate-graph.Opts
---
---Backend used for displaying the graph.
---See: https://graphviz.org/docs/outputs/
---Defaults to `"x11"` if unset.
---@field backend? string
---
---Where to store the output. No output if unset.
---Relative path from `cwd`.
---@field output? string
---
---Override the enabled graphviz backends list, used for input validation and autocompletion.
---@field enabled_graphviz_backends? string[]
---
---Overide the pipe symbol in the shell command.
---Useful if using a shell that is not supported by this plugin.
---@field pipe? string
---@class RustcOpts
---@field edition string The edition to use. See https://rustc-dev-guide.rust-lang.org/guides/editions.html. Default '2021'.
---@class rustaceanvim.rustc.Opts
---
---The default edition to use if it cannot be auto-detected.
---See https://rustc-dev-guide.rust-lang.org/guides/editions.html.
---Default '2021'.
---@field default_edition? string
---@class RustaceanLspClientOpts
---@field auto_attach? boolean | fun(bufnr: integer):boolean Whether to automatically attach the LSP client. Defaults to `true` if the `rust-analyzer` executable is found.
---@field cmd? string[] | fun():string[] Command and arguments for starting rust-analyzer
---@field root_dir? string | fun(filename: string, default: fun(filename: string):string|nil):string|nil The directory to use for the attached LSP. Can be a function, which may return nil if no server should attach. The second argument contains the default implementation, which can be used for fallback behavior.
---@field settings? table | fun(project_root:string|nil, default_settings: table):table Setting passed to rust-analyzer. Defaults to a function that looks for a `rust-analyzer.json` file or returns an empty table. See https://rust-analyzer.github.io/manual.html#configuration.
---@field standalone? boolean Standalone file support (enabled by default). Disabling it may improve rust-analyzer's startup time.
---@field logfile? string The path to the rust-analyzer log file.
---@field load_vscode_settings? boolean Whether to search (upward from the buffer) for rust-analyzer settings in .vscode/settings json. If found, loaded settings will override configured options. Default: false
---@class rustaceanvim.lsp.ClientOpts
---
---Whether to automatically attach the LSP client.
---Defaults to `true` if the `rust-analyzer` executable is found.
---@field auto_attach? boolean | fun(bufnr: integer):boolean
---
---Command and arguments for starting rust-analyzer
---@field cmd? string[] | fun():string[]
---
---The directory to use for the attached LSP.
---Can be a function, which may return nil if no server should attach.
---The second argument contains the default implementation, which can be used for fallback behavior.
---@field root_dir? string | fun(filename: string, default: fun(filename: string):string|nil):string|nil
---
---Setting passed to rust-analyzer.
---Defaults to a function that looks for a `rust-analyzer.json` file or returns an empty table.
---See https://rust-analyzer.github.io/manual.html#configuration.
---@field settings? table | fun(project_root:string|nil, default_settings: table):table
---
---Standalone file support (enabled by default).
---Disabling it may improve rust-analyzer's startup time.
---@field standalone? boolean
---
---The path to the rust-analyzer log file.
---@field logfile? string
---
---Whether to search (upward from the buffer) for rust-analyzer settings in .vscode/settings json.
---If found, loaded settings will override configured options.
---Default: true
---@field load_vscode_settings? boolean
---@see vim.lsp.ClientConfig
---@class RustaceanDapOpts
--- @field autoload_configurations boolean Whether to autoload nvim-dap configurations when rust-analyzer has attached? Default: `true`.
---@field adapter? DapExecutableConfig | DapServerConfig | disable | fun():(DapExecutableConfig | DapServerConfig | disable) Defaults to creating the `rt_lldb` adapter, which is a `DapServerConfig` if `codelldb` is detected, and a `DapExecutableConfig` if `lldb` is detected. Set to `false` to disable.
---@field configuration? DapClientConfig | disable | fun():(DapClientConfig | disable) Dap client configuration. Defaults to a function that looks for a `launch.json` file or returns a `DapExecutableConfig` that launches the `rt_lldb` adapter. Set to `false` to disable.
---@field add_dynamic_library_paths? boolean | fun():boolean Accommodate dynamically-linked targets by passing library paths to lldb. Default: `true`.
---@field auto_generate_source_map? fun():boolean | boolean Whether to auto-generate a source map for the standard library.
---@field load_rust_types? fun():boolean | boolean Whether to get Rust types via initCommands (rustlib/etc/lldb_commands, lldb only). Default: `true`.
---@class rustaceanvim.dap.Opts
---
---Whether to autoload nvim-dap configurations when rust-analyzer has attached?
---Default: `true`.
---@field autoload_configurations boolean
---
---Defaults to creating the `rt_lldb` adapter, which is a |rustaceanvim.dap.server.Config|
---if `codelldb` is detected, and a |rustaceanvim.dap.executable.Config|` if `lldb` is detected.
-- Set to `false` to disable.
---@field adapter? rustaceanvim.dap.executable.Config | rustaceanvim.dap.server.Config | rustaceanvim.disable | fun():(rustaceanvim.dap.executable.Config | rustaceanvim.dap.server.Config | rustaceanvim.disable)
---
---Dap client configuration. Defaults to a function that looks for a `launch.json` file
---or returns a |rustaceanvim.dap.executable.Config| that launches the `rt_lldb` adapter.
---Set to `false` to disable.
---@field configuration? rustaceanvim.dap.client.Config | rustaceanvim.disable | fun():(rustaceanvim.dap.client.Config | rustaceanvim.disable)
---
---Accommodate dynamically-linked targets by passing library paths to lldb.
---Default: `true`.
---@field add_dynamic_library_paths? boolean | fun():boolean
---
---Whether to auto-generate a source map for the standard library.
---@field auto_generate_source_map? fun():boolean | boolean
---
---Whether to get Rust types via initCommands (rustlib/etc/lldb_commands, lldb only).
---Default: `true`.
---@field load_rust_types? fun():boolean | boolean
---@alias disable false
---@alias rustaceanvim.disable false
---@alias DapCommand string
---@alias rustaceanvim.dap.Command string
---@class DapExecutableConfig
---@field type dap_adapter_type_executable The type of debug adapter.
---@class rustaceanvim.dap.executable.Config
---
---The type of debug adapter.
---@field type rustaceanvim.dap.adapter.types.executable
---@field command string Default: `"lldb-vscode"`.
---@field args? string Default: unset.
---@field name? string Default: `"lldb"`.
---@class DapServerConfig
---@field type dap_adapter_type_server The type of debug adapter.
---@class rustaceanvim.dap.server.Config
---@field type rustaceanvim.dap.adapter.types.server The type of debug adapter.
---@field host? string The host to connect to.
---@field port string The port to connect to.
---@field executable DapExecutable The executable to run
---@field executable rustaceanvim.dap.Executable The executable to run
---@field name? string
---@class DapExecutable
---@class rustaceanvim.dap.Executable
---@field command string The executable.
---@field args string[] Its arguments.
---@alias dap_adapter_type_executable "executable"
---@alias dap_adapter_type_server "server"
---@alias rustaceanvim.dap.adapter.types.executable "executable"
---@alias rustaceanvim.dap.adapter.types.server "server"
---@class DapClientConfig: Configuration
---@class rustaceanvim.dap.client.Config: Configuration
---@field type string The dap adapter to use
---@field name string
---@field request dap_config_request_launch | dap_config_request_attach | dap_config_request_custom The type of dap session
---@field request rustaceanvim.dap.config.requests.launch | rustaceanvim.dap.config.requests.attach | rustaceanvim.dap.config.requests.custom The type of dap session
---@field cwd? string Current working directory
---@field program? string Path to executable for most DAP clients
---@field args? string[] Optional args to DAP client, not valid for all client types
---@field env? EnvironmentMap Environmental variables
---@field env? rustaceanvim.EnvironmentMap Environmental variables
---@field initCommands? string[] Initial commands to run, `lldb` clients only
---@field coreConfigs? table Essential config values for `probe-rs` client, see https://probe.rs/docs/tools/debugger/
---
---Essential config values for `probe-rs` client, see https://probe.rs/docs/tools/debugger/
---@field coreConfigs? table
---@alias EnvironmentMap table<string, string[]>
---@alias rustaceanvim.EnvironmentMap table<string, string[]>
---@alias dap_config_request_launch "launch"
---@alias dap_config_request_attach "attach"
---@alias dap_config_request_custom "custom"
---@alias rustaceanvim.dap.config.requests.launch "launch"
---@alias rustaceanvim.dap.config.requests.attach "attach"
---@alias rustaceanvim.dap.config.requests.custom "custom"
---For the heroes who want to use it.
---@param codelldb_path string Path to the codelldb executable
---@param liblldb_path string Path to the liblldb dynamic library
---@return DapServerConfig
---@return rustaceanvim.dap.server.Config
function M.get_codelldb_adapter(codelldb_path, liblldb_path)
return {
type = 'server',

View File

@ -1,6 +1,5 @@
local types = require('rustaceanvim.types.internal')
local cargo = require('rustaceanvim.cargo')
local compat = require('rustaceanvim.compat')
local config = require('rustaceanvim.config')
local executors = require('rustaceanvim.executors')
local os = require('rustaceanvim.os')
@ -8,11 +7,11 @@ local server_config = require('rustaceanvim.config.server')
local RustaceanConfig
---@class RustAnalyzerInitializedStatusInternal : RustAnalyzerInitializedStatus
---@field health lsp_server_health_status
---@class rustaceanvim.internal.RAInitializedStatus : rustaceanvim.RAInitializedStatus
---@field health rustaceanvim.lsp_server_health_status
---@field quiescent boolean inactive?
---
---@param dap_adapter DapExecutableConfig | DapServerConfig | disable
---@param dap_adapter rustaceanvim.dap.executable.Config | rustaceanvim.dap.server.Config | rustaceanvim.disable
---@return boolean
local function should_enable_dap_config_value(dap_adapter)
local adapter = types.evaluate(dap_adapter)
@ -22,21 +21,21 @@ local function should_enable_dap_config_value(dap_adapter)
return vim.fn.executable('rustc') == 1
end
---@param adapter DapServerConfig | DapExecutableConfig
---@param adapter rustaceanvim.dap.server.Config | rustaceanvim.dap.executable.Config
local function is_codelldb_adapter(adapter)
return adapter.type == 'server'
end
---@param adapter DapServerConfig | DapExecutableConfig
---@param adapter rustaceanvim.dap.server.Config | rustaceanvim.dap.executable.Config
local function is_lldb_adapter(adapter)
return adapter.type == 'executable'
end
---@param type string
---@return DapClientConfig
---@return rustaceanvim.dap.client.Config
local function load_dap_configuration(type)
-- default
---@type DapClientConfig
---@type rustaceanvim.dap.client.Config
local dap_config = {
name = 'Rust debug client',
type = type,
@ -55,7 +54,7 @@ local function load_dap_configuration(type)
-- `configurations` are tables of `configuration` entries
-- use the first `configuration` that matches
for _, entry in pairs(configuration_entries) do
---@cast entry DapClientConfig
---@cast entry rustaceanvim.dap.client.Config
if entry.type == type then
dap_config = entry
break
@ -66,39 +65,30 @@ local function load_dap_configuration(type)
return dap_config
end
---@return RustaceanExecutor
local function get_crate_test_executor()
if vim.fn.has('nvim-0.10.0') == 1 then
return executors.background
else
return executors.termopen
end
end
---@return RustaceanExecutor
---@return rustaceanvim.Executor
local function get_test_executor()
if package.loaded['rustaceanvim.neotest'] ~= nil then
-- neotest has been set up with rustaceanvim as an adapter
return executors.neotest
end
return get_crate_test_executor()
return executors.termopen
end
---@class RustaceanConfig
---@class rustaceanvim.Config
local RustaceanDefaultConfig = {
---@class RustaceanToolsConfig
---@class rustaceanvim.tools.Config
tools = {
--- how to execute terminal commands
--- options right now: termopen / quickfix / toggleterm / vimux
---@type RustaceanExecutor
---@type rustaceanvim.Executor
executor = executors.termopen,
---@type RustaceanExecutor
---@type rustaceanvim.Executor
test_executor = get_test_executor(),
---@type RustaceanExecutor
crate_test_executor = get_crate_test_executor(),
---@type rustaceanvim.Executor
crate_test_executor = executors.termopen,
---@type string | nil
cargo_override = nil,
@ -111,7 +101,7 @@ local RustaceanDefaultConfig = {
--- callback to execute once rust-analyzer is done initializing the workspace
--- The callback receives one parameter indicating the `health` of the server: "ok" | "warning" | "error"
---@type fun(health:RustAnalyzerInitializedStatus) | nil
---@type fun(health:rustaceanvim.RAInitializedStatus) | nil
on_initialized = nil,
--- automatically call RustReloadWorkspace when writing to a Cargo.toml file.
@ -120,7 +110,7 @@ local RustaceanDefaultConfig = {
--- options same as lsp hover
---@see vim.lsp.util.open_floating_preview
---@class RustaceanHoverActionsConfig
---@class rustaceanvim.hover-actions.Config
hover_actions = {
--- whether to replace Neovim's built-in `vim.lsp.buf.hover`.
@ -156,7 +146,7 @@ local RustaceanDefaultConfig = {
--- settings for showing the crate graph based on graphviz and the dot
--- command
---@class RustaceanCrateGraphConfig
---@class rustaceanvim.crate-graph.Config
crate_graph = {
-- backend used for displaying the graph
-- see: https://graphviz.org/docs/outputs/
@ -243,17 +233,16 @@ local RustaceanDefaultConfig = {
require('rustaceanvim.os').open_url(url)
end,
---settings for rustc
---@class RustaceanRustcConfig
---@class rustaceanvim.rustc.Config
rustc = {
---@type string
edition = '2021',
default_edition = '2021',
},
},
--- all the opts to send to the LSP client
--- these override the defaults set by rust-tools.nvim
---@diagnostic disable-next-line: undefined-doc-class
---@class RustaceanLspClientConfig: vim.lsp.ClientConfig
---@class rustaceanvim.lsp.ClientConfig: vim.lsp.ClientConfig
server = {
---@type lsp.ClientCapabilities
capabilities = server_config.create_client_capabilities(),
@ -301,34 +290,34 @@ local RustaceanDefaultConfig = {
['rust-analyzer'] = {},
},
---@type boolean Whether to search (upward from the buffer) for rust-analyzer settings in .vscode/settings json.
load_vscode_settings = false,
load_vscode_settings = true,
},
--- debugging stuff
--- @class RustaceanDapConfig
--- @class rustaceanvim.dap.Config
dap = {
--- @type boolean Whether to autoload nvim-dap configurations when rust-analyzer has attached?
autoload_configurations = vim.fn.has('nvim-0.10.0') == 1, -- Compiling the debug build cannot be run asynchronously on Neovim < 0.10
--- @type DapExecutableConfig | DapServerConfig | disable | fun():(DapExecutableConfig | DapServerConfig | disable)
autoload_configurations = true,
--- @type rustaceanvim.dap.executable.Config | rustaceanvim.dap.server.Config | rustaceanvim.disable | fun():(rustaceanvim.dap.executable.Config | rustaceanvim.dap.server.Config | rustaceanvim.disable)
adapter = function()
--- @type DapExecutableConfig | DapServerConfig | disable
--- @type rustaceanvim.dap.executable.Config | rustaceanvim.dap.server.Config | rustaceanvim.disable
local result = false
local has_mason, mason_registry = pcall(require, 'mason-registry')
if has_mason and mason_registry.is_installed('codelldb') then
local codelldb_package = mason_registry.get_package('codelldb')
local mason_codelldb_path = compat.joinpath(codelldb_package:get_install_path(), 'extension')
local codelldb_path = compat.joinpath(mason_codelldb_path, 'adapter', 'codelldb')
local liblldb_path = compat.joinpath(mason_codelldb_path, 'lldb', 'lib', 'liblldb')
local mason_codelldb_path = vim.fs.joinpath(codelldb_package:get_install_path(), 'extension')
local codelldb_path = vim.fs.joinpath(mason_codelldb_path, 'adapter', 'codelldb')
local liblldb_path = vim.fs.joinpath(mason_codelldb_path, 'lldb', 'lib', 'liblldb')
local shell = require('rustaceanvim.shell')
if shell.is_windows() then
codelldb_path = codelldb_path .. '.exe'
liblldb_path = compat.joinpath(mason_codelldb_path, 'lldb', 'bin', 'liblldb.dll')
liblldb_path = vim.fs.joinpath(mason_codelldb_path, 'lldb', 'bin', 'liblldb.dll')
else
liblldb_path = liblldb_path .. (shell.is_macos() and '.dylib' or '.so')
end
result = config.get_codelldb_adapter(codelldb_path, liblldb_path)
elseif vim.fn.executable('codelldb') == 1 then
---@cast result DapServerConfig
---@cast result rustaceanvim.dap.server.Config
result = {
type = 'server',
host = '127.0.0.1',
@ -345,7 +334,7 @@ local RustaceanDefaultConfig = {
return result
end
local command = has_lldb_dap and 'lldb-dap' or 'lldb-vscode'
---@cast result DapExecutableConfig
---@cast result rustaceanvim.dap.executable.Config
result = {
type = 'executable',
command = command,
@ -371,21 +360,21 @@ local RustaceanDefaultConfig = {
return false
end
local adapter = types.evaluate(RustaceanConfig.dap.adapter)
---@cast adapter DapExecutableConfig | DapServerConfig | disable
---@cast adapter rustaceanvim.dap.executable.Config | rustaceanvim.dap.server.Config | rustaceanvim.disable
return adapter ~= false and is_lldb_adapter(adapter)
end,
--- @type DapClientConfig | disable | fun():(DapClientConfig | disable)
--- @type rustaceanvim.dap.client.Config | rustaceanvim.disable | fun():(rustaceanvim.dap.client.Config | rustaceanvim.disable)
configuration = function()
local ok, _ = pcall(require, 'dap')
if not ok then
return false
end
local adapter = types.evaluate(RustaceanConfig.dap.adapter)
---@cast adapter DapExecutableConfig | DapServerConfig | disable
---@cast adapter rustaceanvim.dap.executable.Config | rustaceanvim.dap.server.Config | rustaceanvim.disable
if adapter == false then
return false
end
---@cast adapter DapExecutableConfig | DapServerConfig
---@cast adapter rustaceanvim.dap.executable.Config | rustaceanvim.dap.server.Config
local type = is_codelldb_adapter(adapter) and 'codelldb' or 'lldb'
return load_dap_configuration(type)
end,
@ -401,7 +390,7 @@ for _, executor in pairs { 'executor', 'test_executor', 'crate_test_executor' }
end
end
---@type RustaceanConfig
---@type rustaceanvim.Config
RustaceanConfig = vim.tbl_deep_extend('force', {}, RustaceanDefaultConfig, opts)
-- Override user dap.adapter config in a backward compatible way

View File

@ -2,19 +2,18 @@
local server = {}
---@class LoadRASettingsOpts
---@class rustaceanvim.LoadRASettingsOpts
---@field settings_file_pattern string|nil File name or pattern to search for. Defaults to 'rust-analyzer.json'
---@field default_settings table|nil Default settings to merge the loaded settings into
--- Load rust-analyzer settings from a JSON file,
--- falling back to the default settings if none is found or if it cannot be decoded.
---@param project_root string|nil The project root
---@param opts LoadRASettingsOpts|nil
---@param opts rustaceanvim.LoadRASettingsOpts|nil
---@return table server_settings
---@see https://rust-analyzer.github.io/manual.html#configuration
function server.load_rust_analyzer_settings(project_root, opts)
local config = require('rustaceanvim.config.internal')
local compat = require('rustaceanvim.compat')
local os = require('rustaceanvim.os')
local default_opts = { settings_file_pattern = 'rust-analyzer.json' }
@ -40,7 +39,7 @@ function server.load_rust_analyzer_settings(project_root, opts)
if not project_root then
return default_settings
end
local results = vim.fn.glob(compat.joinpath(project_root, opts.settings_file_pattern), true, true)
local results = vim.fn.glob(vim.fs.joinpath(project_root, opts.settings_file_pattern), true, true)
if #results == 0 then
return default_settings
end
@ -83,6 +82,7 @@ local function make_rustaceanvim_capabilities()
-- send actions with hover request
capabilities.experimental = {
hoverActions = true,
colorDiagnosticOutput = true,
hoverRange = true,
serverStatusNotification = true,
snippetTextEdit = true,

View File

@ -1,5 +1,31 @@
---@mod rustaceanvim.dap
---@brief [[
---
--- The DAP integration requires `nvim-dap` https://github.com/mfussenegger/nvim-dap
--- (Please read the plugin's documentation, see |dap-adapter|)
--- and a debug adapter (e.g. `lldb` https://lldb.llvm.org/
--- or `codelldb` https://github.com/vadimcn/codelldb).
---
--- By default, this plugin will silently attempt to autoload |dap-configuration|s
--- when the LSP client attaches.
--- You can call them with `require('dap').continue()` or `:DapContinue` once
--- they have been loaded. The feature can be disabled by setting
--- `vim.g.rustaceanvim.dap.autoload_configurations = false`.
---
--- - `:RustLsp debuggables` will only load debug configurations
--- created by `rust-analyzer`.
--- - `require('dap').continue()` will load all Rust debug configurations,
--- including those specified in a `.vscode/launch.json`
--- (see |dap-launch.json|)
---
--- IMPORTANT: Note that rustaceanvim may only be able to load DAP configurations
--- when rust-analyzer has finished initializing (which may be after
--- the client attaches, in large projects). This means that the
--- DAP configurations may not be loaded immediately upon startup.
---
---@brief ]]
local config = require('rustaceanvim.config.internal')
local compat = require('rustaceanvim.compat')
local shell = require('rustaceanvim.shell')
local types = require('rustaceanvim.types.internal')
@ -24,27 +50,16 @@ local dap = require('dap')
local M = {}
---@deprecated Use require('rustaceanvim.config').get_codelldb_adapter
function M.get_codelldb_adapter(...)
vim.deprecate(
"require('rustaceanvim.dap').get_codelldb_adapter",
"require('rustaceanvim.config').get_codelldb_adapter",
'4.0.0',
'rustaceanvim'
)
return require('rustaceanvim.config').get_codelldb_adapter(...)
end
local function get_cargo_args_from_runnables_args(runnable_args)
local cargo_args = runnable_args.cargoArgs
local message_json = '--message-format=json'
if not compat.list_contains(cargo_args, message_json) then
if not vim.list_contains(cargo_args, message_json) then
table.insert(cargo_args, message_json)
end
for _, value in ipairs(runnable_args.cargoExtraArgs) do
if not compat.list_contains(cargo_args, value) then
for _, value in ipairs(runnable_args.cargoExtraArgs or {}) do
if not vim.list_contains(cargo_args, value) then
table.insert(cargo_args, value)
end
end
@ -54,7 +69,7 @@ end
---@param callback fun(commit_hash:string)
local function get_rustc_commit_hash(callback)
compat.system({ 'rustc', '--version', '--verbose' }, nil, function(sc)
vim.system({ 'rustc', '--version', '--verbose' }, nil, function(sc)
---@cast sc vim.SystemCompleted
local result = sc.stdout
if sc.code ~= 0 or result == nil then
@ -69,7 +84,7 @@ local function get_rustc_commit_hash(callback)
end
local function get_rustc_sysroot(callback)
compat.system({ 'rustc', '--print', 'sysroot' }, nil, function(sc)
vim.system({ 'rustc', '--print', 'sysroot' }, nil, function(sc)
---@cast sc vim.SystemCompleted
local result = sc.stdout
if sc.code ~= 0 or result == nil then
@ -79,7 +94,8 @@ local function get_rustc_sysroot(callback)
end)
end
---@alias DapSourceMap {[string]: string}
---@package
---@alias rustaceanvim.dap.SourceMap {[string]: string}
---@param tbl { [string]: string }
---@return string[][]
@ -96,7 +112,7 @@ end
---codelldb expects a map,
-- while lldb expects a list of tuples.
---@param adapter DapExecutableConfig | DapServerConfig | boolean
---@param adapter rustaceanvim.dap.executable.Config | rustaceanvim.dap.server.Config | boolean
---@param tbl { [string]: string }
---@return string[][] | { [string]: string }
local function format_source_map(adapter, tbl)
@ -106,7 +122,7 @@ local function format_source_map(adapter, tbl)
return tbl_to_tuple_list(tbl)
end
---@type {[string]: DapSourceMap}
---@type {[string]: rustaceanvim.dap.SourceMap}
local source_maps = {}
---See https://github.com/vadimcn/codelldb/issues/204
@ -119,8 +135,8 @@ local function generate_source_map(workspace_root)
get_rustc_sysroot(function(rustc_sysroot)
local src_path
for _, src_dir in pairs { 'src', 'rustc-src' } do
src_path = compat.joinpath(rustc_sysroot, 'lib', 'rustlib', src_dir, 'rust')
if compat.uv.fs_stat(src_path) then
src_path = vim.fs.joinpath(rustc_sysroot, 'lib', 'rustlib', src_dir, 'rust')
if vim.uv.fs_stat(src_path) then
break
end
src_path = nil
@ -128,9 +144,9 @@ local function generate_source_map(workspace_root)
if not src_path then
return
end
---@type DapSourceMap
---@type rustaceanvim.dap.SourceMap
source_maps[workspace_root] = {
[compat.joinpath('/rustc', commit_hash)] = src_path,
[vim.fs.joinpath('/rustc', commit_hash)] = src_path,
}
end)
end)
@ -145,12 +161,12 @@ local function get_lldb_commands(workspace_root)
return
end
get_rustc_sysroot(function(rustc_sysroot)
local script = compat.joinpath(rustc_sysroot, 'lib', 'rustlib', 'etc', 'lldb_lookup.py')
if not compat.uv.fs_stat(script) then
local script = vim.fs.joinpath(rustc_sysroot, 'lib', 'rustlib', 'etc', 'lldb_lookup.py')
if not vim.uv.fs_stat(script) then
return
end
local script_import = 'command script import "' .. script .. '"'
local commands_file = compat.joinpath(rustc_sysroot, 'lib', 'rustlib', 'etc', 'lldb_commands')
local commands_file = vim.fs.joinpath(rustc_sysroot, 'lib', 'rustlib', 'etc', 'lldb_commands')
local file = io.open(commands_file, 'r')
local workspace_root_cmds = {}
if file then
@ -165,37 +181,37 @@ local function get_lldb_commands(workspace_root)
end
---map for codelldb, list of strings for lldb-dap
---@param adapter DapExecutableConfig | DapServerConfig
---@param adapter rustaceanvim.dap.executable.Config | rustaceanvim.dap.server.Config
---@param key string
---@param segments string[]
---@param sep string
---@return {[string]: string} | string[]
local function format_environment_variable(adapter, key, segments, sep)
---@diagnostic disable-next-line: missing-parameter
local existing = compat.uv.os_getenv(key)
local existing = vim.uv.os_getenv(key)
existing = existing and sep .. existing or ''
local value = table.concat(segments, sep) .. existing
return adapter.type == 'server' and { [key] = value } or { key .. '=' .. value }
end
---@type {[string]: EnvironmentMap}
---@type {[string]: rustaceanvim.EnvironmentMap}
local environments = {}
-- Most succinct description: https://github.com/bevyengine/bevy/issues/2589#issuecomment-1753413600
---@param adapter DapExecutableConfig | DapServerConfig
---@param adapter rustaceanvim.dap.executable.Config | rustaceanvim.dap.server.Config
---@param workspace_root string | nil
local function add_dynamic_library_paths(adapter, workspace_root)
if not workspace_root or environments[workspace_root] then
return
end
compat.system({ 'rustc', '--print', 'target-libdir' }, { cwd = workspace_root }, function(sc)
vim.system({ 'rustc', '--print', 'target-libdir' }, { cwd = workspace_root }, function(sc)
---@cast sc vim.SystemCompleted
local result = sc.stdout
if sc.code ~= 0 or result == nil then
return
end
local rustc_target_path = (result:gsub('\n$', ''))
local target_path = compat.joinpath(workspace_root, 'target', 'debug', 'deps')
local target_path = vim.fs.joinpath(workspace_root, 'target', 'debug', 'deps')
if shell.is_windows() then
environments[workspace_root] = environments[workspace_root]
or format_environment_variable(adapter, 'PATH', { rustc_target_path, target_path }, ';')
@ -222,8 +238,8 @@ local function pall_with_warn(action, desc)
end
end
---@param adapter DapExecutableConfig | DapServerConfig
---@param args RARunnableArgs
---@param adapter rustaceanvim.dap.executable.Config | rustaceanvim.dap.server.Config
---@param args rustaceanvim.RARunnableArgs
---@param verbose? boolean
local function handle_configured_options(adapter, args, verbose)
local is_generate_source_map_enabled = types.evaluate(config.dap.auto_generate_source_map)
@ -251,9 +267,10 @@ local function handle_configured_options(adapter, args, verbose)
end
end
---@param args RARunnableArgs
---@package
---@param args rustaceanvim.RARunnableArgs
---@param verbose? boolean
---@param callback? fun(config: DapClientConfig)
---@param callback? fun(config: rustaceanvim.dap.client.Config)
---@param on_error? fun(err: string)
function M.start(args, verbose, callback, on_error)
if verbose then
@ -265,7 +282,7 @@ function M.start(args, verbose, callback, on_error)
callback = dap.run
end
local adapter = types.evaluate(config.dap.adapter)
--- @cast adapter DapExecutableConfig | DapServerConfig | disable
--- @cast adapter rustaceanvim.dap.executable.Config | rustaceanvim.dap.server.Config | rustaceanvim.disable
if adapter == false then
on_error('Debug adapter is disabled.')
return
@ -278,7 +295,7 @@ function M.start(args, verbose, callback, on_error)
if verbose then
vim.notify('Compiling a debug build for debugging. This might take some time...')
end
compat.system(cmd, { cwd = args.workspaceRoot }, function(sc)
vim.system(cmd, { cwd = args.workspaceRoot }, function(sc)
---@cast sc vim.SystemCompleted
local output = sc.stdout
if sc.code ~= 0 or output == nil then
@ -304,10 +321,10 @@ function M.start(args, verbose, callback, on_error)
goto loop_end
end
local is_binary = compat.list_contains(artifact.target.crate_types, 'bin')
local is_build_script = compat.list_contains(artifact.target.kind, 'custom-build')
local is_binary = vim.list_contains(artifact.target.crate_types, 'bin')
local is_build_script = vim.list_contains(artifact.target.kind, 'custom-build')
local is_test = ((artifact.profile.test == true) and (artifact.executable ~= nil))
or compat.list_contains(artifact.target.kind, 'test')
or vim.list_contains(artifact.target.kind, 'test')
-- only add executable to the list if we want a binary debug and it is a binary
-- or if we want a test debug and it is a test
if
@ -343,11 +360,11 @@ function M.start(args, verbose, callback, on_error)
local _, dap_config = next(dap.configurations.rust or {})
local local_config = types.evaluate(config.dap.configuration)
--- @cast local_config DapClientConfig | boolean
--- @cast local_config rustaceanvim.dap.client.Config | boolean
---@diagnostic disable-next-line: param-type-mismatch
local final_config = local_config ~= false and vim.deepcopy(local_config) or vim.deepcopy(dap_config)
--- @cast final_config DapClientConfig
--- @cast final_config rustaceanvim.dap.client.Config
if dap.adapters[final_config.type] == nil then
on_error('No adapter exists named "' .. final_config.type .. '". See ":h dap-adapter" for more information')

View File

@ -6,7 +6,7 @@ local function get_test_summary(output)
return output:match('(test result:.*)')
end
---@type RustaceanExecutor
---@type rustaceanvim.Executor
---@diagnostic disable-next-line: missing-fields
local M = {}
@ -14,7 +14,7 @@ local M = {}
---@field test_id string
M.execute_command = function(command, args, cwd, opts)
---@type RustaceanExecutorOpts
---@type rustaceanvim.ExecutorOpts
opts = vim.tbl_deep_extend('force', { bufnr = 0 }, opts or {})
if vim.fn.has('nvim-0.10.0') ~= 1 then
vim.schedule(function()
@ -26,10 +26,9 @@ M.execute_command = function(command, args, cwd, opts)
vim.diagnostic.reset(diag_namespace, opts.bufnr)
local is_single_test = args[1] == 'test'
local notify_prefix = (is_single_test and 'test ' or 'tests ')
local compat = require('rustaceanvim.compat')
local cmd = vim.list_extend({ command }, args)
local fname = vim.api.nvim_buf_get_name(opts.bufnr)
compat.system(cmd, { cwd = cwd }, function(sc)
vim.system(cmd, { cwd = cwd }, function(sc)
---@cast sc vim.SystemCompleted
if sc.code == 0 then
local summary = get_test_summary(sc.stdout or '')

View File

@ -7,7 +7,7 @@ local vimux = require('rustaceanvim.executors.vimux')
local background = require('rustaceanvim.executors.background')
local neotest = require('rustaceanvim.executors.neotest')
---@type { [test_executor_alias]: RustaceanExecutor }
---@type { [rustaceanvim.test_executor_alias]: rustaceanvim.Executor }
local M = {}
M.termopen = termopen

View File

@ -1,7 +1,7 @@
error('Cannot import a meta module')
---@class RustaceanTestExecutor: RustaceanExecutor
---@field execute_command fun(cmd:string, args:string[], cwd:string|nil, opts?: RustaceanExecutorOpts)
---@class rustaceanvim.TestExecutor: rustaceanvim.Executor
---@field execute_command fun(cmd:string, args:string[], cwd:string|nil, opts?: rustaceanvim.ExecutorOpts)
---@class RustaceanTestExecutorOpts: RustaceanExecutorOpts
---@field runnable? RARunnable
---@class rustaceanvim.TestExecutor.Opts: rustaceanvim.ExecutorOpts
---@field runnable? rustaceanvim.RARunnable

View File

@ -1,12 +1,12 @@
local trans = require('rustaceanvim.neotest.trans')
---@type RustaceanTestExecutor
---@type rustaceanvim.TestExecutor
---@diagnostic disable-next-line: missing-fields
local M = {}
---@param opts RustaceanTestExecutorOpts
---@param opts rustaceanvim.TestExecutor.Opts
M.execute_command = function(_, _, _, opts)
---@type RustaceanTestExecutorOpts
---@type rustaceanvim.TestExecutor.Opts
opts = vim.tbl_deep_extend('force', { bufnr = 0 }, opts or {})
if type(opts.runnable) ~= 'table' then
vim.notify('rustaceanvim neotest executor called without a runnable. This is a bug!', vim.log.levels.ERROR)

View File

@ -1,5 +1,3 @@
local compat = require('rustaceanvim.compat')
local function clear_qf()
vim.fn.setqflist({}, ' ', { title = 'cargo' })
end
@ -10,8 +8,9 @@ local function scroll_qf()
end
end
local function append_qf(line)
vim.fn.setqflist({}, 'a', { lines = { line } })
---@param lines string[]
local function append_qf(lines)
vim.fn.setqflist({}, 'a', { lines = { lines } })
scroll_qf()
end
@ -19,7 +18,7 @@ local function copen()
vim.cmd('copen')
end
---@type RustaceanExecutor
---@type rustaceanvim.Executor
local M = {
execute_command = function(command, args, cwd, _)
-- open quickfix
@ -31,13 +30,16 @@ local M = {
-- start compiling
local cmd = vim.list_extend({ command }, args)
compat.system(
vim.system(
cmd,
cwd and { cwd = cwd } or {},
vim.schedule_wrap(function(sc)
---@cast sc vim.SystemCompleted
local data = sc.stdout or sc.stderr
append_qf(data)
local data = ([[
%s
%s
]]):format(sc.stdout or '', sc.stderr or '')
append_qf(vim.split(data, '\n'))
end)
)
end,

View File

@ -1,7 +1,7 @@
---@type integer | nil
local latest_buf_id = nil
---@type RustaceanExecutor
---@type rustaceanvim.Executor
local M = {
execute_command = function(command, args, cwd, _)
local shell = require('rustaceanvim.shell')

View File

@ -1,4 +1,4 @@
---@type RustaceanExecutor
---@type rustaceanvim.Executor
local M = {
execute_command = function(command, args, cwd, _)
local ok, term = pcall(require, 'toggleterm.terminal')

View File

@ -1,6 +1,6 @@
local shell = require('rustaceanvim.shell')
---@type RustaceanExecutor
---@type rustaceanvim.Executor
local M = {
execute_command = function(command, args, cwd, _)
local commands = {}

View File

@ -12,13 +12,13 @@ local error = h.error or h.report_error
---@diagnostic disable-next-line: deprecated
local warn = h.warn or h.report_warn
---@class LuaDependency
---@class rustaceanvim.LuaDependency
---@field module string The name of a module
---@field optional fun():boolean Function that returns whether the dependency is optional
---@field url string URL (markdown)
---@field info string Additional information
---@type LuaDependency[]
---@type rustaceanvim.LuaDependency[]
local lua_dependencies = {
{
module = 'dap',
@ -30,7 +30,7 @@ local lua_dependencies = {
},
}
---@class ExternalDependency
---@class rustaceanvim.ExternalDependency
---@field name string Name of the dependency
---@field get_binaries fun():string[] Function that returns the binaries to check for
---@field is_installed? fun(bin: string):boolean Default: `vim.fn.executable(bin) == 1`
@ -40,7 +40,7 @@ local lua_dependencies = {
---@field extra_checks_if_installed? fun(bin: string) Optional extra checks to perform if the dependency is installed
---@field extra_checks_if_not_installed? fun() Optional extra checks to perform if the dependency is not installed
---@param dep LuaDependency
---@param dep rustaceanvim.LuaDependency
local function check_lua_dependency(dep)
if pcall(require, dep.module) then
ok(dep.url .. ' installed.')
@ -53,7 +53,7 @@ local function check_lua_dependency(dep)
end
end
---@param dep ExternalDependency
---@param dep rustaceanvim.ExternalDependency
---@return boolean is_installed
---@return string binary
---@return string version
@ -79,7 +79,7 @@ local check_installed = function(dep)
return false, binaries[1], 'Could not find an executable binary.'
end
---@param dep ExternalDependency
---@param dep rustaceanvim.ExternalDependency
local function check_external_dependency(dep)
local is_installed, binary, version_or_err = check_installed(dep)
if is_installed then
@ -112,7 +112,7 @@ local function check_external_dependency(dep)
end
end
---@param config RustaceanConfig
---@param config rustaceanvim.Config
local function check_config(config)
start('Checking config')
if vim.g.rustaceanvim and not config.was_g_rustaceanvim_sourced then
@ -126,6 +126,15 @@ local function check_config(config)
end
end
local function is_dap_enabled()
if not pcall(require, 'dap') then
return false
end
local rustaceanvim = vim.g.rustaceanvim or {}
local opts = type(rustaceanvim) == 'function' and rustaceanvim() or rustaceanvim
return vim.tbl_get(opts, 'dap', 'adapter') ~= false
end
local function check_for_conflicts()
start('Checking for conflicting plugins')
require('rustaceanvim.config.check').check_for_lspconfig_conflict(error)
@ -139,6 +148,7 @@ end
local function check_tree_sitter()
start('Checking for tree-sitter parser')
local has_tree_sitter_rust_parser = #vim.api.nvim_get_runtime_file('parser/rust.so', true) > 0
or #vim.api.nvim_get_runtime_file('parser/rust.dll', true) > 0
if has_tree_sitter_rust_parser then
ok('tree-sitter parser for Rust detected.')
else
@ -158,7 +168,7 @@ function health.check()
start('Checking external dependencies')
local adapter = types.evaluate(config.dap.adapter)
---@cast adapter DapExecutableConfig | DapServerConfig | boolean
---@cast adapter rustaceanvim.dap.executable.Config | rustaceanvim.dap.server.Config | boolean
---@return string
local function get_rust_analyzer_binary()
@ -173,7 +183,7 @@ function health.check()
return cmd[1]
end
---@type ExternalDependency[]
---@type rustaceanvim.ExternalDependency[]
local external_dependencies = {
{
name = 'rust-analyzer',
@ -253,10 +263,10 @@ function health.check()
name = adapter.name or 'debug adapter',
get_binaries = function()
if adapter.type == 'executable' then
---@cast adapter DapExecutableConfig
---@cast adapter rustaceanvim.dap.executable.Config
return { 'lldb', adapter.command }
else
---@cast adapter DapServerConfig
---@cast adapter rustaceanvim.dap.server.Config
return { 'codelldb', adapter.executable.command }
end
end,
@ -270,6 +280,9 @@ function health.check()
]],
})
end
if adapter == false and is_dap_enabled() then
warn('No debug adapter detected. Make sure either lldb or codelldb is available on the path.')
end
for _, dep in ipairs(external_dependencies) do
check_external_dependency(dep)
end

View File

@ -7,7 +7,7 @@ local function get_params()
return lsp_util.make_position_params(0, nil)
end
---@class HoverActionsState
---@class rustaceanvim.hover_actions.State
local _state = {
---@type integer
winnr = nil,

View File

@ -1,6 +1,6 @@
---@toc rustaceanvim.contents
---@mod intro Introduction
---@mod rustaceanvim.intro Introduction
---@brief [[
---This plugin automatically configures the `rust-analyzer` builtin LSP client
---and integrates with other rust tools.
@ -34,15 +34,25 @@
--- 'expandMacro' - Expand macros recursively.
--- 'moveItem {up|down}' - Move items up or down.
--- 'hover {actions|range}' - Hover actions, or hover over visually selected range.
--- 'explainError' - Display a hover window with explanations form the Rust error index.
--- Like |vim.diagnostic.goto_next|, |explainError| will cycle diagnostics,
--- starting at the cursor position, until it can find a diagnostic with
--- an error code.
--- 'renderDiagnostic' - Display a hover window with the rendered diagnostic,
--- as displayed during `cargo build`.
--- Like |vim.diagnostic.goto_next|, |renderDiagnostic| will cycle diagnostics,
--- starting at the cursor position, until it can find a diagnostic with
--- rendered data.
--- 'explainError {cycle?|current?}' - Display a hover window with explanations form the Rust error index.
--- - If called with |cycle| or no args:
--- Like |vim.diagnostic.goto_next|,
--- |explainError| will cycle diagnostics,
--- starting at the cursor position,
--- until it can find a diagnostic with an error code.
--- - If called with |current|:
--- Searches for diagnostics only in the
--- current cursor line.
--- 'renderDiagnostic {cycle?|current?}' - Display a hover window with the rendered diagnostic,
--- as displayed during |cargo build|.
--- - If called with |cycle| or no args:
--- Like |vim.diagnostic.goto_next|,
--- |renderDiagnostic| will cycle diagnostics,
--- starting at the cursor position,
--- until it can find a diagnostic with rendered data.
--- - If called with |current|:
--- Searches for diagnostics only in the
--- current cursor line.
--- 'openCargo' - Open the Cargo.toml file for the current package.
--- 'openDocs' - Open docs.rs documentation for the symbol under the cursor.
--- 'parentModule' - Open the current module's parent module.

View File

@ -1,7 +1,6 @@
local M = {}
---@type RustaceanConfig
---@type rustaceanvim.Config
local config = require('rustaceanvim.config.internal')
local compat = require('rustaceanvim.compat')
local types = require('rustaceanvim.types.internal')
local rust_analyzer = require('rustaceanvim.rust_analyzer')
local server_status = require('rustaceanvim.server_status')
@ -46,7 +45,7 @@ local function find_vscode_settings(bufname)
return settings
end
local vscode_dir = found_dirs[1]
local results = vim.fn.glob(compat.joinpath(vscode_dir, 'settings.json'), true, true)
local results = vim.fn.glob(vim.fs.joinpath(vscode_dir, 'settings.json'), true, true)
if vim.tbl_isempty(results) then
return settings
end
@ -78,7 +77,7 @@ end
--- Checks if Neovim's file watcher is enabled, and if it isn't,
--- configures rust-analyzer to enable server-side file watching (if not configured otherwise).
---
---@param server_cfg LspStartConfig LSP start settings
---@param server_cfg rustaceanvim.lsp.StartConfig LSP start settings
local function configure_file_watcher(server_cfg)
local is_client_file_watcher_enabled =
vim.tbl_get(server_cfg.capabilities, 'workspace', 'didChangeWatchedFiles', 'dynamicRegistration')
@ -94,7 +93,7 @@ local function configure_file_watcher(server_cfg)
end
end
---@class LspStartConfig: RustaceanLspClientConfig
---@class rustaceanvim.lsp.StartConfig: rustaceanvim.lsp.ClientConfig
---@field root_dir string | nil
---@field init_options? table
---@field settings table
@ -114,7 +113,7 @@ M.start = function(bufnr)
bufnr = bufnr or vim.api.nvim_get_current_buf()
local bufname = vim.api.nvim_buf_get_name(bufnr)
local client_config = config.server
---@type LspStartConfig
---@type rustaceanvim.lsp.StartConfig
local lsp_start_config = vim.tbl_deep_extend('force', {}, client_config)
local root_dir = cargo.get_config_root_dir(client_config, bufname)
if not root_dir then
@ -182,6 +181,10 @@ M.start = function(bufnr)
if type(old_on_attach) == 'function' then
old_on_attach(...)
end
if config.dap.autoload_configurations then
-- When switching projects, there might be new debuggables (#466)
require('rustaceanvim.commands.debuggables').add_dap_debuggables()
end
end
local old_on_exit = lsp_start_config.on_exit
@ -243,7 +246,7 @@ end
M.restart = function(bufnr)
bufnr = bufnr or vim.api.nvim_get_current_buf()
local clients = M.stop(bufnr)
local timer, _, _ = compat.uv.new_timer()
local timer, _, _ = vim.uv.new_timer()
if not timer then
-- TODO: Log error when logging is implemented
return

View File

@ -28,7 +28,6 @@
---@diagnostic disable: duplicate-set-field
local cargo = require('rustaceanvim.cargo')
local compat = require('rustaceanvim.compat')
local config = require('rustaceanvim.config.internal')
local lib = require('neotest.lib')
local nio = require('nio')
@ -62,7 +61,7 @@ end
---@package
---@class rustaceanvim.neotest.Position: neotest.Position
---@field runnable? RARunnable
---@field runnable? rustaceanvim.RARunnable
----@param name string
----@return integer
@ -83,7 +82,7 @@ end
---@package
---@class nio.rustaceanvim.RequestClient: nio.lsp.RequestClient
---@field experimental_runnables fun(args: nio.lsp.types.ImplementationParams, bufnr: integer?, opts: nio.lsp.RequestOpts): nio.lsp.types.ResponseError|nil, RARunnable[]|nil
---@field experimental_runnables fun(args: nio.lsp.types.ImplementationParams, bufnr: integer?, opts: nio.lsp.RequestOpts): nio.lsp.types.ResponseError|nil, rustaceanvim.RARunnable[]|nil
---@package
---@param file_path string
@ -126,7 +125,7 @@ NeotestAdapter.discover_positions = function(file_path)
end
end
---@diagnostic disable-next-line: cast-type-mismatch
---@cast runnables RARunnable[]
---@cast runnables rustaceanvim.RARunnable[]
---@type { [string]: neotest.Position }
local tests_by_name = {}
@ -197,7 +196,7 @@ NeotestAdapter.discover_positions = function(file_path)
-- sort positions by their start range
local function sort_positions(to_sort)
for _, item in ipairs(to_sort) do
if compat.islist(item) then
if vim.islist(item) then
sort_positions(item)
end
end
@ -205,8 +204,8 @@ NeotestAdapter.discover_positions = function(file_path)
-- pop header from the list before sorting since it's used to sort in its parent's context
local header = table.remove(to_sort, 1)
table.sort(to_sort, function(a, b)
local a_item = compat.islist(a) and a[1] or a
local b_item = compat.islist(b) and b[1] or b
local a_item = vim.islist(a) and a[1] or a
local b_item = vim.islist(b) and b[1] or b
if a_item.range[1] == b_item.range[1] then
return a_item.name < b_item.name
else
@ -284,7 +283,7 @@ function NeotestAdapter.build_spec(run_args)
---@cast strategy string
lib.notify(strategy, vim.log.levels.ERROR)
end
---@cast strategy DapClientConfig
---@cast strategy rustaceanvim.dap.client.Config
---@type rustaceanvim.neotest.RunSpec
local run_spec = {
cwd = cwd,
@ -295,6 +294,14 @@ function NeotestAdapter.build_spec(run_args)
else
overrides.undo_debug_sanitize(runnable.args.cargoArgs)
end
local is_cargo_test = args[1] == 'test'
local insert_pos = is_cargo_test and 2 or 3
table.insert(args, insert_pos, '--no-fail-fast')
table.insert(args, insert_pos, '--color=never')
if is_cargo_test then
-- cargo test needs to pass --color=never to the test runner too
table.insert(args, '--color=never')
end
---@type rustaceanvim.neotest.RunSpec
---@diagnostic disable-next-line: missing-fields
local run_spec = {
@ -377,12 +384,7 @@ function NeotestAdapter.results(spec, strategy_result)
end
end
if has_failures then
local pass_positions = output_content:gmatch('test%s(%S+)%s...%sok')
for pos in pass_positions do
results[trans.get_position_id(context.file, pos)] = {
status = 'passed',
}
end
require('rustaceanvim.neotest.parser').populate_pass_positions(results, context, output_content)
end
return results
end

View File

@ -1,6 +1,6 @@
local M = {}
---@param runnable RARunnable
---@param runnable rustaceanvim.RARunnable
---@return string | nil
local function get_test_path(runnable)
local executableArgs = runnable.args and runnable.args.executableArgs or {}
@ -8,7 +8,7 @@ local function get_test_path(runnable)
end
---@overload fun(file_path: string, test_path: string | nil)
---@overload fun(file_path: string, runnable: RARunnable)
---@overload fun(file_path: string, runnable: rustaceanvim.RARunnable)
---@return string
function M.get_position_id(file_path, runnable)
local test_path = runnable
@ -20,7 +20,7 @@ function M.get_position_id(file_path, runnable)
end
---@param file_path string
---@param runnable RARunnable
---@param runnable rustaceanvim.RARunnable
---@return rustaceanvim.neotest.Position | nil
function M.runnable_to_position(file_path, runnable)
local cargoArgs = runnable.args and runnable.args.cargoArgs or {}

View File

@ -2,7 +2,6 @@
local os = {}
local compat = require('rustaceanvim.compat')
local shell = require('rustaceanvim.shell')
---@param url string
@ -17,15 +16,15 @@ function os.open_url(url)
end
if vim.fn.has('mac') == 1 then
compat.system({ 'open', url }, nil, on_exit)
vim.system({ 'open', url }, nil, on_exit)
return
end
if vim.fn.executable('sensible-browser') == 1 then
compat.system({ 'sensible-browser', url }, nil, on_exit)
vim.system({ 'sensible-browser', url }, nil, on_exit)
return
end
if vim.fn.executable('xdg-open') == 1 then
compat.system({ 'xdg-open', url }, nil, on_exit)
vim.system({ 'xdg-open', url }, nil, on_exit)
return
end
local ok, err = pcall(vim.fn['netrw#BrowseX'], url, 0)

View File

@ -1,7 +1,5 @@
local M = {}
local compat = require('rustaceanvim.compat')
---@param input string unparsed snippet
---@return string parsed snippet
local function parse_snippet_fallback(input)
@ -56,7 +54,7 @@ function M.try_nextest_transform(args)
}
local indexes_to_remove_reverse_order = {}
for i, arg in ipairs(args) do
if compat.list_contains(nextest_unsupported_flags, arg) then
if vim.list_contains(nextest_unsupported_flags, arg) then
table.insert(indexes_to_remove_reverse_order, 1, i)
end
end
@ -78,7 +76,7 @@ end
function M.sanitize_command_for_debugging(command)
if command[1] == 'run' then
command[1] = 'build'
elseif command[1] == 'test' and not compat.list_contains(command, '--no-run') then
elseif command[1] == 'test' and not vim.list_contains(command, '--no-run') then
table.insert(command, 2, '--no-run')
end
end

View File

@ -11,19 +11,19 @@ local function get_params()
}
end
---@class RARunnable
---@field args RARunnableArgs
---@class rustaceanvim.RARunnable
---@field args rustaceanvim.RARunnableArgs
---@field label string
---@field location? RARunnableLocation
---@field location? rustaceanvim.RARunnableLocation
---@class RARunnableLocation
---@class rustaceanvim.RARunnableLocation
---@field targetRange lsp.Range
---@field targetSelectionRange lsp.Range
---@class RARunnableArgs
---@class rustaceanvim.RARunnableArgs
---@field workspaceRoot string
---@field cargoArgs string[]
---@field cargoExtraArgs string[]
---@field cargoExtraArgs? string[]
---@field executableArgs string[]
---@param option string
@ -37,9 +37,9 @@ local function prettify_test_option(option)
return option:gsub('%-%-all%-targets', '(all targets)') or option
end
---@param result RARunnable[]
---@param result rustaceanvim.RARunnable[]
---@param executableArgsOverride? string[]
---@param opts RunnablesOpts
---@param opts rustaceanvim.runnables.Opts
---@return string[]
local function get_options(result, executableArgsOverride, opts)
local option_strings = {}
@ -62,9 +62,9 @@ local function get_options(result, executableArgsOverride, opts)
return option_strings
end
---@alias CargoCmd 'cargo'
---@alias rustaceanvim.CargoCmd 'cargo'
---@param runnable RARunnable
---@param runnable rustaceanvim.RARunnable
---@return string executable
---@return string[] args
---@return string | nil dir
@ -89,8 +89,8 @@ function M.get_command(runnable)
end
---@param choice integer
---@param runnables RARunnable[]
---@return CargoCmd command build command
---@param runnables rustaceanvim.RARunnable[]
---@return rustaceanvim.CargoCmd command build command
---@return string[] args
---@return string|nil dir
local function getCommand(choice, runnables)
@ -98,7 +98,7 @@ local function getCommand(choice, runnables)
end
---@param choice integer
---@param runnables RARunnable[]
---@param runnables rustaceanvim.RARunnable[]
function M.run_command(choice, runnables)
-- do nothing if choice is too high or too low
if not choice or choice < 1 or choice > #runnables then
@ -123,17 +123,17 @@ function M.run_command(choice, runnables)
end
end
---@param runnable RARunnable
---@param runnable rustaceanvim.RARunnable
---@return boolean
local function is_testable(runnable)
---@cast runnable RARunnable
---@cast runnable rustaceanvim.RARunnable
local cargoArgs = runnable.args and runnable.args.cargoArgs or {}
return #cargoArgs > 0 and vim.startswith(cargoArgs[1], 'test')
end
---@param executableArgsOverride? string[]
---@param runnables RARunnable[]
---@return RARunnable[]
---@param runnables rustaceanvim.RARunnable[]
---@return rustaceanvim.RARunnable[]
function M.apply_exec_args_override(executableArgsOverride, runnables)
if type(executableArgsOverride) == 'table' and #executableArgsOverride > 0 then
local unique_runnables = {}
@ -147,10 +147,10 @@ function M.apply_exec_args_override(executableArgsOverride, runnables)
end
---@param executableArgsOverride? string[]
---@param opts RunnablesOpts
---@return fun(_, result: RARunnable[])
---@param opts rustaceanvim.runnables.Opts
---@return fun(_, result: rustaceanvim.RARunnable[])
local function mk_handler(executableArgsOverride, opts)
---@param runnables RARunnable[]
---@param runnables rustaceanvim.RARunnable[]
return function(_, runnables)
if runnables == nil then
return
@ -182,7 +182,7 @@ local function is_within_range(position, targetRange)
return targetRange.start.line <= position.line and targetRange['end'].line >= position.line
end
---@param runnables RARunnable
---@param runnables rustaceanvim.RARunnable
---@return integer | nil choice
function M.get_runnable_at_cursor_position(runnables)
---@type lsp.Position
@ -206,7 +206,7 @@ function M.get_runnable_at_cursor_position(runnables)
end
local function mk_cursor_position_handler(executableArgsOverride)
---@param runnables RARunnable[]
---@param runnables rustaceanvim.RARunnable[]
return function(_, runnables)
if runnables == nil then
return
@ -226,14 +226,14 @@ local function mk_cursor_position_handler(executableArgsOverride)
end
end
---@class RunnablesOpts
---@class rustaceanvim.runnables.Opts
---@field tests_only? boolean
---Sends the request to rust-analyzer to get the runnables and handles them
---@param executableArgsOverride? string[]
---@param opts? RunnablesOpts
---@param opts? rustaceanvim.runnables.Opts
function M.runnables(executableArgsOverride, opts)
---@type RunnablesOpts
---@type rustaceanvim.runnables.Opts
opts = vim.tbl_deep_extend('force', { tests_only = false }, opts or {})
vim.lsp.buf_request(0, 'experimental/runnables', get_params(), mk_handler(executableArgsOverride, opts))
end

View File

@ -1,14 +1,13 @@
---@mod rustaceanvim.rust_analyzer Functions for interacting with rust-analyzer
local compat = require('rustaceanvim.compat')
local os = require('rustaceanvim.os')
---@class RustAnalyzerClientAdapter
---@class rustaceanvim.rust-analyzer.ClientAdapter
local M = {}
---@param bufnr number | nil 0 for the current buffer, `nil` for no buffer filter
---@param filter? vim.lsp.get_clients.Filter
---@return lsp.Client[]
---@return vim.lsp.Client[]
M.get_active_rustaceanvim_clients = function(bufnr, filter)
---@type vim.lsp.get_clients.Filter
filter = vim.tbl_deep_extend('force', filter or {}, {
@ -17,7 +16,7 @@ M.get_active_rustaceanvim_clients = function(bufnr, filter)
if bufnr then
filter.bufnr = bufnr
end
return compat.get_clients(filter)
return vim.lsp.get_clients(filter)
end
---@param method string LSP method name

View File

@ -5,7 +5,7 @@ local M = {}
---@type { [integer]: boolean }
local _ran_once = {}
---@param result RustAnalyzerInitializedStatusInternal
---@param result rustaceanvim.internal.RAInitializedStatus
function M.handler(_, result, ctx, _)
-- quiescent means the full set of results is ready.
if not result.quiescent or _ran_once[ctx.client_id] then

View File

@ -1,22 +1,20 @@
local M = {}
local compat = require('rustaceanvim.compat')
---@return boolean
function M.is_windows()
local sysname = compat.uv.os_uname().sysname
local sysname = vim.uv.os_uname().sysname
return sysname == 'Windows' or sysname == 'Windows_NT'
end
---@return boolean
function M.is_macos()
return compat.uv.os_uname().sysname == 'Darwin'
return vim.uv.os_uname().sysname == 'Darwin'
end
---@return boolean
local function is_nushell()
---@diagnostic disable-next-line: missing-parameter
local shell = compat.uv.os_getenv('SHELL')
local shell = vim.uv.os_getenv('SHELL')
local nu = 'nu'
-- Check if $SHELL ends in "nu"
return shell ~= nil and shell:sub(-string.len(nu)) == nu

View File

@ -1 +1 @@
/nix/store/3czmrawji85vf8979kll2yx2f1kjkric-lua-5.1.5
/nix/store/rn8bzg423wwkayzbsbmhmvcgjmbzrq5z-lua-5.1.5

View File

@ -1,72 +1,72 @@
rock_manifest = {
doc = {
["mason.txt"] = "858adffa88b1649b91187f49f191e376",
["rustaceanvim.txt"] = "015b5fced4394fb911e73ba609c2b00c"
["rustaceanvim.txt"] = "1eabb6dea51788209975fd19245bfcbe"
},
ftplugin = {
["rust.lua"] = "b225026e3590a6741373922fbae423e5",
["rust.lua"] = "0bbc548280195d6d0a741e9640808675",
["rust.vim"] = "3121ffa3b7f1aa9c3efbfe32e438dbeb",
["toml.lua"] = "a8807dcfb5f6687ac543f4f8da3a9554"
},
lua = {
rustaceanvim = {
["cached_commands.lua"] = "6e23c8231f44a3edc76be54766fca334",
["cargo.lua"] = "f2a24f708ff861b7aa914407c67a5c0e",
["cached_commands.lua"] = "31274668a1dc9e611c6fb4c0ac757d31",
["cargo.lua"] = "f5378ecec5944cb0ee3444c31c378b88",
commands = {
["code_action_group.lua"] = "55bf0c83a007e5d64924eafe2e2a96eb",
["crate_graph.lua"] = "30d01abc92dff63ace83a5d1697d2073",
["debuggables.lua"] = "6548c5c600f14c9dc3d10e87983f6fb4",
["diagnostic.lua"] = "55160b50ac49bcab96e15176fc5c7dde",
["expand_macro.lua"] = "0a5991437c93aa39ace91d31dfd5d041",
["code_action_group.lua"] = "4d2aee0d4d35a240b1c9d602695ed87e",
["crate_graph.lua"] = "41d7ba76e788d984278f59d6c73f1dbd",
["debuggables.lua"] = "f67f35eb3774672912e785c88cd91d48",
["diagnostic.lua"] = "b37ce82f62b9c0ddc4646147d66765a0",
["expand_macro.lua"] = "8c3785e8b5958081f4bec175d360ebb5",
["external_docs.lua"] = "1d2fa5d88ea197ad9976c23b0ff70763",
["fly_check.lua"] = "3f7b89700bd8f98fd5ab0ec02cce1cdd",
["fly_check.lua"] = "4ff335c2cc84d301b247e85110482311",
["hover_range.lua"] = "68828cfd0c465bbe0915996795ff7b92",
["init.lua"] = "0f99af7dabcd1ad961de545363e0f658",
["init.lua"] = "b637c5c02f9c61c674e01c3eb599bb5d",
["join_lines.lua"] = "f31a68f1ddac01b926d58ccd249bc03d",
["move_item.lua"] = "f05118ba148e66c1e92882141e68343f",
["open_cargo_toml.lua"] = "2368251db4ce52659693acc8eee15b74",
["parent_module.lua"] = "c274b7357e35825f75802dc96e609992",
["parent_module.lua"] = "a607e6c3f3871ed233704a2ba79c5ddc",
["rebuild_proc_macros.lua"] = "6113336c3b82042f60c54446e6c5a887",
["rustc_unpretty.lua"] = "fafde14d3d482667cecce2981444cad2",
["rustc_unpretty.lua"] = "ca233f8271917c20b5265a3161708b33",
["ssr.lua"] = "1c936709630f09b2a81d22452d3e3fa2",
["syntax_tree.lua"] = "c28fd8b22608e3f7bd3bdbb2e10c1617",
["view_ir.lua"] = "12eadc00a2ca1005bcbeda4fa8fc80a0",
["view_ir.lua"] = "97c8467240eb473cb9fc1a0bfc6674ef",
["workspace_refresh.lua"] = "083b2d70533d0f417b65d2b7866f531b",
["workspace_symbol.lua"] = "69bdc6d1255f7eb586ea8e350b840b85"
},
["compat.lua"] = "fedaef1aeaceaf086116ed62b423d0a3",
config = {
["check.lua"] = "55ddc99999546e6951cd2641cc997af2",
["init.lua"] = "4f8a4eb148571862d1439263f18c7cee",
["internal.lua"] = "854115363fcfc13e65098150b873a8ff",
["check.lua"] = "8c87e8208f5b8fa2e5799531b4b88efa",
["init.lua"] = "d9f55e37992cc4be0fa491927382c1df",
["internal.lua"] = "6d452c01acd0e591b1943c949be310d7",
["json.lua"] = "a8c7caf443ad9ce1193726aec053cc8d",
["server.lua"] = "a58c53c1333c5d050d97cf3e2bf82d99"
["server.lua"] = "412839511a5dbc58672df8b182ce7e98"
},
["dap.lua"] = "e39cbe01d5d7c03d585e7448d24ceab7",
["dap.lua"] = "44957dcdc4b2055c8aeaa94c0f833a01",
executors = {
["background.lua"] = "ae1c76a5c2f73e9c58456f580b7552b7",
["init.lua"] = "a443891fc3b974db6787502179d85c19",
["meta.lua"] = "99cae6c6b77725710ec2fc7d86bff665",
["neotest.lua"] = "64a17e71f15a1741f0e7f835472f26e3",
["quickfix.lua"] = "b1ea55a261b8623e73c2fd6aed278fd3",
["termopen.lua"] = "4a225919ab4e1ad67fc591a9947d86e9",
["toggleterm.lua"] = "221616f53cc50124694fcc1b0f1c92a2",
["vimux.lua"] = "24d3f692083ca86f0926e7aa4722c0fe"
["background.lua"] = "93264d91d4f1e40b2ac914b2155544d5",
["init.lua"] = "e0363361b74cbfdc0171bcab526b3fa2",
["meta.lua"] = "c508069ea13f5b6dee89bfbc3baf5cca",
["neotest.lua"] = "aaf98a780d535fc17506c4548ee1ac35",
["quickfix.lua"] = "75bdebff2926554ed1e60fa35ab8b675",
["termopen.lua"] = "394bfe73772bf3a901479e2f0813e265",
["toggleterm.lua"] = "ef28fd456e9350e4250746899a6ae9ee",
["vimux.lua"] = "a26ff98b8b3f0bff6a48090ac3fcf606"
},
["health.lua"] = "126952700269c9ab976f29f59604c5da",
["hover_actions.lua"] = "d0842822fa99c55b4cc5a65eae968ff2",
["init.lua"] = "a48de2e7e937208adc6781a5ea35ec88",
["lsp.lua"] = "5e8af804d16be73193df6067141bdf9f",
["health.lua"] = "d739674bff96b05c82d00538a033aca2",
["hover_actions.lua"] = "47721a479d52ff6cdc5afa76dcb36907",
["init.lua"] = "cc66a50c1f863f59cf1ec703687f3336",
["lsp.lua"] = "fa2f869c3f92b607d62fae44cec51137",
neotest = {
["init.lua"] = "ec54c5df5002742877ec6c925b273b2d",
["trans.lua"] = "1f79320bca0c81d91673543dd7ad4984"
["init.lua"] = "33b7a7be4dd23ee95cda1a170d4d0987",
["parser.lua"] = "32b5c6bacd357015fb5167632bb82f7a",
["trans.lua"] = "61e2e162521d1c47f077a29a8e058059"
},
["os.lua"] = "4c8caca1afb6a8e7862300b4dcc29f09",
["overrides.lua"] = "177b171bfb8c16c19326d6402b94a535",
["runnables.lua"] = "d458cb318b2cd900e178930d3b14f224",
["rust_analyzer.lua"] = "aa3bce32849886001dc2cb38a4ff951e",
["server_status.lua"] = "25017ef9b15fadd713574c897e242970",
["shell.lua"] = "561e4be6d5ba43f93a00ad5e6169e0eb",
["os.lua"] = "7a8abad874b58678039c73b3797328e7",
["overrides.lua"] = "bccbf0314c999a8f51cbdf655651d48c",
["runnables.lua"] = "fa001d0825d5a641649540f37d5d50dc",
["rust_analyzer.lua"] = "68f0a270cb2de0ae86b91b0a10eec6c9",
["server_status.lua"] = "4dade02d4facc6b3ed59a0d117ce3710",
["shell.lua"] = "2a59375b5b9f9971573253c33a392b63",
["test.lua"] = "e436ae539217729f46a1d556974e1100",
types = {
["internal.lua"] = "95d9ff5763390a3efae83cc27dbef452"
@ -74,5 +74,5 @@ rock_manifest = {
["ui.lua"] = "185cbb4ef9b15b4feb6699fcbd5d4435"
}
},
["rustaceanvim-4.25.1-1.rockspec"] = "fc780a2aa2e2df3fdb088697523f426f"
["rustaceanvim-5.2.0-1.rockspec"] = "6551a7b17c39e7a27abb40d620829019"
}