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

tabcloseleft option #5967

Open
gipi opened this issue Apr 22, 2020 · 9 comments
Open

tabcloseleft option #5967

gipi opened this issue Apr 22, 2020 · 9 comments

Comments

@gipi
Copy link

gipi commented Apr 22, 2020

I found that some time ago someone proposed a patch about the option tabcloseleft in the mailing list and indeed into todo.txt there is the line

Patch for :tabcloseleft, after closing a tab go to left tab. (William Bowers, 2012 Aug 4)

and I don't understand if it was dropped or if it needs more work on it in order to be merged or something else.

I think that is an option valuable to add, let me know if I can help, thank for your time.

@chrisbra
Copy link
Member

We do have tablocal variables and autocommands. Is such a feature really needed built into the core? I think this can be achieved by some Vimscript

@gipi
Copy link
Author

gipi commented Apr 22, 2020

The choice to build such feature in the core is yours to do, but since I saw that someone proposed a patch that is listed in the todo I thought that internally the discussion was already settled for a yes but the patch was lost somewhere.

I know that is something feasible with scripting but to me seems an option valuable to be configurable (99% of the time I open a tab via the NerdTree and I would like to close it and come back to the file listing to open another one, not to the tab on the right).

@no-more-secrets
Copy link

no-more-secrets commented Feb 1, 2022

This following vimscript solved this problem for me (adapted from here):

function! OnQuit()
    if winnr("$") == 1 && tabpagenr("$") > 1 && tabpagenr() > 1 && tabpagenr() < tabpagenr("$")
        q | tabprev
    else
        q
    endif
endfunction

cnoremap q<CR> :call OnQuit()<CR>

It would kind of be nice to have an option to do this, since I think vim currently has the "wrong" default behavior. That said, since it can be done with scripts such as the one above, I can understand the hesitancy.

EDIT: the above does not work as written, since it causes trouble when running the :wq command.

@chrisbra
Copy link
Member

chrisbra commented Feb 2, 2022

closing

@gdupras
Copy link

gdupras commented Feb 2, 2022

Then what about these lines in todo.txt?

vim/runtime/doc/todo.txt

Lines 1839 to 1840 in 7325714

Patch for :tabcloseleft, after closing a tab go to left tab. (William Bowers,
2012 Aug 4)

@brammool
Copy link
Contributor

brammool commented Feb 2, 2022

Whether you set the option or include the mentioned piece of Vim script, both require adding the change to your vimrc.
Adding yet another option for this isn't really needed, just nice.

The command only handles ":q" though, not other commands that close a tab page. Something using a WinClose autocommand should work better.

@brammool brammool reopened this Feb 2, 2022
@no-more-secrets
Copy link

no-more-secrets commented Feb 3, 2022

It looks like the tabpagenr command returns different things depending on whether it is called from the quit command handler or the WinClosed handler. For example, let's say that I have two tabs open, then I go to the first tab and, from it, I open a new tab that gets placed between the two, and then vim moves me to that tab. Then, I quit from that second tab, and print the values of tabpagenr with various arguments from both an empty :q handler and an empty WinClosed handler, I get different values:

Handler tabpagenr("$") tabpagenr() tabpagenr("#")
:q 3 2 1
WinClosed 3 3 2

The values in the quit handler make sense, but the values in the WinClosed handler seem inconsistent: if they represent a snapshot from before the window was closed, then why is tabpagenr() == 3 (when it should be 2)? On the other hand, if they represent a snapshot after the window is closed, then why is tabpagenr("$") == 3 (when it should be 2)? Is that something that needs to be fixed?

Furthermore, the winnr("$") value in the WinClosed handler seems to contain the number of windows in the new tab that was selected after the closing, and so we seem to lose the information about how many windows were open in the previous tab.

Given this, I am having difficulty implementing this using the WinClosed handler and convincing myself that it is correct.

Now that I think about it, I think the behavior that most users would actually want by default is not necessarily to always go to the left or right tab after closing a tab, but instead to go to the last tab that was accessed (be it left or right). That way it would do the "right" thing for users whether they have tabs open on the left or right. But either way, the above strange values of the winnr and tabpagenr commands in the WinClosed handler is making it difficult for me to implement that, so for now I am just sticking to my quit handler.

Can someone knowledgeable take a look at those numbers above and comment?

@no-more-secrets
Copy link

Edit to one of my above comments: the vimscript snippet that I pasted actually does not work correctly (for multiple reasons), one of which is that it does not work when running the :wq command. I think we need to get the WinClosed approach working, but would appreciate someone helping me with the issue above regarding the validity of the numbers returned by the various tabpage functions.

@Melandel
Copy link

Melandel commented Nov 1, 2022

For anyone pondering on the issue, right now here's how I'm doing it.

function! ShouldMoveToPreviousTab()
	" In some scenarios one field has the correct information, in other scearios the other has it
	let previousLastTabNr=max([g:TabLeave_TabsStatus.last, g:WinClosed_TabsStatus.last])
	return tabpagenr('$') < previousLastTabNr && g:TabLeave_TabsStatus.current != previousLastTabNr
endfunction

let g:WinClosed_TabsStatus = { 'current': 1, 'last': 1 } 
let g:TabLeave_TabsStatus =  { 'current': 1, 'last': 1 }
augroup tabcloseleft
	au!
	au TabLeave  * let g:TabLeave_TabsStatus  = { 'current': tabpagenr(), 'last': tabpagenr('$') }
	au WinClosed * let g:WinClosed_TabsStatus = { 'current': tabpagenr(), 'last': tabpagenr('$') }
	au TabClosed * if ShouldMoveToPreviousTab() | tabprevious | endif
augroup end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants