Skip to content

Commit 2201fae

Browse files
authored
feat(neovim): Add layout.anchor config options for picker placement (#399)
1 parent 7bad9f2 commit 2201fae

2 files changed

Lines changed: 88 additions & 11 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ require('fff').setup({
170170
-- 'middle': always uses dots (a/./b, a/../b, a/.../b)
171171
-- 'end': truncates from the end (home/user/projects)
172172
path_shorten_strategy = 'middle_number',
173+
anchor = 'center', -- picker placement: 'center', 'top_left', 'top', 'top_right', 'left', 'right', 'bottom_left', 'bottom', 'bottom_right'
173174
},
174175
preview = {
175176
enabled = true,

lua/fff/picker_ui.lua

Lines changed: 87 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -115,34 +115,110 @@ local function compute_layout(config)
115115
local width = math.floor(terminal_width * width_ratio)
116116
local height = math.floor(terminal_height * height_ratio)
117117

118-
local col_ratio_default = 0.5 - (width_ratio / 2)
119-
local col_ratio = col_ratio_default
118+
-- Account for chrome (statusline, tabline, cmdheight) for edge-anchored positions
119+
local has_tabline = vim.o.showtabline == 2 or (vim.o.showtabline == 1 and #vim.api.nvim_list_tabpages() > 1)
120+
local has_statusline = vim.o.laststatus > 0
121+
local top_edge = has_tabline and 1 or 0
122+
local bottom_edge = terminal_height - vim.o.cmdheight - (has_statusline and 1 or 0)
123+
local usable_height = bottom_edge - top_edge
124+
height = math.min(height, usable_height)
125+
126+
-- Anchor controls default placement; manual col/row overrides still work
127+
local anchor = utils.resolve_config_value(
128+
config.layout.anchor,
129+
terminal_width,
130+
terminal_height,
131+
function(v)
132+
return utils.is_one_of(v, {
133+
'center',
134+
'top_left',
135+
'top',
136+
'top_right',
137+
'left',
138+
'right',
139+
'bottom_left',
140+
'bottom',
141+
'bottom_right',
142+
})
143+
end,
144+
'center',
145+
'layout.anchor'
146+
)
147+
148+
-- Compute default positions as direct pixel values.
149+
-- Edge-flush anchors compensate for offsets added by calculate_layout_dimensions:
150+
-- col: -1 for left (internal +1 on list_col makes it flush)
151+
-- -2 for right (internal +1 plus the preview window's independent right border)
152+
-- row: -1 for top/bottom (internal +1 on rows; bottom also accounts for chrome via bottom_edge)
153+
local center_col = math.floor((terminal_width - width) / 2)
154+
local center_row = top_edge + math.floor((usable_height - height) / 2)
155+
local anchor_positions = {
156+
center = {
157+
col = center_col,
158+
row = center_row,
159+
},
160+
top_left = {
161+
col = -1,
162+
row = top_edge - 1,
163+
},
164+
top = {
165+
col = center_col,
166+
row = top_edge - 1,
167+
},
168+
top_right = {
169+
col = terminal_width - width - 2,
170+
row = top_edge - 1,
171+
},
172+
left = {
173+
col = -1,
174+
row = center_row,
175+
},
176+
right = {
177+
col = terminal_width - width - 2,
178+
row = center_row,
179+
},
180+
bottom_left = {
181+
col = -1,
182+
row = bottom_edge - height - 1,
183+
},
184+
bottom = {
185+
col = center_col,
186+
row = bottom_edge - height - 1,
187+
},
188+
bottom_right = {
189+
col = terminal_width - width - 2,
190+
row = bottom_edge - height - 1,
191+
},
192+
}
193+
194+
local pos = anchor_positions[anchor] or anchor_positions.center
195+
local col = pos.col
196+
local row = pos.row
197+
198+
-- Allow manual ratio overrides (backwards compat)
120199
if config.layout.col ~= nil then
121-
col_ratio = utils.resolve_config_value(
200+
local col_ratio = utils.resolve_config_value(
122201
config.layout.col,
123202
terminal_width,
124203
terminal_height,
125204
utils.is_valid_ratio,
126-
col_ratio_default,
205+
col / terminal_width,
127206
'layout.col'
128207
)
208+
col = math.floor(terminal_width * col_ratio)
129209
end
130-
local row_ratio_default = 0.5 - (height_ratio / 2)
131-
local row_ratio = row_ratio_default
132210
if config.layout.row ~= nil then
133-
row_ratio = utils.resolve_config_value(
211+
local row_ratio = utils.resolve_config_value(
134212
config.layout.row,
135213
terminal_width,
136214
terminal_height,
137215
utils.is_valid_ratio,
138-
row_ratio_default,
216+
row / terminal_height,
139217
'layout.row'
140218
)
219+
row = math.floor(terminal_height * row_ratio)
141220
end
142221

143-
local col = math.floor(terminal_width * col_ratio)
144-
local row = math.floor(terminal_height * row_ratio)
145-
146222
local prompt_position = get_prompt_position()
147223
local preview_position = get_preview_position()
148224

0 commit comments

Comments
 (0)