Closed lu5je0 closed 10 months ago
It's the limitation of ufo. To render folded lines use extmark which is buffer related. No way to make the same buffer with different extmarks.
I cannot help with implementation but can offer some info from my own experiments that may help, below sample code using "ephemeral" extmark.
--vim -u NONE
--e <THIS_FILE>
--so %
--fold should be setup
--vsp #to show buffer in another window
vim.cmd('syntax on')
vim.treesitter.start()
vim.opt.splitright = true
vim.opt.splitbelow = true
vim.opt.foldlevel = 99
vim.opt.foldlevelstart = 99
vim.opt.foldenable = true
vim.opt.number = true
vim.opt.foldcolumn = '1'
vim.opt.foldmethod = 'expr'
vim.opt.foldexpr = 'v:lua.vim.treesitter.foldexpr()'
vim.opt.foldtext = ''
vim.opt.fillchars = {
fold = ' '
}
vim.cmd([[au WinNew,BufWinEnter * exec 'normal! zx'|exec 'normal! zR']])
vim.cmd('normal! zx')
vim.cmd('normal! zR')
local ns = vim.api.nvim_create_namespace('')
local function get_or_create_virtext(bufnr, lnum)
--can add more complex hl with treesitter and possibly cache results here and elsewhere
local text = vim.api.nvim_buf_get_lines(bufnr, lnum - 1, lnum, false)[1] or ''
return { { text .. ' …', 'Folded' } }
end
vim.api.nvim_set_decoration_provider(ns, {
on_win = function(_, winid, bufnr, topline, botline_guess)
vim.api.nvim_win_call(winid, function()
local first, last = vim.fn.line('w0'), vim.fn.line('w$')
for lnum = first,last do
local foldline = vim.fn.foldclosed(lnum)
--range w0 to w$ my include lines that are hidden in folds, so skip those
if foldline == lnum then
local fold_virttext = get_or_create_virtext(bufnr, lnum)
--the key thing here is "ephemeral",
--which make this extmark only visible on the current window
--and redrawn each cycle
--another window with same buffer will have different extmarks
vim.api.nvim_buf_set_extmark(bufnr, ns, lnum - 1, 0, {
end_row = lnum - 1,
end_col = 0,
virt_text = fold_virttext,
virt_text_win_col = 0,
priority = 100,
hl_mode = 'combine',
ephemeral = true,
})
end
end
end)
end,
})
https://github.com/kevinhwang91/nvim-ufo/assets/639806/510b00be-043e-4731-b17e-a96ca46b361b
I cannot help with implementation but can offer some info from my own experiments that may help, below sample code using "ephemeral" extmark.
--vim -u NONE --e <THIS_FILE> --so % --fold should be setup --vsp #to show buffer in another window vim.cmd('syntax on') vim.treesitter.start() vim.opt.splitright = true vim.opt.splitbelow = true vim.opt.foldlevel = 99 vim.opt.foldlevelstart = 99 vim.opt.foldenable = true vim.opt.number = true vim.opt.foldcolumn = '1' vim.opt.foldmethod = 'expr' vim.opt.foldexpr = 'v:lua.vim.treesitter.foldexpr()' vim.opt.foldtext = '' vim.opt.fillchars = { fold = ' ' } vim.cmd([[au WinNew,BufWinEnter * exec 'normal! zx'|exec 'normal! zR']]) vim.cmd('normal! zx') vim.cmd('normal! zR') local ns = vim.api.nvim_create_namespace('') local function get_or_create_virtext(bufnr, lnum) --can add more complex hl with treesitter and possibly cache results here and elsewhere local text = vim.api.nvim_buf_get_lines(bufnr, lnum - 1, lnum, false)[1] or '' return { { text .. ' …', 'Folded' } } end vim.api.nvim_set_decoration_provider(ns, { on_win = function(_, winid, bufnr, topline, botline_guess) vim.api.nvim_win_call(winid, function() local first, last = vim.fn.line('w0'), vim.fn.line('w$') for lnum = first,last do local foldline = vim.fn.foldclosed(lnum) --range w0 to w$ my include lines that are hidden in folds, so skip those if foldline == lnum then local fold_virttext = get_or_create_virtext(bufnr, lnum) --the key thing here is "ephemeral", --which make this extmark only visible on the current window --and redrawn each cycle --another window with same buffer will have different extmarks vim.api.nvim_buf_set_extmark(bufnr, ns, lnum - 1, 0, { end_row = lnum - 1, end_col = 0, virt_text = fold_virttext, virt_text_win_col = 0, priority = 100, hl_mode = 'combine', ephemeral = true, }) end end end) end, })
fold_test._rec.mp4
Thanks for the helps. Unfortunately, ufo uses non-ephemeral
extmark to cache fold info and will make perf regression without cache.
sure perhaps you can wait for nvim_win_set_extmark
to be implemented here: https://github.com/neovim/neovim/issues/19654
nightly with the latest codebase of ufo should work.
Neovim version (nvim -v | head -n1)
NVIM v0.9.0
Operating system/version
macOS 13.3.1
How to reproduce the issue
cat mini.lua
nvim --clean +'so mini.lua'
1. 2. 3. ...
Expected behavior
The fold text is only displayed in the window that closes the fold.
Actual behavior