Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: Override vim.ui.select with a nui menu (very basic implementation shown) #798

Open
1 task done
theKnightsOfRohan opened this issue May 13, 2024 · 1 comment
Open
1 task done
Labels
enhancement New feature or request

Comments

@theKnightsOfRohan
Copy link

Did you check the docs?

  • 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.

@theKnightsOfRohan theKnightsOfRohan added the enhancement New feature or request label May 13, 2024
@igorlfs
Copy link

igorlfs commented Jun 12, 2024

By the way, someone made a PR last year, but they deleted their fork. You might also wanna look into dressing.nvim, which is what most people use AFAIK.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants