lambdalisue / vim-fern

🌿 General purpose asynchronous tree viewer written in Pure Vim script
MIT License
1.29k stars 49 forks source link

Buffer content is modified unexpectedly after 'rename' action when foldmethod=expr is used #331

Closed timsofteng closed 3 years ago

timsofteng commented 3 years ago

Hey. When I rename file and try to open it than fern open just empty buffer. But if I try to open it second time it opens. Look at the screencast please.

https://user-images.githubusercontent.com/51912173/115755929-8c610800-a3a6-11eb-966e-2daffc025c81.mp4

lambdalisue commented 3 years ago

Please write step by step procedure to reproduce the situation.

timsofteng commented 3 years ago
  1. Open fern.
  2. Change name of some not empty file.
  3. Press :w.
  4. Open this file. It will be empty buffer.
lambdalisue commented 3 years ago

I could not reproduce. Please make a minimal vimrc to reproduce.

lambdalisue commented 3 years ago

https://user-images.githubusercontent.com/546312/115907414-cb28b800-a4a3-11eb-9d66-2328ec979b4d.mp4

https://user-images.githubusercontent.com/546312/115907423-cebc3f00-a4a3-11eb-9e78-d9fcbb775d19.mp4

windwp commented 3 years ago

Hi this bug happen to me i use

" first i open fern
:Fern . -drawer -reveal=% -toggle<CR>
" then rename with
  nmap <buffer> cw <Plug>(fern-action-rename:split)

" after i press :w<cr> it will override the content to my current file open.
" I think it should override to my fern drawner buffer.

" sometime it work perfect but sometime this bug happen to me.

https://user-images.githubusercontent.com/7578110/116677018-e595f080-a9d1-11eb-9366-a1aa2394309d.mp4

lambdalisue commented 3 years ago

Please make a minimal vimrc and minimal descriptive steps to reproduce. https://github.com/lambdalisue/fern.vim/wiki/Minimal-vimrc#with-native-vimneovim

windwp commented 3 years ago

https://gist.github.com/windwp/be22ae313538e1d6743de0d21dfaadeb hi it is my vimrc.min the first time I press <c-b> rename with cw and save <c-s>. It work correct . I close fern with <c-b> and reopen fern again with<c-b> on second time it override my buffer.

https://user-images.githubusercontent.com/7578110/116766278-d9527780-aa53-11eb-92c4-7bb30db0d7cf.mp4

Thank.

lambdalisue commented 3 years ago

I'm sorry but I don't think it's minimal. Please make it minimal.

windwp commented 3 years ago

https://gist.github.com/windwp/be22ae313538e1d6743de0d21dfaadeb I update it It still happen on the second time rename.

lambdalisue commented 3 years ago

Thanks. It seems minimal enough 👍 I'll try it on my environment within few days but let me know your environment in case (OS, Vim or Neovim? and which version or etc.)

lambdalisue commented 3 years ago

Thanks. I could reproduce the issue. I'll investigate it.

lambdalisue commented 3 years ago

It seems foldmethod=expr is the reason. It happens on Vim (8.2.2681) and Neovim (0.5.0-dev)

vimrc

if exists('+compatible') && &compatible
  set nocompatible
endif

" Disable Vim's native pack feature
set packpath=

" Clone https://github.com/lambdalisue/fern.vim in somewhere
" and specify that directory to the below
"
set runtimepath^=~/ghq/github.com/lambdalisue/fern.vim

filetype plugin indent on
syntax on
"----------------------------------------------------------------

" Add extra settings here to reproduce the issue...
set foldmethod=expr

"----------------------------------------------------------------
echomsg "Custom minimal vimrc has loaded"

procedure

  1. nvim -u ~/.vim/vimrc.min
  2. Open fern by :Fern . -drawer
  3. Close fern by :q
  4. Open fern by :Fern . -drawer
  5. Move cursor on README.md then hit R
  6. Rename to Hello.md then :w

https://user-images.githubusercontent.com/546312/116803675-c1165180-ab54-11eb-98d6-147c1788b565.mp4

lambdalisue commented 3 years ago
                        *'foldexpr'* *'fde'*
'foldexpr' 'fde'    string (default: "0")
            local to window
    The expression used for when 'foldmethod' is "expr".  It is evaluated
    for each line to obtain its fold level.  See |fold-expr|.

    The expression will be evaluated in the |sandbox| if set from a
    modeline, see |sandbox-option|.
    This option can't be set from a |modeline| when the 'diff' option is
    on or the 'modelineexpr' option is off.

    It is not allowed to change text or jump to another window while
    evaluating 'foldexpr' |textlock|.

So fern might update buffer while foldexpr is running?

windwp commented 3 years ago

yeah i think it is a problem i set it because nvim-treesitter use it to fold.

lambdalisue commented 3 years ago

I'm not sure but it seems find_win_for_curbuf() does NOT change the curwin on our case while

  1. Using nvim_buf_set_lines on https://github.com/lambdalisue/fern.vim/blob/master/autoload/fern/internal/buffer.vim#L8 fix issue on Neovim
  2. Changing current window prior to https://github.com/lambdalisue/fern.vim/blob/master/autoload/fern/internal/buffer.vim#L8 fix issue on Vim

I'm trying to create a minimal reproducing procedure to report this as a bug on Vim/Neovim but it's quite difficult....

lambdalisue commented 3 years ago

bufhidden=wipe on fern buffer solve this issue somehow. Of course., it cannot be a solution for this issue while bufhidden=wipe has a lot of side effects.

windwp commented 3 years ago

I use setlocal foldmethod=manual to fern and fern-replacer and it work. Thank.

lambdalisue commented 3 years ago

OK. I've worked on this for more than 4 hours but I couldn't find a way to reproduce the same issue without fern.vim to report it on Vim/Neovim... So I gave up on the solution that @windwp showed.


What I've founds are

But it seems above conditions are not enough...

I tried with something like...

if exists('+compatible') && &compatible
  set nocompatible
endif

" Disable Vim's native pack feature
set packpath=

filetype plugin indent on
syntax on
"----------------------------------------------------------------

" Add extra settings here to reproduce the issue...
set foldmethod=expr

function! Test() abort
  edit A
  vsplit | edit B
  setlocal buftype=nofile bufhidden=hide
  close
  vsplit | edit B
  wincmd p
  split | edit C
  setlocal buftype=acwrite bufhidden=wipe
  autocmd BufWriteCmd <buffer> call s:BufWriteCmd()
endfunction

function! s:BufWriteCmd() abort
  call timer_start(0, { -> setbufline('B', 1, ['Hello']) })
endfunction

call Test()

"----------------------------------------------------------------
echomsg "Custom minimal vimrc has loaded"

If Hello appears on buffer A or C, that mean the script reproduce the issue.

lambdalisue commented 3 years ago

Fixed by #334. Thanks for detailed report and solution @windwp