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:
fdschmidt93
2021-09-01 18:17:18 +02:00
committed by GitHub
parent 67bc1dcdd6
commit 5d37c3ea08
11 changed files with 444 additions and 31 deletions

View File

@@ -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,23 +423,47 @@ function Picker:find()
self.finder = new_finder
end
self.sorter:_start(prompt)
self.manager = EntryManager:new(self.max_results, self.entry_adder, self.stats)
-- 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)
local process_result = self:get_result_processor(find_id, prompt, debounced_status)
local process_complete = self:get_result_completor(self.results_bufnr, find_id, prompt, status_updater)
local process_result = self:get_result_processor(find_id, prompt, debounced_status)
local process_complete = self:get_result_completor(self.results_bufnr, find_id, prompt, status_updater)
local ok, msg = pcall(function()
self.finder(prompt, process_result, process_complete)
end)
local ok, msg = pcall(function()
self.finder(prompt, process_result, process_complete)
end)
if not ok then
log.warn("Finder failed with msg: ", msg)
end
if not ok then
log.warn("Finder failed with msg: ", msg)
end
local diff_time = (vim.loop.hrtime() - start_time) / 1e6
if self.debounce and diff_time < self.debounce then
async.util.sleep(self.debounce - diff_time)
local diff_time = (vim.loop.hrtime() - start_time) / 1e6
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