如何在Vim中关闭一个缓冲区(其中之一)?

571

我通过在 Vim 中运行以下命令打开多个文件:

vim a/*.php

打开了23个文件。

然后,我进行了编辑并运行了以下代码两次:

:q

如何在Vim中关闭单个缓冲区,而不是关闭所有缓冲区?


11
请注意,您可以使用 vim -o a/*.php (或 -O 以使用垂直窗口)在单独的 Vim 窗口中打开文件,避免缓冲区导航。这是一种适用于仅几个文件的好方法,但对于23个文件而言,它们每个文件只有几行/列。 - Cascabel
1
@Jefromi:谢谢你指出这个问题!我以前从来没有使用过-o选项。 - Léo Léopold Hertz 준영
1
关于窗口分割。如果您已经在Vim中并想要在一个分割窗口中打开另一个文件:使用:esp进行水平分割,使用:evsp进行垂直分割。 - Lanzafame
10个回答

751

来自手册的更多内容:

:bd

卸载缓冲区[N](默认:当前缓冲区)并从缓冲区列表中删除它。如果缓冲区已更改,则此操作失败,除非指定了[!],在这种情况下,更改将丢失。 文件保持不变。

如果你知道你在做什么,你也可以使用 :bw

:bw

类似于|:bdelete|,但真正删除缓冲区。

一个警告:“bw 中的 w 不代表写入,而是表示抹除!”


5
还可以通过使用“:M,Nbd”命令关闭M到N号缓冲区。 或者使用“:bd N1 N2...”命令,其中N#是缓冲区编号。 - snowbound
118
手册上说只有“你知道自己在做什么”时才使用:bw,但我不知道,所以我猜我会使用:bd - jberryman
6
根据Vim手册,“w”是“write”命令的缩写,并且没有提到任何“wipeout”。该命令的描述(help write)以“将整个缓冲区写入当前文件”开头。 - Armen Michaeli
6
通过使用:help bw,您将看到bw代表删除。 - noark
7
@amn 我也有点困惑,但他的意思是 bw 命令中的 w 表示擦除,而不是 w 命令。他在那里加了这个警告,以便人们不会认为 bw 命令表示缓冲区写入(实际上它并不是,它表示缓冲区擦除)。 - John
显示剩余8条评论

386
如果之前的回答没有让这个显而易见:使用:bd命令将会关闭当前缓冲区,如果你不想获取缓冲区列表。

4
在发现 :bd 命令之前,我一直无法理解为什么人们会觉得使用 :ls 命令列出文档编号再通过编号卸载缓冲区是没有问题的。人们真的认为这种方法有效吗? - Svend
3
对于一系列缓冲区而言,@svend的做法没问题,但对于单个缓冲区使用:bd可能更为有效。 - Pharaun
12
:bd 只是关闭缓冲区,而 :bw 则会清除所有变量并将其从缓冲区中彻底删除(不管这句话什么意思)。 - RedX

122

使用:buffers命令检查您的缓冲区id。

您将在那里看到缓冲区列表,例如:

1  a.php
2  b.php
3  c.php

如果您想从缓冲区中删除 b.php

:2bw

如果你想要移除/关闭所有的缓冲区

:1,3bw

4
您可以使用“:%bw”命令清除所有缓冲区。 - cdleonard
7
检查缓冲区ID的快捷方式:2号缓冲区 CTRL-G。 - snowbound

54

与其浏览:ls命令的输出并通过指定编号来删除(卸载、清除..)缓冲区,我发现使用文件名通常更有效。

例如,当我打开一些.txt文件以刷新对某些细节的记忆后..复制和粘贴几行文本作为模板等等。我将键入以下命令:

:bd txt <Tab>

请注意,匹配的字符串不一定要在文件名的开头。

以上显示了在屏幕底部匹配'txt'的文件名列表,并保持我最初输入的:bd命令不变,以备完成。

这里是一个例子:

doc1.txt doc2.txt
:bd txt 

我可以退格删除'txt',然后键入我想要删除的文件名,但真正方便的是我不必这样做:如果我第二次按Tab键,Vim会自动完成我的命令与第一个匹配项:

:bd doc1.txt

如果我想要摆脱这个特定的缓冲区,我只需要按Enter键。

如果我想要删除的缓冲区恰好是第二个(第三个..等),我只需要不断按Tab键来使我的:bd命令循环遍历匹配列表。

当然,这种方法也可以用于通过:b.. :sb..等命令切换到给定的缓冲区。

当设置了'hidden' Vim选项时,采用这种方法特别有用,因为缓冲区列表可能会变得非常大,覆盖多个屏幕,使得很难找到我正在寻找的特定缓冲区。

为了充分利用这个功能,最好阅读下面的Vim帮助文件,并相应地调整Tab命令行完成的行为,以最适合您的工作流程:

:help wildmode

上述行为是由下面这个设置引起的,我选择了这个设置以保持一致性,以模拟bash完成:

:set wildmode=list:longest,full

与使用缓冲区号相比,这种方法的优点在于我通常记得给定文件名的一部分,使我可以直接定位缓冲区,而不必先通过 :ls 命令查找其编号。


52

使用:

  • :ls - 列出缓冲区
  • :bd#n - 关闭编号为 #n 的缓冲区(使用 ls 命令获取编号)

示例:

  • 删除第二个缓冲区:

    :bd2
    

19

你也可以将next和previous映射到功能键,使得在缓冲区之间轻松切换成为可能。

map <F2> :bprevious<CR>
map <F3> :bnext<CR>

来自我的vimrc配置文件


8

关闭缓冲区而不关闭窗口

如果你想在不破坏窗口布局(当前基于分割的布局)的情况下关闭缓冲区,你可以使用像bbye这样的插件。基于此,你只需使用以下命令:

:Bdelete (instead of :bdelete)
:Bwipeout (instead of :bwipeout)

或者只需在您的.vimrc中创建一个映射,以便更方便地访问,例如:
:nnoremap <Leader>q :Bdelete<CR>

相比于vim的:bdelete和:bwipeout的优势

来自插件文档

  • 关闭并移除缓冲区。
  • 在该窗口中显示另一个文件。
  • 如果没有其他文件打开,则显示一个空文件。
  • 如果你决定在该窗口编辑另一个文件,请不要留下无用的[无文件]缓冲区。
  • 即使一个文件在多个窗口中打开,也能正常工作。
  • 与各种缓冲区浏览器和选项卡栏完美兼容。

:bdelete vs :bwipeout

来自插件文档

Vim有两个关闭缓冲区的命令::bdelete:bwipeout。前者从缓冲区列表中移除文件,清除其选项、变量和映射。然而,它仍然存在于跳转列表中,所以按下Ctrl-o可以返回并重新打开文件。如果这不是你想要的,使用:bwipeout或Bbye的等效命令:Bwipeout来替代:bdelete

谢谢,这正是我想要的,并且它也可以很好地与 coc-explorer 配合使用。 :) - Ranel Padon

4

[编辑:这是我还不太熟悉Vim时的一个愚蠢建议。请不要使用选项卡来代替缓冲区;选项卡是Vim的“窗口布局”]

也许可以考虑使用选项卡?

vim -p a/*.php 在选项卡中打开相同的文件

gtgT 在选项卡之间切换

:q 仅关闭当前选项卡

:qa 关闭所有选项卡并退出

:tabo 关闭除当前选项卡外的所有选项卡


2
为什么你说使用制表符是一个愚蠢的建议?我只是问一下,因为我一直在使用制表符... :^/ - Nate
2
@Nate:我决定详细阐述一下这个问题 http://leonid.shevtsov.me/en/why-vim-tabs-are-different-from-any-other-editor - Leonid Shevtsov
1
那是一篇很棒的文章 - 它激励我更深入地挖掘 - 你看过wildmenu吗?它类似于lustyjuggler(虽然更简单),但它是内置的(这对我来说很好,因为lustyjuggler需要+ruby,而ubuntu oneiric的默认vim则使用-ruby)。 - Nate
@Nate:是的,我正在使用wildmenu打开文件,但是当项目中有很多文件时,它就无法扩展了。此外,Ubuntu的vim-nox软件包支持Ruby。 - Leonid Shevtsov

3
如何呢?
vim -O a a

那样你就可以在左侧编辑单个文件,在右侧导航整个目录... 只是一个想法,不是解决方案...

1

使用缓冲区或树形导航插件(如Buffergator或NERDTree)的用户,在销毁当前缓冲区之前需要切换这些分割窗口,否则您将会把它们弄乱。

我使用:

"" Buffer Navigation                                                                                                                                                                                        
" Toggle left sidebar: NERDTree and BufferGator                                                                                                                                                             
fu! UiToggle()                                                                                                                                                                                              
  let b = bufnr("%")                                                                                                                                                                                        
  execute "NERDTreeToggle | BuffergatorToggle"                                                                                                                                                              
  execute ( bufwinnr(b) . "wincmd w" )                                                                                                                                                                      
  execute ":set number!"                                                                                                                                                                                    
endf                                                                                                                                                                                                        
map  <silent> <Leader>w  <esc>:call UiToggle()<cr>   

在该列表中,"NERDTreeToggle"与键入:NERDTreeToggle相同。您可以修改此函数以与您自己的配置集成。


对于这个问题,bbye 插件是完美的选择,它可以在使用 :bdelete:bwipeout 命令时保留你的窗口布局。请参考我的回答 - Wolfson

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