feat: allow caching and resuming picker (#1051)
* expose `cache_picker` in telescope.setup to configure caching, see `:h telescope.defaults.cache_picker` * add builtin.resume and builtin.pickers picker
This commit is contained in:
@@ -439,6 +439,8 @@ Built-in functions. Ready to be bound to any key you like. :smile:
|
||||
| `builtin.highlights` | Lists all available highlights |
|
||||
| `builtin.current_buffer_fuzzy_find` | Live fuzzy search inside of the currently open buffer |
|
||||
| `builtin.current_buffer_tags` | Lists all of the tags for the currently open buffer, with a preview |
|
||||
| `builtin.resume` | Lists the results incl. multi-selections of the previous picker |
|
||||
| `builtin.pickers` | Lists the previous pickers incl. multi-selections (see `:h telescope.defaults.cache_picker`) |
|
||||
|
||||
### Neovim LSP Pickers
|
||||
|
||||
|
||||
@@ -25,6 +25,28 @@ telescope.setup({opts}) *telescope.setup()*
|
||||
|
||||
Default: true
|
||||
|
||||
*telescope.defaults.cache_picker*
|
||||
cache_picker: ~
|
||||
This field handles the configuration for picker caching.
|
||||
By default it is a table, with default values (more below).
|
||||
To disable caching, set it to false.
|
||||
|
||||
Caching preserves all previous multi selections and results and
|
||||
therefore may result in slowdown or increased RAM occupation
|
||||
if too many pickers (`cache_picker.num_pickers`) or entries
|
||||
('cache_picker.limit_entries`) are cached.
|
||||
|
||||
Fields:
|
||||
- num_pickers: The number of pickers to be cached.
|
||||
Set to -1 to preserve all pickers of your session.
|
||||
If passed to a picker, the cached pickers with
|
||||
indices larger than `cache_picker.num_pickers` will
|
||||
be cleared.
|
||||
Default: 1
|
||||
- limit_entries: The amount of entries that will be written in the
|
||||
Default: 1000
|
||||
|
||||
|
||||
*telescope.defaults.default_mappings*
|
||||
default_mappings: ~
|
||||
Not recommended to use except for advanced users.
|
||||
@@ -367,8 +389,8 @@ builtin.live_grep({opts}) *builtin.live_grep()*
|
||||
{opts} (table) options to pass to the picker
|
||||
|
||||
Fields: ~
|
||||
{cwd} (string) directory path to search from (default
|
||||
is cwd, use utils.buffer_dir() to search
|
||||
{cwd} (string) root dir to search from (default is cwd,
|
||||
use utils.buffer_dir() to search
|
||||
relative to open buffer)
|
||||
{grep_open_files} (boolean) if true, restrict search to open files
|
||||
only, mutually exclusive with
|
||||
@@ -388,8 +410,8 @@ builtin.grep_string({opts}) *builtin.grep_string()*
|
||||
{opts} (table) options to pass to the picker
|
||||
|
||||
Fields: ~
|
||||
{cwd} (string) directory path to search from (default
|
||||
is cwd, use utils.buffer_dir() to search
|
||||
{cwd} (string) root dir to search from (default is cwd,
|
||||
use utils.buffer_dir() to search
|
||||
relative to open buffer)
|
||||
{search} (string) the query to search
|
||||
{search_dirs} (table) directory/directories to search in
|
||||
@@ -408,9 +430,9 @@ builtin.find_files({opts}) *builtin.find_files()*
|
||||
{opts} (table) options to pass to the picker
|
||||
|
||||
Fields: ~
|
||||
{cwd} (string) directory path to search from (default is
|
||||
cwd, use utils.buffer_dir() to search
|
||||
relative to open buffer)
|
||||
{cwd} (string) root dir to search from (default is cwd, use
|
||||
utils.buffer_dir() to search relative to
|
||||
open buffer)
|
||||
{find_command} (table) command line arguments for `find_files` to
|
||||
use for the search, overrides default config
|
||||
{follow} (boolean) if true, follows symlinks (i.e. uses `-L`
|
||||
@@ -446,8 +468,8 @@ builtin.file_browser({opts}) *builtin.file_browser()*
|
||||
{opts} (table) options to pass to the picker
|
||||
|
||||
Fields: ~
|
||||
{cwd} (string) directory path to browse (default is cwd, use
|
||||
utils.buffer_dir() to browse relative to open
|
||||
{cwd} (string) root dir to browse from (default is cwd, use
|
||||
utils.buffer_dir() to search relative to open
|
||||
buffer)
|
||||
{depth} (number) file tree depth to display (default is 1)
|
||||
{dir_icon} (string) change the icon for a directory. default:
|
||||
@@ -679,6 +701,35 @@ builtin.search_history({opts}) *builtin.search_history()*
|
||||
{opts} (table) options to pass to the picker
|
||||
|
||||
|
||||
builtin.resume({opts}) *builtin.resume()*
|
||||
Opens the previous picker in the identical state (incl. multi selections)
|
||||
- Notes:
|
||||
- Requires `cache_picker` in setup or when having invoked pickers, see
|
||||
|telescope.defaults.cache_picker|
|
||||
|
||||
|
||||
Parameters: ~
|
||||
{opts} (table) options to pass to the picker
|
||||
|
||||
Fields: ~
|
||||
{cache_index} (number) what picker to resume, where 1 denotes most
|
||||
recent (default 1)
|
||||
|
||||
|
||||
builtin.pickers({opts}) *builtin.pickers()*
|
||||
Opens a picker over previously cached pickers in there preserved states
|
||||
(incl. multi selections)
|
||||
- Default keymaps:
|
||||
- `<C-x>`: delete the selected cached picker
|
||||
- Notes:
|
||||
- Requires `cache_picker` in setup or when having invoked pickers, see
|
||||
|telescope.defaults.cache_picker|
|
||||
|
||||
|
||||
Parameters: ~
|
||||
{opts} (table) options to pass to the picker
|
||||
|
||||
|
||||
builtin.vim_options({opts}) *builtin.vim_options()*
|
||||
Lists vim options, allows you to edit the current value on `<cr>`
|
||||
|
||||
@@ -1582,6 +1633,16 @@ actions.cycle_previewers_prev({prompt_bufnr})*actions.cycle_previewers_prev()*
|
||||
{prompt_bufnr} (number) The prompt bufnr
|
||||
|
||||
|
||||
actions.remove_selected_picker({prompt_bufnr})*actions.remove_selected_picker()*
|
||||
Removes the selected picker in |builtin.pickers|.
|
||||
This action is not mapped by default and only intended for
|
||||
|builtin.pickers|.
|
||||
|
||||
|
||||
Parameters: ~
|
||||
{prompt_bufnr} (number) The prompt bufnr
|
||||
|
||||
|
||||
|
||||
================================================================================
|
||||
*telescope.actions.state*
|
||||
|
||||
@@ -832,6 +832,21 @@ actions.cycle_previewers_prev = function(prompt_bufnr)
|
||||
actions.get_current_picker(prompt_bufnr):cycle_previewers(-1)
|
||||
end
|
||||
|
||||
--- Removes the selected picker in |builtin.pickers|.<br>
|
||||
--- This action is not mapped by default and only intended for |builtin.pickers|.
|
||||
---@param prompt_bufnr number: The prompt bufnr
|
||||
actions.remove_selected_picker = function(prompt_bufnr)
|
||||
local current_picker = action_state.get_current_picker(prompt_bufnr)
|
||||
local selection_index = current_picker:get_index(current_picker:get_selection_row())
|
||||
local cached_pickers = state.get_global_key "cached_pickers"
|
||||
current_picker:delete_selection(function()
|
||||
table.remove(cached_pickers, selection_index)
|
||||
end)
|
||||
if #cached_pickers == 0 then
|
||||
actions.close(prompt_bufnr)
|
||||
end
|
||||
end
|
||||
|
||||
-- ==================================================
|
||||
-- Transforms modules and sets the corect metatables.
|
||||
-- ==================================================
|
||||
|
||||
@@ -215,4 +215,41 @@ function LinkedList:ipairs()
|
||||
end
|
||||
end
|
||||
|
||||
function LinkedList:truncate(max_results)
|
||||
if max_results >= self.size then
|
||||
return
|
||||
end
|
||||
|
||||
local current_node
|
||||
if max_results < self.size - max_results then
|
||||
local index = 1
|
||||
current_node = self.head
|
||||
while index < max_results do
|
||||
local node = current_node
|
||||
if not node.next then
|
||||
break
|
||||
end
|
||||
current_node = current_node.next
|
||||
index = index + 1
|
||||
end
|
||||
self.size = max_results
|
||||
else
|
||||
current_node = self.tail
|
||||
while self.size > max_results do
|
||||
if current_node.prev == nil then
|
||||
break
|
||||
end
|
||||
current_node = current_node.prev
|
||||
self.size = self.size - 1
|
||||
end
|
||||
end
|
||||
self.tail = current_node
|
||||
self.tail.next = nil
|
||||
if max_results < self.track_at then
|
||||
self.track_at = max_results
|
||||
self.tracked = current_node.item
|
||||
self._tracked_node = current_node
|
||||
end
|
||||
end
|
||||
|
||||
return LinkedList
|
||||
|
||||
@@ -68,7 +68,7 @@ local builtin = {}
|
||||
|
||||
--- Search for a string and get results live as you type (respecting .gitignore)
|
||||
---@param opts table: options to pass to the picker
|
||||
---@field cwd string: directory path to search from (default is cwd, use utils.buffer_dir() to search relative to open buffer)
|
||||
---@field cwd string: root dir to search from (default is cwd, use utils.buffer_dir() to search relative to open buffer)
|
||||
---@field grep_open_files boolean: if true, restrict search to open files only, mutually exclusive with `search_dirs`
|
||||
---@field search_dirs table: directory/directories to search in, mutually exclusive with `grep_open_files`
|
||||
---@field additional_args function: function(opts) which returns a table of additional arguments to be passed on
|
||||
@@ -76,7 +76,7 @@ builtin.live_grep = require("telescope.builtin.files").live_grep
|
||||
|
||||
--- Searches for the string under your cursor in your current working directory
|
||||
---@param opts table: options to pass to the picker
|
||||
---@field cwd string: directory path to search from (default is cwd, use utils.buffer_dir() to search relative to open buffer)
|
||||
---@field cwd string: root dir to search from (default is cwd, use utils.buffer_dir() to search relative to open buffer)
|
||||
---@field search string: the query to search
|
||||
---@field search_dirs table: directory/directories to search in
|
||||
---@field use_regex boolean: if true, special characters won't be escaped, allows for using regex (default is false)
|
||||
@@ -85,7 +85,7 @@ builtin.grep_string = require("telescope.builtin.files").grep_string
|
||||
|
||||
--- Search for files (respecting .gitignore)
|
||||
---@param opts table: options to pass to the picker
|
||||
---@field cwd string: directory path to search from (default is cwd, use utils.buffer_dir() to search relative to open buffer)
|
||||
---@field cwd string: root dir to search from (default is cwd, use utils.buffer_dir() to search relative to open buffer)
|
||||
---@field find_command table: command line arguments for `find_files` to use for the search, overrides default config
|
||||
---@field follow boolean: if true, follows symlinks (i.e. uses `-L` flag for the `find` command)
|
||||
---@field hidden boolean: determines whether to show hidden files or not (default is false)
|
||||
@@ -105,7 +105,7 @@ builtin.fd = builtin.find_files
|
||||
--- create the file `init.lua` inside of `lua/telescope` and will create the necessary folders (similar to how
|
||||
--- `mkdir -p` would work) if they do not already exist
|
||||
---@param opts table: options to pass to the picker
|
||||
---@field cwd string: directory path to browse (default is cwd, use utils.buffer_dir() to browse relative to open buffer)
|
||||
---@field cwd string: root dir to browse from (default is cwd, use utils.buffer_dir() to search relative to open buffer)
|
||||
---@field depth number: file tree depth to display (default is 1)
|
||||
---@field dir_icon string: change the icon for a directory. default:
|
||||
---@field hidden boolean: determines whether to show hidden files or not (default is false)
|
||||
@@ -243,6 +243,21 @@ builtin.command_history = require("telescope.builtin.internal").command_history
|
||||
---@param opts table: options to pass to the picker
|
||||
builtin.search_history = require("telescope.builtin.internal").search_history
|
||||
|
||||
--- Opens the previous picker in the identical state (incl. multi selections)
|
||||
--- - Notes:
|
||||
--- - Requires `cache_picker` in setup or when having invoked pickers, see |telescope.defaults.cache_picker|
|
||||
---@param opts table: options to pass to the picker
|
||||
---@field cache_index number: what picker to resume, where 1 denotes most recent (default 1)
|
||||
builtin.resume = require("telescope.builtin.internal").resume
|
||||
|
||||
--- Opens a picker over previously cached pickers in there preserved states (incl. multi selections)
|
||||
--- - Default keymaps:
|
||||
--- - `<C-x>`: delete the selected cached picker
|
||||
--- - Notes:
|
||||
--- - Requires `cache_picker` in setup or when having invoked pickers, see |telescope.defaults.cache_picker|
|
||||
---@param opts table: options to pass to the picker
|
||||
builtin.pickers = require("telescope.builtin.internal").pickers
|
||||
|
||||
--- Lists vim options, allows you to edit the current value on `<cr>`
|
||||
---@param opts table: options to pass to the picker
|
||||
builtin.vim_options = require("telescope.builtin.internal").vim_options
|
||||
|
||||
@@ -6,7 +6,9 @@ local make_entry = require "telescope.make_entry"
|
||||
local Path = require "plenary.path"
|
||||
local pickers = require "telescope.pickers"
|
||||
local previewers = require "telescope.previewers"
|
||||
local p_window = require "telescope.pickers.window"
|
||||
local sorters = require "telescope.sorters"
|
||||
local state = require "telescope.state"
|
||||
local utils = require "telescope.utils"
|
||||
|
||||
local conf = require("telescope.config").values
|
||||
@@ -71,6 +73,80 @@ internal.builtin = function(opts)
|
||||
}):find()
|
||||
end
|
||||
|
||||
internal.resume = function(opts)
|
||||
opts = opts or {}
|
||||
opts.cache_index = vim.F.if_nil(opts.cache_index, 1)
|
||||
|
||||
local cached_pickers = state.get_global_key "cached_pickers"
|
||||
if cached_pickers == nil or vim.tbl_isempty(cached_pickers) then
|
||||
print "No picker(s) cached."
|
||||
return
|
||||
end
|
||||
local picker = cached_pickers[opts.cache_index]
|
||||
if picker == nil then
|
||||
print("Index too large as there are only %s pickers cached", #cached_pickers)
|
||||
return
|
||||
end
|
||||
-- reset layout strategy and get_window_options if default as only one is valid
|
||||
-- and otherwise unclear which was actually set
|
||||
if picker.layout_strategy == conf.layout_strategy then
|
||||
picker.layout_strategy = nil
|
||||
end
|
||||
if picker.get_window_options == p_window.get_window_options then
|
||||
picker.get_window_options = nil
|
||||
end
|
||||
picker.cache_picker.index = opts.cache_index
|
||||
|
||||
-- avoid partial `opts.cache_picker` at picker creation
|
||||
if opts.cache_picker ~= false then
|
||||
picker.cache_picker = vim.tbl_extend("keep", opts.cache_picker or {}, picker.cache_picker)
|
||||
else
|
||||
picker.cache_picker.disabled = true
|
||||
end
|
||||
opts.cache_picker = nil
|
||||
pickers.new(opts, picker):find()
|
||||
end
|
||||
|
||||
internal.pickers = function(opts)
|
||||
local cached_pickers = state.get_global_key "cached_pickers"
|
||||
if cached_pickers == nil or vim.tbl_isempty(cached_pickers) then
|
||||
print "No picker(s) cached."
|
||||
return
|
||||
end
|
||||
|
||||
opts = opts or {}
|
||||
|
||||
-- clear cache picker for immediate pickers.new and pass option to resumed picker
|
||||
if opts.cache_picker ~= nil then
|
||||
opts._cache_picker = opts.cache_picker
|
||||
opts.cache_picker = nil
|
||||
end
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = "Pickers",
|
||||
finder = finders.new_table {
|
||||
results = cached_pickers,
|
||||
entry_maker = make_entry.gen_from_picker(opts),
|
||||
},
|
||||
previewer = previewers.pickers.new(opts),
|
||||
sorter = conf.generic_sorter(opts),
|
||||
cache_picker = false,
|
||||
attach_mappings = function(_, map)
|
||||
actions.select_default:replace(function(prompt_bufnr)
|
||||
local current_picker = action_state.get_current_picker(prompt_bufnr)
|
||||
local selection_index = current_picker:get_index(current_picker:get_selection_row())
|
||||
actions._close(prompt_bufnr, cached_pickers[selection_index].initial_mode == "insert")
|
||||
opts.cache_picker = opts._cache_picker
|
||||
opts["cache_index"] = selection_index
|
||||
internal.resume(opts)
|
||||
end)
|
||||
map("i", "<C-x>", actions.remove_selected_picker)
|
||||
map("n", "<C-x>", actions.remove_selected_picker)
|
||||
return true
|
||||
end,
|
||||
}):find()
|
||||
end
|
||||
|
||||
internal.planets = function(opts)
|
||||
local show_pluto = opts.show_pluto or false
|
||||
|
||||
|
||||
@@ -46,11 +46,22 @@ local smarter_depth_2_extend = function(priority, base)
|
||||
return result
|
||||
end
|
||||
|
||||
local resolve_table_opts = function(priority, base)
|
||||
if priority == false or (priority == nil and base == false) then
|
||||
return false
|
||||
end
|
||||
if priority == nil and type(base) == "table" then
|
||||
return base
|
||||
end
|
||||
return smarter_depth_2_extend(priority, base)
|
||||
end
|
||||
|
||||
-- TODO: Add other major configuration points here.
|
||||
-- selection_strategy
|
||||
|
||||
local config = {}
|
||||
config.smarter_depth_2_extend = smarter_depth_2_extend
|
||||
config.resolve_table_opts = resolve_table_opts
|
||||
|
||||
config.values = _TelescopeConfigurationValues
|
||||
config.descriptions = {}
|
||||
@@ -286,6 +297,33 @@ local telescope_defaults = {
|
||||
]],
|
||||
},
|
||||
|
||||
cache_picker = {
|
||||
{
|
||||
num_pickers = 1,
|
||||
limit_entries = 1000,
|
||||
},
|
||||
[[
|
||||
This field handles the configuration for picker caching.
|
||||
By default it is a table, with default values (more below).
|
||||
To disable caching, set it to false.
|
||||
|
||||
Caching preserves all previous multi selections and results and
|
||||
therefore may result in slowdown or increased RAM occupation
|
||||
if too many pickers (`cache_picker.num_pickers`) or entries
|
||||
('cache_picker.limit_entries`) are cached.
|
||||
|
||||
Fields:
|
||||
- num_pickers: The number of pickers to be cached.
|
||||
Set to -1 to preserve all pickers of your session.
|
||||
If passed to a picker, the cached pickers with
|
||||
indices larger than `cache_picker.num_pickers` will
|
||||
be cleared.
|
||||
Default: 1
|
||||
- limit_entries: The amount of entries that will be written in the
|
||||
Default: 1000
|
||||
]],
|
||||
},
|
||||
|
||||
-- Builtin configuration
|
||||
|
||||
-- List that will be executed.
|
||||
@@ -416,7 +454,7 @@ function config.set_defaults(user_defaults, tele_defaults)
|
||||
vim.tbl_deep_extend("keep", if_nil(config.values[name], {}), if_nil(default_val, {}))
|
||||
)
|
||||
end
|
||||
if name == "history" then
|
||||
if name == "history" or name == "cache_picker" then
|
||||
if user_defaults[name] == false or config.values[name] == false then
|
||||
return false
|
||||
end
|
||||
|
||||
@@ -662,6 +662,32 @@ function make_entry.gen_from_highlights()
|
||||
end
|
||||
end
|
||||
|
||||
function make_entry.gen_from_picker(opts)
|
||||
local displayer = entry_display.create {
|
||||
separator = " ",
|
||||
items = {
|
||||
{ width = 30 },
|
||||
{ remaining = true },
|
||||
},
|
||||
}
|
||||
|
||||
local make_display = function(entry)
|
||||
return displayer {
|
||||
entry.value.prompt_title,
|
||||
entry.value.default_text,
|
||||
}
|
||||
end
|
||||
|
||||
return function(entry)
|
||||
return {
|
||||
value = entry,
|
||||
text = entry.prompt_title,
|
||||
ordinal = string.format("%s %s", entry.prompt_title, utils.get_default(entry.default_text, "")),
|
||||
display = make_display,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
function make_entry.gen_from_buffer_lines(opts)
|
||||
local displayer = entry_display.create {
|
||||
separator = " │ ",
|
||||
|
||||
@@ -85,7 +85,11 @@ function Picker:new(opts)
|
||||
|
||||
_find_id = 0,
|
||||
_completion_callbacks = {},
|
||||
_multi = MultiSelect:new(),
|
||||
manager = (type(opts.manager) == "table" and getmetatable(opts.manger) == getmetatable(EntryManager))
|
||||
and opts.manager,
|
||||
_multi = (type(opts._multi) == "table" and getmetatable(opts._multi) == getmetatable(MultiSelect:new()))
|
||||
and opts._multi
|
||||
or MultiSelect:new(),
|
||||
|
||||
track = get_default(opts.track, false),
|
||||
stats = {},
|
||||
@@ -104,6 +108,8 @@ function Picker:new(opts)
|
||||
border = get_default(opts.border, config.values.border),
|
||||
borderchars = get_default(opts.borderchars, config.values.borderchars),
|
||||
},
|
||||
|
||||
cache_picker = config.resolve_table_opts(opts.cache_picker, vim.deepcopy(config.values.cache_picker)),
|
||||
}, self)
|
||||
|
||||
obj.get_window_options = opts.get_window_options or p_window.get_window_options
|
||||
@@ -332,6 +338,7 @@ function Picker:find()
|
||||
if prompt_border_win then
|
||||
vim.api.nvim_win_set_option(prompt_border_win, "winhl", "Normal:TelescopePromptBorder")
|
||||
end
|
||||
self.prompt_bufnr = prompt_bufnr
|
||||
|
||||
-- Prompt prefix
|
||||
local prompt_prefix = self.prompt_prefix
|
||||
@@ -416,6 +423,8 @@ function Picker:find()
|
||||
self.finder = new_finder
|
||||
end
|
||||
|
||||
-- TODO: Entry manager should have a "bulk" setter. This can prevent a lot of redraws from display
|
||||
if self.cache_picker == false or not (self.cache_picker.is_cached == true) then
|
||||
self.sorter:_start(prompt)
|
||||
self.manager = EntryManager:new(self.max_results, self.entry_adder, self.stats)
|
||||
|
||||
@@ -434,6 +443,28 @@ function Picker:find()
|
||||
if self.debounce and diff_time < self.debounce then
|
||||
async.util.sleep(self.debounce - diff_time)
|
||||
end
|
||||
else
|
||||
-- resume previous picker
|
||||
local index = 1
|
||||
for entry in self.manager:iter() do
|
||||
self:entry_adder(index, entry, _, true)
|
||||
index = index + 1
|
||||
end
|
||||
self.cache_picker.is_cached = false
|
||||
-- if text changed, required to set anew to restart finder; otherwise hl and selection
|
||||
if self.cache_picker.cached_prompt ~= self.default_text then
|
||||
self:reset_prompt()
|
||||
self:set_prompt(self.default_text)
|
||||
else
|
||||
-- scheduling required to apply highlighting and selection appropriately
|
||||
await_schedule(function()
|
||||
self:highlight_displayed_rows(self.results_bufnr, self.cache_picker.cached_prompt)
|
||||
if self.cache_picker.selection_row ~= nil then
|
||||
self:set_selection(self.cache_picker.selection_row)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
@@ -444,7 +475,6 @@ function Picker:find()
|
||||
|
||||
self._result_completed = false
|
||||
status_updater { completed = false }
|
||||
|
||||
tx.send(...)
|
||||
end,
|
||||
on_detach = function()
|
||||
@@ -463,8 +493,6 @@ function Picker:find()
|
||||
vim.cmd(on_buf_leave)
|
||||
vim.cmd [[augroup END]]
|
||||
|
||||
self.prompt_bufnr = prompt_bufnr
|
||||
|
||||
local preview_border = preview_opts and preview_opts.border
|
||||
self.preview_border = preview_border
|
||||
local preview_border_win = (preview_border and preview_border.win_id) and preview_border.win_id
|
||||
@@ -1124,6 +1152,41 @@ function pickers.on_close_prompt(prompt_bufnr)
|
||||
local status = state.get_status(prompt_bufnr)
|
||||
local picker = status.picker
|
||||
|
||||
if type(picker.cache_picker) == "table" then
|
||||
local cached_pickers = state.get_global_key "cached_pickers" or {}
|
||||
|
||||
if type(picker.cache_picker.index) == "number" then
|
||||
if not vim.tbl_isempty(cached_pickers) then
|
||||
table.remove(cached_pickers, picker.cache_picker.index)
|
||||
end
|
||||
end
|
||||
|
||||
-- if picker was disabled post-hoc (e.g. `cache_picker = false` conclude after deletion)
|
||||
if picker.cache_picker.disabled ~= true then
|
||||
if picker.cache_picker.limit_entries > 0 then
|
||||
-- edge case: starting in normal mode and not having run a search means having no manager instantiated
|
||||
if picker.manager then
|
||||
picker.manager.linked_states:truncate(picker.cache_picker.limit_entries)
|
||||
else
|
||||
picker.manager = EntryManager:new(picker.max_results, picker.entry_adder, picker.stats)
|
||||
end
|
||||
end
|
||||
picker.default_text = picker:_get_prompt()
|
||||
picker.cache_picker.selection_row = picker._selection_row
|
||||
picker.cache_picker.cached_prompt = picker:_get_prompt()
|
||||
picker.cache_picker.is_cached = true
|
||||
table.insert(cached_pickers, 1, picker)
|
||||
|
||||
-- release pickers
|
||||
if picker.cache_picker.num_pickers > 0 then
|
||||
while #cached_pickers > picker.cache_picker.num_pickers do
|
||||
table.remove(cached_pickers, #cached_pickers)
|
||||
end
|
||||
end
|
||||
state.set_global_key("cached_pickers", cached_pickers)
|
||||
end
|
||||
end
|
||||
|
||||
if picker.sorter then
|
||||
picker.sorter:_destroy()
|
||||
end
|
||||
|
||||
@@ -247,6 +247,8 @@ previewers.new_buffer_previewer = function(opts)
|
||||
buf_delete(bufnr)
|
||||
end
|
||||
end
|
||||
-- enable resuming picker with existing previewer to avoid lookup of deleted bufs
|
||||
bufname_table = {}
|
||||
end
|
||||
|
||||
function opts.preview_fn(self, entry, status)
|
||||
@@ -853,6 +855,83 @@ previewers.highlights = defaulter(function(_)
|
||||
}
|
||||
end, {})
|
||||
|
||||
previewers.pickers = defaulter(function(_)
|
||||
local ns_telescope_multiselection = vim.api.nvim_create_namespace "telescope_mulitselection"
|
||||
local get_row = function(picker, preview_height, index)
|
||||
if picker.sorting_strategy == "ascending" then
|
||||
return index - 1
|
||||
else
|
||||
return preview_height - index
|
||||
end
|
||||
end
|
||||
return previewers.new_buffer_previewer {
|
||||
|
||||
dyn_title = function(_, entry)
|
||||
if entry.value.default_text and entry.value.default_text ~= "" then
|
||||
return string.format("%s ─ %s", entry.value.prompt_title, entry.value.default_text)
|
||||
end
|
||||
return entry.value.prompt_title
|
||||
end,
|
||||
|
||||
get_buffer_by_name = function(_, entry)
|
||||
return tostring(entry.value.prompt_bufnr)
|
||||
end,
|
||||
|
||||
teardown = function(self)
|
||||
if self.state and self.state.last_set_bufnr and vim.api.nvim_buf_is_valid(self.state.last_set_bufnr) then
|
||||
vim.api.nvim_buf_clear_namespace(self.state.last_set_bufnr, ns_telescope_multiselection, 0, -1)
|
||||
end
|
||||
end,
|
||||
|
||||
define_preview = function(self, entry, status)
|
||||
putils.with_preview_window(status, nil, function()
|
||||
local ns_telescope_entry = vim.api.nvim_create_namespace "telescope_entry"
|
||||
local preview_height = vim.api.nvim_win_get_height(status.preview_win)
|
||||
|
||||
if self.state.bufname then
|
||||
return
|
||||
end
|
||||
|
||||
local picker = entry.value
|
||||
-- prefill buffer to be able to set lines individually
|
||||
local placeholder = utils.repeated_table(preview_height, "")
|
||||
vim.api.nvim_buf_set_lines(self.state.bufnr, 0, -1, false, placeholder)
|
||||
|
||||
for index = 1, math.min(preview_height, picker.manager:num_results()) do
|
||||
local row = get_row(picker, preview_height, index)
|
||||
local e = picker.manager:get_entry(index)
|
||||
local display, display_highlight = e:display()
|
||||
|
||||
vim.api.nvim_buf_set_lines(self.state.bufnr, row, row + 1, false, { display })
|
||||
|
||||
if display_highlight ~= nil then
|
||||
for _, hl_block in ipairs(display_highlight) do
|
||||
vim.api.nvim_buf_add_highlight(
|
||||
self.state.bufnr,
|
||||
ns_telescope_entry,
|
||||
hl_block[2],
|
||||
row,
|
||||
hl_block[1][1],
|
||||
hl_block[1][2]
|
||||
)
|
||||
end
|
||||
end
|
||||
if picker._multi:is_selected(e) then
|
||||
vim.api.nvim_buf_add_highlight(
|
||||
self.state.bufnr,
|
||||
ns_telescope_multiselection,
|
||||
"TelescopeMultiSelection",
|
||||
row,
|
||||
0,
|
||||
-1
|
||||
)
|
||||
end
|
||||
end
|
||||
end)
|
||||
end,
|
||||
}
|
||||
end, {})
|
||||
|
||||
previewers.display_content = defaulter(function(_)
|
||||
return previewers.new_buffer_previewer {
|
||||
define_preview = function(self, entry, status)
|
||||
|
||||
@@ -306,6 +306,7 @@ previewers.man = buffer_previewer.man
|
||||
previewers.autocommands = buffer_previewer.autocommands
|
||||
previewers.highlights = buffer_previewer.highlights
|
||||
previewers.buffers = buffer_previewer.buffers
|
||||
previewers.pickers = buffer_previewer.pickers
|
||||
|
||||
--- A deprecated way of displaying content more easily. Was written at a time,
|
||||
--- where the buffer_previewer interface wasn't present. Nowadays it's easier
|
||||
|
||||
Reference in New Issue
Block a user