在Vim中将2位缩进更改为4位


91

我从Internet复制了一些具有2空格缩进的代码,我想将其更改为4空格缩进。我想知道是否有一个简短的vim例程来完成任务而不必编写vim脚本?这是我目前使用HTML文件执行的操作:

  • 录制宏
  • 转到一行的开头
  • 视觉选择所有空格,直到第一次出现“ <”
  • 拉动并粘贴所有空格(基本上是将它们加倍)
  • 重播宏,直到文件末尾

简而言之 qa0vt<yp<esc>jq

陷阱:

宏对于空白行或不以“ <”开头的行失败。而且我不知道如何将该解决方案扩展到非HTML文件。

Answers:


170

更改缩进的一般方法是更改​​制表符:

将文件粘贴到空缓冲区中,然后:

:set ts=2 sts=2 noet
:retab!

这将每2个空格更改为TAB字符,然后:

:set ts=4 sts=4 et
:retab

这会将每个TAB更改为4个空格。

这种方法的优点是您还可以使用另一种方法,例如将4转换为2。


16
@XavierT。我实际上认为这个答案很容易理解。如果将短命令名替换为全名,可能会更清楚ts::= tabstopsts:= softtabstop[no]et:= [no]expandtab
YaOzI 2014年

在什么情况下retab的论点会有用,为什么我们不能将其用于此任务?
joeytwiddle

@joeytwiddle据我所知,您可以使用,并通过使用来达到与该答案相同的效果:set sts=2 noet:retab! 2因此那样会更短(虽然可读性较低)。
达恩·巴克

此方法还将字符串文字和其他位置的2位空格更改为4位空格,而不仅仅是行的开头。
nacitar sevaht

2
将它们放在一起::set ts=2 sts=2 noet | retab! | set ts=4 sts=4 et | retab!然后@:在不同的文件中使用以快速应用相同的操作。
L__16年

58

它可能会以:set shiftwidth=4gg=G


请注意,如果这不起作用,则可能启用了对缩进有其他影响的模式。
达夫·克拉克

1
尽管问题不是关于通用解决方案的问题,但请注意,这并不总是有效的,特别是对于python代码。
2013年

5
究竟gg=G是什么意思?我知道这gg意味着“移至1,1”,也G意味着“移至最后一行”。
乔纳森·莱因哈特

5
@JonathonReinhart =会缩进,所以它只是意味着从文本的开头到结尾缩进
alex

比的效果更好%retab,后者错误地转换了嵌入字符串文字中的空格。
阿里尼塔克

33

我的操作与esneider和cforbish的方法非常相似,但是键入起来要快一些:

:%s/^\s*/&&

只需用两倍的前导空格(&用匹配的表达式替换)替换前导空格(空格或制表符)。


2
这很方便,因为它可以与视觉选择(V)一起使用,只需删除即可%
特雷弗·罗宾逊

1
我喜欢这一个,以及B / C它不惹表的任何手动对齐我有意见等等
stephenmm

@TrevorRobinson前两个答案也适用于范围。
Brian McCutchon 2015年

这还有一个额外的好处,您可以扩展它以使用sed并将其应用到目录superuser.com/a/159286/41494
icc97

3

这是一个非常老的问题,但是所有答案都是错误的……Vim提供了一种非常简单的方法来重新缩进整个文件。我在编写自己的函数后才学到了这一点,所以我在同一条无知的船上;)

类型

gg=G

这是假设您已将Tabstop设置为所需的值(因此,对于OP来说,ts = 4)

我是从http://vim.wikia.com/wiki/Fix_indentation了解到的,

在普通模式下,键入gg = G将重新缩进整个文件。这是一个特例;=是运算符。就像d或y一样,它将对使用光标移动命令移动的任何文本起作用。在这种情况下,gg将光标置于第一行,然后= G从当前光标位置重新缩进缓冲区的末尾。


2
1.如果您一直向下滚动到底部,您将看到一个答案,提及gg = G。2.它并不总是有效。
Lim H.

2

我使用了此正则表达式(它使前导空格的数量加倍):

%s;^\(\s\+\);\=repeat(' ', len(submatch(0))*2);g

不会%s/\s\+/&&/做同样的事情?顺便说一句,我认为该g标志是不必要的(对于一个标志^pattern,每行中只有1个匹配,是吗?)
doubleDown 2013年

感谢您指出“&”。我对您的内容略有修正,主要是因为您忘记了'^' %s/^\s\+/&&/g更近。
cforbish

这类似于spro的答案,但我很感激答案,因为它可以让您在需要做一些更复杂的事情时更加轻松。
stephenmm

1

与cforbish的答案类似(但更简单),此正则表达式将复制前导空格

:%s/^\( \+\)/\1\1

或者,您可以使用此其他正则表达式将2个空格转换为4个空格,并保留单个空格(通常是奇数个)

:%s/^\(\(  \)\+\)/\1\1

那是,

  • 1个空间⇢1个空间
  • 2个空间⇢4个空间
  • 3空间⇢5空间
  • 4空间⇢8空间

0

这是基于正则表达式的答案的变体。

我的本地bin目录中有一个bash脚本,它将使行首的空白量增加一倍。输入可以是stdin或文件:

$ cat ~/bin/dblsp
#!/bin/bash

file=${1--}

while IFS= read -r line; do
    echo "$line" | sed 's/\s*/&&/'
done < <(cat -- "$file")

我通过在视觉上选择一行并发出以下命令在vim中使用此命令:

:'<,'>!dblsp

这使我无需键入(或记住)正则表达式。

我还在如下地图中使用它:

nnoremap <leader>] `[V`]!dblsp<CR>

它将应用于最近粘贴的文本块。我通常使用以下地图粘贴而不是:set paste

nnoremap <leader>p :r !xclip -o<CR>

我通常的工作流程是:

  • 选择代码段(例如,此页面上的示例代码为2个空格,但我想要4个)
  • 粘贴代码段(,p)
  • 更改间距(,])

或者只是更改从另一个缓冲区粘贴的粘贴块的缩进。


0

除了@spro的答案,我还把它放在了我的 .vimrc

command! -range=% Format :<line1>,<line2>s/^\s*/&&

只需键入:Format

通过视觉选择,这只会格式化选定的行。

如果不进行视觉选择,则会格式化整个文件。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.