在Vim中为列插入缩进

时间:2011-09-23 12:36:48

标签: vim text formatting

使用Vim我真的是视觉模式的粉丝,它允许你在列之前插入文本。

在箭头后插入一些间距,

> one
> two
> three

可以通过<Ctrl-V>jjI <Esc>

完成
>   one
>   two
>   three
  • 转到可视模式<Ctrl-V>
  • 扩展视觉选择jj
  • 插入一些空格I__
  • 将更改传播到块状视觉选择<Esc>
  • 的所有行

现在我有一个需要格式化的文本文件。这就是它的样子:

start() -- xxx
initialize() -- xxx
go() -- xxx

现在我想对齐此部分文本,将其排列成如下列:

start()       -- xxx
initialize()  -- xxx
go()          -- xxx

我遇到的问题是我无法在每行中插入不同数量的缩进,只是缩进固定数量的空格/制表符是不够的。 如何缩进所有缩进文本必须在同一列对齐?


编辑:我只想出一个相当冗长而笨拙的方法:

  • 找到要缩进的字符串位置:\--
  • 在此之前插入n(假设为20)空格:20i <Esc>
  • 将这些空格的一部分删回某个列(假设为15):d|15
  • 将这些步骤保存为宏,并根据需要经常重复宏,

......非常丑陋!

5 个答案:

答案 0 :(得分:14)

没有任何vim插件我会好多了。 这是我的解决方案:

<Shift-V>jj:!column -ts --

然后将--插入多行,就像您在问题中所写的一样。


您还可以在插入时添加一些注释。

:set virtualedit=all

<Ctrl-V>jjA-- xxx<Esc>

答案 1 :(得分:4)

您必须使用特定的插件,在这种情况下,您可以使用TabularAlign插件。

它们都允许您在特定字符上对齐文本,例如示例中的--。他们的语法有点不同。选择最适合你的那个。

答案 2 :(得分:3)

没有插件,如果你已经在没有emix解决方案的情况下输入了你的评论:

:,+2 s/--/                                    &

这将确保所有注释都向左移动,以便正确对齐它们。

然后按块顺序选择要与文本对齐的列,并:100<

答案 3 :(得分:3)

在列中对齐文字的简便方法是使用TabularAlign 插入。如果这些都没有准备就绪,可以使用以下内容 有点棘手(有点笨拙的外观)但完美的工作(为 有问题的情况)命令。 1,2

:let m=0|g/\ze -- /let m=max([m,searchpos(@/,'c')[1]])
:%s//\=repeat(' ',m-col('.'))

第一个命令的目的是确定列的宽度 分隔符的左边(我假设这里是--)。宽度是 计算为第一列中文本长度的最大值 所有的线条。 :global命令用于枚举行 包含分隔符(其他行不需要对齐)。 \ze 原子位于模式开始之后,设置结束 在它开始的同一位置匹配(参见:help \ze)。改变了 匹配的边界不会影响:global命令的工作方式, 模式是以这种方式编写的,只是为了满足下一个需求 替换命令:由于这两个命令可以共享相同的模式, 它可以在第二个中省略。

在匹配的行

上运行的命令
:let m=max([m,searchpos(@/,'c')[1]])

调用searchpos()函数来搜索父级中使用的模式 :global命令,以获取匹配的列位置。模式 使用最后一个搜索模式寄存器(参见@/)称为:help "/。这利用了:global命令更新的事实 /一旦开始执行就会注册。 c标志作为传递 searchpos()调用中的第二个参数允许第一个匹配 一行的字符(:global将光标定位在最开头 执行命令的行),因为可能没有文本 在分隔符的左侧。 searchpos()函数返回一个列表,即 第一个元素是匹配位置的行号,以及 第二个是列位置。如果命令在一行上运行,那么该行 匹配包含:global命令的模式。正如searchpos()那样 为了寻找相同的模式,该行肯定有匹配。 因此,只有开始匹配的列才有意义,所以它得到了 通过[1]下标从返回列表中提取。这个位置 等于行第一列中文本的宽度加一。 因此,m设置为其当前值和列位置的最大值。

第二个命令,

:%s//\=repeat(' ',m-col('.'))

在包含的所有行上填充第一次出现的分隔符 它,以及在之前制作文本时缺少的空格数 分隔符,取{1}个字符,减1。这个命令是全局的 替换替换分隔符之前的空间隔(请参阅 评论上面的m命令)和评估结果 表达式(见:global

:help sub-replace-\=

repeat(' ',m-col('.')) 函数重复其第一个参数(作为字符串)的数量 在第二个论点中给出的时间。因为每次替换光标都是 移动到模式匹配的开始,repeat()完全等于 将分隔符向右移动以对齐列所需的空格数 (m-col('.')返回光标的当前列位置。


1 下面是这对命令的单行版本。

col('.')

2 在以前的答案修订版中,命令曾经是 如下:

:let m=0|exe'g/\ze -- /let m=max([m,searchpos(@/,"c")[1]])'|%s//\=repeat(' ',m-col('.'))

对这些特定命令感兴趣的人可以找到详细信息 编辑史上的描述。

答案 4 :(得分:0)

这是对Benoit答案的修改,有两个步骤。

第一步,阻止选择文本搜索和替换 - 使用大量空格。

'<,'>s/--/                         --/

现在所有评论都应该有很多空格,但仍然不均匀。

第二步,阻止再次选择文本并使用另一个正则表达式匹配您要保留的所有字符(比如前20个字符左右)以及后面的所有空格,并将其替换为前20个字符的副本字符:

'<,'>s/\(.\{20}\)\s*/\1/

不像Benoit那么容易,但我无法弄清楚如何让他的第二步工作。