junegunn / goyo.vim

:tulip: Distraction-free writing in Vim
MIT License
4.49k stars 115 forks source link

Not allowed to change the window layout in this autocmd when quitting Goyo #275

Closed dgsiegel closed 1 year ago

dgsiegel commented 1 year ago

With Vim 9 (9.0.963) I get the following error when quitting Goyo with :q:

Error detected while processing WinEnter Autocommands for "<buffer=3>"..function <SNR>10_blank[3]..<SNR>10_goyo_off:
line   38:
E1312: Not allowed to change the window layout in this autocmd
Press ENTER or type command to continue

It probably comes out of this recent patch: https://github.com/vim/vim/commit/d63a85592cef0ee4f0fec5efe2f8d66b31f01f05

pbwn commented 1 year ago

i have this issue on my ms windows 10 computer (vim v9.0) but not on my mx linux computer (version?), i don't know if that's relevant but probably confirms it's a recent issue

SivanC commented 1 year ago

I am getting the same issue with on linux with vim 9.0 and most recent Goyo. Using :x or :q to exit a Goyo window gives the same error and requires the command to be entered several times before exiting vim, although the :Goyo command still works properly to exit the Goyo window.

pbwn commented 1 year ago

... although the :Goyo command still works properly to exit the Goyo window.

i have started using this solution ie :Goyo, but do you find that it throws you to a different buffer? ie if i have several files open and i am looking at the contents of file A, i leave goyo with :Goyo and i am then looking at the contents of file B. If you're working quickly you can run program B instead of the intended A

SivanC commented 1 year ago

@pbwn I just tried to replicate that and could not. Using the :Goyo command works as I would expect when I have two tabs open. However, within a Goyo window if I try to switch tabs using gt it just exits the Goyo window while remaining on the current tab/buffer.

SivanC commented 1 year ago

Additionally, I have noticed that the reason the quit command has to be repeated several times before exiting Vim in my experience is actually because of the creation of 4 scratch buffers when exiting the window, which I did not pick up on before.

griffinli commented 1 year ago

I'm getting this issue as well.

junegunn commented 1 year ago

I can reproduce it. Any idea how we can fix this?

A workaround is to use :Goyo (or :Goyo!) instead of :q.

griffinli commented 1 year ago

Yeah — I'm using that workaround but it makes me do :Goyo (or ,z in my case) and then :q, rather than being able to directly :wq. I don't know how to fix it but if anyone else knows please chip in

SivanC commented 1 year ago

It probably comes out of this recent patch: https://github.com/vim/vim/commit/d63a85592cef0ee4f0fec5efe2f8d66b31f01f05

Just checked and can confirm that the patch before (906) does not have this issue, it looks like the added window_layout_lock() function that was added raises an error when attempting to resize/quit the window while it is locked,. The function that uses window_layout_lock()is may_trigger_winscrolled() in window.c in the vim code. The reason it was added is to be able to restore windows after WinScrolled is triggered. Not sure why it only triggers when Goyo is exited with :q and not Goyo, or when the window is resized in other ways.

SivanC commented 1 year ago

The error points to the following block of code which I don't really understand conceptually, but maybe someone could give more context?:

if tabpagenr() == 1
    tabnew
    normal! gt
    bd
  endif
  tabclose
  execute 'normal! '.s:orig_tab.'gt'
  if winbufnr(0) == goyo_orig_buffer
    " Doesn't work if window closed with `q`
    execute printf('normal! %dG%d|', line, col)
  endif
SivanC commented 1 year ago

@junegunn Hi just wanted to follow up as I'm looking into fixing this bug, I understand (I think?) that the above code block is supposed to delete the four scratch buffers that are created as boundaries for the window, and each line by itself makes sense to me, but I don't really understand the logic and what exactly is going on as a whole that makes this work, would you be able to give a quick explanation? Thanks!

junegunn commented 1 year ago

I could work around the limitation by enqueuing a s:goyo_off call using feedkeys. It is fixed for me, but let me know if you run into any problems.

@SivanC The first part of the above code block handles an exceptional situation where the tab for Goyo is the only one left in Vim. e.g. vim +Goyo +1tabclose. Without tabnew, you will run into E784: Cannot close last tab page. The rest of the code brings you back to the original position after closing Goyo tab.