summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfdschmidt93 <39233597+fdschmidt93@users.noreply.github.com>2021-09-01 18:17:18 +0200
committerGitHub <noreply@github.com>2021-09-01 18:17:18 +0200
commit5d37c3ea08f40d8c9d3a9ebcc72bd641d366c110 (patch)
treee66df8fe1312c38ad28ff64e0f0218b415bf18af
parent67bc1dcdd6eea1915b7c397b7c02451bbdc277a0 (diff)
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
-rw-r--r--README.md2
-rw-r--r--doc/telescope.txt79
-rw-r--r--lua/telescope/actions/init.lua15
-rw-r--r--lua/telescope/algos/linked_list.lua37
-rw-r--r--lua/telescope/builtin/init.lua23
-rw-r--r--lua/telescope/builtin/internal.lua76
-rw-r--r--lua/telescope/config.lua40
-rw-r--r--lua/telescope/make_entry.lua26
-rw-r--r--lua/telescope/pickers.lua97
-rw-r--r--lua/telescope/previewers/buffer_previewer.lua79
-rw-r--r--lua/telescope/previewers/init.lua1
11 files changed, 444 insertions, 31 deletions
diff --git a/README.md b/README.md
index 222b820..a1df186 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/doc/telescope.txt b/doc/telescope.txt
index 8fedd6c..fc36ca5 100644
--- a/doc/telescope.txt
+++ b/doc/telescope.txt
@@ -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*
diff --git a/lua/telescope/actions/init.lua b/lua/telescope/actions/init.lua
index cda5f1d..aa930dc 100644
--- a/lua/telescope/actions/init.lua
+++ b/lua/telescope/actions/init.lua
@@ -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.
-- ==================================================
diff --git a/lua/telescope/algos/linked_list.lua b/lua/telescope/algos/linked_list.lua
index 6015e1e..2da6a6e 100644
--- a/lua/telescope/algos/linked_list.lua
+++ b/lua/telescope/algos/linked_list.lua
@@ -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
diff --git a/lua/telescope/builtin/init.lua b/lua/telescope/builtin/init.lua
index ffc217e..6cc24b4 100644
--- a/lua/telescope/builtin/init.lua
+++ b/lua/telescope/builtin/init.lua
@@ -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
diff --git a/lua/telescope/builtin/internal.lua b/lua/telescope/builtin/internal.lua
index b71811e..cbacf97 100644
--- a/lua/telescope/builtin/internal.lua
+++ b/lua/telescope/builtin/internal.lua
@@ -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
diff --git a/lua/telescope/config.lua b/lua/telescope/config.lua
index a4899af..d58b94e 100644
--- a/lua/telescope/config.lua
+++ b/lua/telescope/config.lua
@@ -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
diff --git a/lua/telescope/make_entry.lua b/lua/telescope/make_entry.lua
index e2c6d45..14d5ecb 100644
--- a/lua/telescope/make_entry.lua
+++ b/lua/telescope/make_entry.lua
@@ -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 = " │ ",
diff --git a/lua/telescope/pickers.lua b/lua/telescope/pickers.lua
index 9e5f251..42e37d9 100644
--- a/lua/telescope/pickers.lua
+++ b/lua/telescope/pickers.lua
@@ -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
diff --git a/lua/telescope/previewers/buffer_previewer.lua b/lua/telescope/previewers/buffer_previewer.lua
index f6c4a78..59630b8 100644
--- a/lua/telescope/previewers/buffer_previewer.lua
+++ b/lua/telescope/previewers/buffer_previewer.lua
@@ -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)
diff --git a/lua/telescope/previewers/init.lua b/lua/telescope/previewers/init.lua
index 1d7d63e..b749056 100644
--- a/lua/telescope/previewers/init.lua
+++ b/lua/telescope/previewers/init.lua
@@ -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