Inquirer.js: custom exit handlers

Created on 8 Aug 2016  路  5Comments  路  Source: SBoudrias/Inquirer.js

https://github.com/SBoudrias/Inquirer.js/blob/master/lib/ui/baseUI.js#L21

this.rl.on('SIGINT', this.onForceClose);
process.on('exit', this.onForceClose);

Please provide an option or function to set exit handlers our own.

Most helpful comment

I would prefer prompt() to return a rejected promise on Ctrl-C. This is achievable if you're willing to reach in and monkey with a Prompt object's readline directly:

/**
 * By default Inquirer handles Ctrl-C itself by force-quitting the process with
 * no way to clean up. This wrapper around Inquirer throws a Error
 * instead, allowing normal exception handling.
 */
async function safePrompt<T>(question: inquirer.Question<T>): Promise<T> {
    const promptModule = inquirer.createPromptModule()
    const ui = new inquirer.ui.Prompt((promptModule as any).prompts, {})
    const deferred = PromiseUtils.deferred<T>()

    // Remove the force-quit behavior
    const rl = ui.rl
    rl.listeners("SIGINT").forEach(listener => rl.off("SIGINT", listener as any))

    // Insert our listener to reject the promise
    function handleCtrlC() {
        // remove the listener
        rl.off("SIGINT", handleCtrlC)

        // Clean up inquirer
        ui.close()

        // Then reject our promise
        deferred.reject(
            new Error("Aborted due to Ctrl-C during a prompt", ui)
        )
    }
    rl.on("SIGINT", handleCtrlC)

    // Run the UI
    ui.run<T>([question]).then(deferred.resolve, deferred.reject)
    return await deferred.promise
}

(Implementation of PromiseUtils.deferred left as an exercise to the reader)

All 5 comments

Why not listen to those events yourself?

Those events never triggers in prompt mode. I want to return back to prev. menu or cancel a step with this keys.

'use strict';

process.on('SIGINT', () => console.log('bye!'));

const inquirer = require('inquirer');

inquirer.prompt({
  type: 'input',
  name: 'test',
  message: 'hit CTRL + C to test SIGINT in prompt mode'
});

You can pass your own event listener like @SBoudrias suggested. I ended up doing this in my app since I needed synchronous behavior.

```
let stdin = process.stdin;
stdin.on("data", (key) => {
if (key == "\u0003") {
LOG("catching ctrl+c");
}
});

inquirer.prompt(questions, {input: stdin});
```

I would prefer prompt() to return a rejected promise on Ctrl-C. This is achievable if you're willing to reach in and monkey with a Prompt object's readline directly:

/**
 * By default Inquirer handles Ctrl-C itself by force-quitting the process with
 * no way to clean up. This wrapper around Inquirer throws a Error
 * instead, allowing normal exception handling.
 */
async function safePrompt<T>(question: inquirer.Question<T>): Promise<T> {
    const promptModule = inquirer.createPromptModule()
    const ui = new inquirer.ui.Prompt((promptModule as any).prompts, {})
    const deferred = PromiseUtils.deferred<T>()

    // Remove the force-quit behavior
    const rl = ui.rl
    rl.listeners("SIGINT").forEach(listener => rl.off("SIGINT", listener as any))

    // Insert our listener to reject the promise
    function handleCtrlC() {
        // remove the listener
        rl.off("SIGINT", handleCtrlC)

        // Clean up inquirer
        ui.close()

        // Then reject our promise
        deferred.reject(
            new Error("Aborted due to Ctrl-C during a prompt", ui)
        )
    }
    rl.on("SIGINT", handleCtrlC)

    // Run the UI
    ui.run<T>([question]).then(deferred.resolve, deferred.reject)
    return await deferred.promise
}

(Implementation of PromiseUtils.deferred left as an exercise to the reader)

I would prefer prompt() to return a rejected promise on Ctrl-C. This is achievable if you're willing to reach in and monkey with a Prompt object's readline directly:

/**
 * By default Inquirer handles Ctrl-C itself by force-quitting the process with
 * no way to clean up. This wrapper around Inquirer throws a Error
 * instead, allowing normal exception handling.
 */
async function safePrompt<T>(question: inquirer.Question<T>): Promise<T> {
  const promptModule = inquirer.createPromptModule()
  const ui = new inquirer.ui.Prompt((promptModule as any).prompts, {})
  const deferred = PromiseUtils.deferred<T>()

  // Remove the force-quit behavior
  const rl = ui.rl
  rl.listeners("SIGINT").forEach(listener => rl.off("SIGINT", listener as any))

  // Insert our listener to reject the promise
  function handleCtrlC() {
      // remove the listener
      rl.off("SIGINT", handleCtrlC)

      // Clean up inquirer
      ui.close()

      // Then reject our promise
      deferred.reject(
          new Error("Aborted due to Ctrl-C during a prompt", ui)
      )
  }
  rl.on("SIGINT", handleCtrlC)

  // Run the UI
  ui.run<T>([question]).then(deferred.resolve, deferred.reject)
  return await deferred.promise
}

(Implementation of PromiseUtils.deferred left as an exercise to the reader)

Hey, i'm using inquirer on nodejs, i would like to use this function but in a js file

Was this page helpful?
0 / 5 - 0 ratings

Related issues

XhmikosR picture XhmikosR  路  7Comments

jahvi picture jahvi  路  6Comments

aaronshaf picture aaronshaf  路  7Comments

fuechter picture fuechter  路  3Comments

bugzpodder picture bugzpodder  路  4Comments