Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending visual selection to external program without affecting the buffer

Tags:

vim

What I am trying to achieve is sending visual selections to external programs without affecting the contents of the buffer.

Example

Let the following code block represent the current buffer. Let [<] represent the start of visual selection, and [>] represent the end.

This is not a test 1
[<]This is not[>] a test 2
This is not a test 3
This is not a test 4

From this I would like to send this text to external program. e.g:

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

The Almost Solution?

A solution that almost works is:

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

This works for sending things linewise. For example:

:%w ! wc -l      # produces --> '4'
:2,3w ! wc -l    # produces --> '2'
:2w ! wc -w      # produces --> '6'

However, using the example buffer above:

:'<,'>w ! wc -w  # produces --> '6'

But I would like something that to produces '3' and does not affect the contents of the buffer.

Ideas?

like image 826
Douglas Anderson Avatar asked Dec 25 '22 03:12

Douglas Anderson


2 Answers

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

Seems to do the trick.

With lh#visual#selection() coming from lh-vim-lib

like image 45
Luc Hermitte Avatar answered Dec 28 '22 18:12

Luc Hermitte


A range is always linewise.

No matter what you do, every Ex command that accept a range will always take '< as the start line and '> as the end line.

Passing a non-linewise selection to an external program is done like this:

  • backup the content of a register
  • yank the selection in that register
  • pass the content of that register to system() and output the result
  • restore the register

Here it is, in a function:

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

that you can use in a mapping like this:

xnoremap <F6> :call VisualCountWords()<CR>

Also your use of cat is useless:

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

should be:

:[range]w ! <some shell command>
like image 181
romainl Avatar answered Dec 28 '22 19:12

romainl