用命令输出替换可视选择

时间:2018-09-24 07:41:22

标签: vim

我想用选择的结果通过管道传递到命令中来替换一行的一部分。

例如:

echo "hello $(echo "world" | base64)" | vim -

这将打开其中包含hello d29ybGQK的缓冲区。现在按wvw以可视方式选择d29ybGQK

然后,我尝试:!base64 -d,并且希望缓冲区包含hello world,但没有发生。确实,整行都通过管道传递到命令中,并且替换了整行。

是否可以仅替换视觉选择,并且仅将该选择通过管道传递到命令中?

我也尝试了c<c-r>=system('base64 -d'),但是没有将视觉选择发送到命令的标准输入。

2 个答案:

答案 0 :(得分:4)

使用!进行过滤始终是逐行的。您使用c和 表达式寄存器是解决此问题的绝佳方法。你才忘了 将输入传递给system(),这是它的第二个可选参数。

由于您刚刚更改了所选文本,因此它进入了"寄存器 自动。您需要做的就是将其取回并传递给 getreg()的系统:

c<C-R>=system('base64 -D', getreg('"'))

请注意,base64可能在末尾添加换行符。如果要删除 可以将整个内容包装在trim()中,这是Vim 8中的新功能,或者 使用[:-2]

c<C-R>=trim(system('base64 -D', getreg('"')))
c<C-R>=system('base64 -D', getreg('"'))[:-2]

这是[0:-2]的简写,意味着从角色那里抢走一切 从0到倒数第二个字符串。

如果经常使用,请考虑创建视觉地图:

vnoremap <leader>d c<C-R>=system('base64 -D', getreg('"'))[:-2]<CR>

答案 1 :(得分:1)

出于历史原因, Ex命令本质上是基于行的。尊敬的 vi 还没有可视模式。该限制包括使用:range!通过外部命令进行过滤;它将始终过滤整行。

手动解决方案

对于像您的示例这样的简单输入,临时拆分行,过滤然后重新组装可能是最简单的。例如:

:substitute/ /\r/ | execute '.!base64 -d' | -1join

插件解决方案

对于通用解决方案,您需要使用或实现一个插件,该插件可抓取所选文本,对其进行过滤(可能通过system()进行过滤),然后用结果替换所选内容。

我的SubstituteExpression plugin有一个{Visual}g=映射,可以映射Vimscript表达式,Vim函数和命令以及外部命令。

Tom McDonald的

express.vim提供了几乎相同的实现。它还允许通过:MapExpress:MapSubpress动态创建运算符,而我将使用TextTransform plugin来创建运算符,无论如何,您都需要将其安装为依赖项。我的插件提供了更高级的(跨模式)重复和:Ex-命令表达式变体,但您还需要安装两个大的依赖项。