feat: layout anchor (#1582)
* feat: add `anchor` option to some `layout_strategies` * tests: improve tests for `resolve_height/width`
This commit is contained in:
@@ -213,6 +213,35 @@ resolver.resolve_width = function(val)
|
||||
error("invalid configuration option for width:" .. tostring(val))
|
||||
end
|
||||
|
||||
--- Calculates the adjustment required to move the picker from the middle of the screen to
|
||||
--- an edge or corner. <br>
|
||||
--- The `anchor` can be any of the following strings:
|
||||
--- - "", "CENTER", "NW", "N", "NE", "E", "SE", "S", "SW", "W"
|
||||
--- The anchors have the following meanings:
|
||||
--- - "" or "CENTER":<br>
|
||||
--- the picker will remain in the middle of the screen.
|
||||
--- - Compass directions:<br>
|
||||
--- the picker will move to the corresponding edge/corner
|
||||
--- e.g. "NW" -> "top left corner", "E" -> "right edge", "S" -> "bottom edge"
|
||||
resolver.resolve_anchor_pos = function(anchor, p_width, p_height, max_columns, max_lines)
|
||||
anchor = anchor:upper()
|
||||
local pos = { 0, 0 }
|
||||
if anchor == "CENTER" then
|
||||
return pos
|
||||
end
|
||||
if anchor:find "W" then
|
||||
pos[1] = math.ceil((p_width - max_columns) / 2) + 1
|
||||
elseif anchor:find "E" then
|
||||
pos[1] = math.ceil((max_columns - p_width) / 2) - 1
|
||||
end
|
||||
if anchor:find "N" then
|
||||
pos[2] = math.ceil((p_height - max_lines) / 2) + 1
|
||||
elseif anchor:find "S" then
|
||||
pos[2] = math.ceil((max_lines - p_height) / 2) - 1
|
||||
end
|
||||
return pos
|
||||
end
|
||||
|
||||
-- Win option always returns a table with preview, results, and prompt.
|
||||
-- It handles many different ways. Some examples are as follows:
|
||||
--
|
||||
|
||||
@@ -107,6 +107,13 @@ local get_valid_configuration_keys = function(strategy_config)
|
||||
return valid_configuration_keys
|
||||
end
|
||||
|
||||
local adjust_pos = function(pos, ...)
|
||||
for _, opts in ipairs { ... } do
|
||||
opts.col = opts.col and opts.col + pos[1]
|
||||
opts.line = opts.line and opts.line + pos[2]
|
||||
end
|
||||
end
|
||||
|
||||
--@param strategy_name string: the name of the layout_strategy we are validating for
|
||||
--@param configuration table: table with keys for each option available
|
||||
--@param values table: table containing all of the non-default options we want to set
|
||||
@@ -187,6 +194,7 @@ local shared_options = {
|
||||
mirror = "Flip the location of the results/prompt and preview windows",
|
||||
scroll_speed = "The number of lines to scroll through the previewer",
|
||||
prompt_position = { "Where to place prompt window.", "Available Values: 'bottom', 'top'" },
|
||||
anchor = { "Which edge/corner to pin the picker to", "See |resolver.resolve_anchor_pos()|" },
|
||||
}
|
||||
|
||||
-- Used for generating vim help documentation.
|
||||
@@ -368,6 +376,9 @@ layout_strategies.horizontal = make_documented_layout(
|
||||
error(string.format("Unknown prompt_position: %s\n%s", self.window.prompt_position, vim.inspect(layout_config)))
|
||||
end
|
||||
|
||||
local anchor_pos = resolve.resolve_anchor_pos(layout_config.anchor or "", width, height, max_columns, max_lines)
|
||||
adjust_pos(anchor_pos, prompt, results, preview)
|
||||
|
||||
if tbln then
|
||||
prompt.line = prompt.line + 1
|
||||
results.line = results.line + 1
|
||||
@@ -388,6 +399,8 @@ layout_strategies.horizontal = make_documented_layout(
|
||||
--- Particularly useful for creating dropdown menus
|
||||
--- (see |telescope.themes| and |themes.get_dropdown()|`).
|
||||
---
|
||||
--- Note that the `anchor` option can only pin this layout to the left or right edges.
|
||||
---
|
||||
--- <pre>
|
||||
--- ┌──────────────────────────────────────────────────┐
|
||||
--- │ ┌────────────────────────────────────────┐ │
|
||||
@@ -475,7 +488,12 @@ layout_strategies.center = make_documented_layout(
|
||||
preview.height = 0
|
||||
end
|
||||
|
||||
results.col, preview.col, prompt.col = 0, 0, 0 -- all centered
|
||||
local width_padding = math.floor((max_columns - width) / 2) + bs + 1
|
||||
results.col, preview.col, prompt.col = width_padding, width_padding, width_padding
|
||||
|
||||
local anchor_pos = resolve.resolve_anchor_pos(layout_config.anchor or "", width, height, max_columns, max_lines)
|
||||
anchor_pos[2] = 0 -- only use horizontal anchoring
|
||||
adjust_pos(anchor_pos, prompt, results, preview)
|
||||
|
||||
if tbln then
|
||||
prompt.line = prompt.line + 1
|
||||
@@ -514,7 +532,11 @@ layout_strategies.center = make_documented_layout(
|
||||
--- </pre>
|
||||
layout_strategies.cursor = make_documented_layout(
|
||||
"cursor",
|
||||
vim.tbl_extend("error", shared_options, {
|
||||
vim.tbl_extend("error", {
|
||||
width = shared_options.width,
|
||||
height = shared_options.height,
|
||||
scroll_speed = shared_options.scroll_speed,
|
||||
}, {
|
||||
preview_width = { "Change the width of Telescope's preview window", "See |resolver.resolve_width()|" },
|
||||
preview_cutoff = "When columns are less than this value, the preview will be disabled",
|
||||
}),
|
||||
@@ -661,7 +683,8 @@ layout_strategies.vertical = make_documented_layout(
|
||||
prompt.height = 1
|
||||
results.height = height - preview.height - prompt.height - h_space
|
||||
|
||||
results.col, preview.col, prompt.col = 0, 0, 0 -- all centered
|
||||
local width_padding = math.floor((max_columns - width) / 2) + bs + 1
|
||||
results.col, preview.col, prompt.col = width_padding, width_padding, width_padding
|
||||
|
||||
local height_padding = math.floor((max_lines - height) / 2)
|
||||
if not layout_config.mirror then
|
||||
@@ -689,6 +712,9 @@ layout_strategies.vertical = make_documented_layout(
|
||||
end
|
||||
end
|
||||
|
||||
local anchor_pos = resolve.resolve_anchor_pos(layout_config.anchor or "", width, height, max_columns, max_lines)
|
||||
adjust_pos(anchor_pos, prompt, results, preview)
|
||||
|
||||
if tbln then
|
||||
prompt.line = prompt.line + 1
|
||||
results.line = results.line + 1
|
||||
|
||||
Reference in New Issue
Block a user