AndrewRadev/undoquit.vim

Undo close tab

Closed this issue · 4 comments

This plugin seems to handle only windows. Would be great to have all-in-one solution for undo close with undo close tab as well.

Currently when I close tab with multiple windows I cannot restore them. That's why I have to use different script https://www.reddit.com/r/vim/comments/3ke941/undo_close_tab/cuxwxy1/

The way the plugin is implemented, it listens to an autocommand to determine when a window was closed, and stores it in history for later. Unfortunately, :tabclose doesn't trigger this autocommand, or any different one that I can monitor (as far as I could tell).

The only way to fix it is with some custom mapping/command to close the tab and somehow store it in history -- that's what the script you linked to does, but it uses its own history.

I see two possible ideas. One is, instead of using that script, you use something that closes a tab by closing its windows one by one. I even have one in my own vimfiles (originally for a different reason), which is why this has never been a problem for me :) https://github.com/AndrewRadev/Vimfiles/blob/c92287283f82db9221e148bca114d81be311295e/startup/mappings.vim#L139-L149

I could even provide this sort of mapping from the plugin, as an optional "map this to something and use it if you'd like tabs to be closed and their windows to be restorable" (Note that if you just :quit windows one by one, they get restored just fine, even if they were in a different tab). This would restore windows one by one, though, instead of just restoring the whole tab, which might be inconvenient.

The second option I see is to create some kind of interface to allow custom "store" and "restore" functionality with a custom mapping. Maybe something like:

nnoremap <leader>c :<c-u>call undoquit#CustomClose({
      \ 'store': {-> windowlayout#GetLayout()},
      \ 'restore': {state -> windowlayout#SetLayout(state)}
      \ 'execute': 'tabclose',
      \ })<cr>

Or maybe:

nnoremap <leader>c :<c-u>call undoquit#PushState(windowlayout#GetLayout(), {
      \ 'pop': {state -> windowlayout#SetLayout(state)},
      \ 'after': 'tabclose'
      \ })<cr>

What do you think? Would you rather the plugin provided a "close tab, while storing window states" mapping that lets you restore windows one by one? Or a custom callback setup that's more complicated, but theoretically might give you more options? Or some third option I might be missing?

I've just installed your plugin along with the mentioned script and I'm quite happy with both solutions working for windows and tabs respectively. Thank you for the seamless experience.

Reopening windows one by one from different tabs is good and useful.
Having a shortcut to reopen tabs is even better, as it is seamless and faster (especially in the case when "closing all other tabs except current". And if I close tab by ":tabclose" having no option to restore windows is sad, that's why I immediately installed that script to have complete solution.

My suggestion was just to add that script to the plugin (probably eliminating a need to have 'godlygeek/windowlayout' installed, if you know how, as I personally have no clue in vimscript) and provide a plugin with complete feature set for undo close functionality.

To summarise: user will be required to set two mappings: 1) undo close window 2) undo close tab
And probably override existing mappings for closing tab, as required by that script.

Sorry for taking a while to get around to this. While I could see the logic in what you were describing, it took some thinking and inspiration to come up with some way of implementing it.

I've pushed an :UndoableTabclose that could be used as a :tabclose replacement, and a <c-w>U mapping that should be able to restore all the windows of a full tab. Could you go over the updated documentation and try it out?

I'll go ahead and close this issue, since I think the command and mapping are the best I can do for this scenario.