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

Time:11-18

Program Overview

I've been writing a program to help its user memorize digits of pi.

Problems encountered

The program includes the following prompt which is offered by enquirer npm.

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

I want to receive standard input after mode selection, but the programs exits without waiting.

Predicted Cause

If you skip the mode select offered by enquirer and start the mode directly, the program accepts standard input as intended. Therefore, the cause seems to be that the process related to the standard input is being executed while some state related to it has been changed from the initial state by enquirer.

What I need to know

Is there any way to reset the changes made by enquirer to the initial state and move to the selected mode? If this is difficult, I would like to know if there is a way to handle the standard input properly after selecting the mode. Thank you very much beforehand.

Code

#!/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()
}

CodePudding user response:

Insert a line as follows:

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

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

  • Related