有没有办法使用 "enquirer" npm 来处理标准输入?

Is there a way to handle standard input using "enquirer" npm?

计划概览

我一直在编写一个程序来帮助其用户记住圆周率的数字。

遇到的问题

该程序包含以下由 enquirer npm 提供的提示。

>>>>>>>>>> PI GAME <<<<<<<<<<
? Select your mode: …
❯ PRACTICE MODE
  SHOW PI DIGITS
  HIGH SCORES

我想在 selection 模式后接收标准输入,但程序没有等待就退出了。

预测原因

如果您跳过 enquirer 提供的模式 select 并直接启动该模式,程序将按预期接受标准输入。 因此,原因似乎是与标准输入相关的进程正在执行,而与它相关的某些状态已被询问者从初始状态更改。

我需要知道的

有什么方法可以将查询者所做的更改重置为初始状态并进入selected模式吗? 如果这很难,我想知道在 select 模式后是否有办法正确处理标准输入。 非常感谢你。

代码

#!/usr/bin/env node

'use strict'

{
  const { Select } = require('enquirer')
  const chalk = require('chalk')
  const PI_START_TEXT = '3.'
  const PI_BELOW_THE_DECIMAL_POINT = '1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679'

  class PracticeMode {
    start () {
      const instruction = 'Keep typing in the number which fits the cursor position.'
      // This program stops after executing the next line.
      process.stdout.write(chalk.bold.green(instruction) + '\n\n' + PI_START_TEXT)
      const readline = require('readline');
      readline.emitKeypressEvents(process.stdin)
      process.stdin.setRawMode(true);
      let currentIndex = 0
      process.stdin.on('keypress', (char, key) => {
        if (key.ctrl && key.name === 'c') {
          process.exit();
        } else if (currentIndex === 100) {
          this.putsCongratulations()
          process.exit();
        } else if (char === PI_BELOW_THE_DECIMAL_POINT[currentIndex]) {
          process.stdout.write(char)
          currentIndex++
        } else {
          const scoreMessage = `Your score: ${currentIndex}`
          const remaining_digits_text = this.make_remaining_digits_text(currentIndex)
          console.log(chalk.red(remaining_digits_text) + '\n' + scoreMessage)
          process.exit();
        }
      })
    }

    putsCongratulations () {
      const headSpaces = ' '.repeat(6)
      const congratulationsSentences = [
        'Congratulations!',
        'You have memorized the first 100 digits of pi.'
      ]
      let congratulations = ''
      congratulationsSentences.forEach(sentence => {
        congratulations += headSpaces + sentence + '\n'
      })
      console.log(chalk.bold.green(congratulations))
    }

    make_remaining_digits_text (currentIndex) {
      let remaining_digits_text = ''
      const digitsNum = 100
      const sectionDigitsNum = 10
      const lineDigitsNum = 50
      for (let i = currentIndex; i < digitsNum; i++) {
        if (i  === lineDigitsNum) {
          remaining_digits_text += '\n' + ' '.repeat(PI_START_TEXT.length)
        } else if (i % sectionDigitsNum === 0) {
          remaining_digits_text += ' '
        }
        remaining_digits_text += PI_BELOW_THE_DECIMAL_POINT[i]
      }
      return remaining_digits_text
    }
  }

  class Game {
    constructor () {
      this.practiceMode = 'PRACTICE MODE'
      this.showPiDigits = 'SHOW PI DIGITS'
      this.highScores = 'HIGH SCORES'
    }

    start () {
      const modes = [
        { name: this.practiceMode, explanation: 'Check how many digits of pi you can name from the point you designated.' },
        { name: this.showPiDigits, explanation: 'Check the first 100 digits of pi.' },
        { name: this.highScores, explanation: 'Check the high scores.' }
      ]
      const prompt = new Select({
        name: 'mode',
        message: 'Select your mode:',
        choices: modes.map(mode => mode.name),
        footer () {
          const explanations = modes.map(mode => ' '.repeat(2) + mode.explanation)
          return chalk.green('\n' + explanations[this.index])
        }
      })

      prompt.run()
        .then(answer => {
          switch (answer) {
            case this.practiceMode:
              // I have the problem here.
              new PracticeMode().start()
              break;
            case this.showPiDigits:
              break;
            case this.highScores:
              break;
          }
        })
    }
  }

  function main () {
    const welcomeMessage = '>'.repeat(10) + ' PI GAME ' + '<'.repeat(10)
    console.log(chalk.bold.green(welcomeMessage))

    // This doesn't work as intended.
    new Game().start()

    // If you run the next line instead, it works as intended.
    // new PracticeMode().start()
  }

  main()
}

插入一行如下:

    let currentIndex = 0
    process.stdin.resume()
    process.stdin.on('keypress', (char, key) => {

参考:Node.js のプロセス処理を少し学ぶ - ashiris’s diary