How do I send the current buffer or line as stdin to system() in vim?
shell, stdin, stdout, vim
Solution
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).
Problem
There are 3 closely related vim commands that let you call an external program: `:[range]!{filter-cmd} {arg}` (ex-command, `:help :range!`) `:[range]write !{cmd}` (ex-command, `:help :w_c`) `system({expr}, {arg})` (vimscript function, `:help system()`) (I'm including `!` and `:!cmd` as part of 1.) From my view, there are three important distinctions: - `[range]` is sent to stdin in, stdout replaces `[range]` - `[range]` is sent to stdin, stdout is ignored - 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.