Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I send the current buffer or line as stdin to system() in vim?

There are 3 closely related vim commands that let you call an external program:

  1. :[range]!{filter-cmd} {arg} (ex-command, :help :range!)

  2. :[range]write !{cmd} (ex-command, :help :w_c)

  3. system({expr}, {arg}) (vimscript function, :help system())

(I'm including ! and :!cmd as part of 1.)

From my view, there are three important distinctions:

  1. [range] is sent to stdin in, stdout replaces [range]
  2. [range] is sent to stdin, stdout is ignored
  3. stdout is the return value of system(), so stdout can be saved to a variable as :let @a = system(..)

Is there really no way to send the current buffer or current line as stdin to an external command AND have unfettered access to stdout?

If you want to write, e.g., a complicated movement command that requires parsing of the line/buffer (parsing which would be better off not written in vimscript), this seems very surprising.

(Trying to send stuff through {arg} would be crazy for a couple reasons: 1. character length limits, 2. you'd have to write a shell escaping function from within vimscript*)

Here is the only other related question I could find. It sends a string variable as shell arguments to (unix) 'echo', which then sends it as stdin to your program: Can I pass a string as stdin to a system call from vim?

*If the vim function shellescape() does what you want, great, but on Windows it isn't even remotely robust for protecting input from cmd.exe and from CommandLineToArgvW. In fact, on Windows vim sends any single shell string through cmd.exe twice.

like image 223
Ein Avatar asked Feb 03 '14 14:02

Ein


1 Answers

OK, I was erring about one very important detail: the second argument to system({expr},{input}) isn't treated as shell input, it is sent as stdin. So you would do something like:

:let stdin = join(getline(1,'$'), "\n")
:let a = system('C:/main.exe',stdin)

Almost all examples of system(..) use and warn about shell escaping, but that is for the {expr} argument (and this escaping is a much smaller problem if {expr} is not a dynamic string).

like image 120
Ein Avatar answered Nov 05 '22 12:11

Ein