Closed savchenko closed 8 months ago
hi @savchenko ,
The code looks like doing below things:
--padding=1
option to fzf binary.width
, height
, border
, rounded
options for --preview-window
option.If all the code is going to setting the options directly pass to fzf binary, then it could be done via the fzf_opts
option (the only difference is written by lua), please see:
FzfxBuffers
command default fzf_opts
option: https://github.com/linrongbin16/fzfx.nvim/blob/be08a3006551843cf273184c89233e5114d8a21b/lua/fzfx/cfg/buffers.lua#L158-L165To configure the fzf_opts
for FzfxBuffers
, please use:
require('fzfx').setup({
buffers = {
fzf_opts = {
-- please note, this configured `fzf_opts` will override the default configs.
-- so you may want to also add the builtin options.
"--multi",
{ "--prompt", "Buffers > " },
function()
local current_bufnr = vim.api.nvim_get_current_buf()
return nvims.buf_is_valid(current_bufnr) and "--header-lines=1" or nil
end,
-- add more options here: height, width, rounded, etc.
},
},
})
After further investigation, this works:
buffers = {
fzf_opts = {
"--info=hidden --header= --preview-window=hidden --padding=1"
},
win_opts = {
relative = 'win',
height = 10,
width = 40,
border = "rounded",
zindex = 51,
}
}
However, this does not:
buffers = {
fzf_opts = {
"--info=hidden --header= --preview-window=hidden --padding=1"
},
win_opts = function()
local blengths = {}
local max_length = 0
for _, buffer_number in ipairs(vim.api.nvim_list_bufs()) do
local buffer_object = vim.api.nvim_buf_get_name(buffer_number)
local buffer_name = vim.fn.expand(buffer_object)
buffer_name = vim.fn.substitute(buffer_name, vim.fn.getcwd(), "", "g")
buffer_name = vim.fn.substitute(buffer_name, vim.fn.expand("$HOME"), "~", "g")
blengths[#blengths + 1] = vim.fn.strwidth(buffer_name)
end
for _, length in ipairs(blengths) do
max_length = math.max(max_length, length)
end
return {
border = "rounded",
height = #blengths + 4,
width = max_length + 4,
relative = 'win',
zindex = 51,
}
end
}
Any idea why? The function returns correctly.
@savchenko, because 'win_opts' doesn't support function.
but it looks like function is a good idea.
@linrongbin16, rather vital I'd say. Would allow changing window size / position based on context. Buffer switching is one of the examples.
After further investigation, this works:
buffers = { fzf_opts = { "--info=hidden --header= --preview-window=hidden --padding=1" }, win_opts = { relative = 'win', height = 10, width = 40, border = "rounded", zindex = 51, } }
However, this does not:
buffers = { fzf_opts = { "--info=hidden --header= --preview-window=hidden --padding=1" }, win_opts = function() local blengths = {} local max_length = 0 for _, buffer_number in ipairs(vim.api.nvim_list_bufs()) do local buffer_object = vim.api.nvim_buf_get_name(buffer_number) local buffer_name = vim.fn.expand(buffer_object) buffer_name = vim.fn.substitute(buffer_name, vim.fn.getcwd(), "", "g") buffer_name = vim.fn.substitute(buffer_name, vim.fn.expand("$HOME"), "~", "g") blengths[#blengths + 1] = vim.fn.strwidth(buffer_name) end for _, length in ipairs(blengths) do max_length = math.max(max_length, length) end return { border = "rounded", height = #blengths + 4, width = max_length + 4, relative = 'win', zindex = 51, } end }
Any idea why? The function returns correctly.
hi @savchenko,
After carefully read your win_opts
function, I think it's trying to calculate current buffer list size (for example 8), and max buffer name length (for example 36). Then returns the 8
as the fzfx popup window's height, 36
as the fzfx popup window's width.
Is that correct?
@linrongbin16 , it returns a table with width
and height
set to maximum length of the buffer name and number of buffers respectively.
+4
is just for testing/safety to make sure we're not kissing the window border, likely will need to be re-adjusted based on the actual behaviour. As you can see in the original fzf.vim
function, it was empirically set to +17/+6
and it rendered perfectly sized every time.
hi @savchenko, current engine doesn't support real-time refresh the 'win_opts'.
for example, when 1st run FzfxBuffers
, the height is 8
, max buffer name length is 36
. (we have 8 buffers, and max buffer name length is 36).
in the 1st fzfx popup, if you press some 'ctrl-d' keys and delete some buffers, the 'win_opts' will not be calculate again and refresh the 1st fzfx popup.
but after you press esc
key and quit 1st popup, then run the 2nd FzfxBuffers
, now the height and width will be calculate by the current buffers status.
I will submit PR to support the 'win_opts' to be a function, but it still cannot support the real-time scenario when you press 'ctrl-d' key.
I will submit PR to support the 'win_opts' to be a function
This should be enough. I am not certain even if the original fzf.vim
supports real-time updates.
hi @savchenko , this feature is added in #517 and #520 , please pull latest main branch and have a try.
@linrongbin16 , tested. Works well.
Here is the resulting function, please feel free to use in the base distribution if you'd like:
win_opts = function()
local bufs_fn_len = {}
local max_len = 0
for _, buf_nr in ipairs(vim.api.nvim_list_bufs()) do
if vim.api.nvim_buf_is_valid(buf_nr) and vim.api.nvim_buf_is_loaded(buf_nr) then
local buf = vim.api.nvim_buf_get_name(buf_nr)
local buf_nm = vim.fn.expand(buf)
if buf_nm ~= "" then
buf_nm = vim.fn.substitute(buf_nm, vim.fn.getcwd(), "", "g")
buf_nm = vim.fn.substitute(buf_nm, vim.fn.expand("$HOME"), "~", "g")
table.insert(bufs_fn_len, string.len(buf_nm))
end
end
end
for _, len in ipairs(bufs_fn_len) do
max_len = math.max(max_len, len)
end
return {
height = #bufs_fn_len + 4,
width = max_len + 7,
relative = 'win',
zindex = 51,
}
end
The only caveat is that I explicitly calculate loaded buffers, which might result in buffers
returning more than we have accounted for. https://github.com/linrongbin16/fzfx.nvim/issues/522 would be fix this.
Buffer names are usually comparatively short and don't require a preview.
I have implemented it via
fzf.vim
ages ago:Would it be possible to have something like this in
fzfx.nvim
in Lua?