有没有一种Vim命令可以重新定位标签页?

243
我该如何在 Vim 中更改当前选项卡的位置/顺序?例如,如果我想将当前选项卡重新定位为第一个选项卡?
8个回答

332

您可以使用 :tabm 命令相对或绝对索引来重新定位标签页。

绝对索引:

  • 将标签页移动到位置 i::tabm i

相对索引:

  • 将标签页向右移动 i 个位置::tabm +i
  • 将标签页向左移动 i 个位置::tabm -i

这是一个相对较新的功能。如果无法正常工作,请尝试更新您的Vim版本。


2
这个不起作用。:tabm不接受相对参数,尽管它应该接受。 - Gavin
6
如果您的vim版本低于7.3,建议您升级到最新版本,因为在vim 7.3中,:tabm命令支持相对参数。 - maybeshewill
6
请注意,绝对位置从零开始计数,这有点奇怪,因为vim按1索引显示选项卡(或者可能只是我的vim配置)。 - Elliot Foster
2
这个不能处理换行的情况。 - Andy Ray
1
值得一提的是,:tabm+/-是在Vim 7.3.591中引入的(发布于2012年7月6日),现已进入几乎所有维护的发行版中。 :) - n.st
显示剩余5条评论

45

您的意思是移动当前标签吗?使用tabmove可以实现这一功能。

:tabm[ove] [N]                                          *:tabm* *:tabmove*
            Move the current tab page to after tab page N.  Use zero to
            make the current tab page the first one.  Without N the tab
            page is made the last one.

我有两个按键绑定可以将我的当前标签页向左或向右移动。非常方便!

编辑:这是我的VIM宏。我不是一个很擅长ViM编程的人,也许可以做得更好,但对我来说它就是这样工作的:

" Move current tab into the specified direction.
"
" @param direction -1 for left, 1 for right.
function! TabMove(direction)
    " get number of tab pages.
    let ntp=tabpagenr("$")
    " move tab, if necessary.
    if ntp > 1
        " get number of current tab page.
        let ctpn=tabpagenr()
        " move left.
        if a:direction < 0
            let index=((ctpn-1+ntp-1)%ntp)
        else
            let index=(ctpn%ntp)
        endif

        " move tab page.
        execute "tabmove ".index
    endif
endfunction

接下来,您可以绑定按键,例如在您的.vimrc文件中这样做:

map <F9> :call TabMove(-1)<CR>
map <F10> :call TabMove(1)<CR>

现在你可以通过按下 F9 或 F10 来移动当前的选项卡。


嗯...所以将选项卡向左或向右移动一个位置需要脚本吗?你能粘贴一下吗? - Gavin
2
我添加了我的脚本。这对你有帮助吗? - hochl

26

我也在寻找同样的答案,在看了一些帖子之后,我找到了比函数更简单的方法:

:execute "tabmove" tabpagenr() # Move the tab to the right
:execute "tabmove" tabpagenr() - 2 # Move the tab to the left

tabpagenr()函数返回当前打开标签页的编号,而tabmove命令使用索引进行移动。

我将向右移动映射为Ctrl+L,向左移动映射为Ctrl+H:

map <C-H> :execute "tabmove" tabpagenr() - 2 <CR>
map <C-J> :execute "tabmove" tabpagenr() <CR>

1
这个没有处理换行的情况,供你参考。 - Andy Ray
3
MacVim 8.0.1420 (144) 中,我必须使用 :execute "tabmove" tabpagenr() + 1 <CR> 来向右移动标签页。 - Paul Oliver

10

将当前标签移到第 nth 位置

:tabm n

其中n是表示位置的数字(从零开始)


将选项卡向左/右移动

我认为更好的解决方案是将选项卡移动到其当前位置的左侧或右侧,而不是计算出您想要它到达的新位置的数字值。

noremap <A-Left>  :-tabmove<cr>
noremap <A-Right> :+tabmove<cr>

使用上述按键映射,您将能够移动当前标签页:

  • 向左移动:按下 Alt + Left
  • 向右移动:按下 Alt + Right

+tabmovetabmove+有什么区别吗?位置重要吗? - user4104817
这对我来说似乎是最压缩的版本 :) - kellekai

5
除了其他答案中的好建议外,如果启用了鼠标支持,您还可以通过鼠标拖动选项卡来移动它们。
在MacVim和其他GUI vim实现中,默认情况下启用此功能,无论是使用GUI小部件选项卡还是在GUI模式下使用终端样式选项卡。
如果您设置了set mouse=a并且有适当的终端(xterm和大多数仿真器,例如gnome-terminal、Terminal.app、iTerm2和PuTTY/KiTTY等),它也可以在纯tty模式Vim中工作。请注意,超过222列的鼠标单击还需要set ttymouse=sgr; 有关该背景,请参见在Vim中,为什么我的鼠标不能在第220列之后工作?
我编写了一个名为vim-tabber的插件,为交换选项卡、移动它们和增加内置选项卡操作命令的功能提供了一些额外的功能,同时基本上与内置命令兼容。即使您选择不使用该插件,在README中也有一些常规的选项卡使用信息。

重新使用鼠标排列选项卡后,我无法再使用鼠标调整窗格大小。相反,每次我点击并拖动鼠标光标时,选项卡会再次重新排列,就好像鼠标单击“卡住”了一样。你有任何想法这里可能出了什么问题吗? - oldhomemovie
Jim,我已经单独发布了这个问题:http://stackoverflow.com/questions/43734501/cannot-resize-pane-with-mouse - oldhomemovie

4

这是一个很好的问题,Gavin,因为它有一些微妙之处。

来自maybeshewillhochl的答案大多回答了这个问题--使用带有索引或相对(+/-)索引的":tabm"。

请注意,这里存在混淆的可能性,其他答案可能会忽略这一点。看一下下面由hochl包含的帮助文本:

   :tabm[ove] [N]                                          *:tabm* *:tabmove*
            Move the current tab page to after tab page N.  Use zero to
            make the current tab page the first one.  Without N the tab
            page is made the last one.

关键字是 after。我怀疑有时会让人们感到困惑。为什么?因为如果使用 ":tabm3" 将选项卡移出第一个位置,随后输入 ":tabm2" 不会再次移动选项卡。原本占用选项卡#3的文件现在占用选项卡#2,而 ":tabm2" 不会改变顺序。
这是一个图示。每一行中,选中的选项卡是[file_c]。
file_a file_b [file_c] file_d
:tabm0
[file_c] file_a file_b file_d
:tabm3
file_a file_b [file_c] file_d
:tabm2
file_a file_b [file_c] file_d

":tabm" 命令可以被视为将当前标签页移动到从0开始计数的占据位置后面的标签页,其中标签页0是最左边的标签页且是虚构的。":tabmi" 不会移动到第i个位置 -- 如果这样做了,":tabm3" 和 ":tabm2" 将会产生不同的结果。

最终,如果你有一个好的按键映射,相对移动 +/- 语法更简单易用。


1
由于某些原因,答案函数对我停止工作了。我怀疑这与vim-ctrlspace有冲突。无论如何,答案函数中的数学计算是不必要的,因为Vim可以使用内置函数向左和向右移动标签页。我们只需要处理换行情况,因为Vim不太用户友好。
" Move current tab into the specified direction.
"
" @param direction -1 for left, 1 for right.
function! TabMove(direction)
    let s:current_tab=tabpagenr()
    let s:total_tabs = tabpagenr("$")

    " Wrap to end
    if s:current_tab == 1 && a:direction == -1
        tabmove
    " Wrap to start
    elseif s:current_tab == s:total_tabs && a:direction == 1
        tabmove 0
    " Normal move
    else
        execute (a:direction > 0 ? "+" : "-") . "tabmove"
    endif
    echo "Moved to tab " . tabpagenr() . " (previosuly " . s:current_tab . ")"
endfunction

" Move tab left or right using Command-Shift-H or L
map <D-H> :call TabMove(-1)<CR>
map <D-L> :call TabMove(1)<CR>

我的vim 7.4中的-tabm+tabm不能正确移动标签。而且我的:help tabm没有列出这个有效的语法。所以我使用了Pablo的答案,将最后的else execute ... endif替换为elseif a:direction == 1 execute "tabmove" s:current_tab else execute "tabmove" s:current_tab - 2 endif - cfi
现在我正在使用这个解决方案来包装开始/结束,因为它比我的解决方案更加简洁易读和易于维护。只需将 tabmove-/+ 符号的顺序反转即可。 - rld.

1
这是我根据@maybeshewill的答案编写的宏,使用了相对参数:
" Shortcuts to move between tabs with Ctrl+Shift+Left/Right
function TabLeft()
   if tabpagenr() == 1
      execute "tabm"
   else
      execute "tabm -1"
   endif
endfunction

function TabRight()
   if tabpagenr() == tabpagenr('$')
      execute "tabm" 0
   else
      execute "tabm +1"
   endif
endfunction

map <silent><C-S-Right> :execute TabRight()<CR>
map <silent><C-S-Left> :execute TabLeft()<CR>

它处理包装的情况。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接