在vi中快速缩进多行

2405

这应该很简单,甚至可能在帮助文档中提到,但我不知道如何在vi中快速缩进多行。请问应该怎么做?

34个回答

2854

使用 > 命令缩进内容。要缩进五行,输入 5>>。要标记一段文本并缩进,可以用 Vjj> 缩进三行(仅适用于 Vim)。要缩进花括号(curly-braces)块,将光标放在一个花括号上,使用 >% 或从块内任何位置使用 >iB

如果您需要复制文本块并需要在新位置对齐缩进,则使用 ]p 而不是只使用 p。这将使粘贴的文本块与周围的文本对齐。

此外,shiftwidth 设置可让您控制缩进的空格数。


85
我使用>i}(缩进内部 {} 块)命令。在 Vim 中有效,但不确定在 Vi 中是否有效。 - R. Martinho Fernandes
13
我在gVim中遇到的问题是,命令> 缩进比两个空格多得多(我只想要两个空格,但> 却会缩进大约5个空格)。 - Kamran Bigdely
32
@Kamran:请查看shiftwidth设置以更改缩进方式。 - Greg Hewgill
4
@MattStevens:你可以在这里找到关于这个现象的更详细讨论:http://meta.stackexchange.com/questions/9731/fastest-gun-in-the-west-problem - Greg Hewgill
6
我经常多次缩进可视块,例如修复粘贴到XML文件中的一些标签。不必每次重新在可视模式下选择块,可以使用“gv”重用上次的可视块。参考http://superuser.com/questions/220666/how-do-you-reuse-a-visual-mode-selection - David Mann
显示剩余12条评论

1046

这篇答案总结了该问题的其他答案和评论,并根据Vim文档Vim维基提供了额外信息。为了简洁起见,此答案不区分Vi和Vim特定命令。

在下面的命令中,“重新缩进”意味着“根据您的缩进设置缩进行。”shiftwidth是控制缩进的主要变量。

常规命令

>>   Indent line by shiftwidth spaces
<<   De-indent line by shiftwidth spaces
5>>  Indent 5 lines
5==  Re-indent 5 lines

>%   Increase indent of a braced or bracketed block (place cursor on brace first)
=%   Reindent a braced or bracketed block (cursor on brace)
<%   Decrease indent of a braced or bracketed block (cursor on brace)
]p   Paste text, aligning indentation with surroundings

=i{  Re-indent the 'inner block', i.e. the contents of the block
=a{  Re-indent 'a block', i.e. block and containing braces
=2a{ Re-indent '2 blocks', i.e. this block and containing block

>i{  Increase inner block indent
<i{  Decrease inner block indent
你可以用 }B 替换 {, 比如说 =iB 是一个有效的块缩进命令。请查看 "缩进代码块"来试用这些命令的好例子。
另外,请记住:
.    Repeat last command

因此缩进命令可以轻松方便地重复使用。

重新缩进整个文件

另一种常见情况是需要在整个源文件中修复缩进:

gg=G  Re-indent entire buffer
你可以将这个想法扩展到多个文件:
" Re-indent all your C source code:
:args *.c
:argdo normal gg=G
:wall

或者是多个缓冲区:

" Re-indent all open buffers:
:bufdo normal gg=G:wall

在可视化模式下

Vjj> Visually mark and then indent three lines

在插入模式下

这些命令适用于当前行:

CTRL-t   insert indent at start of line
CTRL-d   remove indent at start of line
0 CTRL-d remove all indentation from line

Ex命令

当你想要缩进一定范围的行但不想移动光标时,这些命令很有用。

:< and :> Given a range, apply indentation e.g.
:4,8>   indent lines 4 to 8, inclusive

使用标记进行缩进

另一种方法是通过标记实现:

ma     Mark top of block to indent as marker 'a'

...将光标移动到末尾位置

>'a    Indent from marker 'a' to current location

控制缩进的变量

您可以在您的.vimrc文件中进行设置。

set expandtab       "Use softtabstop spaces instead of tab characters for indentation
set shiftwidth=4    "Indent by 4 spaces when using >>, <<, == etc.
set softtabstop=4   "Indent by 4 spaces when pressing <TAB>

set autoindent      "Keep indentation from previous line
set smartindent     "Automatically inserts indentation in some cases
set cindent         "Like smartindent, but stricter and more customisable

Vim会根据文件类型智能缩进。尝试将以下内容添加到你的 .vimrc 文件中:

if has ("autocmd")
    " File type detection. Indent based on filetype. Recommended.
    filetype plugin indent on
endif

参考资料


16
这个回答和上一个回答都很棒。但我点赞这个是因为它让我想起了“点”操作符,它可以重复上一个命令。在需要将整个代码块缩进多个空格(或缩进)而不需要一直按 >} 时,这非常有用。非常感谢。 - Amit
1
5>> 缩进5行:该命令缩进第五行,而不是5行。这可能是由于我的VIM设置,还是您的措辞不正确? - Wipqozn
1
@Wipqozn - 这很奇怪。对我来说,它明显缩进了接下来的五行,我在Vim 7.2.330上测试过。 - ire_and_curses
11
请从您所在的位置缩进到第42行。 - Steve
很棒的总结!还要注意,“缩进内部块”和“缩进所有块”(<i{ >a{等)也适用于括号和方括号:>a( <i]等。(顺便说一句,除了<>之外,它们也适用于d、c、y等。) - aqn
你可能需要指出repeat命令是一个点/句号,因为根据字体、人的视力(如果他们疲劳可能会更糟)它可能看起来像其他东西。当我第一次在你的答案中看到它时,我最初感到困惑,因为我本以为它是单引号。这只是一个可能或可能不值得考虑的想法。 - Pryftan

131

一个很大的选择会是:

gg=G

它真的很快,而且所有东西都会缩进;-)


1
我有一个XML文件并打开了语法高亮。键入“gg=G”只会将从位置1开始的每一行放置在一起。所有空格都已被删除。还有其他与XML相关的特殊要求吗? - asgs
2
我认为set cindent应该在vimrc中设置,或者在运行该命令之前运行:set cindent - Amanuel Nega
3
我认为必须首先设置cindent。@asgs,我认为这仅适用于C风格的编程语言。 - Amanuel Nega

114

针对C语言代码的缩进,请尝试以下方法。更多信息请键入:help =

={

这将自动缩进您当前所在的代码块。

或者只需输入:

==

以自动缩进当前行。


2
对我来说不起作用,只是将我的光标转移到了当前代码块的左括号上方。 - underscore_d

85

视觉型人群的按键:

  1. 进入命令模式:
    Esc

  2. 移动到要缩进的区域开头:
    hjkl

  3. 开始一个块:
    v

  4. 移动到要缩进的区域结尾:
    hjkl

  5. (可选)键入您想要的缩进级别数字:
    0..9

  6. 对该块进行缩进:
    >


2
这很好,但它使用空格而不是制表符。有没有可能修复这个问题? - Shane Reustle
13
如果它使用空格而不是制表符,则很可能是因为您设置了缩进以使用空格。=) - Kent Fredric
4
当 'expandtab' 选项关闭时(这是默认设置),Vim 尽可能地使用 <Tab> 来进行缩进。(参见 :help :>) - Kent Fredric
1
我改变过的与tab/空格相关的vim设置只有:set tabstop=3。实际上,每次我使用>>时它都会插入这个:“<tab><space><space>”。缩进块也是一样的。有什么想法吗? - Shane Reustle
3
对于“制表符 vs 空格”你需要查看的三个设置是1. tabstop 2. shiftwidth 3. expandtab。你可能已经设置了“shiftwidth=5 noexpandtab”,这意味着一个“制表符”等于3个空格,缩进级别为“5”个空格,因此它用1个制表符和2个空格组成了5个空格。 - Kent Fredric
显示剩余2条评论

74
除了已经给出并接受的答案之外,还可以放置一个标记,然后将当前光标到标记的所有内容缩进。因此,在您想要缩进块顶部的位置输入ma,向下移动光标直到需要的位置,然后键入>'a(注意,“a”可以替换为任何有效的标记名称)。这有时比5>>vjjj>更容易。

1
这真的很有用。我得查一下这个能做什么。我知道d'a和y'a,还有什么? - user606723
3
这非常有用,因为它避免了需要数一数你想要缩进多少行的情况。 - ziggy
当我尝试时,它缩进了9个空格 - 有没有办法设置缩进多少个空格? - likejudo
这似乎是迄今为止在简单基本的VI编辑器中有效的唯一解决方案! - user109764

69

最强大的命令是
gg=G

这会给整个文件进行缩进!

以下是在Vim或gVim中快速缩进行的一些简单而优雅的命令:

对当前行进行缩进
==

对当前行下面所有行进行缩进

=G

对当前行下方n行进行缩进

n==

例如,要对当前行下面的4行进行缩进

4==

要缩进代码块,请移动到其中之一的括号并使用命令

=%

这些是缩进多行的最简单但强大的命令。


4
这仅适用于 vim,不适用于 vi - rojomoke
3
在我的 Solaris 或 AIX 系统上,它不是这样的。等于号键一直是我标准的即席宏分配之一。你确定你没有看到一个被链接为 vivim 吗? - rojomoke
我非常确定!!看到你的评论后,我打开了“vi”并尝试了我回答中的所有命令,结果如预期。 - Sagar Jain
3
没问题,对于Linux系统来说,vi几乎总是链接到vim。尝试在vi中运行:ve命令。 - rojomoke
4
我喜欢这种回答:清晰、精确且简洁。在Debian Jessie中对我起作用了。谢谢@SJain。 - digitai
1
既然我使用vim而不是vi,我非常高兴这个答案在这里。谢谢。 - Dan Nissenbaum

33

当您选择一个块并使用>进行缩进时,它会缩进然后返回正常模式。我在我的.vimrc文件中有以下内容:

vnoremap < <gv

vnoremap > >gv

它允许您将所选内容缩进任意次数。


17
要将选择区域向右缩进多次,只需按“.”键重复执行上一个命令即可。 - Sundar R
3
在这种情况下,使用“.”的问题在于你需要移动手指。使用@mike的解决方案(我也是用这个)已经让你的手指放在了缩进键上,只需要不断地按它来保持缩进,而不是切换并做其他操作。使用句点需要更长时间,因为你需要移动手部并且它需要更多的思考,因为它是第二个不同的操作。 - masukomi

31

回到文本开头

  • 按下 v 进入可视模式。
  • 使用 上箭头/下箭头 高亮文本。
  • 按下 = 缩进所有你高亮的行。

29

除了提供的解决方案外,我喜欢逐段进行操作,并使用>}代码。


2
是的,这就是为什么我最讨厌在空行上留白:它们会破坏vim对“段落”的概念。 - aqn

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