Konfekt / FastFold

Speed up Vim by updating folds only when called-for.
708 stars 24 forks source link

Prevent `w:lastfdm` from leaking into a new window for a different buffer #64

Closed tomtomjhj closed 3 years ago

tomtomjhj commented 3 years ago

Suppose I'm editing buffer 1 on window 1 with fdm=expr, b:lastfdm='expr', w:lastfdm='expr'. Then, I run :sp file to create window 2 and buffer 2 whose FileType does setl fdm=manual. But when a window is created for a new buffer, the current buffer during WinEnter is buffer 2, not 1. Here is the snippet to demonstrate it:

au WinNew      * unsilent echom 'WinNew' winnr() bufnr()
au WinEnter    * unsilent echom 'WinEnter' winnr() bufnr()
au BufWinEnter * unsilent echom 'BufWinEnter' winnr() bufnr()
au WinLeave    * unsilent echom 'WinLeave' winnr() bufnr()

Result:

WinLeave 1 1
WinNew 2 1
WinEnter 2 1
BufWinEnter 2 2

Because of this, the WinEnter autocmd sets w:lastfdm of window 2 to 'expr', which does not match the intended fdm=manual of the buffer 2. This makes the manual folds get removed when UpdateWin() is called, because it calls LeaveWin() that sets fdm to w:lastfdm (='expr').

To fix this issue, we should first classify WinEnter based on the events fired before/after it:

  1. right after WinNew, not followed by BufWinEnter (e.g. :sp)
  2. right after WinNew, before BufWinEnter for the same buffer (e.g. :sp %)
  3. right after WinNew, before BufWinEnter for a different buffer (e.g. :new, :sp file)
  4. right after WinLeave (e.g. <C-w><C-w>)

We only need to fix 3's behavior. The solution is to check if the bufnr() at WinEnter and BufWinEnter are different, and if that's the case, undo the effect of WinEnter by removing w:lastfdm.

Konfekt commented 3 years ago

Thank you very much. Sounds and looks sensible. BufEnter comes before BufWinEnter. Since we want to remove the erroneous w:lastfdm as soon as possible, it looks more appropriate an autocmd event.

tomtomjhj commented 3 years ago

That makes sense. Fixed.