fzf-lua Neovim Plugin

repository·main·Indexed 26 days ago

https://github.com/ibhagwan/fzf-lua

A Neovim plugin that integrates the fzf or skim fuzzy finder with internal Neovim features and external utilities like ripgrep and fd. It provides high-performance fuzzy searching for files, buffers, LSP symbols, diagnostics, and Git/Jujutsu VCS operations. Features include preconfigured UI profiles (such as telescope, fzf-native, and ivy), a global picker for a VS-Code-like experience, and the ability to register as the Neovim UI selector for vim.ui.select.

Tokens
14.5K
Snippets
33
Records
75
Agent score
83%

What's inside fzf-lua

  1. Quickstart testing fzf-lua

    main

    You can quickly test fzf-lua in a sandbox environment without modifying your Neovim configuration by running the following shell command. This will use default keybindings for various pickers.

    sh -c "$(curl -s https://raw.githubusercontent.com/ibhagwan/fzf-lua/main/scripts/mini.sh)"
  2. Customize picker options inline

    main
    You can experiment with different options without modifying the global configuration by passing them as inline parameters to the function calls. This works for both the Lua API and the VimL command interface.
  3. Use Global Options with Fzf-Lua

    main

    Global options apply to all fzf-lua commands and are not picker-specific. When using the :FzfLua user command, omit the globals. prefix. When using the Lua API, you can pass them as a nested table or use the recursive option format.

    For example, to position a floating window at the top row using winopts.row:

    Via Command: :FzfLua files winopts.row=1

    Via Lua API:

    require("fzf-lua").files({ winopts = { row = 1 } })
    -- Or using recursive format
    require("fzf-lua").files({ ["winopts.row"] = 1 })
    require("fzf-lua").files({ winopts = { row = 1 } })
    -- Using the recursive option format
    require("fzf-lua").files({ ["winopts.row"] = 1 })
  4. Configure fzf-lua option precedence

    main

    Options in fzf-lua can be applied at four different levels of granularity. The most specific setting takes precedence:

    1. Command call options: Passed directly to a picker function or via the :FzfLua command (highest precedence).
    2. Provider-specific setup options: Defined in setup() for a specific picker (e.g., files = { ... }).
    3. Provider-defaults setup options: Defined in setup() via the defaults key, applying to all pickers unless overridden by provider-specific settings.
    4. Global setup options: Defined in setup() and applying to all interfaces (lowest precedence).

    Example of setting a global window position:

    require("fzf-lua").setup({ winopts = { row = 1, col = 0 } })
  5. Configure fzf-lua via setup()

    main

    Use require("fzf-lua").setup() to configure global settings and specific picker options. You can pass tables for various configuration sections like winopts, keymap, actions, fzf_opts, fzf_colors, hls, and previewers. Many options can also be passed as functions that return an options table.

    Common global options include:

    • fzf_bin: Specify a custom fzf binary (e.g., 'sk' for skim).
    • file_icon_padding: Add padding for terminal icon rendering.
    • help_open_win: Override the function used to open the help window (defaults to vim.api.nvim_open_win).
    require("fzf-lua").setup {
      winopts = { ... },     -- UI Options
      keymap = { ... },      -- Neovim keymaps / fzf binds
      actions = { ... },     -- Fzf "accept" binds
      fzf_opts = { ... },    -- Fzf CLI flags
      fzf_colors = { ... },  -- Fzf `--color` specification
      hls = { ... },         -- Highlights
      previewers = { ... },  -- Previewers options
      -- SPECIFIC COMMAND/PICKER OPTIONS
      files = { ... },
    }
  6. Configure fzf-lua using Profiles

    main
    Fzf-lua provides preconfigured profiles to avoid manual customization. You can apply a profile during setup by passing the profile name as a string at the first index of the table. You can also use a profile as a baseline and add custom options, or combine multiple profiles by passing a table of strings.
  7. Activate FzfLua profiles via setup()

    main

    You can activate preconfigured profiles by passing the profile name as a string at the first index of the table passed to the setup function. Calling setup multiple times allows for "live" switching of profiles.

    To use a specific profile, pass its name as the first element in the configuration table.

    require("fzf-lua").setup({ "fzf-native" })
  8. Install fzf-lua using lazy.nvim

    main

    To install fzf-lua with lazy.nvim, use the following configuration. You can optionally include nvim-web-devicons or mini.icons for icon support.

    {
      "ibhagwan/fzf-lua",
      -- optional for icon support
      dependencies = { "nvim-tree/nvim-web-devicons" },
      -- or if using mini.icons/mini.nvim
      -- dependencies = { "nvim-mini/mini.icons" },
      ---@module "fzf-lua"
      ---@type fzf-lua.Config|{}
      ---@diagnostic disable: missing-fields
      opts = {}
      ---@diagnostic enable: missing-fields
    }
  9. Verify recommended fzf version for live_grep

    main

    To ensure live_grep and live_grep_native function correctly with special characters, ensure your fzf binary is version 0.52.1 or higher.

    Avoid the following versions:

    • Versions <= 0.50: Will have issues with live_grep_native.
    • Versions 0.51.0 and 0.52.0: Should be avoided due to known issues.
  10. Configure the tabs picker

    main

    Customize the tabs() picker using the tabs configuration table. Key options include:

    • prompt: The prompt string displayed.
    • tab_title: The title for each tab.
    • tab_marker: The marker used to identify the current tab.
    • locate: If true, positions the cursor at the current window.
    • file_icons / color_icons: Control icon display and coloring.
    • actions: Define custom keybindings. For example, mapping enter to actions.buf_switch or ctrl-x to actions.buf_del with reload = true to prevent window flashing.
    tabs = {
      prompt            = 'Tabs❯ ',
      tab_title         = "Tab",
      tab_marker        = "<<",
      locate            = true,
      file_icons        = true,
      color_icons       = true,
      actions = {
        ["enter"]       = actions.buf_switch,
        ["ctrl-x"]      = { fn = actions.buf_del, reload = true },
      },
      fzf_opts = {
        ["--delimiter"] = "[\\):]",
        ["--with-nth"]  = '2..',
      },
    }
  11. Configure fzf colors (fzf_colors)

    main

    The fzf_colors table controls the terminal colorscheme for fzf.

    Options:

    • true: Automatically generate a colorscheme from Neovim's current colorscheme.
    • Custom Table: Define specific colors for fzf elements.

    Custom Color Syntax:

    • If the value is a string, it is passed raw (e.g., ["fg"] = "underline" becomes --color fg:underline).
    • If the value is a table, it follows this convention: [1] is the attribute (e.g., "fg", "bg"), [2] is the Neovim highlight group(s) (string or table), and [3+] are additional raw arguments.

    Example of a fully loaded color option: ["fg"] = { "fg", { "NonExistentHl", "Comment" }, "underline", "bold" } results in --color fg:#010101:underline:bold (assuming Comment.fg is #010101).

    fzf_colors = {
          true,   -- inherit fzf colors that aren't specified below
          ["fg"]          = { "fg", "CursorLine" },
          ["bg"]          = { "bg", "Normal" },
          ["hl"]          = { "fg", "Comment" },
          ["fg+"]         = { "fg", "Normal", "underline" },
          ["bg+"]         = { "bg", { "CursorLine", "Normal" } },
          ["hl+"]         = { "fg", "Statement" },
          ["info"]        = { "fg", "PreProc" },
          ["prompt"]      = { "fg", "Conditional" },
          ["pointer"]     = { "fg", "Exception" },
          ["marker"]      = { "fg", "Keyword" },
          ["spinner"]     = { "fg", "Label" },
          ["header"]      = { "fg", "Comment" },
          ["gutter"]      = "-1",
      }
  12. Configure the git picker

    main

    The git configuration provides specialized pickers for Git-related tasks. It is divided into several sub-pickers:

    • files: Search for files tracked by Git.
    • status: View and interact with the Git status (stage/unstage/reset).
    • diff: View changes between commits.
    • hunks: View individual hunks in a diff.
    • commits: Browse and checkout commits.
    • bcommits: Browse buffer history across renames.
    • blame: View git blame information.
    • branches: List and switch between branches.
    • tags: List and checkout tags.
    • stash: Manage Git stashes.

    You can customize commands (cmd), previews (preview), and keybindings (actions) for each sub-picker.

    git = {
      files = {
        prompt        = 'GitFiles❯ ',
        cmd           = 'git ls-files --exclude-standard',
      },
      status = {
        prompt        = 'GitStatus❯ ',
        cmd           = "git -c color.status=false --no-optional-locks status --porcelain=v1 -u",
        actions = {
          ["right"]  = { fn = actions.git_unstage, reload = true },
          ["left"]   = { fn = actions.git_stage, reload = true },
          ["ctrl-x"] = { fn = actions.git_reset, reload = true },
        },
      },
      branches = {
        prompt   = 'Branches❯ ',
        cmd      = "git branch --all --color",
        actions  = {
          ["enter"]   = actions.git_switch,
          ["ctrl-x"]  = { fn = actions.git_branch_del, reload = true },
          ["ctrl-a"]  = { fn = actions.git_branch_add, field_index = "{q}", reload = true },
        },
      },
    }