如何设置Vim以每行一个句子使用?


17

我目前正在写很多纯文本(以及LaTeX,段落中的格式最少),如果可以设置vim保留每个句子(为简单起见,文本以'。','!或“?”;这是一个终止标点符号,后跟一个空格,以避免在其自己的行上出现小数点),因此VCS差异将更加有用。

最少,我想gq格式化以下文本:

He lay flat on the brown, pine-needled floor of the forest, his chin on his
folded arms, and high overhead the wind blew in the tops of the pine trees.
The mountainside sloped gently where he lay; but below it was steep and he
could see the dark of the oiled road winding through the pass. There was a
stream alongside the road and far down the pass he saw a mill beside the
stream and the falling water of the dam, white in the summer sunlight. 

至:

He lay flat on the brown, pine-needled floor of the forest, his chin on his folded arms, and high overhead the wind blew in the tops of the pine trees.
The mountainside sloped gently where he lay; but below it was steep and he could see the dark of the oiled road winding through the pass.
There was a stream alongside the road and far down the pass he saw a mill beside the stream and the falling water of the dam, white in the summer sunlight.

但是如果vim在键入时也执行这种格式设置(就像它对textwidth reflow一样),那就太好了。这可能吗?

我当前的解决方案是使用来加入一个段落J,然后运行:'<,'>s/\. /.\r/g,由于没有感叹号和问号,因此运行起来相当不错,但是如果我可以使gq稍微聪明一点会更好。

Answers:


23

'formatexpr'选项

您可以使用该'formatexpr'选项来实现。从帮助中:

该表达式被评估为gq运算符格式化行范围或自动格式化(请参阅“ formatoptions”)。如果此选项为空,则使用'formatprg'。

'formatexpr'使用gq和插入文本时都可以正确设置您的设置。

一个简单的例子

'formatexpr'是应该执行的简单VimScript函数和相应的值。我尚未在所有极端情况下进行过测试,但是对于我的简单测试而言,它工作得很好。

function! MyFormatExpr(start, end)
    silent execute a:start.','.a:end.'s/[.!?]\zs /\r/g'
endfunction

set formatexpr=MyFormatExpr(v:lnum,v:lnum+v:count-1)

说明

该表达式是对函数的调用MyFormatExpr(),传入将在其上应用格式的开始和结束行。这些行是使用自动填充的变量v:lnum(要格式化的第一行)和v:count(要格式化的行数)计算的。

MyFormatExpr()函数构造一个:substitute与范围内的所传递的指令,并替换一个空白以下结束句子的标点符号(.!,或?以新行)( \r)。

注意事项

  • MyFormatExpr()函数不保留前导缩进。需要一些更复杂的逻辑来解决此问题。
  • 在其他情况下,这可能会崩溃。试一下,并根据需要进行调整!

哦,是的,这完全是要走的路,请忽略我的回答。
Sukima 2015年

这太棒了!我希望我能做的是让函数运行一个宏,例如“前进到下一个句子)并插入换行符;重复直到到达范围的结尾。” 然后大概会应用任何缩进规则。但是我的Vim-fu太弱了。:)
内森·朗

这在上分开e.g. blahBlah et al. 2018这有点烦人。您可以使用取消匹配类似的模式's/\(e\.g\|\<al\)\@<![.!?]\zs /\r/g'。只需在第一组中添加更多模式即可避免其他您不想拆分的事情。否则,这非常有用,谢谢。我以前没看过gqgqip对于格式化合著者的文本编辑器所破坏的文本非常有用。
naught101 '18

有没有一种方法可以将此行为添加到默认行为?我希望能够以给定的文本宽度换行,以及在句子的末尾拆分
。.– naught101

1

好了,您可以设置一些地图和自动命令:

function! AddSentenceMaps()
  imap .<Space> .<CR>
  imap !<Space> !<CR>
  imap ?<Space> ?<CR>
  exec "nmap gq vipJ:s/\\([.!?]\\)\\s\\+/\\1\\r/g<CR>"
endfunction

autocmd Filetype customtxt call AddSentenceMaps()

然后只需将文件类型设置为customtxt或AddSentenceMaps手动调用该函数即可。


0

我想对这个问题发表自己的看法。通常,人们希望使用这种功能,因为当使用jk命令浏览代码时,跳过了换行,这是Vim的默认行为。对于通过包装线的导航,我使用gj-向下gk移动-向上移动。也有可能在g前缀的对应项上重新映射标准jk命令,但是恕我直言,这可能会过大。


或有一键做的是重映射j,并kgjgk当你想它;-)
安东尼

0

它没有回答您有关重新格式化的具体问题,但是“设置换行”和“设置换行符”可以使编辑长行变得更加愉快。将其与gj和gk结合使用可在包装线内导航。我将向上和向下箭头分别映射到gj和gk,以便在上下移动实线或可视线之间进行选择。对于Home / End to g0 / g $一样明智。

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.