如何在Vim中取消文本自动换行?

40

我通常在编辑文件时使用tw=80选项,特别是LaTeX源代码。但是,假设我想在Vim中使用tw=80选项撰写电子邮件,然后将其复制并粘贴到Web浏览器中。在复制和粘贴之前,我想取消文本换行,以便每80个字符左右没有换行符。我尝试了tw=0,然后使用gq,但那只是将文本包装到默认宽度为80个字符。我的问题是:如何取消文本换行,使得我的每个电子邮件段落都显示为单行?是否有一个简单的命令可以实现这一点?

3个回答

65

回到段落开头并输入:

v i p J

(如果不清楚,J是大写字母)

对于整个文档,请与norm命令结合使用:

:%norm vipJ

这个命令只会取消段落的包裹。我想这就是您想要的行为。


谢谢!我想这是目前最简单的方法了吧?我猜没有一次性为整个文档完成此操作的方法,对吗? - Ray
2
@Ray,我已经编辑了我的答案,并添加了执行整个文档的命令。 - Fatih Arslan
2
在这种情况下最好使用带有!说明符的:normal命令,以避免与自定义映射发生冲突。 - ib.
4
就这个问题而言,你不需要回到段落的开头。该命令中的“ip”代表的是获取整个段落的内容,无论你是否在段落的开头位置。请注意,这并不改变原文的意思。 - Derek
@Derek,你说得对。我知道像at、iB等这样的移动标签(将移动与i和a结合起来)。但我想给出一个清晰的答案,没有任何干扰。 - Fatih Arslan
哇!我不想对每一行使用 J。我应该知道我可以用 Vim 来 J 多个。更重要的是,你可以在之后进入下一个段落并按 . - young_souvlaki

11

由于使用普通模式命令连接段落行已经在另一个答案中涵盖,让我们考虑通过基于行的Ex命令解决相同的问题。

假设光标位于段落的第一行。然后,要取消换行,可以简单地将以下行连接起来,直到该段落的最后一行。一种方便的方法是运行专门设计用于此目的的:join命令。除了明显的起始行(即当前行),还需要指定结束行来定义命令要操作的行范围。可以使用匹配段落结尾的模式来找到它,也就是两个连续的换行符,或者等效地,一个换行符后面跟着一个空行。因此,将上述定义翻译成Ex命令语法,我们得到:

:,-/\n$/j

要将所有段落都解开,可以在每个段落的第一行上运行此命令。一个有用的工具来跳转到它们,重复一系列的动作,是:global命令(或简称:g)。由于:global从上到下扫描行,下一个段落的第一行就是那些剩余未处理的行中的第一行非空行。这个观察结果给出了以下命令

:g/./,-/\n$/j

相对于其直接的正常模式(Normal-mode)对应物,这种方式更加高效。


这个命令有一个小错误:如果你有一个单行段落,它会粘在下一个段落的开头。 - Omar Antolín-Camarena
1
@Omar:非常好的发现,谢谢!答案已更新以解决这种情况。 - ib.
我一开始按照@fatih的回答来做,但由于某种原因它会把非常短的段落连接在一起,所以我来这里寻找替代方案,这个很好用,谢谢! - dbmrq

6
< p > 使用:%norm vipJ的问题在于,如果您有连续的行长度小于80个字符,它也会将它们连接起来,即使它们被空行分隔开。例如以下示例:

# Title 1

## Title 2

Will become:

# Title 1 ## Title 2

使用ib的答案后,问题出在列表上:

- item1
- item2

Becomes:

- item1 - item2

感谢这篇论坛帖子,我发现了另一种方法来实现这个功能,我将其封装在一个函数中,这个函数对我来说更好用,因为它不会执行任何操作:

function! SoftWrap()
    let s:old_fo = &formatoptions
    let s:old_tw = &textwidth
    set fo=
    set tw=999999 " works for paragraphs up to 12k lines
    normal gggqG
    let &fo = s:old_fo
    let &tw = s:old_tw
endfunction

编辑:更新了方法,因为我意识到它在Linux环境下无法工作。如果这个新版本不能与MacVim一起使用(我没有测试的方法),请删除包含fo的行。


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