commander chalk ora
commander, chalk, 和 ora 是三个常用的 Node.js 库,它们分别用于命令行界面的命令解析、终端字符串样式和命令行加载动画。以下是每个库的介绍及其基本用法。
Commander
commander 是一个用于 Node.js 命令行界面的命令解析库。它可以帮助你轻松地定义和解析命令行参数和选项。
安装
npm install commander
基本用法
const { Command } = require('commander');
const program = new Command();
program
  .version('1.0.0')
  .description('An example CLI for demonstration purposes')
  .option('-n, --name <type>', 'specify your name')
  .option('-a, --age <number>', 'specify your age', parseInt);
program.parse(process.argv);
const options = program.opts();
if (options.name) console.log(`Hello, ${options.name}!`);
if (options.age) console.log(`You are ${options.age} years old.`);
Chalk
chalk 是一个用于终端字符串样式的库。它可以帮助你为终端输出添加颜色和样式。
安装
npm install chalk
基本用法
const chalk = require('chalk');
console.log(chalk.blue('Hello world!'));
console.log(chalk.red.bold('Error!'));
console.log(chalk.green.underline('Success!'));
console.log(chalk.yellow.bgRed.bold('Warning!'));
Ora
ora 是一个用于在命令行界面中显示加载动画的库。它可以帮助你在执行异步操作时显示一个旋转的加载指示器。
安装
npm install ora
基本用法
const ora = require('ora');
const spinner = ora('Loading...').start();
setTimeout(() => {
  spinner.color = 'yellow';
  spinner.text = 'Loading something else...';
}, 1000);
setTimeout(() => {
  spinner.succeed('Loading complete');
}, 3000);
综合示例
下面是一个综合示例,展示如何将 commander, chalk, 和 ora 结合使用,创建一个简单的命令行工具。
安装依赖
npm install commander chalk ora
代码示例
const { Command } = require('commander');
const chalk = require('chalk');
const ora = require('ora');
const program = new Command();
program
  .version('1.0.0')
  .description('An example CLI for demonstration purposes')
  .option('-n, --name <type>', 'specify your name')
  .option('-a, --age <number>', 'specify your age', parseInt);
program.parse(process.argv);
const options = program.opts();
const spinner = ora('Processing...').start();
setTimeout(() => {
  spinner.succeed('Processing complete');
  
  if (options.name) {
    console.log(chalk.blue(`Hello, ${options.name}!`));
  } else {
    console.log(chalk.red('Name not specified.'));
  }
  if (options.age) {
    console.log(chalk.green(`You are ${options.age} years old.`));
  } else {
    console.log(chalk.red('Age not specified.'));
  }
}, 2000);
在这个示例中,我们使用 commander 解析命令行参数,使用 ora 显示加载动画,并使用 chalk 为终端输出添加颜色和样式。运行这个脚本时,可以使用以下命令:
node script.js --name John --age 30
这将输出带有颜色和样式的文本,并在处理过程中显示加载动画。
inquirer(推荐使用@inquirer/prompts)
inquirer 是一个用于创建交互式命令行界面(CLI)的 Node.js 库。它提供了一种简单的方式来与用户进行交互,通过命令行提示用户输入信息、选择选项等。
安装
首先,你需要安装 inquirer:
npm install inquirer
基本用法
以下是一个基本示例,展示如何使用 inquirer 提示用户输入信息并处理用户的输入:
const inquirer = require('inquirer');
const questions = [
  {
    type: 'input',
    name: 'name',
    message: 'What is your name?',
  },
  {
    type: 'number',
    name: 'age',
    message: 'How old are you?',
  },
  {
    type: 'list',
    name: 'favoriteColor',
    message: 'What is your favorite color?',
    choices: ['Red', 'Green', 'Blue', 'Yellow'],
  },
];
inquirer.prompt(questions).then((answers) => {
  console.log(`Hello, ${answers.name}!`);
  console.log(`You are ${answers.age} years old.`);
  console.log(`Your favorite color is ${answers.favoriteColor}.`);
});
常见的提示类型
inquirer 支持多种提示类型,包括:
input: 用于接收用户的输入。number: 用于接收数字类型的输入。confirm: 用于接收布尔值(是/否)。list: 用于让用户从多个选项中选择一个。rawlist: 类似于list,但选项使用数字索引。expand: 类似于list,但使用单个字符作为快捷键。checkbox: 用于让用户从多个选项中选择多个。password: 用于接收密码类型的输入,输入内容会被隐藏。editor: 用于打开默认文本编辑器让用户输入长文本。
提示类型示例
以下是一些常见提示类型的示例:
const inquirer = require('inquirer');
const questions = [
  {
    type: 'input',
    name: 'username',
    message: 'What is your username?',
  },
  {
    type: 'password',
    name: 'password',
    message: 'Enter your password',
  },
  {
    type: 'confirm',
    name: 'confirm',
    message: 'Are you sure?',
  },
  {
    type: 'list',
    name: 'theme',
    message: 'What is your preferred theme?',
    choices: ['Light', 'Dark', 'Solarized'],
  },
  {
    type: 'checkbox',
    name: 'features',
    message: 'Select the features you want:',
    choices: [
      'Feature A',
      'Feature B',
      'Feature C',
    ],
  },
];
inquirer.prompt(questions).then((answers) => {
  console.log('Answers:', answers);
});
报错
inquirer.prompt(...).then is not a function 解决:使用v8版本(v9开始不再兼容CJS) 或者使用@inquirer/prompts(兼容CJS)
综合示例
下面是一个综合示例,展示如何将 commander, chalk, ora, 和 inquirer 结合使用,创建一个更复杂的命令行工具。
安装依赖
npm install commander chalk ora inquirer
代码示例
const { Command } = require('commander');
const chalk = require('chalk');
const ora = require('ora');
const inquirer = require('inquirer');
const program = new Command();
program
  .version('1.0.0')
  .description('An example CLI for demonstration purposes')
  .option('-i, --interactive', 'run in interactive mode');
program.parse(process.argv);
const options = program.opts();
if (options.interactive) {
  const questions = [
    {
      type: 'input',
      name: 'name',
      message: 'What is your name?',
    },
    {
      type: 'number',
      name: 'age',
      message: 'How old are you?',
    },
    {
      type: 'list',
      name: 'favoriteColor',
      message: 'What is your favorite color?',
      choices: ['Red', 'Green', 'Blue', 'Yellow'],
    },
  ];
  inquirer.prompt(questions).then((answers) => {
    console.log(chalk.blue(`Hello, ${answers.name}!`));
    console.log(chalk.green(`You are ${answers.age} years old.`));
    console.log(chalk.yellow(`Your favorite color is ${answers.favoriteColor}.`));
  });
} else {
  const spinner = ora('Processing...').start();
  setTimeout(() => {
    spinner.succeed('Processing complete');
    console.log(chalk.red('Run the script with --interactive to provide inputs.'));
  }, 2000);
}
在这个综合示例中,我们使用 commander 解析命令行参数,使用 ora 显示加载动画,使用 inquirer 提示用户输入信息,并使用 chalk 为终端输出添加颜色和样式。运行这个脚本时,可以使用以下命令:
node script.js --interactive
这将启动交互模式,提示用户输入信息。
Ctrl+C 中断不报错退出
为了优雅地处理 Ctrl+C 退出并避免报错,我们需要捕获 inquirer 库抛出的 ExitPromptError 异常。我们可以在捕获异常时进行特定处理,从而避免程序报错。
以下是一个示例,展示如何捕获并处理 ExitPromptError 异常:
const inquirer = require('@inquirer/prompts');
// 捕获 SIGINT 信号 (Ctrl+C)
process.on('SIGINT', () => {
  console.log('\n操作已取消');
  process.exit(0); // 正常退出
});
async function promptUser() {
  try {
    const answers = await inquirer.prompt([
      {
        type: 'input',
        name: 'username',
        message: '请输入你的用户名:',
      },
      {
        type: 'password',
        name: 'password',
        message: '请输入你的密码:',
      },
    ]);
    console.log('你的输入:', answers);
  } catch (error) {
    if (error.isTtyError) {
      console.error('Prompt couldn't be rendered in the current environment');
    } else if (error.message === 'User force closed the prompt with 0 null') {
      console.log('用户中断了输入');
    } else {
      console.error('发生错误:', error);
    }
  }
}
promptUser();
解释:
捕获
SIGINT信号:- 使用 
process.on('SIGINT', ...)监听SIGINT信号,这个信号在用户按下Ctrl+C时触发。 - 在信号处理函数中,输出一条消息(例如 
操作已取消),然后调用process.exit(0)正常退出程序。process.exit(0)表示正常退出,而非错误退出。 
- 使用 
 处理用户输入:
- 使用 
inquirer.prompt提示用户输入。 - 如果用户按下 
Ctrl+C,程序会抛出一个ExitPromptError异常。 - 在 
catch块中捕获这个异常,并根据异常信息进行特定处理:- 如果异常信息为 
User force closed the prompt with 0 null,则表示用户中断了输入,此时可以输出一条友好的消息(例如用户中断了输入),而不是抛出错误。 - 其他异常则按常规处理。
 
 - 如果异常信息为 
 
- 使用 
 
通过这种方式,你可以确保在用户按下 Ctrl+C 时,程序能够优雅地退出,并且不会抛出未处理的错误。