diff --git a/lua/telescope/pickers.lua b/lua/telescope/pickers.lua index 41f010c..e7ba113 100644 --- a/lua/telescope/pickers.lua +++ b/lua/telescope/pickers.lua @@ -35,8 +35,9 @@ local pickers = {} -- TODO: Add overscroll option for results buffer +---@class Picker --- Picker is the main UI that shows up to interact w/ your results. --- Takes a filter & a previewr +-- Takes a filter & a previewer local Picker = {} Picker.__index = Picker @@ -161,8 +162,8 @@ end --- Take an index and get a row. ---@note: Rows are 0-indexed, and `index` is 1 indexed (table index) ----@param index number: The index in line_manager ----@return number: The row for the picker to display in +---@param index number: the index in line_manager +---@return number: the row for the picker to display in function Picker:get_row(index) if self.sorting_strategy == "ascending" then return index - 1 @@ -183,6 +184,8 @@ function Picker:get_index(row) end end +--- Get the row number of the "best" entry +---@return number: the number of the "reset" row function Picker:get_reset_row() if self.sorting_strategy == "ascending" then return 0 @@ -191,12 +194,17 @@ function Picker:get_reset_row() end end +--- Check if the picker is no longer in use +---@return boolean|nil: `true` if picker is closed, `nil` otherwise function Picker:is_done() if not self.manager then return true end end +--- Clear rows that are after the final remaining entry +---@note: useful when number of remaining results is narrowed down +---@param results_bufnr number: the buffer number of the results buffer function Picker:clear_extra_rows(results_bufnr) if self:is_done() then log.trace "Not clearing due to being already complete" @@ -235,6 +243,11 @@ function Picker:clear_extra_rows(results_bufnr) log.trace("Clearing:", worst_line) end +--- Highlight the entry corresponding to the given row +---@param results_bufnr number: the buffer number of the results buffer +---@param prompt table: table with information about the prompt buffer +---@param display string: the text corresponding to the given row +---@param row number: the number of the chosen row function Picker:highlight_one_row(results_bufnr, prompt, display, row) if not self.sorter.highlighter then return @@ -267,6 +280,9 @@ function Picker:highlight_one_row(results_bufnr, prompt, display, row) self.highlighter:hi_multiselect(row, self:is_multi_selected(entry)) end +--- Check if the given row number can be selected +---@param row number: the number of the chosen row in the results buffer +---@return boolean function Picker:can_select_row(row) if self.sorting_strategy == "ascending" then return row <= self.manager:num_results() @@ -275,6 +291,7 @@ function Picker:can_select_row(row) end end +--TODO: document what `find_id` is for function Picker:_next_find_id() local find_id = self._find_id + 1 self._find_id = find_id @@ -282,6 +299,10 @@ function Picker:_next_find_id() return find_id end +--- A helper function for creating each of the windows in a picker +---@param bufnr number: the buffer number to be used in the window +---@param popup_opts table: options to pass to `popup.create` +---@param nowrap boolean: is |'wrap'| disabled in the created window function Picker:_create_window(bufnr, popup_opts, nowrap) local what = bufnr or "" local win, opts = popup.create(what, popup_opts) @@ -297,6 +318,8 @@ function Picker:_create_window(bufnr, popup_opts, nowrap) return win, opts, border_win end +--- Opens the given picker for the user to interact with +---@note: this is the main function for pickers, as it actually creates the interface for users function Picker:find() self:close_existing_pickers() self:reset_selection() @@ -514,6 +537,7 @@ function Picker:find() main_loop() end +--- A helper function to update picker windows when layout options are changed function Picker:recalculate_layout() local line_count = vim.o.lines - vim.o.cmdheight if vim.o.laststatus ~= 0 then @@ -607,6 +631,7 @@ local update_scroll = function(win, oldinfo, oldcursor, strategy, buf_maxline) end end +--- A wrapper for `Picker:recalculate_layout()` that also handles maintaining cursor position function Picker:full_layout_update() local oldinfo = vim.fn.getwininfo(self.results_win)[1] local oldcursor = vim.api.nvim_win_get_cursor(self.results_win) @@ -682,6 +707,9 @@ function Picker:set_prompt(str) vim.api.nvim_feedkeys(str, "n", false) end +--- Closes the windows for the prompt, results and preview +---@param status table: table containing information on the picker +--- and associated windows. Generally obtained from `state.get_status` function Picker.close_windows(status) local prompt_win = status.prompt_win local results_win = status.results_win @@ -705,18 +733,26 @@ function Picker.close_windows(status) state.clear_status(status.prompt_bufnr) end +--- Get the entry table of the current selection +---@return table function Picker:get_selection() return self._selection_entry end +--- Get the row number of the current selection +---@return number function Picker:get_selection_row() return self._selection_row or self.max_results end +--- Move the current selection by `change` steps +---@param change number function Picker:move_selection(change) self:set_selection(self:get_selection_row() + change) end +--- Add the entry of the given row to the multi-select object +---@param row number: the number of the chosen row function Picker:add_selection(row) local entry = self.manager:get_entry(self:get_index(row)) self._multi:add(entry) @@ -724,6 +760,8 @@ function Picker:add_selection(row) self.highlighter:hi_multiselect(row, true) end +--- Remove the entry of the given row to the multi-select object +---@param row number: the number of the chosen row function Picker:remove_selection(row) local entry = self.manager:get_entry(self:get_index(row)) self._multi:drop(entry) @@ -731,14 +769,23 @@ function Picker:remove_selection(row) self.highlighter:hi_multiselect(row, false) end +--- Check if the given row is in the multi-select object +---@param entry table: table with information about the chosen entry +---@return number: the "count" associated to the entry in the multi-select +--- object (if present), `nil` otherwise function Picker:is_multi_selected(entry) return self._multi:is_selected(entry) end +--- Get a table containing all of the currently selected entries +---@return table: an integer indexed table of selected entries function Picker:get_multi_selection() return self._multi:get() end +--- Toggle the given row in and out of the multi-select object. +--- Also updates the highlighting for the given entry +---@param row number: the number of the chosen row function Picker:toggle_selection(row) local entry = self.manager:get_entry(self:get_index(row)) self._multi:toggle(entry) @@ -746,6 +793,8 @@ function Picker:toggle_selection(row) self.highlighter:hi_multiselect(row, self._multi:is_selected(entry)) end +--- Set the current selection to `nil` +---@note: generally used when a picker is first activated with `find()` function Picker:reset_selection() self._selection_entry = nil self._selection_row = nil @@ -769,6 +818,9 @@ end -- TODO(conni2461): Maybe _ prefix these next two functions -- TODO(conni2461): Next two functions only work together otherwise color doesn't work -- Probably a issue with prompt buffers +--- Change the prefix in the prompt to be `new_prefix` and apply `hl_group` +---@param new_prefix string: the string to be used as the new prefix +---@param hl_group string: the name of the chosen highlight function Picker:change_prompt_prefix(new_prefix, hl_group) if not new_prefix then return @@ -784,6 +836,8 @@ function Picker:change_prompt_prefix(new_prefix, hl_group) self:_reset_prefix_color(hl_group) end +--- Reset the prompt to the provided `text` +---@param text string function Picker:reset_prompt(text) local prompt_text = self.prompt_prefix .. (text or "") vim.api.nvim_buf_set_lines(self.prompt_bufnr, 0, -1, false, { prompt_text }) @@ -821,6 +875,8 @@ function Picker:refresh(finder, opts) self._on_lines(nil, nil, nil, 0, 1) end +---Set the selection to the provided `row` +---@param row number function Picker:set_selection(row) if not self.manager then return @@ -925,6 +981,7 @@ function Picker:set_selection(row) vim.api.nvim_win_set_cursor(self.results_win, { row + 1, 0 }) end +--- Refresh the previewer based on the current `status` of the picker function Picker:refresh_previewer() local status = state.get_status(self.prompt_bufnr) if not self._selection_entry then @@ -970,6 +1027,10 @@ function Picker:cycle_previewers(next) end end +--- Handler for when entries are added by `self.manager` +---@param index number: the index to add the entry at +---@param entry table: the entry that has been added to the manager +---@param insert boolean: whether the entry has been "inserted" or not function Picker:entry_adder(index, entry, _, insert) if not entry then return @@ -1036,6 +1097,7 @@ function Picker:entry_adder(index, entry, _, insert) end end +--- Reset tracked information for this picker function Picker:_reset_track() self.stats.processed = 0 self.stats.displayed = 0 @@ -1047,10 +1109,14 @@ function Picker:_reset_track() self.stats.highlights = 0 end +--- Increment the count of the tracked info at `self.stats[key]` +---@param key string function Picker:_increment(key) self.stats[key] = (self.stats[key] or 0) + 1 end +--- Decrement the count of the tracked info at `self.stats[key]` +---@param key string function Picker:_decrement(key) self.stats[key] = (self.stats[key] or 0) - 1 end @@ -1071,12 +1137,18 @@ function Picker:_on_complete() end end +--- Close all open Telescope pickers function Picker:close_existing_pickers() for _, prompt_bufnr in ipairs(state.get_existing_prompts()) do - pcall(actions.close, prompt_bufnr) + pcall(actions._close, prompt_bufnr, true) end end +--- Returns a function that sets virtual text for the count indicator +--- e.g. "10/50" as "filtered"/"processed" +---@param prompt_win number +---@param prompt_bufnr number +---@return function function Picker:get_status_updater(prompt_win, prompt_bufnr) return function(opts) if self.closed or not vim.api.nvim_buf_is_valid(prompt_bufnr) then @@ -1103,6 +1175,13 @@ function Picker:get_status_updater(prompt_win, prompt_bufnr) end end +--- Returns a function that will process an element. +--- Returned function handles updating the "filtered" and "processed" counts +--- as appropriate and runs the sorters score function +---@param find_id number +---@param prompt string +---@param status_updater function +---@return function function Picker:get_result_processor(find_id, prompt, status_updater) local count = 0 @@ -1153,6 +1232,11 @@ function Picker:get_result_processor(find_id, prompt, status_updater) end end +--- Handles updating the picker after all the entries are scored/processed. +---@param results_bufnr number +---@param find_id number +---@param prompt string +---@param status_updater function function Picker:get_result_completor(results_bufnr, find_id, prompt, status_updater) return vim.schedule_wrap(function() if self.closed == true or self:is_done() then @@ -1210,6 +1294,11 @@ function Picker:_do_selection(prompt) end end +--- Wrapper function for `Picker:new` that incorporates user provided `opts` +--- with the telescope `defaults` +---@param opts table +---@param defaults table +---@return Picker pickers.new = function(opts, defaults) opts = opts or {} defaults = defaults or {} @@ -1247,6 +1336,8 @@ pickers.new = function(opts, defaults) return Picker:new(result) end +--- Close the picker which has prompt with buffer number `prompt_bufnr` +---@param prompt_bufnr number function pickers.on_close_prompt(prompt_bufnr) local status = state.get_status(prompt_bufnr) local picker = status.picker