node.js vim terminal coffeescript readline

¿Cómo abro una aplicación de terminal desde node.js?



vim coffeescript (2)

Me gustaría poder abrir Vim desde el programa node.js que se ejecuta en el terminal, crear contenido, guardar y salir de Vim , y luego capturar el contenido del archivo.

Estoy tratando de hacer algo como esto:

filename = ''/tmp/tmpfile-'' + process.pid editor = process.env[''EDITOR''] ? ''vi'' spawn editor, [filename], (err, stdout, stderr) -> text = fs.readFileSync filename console.log text

Sin embargo, cuando esto se ejecuta, simplemente se bloquea el terminal.

También lo he probado con exec y obtuve el mismo resultado.

Actualizar:

Esto se complica por el hecho de que este proceso se inicia desde un comando escrito en un indicador con línea de readline ejecución. Extraje completamente las partes relevantes de mi última versión en un archivo. Aquí está en su totalidad:

{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()

La forma en que funciona como se muestra arriba, es que muestra un aviso durante un par de segundos y luego se inicia en Vim, pero el TTY está desordenado. Puedo editar y guardar el archivo, y los contenidos se imprimen correctamente. También hay un montón de basura impresa en el terminal al salir, y la funcionalidad de Readline se interrumpe después (no hay flecha arriba / abajo, no se completa la pestaña).

Si cli.pause() el comentario de la línea cli.pause() , el TTY está bien en Vim, pero estoy bloqueado en el modo de inserción y la Esc no funciona. Si presiono Ctrl-C se cierra el proceso hijo y padre.



Actualización: mi respuesta se aplicó en el momento en que se creó, pero para las versiones modernas de Node, vea esta otra respuesta .

En primer lugar, su uso de engendro no es correcto. Aquí están los documentos. http://nodejs.org/docs/latest/api/child_processes.html#child_process.spawn

Su código de muestra hace que parezca que espera que vim aparezca automáticamente y se haga cargo de la terminal, pero no lo hará. Lo importante a recordar es que, aunque puede generar un proceso, depende de usted asegurarse de que los datos del proceso lleguen a su terminal para su visualización.

En este caso, debe tomar los datos de la entrada estándar y enviarlos a vim, y debe tomar los datos de salida de vim y establecerlos en su terminal, de lo contrario no verá nada. También debe configurar tty en modo raw, de lo contrario el nodo interceptará algunas de las secuencias de teclas, por lo que vim no se comportará correctamente.

A continuación, no haga readFileSync. Si te encuentras con un caso en el que crees que necesitas usar un método de sincronización, es probable que estés haciendo algo mal.

Aquí hay un ejemplo rápido que junté. No puedo garantizar que funcione en todos los casos, pero debería cubrir la mayoría de los casos.

var tty = require(''tty''); var child_process = require(''child_process''); var fs = require(''fs''); function spawnVim(file, cb) { var vim = child_process.spawn( ''vim'', [file]) function indata(c) { vim.stdin.write(c); } function outdata(c) { process.stdout.write(c); } process.stdin.resume(); process.stdin.on(''data'', indata); vim.stdout.on(''data'', outdata); tty.setRawMode(true); vim.on(''exit'', function(code) { tty.setRawMode(false); process.stdin.pause(); process.stdin.removeListener(''data'', indata); vim.stdout.removeListener(''data'', outdata); cb(code); }); } var filename = ''/tmp/somefile.txt''; spawnVim(filename, function(code) { if (code == 0) { fs.readFile(filename, function(err, data) { if (!err) { console.log(data.toString()); } }); } });

Actualizar

Yo veo No creo que readline sea tan compatible con todo esto como desearías desafortunadamente. El problema es que cuando crea Interfaz, el nodo asume que tendrá control total sobre esa corriente desde ese punto en adelante. Cuando redirigimos esos datos a vim, readline todavía está procesando pulsaciones de teclas, pero vim también está haciendo lo mismo.

La única forma de evitar esto es ver que se deshabilite manualmente todo desde la interfaz cli antes de iniciar vim.

Justo antes de generar el proceso, debemos cerrar la interfaz y, lamentablemente, eliminar manualmente el oyente de pulsación de tecla porque, al menos en este momento, el nodo no lo elimina automáticamente.

process.stdin.removeAllListeners ''keypress'' cli.close() tty.setRawMode true

Luego, en el proceso de ''salir'' de la devolución de llamada, deberá llamar a createInterface nuevamente.