noice.nvim
noice.nvim copied to clipboard
feature: Override vim.ui.select with a nui menu (very basic implementation shown)
Did you check the docs?
- [X] I have read all the noice.nvim docs
Is your feature request related to a problem? Please describe.
Whether using notify or mini as the message mechanism, it's a little disconcerting to have the selection dialog appear in the same place as your notifications, and have no visual indication of escaping out/selecting an item. I've tried doing this myself, and it works okay, but I think integrating it into noice as a preset or something would be "noice". 🙃
Describe the solution you'd like
Since the nui menu is pretty robust, I think just the ability to create a menu at the cursor or at an arbitrary position on the screen whenever vim.ui.select()
is called would be enough. The reason I care about cursor position is for vim.lsp.buf.code_action()
, which I use a lot, so that eye position is maintained.
Describe alternatives you've considered
I guess custom creating a menu from scratch, or a special input buffer would be an alternative? But the nui menu seems like a pretty 1:1 layer between inputs, so I don't see anything that would be too much better. I guess you could make the selection menu part of the configuration options if there are multiple ways to implement it.
Additional context
Here's a very basic 1-afternoon implementation of what I mean (note that I am no lua whiz):
return {
"MunifTanjim/nui.nvim",
config = function()
local Menu = require("nui.menu")
vim.ui.select = function(items, opts, on_choice)
vim.validate({
items = { items, 'table', false },
on_choice = { on_choice, 'function', false },
})
opts = opts or {}
local format_item = opts.format_item or tostring
Menu({
relative = "cursor",
position = {
row = 2,
col = 0,
},
size = {
width = 40,
},
border = {
style = "rounded",
text = {
top = opts.prompt or "Select an item",
top_align = "center",
},
},
}, {
lines = (function()
---@type NuiTree.Node[]
local selections = {}
for _, item in ipairs(items) do
if type(item) == "string" then
table.insert(selections, Menu.item(item))
elseif type(item) == "table" then
table.insert(selections, Menu.item(format_item(item), item))
end
end
return selections
end)(),
on_close = function()
print("Closed")
end,
on_submit = function(selected)
on_choice(selected)
end,
}):mount()
end
vim.keymap.set("n", "<leader><leader>", function()
vim.ui.select({ 'One', 'Two', 'Three' }, {}, function(selected)
print("Selected: " .. selected)
end)
end)
end,
}
This implementation works with both vim.lsp.buf.code_action()
and the string example keymapped below, which should mean that it works with both the table and string versions of nui's Menu
.