How do I open a terminal application from node.js?

mkopala picture mkopala · Feb 3, 2012 · Viewed 12.8k times · Source

I would like to be able to open Vim from node.js program running in the terminal, create some content, save and exit Vim, and then grab the contents of the file.

I'm trying to do something like this:

filename = '/tmp/tmpfile-' + process.pid

editor = process.env['EDITOR'] ? 'vi'
spawn editor, [filename], (err, stdout, stderr) ->

  text = fs.readFileSync filename
  console.log text

However, when this runs, it just hangs the terminal.

I've also tried it with exec and got the same result.

Update:

This is complicated by the fact that this process is launched from a command typed at a prompt with readline running. I completely extracted the relevant parts of my latest version out to a file. Here is it in its entirety:

{spawn} = require 'child_process'
fs = require 'fs'
tty = require 'tty'
rl = require 'readline'

cli = rl.createInterface process.stdin, process.stdout, null
cli.prompt()

filename = '/tmp/tmpfile-' + process.pid

proc = spawn 'vim', [filename]

#cli.pause()
process.stdin.resume()

indata = (c) ->
    proc.stdin.write c
process.stdin.on 'data', indata

proc.stdout.on 'data', (c) ->
    process.stdout.write c

proc.on 'exit', () ->
    tty.setRawMode false
    process.stdin.removeListener 'data', indata

    # Grab content from the temporary file and display it
    text = fs.readFile filename, (err, data) ->
        throw err if err?  
        console.log data.toString()

        # Try to resume readline prompt
        cli.prompt()

The way it works as show above, is that it shows a prompt for a couple of seconds, and then launches in to Vim, but the TTY is messed up. I can edit, and save the file, and the contents are printed correctly. There is a bunch of junk printed to terminal on exit as well, and Readline functionality is broken afterward (no Up/Down arrow, no Tab completion).

If I uncomment the cli.pause() line, then the TTY is OK in Vim, but I'm stuck in insert mode, and the Esc key doesn't work. If I hit Ctrl-C it quits the child and parent process.

Answer

Ilia Sidorenko picture Ilia Sidorenko · Jun 14, 2013

You can inherit stdio from the main process.

const child_process = require('child_process')
var editor = process.env.EDITOR || 'vi';

var child = child_process.spawn(editor, ['/tmp/somefile.txt'], {
    stdio: 'inherit'
});

child.on('exit', function (e, code) {
    console.log("finished");
});

More options here: http://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options