从管道中获取参数,但也有 运行 提示?
Get argument from pipe but also run prompts?
我正在编写一个旨在从 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
将某些内容通过管道传输到我的脚本中似乎会干扰提示本身。
基本上,我希望能够使用我的脚本中通过管道输入的内容,但让提示符像第一种情况一样工作。我怎样才能做到这一点?
你可以在子 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
我找到了一个使用包组合的解决方案,即 prompts and 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();
})();
我正在编写一个旨在从 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
将某些内容通过管道传输到我的脚本中似乎会干扰提示本身。
基本上,我希望能够使用我的脚本中通过管道输入的内容,但让提示符像第一种情况一样工作。我怎样才能做到这一点?
你可以在子 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
我找到了一个使用包组合的解决方案,即 prompts and 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();
})();