I've mostly been avoiding tabs because of this problem, but now I have a function that has the tab duplication behavior I want. I've tested it, but haven't started using it in earnest. There may be some hidden drawback to this workflow.
One problem with the function is that it doesn't duplicate some of the state from the previous buffer-window pair (like whether set number
is on or not). Speculating a bit, c-w T
probably does not have this problem because no duplication is performed and the window is probably just reparented.
Vim has a couple of 1-based lists for things like buffers, tabs, and windows. As far as I can tell, they are 1-based because the 0
key is used to move to the beginning of a line and as a result passing zero as a numeric argument is impossible.
We care about three lists for emulating this functionality:
- The global list of tab pages
- The per-[tab page] list of windows
- The global list of buffers
We save all of this values, then create a new tab via "tabnew". New tabs are always created to the right, so none of the indices below the tab that we tabnew
'd from are invalidated. (A more robust way to do this would probably be better though).
The tabnew
command also moves focus to the new tab and the single window within it. From there we can use the buffer
command to create a view onto the buffer that originally had focus.
Then we use the saved index of the original tab to restore focus back to that tab. And then, largely out of paranoia, we set the focus within that tab to the original window. Vim seems to remember which window has focus in non-visible tabs, but I don't like relying on that.
(A few stylistic points: the explicit numeric conversion 0+
, global variables, and assertions are all intentional)
function! TabDuplicate()
" set vars, sanity checking
let g:tabdup_win = 0+ winnr()
let g:tabdup_buf = 0+ bufnr('%')
let g:tabdup_tabpage = 0+ tabpagenr()
call assert_true(g:tabdup_win > 0)
call assert_true(g:tabdup_buf > 0)
call assert_true(g:tabdup_tabpage > 0)
" make a new tab page,
" the new tab page will have focus
" none of the indices, which are all
" less than the current index, are
" invalidated by creating a new tab
execute "tabnew"
" visit the buffer we saved
execute "buffer " . g:tabdup_buf
" return to the original tab page
execute "tabnext " . g:tabdup_tabpage
" return focus to original window
execute g:tabdup_win . " windcmd w"
endfunction