我目前正在写很多纯文本(以及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稍微聪明一点。

#1 楼

'formatexpr'选项

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


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


正确设置'formatexpr'既可以在使用gq时又可以在插入文本时使用。

一个简单的例子

这里有一个简单的VimScript函数和相应的'formatexpr'值可以完成此工作。我尚未在所有边缘情况下都对其进行过测试,但它对我的简单测试非常有效。

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年4月8日在2:39

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

–内森·朗(Nathan Long)
16年5月21日在11:13



这在例如例如等等,布拉等人。 2018年这有点烦人。您可以使用's / \(e \ .g \ | \\
–naught101
18年2月14日在2:18

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

–naught101
19年1月15日在1:17

#2 楼

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

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函数即可。

#3 楼

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

评论


或者有一个钥匙可以在需要时将j和k重新映射为gj和gk ;-)

–安东尼
19-10-2在6:07

#4 楼

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