Skip to content

Bug: :FzfLua history hangs, :bro ol does not #2793

Description

@savchenko

RTFM Checklist

  • I have searched exisiting issues / discussions
  • I have read the Wiki including the Advanced section
  • I have read man fzf / I am well versed in shell fzf

Operating system

Linux

Shell

Bash

Neovim version (nvim --version)

NVIM v0.11.7

Fzf version (fzf --version)

0.67.0 (2ab923f3)

Output of :lua print(os.getenv('FZF_DEFAULT_OPTS'))

nil

Is the problem reproducible with mini.sh?

  • My issue is reproducible with mini.sh
  • My issue IS NOT reproducible with mini.sh
  • I have not tested with mini.sh (not relevant, requires LSP, Windows, etc)

Fzf-lua configuration

return {
    "https://github.com/ibhagwan/fzf-lua",
    lazy = false,
    config = function()
        _G.rendered = false
        local fzf = require("fzf-lua")
        local actions = fzf.actions

        local win_opts = function() -- {{{
            local bufs_fn_len = {}
            local max_len = 1
            for _, buf_nr in ipairs(vim.api.nvim_list_bufs()) do
                if vim.api.nvim_buf_is_valid(buf_nr) then
                    local buf_listed = vim.api.nvim_get_option_value('buflisted', { buf = buf_nr })
                    local buf_nm = vim.api.nvim_buf_get_name(buf_nr)
                    buf_nm = vim.fn.expand(buf_nm)
                    buf_nm = vim.fn.fnamemodify(buf_nm, ":.")
                    if buf_listed then
                        if buf_nm ~= '' then
                            buf_len = string.len(buf_nm)
                            table.insert(bufs_fn_len, buf_len)
                        end
                    end
                end
            end
            for _, len in ipairs(bufs_fn_len) do
                max_len = math.max(max_len, len)
            end
            return {
                width = max_len,
                height = #bufs_fn_len,
            }
        end -- }}}

        fzf.setup({

            actions = { -- {{{
                files = {
                    false,
                    ["enter"] = actions.file_switch_or_edit,
                },
            }, -- }}}

            tabs = { -- {{{
                header = false,
                keymap = function() -- autofocus current tab
                    local curtab = vim.fn.tabpagenr()
                    local pos = 1
                    for i, t in ipairs(vim.api.nvim_list_tabpages()) do
                        if i < curtab then pos = pos + 1 + #vim.api.nvim_tabpage_list_wins(t) end
                    end
                    return { fzf = { load = string.format("transform:echo 'pos(%d)'", pos) } }
                end,
                winopts = {
                    on_create = function()
                        local w = require('fzf-lua.utils').fzf_winobj()
                        local opts = win_opts()
                        w._o.winopts.width = opts.width + 20
                        w._o.winopts.height = opts.height + 2
                        w:redraw()
                    end,
                },
            }, -- }}}

            buffers = { -- {{{
                cwd_header = false,
                fzf_opts = { ["--delimiter"] = FzfLua.utils.nbsp, ["--with-nth"] = "-1.." },
                header = false,
                winopts = {
                    hide = true,
                    preview = {
                        hidden = true
                    },
                    on_close = function()
                        _G.rendered = false
                    end,
                    on_create = function()
                        local w = require('fzf-lua.utils').fzf_winobj()
                        local opts = win_opts()
                        w._o.winopts.width = opts.width + 18
                        w._o.winopts.height = opts.height + 4
                        w._o.winopts.hide = false
                        w:redraw()
                        _G.rendered = true
                    end,
                },
            }, -- }}}

            oldfiles = { -- {{{
                winopts = {
                    width = 0.5,
                    height = 0.1,
                    hide = true,
                    title = ' History ',
                    on_close = function()
                        _G.rendered = false
                    end,
                },
                actions = {
                    result = {
                        fn = function(idx)
                            if not _G.rendered then
                                local fzf_match_cnt = tonumber(unpack(idx))
                                local w = require('fzf-lua.utils').fzf_winobj()
                                w._o.winopts.width = 0.5
                                w._o.winopts.height = math.min(50, fzf_match_cnt + 3)
                                w._o.winopts.hide = false
                                w:redraw()
                                _G.rendered = true
                            end
                        end,
                        exec_silent = true,
                        field_index = '$FZF_MATCH_COUNT',
                    },
                },
            }, -- }}}

            files = { -- {{{
                cmd = "fdfind --no-ignore --follow --one-file-system --hidden --type f --type l --exclude .git --color=never || true",
                git_icons = false,
                cwd_header = false,
                cwd_prompt = true,
                winopts = {
                    fullscreen = true,
                    width = 0.5,
                    height = 0.1,
                    hide = true,
                    preview = {
                        hidden = true
                    },
                    on_close = function()
                        _G.rendered = false
                    end,
                },
                actions = {
                    ["alt-i"] = actions.toggle_ignore,
                    ["ctrl-g"] = actions.grep_lgrep,
                    result = {
                        fn = function(idx)
                            if not _G.rendered then
                                local fzf_match_cnt = tonumber(unpack(idx))
                                local w = require('fzf-lua.utils').fzf_winobj()
                                w._o.winopts.width = 0.5
                                w._o.winopts.height = math.min(50, fzf_match_cnt + 1)
                                w._o.winopts.hide = false
                                w:redraw()
                                _G.rendered = true
                            end
                        end,
                        exec_silent = true,
                        field_index = '$FZF_MATCH_COUNT',
                    },
                },
            }, -- }}}

            git = { -- {{{
                files = {
                    git_icons = false,
                    cwd_header = false,
                    cwd_prompt = true,
                    winopts = {
                        width = 0.5,
                        height = 0.1,
                        hide = true,
                        preview = {
                            hidden = true
                        },
                        on_close = function()
                            _G.rendered = false
                        end,
                    },
                    actions = {
                        result = {
                            fn = function(idx)
                                if not _G.rendered then
                                    local fzf_match_cnt = tonumber(unpack(idx))
                                    local w = require('fzf-lua.utils').fzf_winobj()
                                    w._o.winopts.width = 0.5
                                    w._o.winopts.height = math.min(50, fzf_match_cnt + 1)
                                    w._o.winopts.hide = false
                                    w:redraw()
                                    _G.rendered = true
                                end
                            end,
                            exec_silent = true,
                            field_index = '$FZF_MATCH_COUNT',
                        },
                    },
                },
            }, -- }}}

            grep = { -- {{{
                header = false,
                RIPGREP_CONFIG_PATH = vim.env.RIPGREP_CONFIG_PATH,
                fzf_opts = {
                    ["--with-nth"] = "{1} {4}",
                    ["--delimiter"] = ":",
                },
                actions = {
                    -- WARNING: In terminals, Ctrl-I is literally the same as Tab.
                    ["alt-i"] = actions.toggle_ignore,
                    ["ctrl-g"] = actions.grep_lgrep,
                    ['ctrl-q'] = actions.file_sel_to_qf,
                },
            }, -- }}}

            hls = { -- {{{
                preview_title = "Normal",
                title_flags = "CursorLineNr",
            }, -- }}}

            winopts = { -- {{{
                row = 0.5,
                col = 0.5,
                backdrop = 90,
                border = "solid",
                preview = {
                    border = "single",
                    hidden = true,
                    winopts = {
                        number = false,
                        relativenumber = false,
                        foldmethod = "manual",
                        foldenable = false,
                    },
                },
            }, -- }}}

            keymap = { -- {{{
                builtin = {
                    -- neovim `:tmap` mappings for the fzf win
                    false,
                    ["<M-Esc>"] = "hide", -- `:FzfLua resume` to continue
                    ["<F1>"] = "toggle-help",
                    ["<F11>"] = "toggle-fullscreen",
                    -- Only valid with the 'builtin' previewer
                    ["<C-r>"] = "toggle-preview-wrap",
                    ["<C-e>"] = "toggle-preview",
                    -- Rotate preview clockwise/counter-clockwise
                    ["<C-left>"] = "toggle-preview-ccw",
                    ["<C-right>"] = "toggle-preview-cw",
                    ["<S-PageDown>"] = "preview-page-down",
                    ["<S-PageUp>"] = "preview-page-up",
                    ["<S-down>"] = "preview-down",
                    ["<S-up>"] = "preview-up",
                },
            }, -- }}}

            fzf_opts = { -- {{{
                ["--gutter"] = ' ',
                ["--exact"] = true,
                ["--pointer"] = "",
                ["--marker"]="",
                ["--bind"] = "ctrl-backspace:backward-kill-word",
            }, -- }}}

            fzf_colors = function() -- {{{
                if _G.GetFzfColors then
                    return _G.GetFzfColors()
                end

                return {
                    false,
                    ["gutter"] = "-1",
                }
            end, -- }}}

            blines = { -- {{{
                winopts = {
                    treesitter = false,
                    preview = {
                        hidden = true
                    }
                },
                fzf_opts = {
                    ["--with-nth"] = "{4} {5}",
                    ["--nth"] = "1",
                },
            }, -- }}}

            lsp = { -- {{{
                symbols = {
                    symbol_style = 2, -- 2 for icon only
                    symbol_icons = LspIcons,
                }
            } -- }}}

        })

        vim.keymap.set(
            'n',
            '<leader>l',
            function() fzf.blines() end,
            { silent = true, noremap = true, desc = 'Buffer lines' }
        )

        vim.keymap.set(
            'n',
            '<leader>s',
            function() fzf.lsp_document_symbols() end,
            { silent = true, noremap = true, desc = 'Buffer symbols' }
        )

        vim.keymap.set(
            'n',
            '<leader><S-s>',
            function() fzf.lsp_live_workspace_symbols() end,
            { silent = true, noremap = true, desc = 'Project symbols' }
        )

        vim.keymap.set( -- "double grep"
            'n',
            '<C-S-g>',
            function() fzf.grep() end,
            { silent = true, noremap = true, desc = 'Grep' }
        )

        vim.keymap.set( -- "regular, ripgrep-powered grep"
            'n',
            '<C-g>',
            function() fzf.live_grep_native() end,
            { silent = true, noremap = true, desc = 'Grep' }
        )

        vim.keymap.set(
            'n',
            '<leader>ts',
            function() fzf.treesitter() end,
            { silent = true, noremap = true, desc = 'Treesitter' }
        )

        vim.keymap.set(
            'n',
            '<leader>\\',
            function() fzf.buffers() end,
            { silent = true, noremap = true, desc = 'Buffers' }
        )

        vim.keymap.set(
            'n',
            '<leader>i',
            function() fzf.oldfiles() end,
            { silent = true, noremap = true, desc = 'History' }
        )

        vim.keymap.set(
            'n',
            '<C-f>',
            function() fzf.files() end,
            { silent = true, noremap = true, desc = 'Files' }
        )

        vim.keymap.set(
            'n',
            '<C-S-f>',
            function() fzf.git_files() end,
            { silent = true, noremap = true, desc = 'Git files' }
        )

        vim.keymap.set(
            'n',
            '<C-A-f>',
            function() fzf.files({ cwd = vim.fn.expand('%:p:h') }) end,
            { silent = true, noremap = true, desc = 'Files in the buffer\'s folder' }
        )

        fzf.register_ui_select()
    end
}

Describe the bug / steps to reproduce

Since ~ recently, :FzfLua history either hangs or takes seconds (at times 10+) to render the list of items. When it hangs - nVim as the whole is not responding (e.g. <C-w>c does nothing).

Of note, with mini.sh the history command shows only 2 elements, so it's not really a fair comparison.

Happy to debug further.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions