feat(picker): added support for split layouts to picker (sidebar and ivy_split)

This commit is contained in:
Folke Lemaitre 2025-01-29 18:06:13 +01:00
parent ad8f16632c
commit 5496c22b6e
No known key found for this signature in database
GPG key ID: 41F8B1FBACAE2040
2 changed files with 70 additions and 3 deletions

View file

@ -19,6 +19,28 @@ M.default = {
},
}
M.sidebar = {
preview = "main",
layout = {
backdrop = false,
width = 40,
min_width = 40,
height = 0,
position = "left",
border = "none",
box = "vertical",
{
win = "input",
height = 1,
border = "rounded",
title = "{title} {live} {flags}",
title_pos = "center",
},
{ win = "list", border = "none" },
{ win = "preview", title = "{preview}", height = 0.4, border = "top" },
},
}
M.telescope = {
reverse = true,
layout = {
@ -61,6 +83,26 @@ M.ivy = {
},
}
M.ivy_split = {
preview = "main",
layout = {
box = "vertical",
backdrop = false,
width = 0,
height = 0.4,
position = "bottom",
border = "top",
title = " {title} {live} {flags}",
title_pos = "left",
{ win = "input", height = 1, border = "bottom" },
{
box = "horizontal",
{ win = "list", border = "none" },
{ win = "preview", title = "{preview}", width = 0.6, border = "left" },
},
},
}
M.dropdown = {
layout = {
backdrop = false,

View file

@ -9,6 +9,7 @@
---@field win_opts {main: snacks.win.Config, layout: snacks.win.Config, win: snacks.win.Config}
---@field winhl string
---@field title? string
---@field split_layout? boolean
local M = {}
M.__index = M
@ -91,7 +92,14 @@ function M:update(main)
self.main = main
self.win_opts.main.win = main
self.win.opts = vim.tbl_deep_extend("force", self.win.opts, main and self.win_opts.main or self.win_opts.layout)
self.win.opts.wo.winhighlight = main and vim.wo[main].winhighlight or self.winhl
local winhl = self.winhl
if main then
winhl = (vim.wo[main].winhighlight .. ",Normal:Normal," .. "CursorLine:SnacksPickerPreviewCursorLine"):gsub(
"^,",
""
)
end
self.win.opts.wo.winhighlight = winhl
if main then
self.win:update()
end
@ -99,6 +107,7 @@ end
---@param picker snacks.Picker
function M:show(picker)
self.split_layout = not picker.layout.root:is_floating()
local item, prev = picker:current({ resolve = false }), self.item
if self.item == item and self.pos == (item and item.pos or nil) then
return
@ -159,7 +168,10 @@ function M:clear(buf)
end
function M:reset()
if vim.api.nvim_buf_is_valid(self.win.scratch_buf) then
if not self.win:valid() then
return
end
if self.win.scratch_buf and vim.api.nvim_buf_is_valid(self.win.scratch_buf) then
vim.api.nvim_win_set_buf(self.win.win, self.win.scratch_buf)
else
self.win:scratch()
@ -223,9 +235,22 @@ function M:loc()
Snacks.picker.util.resolve_loc(self.item, self.win.buf)
local function show(pos)
local center = true
if self.split_layout and self.main and self.item and self.item.buf then
local main_buf = vim.api.nvim_win_get_buf(self.main)
if main_buf == self.item.buf then
center = false
local view = vim.api.nvim_win_call(self.main, vim.fn.winsaveview)
vim.api.nvim_win_call(self.win.win, function()
vim.fn.winrestview(view)
end)
end
end
vim.api.nvim_win_set_cursor(self.win.win, pos)
vim.api.nvim_win_call(self.win.win, function()
vim.cmd("norm! zzze")
if center then
vim.cmd("norm! zzze")
end
self:wo({ cursorline = true })
end)
end