如何通过 Vim 中的外部命令过滤不跨越整行的可视选择的内容?

Posted

技术标签:

【中文标题】如何通过 Vim 中的外部命令过滤不跨越整行的可视选择的内容?【英文标题】:How to filter the contents of a Visual selection that does not span an entire line through an external command in Vim? 【发布时间】:2012-03-09 16:53:50 【问题描述】:

我想通过命令过滤 Vim 中的视觉选择。我知道的方式总是过滤视觉选择延伸的完整线条:

在该行中选择a test

this is a test

然后打字

:'<,'>!echo "the result"

将导致

the result

但我想要:

this is the result

【问题讨论】:

另见“How to execute ‘base64 --decode’ on selected text in Vim?”。 【参考方案1】:

考虑以下符合! 行为的映射 过滤命令(参见:helpg \*!\*:help v_!)。

nnoremap <silent> <leader>! :set opfunc=ProgramFilter<cr>g@
vnoremap <silent> <leader>! :<c-u>call ProgramFilter(visualmode(), 1)<cr>
function! ProgramFilter(vt, ...)
    let [qr, qt] = [getreg('"'), getregtype('"')]
    let [oai, ocin, osi, oinde] = [&ai, &cin, &si, &inde]
    setl noai nocin nosi inde=

    let [sm, em] = ['[<'[a:0], ']>'[a:0]]
    exe 'norm!`' . sm . a:vt . '`' . em . 'x'

    call inputsave()
    let cmd = input('!')
    call inputrestore()

    let out = system(cmd, @")
    let out = substitute(out, '\n$', '', '')
    exe "norm!i\<c-r>=out\r"

    let [&ai, &cin, &si, &inde] = [oai, ocin, osi, oinde]
    call setreg('"', qr, qt)
endfunction

【讨论】:

非常好!抱歉,我的问题不太准确(同上 kev)。它实际上是针对最常见的情况,在这种情况下我想要同时执行以下操作:1)将视觉选择传递给命令 2)使用短命令在 vim 中指定此命令;即 vim 命令应将示例中的“base64 --decode”作为参数。 换句话说,它应该有效地执行与过滤命令相同的操作!,仅用于视觉选择,而不是完整的行。 @user429540:现在我明白了。查看更新的答案,列出了为实现过滤命令而编写的映射。 我怎么称呼它? :',!回声(我的领导在哪里)?对我来说,它仍然做同样的事情:'!回声(没有领导者)。 @user429540:Leader是一个可配置的key,方便创建映射(见:help mapleader);默认情况下,它是反斜杠字符。上面的映射应该与默认的!过滤使用相同的方式:在可视模式下选择一段文本,然后按您的前导键(同样,默认情况下为反斜杠),然后按!;或不选择任何内容,按下此组合键,然后使用运动命令(例如wW) 等)。【参考方案2】:

您可以使用\%V在可视区域内进行匹配:

:'<,'>s/\%V.*\%V/\=system('echo -n "the result"')

【讨论】:

谢谢,这行得通,但是有点长。以 shell 命令为参数的 vmap 会是什么样子? .. 当然,在我的示例中,该命令不依赖于通常情况下的视觉选择。那么如何将视觉选择作为参数传递给命令呢?

以上是关于如何通过 Vim 中的外部命令过滤不跨越整行的可视选择的内容?的主要内容,如果未能解决你的问题,请参考以下文章

vim的一些常用命令

vim技巧

vim 详解

vim快捷键

如何在可视模式下在外部过滤器命令中使用 vim 变量?

Vim常用快捷键--正常的学习曲线