Execute shell command without filtering from Vim

Viewed 7538

I want to select a block of text (for example, V%) and use the text as input to a shell command (for example, 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) then continue editing 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?

4 Answers

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

Update: my answer is nonsense.

@pixelearth's answer is good, but I had a little trouble understanding what he did exactly, so I wrote the following. This sequence of commands let's you execute wc -l on your visual selection. wc -l simply counts the number of lines passed to it.

  1. In Vim go into Visual Mode using v
  2. Select a few lines by going down: jjjj
  3. Type : which Vim will translate to :'<,'>
  4. Type w !wc -l, your complete commandline should now be :'<,'>w !wc -l
  5. Press Enter to get the result of your command (in this example it would be 4)
  6. Press Enter to continue editing

I don't understand what exactly happens at step 3 and 4 but I do know that it works.

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.

Related