Introduction to Telescope development
master:h telescope.nvim before diving into implementation. This guide assumes proficiency in the Lua programming language.repository·master·Indexed 12 days ago
https://github.com/nvim-telescope/telescope.nvimA highly extendable fuzzy finder for Neovim designed around modularity with pluggable pickers, sorters, and previewers. It supports file, Vim, Git, and LSP pickers, and requires Neovim >=v0.11.7 and plenary.nvim.
:h telescope.nvim before diving into implementation. This guide assumes proficiency in the Lua programming language.A Sorter is a function called by a Picker for every item returned by a Finder. It calculates the "distance" between the current user prompt and the entry provided by the finder. Lower distance values typically result in higher ranking in the results list.
Available Sorters:
- `sorters.get_fuzzy_file`: Default for files.
- `sorters.get_generic_fuzzy_sorter`: Default for everything else.
- `sorters.get_levenshtein_sorter`: Levenshtein distance algorithm.
- `sorters.get_fzy_sorter`: fzy algorithm.
- `sorters.fuzzy_with_index_bias`: Considers when an item was added to the list.To change what happens when a user interacts with the picker (e.g., pressing <CR>), use the attach_mappings key in the picker's configuration table.
attach_mappings as a function that receives prompt_bufnr and map.actions.select_default:replace(callback) to override the default selection behavior.actions.close(prompt_bufnr) to close the picker and action_state.get_selected_entry() to retrieve the chosen item.attach_mappings function must return true to keep default mappings (like selection movement) or false to replace them entirely. Returning nil will cause an error.Note: Replacing actions via select_default:replace ensures that if a user has remapped their default selection key, your picker will respect that mapping.
local actions = require "telescope.actions"
local action_state = require "telescope.actions.state"
-- Inside your pickers.new configuration:
attach_mappings = function(prompt_bufnr, map)
actions.select_default:replace(function()
actions.close(prompt_bufnr)
local selection = action_state.get_selected_entry()
-- Do something with selection
print(vim.inspect(selection))
end)
return true
end,To install telescope.nvim, it is recommended to pin to the latest release tag. Using lazy.nvim, you can include plenary.nvim as a required dependency and telescope-fzf-native.nvim as an optional but highly recommended dependency for improved sorting performance.
Before installing, ensure you meet the requirements:
{
'nvim-telescope/telescope.nvim', version = '*',
dependencies = {
'nvim-lua/plenary.nvim',
-- optional but recommended
{ 'nvim-telescope/telescope-fzf-native.nvim', build = 'make' },
}
}To make your picker available via the :Telescope <name> command, you must structure your plugin and register it as an extension.
Directory Structure:
.
└── lua
├── plugin_name
│ └── init.lua
└── telescope
└── _extensions
└── plugin_name.luaNote: The _extensions directory name is significant.
Registration:
In lua/telescope/_extensions/plugin_name.lua, return the result of telescope.register_extension:
return require("telescope").register_extension {
setup = function(ext_config, config)
-- access extension config and user config
end,
exports = {
stuff = require("plugin_name").stuff
},
}setup: A function called during registration. It provides access to ext_config (extension-specific) and config (user's global telescope config). Use this to set up defaults or override internal functions like sorters.exports: A table of pickers/functions exported by your extension. If you export a single item, name the key after your plugin so it can be accessed via Telescope plugin_name.return require("telescope").register_extension {
setup = function(ext_config, config)
-- access extension config and user config
end,
exports = {
stuff = require("plugin_name").stuff
},
}Before using Telescope, ensure your environment meets these specifications:
>=v0.11.7 built with LuaJIT (verify with :version).nvim-lua/plenary.nvim is a required dependency.Recommended external tools for specific features:
BurntSushi/ripgrep): Required for live_grep and grep_string; also used by find_files.sharkdp/fd): Recommended finder.nvim-tree/nvim-web-devicons): For file icons.telescope-fzf-native.nvim or telescope-fzy-native.nvim.Themes are pre-defined groups of settings that change the visual appearance of the picker. You can apply themes in three ways:
theme option.pickers table." 1. Using Lua builtin with a theme
noremap <Leader>f :lua require'telescope.builtin'.find_files(require('telescope.themes').get_dropdown({}))<cr>
" 2. Using Vim command with theme option
Telescope find_files theme=dropdown
" 3. Configuring in setup()
require('telescope').setup{
pickers = {
find_files = {
theme = "dropdown",
}
}
}Extensions add new functionality or integrations. To use an extension, you must load it using load_extension(). Once loaded, extension pickers are available via the :Telescope command or through the telescope.extensions Lua API.
-- Loading an extension
require('telescope').load_extension('fzy_native')
-- Accessing an extension picker via Lua
-- (Example using 'dap' extension)
require('telescope').extensions.dap.configurations()Layouts are controlled by a layout_strategy and a corresponding layout_config. Sizes in layouts are "resolvable": a value like 0.5 represents 50% of the screen width, while 80 represents exactly 80 characters.
You can configure layouts globally in setup() or per-call in a builtin function.
-- Per-call configuration
require('telescope.builtin').find_files({layout_strategy='vertical', layout_config={width=0.5}})
-- Global configuration in setup()
require('telescope').setup({
defaults = {
layout_config = {
vertical = { width = 0.5 }
},
},
})Telescope supports two levels of customization:
setup() method.opts table to the builtin function (e.g., builtin.find_files(opts)).The setup() function accepts a table with three main sections: defaults (global), pickers (per-picker defaults), and extensions (extension-specific config).
require('telescope').setup{
defaults = {
-- Default configuration for telescope goes here:
-- config_key = value,
mappings = {
i = {
-- map actions.which_key to <C-h>
["<C-h>"] = "which_key"
}
}
},
pickers = {
-- Default configuration for builtin pickers goes here:
-- picker_name = {
-- picker_config_key = value,
-- ...
-- }
},
extensions = {
-- Your extension configuration goes here:
-- extension_name = {
-- extension_config_key = value,
-- }
}
}After installation, run the following command in Neovim to ensure all dependencies and requirements are correctly configured:
:checkhealth telescope
You can test the installation by running :Telescope find_files.
To use Telescope effectively, it is common to map builtin pickers to keybindings. Here is a standard setup using the telescope.builtin module:
local builtin = require('telescope.builtin')
vim.keymap.set('n', '<leader>ff', builtin.find_files, { desc = 'Telescope find files' })
vim.keymap.set('n', '<leader>fg', builtin.live_grep, { desc = 'Telescope live grep' })
vim.keymap.set('n', '<leader>fb', builtin.buffers, { desc = 'Telescope buffers' })
vim.keymap.set('n', '<leader>fh', builtin.help_tags, { desc = 'Telescope help tags' })