tags:

views:

803

answers:

3

I want to select a block of text (eg. V%) and use the text as input to a shell command (eg. wc or pbcopy) - but I DON'T want to alter the current buffer - I just want to see the output of the command (if any) the continue editting without any changes.

Typing V%!wc translates to :'<,'>!wc and switches the block of text for the output of the wc command.

How do you pipe a chunk of text to an arbitrary shell command without affecting the current buffer?

A: 

I know it's not the ideal solution, but if all else fails, you could always just press u after running the command to undo the buffer change.

Amber
Sure, that's what I do currently - I'm just hoping I'm missing something. I guess if there isn't a built-in way of doing this, a small <code>cmap</code> could do the trick - anyone got a ready-made one?
searlea
Offtopic: /me wishes <code> tags worked in comments too.
Amber
After glancing around on meta-SO, using `backticks around text` apparently is supposed to allow code-formatting in comments.
Amber
Really? `sweet` - that's good to know.
searlea
+4  A: 

One possibility would be to use system() in a custom command, something like this:

command! -range -nargs=1 SendToCommand <line1>,<line2>call SendToCommand(<q-args>) 

function! SendToCommand(UserCommand) range
    " Get a list of lines containing the selected range
    let SelectedLines = getline(a:firstline,a:lastline)
    " Convert to a single string suitable for passing to the command
    let ScriptInput = join(SelectedLines, "\n") . "\n"
    " Run the command
    let result = system(a:UserCommand, ScriptInput)
    " Echo the result (could just do "echo system(....)")
    echo result
endfunction

Call this with (e.g.):

:'<,'>SendToCommand wc -w

Note that if you press V%:, the :'<,'> will be entered for you.

:help command
:help command-range
:help command-nargs
:help q-args
:help function
:help system()
:help function-range
Al
My first thought was that it looked really chunky and verbose, but after adding chucking it in my .vimrc and adding a mapping, it's perfect:vmap # :SendToCommand<Space>Now I can just do V%# and bang out the command name. Just what I wanted.
searlea
Glad you like it! Your mapping looks like a good idea (I do tend to go for long and verbose command names and rely on tab-completion to save me the effort). Consider putting it in `~/.vim/plugin/sendtocommand.vim` or `~/.vim/autoload/sendtocommand.vim` (the latter will require some changes) to help keep your vimrc manageable.
Al
+3  A: 

Select your block of text, then type these keys :w !sh

The whole thing should look like:

'<,'>w !sh

That's it. Only took me 8 years to learn that one : )

pixelearth
Awesome, neat and builtin --- all one could hope for.
Michael Anderson