有没有一种方法,在将vim缓冲区复制到剪贴板之前,将sed转换应用于它?

4
我正在使用以下命令将文档中的所有文本行复制到系统剪贴板:
%y+

通常,特别是为了将代码复制到 StackOverflow ;),我会对我的缓冲区进行 sed 转换,以便更容易地使用 MarkDown 粘贴:
%s:^:\t:g

有没有一种方法可以链接命令,而不实际将其应用于我的缓冲区,只应用于复制的文本?

1
+1 for :%y+ -- 我之前一直沿用着 gg"+yG 这种糟糕的习惯,因为...我总是忘记大多数行内正常命令都有简洁的 ex 版本 :)。使用 :%y+ 的另一个巨大优势是可以立即通过 @: 重复执行。 - sehe
1
这是个修辞问题吗?现在对我来说似乎有点混淆。:%y+ 显然更快。然而,ex 命令通常使用较少,因此它可能只是“要记住的另一件事情”? - sehe
我想这是个修辞问题。我是vim的新手,但很快就爱上了它作为编辑器。它只是...太...棒了... - Naftuli Kay
@TK Kocheran,之前提出的同样问题已经有另一个被选中的答案了:https://dev59.com/PXRA5IYBdhLWcg3wyBD1#830075 ... - Luc Hermitte
世界上似乎确实有正义 ;) - Naftuli Kay
显示剩余2条评论
3个回答

6
我建议使用CLI实用程序将其复制到剪贴板:以前我找过几个,但这里是其中之一: 所以你需要执行以下命令:
:%!sed 's:^:\t:g`|xclip

或者

:%!sed 's:^:\t:g`|xclip -selection c

后者使用 X 剪贴板而不是主剪贴板(假设 UNIX)。

在 Windows 上,可能有类似的实用程序。

编辑

一个纯 vim 解决方案如下:

:let @+=substitute(join(getbufline("%", 1, "$"), "\r\n"), "^\\|\n", "\&\t", "g")

注意:

  • 虽然不是非常高效(但你使用它在 SO 的帖子中...所以不是荷马的奥德赛)
  • 我假设你想要 Windows 行尾符(这就是我从 SO 复制时得到的)

哦,好的。我不知道从vim内部使用外部命令有多容易,因为我对它还比较新。如果我早知道这一点,那么离胜利只有一个sed 's:^:\t:g' | xclip -selection clipboard的距离了。没有vim本地解决方案可用吗? - Naftuli Kay
1
我更喜欢简单的 :%s/^/\t/|%y+|u 命令,而不是这两个解决方案中的任何一个。(尽管它会向撤销列表中添加一个新条目。) - ib.

3

如果您不介意将条目添加到撤销列表中(这意味着实际编辑缓冲区的内容),则可以执行替换,复制文本,并在一个命令中撤消该替换。

:%s/^/\t/|%y+|u

另一个解决方案是在复制后直接在+寄存器的内容中进行替换。
:%y+|let@+=substitute(@+,'^\|\n\zs','\t','g')

1
最后一个选项可以说是在此页面上看到的所有好方法中最佳的选择。这里有一些关于 Vim 的绝妙技巧! - sehe
1
我非常喜欢第一条命令,这就是我会去执行的方式 :) - Naftuli Kay
@sehe:谢谢!甚至还有更多的方法可以做到这一点——例如,看看我对Benoit答案的最后评论。 - ib.

2
如果shiftwidth等于4且expandtab被设置,我会这样做:
:set guioptions+=a
ggVG>gv

7个按键并不算太糟糕。当然,这里没有 ex 命令。如果你想要 ex 命令,可以执行以下操作:

function! ToSo()
    %y +
    let @+ = "    " . substitute(@+, '\n', "\n    ", 'g')
endfunction
command! -nargs=0 ToSo :call ToSo()<Enter>

然后:

:ToSo

将任何您想要的内容放入剪贴板中


有趣的是,我没有想到在“behave xterm”下使用“:se go+=a”会影响Windows剪贴板。然而,它确实会这样做。我肯定会讨厌它覆盖我的剪贴板,但我会尝试一下看看它是否适合我。它有潜力成为一种习惯破坏者。很有意思。 - sehe
需要一个辅助寄存器吗?为什么不直接使用%y+|let@+=substitute(@+,'^\|\n\zs',"\t",'g')呢?(顺便说一下,你错误地恢复了寄存器的内容--想象一下x包含从块可视模式中复制的文本。) - ib.
@ib:是的,我应该使用getregtypegetregsetreg来完成它。你说得很对,我确实可以只用+寄存器来完成它,但由于我有一个剪贴板监视应用程序(Ditto),这样会在历史记录中填充一个不必要的项目。 - Benoit
@Benoit:嗯,在剪贴板监视应用程序中复制项目可能会很烦人。如果是这种情况,您可以尝试:redir=>s|sil%p|redir END|let@+=s或类似第二个@sehe的解决方案。 - ib.

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