Vim-go: All folds get closed on write

Created on 29 Jul 2015  Â·  39Comments  Â·  Source: fatih/vim-go

This is obviously highly annoying, having to re-expand whatever fold you need every time you write the buffer.

bug

Most helpful comment

@xh3b4sd folds are saved if you enable experimental mode with let g:go_fmt_experimental = 1

@oryband your plugin uses python to format the code. I'm explicitly not using any binding (ruby, lua, python, etc..) for compatibility. We only use pure vimscrirpt and so far it's all good. But we have an open issue to provide a python based formatter as an additional feature for those who wish it.

All 39 comments

also encounter this problem, hope it can be fixed soon

This bug was introduced with the fmt-in-write merge, which was created to
address the exponential slowdown when using setline() to update a buffer with
folds.¹

The GoFmt implementation before 99a1732e40e3f064300d544eebd4153dbc3c60c7 also
suffered the same problem of resetting folds since the buffer was truncated
before being rewritten.

Between these two commits, buffers were replaced line by line with setline(),
which kept fold information intact, albeit at an unbearable cost (2-5 seconds
per :GoFmt for medium/large buffers on my machine).

Even with the setline() implementation, however, if the output of gofmt
changed the number of lines (e.g. breaking a block into multiple lines), all
fold information below that change was also discarded.²

This is ultimately due to the fact that the fold system is line-based, even
with foldmethod=syntax. For instance, saving folds via :mkview with
set viewoptions=folds will reveal the ugly truth about the fragility of the
vim fold system.

There are a few options:

  1. Add the setline() implementation as an option for frequent users of vim
    folds. These users will suffer very slow :GoFmt calls since the existence
    of folds triggers the exponential branch of setline().
  2. Attempt to use :mkview to save and reload folds after updating the
    buffer. Initial testing suggests that this is unlikely to work very well.
  3. Write a custom routine that uses regexps or simple line matching + line
    numbers to save and restore folds.

None of these options are particularly palatable, but option 3 will probably
work if someone is willing to put in the time. It might be a good idea to
start with option 1 as a workaround until a solid fold-restoring solution is
implemented.

¹ https://github.com/fatih/vim-go/issues/459#issuecomment-124096485

² Effectively the whole file if you use goimports and an import is
added/dropped.

This problem annoys me. Thanks for the explanation and research in solutions. Understanding that, it makes me sad, because it seems to be very unlikely to be fixed soon.

If people don't mind auto-folding based on syntax, one could use
:set foldmethod=syntax

If the folds are too deep, one could change foldnestmax. For example, to only fold at the function level:
:set foldnestmax=1

To open a single fold under cursor: hit enter (or zo)
To open all folds under the cursor: zO
To close a single fold under cursor: zc
To close all folds under cursor: zC

To open all folds in the file: zR
To close all folds in the file: zM

Of course, we would lose creating manual folds, but this has worked for me.

update:
I believe my issue was different than the one stated. For me, all the folds were deleted on write.

This has been annoying me for a while too.

@Konfekt I'm a big fan of FastFold and since you know so much about vim's folding mechanism I was wondering if you had any ideas here?

I am not in the picture about what GoFmt does on BufWrite.

How about

autocmd BufWritePost *.go normal! zv

as a provisional work around?

I am not in the picture about what GoFmt does on BufWrite.

It runs an external tool to reformat the file, and then simply reloads the modified file with edit!. Of course this destroys any folds, which is quite annoying.

Oh, then give vim-stay a try, or save and load folds by mkview and Loadview. That's an intruuusive cmd then, this GoFmt.

One work-around to avoid this issue is to disable GoFmt: let g:go_fmt_autosave = 0
You can then run GoFmt manually at specific times via :GoFmt in vim (but you still loose all folds at this point).

However, an actual solution would be preferred of course. I'll give the vim-stay solution of @eapache a try.

Hi everyone. I'm going to work on this as my next issue. Thanks for the feedback. Unfortunately there is no easy way to update the content of a file in vim. There are multiple iterations of :GoFmt (check the history), each with its own problems. Right now :GoFmt is quite stable and works very well. Though, it has problems as seen in this issue.

My plan is to look at mkview based solution and see if that helps to fix our problem here. I'll let you know once I have a fix for it. Thanks!

Can you please try this PR: https://github.com/fatih/vim-go/pull/691, I've tried locally and for me it's saving/restoring folds + cursor positions without any problem so far.

@guns you said:

2. Attempt to use :mkview to save and reload folds after updating the
buffer. Initial testing suggests that this is unlikely to work very well.

In my tests (#691), it seems like it works without any problem. Did you encountered any kind of problem, any edge case that I'm not aware of?

I just tested #691. Works for me. Thanks :)

Just ran into this issue and tested the fix. Working well here so far. Tip for others eager to fix this with vim-plug:

Plug 'fatih/vim-go', { 'commit': '6c1cc914c35735768e54fc4ab0be900a9d62797b' } " fix folds

Thanks for being an awesome maintainer, fatih!

Edit: Hmm, seems like it now happens kind of rarely, but still sometimes.

@Garoth :+1: thanks for the quick tip

Thanks for all the feedback.

@fatih looks like this issue isn't resolved for me, even though I'm using latest vim-go version. Calling :GoFmt still folds everything.

you can see my .vimrc here: https://github.com/oryband/dotvim/blob/6c49a5d6eeb31f090e997534546f404bfa9462bf/.vimrc

I checked master and the issue is not solved for me. I used #691 all the time and everything was fine. Now back to master the issue is present again.

691 was effectively reverted by default in #745 although I believe there is still a vimrc flag to re-enable it.

Is there any progress on this issue? I am hitting this over and over again.

Update: I've switched to vim-autoformat, which takes care of code formatting for various languages, go included. It works ok there. Give it a try.

add this to your .vimrc to only use gofmt without goimports:

let g:formatters_go = ['gofmt_1', 'gofmt_2']  " disable goimports

@xh3b4sd folds are saved if you enable experimental mode with let g:go_fmt_experimental = 1

@oryband your plugin uses python to format the code. I'm explicitly not using any binding (ruby, lua, python, etc..) for compatibility. We only use pure vimscrirpt and so far it's all good. But we have an open issue to provide a python based formatter as an additional feature for those who wish it.

Setting let g:go_fmt_experimental = 1 resolves my issues with folds as well. Are there any major tradeoffs from using this feature? Just curious how much different this is from having it off.

@chancez see :help g:go_fmt_experimental. It is apparently slower and causes an issue on some vim versions. Works for me on v0.2.0, though folds still get closed if goimports needs to add an import. Without it, though, every save closes my folds.

@rcorre I just tried this on with a minimal working example and it doesn't work for me. I checked and I'm on commit 7fb9689.

mini.vimrc

set nocompatible
filetype plugin indent on
syntax enable
set foldmethod=syntax
set foldcolumn=2
set runtimepath^=~/vimfiles/bundle/vim-go
let g:go_fmt_experimental=1

Started up vim by vim -u mini.vimrc and then :e ~/test.go. Every write triggers a fold collapse. I checked and the changes from #691 are in vim-go (consistent with the commit I'm on). So, I'm confused. Would you be able to provide any feedback?

@fuzzybear3965 sorry for the long delayed response. I tried with your mini.vimrc and the behavior is still as I described above. I'm on commit aab6381

I'm on neovim, which could be different ...

I can confirm that this works on neovim but not on vim/gvim on my Windows 10 installation. Changing g:go_fmt_experimental from 0 <->1 has no effect on vim/gvim but has the exactly desired effect on neovim. Is it vim-go's goal to support neovim but not necessarily vim/gvim?

I can confirm with my Fedora 27 vim installation, this does not work by default. I need to set g:go_fmt_experimental = 1 to have the saves folded.

For what it's worth, I have to set g:go_fmt_experimental = 1 for the desired behavior (don't auto close folds on write).

g:go_fmt_experimental = 1 squad

the g:go_fmt_experimental = 1 fix stopped working for me when I updated today. currently on commit cf0b9c919ef1e6e312bc471495d989abb42a5eea

using gvim (2:8.0.1453-1ubuntu1) g:go_fmt_experimental = 1 doesn't work for me on with vim-go at 9a4f21e5343437bdb4619f19b48cbf6d5cb7755c

Anyone know does neovim still 'just work' with this fix?

@bhcleek Do you have any thoughts on this/ It seems to be back with g:go_fmt_experimental = 1. Sorry for tagging you if inappropriate, you just seemed really active in the commit history.

@xzys @bioe0007 @ayjayt I don't monitor closed issues closely. Please feel free to open a new issue with clear reproduction steps (if possible) if you're experiencing problems.

@ayjayt I am the right person to mention; I am the current maintainer of vim-go.

I have two systems that work perfectly with this .vimrc. The important settings are:

set foldmethod=syntax
set foldnestmax=1
let g:go_fmt_experimental = 1

Both systems are Arch, with latest packages:

powerline-vim 2.8.1-1
vim 8.2.1684-1
vim-ale 2.7.0-1
vim-gitgutter 708.c27bfab-1
vim-go 1.23-1
vim-indentline-git r214.5bf4903-1
vim-runtime 8.2.1684-1

However I installed yesterday a new desktop with the exact same packages, exact same versions, I updated the go binaries on all 3 systems so all 3 systems are the same... However on the new desktop, saving closes the fold.

I am going crazy. Am I missing something? How come let g:go_fmt_experimental = 1 works on two systems but not on the 3rd?

We might need to open a new pull request. I think this is still happening
with me, I think I ended up just turning folds off completely.

If you run :GoInstallBinaries and :GoUpdateBinaries which updates
vim-go's dependencies on the old systems, you might start getting the error?

I don't believe the current maintainer gets notifs for closed issues like
this.

"All the devil requires is acquiescence... not struggle, not conflict.
Acquiescence."

On Tue, Sep 15, 2020 at 6:40 PM goonix notifications@github.com wrote:

I have two systems that work perfectly with this .vimrc
https://gitlab.com/gun1x/dotfiles/-/blob/master/.vimrc. The important
settings are:

set foldmethod=syntax
set foldnestmax=1
let g:go_fmt_experimental = 1

Both systems are Arch, with latest packages:

powerline-vim 2.8.1-1
vim 8.2.1684-1
vim-ale 2.7.0-1
vim-gitgutter 708.c27bfab-1
vim-go 1.23-1
vim-indentline-git r214.5bf4903-1
vim-runtime 8.2.1684-1

However I installed yesterday a new desktop with the exact same packages,
exact same versions, I updated the go binaries on all 3 systems so all 3
systems are the same... However on the new desktop, saving closes the fold.

I am going crazy. Am I missing something? How come let
g:go_fmt_experimental = 1 works on two systems but not on the 3rd?

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/fatih/vim-go/issues/502#issuecomment-693016659, or
unsubscribe
https://github.com/notifications/unsubscribe-auth/AHHLRFMZAEZKTCZJK2TS2H3SF7UMBANCNFSM4BMGYJOQ
.

If you run :GoInstallBinaries and :GoUpdateBinaries which updates vim-go's dependencies on the old systems, you might start getting the error?

I already tried :GoInstallBinaries and :GoUpdateBinaries to upgrade binaries on the old systems, and I do not have the bug on the old system, but I do have the bug on the new one. All have the same packages.

I don't believe the current maintainer gets notifs for closed issues like this.

@bhcleek There is the notification :smile:

Feel free to open a new issue if you believe something is wrong with vim-go.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

derekchiang picture derekchiang  Â·  3Comments

surest picture surest  Â·  3Comments

svanharmelen picture svanharmelen  Â·  3Comments

orlangure picture orlangure  Â·  3Comments

groob picture groob  Â·  3Comments