Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix E1312 when quitting a window #875

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 17 additions & 6 deletions autoload/tagbar.vim
Original file line number Diff line number Diff line change
Expand Up @@ -3522,26 +3522,37 @@ function! s:HandleOnlyWindow() abort
let file_open = s:HasOpenFileWindows()

if vim_quitting && file_open == 2 && !g:tagbar_autoclose_netrw
call tagbar#debug#log('Closing Tagbar due to QuitPre - netrw only remaining window')
call s:CloseWindow()
call tagbar#debug#log('Closing Tagbar due to QuitPre - leave netrw')
if has('patch-9.0.907')
call timer_start(10, {-> s:CloseWindow() })
else
call s:CloseWindow()
endif
return
endif

if vim_quitting && file_open != 1
call tagbar#debug#log('Closing Tagbar window due to QuitPre event')
call tagbar#debug#log('Closing Tagbar and netrw due to QuitPre event')
if winnr('$') >= 1
call s:goto_win(tagbarwinnr, 1)
endif

" Before quitting Vim, delete the tagbar buffer so that the '0 mark is
" correctly set to the previous buffer.
if tabpagenr('$') == 1
noautocmd keepalt bdelete
if has('patch-9.0.907')
call timer_start(20, {-> execute('noautocmd keepalt bdelete ' . tagbarwinnr)})
else
noautocmd keepalt bdelete
endif
endif

try
try
quit
if has('patch-9.0.907')
call timer_start(50, {-> execute('q', 'silent!') })
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why different wait time argument for the 3 timer_start call? I think maybe what matters is where the command is going to be invoked, and the wait time can be all 0.

Copy link
Collaborator

@raven42 raven42 Mar 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The call timer_start() will return immediately after the call is queued. But there can be different background threads that will actually execute the queued call. So the delay is in there to allow for the previously queued call time to execute and complete before starting the next one. It is kind of a soft serialization of the queued calls so they aren't trying to all execute at the same time.

What we want to avoid

The par section will execute in parallel, and we don't have control over the order in which the threads execute.

sequenceDiagram
    participant main
    create participant only_window as s:HandleOnlyWindow()
    main->>only_window: call
    create participant close as timer_start(0)
    only_window-->>close: call timer_start(0)
    create participant bdelete as timer_start(0)
    only_window-->>bdelete: call timer_start(0)
    create participant quit as timer_start(0)
    only_window-->>quit: call timer_start(0)
    destroy only_window
    only_window->>main: return

    par
        note over bdelete: execute('noautocmd keepalt bdelete ' . tagbarwinnr)
    and
        note over close: s:CloseWindow()
    and
        note over quit: execute('q', 'silent!')
    end
    destroy close

    close->>main: done

    destroy bdelete
    bdelete->>main: done

    destroy quit
    quit->>main: done
Loading

Adding delay in timer

In this instance, we add the delays to ensure there is time for the other tasks to complete in proper order.

sequenceDiagram
    participant main
    create participant only_window as s:HandleOnlyWindow()
    main->>only_window: call
    create participant close as timer_start(10)
    only_window-->>close: call timer_start(10)
    create participant bdelete as timer_start(20)
    only_window-->>bdelete: call timer_start(20)
    create participant quit as timer_start(50)
    only_window-->>quit: call timer_start(50)
    destroy only_window
    only_window->>main: return

    note over close: s:CloseWindow()
    destroy close
    close->>main: done

    note over bdelete: execute('noautocmd keepalt bdelete ' . tagbarwinnr)
    destroy bdelete
    bdelete->>main: done

    note over quit: execute('q', 'silent!')
    destroy quit
    quit->>main: done
Loading

else
quit
endif
catch /.*/ " This can be E173 and maybe others
call s:OpenWindow('')
echoerr v:exception
Expand Down
Loading