picker.nvim picker.nvim is a lightweight, high-performance fuzzy finder for Neovim, built around a simple and extensible design. It provides a fast fzy-based matcher, flexible UI layouts, and an easy-to-write source API that lets you create custom pickers with minimal code. Whether you need file search, LSP symbols, diagnostics, or fully custom workflows, picker.nvim offers a clean and composable approach without the overhead of larger frameworks. β¨ Features π¦ Installation π§ Configuration βοΈ Basic Usage Picker Command Key bindings π Builtin sources files cmd_history picker_config highlights async_files colorscheme buftags buffers lines help_tags qflist loclist registers jumps marks lsp_document_symbols lsp_workspace_symbols lsp_references emoji key-mappings π Third party sources π§© Custom source πͺ Custom layout β FAQ π£ Self-Promotion π¬ Feedback π Credits π License β¨ Features β‘ High-performance fuzzy matching powered by the fzy algorithm π§ Simple yet extensible source API πͺ Flexible UI layouts (floating window, preview panel) π§© built-in picker sources π¦ Growing ecosystem of third-party extensions β¨οΈ Fully configurable actions & key mappings π Live preview and asynchronous loading support π¦ Installation picker.nvim works with all major Neovim plugin managers. Neovim 0.11+ is recommended for best compatibility. Using nvim-plug require("plug").add({ { "wsdjeg/picker.nvim", }, }) Using lazy.nvim { "wsdjeg/picker.nvim", event = "VeryLazy", config = function() require("picker").setup() end, } Using packer.nvim use({ "wsdjeg/picker.nvim", config = function() require("picker").setup() end, }) Using luarocks luarocks install picker.nvim π§ Configuration require("plug").add({ { "wsdjeg/picker.nvim", config = function() require("picker").setup({ filter = { ignorecase = false, -- ignorecase (boolean): defaults to false matcher = 'fzy', -- fzy or matchfuzzy }, window = { width = 0.8, -- set picker screen width, default is 0.8 * vim.o.columns height = 0.8, col = 0.1, row = 0.1, current_icon = ">", current_icon_hl = "CursorLine", enable_preview = false, preview_timeout = 500, show_score = false, -- display/hide match score at the end of each item. }, highlight = { matched = "Tag", score = "Comment", }, prompt = { position = "bottom", -- set prompt position, bottom or top icon = ">", icon_hl = "Error", insert_timeout = 100, title = true, -- display/hide source name }, mappings = { close = "<Esc>", next_item = "<Tab>", previous_item = "<S-Tab>", open_item = "<Enter>", toggle_preview = "<C-p>", }, }) end, }, }) βοΈ Basic Usage Picker Command fuzzy finder picker source. run :Picker command without source name. :Picker open picker source. run :Picker command with a name of source. :Picker <name> specific default input with --input option, users also can specific default input text. :Picker file --input=foo or use <cword> for word under cursor. :Picker help_tags --input=<cword> Key bindings In picker prompt window, the these mappings are defined by default. key binding description Tab next item S-Tab previous item Enter default action Esc close picker π Builtin sources source description buffers listed buffers buftags ctags outline for current buffer cmd_history results from :history : colorscheme all colorschemes files files in current dir help_tags neovim help tags source highlights highlight group source jumps jump list lines lines in current buffer loclist location list source lsp_document_symbols document symbols result from lsp client lsp_references lsp references lsp_workspace_symbols workspace symbols marks marks list picker_config picker config source qflist quickfix source registers registers context emoji emoji entries key-mappings key mappings files The default commands for listing files is {'rg', '--files'}. this can be changed via: require("picker.sources.files").set({ cmd = { "rg", "--files" } }) key binding description <Enter> open select file <C-v> open select file in vertical split <C-t> open select file in new tabpage cmd_history filter results from :history cmd. key binding description <Enter> execute select command <C-d> delete select command history picker_config filter and setup picker.nvim without changing configuration file. items description prompt-top change the prompt position to top prompt-bottom change the prompt position to bottom show-score display matched score hide-score hide matched score ignrecase change filter ignrecase to true noignrecase change filter ignrecase to false key binding description <Enter> set selected picker config highlights filter results from :highlight key binding description <Enter> yank selected highlight group name async_files same as files source, but require job.nvim. key binding description <Enter> open select file colorscheme filter colorschemes. key binding description <Enter> change to selected colorscheme buftags filter ctags outline, require ctags command. key binding description <Enter> jump to select tag buffers file results from nvim_list_bufs() key binding description <Enter> switch to select buffer lines key binding description <Enter> jump to selected line help_tags key binding description <Enter> jump selected help tag qflist key binding description <Enter> jump selected quickfix list item loclist key binding description <Enter> jump selected loclist item registers key binding description <Enter> paste selected context jumps key binding description <Enter> jump selected position marks key binding description <Enter> jump selected position lsp_document_symbols key binding description <Enter> jump selected symbol lsp_workspace_symbols key binding description <Enter> jump selected symbol lsp_references key binding description <Enter> jump selected reference emoji filter emoji entries from muan/unicode-emoji-json. This source will try to use job.nvim to download emoji json data, if job.nvim is not installed, vim.fn.system() will be used. key binding description <Enter> insert selected emoji key-mappings key binding description <Enter> trigger selected key mapping π Third party sources source description mru most recent used files, need mru.nvim project project history, need rooter.nvim bookmarks all bookmarks, need bookmarks.nvim zettelkasten zettelkasten notes source from zettelkasten.nvim zettelkasten_tags zettelkasten tags source from zettelkasten.nvim git-branch git branch source from git.nvim music-player music-player source form music-player.nvim plug plugins source for nvim-plug async_files async files source, require job.nvim π§© Custom source a source main module should be picker.sources.<name>, that means you can create a custom source in lua/picker/sources/ directory in your plugin. --- @class PickerSource --- @field get function --- @field default_action function --- @field __results nil | table<string> --- @field preview_win boolean --- @field preview function --- @field set function --- @field actions? table close picker window and trigger action --- @field redraw_actions? table picker window will not be closed after action To create picker source in script without using lua/picker/ directory: local custom_source = { get = function() return vim.tbl_map(function(t) return { value = t, str = t, } end, vim.split(vim.o.runtimepath, ',')) end, default_action = function(entry) vim.print(entry) end, } require('picker.windows').open(custom_source, {}) πͺ Custom layout picker.nvim use default layout by default. a layout should provide following public functions: local M = {} ---@class PickerLayout ---@field prompt_buf integer ---@field prompt_win integer ---@field list_buf integer ---@field list_win integer ---@field preview_buf integer ---@field preview_win integer ---@param source PickerSource ---@param config PickerConfig ---@return PickerLayout function M.render_windows(source, config) end return M β FAQ how to disable nvim-cmp in picker.nvim buffer? require("cmp").setup({ enabled = function() if vim.bo.filetype == "picker-prompt" then return false end return true end, }) how to use picker.nvim as vim.ui.select? vim.ui.select = function(items, opt, callback) local source = {} opt = opt or {} if opt.prompt then source.name = opt.prompt else source.name = "Select one of:" end source.get = function() local entrys = {} for idx, item in ipairs(items) do local entry = { value = item, idx = idx, -- this also can be nil } if opt.format_item then entry.str = opt.format_item(item) else entry.str = item end table.insert(entrys, entry) end return entrys end source.default_action = function(entry) if callback then callback(entry.value, entry.idx) end end require("picker.windows").open(source, { buf = vim.api.nvim_get_current_buf(), }) end π£ Self-Promotion Like this plugin? Star the repository on GitHub. Love this plugin? Follow me on GitHub. π¬ Feedback If you encounter any bugs or have suggestions, please file an issue in the issue tracker π Credits telescope.nvim denite.nvim π License Licensed under GPL-3.0.