stdio/piping issues when using vim in child process in node.js

844 views Asked by At

I am using node.js to write a command line interface that generates unit test files. I have been using inquirer to get user input, however there is one field in which the user will very likely want to copy-paste and/or edit, large multi-line chunks of JSON data. Therefore, my goal is to: open vim @ certain point in CLI -> allow input-> close vim -> write out to tmp file -> process the result.

The problem is that input to vim is also going to the parent stdin, and when the return key is hit, the program continues on top of vim (mayhem). I'm fairly certain that stdio/in/out/err are not set up properly, but i cant seem to find the exact solution anywhere. Every iteration of my manipulating the streams seems closer, but i know that there is a small missing link.

i have tried a lot of things along the lines of:

var vim = child_process.spawn('vim', [path], {stdin: 'pipe', stdout: 'pipe', stderr: 'pipe'});

var vim = child_process.spawn('vim', [path], {stdio: 'inherit'}); //{stdio: ['pipe','pipe','pipe']}

Finally, i have followed a lot of the stdio manipulation from this example, How do I open a terminal application from node.js?, but there still remains some small missing link that i need help with

Notes:

  • I am 99% certain that my async promises are in order.
  • it doesn't necessarily have to be vim, as I am checking the ENV for an editor first
  • I liken this to git commit, where an editor pops up and allows input before closing
  • in a small test program, i can get perfect functionality, but when trying to do this over another process, it doesnt go well

tl;dr : i want to ignore the parent process while input goes only to vim (child_process), but i cannot keep them separated, and because of this, the program goes haywire

If there is anything i can clarify, please let me know. Thanks!

1

There are 1 answers

0
Alexander Hansen On

I know this is old, but anyway 6 days ago they released a function with 2015.02.06 Version 0.12.0 (Stable) that makes this very easy.

var spawnSync=require("child_process").spawnSync;
spawnSync("vim",[__filename],{stdio:"inherit"});

It will of course block the event loop, but in such a situation you likely want to wait for the user. Otherwise, you may end up with node writing to stdout and reading stdin while you are editing, which is obviously very confusing, and is the issue you were running into.

If you really still need asynchronous stuff while you are editing, it's probably easier to require("child_process").fork so you don't confuse the stdin/stdout. I imagine you could do some fancy stuff to remove all the listeners and add them back later, but it's probably not worth the effort.