使用Vim的标签页来像缓冲区一样工作

389

我研究了在Vim中使用标签页(使用:tabe, :tabnew等命令)作为替代方法,用于替换当前打开多个文件的隐藏缓冲区的做法。

我希望每个不同的打开的文件都始终在自己的标签页中。然而,有一些事情会妨碍这个目标。如何解决以下问题:

  1. 当类似gf^]这样的命令跳转到另一个文件中的某个位置时,文件会在当前标签页中以新的缓冲区打开。是否有一种方法可以使所有这类命令打开新的标签页,并且如果文件已经打开则切换到包含该文件的现有标签页?

  2. 在切换缓冲区时,我可以使用 :b <part of filename><tab> 它将完成现有缓冲区中文件名的匹配。甚至<part of filename>可以是文件名的中间部分而不是开头。是否有相应的方法来切换标签页?

11个回答

691

停止,停止,停止。

这不是 Vim 标签页的设计方式。实际上,它们被命名错误了。一个更好的名字应该是“视口”或“布局”,因为这就是标签页的作用——它是您所有现有缓冲区窗口的不同布局。

试图让 Vim 支持“1 个标签页=1 个缓冲区”的想法是徒劳无益的。Vim 不知道也不关心,并且它不会在所有命令中都遵守这种想法——特别是任何使用快速修复缓冲区(如:make:grep:helpgrep)的命令都会完全忽略标签页,你无能为力。

相反:

  • :set hidden
    如果您尚未设置此项,则进行设置。它使 Vim 的工作方式与地球上其他多文件编辑器的工作方式相同。您可以编辑的缓冲区没有出现在窗口中。
  • 使用 :bn:bp:b #:b namectrl-6 在缓冲区之间切换。我自己喜欢 ctrl-6(单独使用它会切换到先前使用的缓冲区,或者 #ctrl-6 可以切换到缓冲区号码#)。
  • 使用:ls 列出缓冲区,或使用插件如MiniBufExplBufExplorer

209
在我看来,这是一个Bug,而不是"用户错误"。在网上搜索"vim tabs"一词时,几乎每个人都不同意你的观点或者并不知道使用Vim标签页的"正确"方法。另外,如果标签页真的是"布局"视图,那么为什么默认的标签标题是当前文件名呢?如果我想要同一个文件的多个视图,那么所有的标签标题都将是相同的名称(并不是很有用吧?)。所以无论从哪个方面来看,Vim中默认的标签页实现都有缺陷。 - cmcginty
48
标签标题要展示什么?它会显示当前的缓冲区名称(而不是“文件名”)。你可以随意更改标签标题中的内容。 - aehlke
1
请记住,在非美国键盘上,CTRL-^可能比CTRL-6更容易到达。在德国键盘上,^位于1的左侧 - 非常方便。:h CTRL-^:大多数情况下,^字符位于6键上,按下CTRL和6键即可获得我们所说的CTRL-^。但是在某些非美国键盘上,CTRL-^以另一种方式产生。 - ischeriad
47
+1表示赞同“停止,停止,停止”。Vim不仅是一种工具,更是一种思维方式。教授新用户这种思维方式非常重要,这样他们才能充分利用这个工具。 - Cody Poll
6
Drew Neil在Vimcasts上的"How to use tabs"(如何使用标签页)一集中,在Textmate中使用标签页和在Vim中使用标签页之间做出了很好的比较。 - icc97
@aehlke 对于选项卡标题,可以使用编号或自定义命名。 - fde-capu

285

我来晚了,但惊讶地发现这个列表中没有以下内容:

:tab sball - 这将为每个打开的缓冲区打开一个新选项卡。

:help switchbuf - 这控制着缓冲区切换行为,尝试使用:set switchbuf=usetab,newtab。这应该意味着如果缓冲区已经打开,则切换到现有选项卡,否则创建一个新选项卡。


4
对于 switchbuf 命令的加一赞成 - set switchbuf=useopen 非常棒,可以避免 :make:vimgrep 等命令带来的烦人行为,即使缓冲区已经显示,也不会改变窗口布局中的缓冲区。 - mMontu
4
为什么不适用于我?在设置了:se switchbuf=usetab,newtab后,当我使用bn命令切换缓冲区时,它仍然在当前标签页中打开缓冲区文件,而没有切换到已存在的标签页。这里有什么问题吗? - zhiyelee
switchbuf 只能与缓冲区分割命令 (:sb) 和快速修复命令 (:cc) 一起使用。来源:vim文档。 - PyariBilli

193

Vim的:help window解释了"选项卡 vs 缓冲区"的混淆问题。

缓冲区是文件的内存文本。
窗口是缓冲区的视口。
标签页是窗口的集合。

在vim中使用缓冲区来打开多个文件。在其他编辑器中(例如notepad ++)可以通过选项卡来实现这一点,因此vim中的名称可能会引起误解。

窗口用于拆分工作区并在一个屏幕上显示多个文件(缓冲区)。在其他编辑器中,可以通过打开多个GUI窗口并在桌面上重新排列它们来实现这一点。

最后,在这个类比中,vim的标签页将对应于多个桌面,即窗口的不同排列方式。

正如vim的help: tab-page所解释的那样,当想要暂时编辑一个文件但不想更改当前窗口和缓冲区的布局时,可以使用标签页。在这种情况下,可以使用另一个标签页专门用于编辑该特定文件。

当然,您必须记住,在许多标签页或窗口中显示相同的文件会导致显示相同的工作副本(缓冲区)。


13
这实际上是一个很棒的回答,但需要读几遍才能理解。buffers(缓冲区)可以理解为“标签页”,windows(窗口)可以理解为“图形界面窗口”,tab pages(标签页)可以理解为“桌面”,这是我发现对于不熟悉这些概念的人来说最容易理解的解释。 - icc97
6
我倾向于将它们想象成透过窗户望进一个房间——缓冲区 = 物体窗口 = 窗格选项卡 = 窗口。我可以在房间里四处走动,并从不同的窗口(选项卡)观看。不同的窗口可以拥有不同数量、排列和大小的窗格。同一物体可以在不同的窗口的不同窗格中同时被查看。 - go2null
如果您熟悉Linux工作区和Windows范例,那么您将会看到vim使用的遗产。一开始只有一个窗口。然后窗口管理器允许您将窗口分成平铺式窗口管理器中的窗格或重叠窗格(浮动式窗口管理器),但它们仍将每个窗格称为窗口。现在添加工作区的概念,其中窗格可以显示在多个工作区中。因此,在这种范例中,buffer = appwindow = windowtab = workspace - go2null
另一种思考方式是,其他编辑器(如NotePad ++)仍在使用多个缓冲区,选项卡只是向用户展示的一种方式。真正的区别在于,Vim的:ls输出并不总是可见的。(请参见上面提到的BufExplorer和MiniBufExpl) - Dan

58
与其他答案不同,我认为你可以随意使用标签页。vim旨在具有多样性和可定制性,而不是强制您按照预定义的参数工作。我们都知道程序员喜欢将自己的“道德观”强加给其他人,因此这一成就显然是一个主要特点。 <C-w>gf是缓冲区gf命令的标签页等效命令。<C-PageUp><C-PageDown>将在标签页之间切换。(在Byobu中,这两个命令从未对我起作用,但它们在Byobu / tmux之外起作用。替代方法是gtgT。)<C-w>T将当前窗口移动到新的标签页。
如果您愿意让vim尽可能使用现有的标签页,而不是创建重复的标签页,请将:set switchbuf=usetab添加到您的.vimrc文件中。您可以将newtab添加到列表中(:set switchbuf=usetab,newtab),以强制显示编译错误的QuickFix命令在单独的标签页中打开。我更喜欢使用split,它在分割窗口中打开编译错误。
如果您启用了鼠标支持:set mouse=a,则可以通过单击它们与标签页交互。默认情况下还有一个+按钮,可创建新的标签页。
要查看标签页文档,请在正常模式下键入:help tab-page。(在这样做之后,您可以使用<C-w>T练习将窗口移动到标签页中。)有一长串命令。一些窗口命令与标签页有关,因此您可能还想通过:help windows查看该文档。
补充:2013-12-19
要在vim中打开多个文件,并将每个文件放在单独的标签页中,请使用vim -p file1 file2 ...。如果像我一样经常忘记添加-p,则可以在末尾添加它,因为vim遵循正常的命令行选项解析规则。或者,您可以添加一个bash别名,将vim映射到vim -p

4
+1 支持使用 vim -p 命令,但需要注意默认情况下只能显示最多10个标签页。额外的文件会被加载到缓冲区中,但不会在自己的标签页中显示。 - IanB
@IanB:我该如何克服默认设置,以避免将其限制为10个选项卡? - 0xC0000022L
3
@0xC0000022L 看一下 tabpagemax 设置。 - IanB

14

我也遇到了同样的问题,我希望选项卡能够像缓冲区一样工作,但我从来没有完全掌握它们。最终我采用的解决方案是让缓冲区表现得像选项卡一样!

请查看名为Mini Buffer Explorer的插件,一旦安装和配置完成后,您将能够以几乎与选项卡相同的方式处理缓冲区,而不会失去任何功能。


11

这是一个针对那些不熟悉Vim并来自其他文本编辑器(在我这里是Sublime Text)的答案。

我阅读了所有这些答案,但仍然不清楚。如果你足够阅读它们,一些事情开始变得清晰,但我花了数小时来回看问题。

首先,正如其他人所解释的:

标签页听起来很像标签,它们的行为也像标签,在大多数其他GUI编辑器中也很像标签,但它们不是。我认为这是在Vim中建立的一个错误的心理模型,不幸的是,它掩盖了你在标签页内拥有的额外功能。

我理解的第一个描述来自@crenate's answer,即它们相当于多个桌面。从这个角度看,你只会打开几个桌面,但每个桌面内会有许多GUI窗口打开。

我会说它们类似于其他编辑器/浏览器中的:

  1. 标签分组
  2. Sublime Text工作区(即项目中打开的文件列表)

当你看到它们那样时,你会意识到它们的强大之处,你可以轻松地将文件集(缓冲区)分组在一起,例如你的CSS文件、HTML文件和JS文件在不同的选项卡页中。这实际上非常棒。

其他我觉得令人困惑的描述

视口

这对我来说没有任何意义。虽然视口确实有一个定义的词典术语,但我只听过在:help window文档中提到Vim窗口。在像Sublime Text、Visual Studio、Atom、Notepad++这样的编辑器中,我从未听说过视口这个术语。事实上,直到我开始尝试使用选项卡页之前,我都没有听说过它与Vim有关。

如果您将选项卡页视为多个桌面,则将桌面称为单个窗口似乎很奇怪。

工作区

这可能更有意义,字典定义如下:

用于临时存储的存储设施。

因此,它就像是一个存储一组缓冲区的地方。

一开始听起来像是Sublime Text工作区的概念,它是您在项目中打开的所有文件列表,详见 Sublime Text's concept:

sublime-workspace文件包含用户特定数据,例如打开的文件和每个文件的修改。

然而,更仔细考虑后,这确实是正确的。如果您把Vim标签页看作是Sublime Text项目,那么在每个项目中只打开一个文件并不合适,需要不断在项目之间切换。因此,使用标签页只打开一个文件很奇怪。

窗口集合

:help window是以这种方式引用标签页的。此外,许多其他答案也使用了同样的概念。但是,如果您还不了解vim窗口是什么,那就没什么用处了,就像在沙子上建造城堡。

如上所述,vim窗口与视口相同,在这篇linux.com article文章中得到了很好的解释:

Vim中一个非常有用的功能是能够在一个或多个文件之间分割可视区域,或者只是分割窗口以更轻松地查看同一文件的两个部分。Vim文档将此称为视口或窗口,可以互换使用。
如果你曾经使用过Vim的帮助功能,比如使用:help topic命令或按下F1键,那么你可能已经熟悉了这个功能。当你进入帮助界面时,Vim会将视口分割开,并在顶部视口中打开帮助文档,同时保持底部视口中打开你的文档。
我觉得有点奇怪的是,标签页被称为窗口的集合,而不是缓冲区的集合。但我猜想你可以打开两个单独的标签页,每个标签页都有多个窗口,这些窗口都指向同一个缓冲区,至少目前我是这样理解的。

1
终于,在全职使用Vim一年之后,我遇到了一个需要使用多个标签页的情况。目前,缓冲区对我来说完美地解决了在其他编辑器中使用标签页的问题。但是,由于我有一个大屏幕,我正在比较大量的3-4个不同的缓冲区。然后,一个同事要求我在代码库的其他地方搜索一些代码。为了不失去我的比较窗口组合,我可以创建一个新的标签页,这样就可以像平常使用Vim一样进行单独的搜索,完成后关闭标签页并返回到初始设置。 - icc97

5
  • You can map commands that normally manipulate buffers to manipulate tabs, as I've done with gf in my .vimrc:

    map gf :tabe <cfile><CR>
    

    I'm sure you can do the same with [^

  • I don't think vim supports this for tabs (yet). I use gt and gT to move to the next and previous tabs, respectively. You can also use Ngt, where N is the tab number. One peeve I have is that, by default, the tab number is not displayed in the tab line. To fix this, I put a couple functions at the end of my .vimrc file (I didn't paste here because it's long and didn't format correctly).


<c-w>gf 将会在新标签页中打开光标下的文件名。 - Peter Rincker

5

我像使用标签一样使用缓冲区,使用BufExplorer插件和一些宏:

" CTRL+b opens the buffer list
map <C-b> <esc>:BufExplorer<cr>

" gz in command mode closes the current buffer
map gz :bdelete<cr>

" g[bB] in command mode switch to the next/prev. buffer
map gb :bnext<cr>
map gB :bprev<cr>

使用BufExplorer,您在顶部没有选项卡栏,但另一方面它可以节省屏幕空间,而且您可以打开无限数量的文件/缓冲区,并且缓冲区列表是可搜索的...


4

看起来,根据:help tabs所述,vim似乎不想按照你的方式工作...

缓冲区在选项卡之间是共享的,因此似乎不可能锁定特定的缓冲区仅出现在某个选项卡中。

这是一个好主意,但是...

您可能可以通过使用支持选项卡的终端(例如multi-gnome-terminal),然后在每个终端选项卡中运行vim实例来获得所需的效果。但并不完美。


我尝试过这个,除了使在选项卡之间导航变得困难之外,问题还在于复制的文本不能在终端选项卡之间共享,因为它们本质上是两个不同的终端/Shell。 - puk
@puk:尝试使用YankRing vim插件。它可以将复制的文本保存在文件中,因此可以在不同的vim实例之间共享。 - pixelastic
@Pixelastic 我在这里找到了一个适合将内容复制到系统剪贴板的解决方案。此外,Vim 最好只在一个实例中运行。我停止让它按照我的意愿工作,并学会了如何正确地使用 Vim :-) https://dev59.com/fWoy5IYBdhLWcg3wHqiB#8757876 - puk
@puk:谢谢,我没有想到使用系统剪贴板也意味着在vim实例之间共享它 :) - pixelastic

2
如果您想让缓冲区像选项卡一样工作,请查看选项卡插件。 该插件使用单个窗口,在顶部添加一行以模拟选项卡(只显示缓冲区列表)。这个插件很早之前发布,当时GVim支持选项卡,但命令行vim不支持。由于它仅与缓冲区交互,因此一切都很好地融入了vim的其余部分。

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