首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何从node.js打开终端应用程序?

如何从node.js打开终端应用程序?
EN

Stack Overflow用户
提问于 2012-02-03 08:51:28
回答 3查看 14.4K关注 0票数 27

我希望能够从终端中运行的node.js程序打开Vim,创建一些内容,保存并退出Vim,然后抓取文件的内容。

我正在尝试这样做:

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

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

  text = fs.readFileSync filename
  console.log text

但是,当它运行时,它只会挂起终端。

我也在exec上尝试过,也得到了同样的结果。

更新:

由于此进程是从运行readline的提示符处键入的命令启动的,这一点变得复杂起来。我完整地将最新版本的相关部分提取到一个文件中。下面是它的全部内容:

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

它的工作方式如上图所示,它会显示几秒钟的提示符,然后启动到Vim,但TTY搞乱了。我可以编辑和保存文件,并且内容打印正确。在退出时也有一堆垃圾打印到终端,并且Readline功能在退出后被破坏(没有向上/向下箭头,没有Tab补全)。

如果我取消对cli.pause()行的注释,那么TTY在Vim中是可以的,但是我被困在插入模式中,并且Esc键不起作用。如果我点击Ctrl-C,它将退出子进程和父进程。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-06-14 21:59:42

你可以从主进程继承stdio。

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");
});

更多选项请点击此处:http://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options

票数 46
EN

Stack Overflow用户

发布于 2012-02-03 10:51:35

Node: My answer在创建时应用,但对于的现代版本,请查看this other answer

首先,你对spawn的使用是不正确的。这是文档。http://nodejs.org/docs/latest/api/child_processes.html#child_process.spawn

您的示例代码看起来像是您希望vim自动弹出并接管终端,但事实并非如此。重要的是要记住,即使您可能会产生一个进程,也要由您来确保来自该进程的数据能够通过终端进行显示。

在这种情况下,您需要从stdin获取数据并将其发送到vim,还需要获取vim输出的数据并将其设置为您的终端,否则您将什么也看不到。您还需要将tty设置为raw模式,否则节点将截获一些键序列,因此vim将无法正常运行。

接下来,不要执行readFileSync。如果您遇到需要使用sync方法的情况,那么很可能是您做错了什么。

这里有一个我放在一起的快速示例。我不能保证它在每一种情况下都有效,但它应该涵盖大多数情况。

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());
      }
    });
  }
});

更新

我明白了。不幸的是,我认为readline并不像你希望的那样与所有这些兼容。问题是,当你使用createInterface时,节点会假设从那时起它将完全控制该流。当我们将数据重定向到vim时,readline仍然在那里处理按键,但vim也在做同样的事情。

我认为解决这个问题的唯一方法是在启动vim之前手动禁用cli界面中的所有内容。

就在你产生进程之前,我们需要关闭接口,不幸的是手动删除按键监听器,因为至少在目前,节点不会自动删除它。

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

然后在进程的'exit‘回调中,你需要再次调用createInterface。

票数 12
EN

Stack Overflow用户

发布于 2021-06-27 20:04:10

我试着用Node的repl库-- https://nodejs.org/api/repl.html --来做类似的事情,但是都没有效果。我试着启动了vscode和TextEdit,但在Mac上似乎没有办法等待这些程序关闭。将execSync与vim、nano和micro一起使用时,行为都很奇怪,或者挂起了终端。

最后,我转而使用这里给出的示例https://nodejs.org/api/readline.html#readline_example_tiny_cli来使用readline库--它使用micro来工作,例如

import { execSync } from 'child_process'
...
case 'edit':
  const cmd = `micro foo.txt`
  const result = execSync(cmd).toString()
  console.log({ result })
  break

完成后,它在临时缓冲区命中的ctrl-q中切换到micro,并在result中返回缓冲区内容。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9122282

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档