Vim 中的智能换行

99

我一直在想,Vim是否具有智能换行代码的功能,以便它保持与正在缩进的行相同的缩进。我在其他一些文本编辑器上注意到了这一点,例如e-text编辑器,发现它帮助我更轻松地理解我所看到的内容。

例如,不是:

<p>
    <a href="http://www.example.com">
        This is a bogus link, used to demonstrate
an example
    </a>
</p>

它看起来是这样的

<p>
    <a href="somelink">
        This is a bogus link, used to demonstrate
        an example
    </a>
</p>

请参见https://dev59.com/0HRA5IYBdhLWcg3w_C8w。 - ergosys
你应该重新审查答案,因为情况已经改变了。 - user636044
1
使用 :set autoindent:set smartindent - Shammel Lee
8个回答

83

这个功能已经在2014年6月25日作为7.4.338的补丁实现。紧接着出现了几个补丁来完善这个功能,最后一个是7.4.354版本,所以你需要使用这个版本。

:help breakindent
:help breakindentopt

以下是来自vim帮助文档的摘录:
'breakindent'     'bri'   boolean (default off)
                          local to window
                          {not in Vi}
                          {not available when compiled without the |+linebreak|
                          feature}
        Every wrapped line will continue visually indented (same amount of
        space as the beginning of that line), thus preserving horizontal blocks
        of text.

'breakindentopt' 'briopt' string (default empty)
                          local to window
                          {not in Vi}
                          {not available when compiled without the |+linebreak|
                          feature}
        Settings for 'breakindent'. It can consist of the following optional
        items and must be seperated by a comma:
                  min:{n}     Minimum text width that will be kept after
                              applying 'breakindent', even if the resulting
                              text should normally be narrower. This prevents
                              text indented almost to the right window border
                              occupying lot of vertical space when broken.
                  shift:{n}   After applying 'breakindent', wrapped line
                              beginning will be shift by given number of
                              characters. It permits dynamic French paragraph
                              indentation (negative) or emphasizing the line
                              continuation (positive).
                  sbr         Display the 'showbreak' value before applying the 
                              additional indent.
        The default value for min is 20 and shift is 0.

与此相关的是showbreak设置,它将在您指定的字符后缀中加上您的移位量。

示例配置

" enable indentation
set breakindent

" ident by an additional 2 characters on wrapped lines, when line >= 40 characters, put 'showbreak' at start of line
set breakindentopt=shift:2,min:40,sbr

" append '>>' to indent
set showbreak=>>   

行为说明

如果您不指定sbr选项,则任何showbreak字符都会被附加到缩进处。从上面的示例中删除sbr会导致有效缩进为4个字符;如果您只想使用showbreak而没有额外的缩进,请指定shift:0

您还可以给出负数的shift值,这将使showbreak字符和换行文本回到任何可用的缩进空间中。

在指定min值时,如果终端宽度更窄,则移位量将被压缩,但showbreak字符始终被保留。


2
简而言之,在您的vim配置中添加“set breakindent”将使行在缩进处断行和换行,而不是像新行一样断行并开始下一行。 - james2doyle
3
在您的 Vim 配置中添加set breakindentopt=shift:4将会使额外缩进 4 个空格。 - fritzo
这个答案可以通过添加更多breakindentopt的示例来帮助理解。从帮助文档中无法明显看出其语法。感谢@fritzo在评论中提供的示例。 - Mnebuerquo
链接已损坏。 - undefined

35

我非常希望能做到这一点,我将使HTML标记更易读。 - Jose Elera
我在那个网站上没有看到任何补丁。还有其他人可以确认吗? - puk
显然,该网站最近进行了重建,这些链接已经失效。该网站上有一篇最新的博客文章,其中包含了一个更新的补丁。 - ergosys
1
这真的很遗憾。我不明白为什么这不在主线中,特别是补丁写得非常好。 - cseelus
2
感谢 @Vitor Eiji 的更新。这是个好消息。 - ergosys

18

我认为无法完全保持相同的缩进,但您仍可以通过设置“showbreak”选项来获得更好的视图。

:set showbreak=>>>

示例:

<p>
    <a href="http://www.example.com">
        This is a bogus link, used to demonstrate
>>>an example
    </a>
</p>

实际效果比上面的示例代码要好,因为Vim会为'>>>'使用不同的颜色。


6
您还可以使用:set showbreak=\ \ \ \ \ \ \ \ \ \ \ \ \ \(反斜杠和空格的组合使换行符成为空格。因此,您可以添加足够的空格,使其比大多数自动换行的代码更深(例如,10个空格比2个四空格制表符深,14个空格比3个四空格制表符深);空格的一个好处是它的视觉分散性较小(如果这是您想要的)。 - Jeromy Anglim
8
@Jeromy Anglim 一个小修正:set showbreak=\ \ \ \ \ \ \ \ \ \ \ \ \ \ let &showbreak=repeat(' ', 14)难以阅读。 - ZyX

9

更新:2014年6月,Vim(版本7.4.346或更高版本)合并了支持breakindent选项的补丁以获得最佳支持。


你可以尝试使用:set nowrap,这将允许vim通过向右滚动来显示长行。这对于检查文档的总体结构可能很有用,但实际编辑可能不太方便。
其他接近你所寻找的选项是linebreakshowbreak。使用showbreak,您可以修改在换行的行左边缘显示的内容,但不幸的是它不允许根据当前上下文进行可变缩进。

5
我知道的唯一方法是使用回车符(如Cfreak所提到的),并结合各种缩进选项来使用textwidth选项。如果您的缩进已正确配置(在HTML语法中默认情况下是这样,但否则请参见autoindentsmartindent选项),您可以:
:set formatoptions = tcqw
:set textwidth = 50
gggqG

如果您对formatoptions设置进行了任何自定义,那么最好的方法可能是简单地执行以下操作:

:set fo += w
:set tw = 50
gggqG

这是做什么的:

:set fo+=w  " Add the 'w' flag to the formatoptions so 
            " that reformatting is only done when lines
            " end in spaces or are too long (so your <p>
            " isn't moved onto the same line as your <a...).
:set tw=50  " Set the textwidth up to wrap at column 50
gg          " Go to the start of the file
gq{motion}  " Reformat the lines that {motion} moves over.
G           " Motion that goes to the end of the file.

请注意,这与软换行不同:它将在源文件和屏幕上都换行(当然,如果您不保存它的话就不会)。可以添加其他设置到formatoptions中,以便在键入时自动格式化:详见:help fo-table
更多信息,请参见:
:help 'formatoptions'
:help fo-table
:help 'textwidth'
:help gq
:help gg
:help G
:help 'autoindent'
:help 'smartindent'

3
:set smartindent
:set autoindent

我认为你仍然需要使用“return”关键字


2

宏解决方案:


编辑:

操作gq{motion}会自动格式化为变量“textwidth”设置的任何内容。这比使用我宏中的80lBi^M更容易/更好。


如果启用了自动缩进

:set autoindent

在一行的末尾输入回车键会使下一行缩进相同的距离。如果您愿意,可以使用此功能来进行硬换行。以下宏利用此功能自动缩进您的文本:

将寄存器z设置为:

gg/\v^.{80,}$^M@x (change 80 to whatever length you want your text to be)

并将寄存器 x 设置为:

80lBi^M^[n@x (change 80 to whatever length you want your text to be)

然后执行。
@x   

激活宏后,几秒钟后您的文本将全部转换为每行80个字符或更少的正确缩进的行。

解释:

这是宏的分解:

第一部分(宏z):

gg/\v^.{80,}$^M@x

gg - start at the top of the file (this avoids some formatting issues)
/  - begin search
\v - switch search mode to use a more generic regex input style - no weird vim 'magic'
^.{80,}$ - regex for lines that contain 80 or more characters
^M - enter - do the search (don't type this, you can enter it with ctrl+v then enter)
@x - do macro x

第二部分(宏x):

80lBi^M^[n@x

80l - move right 80 characters
B   - move back one WORD (WORDS include characters like "[];:" etc.)
i^M - enter insert mode and then add a return (again don't type this, use ctrl+v)
^[  - escape out of insert mode (enter this with ctrl+v then escape)
@x  - repeat the macro (macro will run until there are no more lines of 80 characters or more)

注意事项:

  • 如果有一个单词超过80个字符,此宏将会出错。

  • 此宏不会聪明地缩进标签后面的行。

  • 使用lazyredraw设置(:set lazyredraw)可以加快速度。


2
如果您的 HTML 格式足够良好,将其通过 xmllint 可能会有所帮助:
:%!xmllint --html --format

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