Skip to content

Configuration Recipes

Marrek Nožka edited this page Apr 3, 2024 · 53 revisions

A place for the community to share configurations and custom pickers that dont fit into core or an extension

Table Of Contents


Mappings

Mapping <Esc> to quit in insert mode

If you'd prefer Telescope not to enter a normal-like mode when hitting escape (and instead exiting), you can map <Esc> to do so via:

local actions = require("telescope.actions")
require("telescope").setup{
  defaults = {
    mappings = {
      i = {
        ["<esc>"] = actions.close
      },
    },
  }
}

Mapping <C-u> to clear prompt

If you'd prefer Telescope to clear the prompt on <C-u> rather than scroll the previewer add the following to your config:

local actions = require("telescope.actions")
require("telescope").setup{
  defaults = {
    mappings = {
      i = {
        ["<C-u>"] = false
      },
    },
  }
}

Mapping <C-d> to delete buffer

If you would like to delete a buffer from picker without closing telescope. For more information, you can check Pull Request #828.

local actions = require "telescope.actions"
require("telescope").setup {
  pickers = {
    buffers = {
      mappings = {
        i = {
          ["<c-d>"] = actions.delete_buffer + actions.move_to_top,
        }
      }
    }
  }
}

Add mapping to toggle the preview

If you want to add a mapping to toggle the previewer (when applicable), you can map it using the toggle_preview action. For example, you can map <M-p> to do so via:

local action_layout = require("telescope.actions.layout")
require("telescope").setup{
  defaults = {
    mappings = {
      n = {
        ["<M-p>"] = action_layout.toggle_preview
      },
      i = {
        ["<M-p>"] = action_layout.toggle_preview
      },
    },
  }
}

Mapping <C-s>/<C-a> to cycle previewer for git commits to show full message

local telescope = require("telescope")
local actions = require("telescope.actions")

telescope.setup({
  defaults = {
    mappings = {
      i = {
        ["<C-s>"] = actions.cycle_previewers_next,
        ["<C-a>"] = actions.cycle_previewers_prev,
      },
    },
  },
})

Layouts

Fused Layout

Requirements:

Horizontal Fused Layout
See Vertical and Minimal Fused Layout Vertical Fused Layout Minimal Fused Layout
local Layout = require("nui.layout")
local Popup = require("nui.popup")

local telescope = require("telescope")
local TSLayout = require("telescope.pickers.layout")

local function make_popup(options)
  local popup = Popup(options)
  function popup.border:change_title(title)
    popup.border.set_text(popup.border, "top", title)
  end
  return TSLayout.Window(popup)
end

telescope.setup({
  defaults = {
    layout_strategy = "flex",
    layout_config = {
      horizontal = {
        size = {
          width = "90%",
          height = "60%",
        },
      },
      vertical = {
        size = {
          width = "90%",
          height = "90%",
        },
      },
    },
    create_layout = function(picker)
      local border = {
        results = {
          top_left = "",
          top = "",
          top_right = "",
          right = "",
          bottom_right = "",
          bottom = "",
          bottom_left = "",
          left = "",
        },
        results_patch = {
          minimal = {
            top_left = "",
            top_right = "",
          },
          horizontal = {
            top_left = "",
            top_right = "",
          },
          vertical = {
            top_left = "",
            top_right = "",
          },
        },
        prompt = {
          top_left = "",
          top = "",
          top_right = "",
          right = "",
          bottom_right = "",
          bottom = "",
          bottom_left = "",
          left = "",
        },
        prompt_patch = {
          minimal = {
            bottom_right = "",
          },
          horizontal = {
            bottom_right = "",
          },
          vertical = {
            bottom_right = "",
          },
        },
        preview = {
          top_left = "",
          top = "",
          top_right = "",
          right = "",
          bottom_right = "",
          bottom = "",
          bottom_left = "",
          left = "",
        },
        preview_patch = {
          minimal = {},
          horizontal = {
            bottom = "",
            bottom_left = "",
            bottom_right = "",
            left = "",
            top_left = "",
          },
          vertical = {
            bottom = "",
            bottom_left = "",
            bottom_right = "",
            left = "",
            top_left = "",
          },
        },
      }

      local results = make_popup({
        focusable = false,
        border = {
          style = border.results,
          text = {
            top = picker.results_title,
            top_align = "center",
          },
        },
        win_options = {
          winhighlight = "Normal:Normal",
        },
      })

      local prompt = make_popup({
        enter = true,
        border = {
          style = border.prompt,
          text = {
            top = picker.prompt_title,
            top_align = "center",
          },
        },
        win_options = {
          winhighlight = "Normal:Normal",
        },
      })

      local preview = make_popup({
        focusable = false,
        border = {
          style = border.preview,
          text = {
            top = picker.preview_title,
            top_align = "center",
          },
        },
      })

      local box_by_kind = {
        vertical = Layout.Box({
          Layout.Box(preview, { grow = 1 }),
          Layout.Box(results, { grow = 1 }),
          Layout.Box(prompt, { size = 3 }),
        }, { dir = "col" }),
        horizontal = Layout.Box({
          Layout.Box({
            Layout.Box(results, { grow = 1 }),
            Layout.Box(prompt, { size = 3 }),
          }, { dir = "col", size = "50%" }),
          Layout.Box(preview, { size = "50%" }),
        }, { dir = "row" }),
        minimal = Layout.Box({
          Layout.Box(results, { grow = 1 }),
          Layout.Box(prompt, { size = 3 }),
        }, { dir = "col" }),
      }

      local function get_box()
        local strategy = picker.layout_strategy
        if strategy == "vertical" or strategy == "horizontal" then
          return box_by_kind[strategy], strategy
        end

        local height, width = vim.o.lines, vim.o.columns
        local box_kind = "horizontal"
        if width < 100 then
          box_kind = "vertical"
          if height < 40 then
            box_kind = "minimal"
          end
        end
        return box_by_kind[box_kind], box_kind
      end

      local function prepare_layout_parts(layout, box_type)
        layout.results = results
        results.border:set_style(border.results_patch[box_type])

        layout.prompt = prompt
        prompt.border:set_style(border.prompt_patch[box_type])

        if box_type == "minimal" then
          layout.preview = nil
        else
          layout.preview = preview
          preview.border:set_style(border.preview_patch[box_type])
        end
      end

      local function get_layout_size(box_kind)
        return picker.layout_config[box_kind == "minimal" and "vertical" or box_kind].size
      end

      local box, box_kind = get_box()
      local layout = Layout({
        relative = "editor",
        position = "50%",
        size = get_layout_size(box_kind),
      }, box)

      layout.picker = picker
      prepare_layout_parts(layout, box_kind)

      local layout_update = layout.update
      function layout:update()
        local box, box_kind = get_box()
        prepare_layout_parts(layout, box_kind)
        layout_update(self, { size = get_layout_size(box_kind) }, box)
      end

      return TSLayout(layout)
    end,
  },
})

Pickers

File and text search in hidden files and directories

local telescope = require("telescope")
local telescopeConfig = require("telescope.config")

-- Clone the default Telescope configuration
local vimgrep_arguments = { unpack(telescopeConfig.values.vimgrep_arguments) }

-- I want to search in hidden/dot files.
table.insert(vimgrep_arguments, "--hidden")
-- I don't want to search in the `.git` directory.
table.insert(vimgrep_arguments, "--glob")
table.insert(vimgrep_arguments, "!**/.git/*")

telescope.setup({
	defaults = {
		-- `hidden = true` is not supported in text grep commands.
		vimgrep_arguments = vimgrep_arguments,
	},
	pickers = {
		find_files = {
			-- `hidden = true` will still show the inside of `.git/` as it's not `.gitignore`d.
			find_command = { "rg", "--files", "--hidden", "--glob", "!**/.git/*" },
		},
	},
})

Falling back to find_files if git_files can't find a .git directory

-- telescope-config.lua
local M = {}

-- We cache the results of "git rev-parse"
-- Process creation is expensive in Windows, so this reduces latency
local is_inside_work_tree = {}

M.project_files = function()
  local opts = {} -- define here if you want to define something

  local cwd = vim.fn.getcwd()
  if is_inside_work_tree[cwd] == nil then
    vim.fn.system("git rev-parse --is-inside-work-tree")
    is_inside_work_tree[cwd] = vim.v.shell_error == 0
  end

  if is_inside_work_tree[cwd] then
    builtin.git_files(opts)
  else
    builtin.find_files(opts)
  end
end

return M

-- call via:
-- :lua require"telescope-config".project_files()

-- example keymap:
-- vim.api.nvim_set_keymap("n", "<Leader><Space>", "<CMD>lua require'telescope-config'.project_files()<CR>", {noremap = true, silent = true})

Credits to @Conni2461 for the project_files snippet.

Remove ./ from fd results

Require at least fd v0.8.3. Prior to this version there shouldn't be a ./

require("telescope").setup {
  defaults = {
    -- ....
  },
  pickers = {
    find_files = {
      find_command = { "fd", "--type", "f", "--strip-cwd-prefix" }
    },
  }
}

Credits to @numToStr

ripgrep remove indentation

To trim the indentation at the beginning of presented line in the result window, change the defaults like shown below:

require("telescope").setup {
  defaults = {
    vimgrep_arguments = {
      "rg",
      "--color=never",
      "--no-heading",
      "--with-filename",
      "--line-number",
      "--column",
      "--smart-case",
      "--trim" -- add this value
    }
  }
}

Change directory

This is a snippet on how you can add change directory functionality to some pickers, like find files.

require("telescope").setup {
  defaults = {
    -- ....
  },
  pickers = {
    find_files = {
      mappings = {
        n = {
          ["cd"] = function(prompt_bufnr)
            local selection = require("telescope.actions.state").get_selected_entry()
            local dir = vim.fn.fnamemodify(selection.path, ":p:h")
            require("telescope.actions").close(prompt_bufnr)
            -- Depending on what you want put `cd`, `lcd`, `tcd`
            vim.cmd(string.format("silent lcd %s", dir))
          end
        }
      }
    },
  }
}

Credits to @ranjithshegde

Live grep from project git root with fallback

function live_grep_from_project_git_root()
	local function is_git_repo()
		vim.fn.system("git rev-parse --is-inside-work-tree")

		return vim.v.shell_error == 0
	end

	local function get_git_root()
		local dot_git_path = vim.fn.finddir(".git", ".;")
		return vim.fn.fnamemodify(dot_git_path, ":h")
	end

	local opts = {}

	if is_git_repo() then
		opts = {
			cwd = get_git_root(),
		}
	end

	require("telescope.builtin").live_grep(opts)
end

Credits to @wesbragagt

Find files from project git root with fallback

This function is basically find_files() combined with git_files(). The appeal of this function over the default find_files() is that you can find files that are not tracked by git. Also, find_files() only finds files in the current directory but this function finds files regardless of your current directory as long as you're in the project directory.

function vim.find_files_from_project_git_root()
  local function is_git_repo()
    vim.fn.system("git rev-parse --is-inside-work-tree")
    return vim.v.shell_error == 0
  end
  local function get_git_root()
    local dot_git_path = vim.fn.finddir(".git", ".;")
    return vim.fn.fnamemodify(dot_git_path, ":h")
  end
  local opts = {}
  if is_git_repo() then
    opts = {
      cwd = get_git_root(),
    }
  end
  require("telescope.builtin").find_files(opts)
end

Credits to @wesbragagt for most of the code from Live grep from project git root with fallback.

Find sibling files of current file

This function is basically find_files() but only for the directory containing the file you're currently editing. So you don't have to open up :Explore, tree, or anything else to browse next to the current file.

vim.keymap.set('n', '<leader>.', function() builtin.find_files({ cwd = vim.fn.expand('%:p:h') }) end)

Find files using Ag

telescope.setup({
  pickers = {
    find_files = {
      find_command = {"ag", "--silent", "--nocolor", "--follow", "-g", "", "--literal", "--hidden","--ignore", ".git "},
    },
  },

})

Previewers

Disable highlighting for certain files

local previewers = require("telescope.previewers")

local _bad = { ".*%.csv", ".*%.lua" } -- Put all filetypes that slow you down in this array
local bad_files = function(filepath)
  for _, v in ipairs(_bad) do
    if filepath:match(v) then
      return false
    end
  end

  return true
end

local new_maker = function(filepath, bufnr, opts)
  opts = opts or {}
  if opts.use_ft_detect == nil then opts.use_ft_detect = true end
  opts.use_ft_detect = opts.use_ft_detect == false and false or bad_files(filepath)
  previewers.buffer_previewer_maker(filepath, bufnr, opts)
end

require("telescope").setup {
  defaults = {
    buffer_previewer_maker = new_maker,
  }
}

Credit: @Conni2461

Ignore files bigger than a threshold

require("telescope").setup {
  defaults = {
    preview = {
        filesize_limit = 0.1, -- MB
    },
  }
}

Enable regex highlighting for certain filetypes

local previewers = require("telescope.previewers")
local putils = require("telescope.previewers.utils")
local pfiletype = require("plenary.filetype")

local new_maker = function(filepath, bufnr, opts)
  opts = opts or {}
  if opts.use_ft_detect == nil then
    local ft = pfiletype.detect(filepath)
    -- Here for example you can say: if ft == "xyz" then this_regex_highlighing else nothing end
    opts.use_ft_detect = false
    putils.regex_highlighter(bufnr, ft)
  end
  previewers.buffer_previewer_maker(filepath, bufnr, opts)
end

require("telescope").setup {
  defaults = {
    buffer_previewer_maker = new_maker,
  }
}

Credit: @Conni2461

Dont preview binaries

local previewers = require("telescope.previewers")
local Job = require("plenary.job")
local new_maker = function(filepath, bufnr, opts)
  filepath = vim.fn.expand(filepath)
  Job:new({
    command = "file",
    args = { "--mime-type", "-b", filepath },
    on_exit = function(j)
      local mime_type = vim.split(j:result()[1], "/")[1]
      if mime_type == "text" then
        previewers.buffer_previewer_maker(filepath, bufnr, opts)
      else
        -- maybe we want to write something to the buffer here
        vim.schedule(function()
          vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, { "BINARY" })
        end)
      end
    end
  }):sync()
end

require("telescope").setup {
  defaults = {
    buffer_previewer_maker = new_maker,
  }
}

Credit: @Conni2461

Use terminal image viewer to preview images

It is possible to use a terminal image viewer such as catimg to preview images in telescope.

require("telescope").setup {
  defaults = {
    preview = {
      mime_hook = function(filepath, bufnr, opts)
        local is_image = function(filepath)
          local image_extensions = {'png','jpg'}   -- Supported image formats
          local split_path = vim.split(filepath:lower(), '.', {plain=true})
          local extension = split_path[#split_path]
          return vim.tbl_contains(image_extensions, extension)
        end
        if is_image(filepath) then
          local term = vim.api.nvim_open_term(bufnr, {})
          local function send_output(_, data, _ )
            for _, d in ipairs(data) do
              vim.api.nvim_chan_send(term, d..'\r\n')
            end
          end
          vim.fn.jobstart(
            {
              'catimg', filepath  -- Terminal image viewer command
            }, 
            {on_stdout=send_output, stdout_buffered=true, pty=true})
        else
          require("telescope.previewers.utils").set_preview_message(bufnr, opts.winid, "Binary cannot be previewed")
        end
      end
    },
  }
}

Actions

Performing an arbitrary command by extending existing find_files picker

local actions = require "telescope.actions"
local action_state = require "telescope.actions.state"

local function run_selection(prompt_bufnr, map)
  actions.select_default:replace(function()
    actions.close(prompt_bufnr)
    local selection = action_state.get_selected_entry()
    vim.cmd([[!git log ]]..selection[1])
  end)
  return true
end

M.git_log = function()
  -- example for running a command on a file
  local opts = {
    attach_mappings = run_selection
  }
  require('telescope.builtin').find_files(opts)
end
return M

Using nvim-window-picker to choose a target window when opening a file from any picker.

require('telescope').setup({
  defaults = {
    mappings = {
      i = {
        ['<C-g>'] = function(prompt_bufnr)
          -- Use nvim-window-picker to choose the window by dynamically attaching a function
          local action_set = require('telescope.actions.set')
          local action_state = require('telescope.actions.state')

          local picker = action_state.get_current_picker(prompt_bufnr)
          picker.get_selection_window = function(picker, entry)
            local picked_window_id = require('window-picker').pick_window() or vim.api.nvim_get_current_win()
            -- Unbind after using so next instance of the picker acts normally
            picker.get_selection_window = nil
            return picked_window_id
          end

          return action_set.edit(prompt_bufnr, 'edit')
        end,
      },
    }
  }
}

Themes

Having two different themes and applying them selectively.

-- in lua/finders.lua
local finders = {}

-- Dropdown list theme using a builtin theme definitions :
local center_list = require"telescope.themes".get_dropdown({
  winblend = 10,
  width = 0.5,
  prompt = " ",
  results_height = 15,
  previewer = false,
})

-- Settings for with preview option
local with_preview = {
  winblend = 10,
  show_line = false,
  results_title = false,
  preview_title = false,
  layout_config = {
    preview_width = 0.5,
  },
}

-- Find in neovim config with center theme
finders.fd_in_nvim = function()
  local opts = vim.deepcopy(center_list)
  opts.prompt_prefix = "Nvim>"
  opts.cwd = vim.fn.stdpath("config")
  require"telescope.builtin".fd(opts)
end

-- Find files with_preview settings
function fd()
  local opts = vim.deepcopy(with_preview)
  opts.prompt_prefix = "FD>"
  require"telescope.builtin".fd(opts)
end

return finders

-- make sure to map it:
-- nnoremap <leader>ff :lua require"finders".fd_in_nvim()<cr>
-- nnoremap <leader>ff :lua require"finders".fd()<cr>

Others

Having a factory-like function based on a dict

local center_list  -- check the above snippet
local with_preview -- check the above snippet
local main = {}
local telescopes = {
  fd_nvim = {
    prompt_prefix = "Nvim>",
    fun = "fd",
    theme = center_list,
    cwd = vim.fn.stdpath("config")
    -- .. other options
  }
  fd = {
    prompt_prefix = "Files>",
    fun = "fd",
    theme = with_preview,
    -- .. other options
  }
}

main.run = function(str, theme)
  local base, fun, opts
  if not telescopes[str] then
    fun = str
    opts = theme or {}
    --return print("Sorry not found")
  else
    base = telescopes[str]
    fun = base.fun; theme = base.theme
    base.theme = nil; base.fun = nil
    opts = vim.tbl_extend("force", theme, base)
  end
  if str then
    return require"telescope.builtin"[fun](opts)
  else
    return print("You need to a set a default function")
    -- return require"telescope.builtin".find_files(opts)
  end
end

return main
-- make sure to map it:
-- nnoremap <leader>ff :lua require"main".run("fd")<cr>
-- nnoremap <leader>ff :lua require"main".run("fd_in_nvim")<cr>

Customize buffers display to look like LeaderF

telescope_like_leaderf
-- In: lua/rc/telescope/my_make_entry.lua
local my_make_entry = {}

local devicons = require"nvim-web-devicons"
local entry_display = require("telescope.pickers.entry_display")

local filter = vim.tbl_filter
local map = vim.tbl_map

function my_make_entry.gen_from_buffer_like_leaderf(opts)
  opts = opts or {}
  local default_icons, _ = devicons.get_icon("file", "", {default = true})

  local bufnrs = filter(function(b)
    return 1 == vim.fn.buflisted(b)
  end, vim.api.nvim_list_bufs())

  local max_bufnr = math.max(unpack(bufnrs))
  local bufnr_width = #tostring(max_bufnr)

  local max_bufname = math.max(
    unpack(
      map(function(bufnr)
        return vim.fn.strdisplaywidth(vim.fn.fnamemodify(vim.api.nvim_buf_get_name(bufnr), ":p:t"))
      end, bufnrs)
    )
  )

  local displayer = entry_display.create {
    separator = " ",
    items = {
      { width = bufnr_width },
      { width = 4 },
      { width = vim.fn.strwidth(default_icons) },
      { width = max_bufname },
      { remaining = true },
    },
  }

  local make_display = function(entry)
    return displayer {
      {entry.bufnr, "TelescopeResultsNumber"},
      {entry.indicator, "TelescopeResultsComment"},
      {entry.devicons, entry.devicons_highlight},
      entry.file_name,
      {entry.dir_name, "Comment"}
    }
  end

  return function(entry)
    local bufname = entry.info.name ~= "" and entry.info.name or "[No Name]"
    local hidden = entry.info.hidden == 1 and "h" or "a"
    local readonly = vim.api.nvim_buf_get_option(entry.bufnr, "readonly") and "=" or " "
    local changed = entry.info.changed == 1 and "+" or " "
    local indicator = entry.flag .. hidden .. readonly .. changed

    local dir_name = vim.fn.fnamemodify(bufname, ":p:h")
    local file_name = vim.fn.fnamemodify(bufname, ":p:t")

    local icons, highlight = devicons.get_icon(bufname, string.match(bufname, "%a+$"), { default = true })

    return {
      valid = true,

      value = bufname,
      ordinal = entry.bufnr .. " : " .. file_name,
      display = make_display,

      bufnr = entry.bufnr,

      lnum = entry.info.lnum ~= 0 and entry.info.lnum or 1,
      indicator = indicator,
      devicons = icons,
      devicons_highlight = highlight,

      file_name = file_name,
      dir_name = dir_name,
    }
  end
end

return my_make_entry


-- Use in telescope buffers

require("telescope.builtin").buffers({
  -- ...
  entry_maker = require"vimrc.telescope.my_make_entry".gen_from_buffer_like_leaderf(),
})

Credit: @elianiva

Running external commands

local previewers = require("telescope.previewers")
local pickers = require("telescope.pickers")
local sorters = require("telescope.sorters")
local finders = require("telescope.finders")

pickers.new {
  results_title = "Resources",
  -- Run an external command and show the results in the finder window
  finder = finders.new_oneshot_job({"terraform", "show"}),
  sorter = sorters.get_fuzzy_file(),
  previewer = previewers.new_buffer_previewer {
    define_preview = function(self, entry, status)
       -- Execute another command using the highlighted entry
      return require('telescope.previewers.utils').job_maker(
          {"terraform", "state", "list", entry.value},
          self.state.bufnr,
          {
            callback = function(bufnr, content)
              if content ~= nil then
                require('telescope.previewers.utils').regex_highlighter(bufnr, 'terraform')
              end
            end,
          })
    end
  },
}:find()

Fuzzy search among YAML objects

Utilizes treesitter. Let's imagine you have such a structure

services:
  database:
    volumes:
....

Telescope will have entries:

services
services.database
services.database.volumes

So you can jump to any of them

local pickers = require("telescope.pickers")
local conf = require('telescope.config').values
local finders = require("telescope.finders")

local function visit_yaml_node(node, name, yaml_path, result, file_path, bufnr)
    local key = ''
    if node:type() == "block_mapping_pair" then
        local field_key = node:field("key")[1]
        key = vim.treesitter.query.get_node_text(field_key, bufnr)
    end

    if key ~= nil and string.len(key) > 0 then
        table.insert(yaml_path, key)
        local line, col = node:start()
        table.insert(result, {
            lnum = line + 1,
            col = col + 1,
            bufnr = bufnr,
            filename = file_path,
            text = table.concat(yaml_path, '.'),
        })
    end

    for node, name in node:iter_children() do
        visit_yaml_node(node, name, yaml_path, result, file_path, bufnr)
    end

    if key ~= nil and string.len(key) > 0 then
        table.remove(yaml_path, table.maxn(yaml_path))
    end
end

local function gen_from_yaml_nodes(opts)
    local displayer = entry_display.create {
        separator = "",
        items = {
            { width = 5 },
            { remaining = true },
        },
    }

    local make_display = function(entry)
        return displayer {
            { entry.lnum, "TelescopeResultsSpecialComment" },
            { entry.text, function() return {} end },
        }
    end

    return function(entry)
        return make_entry.set_default_entry_mt({
            ordinal = entry.text,
            display = make_display,
            filename = entry.filename,
            lnum = entry.lnum,
            text = entry.text,
            col = entry.col,
        }, opts)
    end
end

local yaml_symbols = function(opts)
    local yaml_path = {}
    local result = {}
    local bufnr = vim.api.nvim_get_current_buf()
    local ft = vim.api.nvim_buf_get_option(bufnr, "ft")
    local tree = vim.treesitter.get_parser(bufnr, ft):parse()[1]
    local file_path = vim.api.nvim_buf_get_name(bufnr)
    local root = tree:root()
    for node, name in root:iter_children() do
        visit_yaml_node(node, name, yaml_path, result, file_path, bufnr)
    end

  -- return result
  pickers.new(opts, {
      prompt_title = "YAML symbols",
      finder = finders.new_table {
          results = result,
          entry_maker = opts.entry_maker or gen_from_yaml_nodes(opts),
      },
      sorter = conf.generic_sorter(opts),
      previewer = conf.grep_previewer(opts),
  })
  :find()
end