diff --git a/doc/telescope.txt b/doc/telescope.txt index 14a63e5..7b893d5 100644 --- a/doc/telescope.txt +++ b/doc/telescope.txt @@ -774,7 +774,7 @@ builtin.treesitter() *builtin.treesitter()* hl_group -builtin.current_buffer_fuzzy_find({opts})*builtin.current_buffer_fuzzy_find()* +builtin.current_buffer_fuzzy_find({opts}) *builtin.current_buffer_fuzzy_find()* Live fuzzy search inside of the currently open buffer @@ -1390,7 +1390,7 @@ builtin.lsp_workspace_symbols({opts}) *builtin.lsp_workspace_symbols()* with hl_group -builtin.lsp_dynamic_workspace_symbols({opts})*builtin.lsp_dynamic_workspace_symbols()* +builtin.lsp_dynamic_workspace_symbols({opts}) *builtin.lsp_dynamic_workspace_symbols()* Dynamically lists LSP for all workspace symbols - Default keymaps: - ``: show autocompletion menu to prefilter your query by type of @@ -1439,7 +1439,7 @@ builtin.lsp_document_diagnostics({opts}) *builtin.lsp_document_diagnostics()* in Results -builtin.lsp_workspace_diagnostics({opts})*builtin.lsp_workspace_diagnostics()* +builtin.lsp_workspace_diagnostics({opts}) *builtin.lsp_workspace_diagnostics()* Lists LSP diagnostics for the current workspace if supported, otherwise searches in all open buffers - Fields: @@ -1782,7 +1782,7 @@ actions.move_selection_next({prompt_bufnr}) *actions.move_selection_next()* {prompt_bufnr} (number) The prompt bufnr -actions.move_selection_previous({prompt_bufnr})*actions.move_selection_previous()* +actions.move_selection_previous({prompt_bufnr}) *actions.move_selection_previous()* Move the selection to the previous entry @@ -1798,7 +1798,7 @@ actions.move_selection_worse({prompt_bufnr}) *actions.move_selection_worse()* {prompt_bufnr} (number) The prompt bufnr -actions.move_selection_better({prompt_bufnr})*actions.move_selection_better()* +actions.move_selection_better({prompt_bufnr}) *actions.move_selection_better()* Move the selection to the entry that has a better score @@ -2067,7 +2067,7 @@ actions.delete_buffer({prompt_bufnr}) *actions.delete_buffer()* {prompt_bufnr} (number) The prompt bufnr -actions.cycle_previewers_next({prompt_bufnr})*actions.cycle_previewers_next()* +actions.cycle_previewers_next({prompt_bufnr}) *actions.cycle_previewers_next()* Cycle to the next previewer if there is one available. This action is not mapped on default. @@ -2076,7 +2076,7 @@ actions.cycle_previewers_next({prompt_bufnr})*actions.cycle_previewers_next()* {prompt_bufnr} (number) The prompt bufnr -actions.cycle_previewers_prev({prompt_bufnr})*actions.cycle_previewers_prev()* +actions.cycle_previewers_prev({prompt_bufnr}) *actions.cycle_previewers_prev()* Cycle to the previous previewer if there is one available. This action is not mapped on default. @@ -2085,7 +2085,7 @@ 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()* +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|. @@ -2125,7 +2125,7 @@ action_state.get_current_line() *action_state.get_current_line()* -action_state.get_current_picker({prompt_bufnr})*action_state.get_current_picker()* +action_state.get_current_picker({prompt_bufnr}) *action_state.get_current_picker()* Gets the current picker @@ -2145,7 +2145,7 @@ vertical split, etc. Instead of making users have to overwrite EACH of those every time they want to change this behavior, they can instead replace the `set` itself and then it will work great and they're done. -action_set.shift_selection({prompt_bufnr}, {change})*action_set.shift_selection()* +action_set.shift_selection({prompt_bufnr}, {change}) *action_set.shift_selection()* Move the current selection of a picker {change} rows. Handles not overflowing / underflowing the list. @@ -2176,7 +2176,7 @@ action_set.edit({prompt_bufnr}, {command}) *action_set.edit()* {command} (string) The command to use to open the file. -action_set.scroll_previewer({prompt_bufnr}, {direction})*action_set.scroll_previewer()* +action_set.scroll_previewer({prompt_bufnr}, {direction}) *action_set.scroll_previewer()* Scrolls the previewer up or down @@ -2255,7 +2255,7 @@ utils.map_selections({prompt_bufnr}, {f}) *utils.map_selections()* that takes (selection) as a viable argument -utils.get_registered_mappings({prompt_bufnr})*utils.get_registered_mappings()* +utils.get_registered_mappings({prompt_bufnr}) *utils.get_registered_mappings()* Utility to collect mappings of prompt buffer in array of `{mode, keybind, name}`. @@ -2571,7 +2571,7 @@ previewers.new_buffer_previewer() *previewers.new_buffer_previewer()* -previewers.buffer_previewer_maker({filepath}, {bufnr}, {opts})*previewers.buffer_previewer_maker()* +previewers.buffer_previewer_maker({filepath}, {bufnr}, {opts}) *previewers.buffer_previewer_maker()* A universal way of reading a file into a buffer previewer. It handles async reading, cache, highlighting, displaying directories and provides a callback which can be used, to jump to a line in the buffer. @@ -2627,7 +2627,7 @@ previewers.git_stash_diff() *previewers.git_stash_diff()* -previewers.git_commit_diff_to_parent()*previewers.git_commit_diff_to_parent()* +previewers.git_commit_diff_to_parent() *previewers.git_commit_diff_to_parent()* A previewer that shows a diff of a commit to a parent commit. The run command is `git --no-pager diff SHA^! -- $CURRENT_FILE` @@ -2735,7 +2735,7 @@ histories.History:reset() *histories.History:reset()* -histories.History:append({line}, {picker}, {no_reset})*histories.History:append()* +histories.History:append({line}, {picker}, {no_reset}) *histories.History:append()* Append a new line to the history diff --git a/lua/telescope/pickers.lua b/lua/telescope/pickers.lua index 9c59918..c4fae21 100644 --- a/lua/telescope/pickers.lua +++ b/lua/telescope/pickers.lua @@ -266,6 +266,18 @@ function Picker:_next_find_id() return find_id end +function Picker:_create_window(bufnr, popup_opts, nowrap) + local what = bufnr or "" + local win, opts = popup.create(what, popup_opts) + + a.nvim_win_set_option(win, "winblend", self.window.winblend) + if nowrap then + a.nvim_win_set_option(win, "wrap", false) + end + local border_win = opts and opts.border and opts.border.win_id + return win, opts, border_win +end + function Picker:find() self:close_existing_pickers() self:reset_selection() @@ -288,48 +300,35 @@ function Picker:find() -- `popup.nvim` massaging so people don't have to remember minheight shenanigans popup_opts.results.minheight = popup_opts.results.height + popup_opts.results.highlight = "TelescopeNormal" + popup_opts.results.borderhighlight = "TelescopeResultsBorder" popup_opts.prompt.minheight = popup_opts.prompt.height + popup_opts.prompt.highlight = "TelescopeNormal" + popup_opts.prompt.borderhighlight = "TelescopePromptBorder" if popup_opts.preview then popup_opts.preview.minheight = popup_opts.preview.height + popup_opts.preview.highlight = "TelescopeNormal" + popup_opts.preview.borderhighlight = "TelescopePreviewBorder" end - local results_win, results_opts = popup.create("", popup_opts.results) + -- local results_win, results_opts = popup.create("", popup_opts.results) + local results_win, _, results_border_win = self:_create_window("", popup_opts.results, true) local results_bufnr = a.nvim_win_get_buf(results_win) self.results_bufnr = results_bufnr self.results_win = results_win - -- TODO: Should probably always show all the line for results win, so should implement a resize for the windows - a.nvim_win_set_option(results_win, "wrap", false) - a.nvim_win_set_option(results_win, "winhl", "Normal:TelescopeNormal") - a.nvim_win_set_option(results_win, "winblend", self.window.winblend) - local results_border_win = results_opts.border and results_opts.border.win_id - if results_border_win then - vim.api.nvim_win_set_option(results_border_win, "winhl", "Normal:TelescopeResultsBorder") - end - - local preview_win, preview_opts, preview_bufnr + local preview_win, preview_opts, preview_bufnr, preview_border_win if popup_opts.preview then - preview_win, preview_opts = popup.create("", popup_opts.preview) + preview_win, preview_opts, preview_border_win = self:_create_window("", popup_opts.preview) preview_bufnr = a.nvim_win_get_buf(preview_win) - - a.nvim_win_set_option(preview_win, "winhl", "Normal:TelescopePreviewNormal") - a.nvim_win_set_option(preview_win, "winblend", self.window.winblend) - local preview_border_win = preview_opts and preview_opts.border and preview_opts.border.win_id - if preview_border_win then - vim.api.nvim_win_set_option(preview_border_win, "winhl", "Normal:TelescopePreviewBorder") - end end + -- This is needed for updating the title + local preview_border = preview_opts and preview_opts.border + self.preview_border = preview_border - -- TODO: We need to center this and make it prettier... - local prompt_win, prompt_opts = popup.create("", popup_opts.prompt) + local prompt_win, _, prompt_border_win = self:_create_window("", popup_opts.prompt) local prompt_bufnr = a.nvim_win_get_buf(prompt_win) - a.nvim_win_set_option(prompt_win, "winhl", "Normal:TelescopeNormal") - a.nvim_win_set_option(prompt_win, "winblend", self.window.winblend) - local prompt_border_win = prompt_opts.border and prompt_opts.border.win_id - 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 @@ -448,14 +447,18 @@ function Picker:find() prompt_bufnr ) + local on_vim_resize = string.format( + [[ autocmd VimResized ++nested :lua require('telescope.pickers').on_resize_window(%s)]], + prompt_bufnr + ) + vim.cmd [[augroup PickerInsert]] vim.cmd [[ au!]] vim.cmd(on_buf_leave) + vim.cmd(on_vim_resize) vim.cmd [[augroup END]] - 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 + self.prompt_bufnr = prompt_bufnr state.set_status( prompt_bufnr, @@ -483,11 +486,78 @@ function Picker:find() main_loop() end +function Picker:recalculate_layout() + local line_count = vim.o.lines - vim.o.cmdheight + if vim.o.laststatus ~= 0 then + line_count = line_count - 1 + end + + local popup_opts = self:get_window_options(vim.o.columns, line_count) + -- `popup.nvim` massaging so people don't have to remember minheight shenanigans + popup_opts.results.minheight = popup_opts.results.height + popup_opts.prompt.minheight = popup_opts.prompt.height + if popup_opts.preview then + popup_opts.preview.minheight = popup_opts.preview.height + end + + local status = state.get_status(self.prompt_bufnr) + + local prompt_win = status.prompt_win + local results_win = status.results_win + local preview_win = status.preview_win + + popup.move(results_win, popup_opts.results) + + local preview_opts, preview_border_win + if popup_opts.preview then + if preview_win ~= nil then + popup.move(preview_win, popup_opts.preview) + else + popup_opts.preview.highlight = "TelescopeNormal" + popup_opts.preview.borderhighlight = "TelescopePreviewBorder" + preview_win, preview_opts, preview_border_win = self:_create_window("", popup_opts.preview) + status.preview_win = preview_win + status.preview_border_win = preview_border_win + state.set_status(prompt_win, status) + self.preview_win = preview_win + self.preview_border_win = preview_border_win + self.preview_border = preview_opts and preview_opts.border + end + elseif preview_win ~= nil then + vim.api.nvim_win_close(preview_win, false) + if status.preview_border_win then + vim.api.nvim_win_close(status.preview_border_win, false) + end + status.preview_win = nil + status.preview_border_win = nil + state.set_status(prompt_win, status) + self.preview_win = nil + self.preview_border_win = nil + self.preview_border = nil + end + + popup.move(prompt_win, popup_opts.prompt) + + -- Temporarily disabled: Draw the screen ASAP. This makes things feel speedier. + -- vim.cmd [[redraw]] + + -- self.max_results = popup_opts.results.height +end + function Picker:hide_preview() -- 1. Hide the window (and border) -- 2. Resize prompt & results windows accordingly end +function Picker:toggle_padding() + -- if padding ~= 0 + -- 1. Save `height` and `width` of picker + -- 2. Set both to `{padding = 0}` + -- else + -- 1. Lookup previous `height` and `width` of picker + -- 2. Set both to previous values +end + -- TODO: update multi-select with the correct tag name when available --- A simple interface to remove an entry from the results window without --- closing telescope. This either deletes the current selection or all the @@ -1172,6 +1242,33 @@ function pickers.on_close_prompt(prompt_bufnr) picker.close_windows(status) end +local update_scroll = function(win, oldinfo, oldcursor, strategy, max_results) + if strategy == "ascending" then + vim.api.nvim_win_set_cursor(win, { max_results, 0 }) + vim.api.nvim_win_set_cursor(win, { oldinfo.topline, 0 }) + vim.api.nvim_win_set_cursor(win, oldcursor) + elseif strategy == "descending" then + vim.api.nvim_win_set_cursor(win, { 1, 0 }) + vim.api.nvim_win_set_cursor(win, { oldinfo.botline, 0 }) + vim.api.nvim_win_set_cursor(win, oldcursor) + else + error(debug.traceback("Unknown sorting strategy: " .. (strategy or ""))) + end +end + +function pickers.on_resize_window(prompt_bufnr) + local status = state.get_status(prompt_bufnr) + local picker = status.picker + + local oldinfo = vim.fn.getwininfo(status.results_win)[1] + local oldcursor = vim.api.nvim_win_get_cursor(status.results_win) + picker:recalculate_layout() + picker:refresh_previewer() + + -- update scrolled position + update_scroll(status.results_win, oldinfo, oldcursor, picker.sorting_strategy, picker.max_results) +end + --- Get the prompt text without the prompt prefix. function Picker:_get_prompt() return vim.api.nvim_buf_get_lines(self.prompt_bufnr, 0, 1, false)[1]:sub(#self.prompt_prefix + 1)