7

有没有一种简单的方法使用宏或 ~10 行函数(没有插件!)在一行的第一个和最后一个单词(=非空白字符序列)之间居中一些文本?例如转

        >>> No user serviceable parts below.               <<<

进入

        >>>       No user serviceable parts below.         <<<

通过平衡空间+/-1?您可以假设没有制表符,结果不应包含制表符,但请注意,第一个单词可能不在第 1 列中开始。(编辑:...事实上,分隔词以及文本的开头和结尾都居中可能在任意列上。)

4

3 回答 3

7

源这个函数:

fun! CenterInSpaces()
    let l   = getline('.')
    let lre = '\v^\s*\S+\zs\s*\ze'
    let rre = '\v\zs\s*\ze\S+\s*$'
    let sp  = matchstr(l,lre)
    let sp  = sp.matchstr(l,rre)
    let ln  = len(sp)
    let l   = substitute(l,lre,sp[:ln/2-1],'')
    let l   = substitute(l,rre,sp[ln/2:],'')
    call setline('.',l)
endf

笔记

  • 此功能可能不适用于所有情况。我只是为通常的情况快速写了它。毕竟这不是插件

  • 通过组合函数调用可以减少代码行。但我认为这样就很清楚了,所以我就这样放着。

  • 如果它对你有用,你可以创建一张地图

  • 它的工作原理是这样的:(我输入的最后两行@:重复 cmd 调用)

在此处输入图像描述

于 2013-04-05T13:02:10.830 回答
3

您可以将该:s命令与\=aka sub-replace-expression 一起使用。

:s#\v^\s*\S+\zs(\s+)(.{-})(\s+)\ze\S+\s*$#\=substitute(submatch(1).submatch(3),'\v^(\s*)(\1\s=)$','\1'.escape(submatch(2),'~&\').'\2','')#

概述

>>>捕获和<<<标记之间的文本(包括空格) 。将文本两边的空白分成两半,并用中间的非空白文本替换。这种空白平衡行为是通过正则表达式引擎的回溯完成的,因为数学很难。我们去购物吧!

笔记:

  • 使用\vorvery magic模式来减少转义,因为这个命令已经足够长了
  • 用作#替代分隔符而不是通常/的 for:s/pat/sub/以使其更具可读性

匹配模式

:s#\v^\s*\S+\zs(\s+)(.{-})(\s+)\ze\S+\s*$#...
  • :s如果没有提供范围,则仅在当前行上进行替换。
  • ^\s*\S+匹配起始空白,后跟非空白。>>>在这种情况下。
  • (\s+)(.{-})(\s+)匹配空格后跟“文本”后跟空格
  • 3 个捕获组:1)前导空白,2)“文本”,以及 3)尾随空白。这些将在稍后分别由submatch(1)submatch(2)和引用submatch(3)
  • .{-}是 vim-speak 用于非贪婪匹配或.*?perl-speak
  • 如果没有非贪婪匹配,第二个捕获组将在其末尾包含太多空白
  • \S+\s*$匹配非空白(即<<<)和任何尾随空白
  • 使用\zsandze指定要替换的比赛的开始和结束

替换

\=substitute(submatch(1).submatch(3),'\v^(\s*)(\1\s=)$','\1'.escape(submatch(2),'~&\').'\2','')
  • \=告诉 vim 替换将是一个 vim 表达式。还允许使用submatch()函数
  • substitute({str}, {pat}, {sub}, {flags})我们的表达式将是一个嵌套替换
  • substitute(submatch(1).submatch(3), ...)submatch(1)对在和中捕获的前导和尾随空白的串联进行替换submatch(3)
  • {pat}^(\s*)(\1\s=)$。_ 匹配一些空格,后跟与第一个或 1 个字符长度相同的空格。捕获两半。
  • escape(submatch(2),'~&\')任何特殊字符的转义submatch(2)。例如~, &, \1, ...
  • {sub}'\1'.escape(submatch(2),'~&\').'\2'。_ 替换submatch(2)为空格之间的转义(即我们想要居中的“文本”),\1\2{pat}
  • 不需要{flag},所以''

用法

如果您经常使用它,我建议您创建一个命令并将其放入~/.vimrc.

command! -range -bar -nargs=0 CenterBetween <line1>,<line2>s#\v^\s*\S+\zs(\s+)(.{-})(\s+)\ze\S+\s*$#\=substitute(submatch(1).submatch(3),'\v^(\s*)(\1\s=)$','\1'.submatch(2).'\2','')#`

否则使用一次,然后&在每个需要的行上重复最后一次替换。

如需更多帮助,请参阅

:h :s/
:h :s/\=
:h sub-replace-\=
:h submatch(
:h substitute(
:h escape(
:h /\v
:h /\S
:h /\{-
:h /\zs
:h &

肯特编辑

不要嫉妒,你的答案也有。^_^

我没有更改命令,只是 cp/paste 到我的 vim。仅|noh在末尾添加以禁用突出显示。

如果执行这个命令,它看起来像:

在此处输入图像描述

于 2013-04-05T21:48:44.227 回答
1

不知道有什么好办法。我通常以半自动的方式进行,通过:center在仅包含要居中的部分的文本行上使用,然后将结果移动到包含周围部分的行中。

如果没有其他人有更好的答案,如果您需要做很多此类事情,也许盒子可以提供帮助。

于 2013-04-05T12:06:52.383 回答