6

I tend to open multiple tabs in vim and multiple windows within a tab.

I have a habit of traversing the code in a tree format - I open a tag in a new tab, so that my current view of the window remains unchanged. I can simply close the newly opened tab/window to resume to my previous view.

Consider a case where I have window A focused. I open a new split as window B. Now, when I close window B, it should focus the earlier window A. Currently, it always focuses the window on left side of B.

Similarly, for tab close case, it always selects the tab on the right side of tab being closed.

Is there a way to keep track of the tab/window opening sequence in vim? Then I can trace back the sequence while closing the tab/windows...
Or better, is there a vim set command option or an internal variable that handles this automatically?

5
  • You can use WinLeave and WinEnter to maintain a stack of windows in the order you visit them. But maintaining the stack directly would be a pain in the rear, since (1) windows are per-tab, and (2) their IDs get re-allocated. You could get around that by creating your own unique IDs for each window, store them in w: variables, and put those in the stack. It would probably work eventually, but it would still be as robust as autocmds. Probably a reasonable idea for a plugin, too. Commented Aug 17, 2016 at 21:05
  • ^^ part1 is fine, because that's what I would want - I need to record the window opening order to be tab specific.Part2 is where I was struggling. If there are windows "1 2 3 4" and we open a window between 3 & 4, it will become #4 and #4 will be re-numbered as #5. Probably I could add a numbering system parallel to winnr() & store that as w:winnr2...
    – anishsane
    Commented Aug 18, 2016 at 3:35
  • @anishsane: Note that this problem of windows ID should be solved in Vim 8 which should be released in about 2 weeks: The change list announce that windows will have unique IDs I think that it will allow you to maintain the stack more easily.
    – statox
    Commented Aug 18, 2016 at 7:45
  • Oh cool! I was trying to write a vimscript using winenter/winleave autocmd plus the parallel numbering scheme I mentioned. But if it is going to be solved soon, then I don't need the parallel numbering scheme... :-)
    – anishsane
    Commented Aug 18, 2016 at 8:36
  • Wrote a script: vi.stackexchange.com/a/9288/2749 Using my parallel numbering scheme for now, so that it remains vim7 compatible.
    – anishsane
    Commented Aug 22, 2016 at 8:36

4 Answers 4

2

I have written the script for this purpose.
It can be downloaded as vimball based plugin from http://www.vim.org/scripts/script.php?script_id=5430.

Installation details:
$ wget http://www.vim.org/scripts/download_script.php?src_id=24462 -O FocusPrevious.vmb
$ vim FocusPrevious.vmb

Within vim:
:source %
:q

Restart vim
4
1

For the windows you could use a function which get the number of the current window, goes to the previous one and close the window of which you got the number earlier. Something like this:

function CloseAndGoToPreviousW()
    let prevWin = winnr()
    execute "wincmd p"
    execute prevWin . "wincmd q"
endfunction

You can then call the function directly or create a mapping to call it:

nnoremap <key> :call CloseAndGoToPreviousW()<CR>

Based on that I think you can do the same with the buffers with :h tabpagenr() and :h :tabclose.

2
  • wincmd p only works to toggle between 2 windows, not a sequence of windows. So, if I open windows A->B->C, then closing C should focus B & closing B should focus A. with wincmd p based solution, first part will work, but second part will not work. I should have mentioned that I had tried it.
    – anishsane
    Commented Aug 17, 2016 at 17:40
  • @anishsane: Oh indeed I hadn't thought about more complex use cases.
    – statox
    Commented Aug 18, 2016 at 7:43
0

Similarly, for tab close case, it always selects the tab on the right side of tab being closed.

These two lines force vim to go to the left on tabclose and closing a buffer will not close the window. They don't answer OP's question, but they answer the similar question that led me here.

The TabClosed autocommand now works for an arbitrary last tab. I'll leave the buffer command as is, though I may fix it later.

" Keep a list of the most recent two tabs.
let g:tablist = [1, 1]
autocmd TabLeave * let g:tablist[0] = g:tablist[1]
autocmd TabLeave * let g:tablist[1] = tabpagenr()
" When a tab is closed, return to the most recent tab.
" The way vim updates tabs, in reality, this means we must return
" to the second most recent tab.
autocmd TabClosed * exe "normal " . g:tablist[0] . "gt"

cnoremap bd<cr> b#<bar>bd#<cr>
2
  • 1
    Not the left tab; the last focussed tab.
    – anishsane
    Commented Dec 2, 2020 at 6:05
  • @anishsane The tab commands should now work as described in the OP.
    – JDG
    Commented Dec 2, 2020 at 6:57
0

Vim8 or Vim9 with the following snippet in ~/.vimrc works for me.

autocmd TabClosed * tabprevious
1
  • That is not necessarily the last focussed tab. But my fault for using the wrong word in the title.
    – anishsane
    Commented Aug 30, 2023 at 15:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.