【问题标题】:Get argument from pipe but also run prompts?从管道获取参数但也运行提示?
【发布时间】:2020-04-28 18:40:49
【问题描述】:

我正在编写一个旨在从 Bash 终端执行的 Node 脚本。它需要几个文件名,然后通过有关如何处理它们的提示向用户提问。我使用yargs 解析命令行参数,使用prompt-sync 询问用户问题,一切似乎都很好......

除非我像这样将参数传递给我的脚本:

echo "file2.md" | .myscript.js --f1 file1.md

只要它比较 file1.md 和 file2.md 并且我使用 pipe-args 和 yargs 就可以做到这一点。但是当涉及到提示时,管道参数会干扰并阻止它们工作。

我尝试将它放在我的脚本之外并单独测试它,同时使用 prompt-sync 和 inquirer 并将参数传递到脚本中似乎也会影响提示。

所以我现在很确定这不是特定的提示包。


重新创建:

这是我对提示同步的测试(文件名为 prompt-sync-test.js):

#!/usr/bin/env node
const prompt = require("prompt-sync")({"sigint": true})

for (var i = 0; i < 5; i++) {
  console.log("Going to bring up a prompt")
  var result = prompt("This is a test -- enter something >");
  console.log("Result", result)
}

...当它起作用时:

运行./prompt-sync-test.js 运行良好,每次都会询问五个问题并打印结果。

$ ./prompt-sync-test.js
Going to bring up a prompt
This is a test -- enter something >1
Result 1
Going to bring up a prompt
This is a test -- enter something >2
Result 2
Going to bring up a prompt
This is a test -- enter something >3
Result 3
Going to bring up a prompt
This is a test -- enter something >4
Result 4
Going to bring up a prompt
This is a test -- enter something >5
Result 5

...当它没有时:

但是运行echo hello world | ./prompt-sync-test.js 会打印第一个提示的消息,但是输入的任何输入都会再次重复提示消息,输入任何以前的答案,就像这样(我输入的数字与上述测试中的相同并在每个之后按回车键)...

$ echo hello world | ./prompt-test.
js
Going to bring up a prompt
This is a test -- enter something >1
This is a test -- enter something >1
                                     2
This is a test -- enter something >1
2
                                       3
This is a test -- enter something >1
2
3
                                         4
This is a test -- enter something >1
2
3
4
                                           5
This is a test -- enter something >1
2
3
4
5

在我的脚本中添加一些内容似乎会干扰提示本身。

基本上,我希望能够使用在我的脚本中输入的内容,但可以像第一种情况一样进行提示工作。我怎样才能做到这一点?

【问题讨论】:

    标签: javascript node.js pipe prompt


    【解决方案1】:

    我找到了一个使用组合包的解决方案,即prompts 和ttys。

    我切换到prompts,因为它允许您为每个问题配置一个名为stdin 的变量,这意味着您可以决定从哪里获取输入。

    大多数提示包似乎默认使用process.stdin 作为输入。这通常很好,但是当您将数据传输到命令中时,process.stdin 被管道占用,因此我之前遇到了问题。但是,如果您知道process.stdin 已被管道占用,您仍然可以从用户那里获得键盘输入。

    这就是ttys 的用武之地。它是一个非常简单的包,用于检查管道是否已被使用。

    我几乎可以使用以下脚本重新创建我在问题中概述的成功结果——唯一缺少的是预先提示消息 (Going to bring up a prompt)。而且我添加了 pipe-args 和 yargs 以表明保留了管道输入的数据。

    #!/usr/bin/env node
    const prompts = require("prompts");
    const tty = require("tty");
    const pipe = require("pipe-args").load();
    const argv = require("yargs").argv;
    const ttys = require("ttys");
    
    const questions = [0, 1, 2, 3, 4]
      .map(x => ({
        type: "text",
        name: `prompt-${x}`,
        message: "This is a test -- enter something",
        stdin: ttys.stdin
      }));
    
    
    const onSubmit = function (prompt, answer) {
      console.log("Result", answer); // => { value: 24 }
    };
    
    (async () => {
      const response = await prompts(questions, { onSubmit });
      console.log(argv);
      ttys.stdin.destroy();
    })();
    

    【讨论】:

      【解决方案2】:

      您可以在子shell 中使用cat,如下所示:

      (echo "file2.md"; cat) | .myscript.js --f1 file1.md
      (echo hello world; cat) | ./prompt-test.js
      

      您也可以添加exec 以减少一个流程:

      (echo "file2.md"; exec cat) | .myscript.js --f1 file1.md
      (echo hello world; exec cat) | ./prompt-test.js
      

      你也可以把cat放在外面,用-:

      cat <(echo "file2.md") - | .myscript.js --f1 file1.md
      cat <(echo hello world) - | ./prompt-test.js
      

      【讨论】:

      • 感谢您的回复。我对此进行了测试,但仍然看到与提示相同的行为。
      • 添加了更多关于如何重现我遇到的问题的详细信息,以防有助于使其更清晰。
      猜你喜欢
      • 2013-07-24
      • 1970-01-01
      • 1970-01-01
      • 2019-06-15
      • 2011-09-26
      • 1970-01-01
      • 2020-12-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多