feat: recalculate picker layout on VimResized (#959)
* WIP: recalculate picker layout on `VimResized` * refactor: `popup.resize` -> `popup.move` * fix: scroll to the correct place after resize * fix: update positioning in results buffer * fix: completely redraw results buffer on resize * fix: handle preview enable/disable * fix: work with scrolling * docs: add plan for `toggle_padding` * refactor: factor out creation of picker windows * refactor: pass highlights directly to popup_create * refactor: remove lines update and factor out scroll repositioning Co-authored-by: Github Actions <actions@github>
This commit is contained in:
@@ -774,7 +774,7 @@ builtin.treesitter() *builtin.treesitter()*
|
|||||||
hl_group
|
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
|
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
|
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
|
Dynamically lists LSP for all workspace symbols
|
||||||
- Default keymaps:
|
- Default keymaps:
|
||||||
- `<C-l>`: show autocompletion menu to prefilter your query by type of
|
- `<C-l>`: 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
|
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
|
Lists LSP diagnostics for the current workspace if supported, otherwise
|
||||||
searches in all open buffers
|
searches in all open buffers
|
||||||
- Fields:
|
- Fields:
|
||||||
@@ -1782,7 +1782,7 @@ actions.move_selection_next({prompt_bufnr}) *actions.move_selection_next()*
|
|||||||
{prompt_bufnr} (number) The prompt bufnr
|
{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
|
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
|
{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
|
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
|
{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.
|
Cycle to the next previewer if there is one available.
|
||||||
This action is not mapped on default.
|
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
|
{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.
|
Cycle to the previous previewer if there is one available.
|
||||||
This action is not mapped on default.
|
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
|
{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|.
|
Removes the selected picker in |builtin.pickers|.
|
||||||
This action is not mapped by default and only intended for
|
This action is not mapped by default and only intended for
|
||||||
|builtin.pickers|.
|
|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
|
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
|
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.
|
`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
|
Move the current selection of a picker {change} rows. Handles not
|
||||||
overflowing / underflowing the list.
|
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.
|
{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
|
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
|
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,
|
Utility to collect mappings of prompt buffer in array of `{mode, keybind,
|
||||||
name}`.
|
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
|
A universal way of reading a file into a buffer previewer. It handles async
|
||||||
reading, cache, highlighting, displaying directories and provides a
|
reading, cache, highlighting, displaying directories and provides a
|
||||||
callback which can be used, to jump to a line in the buffer.
|
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.
|
A previewer that shows a diff of a commit to a parent commit.
|
||||||
The run command is `git --no-pager diff SHA^! -- $CURRENT_FILE`
|
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
|
Append a new line to the history
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -266,6 +266,18 @@ function Picker:_next_find_id()
|
|||||||
return find_id
|
return find_id
|
||||||
end
|
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()
|
function Picker:find()
|
||||||
self:close_existing_pickers()
|
self:close_existing_pickers()
|
||||||
self:reset_selection()
|
self:reset_selection()
|
||||||
@@ -288,48 +300,35 @@ function Picker:find()
|
|||||||
|
|
||||||
-- `popup.nvim` massaging so people don't have to remember minheight shenanigans
|
-- `popup.nvim` massaging so people don't have to remember minheight shenanigans
|
||||||
popup_opts.results.minheight = popup_opts.results.height
|
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.minheight = popup_opts.prompt.height
|
||||||
|
popup_opts.prompt.highlight = "TelescopeNormal"
|
||||||
|
popup_opts.prompt.borderhighlight = "TelescopePromptBorder"
|
||||||
if popup_opts.preview then
|
if popup_opts.preview then
|
||||||
popup_opts.preview.minheight = popup_opts.preview.height
|
popup_opts.preview.minheight = popup_opts.preview.height
|
||||||
|
popup_opts.preview.highlight = "TelescopeNormal"
|
||||||
|
popup_opts.preview.borderhighlight = "TelescopePreviewBorder"
|
||||||
end
|
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)
|
local results_bufnr = a.nvim_win_get_buf(results_win)
|
||||||
|
|
||||||
self.results_bufnr = results_bufnr
|
self.results_bufnr = results_bufnr
|
||||||
self.results_win = results_win
|
self.results_win = results_win
|
||||||
|
|
||||||
-- TODO: Should probably always show all the line for results win, so should implement a resize for the windows
|
local preview_win, preview_opts, preview_bufnr, preview_border_win
|
||||||
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
|
|
||||||
if popup_opts.preview then
|
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)
|
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
|
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_border_win = self:_create_window("", popup_opts.prompt)
|
||||||
local prompt_win, prompt_opts = popup.create("", popup_opts.prompt)
|
|
||||||
local prompt_bufnr = a.nvim_win_get_buf(prompt_win)
|
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
|
self.prompt_bufnr = prompt_bufnr
|
||||||
|
|
||||||
-- Prompt prefix
|
-- Prompt prefix
|
||||||
@@ -448,14 +447,18 @@ function Picker:find()
|
|||||||
prompt_bufnr
|
prompt_bufnr
|
||||||
)
|
)
|
||||||
|
|
||||||
|
local on_vim_resize = string.format(
|
||||||
|
[[ autocmd VimResized <buffer> ++nested :lua require('telescope.pickers').on_resize_window(%s)]],
|
||||||
|
prompt_bufnr
|
||||||
|
)
|
||||||
|
|
||||||
vim.cmd [[augroup PickerInsert]]
|
vim.cmd [[augroup PickerInsert]]
|
||||||
vim.cmd [[ au!]]
|
vim.cmd [[ au!]]
|
||||||
vim.cmd(on_buf_leave)
|
vim.cmd(on_buf_leave)
|
||||||
|
vim.cmd(on_vim_resize)
|
||||||
vim.cmd [[augroup END]]
|
vim.cmd [[augroup END]]
|
||||||
|
|
||||||
local preview_border = preview_opts and preview_opts.border
|
self.prompt_bufnr = prompt_bufnr
|
||||||
self.preview_border = preview_border
|
|
||||||
local preview_border_win = (preview_border and preview_border.win_id) and preview_border.win_id
|
|
||||||
|
|
||||||
state.set_status(
|
state.set_status(
|
||||||
prompt_bufnr,
|
prompt_bufnr,
|
||||||
@@ -483,11 +486,78 @@ function Picker:find()
|
|||||||
main_loop()
|
main_loop()
|
||||||
end
|
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()
|
function Picker:hide_preview()
|
||||||
-- 1. Hide the window (and border)
|
-- 1. Hide the window (and border)
|
||||||
-- 2. Resize prompt & results windows accordingly
|
-- 2. Resize prompt & results windows accordingly
|
||||||
end
|
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
|
-- TODO: update multi-select with the correct tag name when available
|
||||||
--- A simple interface to remove an entry from the results window without
|
--- A simple interface to remove an entry from the results window without
|
||||||
--- closing telescope. This either deletes the current selection or all the
|
--- 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)
|
picker.close_windows(status)
|
||||||
end
|
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.
|
--- Get the prompt text without the prompt prefix.
|
||||||
function Picker:_get_prompt()
|
function Picker:_get_prompt()
|
||||||
return vim.api.nvim_buf_get_lines(self.prompt_bufnr, 0, 1, false)[1]:sub(#self.prompt_prefix + 1)
|
return vim.api.nvim_buf_get_lines(self.prompt_bufnr, 0, 1, false)[1]:sub(#self.prompt_prefix + 1)
|
||||||
|
|||||||
Reference in New Issue
Block a user