将视觉选区发送到外部程序而不影响缓冲区

4
我想要实现的是将视觉选择发送到外部程序,而不影响缓冲区内容。
示例
让以下代码块表示当前缓冲区。让[<]表示视觉选择的开始,[>]表示结束。
This is not a test 1
[<]This is not[>] a test 2
This is not a test 3
This is not a test 4

我希望能将此文本发送到外部程序,例如:

:<some vim command>!<some shell command>

近乎解决方案?

一个几乎可行的解决方案是:

:[range]w ! cat | <some shell command>

这适用于逐行发送内容,例如:
:%w ! wc -l      # produces --> '4'
:2,3w ! wc -l    # produces --> '2'
:2w ! wc -w      # produces --> '6'

然而,使用上述缓冲区作为示例:
:'<,'>w ! wc -w  # produces --> '6'

但我希望有一种方法可以产生数字“3”,并且不会影响缓冲区的内容。

有什么想法吗?


2
如果你的目标是计算 Visual 选择中的单词数,那么请注意,Vim 中有一个内置命令可以实现:选择文本后按 g CTRL-G。参见:h v_g^g - glts
谢谢。知道了。但我只是举了一个例子命令,因为它的输出非常易读。 - Douglas Anderson
2个回答

9

范围始终是按行排序的。

无论你做什么,每个接受范围的 Ex 命令都将始终将'<作为起始'>作为结束

像这样将非行向选择传递给外部程序:

  • 备份寄存器的内容
  • 将选择复制到该寄存器中
  • 将该寄存器的内容传递给 system() 并输出结果
  • 恢复寄存器

以下是一个函数示例:

function! VisualCountWords() range
    let n = @n
    silent! normal gv"ny
    echo "Word count:" . system("echo '" . @n . "' | wc -w")
    let @n = n
    " bonus: restores the visual selection
    normal! gv
endfunction

您可以在这样的映射中使用它:
xnoremap <F6> :call VisualCountWords()<CR>

此外,你使用 cat 命令是无用的

:[range]w ! cat | <some shell command>

should be:

:[range]w ! <some shell command>

gv"ny 是做什么的? - geckos
1
@geckos的gv重新选择上次的可视选择,"ny将其复制到寄存器n - romainl

1
select...
<esc>
:exe '!echo '.string(lh#visual#selection()).' | wc -w'

看起来能解决问题。

使用来自lh-vim-liblh#visual#selection()


1
使用 shellescape(..., 1)string() 更加合适。 - Ingo Karkat

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