diff --git a/CHANGELOG.md b/CHANGELOG.md
index 79d483fb..92eadb5a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
+### Added
+
+- LSP: Option to fall back to `vim.ui.select` if there
+ are no code action groups when running `:RustLsp codeAction`.
+
### Fixed
- LSP: Focus lost when secondary float opens on `:RustLsp codeAction` [[#169](https://github.com/mrcjkb/rustaceanvim/issues/169)].
diff --git a/README.md b/README.md
index 7b1d712e..68841098 100644
--- a/README.md
+++ b/README.md
@@ -245,6 +245,30 @@ vim.keymap.set(
```
+
+
+ Grouped code actions
+
+
+ Sometimes, rust-analyzer groups code actions by category,
+ which is not supported by Neovim's built-in `vim.lsp.buf.codeAction`.
+ This plugin provides a command with a UI that does:
+
+ ```vimscript
+ :RustLsp codeAction
+ ```
+ ```lua
+ vim.cmd.RustLsp('codeAction')
+ ```
+
+ If you set the option `vim.g.rustaceanvim.tools.code_actions.ui_select_fallback`
+ to `true` (defaults to `false`), it will fall back to `vim.ui.select`
+ if there are no grouped code actions.
+
+![](https://github.com/mrcjkb/rustaceanvim/assets/12857160/866d3cb1-8e56-4380-8c03-812386441f47)
+
+
+
Hover Actions
diff --git a/doc/rustaceanvim.txt b/doc/rustaceanvim.txt
index 25a1cdef..e9ce4042 100644
--- a/doc/rustaceanvim.txt
+++ b/doc/rustaceanvim.txt
@@ -109,6 +109,7 @@ RustaceanToolsOpts *RustaceanToolsOpts*
{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?} (table) 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
@@ -120,6 +121,12 @@ RustaceanHoverActionsOpts *RustaceanHoverActionsOpts*
{replace_builtin_hover?} (boolean) Whether to replace Neovim's built-in `vim.lsp.buf.hover` with hover actions. Default: `true`
+RustaceanCodeActionOpts *RustaceanCodeActionOpts*
+
+ Fields: ~
+ {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*
Type: ~
diff --git a/lua/rustaceanvim/commands/code_action_group.lua b/lua/rustaceanvim/commands/code_action_group.lua
index 8b4c02ca..47165e54 100644
--- a/lua/rustaceanvim/commands/code_action_group.lua
+++ b/lua/rustaceanvim/commands/code_action_group.lua
@@ -1,4 +1,5 @@
local ui = require('rustaceanvim.ui')
+local config = require('rustaceanvim.config.internal')
local M = {}
---@class RACodeAction
@@ -147,6 +148,22 @@ local function on_code_action_results(results, ctx)
table.insert(M.state.actions.ungrouped, value)
end
end
+
+ if #M.state.actions.grouped == 0 and config.tools.code_actions.ui_select_fallback then
+ ---@param item action_tuple
+ local function format_item(item)
+ local title = item[2].title:gsub('\r\n', '\\r\\n')
+ return title:gsub('\n', '\\n')
+ end
+ local select_opts = {
+ prompt = 'Code actions:',
+ kind = 'codeaction',
+ format_item = format_item,
+ }
+ vim.ui.select(M.state.actions.ungrouped, select_opts, M.on_user_choice)
+ return
+ end
+
M.state.primary.bufnr = vim.api.nvim_create_buf(false, true)
M.state.primary.winnr = vim.api.nvim_open_win(M.state.primary.bufnr, true, {
relative = 'cursor',
diff --git a/lua/rustaceanvim/config/init.lua b/lua/rustaceanvim/config/init.lua
index b7cfc097..91e36cde 100644
--- a/lua/rustaceanvim/config/init.lua
+++ b/lua/rustaceanvim/config/init.lua
@@ -59,6 +59,7 @@ vim.g.rustaceanvim = vim.g.rustaceanvim
---@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? table 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
@@ -66,6 +67,9 @@ vim.g.rustaceanvim = vim.g.rustaceanvim
---@class RustaceanHoverActionsOpts
---@field replace_builtin_hover? boolean Whether to replace Neovim's built-in `vim.lsp.buf.hover` with hover actions. Default: `true`
+---@class RustaceanCodeActionOpts
+---@field ui_select_fallback? boolean Whether to fall back to `vim.ui.select` if there are no grouped code actions. Default: `false`
+
---@alias lsp_server_health_status 'ok' | 'warning' | 'error'
---@class RustAnalyzerInitializedStatus
diff --git a/lua/rustaceanvim/config/internal.lua b/lua/rustaceanvim/config/internal.lua
index 76d101d9..883f9aa1 100644
--- a/lua/rustaceanvim/config/internal.lua
+++ b/lua/rustaceanvim/config/internal.lua
@@ -53,11 +53,16 @@ local RustaceanDefaultConfig = {
hover_actions = {
--- whether to replace Neovim's built-in `vim.lsp.buf.hover`.
- --- default: true
---@type boolean
replace_builtin_hover = true,
},
+ code_actions = {
+ --- whether to fall back to `vim.ui.select` if there are no grouped code actions
+ ---@type boolean
+ ui_select_fallback = false,
+ },
+
--- options same as lsp hover
---@see vim.lsp.util.open_floating_preview
---@type table Options applied to floating windows.
@@ -331,6 +336,7 @@ local RustaceanDefaultConfig = {
return dap_config
end,
},
+ -- debug info
was_g_rustaceanvim_sourced = vim.g.rustaceanvim ~= nil,
}
local rustaceanvim = vim.g.rustaceanvim or {}