nvim-ufo
nvim-ufo copied to clipboard
High level folds wrongly folded
Neovim version (nvim -v | head -n1)
head
Operating system/version
macOS 12.4
How to reproduce the issue
When executing vim.lsp.buf.format()
the high-level folds are broken i.e. the high-level fold includes other lines that shouldn't be in it. Opening/closing the fold brings back the good folding. Here's the video showing the issue:
https://user-images.githubusercontent.com/6879030/181639721-54edb378-942a-44b3-b466-5a67625f0a05.mov
setup:
vim.o.foldlevel = 99
vim.o.foldlevelstart = 99
vim.o.foldenable = true
require("ufo").setup({
open_fold_hl_timeout = 0,
-- enable_fold_end_virt_text = true,
provider_selector = function(bufnr, filetype)
return 'treesitter'
end
})
vim.keymap.set("n", "zR", "<cmd> lua require('ufo').openAllFolds()<cr>")
vim.keymap.set("n", "zM", "<cmd> lua require('ufo').closeAllFolds()<cr>")
NOTE: the bug also happens with indent
provider.
Expected behavior
The folds to be correctly represented after the format is being done.
Actual behavior
The folds are miss-calculated.
Fixted
@kevinhwang91 the issue still occurs, it isn't fixed with latest commit.
UFO_LOG=info nvim
and provide the log. BTW, what's the formater you use?
Will provide the log 👍🏻 I'm using sumneko_lua formatter in this case, but also happens with black (null-ls) formatter. BTW I remember having this issue with default tree-sitter foldexpr, it could be something with my config, but I was checking autocmd
s I have in my set-up, and nothing should affect the problem.
log:
[22-07-29 09:12:42] [INFO] manager.lua:195 : apply fold ranges: { {
endLine = 3,
startLine = 1
} }
[22-07-29 09:12:42] [INFO] manager.lua:196 : apply fold rowPairs: {}
[22-07-29 09:12:48] [INFO] manager.lua:195 : apply fold ranges: { {
endLine = 3,
startLine = 1
} }
[22-07-29 09:12:48] [INFO] manager.lua:196 : apply fold rowPairs: { 3 }
[22-07-29 09:12:51] [INFO] manager.lua:195 : apply fold ranges: { {
endLine = 3,
startLine = 1
} }
[22-07-29 09:12:51] [INFO] manager.lua:196 : apply fold rowPairs: {
[3] = 5
}
file:
-- smart dd
function smart_dd()
return ""
end
vim.keymap.set("n", "dd", smart_dd, { noremap = true, expr = true })
reproduced. I will fix it later.
After debugging, this is nvim_buf_set_text
issue called from lua vim.lsp.buf.format()
, you can disable ufo and then open the text you provided, and then:
-
2,4fold
-
5delete
-
lua vim.lsp.buf.format()
line 4-6 are folded. If ufo is enabled, will add this range to extmark and apply folds with these additional ranges.
https://github.com/neovim/neovim/issues/19571
@kevinhwang91 do you have in-mind any workaround that I can use, to make the folds stable? The one that comes to my mind is saving and restoring the view – before and after the formatting, but I'm not sure if that's safe as the folded lines could change.
saving and restoring the view
: is this issue existing for now?
before and after the formatting
: There're two format ways, one is full edit, and another is local range edit.
As a workaround, ufo can delete any folds manually if the range is edited. After formatting:
- Full edit: the fold will be always opened.
- Local range edit: local fold will be always opened, others will keep the original status.
~~This workaround I don't think is good, which must delete fold after every change will cause perf regression while editing.~~
AFAIK, sumneko_lua
formatter always does full edit for a buffer that doesn't diff content. You should use lua vim.lsp.buf.range_formatting
instead.
A full edit will always open all folds, please use a range format. I think null-ls
can do this. Most language server has diff content before generating textEdit[]
even for textDocument/formatting
interface.
Got it, thanks for the input! I hope the issue gets fixed upstream soon 🤞🏻
FYI: https://github.com/fannheyward/coc-pyright/blob/bae9ce6dce09c67fcd0d15394864553c70951d50/src/formatters/black.ts#L5-L31 https://github.com/fannheyward/coc-pyright/blob/bae9ce6dce09c67fcd0d15394864553c70951d50/src/common.ts#L199-L228
https://github.com/kevinhwang91/nvim-ufo/commit/65af01fe5efecf005dc33a6d6afe4469c5be467c it does fix the issue I'm having, looks neat so far 👌🏻 the only drawback is that it would open all the folds after the line that has been deleted, but that's an edge-case we're solving anyway.
Great, AFAIK, https://github.com/mattn/efm-langserver will diff result to generate multiple textEdit
I think upstream can't keep the folds while the lines are changed. ufo will clear the folds if the lines changed to make sure that the folds are correct. Users should use a range edit instead of a full edit.