stevearc / dressing.nvim

Neovim plugin to improve the default vim.ui interfaces
MIT License
1.69k stars 32 forks source link

vim.ui.input doesn't trigger a prompt after telescope picker #115

Closed desdic closed 10 months ago

desdic commented 10 months ago

Describe the bug

If you use vim.ui.input just after a telescope picker it just closes. It never prompts and even when setting the default value its just nil. If I disable dressing vim.ui.input prompts and prints the value I entered.

System information

{ "stevearc/dressing.nvim", opts = {} },

To Reproduce

Steps to reproduce the behavior:

  1. Use vim.ui.input from dressing after a telescope picker

The example is a bit on the large side but I wanted to show it in an reproducable way. When starting with NVIM_APPNAME="dressing" nvim and pressing telescope starts, pick any and press enter and you'll the se bug or .. its visible via messages

local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
    vim.fn.system({
        "git",
        "clone",
        "--filter=blob:none",
        "https://github.com/folke/lazy.nvim.git",
        "--branch=stable", -- latest stable release
        lazypath,
    })
end
vim.opt.rtp:prepend(lazypath)

require("lazy").setup({
    {
        { "stevearc/dressing.nvim", opts = {} },
        "nvim-lua/plenary.nvim",
        {
            "nvim-telescope/telescope.nvim",
            keys = {
                {
                    "<CR>",
                    function()
                        local finders = require("telescope.finders")
                        local action_state = require("telescope.actions.state")
                        local actions = require("telescope.actions")
                        local sorters = require("telescope.sorters")
                        local pickers = require("telescope.pickers")
                        local entry_display = require("telescope.pickers.entry_display")

                        local generate_new_finder_registers = function()
                            local displayer =
                                entry_display.create({
                                    separator = " ",
                                    hl_chars = { ["["] = "TelescopeBorder", ["]"] = "TelescopeBorder" },
                                    items = {
                                        { width = 4 },
                                        { remaining = true },
                                    },
                                })

                            local function make_display(entry)
                                local content = entry.value.value
                                content = type(content) == "string" and content:gsub("\n", "\\n")
                                    or content

                                return displayer({
                                    { "[" .. entry.value.label .. "]", "TelescopeResultsNumber" },
                                    content,
                                })
                            end
                            return finders.new_table({
                                results = { { label = "A", value = "A" }, { label = "B", value = "B" } },
                                entry_maker = function(entry)
                                    local content = entry.value
                                    content = type(content) == "string" and content:gsub("\n", "\\n")
                                        or content

                                    local table = {
                                        value = entry,
                                        ordinal = entry.label,
                                        display = make_display,
                                        content = content,
                                    }
                                    return table
                                end,
                            })
                        end

                        pickers
                            .new({}, {
                                prompt_title = "Choose register",
                                finder = generate_new_finder_registers(),
                                sorter = sorters.get_generic_fuzzy_sorter(),
                                attach_mappings = function(_, map)
                                    map(
                                        "i",
                                        "<CR>",
                                        function(newprompt_bufnr)
                                            local _ =
                                                action_state.get_selected_entry()

                                            -- input is always nil and the prompt is never trigger
                                            vim.ui.input({ prompt = "Enter description: ", default = "testing" }, function(input)
                                                print(vim.inspect(input))
                                            end)

                                            actions.close(newprompt_bufnr)
                                        end
                                    )
                                    return true
                                end,
                            })
                            :find()
                    end,
                    desc = "trigger"
                }
            }
        },
    },
})
stevearc commented 10 months ago

vim.ui.input opens a floating window. actions.close closes the telescope window, and then sets the focus back to the original window you were in before opening telescope. Dressing is configured to automatically cancel the input if your focus leaves the input window. You can fix this by reordering the calls.

actions.close(newprompt_bufnr)

-- input is always nil and the prompt is never trigger
vim.ui.input({ prompt = "Enter description: ", default = "testing" }, function(input)
  print(vim.inspect(input))
end)
desdic commented 10 months ago

ah oki .. but I really wanted the same behavior as the default so the telescope would stay in the background while typing the description. This makes it hard for plugin developers to use vim.ui.input if the behavior changes because the dev has no control if it works for the enduser or not.

stevearc commented 10 months ago

If you want it to close after input, put the close action after the input completes

-- input is always nil and the prompt is never trigger
vim.ui.input({ prompt = "Enter description: ", default = "testing" }, function(input)
  print(vim.inspect(input))
  actions.close(newprompt_bufnr)
end)

vim.ui.input is designed to be asynchronous. The default implementation uses vim.fn.input, which is synchronous, but this is a side effect and not part of the intended design.