Open mattmartini opened 1 year ago
The error also does not occur on MacVim 9.0.472
I'm seeing the same behavior. This started for me after an upgrade from MacOs 12 to 13 (Ventura). I would love to solve this, so will add what I've found so far.
I suspect this issue is related to a recent change in the way auto commands are processed. In this discussion Bram essentially says "you can no longer close your current buffer from within an autocmd". To confirm my suspicion, I used :9verbose q
instead of simply :q
to see debug print. This shows
E1312: Not allowed to change the window layout in this autocmd
So it seems to me we need to find a way in vimscript to quit the current buffer without using an autocmd
?
My current workaround is to use :tabc
rather than :q
, but this is far from ideal (muscle memory is hard to change).
vim 9.0.1200 on macOS 13.1 (22C65) (Ventura)
vim 8.2.4919 on ubuntu 22.04.1 LTS (Jammy Jellyfish)
Matt,
I added to the discussion you referenced above, asking if Gary J found a solution/work around. [because I am a new member to the group, my message is moderated and may not show up right away]. I'm hoping that he found a way to use SafeState or some other method which we could employ.
Matt
Matt,
Gary responded with a few possible solutions. I will give them a try and report what works.
Matt
Using:
call feedkeys(":tabc\
works, however the NERDTree window in all the other tabs becomes wide.
I was trying to use:
execute 'silent vertical resize ' . g:NERDTreeWinSize
which works on the commandline, to resize the window, but I am not sure what function to put it into.
call timer_start(1, {-> execute('tabc') })
also works (and might avoid a race condition) yet it has the same problem of the NERDTree window resizing to wide.
Here is the work-around I put together. It works pretty well.
fun! s:CloseIfOnlyNerdTreeLeft()
" Only take action when we are in NERDTree window, and no more window
" with normal buffer open.
if exists("t:NERDTreeBufName") && bufwinnr(t:NERDTreeBufName) == winnr() && s:NextNormalWindow() == -1
if tabpagenr('$') == 1
" Before quitting Vim, delete the buffer so that the '0 mark
" is correctly set to the previous buffer. This avoids NERDTree
" buffer being the last displayed buffer if Vim fails to quit
" due to the last file in the argument list has not been edited
" yet. Also disable autocmd on this command to avoid unnecessary
" autocmd nesting.
if winnr('$') == 1
noautocmd bdelete
endif
" Quit as usual, we have autocmd nesting open, so this command
" will trigger other plugin window's quiting behavior. If we are
" quiting Vim, our current buffer is successfully reset to the
" last file buffer, no need to warry about failure.
quit
else
call feedkeys(":tabc\
Nice work @mattmartini! I'm so happy to have vim-nerdtree-tabs
back to functional! I futzed with this earlier in the week with no luck, so I appreciate your work.
Your solution didn't exactly work for me, but led me to one that does. For some reason, the feedkeys
command causes weird side effects, so I replaced it with the start_timer
version. Also, I added a wincmd w
so my focus ends up in the next buffer's window rather than the NerdTree window. Here is what I am using. I will post back if I run into issues or modify it more.
fun! s:CloseIfOnlyNerdTreeLeft()
if exists("t:NERDTreeBufName") && bufwinnr(t:NERDTreeBufName) != -1 && winnr("$") == 1
if has('patch-9.0.907')
" Vim forbids closing the window inside an autocommand
" Ref: https://groups.google.com/g/vim_dev/c/Cw8McBH6DDM?pli=1
" So let's do it afterwards. Solution came from @mattmartini
" Ref: https://github.com/jistr/vim-nerdtree-tabs/issues/102
call timer_start(1, {-> execute('q') }) " close buffer after we exit autocmd
call timer_start(20, {-> execute('vertical resize 31') }) " window sizing is goofed up, so fix it
call timer_start(25, {-> execute('wincmd w') }) " shift focus from NerdTree window to buffer window
else
q
endif
endif
endfun
Thanks for your addition of wincmd w !!
On Feb 1, 2023, at 5:43 PM, Matt Jeffery @.***> wrote:
Nice work @mattmartini https://github.com/mattmartini! I'm so happy to have vim-nerdtree-tabs back to functional! I futzed with this earlier in the week with no luck, so I appreciate your work.
Your solution didn't exactly work for me, but led me to one that does. For some reason, the feedkeys command causes weird side effects, so I replaced it with the start_timer version. Also, I added a wincmd w so my focus ends up in the next buffer's window rather than the NerdTree window. Here is what I am using. I will post back if I run into issues or modify it more.
fun! s:CloseIfOnlyNerdTreeLeft() if exists("t:NERDTreeBufName") && bufwinnr(t:NERDTreeBufName) != -1 && winnr("$") == 1 if has('patch-9.0.907') " Vim forbids closing the window inside an autocommand " Ref: https://groups.google.com/g/vim_dev/c/Cw8McBH6DDM?pli=1 " So let's do it afterwards. Solution came from @mattmartini " Ref: https://github.com/jistr/vim-nerdtree-tabs/issues/102 call timer_start(1, {-> execute('q') }) " close buffer after we exit autocmd call timer_start(20, {-> execute('vertical resize 31') }) " window sizing is goofed up, so fix it call timer_start(25, {-> execute('wincmd w') }) " shift focus from NerdTree window to buffer window else q endif endif endfun — Reply to this email directly, view it on GitHub https://github.com/jistr/vim-nerdtree-tabs/issues/102#issuecomment-1412841300, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAAM6OTNBP56LG3M4J7LJD3WVLRJJANCNFSM6AAAAAAUGWWMUA. You are receiving this because you were mentioned.
@mjeffe I'm getting E930: Cannot use :redir inside execute()
with vim 9.0 1-1302 with your solution. :( Also the timings for my setup vary. Here's my customized version:
fun! s:CloseIfOnlyNerdTreeLeft()
if exists("t:NERDTreeBufName") && bufwinnr(t:NERDTreeBufName) != -1 && winnr("$") == 1
if has('patch-9.0.907')
" Vim forbids closing the window inside an autocommand
" Ref: https://groups.google.com/g/vim_dev/c/Cw8McBH6DDM?pli=1
" So let's do it afterwards. Solution came from @mattmartini
" Ref: https://github.com/jistr/vim-nerdtree-tabs/issues/102
call timer_start(1, {-> execute('q', 'silent!') }) " close buffer after we exit autocmd
call timer_start(100, {-> execute('vertical resize 31', 'silent!') }) " window sizing is goofed up, so fix it
call timer_start(250, {-> execute('wincmd w', 'silent!') }) " shift focus from NerdTree window to buffer window
else
q
endif
endif
endfun
@jack12816, my version has been working well for me. Does it work for you with the longer timer_start()
waits? If not, be sure to post back if you find a solution.
@Jack12816 God, your code save my life, finally
I've been plagued by this problem for literally years. Thank you guys so much for tracing this down! @mjeffe's solution works great!
I'm still getting this error unfortunately:
Error detected while processing WinEnter Autocommands for "*"..function <SNR>127_CloseIfOnlyNerdTreeLeft:
line 4:
E1312: Not allowed to change the window layout in this autocmd
But it's infinitely better dismissing one error message versus having all my tab sizes messed up!
Maybe I did something wrong with that function? Right now I'm commenting out the original function in https://github.com/jistr/vim-nerdtree-tabs/blob/07d19f0299762669c6f93fbadb8249da6ba9de62/nerdtree_plugin/vim-nerdtree-tabs.vim#L337 and replacing it with the patch.
@JonDum the error message you are seeing is the original error message that we encountered, so it makes me suspect the patched function is not actually running. To answer your question, yes I simply replaced the CloseIfOnlyNerdTreeLeft()
function in ~/.vim/bundle/vim-nerdtree-tabs/nerdtree_plugin/vim-nerdtree-tabs.vim
with my patched version.
You might try removing the if has('patch-9.0.907')
check. Perhaps that patch version is not being detected correctly. You could also try increasing the timer_start
times like @Jack12816 and @mattmartini have above. I used shorter wait times because my machines seem to run quickly enough and it prevents the screen flashing. So the combined suggestions would look like this
fun! s:CloseIfOnlyNerdTreeLeft()
if exists("t:NERDTreeBufName") && bufwinnr(t:NERDTreeBufName) != -1 && winnr("$") == 1
call timer_start(1, {-> execute('q') }) " close buffer after we exit autocmd
call timer_start(200, {-> execute('vertical resize 31') }) " window sizing is goofed up, so fix it
call timer_start(250, {-> execute('wincmd w') }) " shift focus from NerdTree window to buffer window
endif
endfun
I'm a big dummy it turns out. Kinda. 😅
I had figured as much about the patching and that's what I had done as well! I even ran rg -uuu CloseIfOnlyNerdTreeLeft
in ~/.vim
to look for any other occurrences of that function. Notta. I added some echom
calls in the function and they didn't show up. So now I'm really puzzled. I deleted it entirely and still got the error message! What the heck? I then sifted through :verbose function
and... boom there's the culprit. It turns out I actually had a duplicate function in my .gvimrc
! I can't even remember the last time I opened .gvimrc
haha
I'm guessing I had it in there from before it was even added into nerd-tree-tabs!
I was curious how long ago this was so I did a little digging. I found this issue from twelve years ago that matches the function I had.
It wasn't until six months later that auto close was added to nerd-tree-tabs via https://github.com/jistr/vim-nerdtree-tabs/commit/cefef278c2f0263a9d86bfc6a64d8fbf3c8d962f so I guess I had that lingering there as a duplicate all this time! Ain't software development neat.
Anyways it's all working now and my god is un-exaggeratedly life changing. Thanks again guys! 😆
@JonDum glad you figured it out! I was pretty distressed as well when vim-nerdtree-tabs
quit working, so I'm really glad that together we have been able to keep it alive. Thanks for posting back, so we have a record.
Also impacted. Debian Bookworm. vim 9.0.1499.
Thank you guys so much for providing a workaround.
Not proficient in vim tweaking, I figured from @JonDum's comment above I could paste that function in my .vimrc but it didn't work. It works, however, if I patch the plugin file itself as instructed in @mjeffe's comment above.
Obviously, it would be nice if this was fixed "upstream" but I understand much too few of the internals to have an idea what that implies.
Issue:
While NERDTree is open, if there is more than one open tab and you close a tab (
:q
) the following error is reported:After acknowledging the error, the buffer in the tab is replaced by a full width NERDTree and NERDTree becomes about 80% width in all other open tabs.
If there is only one tab open then
:q
closes that tab and vim quits.This seems to be caused by the function
CloseIfOnlyNerdTreeLeft
innerdtree_plugin/vim-nerdtree-tabs.vim
specifically:Similarly:
In the NERDTree issue https://github.com/preservim/nerdtree/issues/21 there is a discussion around a similar problem and it is noted that
t:NERDTreeBufName
no longer exists.I tried replacing the
if
statement with a few suggestions from that issue, to no avail. I tried:and
I understand that this project is no longer actively maintained, however I wanted to report the issue in case others are seeing similar problems.
Versions:
Error occurs:
vim 9.0.1200 on macOS 11.7.2 (Big Sur) vim 9.0.1151 on macOS 13.1 (Ventura)
Error does not occur:
vim 9.0.920 on macOS 11.7.2 (Big Sur) vim 8.0.3741 on ubuntu 18.04.6 LTS (Bionic Beaver)