kevinhwang91 / nvim-ufo

Not UFO in the sky, but an ultra fold in Neovim.
BSD 3-Clause "New" or "Revised" License
2.23k stars 44 forks source link

when using `zr` `zm` or `:set foldlevel=n` folds autoclose to that level after edit #62

Closed Frydac closed 2 years ago

Frydac commented 2 years ago

Neovim version (nvim -v | head -n1)

NVIM v0.7.2

Operating system/version

Manjaro Linux (updated yesterday)

How to reproduce the issue

cat mini.lua

-- Use Vim packages install the plugin, also work with some plugins manager such as packer.nvim
vim.o.packpath = '~/.local/share/nvim/site'
vim.cmd('packadd promise-async')
vim.cmd('packadd nvim-ufo')

-- Setting
vim.o.foldcolumn = '1'
vim.o.foldlevel = 99
vim.o.foldlevelstart = -1
vim.o.foldenable = true

local ufo = require('ufo')
ufo.setup()
vim.keymap.set('n', 'zR', ufo.openAllFolds)
vim.keymap.set('n', 'zM', ufo.closeAllFolds)

nvim --clean -u mini.lua

  1. create a new file with
    
    do
    do
        do
            -- line 1
            -- line 2
        end
    end
    end

do do do -- line 1 -- line 2 end end end


3. `:set foldlevel = 2`
4. open a closed fold with `zo`
5. go to insert mode, and go back to normal mode

### Expected behavior

The folds stays open

### Actual behavior

The fold autocloses

----

It seems to be related to the fix/workaround of https://github.com/kevinhwang91/nvim-ufo/issues/7 where it seems the folds that are open are only 'remembered' when the window foldlevel is larger than the open folds?

Not sure, maybe this is just the way ufo works, and can't be easily fixed?

Additionally, not changing the foldlevel when doing `zM` (openAllFolds) or `zR` (closeAllFolds) also breaks the `zr` and `zm` behavior as they seem to work by setting the foldlevel:

I tend to use folds as follows (in C++ code with lots foldlevels due to namespaces and classes)
- I close all folds with `zR`, which with default neovim sets the foldlevel to 0, but this doesn't happen  with `closeAllFolds`
- I open a few foldlevels with `zm` to see the function signatures I'm interested in. The default behavior is then that `zm` increased the foldlevel by 1. But because the foldlevel is still 99, it results in changing the foldlevel to the highest foldlevel in the buffer/window. So as a workaround I now set the foldlevel manually with `:set foldlevel=x` to what I need.
- Then I open the function I want to edit with `zO`. But this doesn't work now, because when the foldlevel is set to the foldlevel of the function, the fold will autoclose as soon as I go from insert mode to normal mode.
kevinhwang91 commented 2 years ago

It's limilition of foldmethod=manual which is driver level issue. I can provide the API like zR and zM as a workaround.

Frydac commented 2 years ago

Oh ok, thanks for the info, I see now that it is in the README.md under Usage (my bad.. sry) I didn't understand it when I read it, I guess I needed the above example/experimentation to understand vim folds a bit better to understand the issue.

If you ever decide to tackle this, I would definitely appreciate it.

I do think this is already such a cool plugin, the syntax highlighting in the folds are an absolute game-changer for usability, the main reason I didn't like folds before, and should be part of core (neo)vim imho. Great work, thanks!

kevinhwang91 commented 2 years ago

It's the duplicate of https://github.com/kevinhwang91/nvim-ufo/issues/49. I read this issue from my cell phone roughly just now. The new API only changes virtual foldlevel, the actual foldlevel will never change. Do you think it's worthwhile? I'm not clear your workflow, but zo, zO, zc, zC, zR and zM work fine with me.

kevinhwang91 commented 2 years ago

I do think this is already such a cool plugin, the syntax highlighting in the folds are an absolute game-changer for usability, the main reason I didn't like folds before, and should be part of core (neo)vim IMHO.

The core is hard to imp syntax fold, I have read the source code so I release this plugin. ufo is the best solution for neovim fold AFAIK, never block, extremely fast.

Frydac commented 2 years ago

It's the duplicate of #49. I read this issue from my cell phone roughly just now. The new API only changes virtual foldlevel, the actual foldlevel will never change. Do you think it's worthwhile? I'm not clear your workflow, but zo, zO, zc, zC, zR and zM work fine with me.

yes, zo, zO, zc, zC, zR and zM have the intended effect. However, zr and zm work with the actual foldlevel (afaik), they have an effect: they set the actual foldlevel and the folds close or open accordingly, but they also cause 2 issues in my experience:

  1. when using zr and zm, then the actual foldlevel can get smaller than the highest foldlevel of the buffer, any fold the user opens that has a higher level than the current actual foldlevel (e.g. with zO) will autoclose when editing (because of the foldmethod=manual limitation iirc). I think that the person of #49 maybe didn't notice this? Or maybe I'm wrong somehow?
  2. zr and zm don't have the same behavior when used after zR and zM (as I tried to explain in the 3 bulletpoints in my original post).
    • example default behavior: first zR will close all folds and set foldlevel to 0, then zm will open 1 foldlevel and set foldlevel to 1.
    • example behavior when using closeAllFolds : first zR will close all folds and foldlevel remains 99, then zm opens all folds to the highest foldlevel and the actual foldlevel will be set to the highest foldlevel. (I would like to be able to open all folds one level at a time after using zR, which I don't think is possible now)

These issues makes zr and zm not useful anymore imho.

I don't fully understand how folds and ufo work, but maybe the solution could be that zm and zr also get mapped to API functions that work with the virtual foldlevel and don't depend on or change the actual foldlevel?

kevinhwang91 commented 2 years ago

Yes, zr and zm make non-sense if using ufo, I want to know the workflow why ufo needs to be compatible with native zr and zm which is hard to imp in ufo.

From example 2 you provided, I think you need to change the virtual foldlevel to a specified level, like type v:count z your_key. For now, 0 for closeAllFolds and max for openAllFolds. This feature is not hard to imp, but incremental action like native zr and zm are not, because ufo don't maintain the virtual foldlevel and no way to maintain it correctly.

Frydac commented 2 years ago

I tried to make a video of the main usecase I use this for, it is not a super important usecase, but I do encounter it regularly in my work, and I seem to default to this behavior.

I added some pseudo C++ code where there are 2 nested namespaces then it has a few classes with a bunch of functions, these functions live at the same foldlevel, but are in different parent folds. This is the condition where this usecase is most effective imo, things at the same foldlevel but in different parent folds.

Without moving the cursor I can close all the folds zR, then use a few zm to open a few levels of folds until the functions of both classes become easily visible.

https://user-images.githubusercontent.com/2588526/183250481-de2f3606-c21a-4b08-97b0-98abc128c393.mp4

Doing this without zm takes more keystrokes to accomplish.

I've been experimenting a bit, and it seems that it is possible to make a visual selection and then do open fold zo, something like ggvGzo which accomplishes similar behavior to the above usecase, and might make a usable mapping for zm for this usecase. ggvGzc doesn't work as expected though, it closes the top fold, and after that ggvGzo also doesn't work like that anymore, but a zM and then restarting does work. Not the same, but at least better than going to each class and opening it until I can see the functions.

kevinhwang91 commented 2 years ago
    vim.keymap.set('n', 'zm', require('ufo').closeFoldsWith, {})

eg. zm, 1zm, 2zm and so on.

1zm is extremely useful for methods in a class. Thank you for pushing me.