Получить аргумент из трубы, но также запустить подсказки? - PullRequest
1 голос
/ 28 апреля 2020

Я пишу сценарий Node, предназначенный для запуска с терминала Bash. Он берет пару имен файлов и затем задает вопросы пользователю через подсказку о том, как их обработать. Я использую yargs для разбора аргументов командной строки и prompt-sync для того, чтобы задавать пользовательские вопросы, и кажется, что все работает нормально ...

За исключением случаев, когда я передаю аргумент в свой скрипт следующим образом:

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

Это работает, поскольку сравнивает file1.md и file2.md, и я использую pipe-args в сочетании с yargs, чтобы получить это далеко. Но когда дело доходит до подсказок, наличие аргумента piped мешает и мешает им работать.

Я попытался вывести это за пределы моего сценария и протестировать его изолированно, используя как prompt-sync, так и inquirer и Внесение аргумента в скрипт, по-видимому, также влияет на приглашение.

Так что теперь я почти уверен, что это не указанный пакет приглашения c.


Для воссоздания:

Вот мой тест для приглашения к ответу c (файл с именем 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

Piping что-то в моем сценарии, кажется, мешает пр ompt сама по себе.

По сути, я хочу иметь возможность использовать то, что указано в моем скрипте, но иметь быструю работу, как в первом случае. Как я могу это сделать?

Ответы [ 2 ]

1 голос
/ 30 апреля 2020

Я нашел решение, используя комбинацию пакетов, а именно приглашения и ttys .

Я переключился на приглашения , потому что это позволяет вам настроить переменную с именем stdin для каждого вопроса, что означает, что вы можете решить, откуда взять ввод.

Большинство пакетов подсказок, по-видимому, по умолчанию используют process.stdin в качестве ввода. Обычно это нормально, но когда вы передаете данные в команду, process.stdin занят конвейером, поэтому у меня возникла проблема. Тем не менее, если вы знаете, что process.stdin занята каналом, вы все равно можете получить ввод с клавиатуры от пользователя.

Вот где приходит ttys . Это очень простой пакет, который проверяет использовался ли pipe или нет.

Я могу почти воссоздать успешный результат, который я изложил в своем вопросе, с помощью следующего сценария - единственное, чего не хватает - это предварительное сообщение (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();
})();
0 голосов
/ 28 апреля 2020

Вы можете использовать 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
...