This blog post describes how commander, Inquirer, and Chalk created their own command line tools from scratch.

0. One-minute experience

First let’s take a minute to experience what it’s like to create your own command-line cli tool.

0.1. Create a project directory

If our project name is hello-cli, use the following command to create a new project directory.

mkdir hello-cli && cd hello-cli
Copy the code

0.2. Initialize the project

Next, use the npm-init command to initialize a simple package.json file.

npm init -y
Copy the code

The -y command accepts all default parameters of NPM. Then replace package.json with the following code.

{
  "name": "hello-cli"."version": "1.0.0"."description": ""."main": "index.js"."bin": {
    "hello": "hello"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": []."author": ""."license": "ISC"."dependencies": {
    "chalk": "^" 2.4.2."commander": "^ 2.20.0"."inquirer": "^ 6.3.1"."shelljs": "^ 0.8.3"}}Copy the code

Then use NPM Install to install the dependencies.

0.3. Create an import file

Create a new file named Hello in the project root directory, without any suffix. Note that the file name is the first command typed by your CLI tool, such as NPM install, so hello is equivalent to NPM. And replace the code as follows.

#! /usr/bin/env node

const program = require('commander');
const inquirer = require('inquirer');
const chalk = require('chalk');

program
  .command('init')
  .alias('i')
  .description('Initialize the project')
  .action(option= > {
    // This object is used to store all the data that the user interacts with
    let config = {
      // Suppose we need a user-defined project name
      projectName: null
    };
    // Use Chalk to print the beautified version information
    console.log(chalk.default.bold('hello v1.0.0'));

    // Used to store all interactive steps, such as having the user enter a project name
    let promps = [];
    if (config.projectName === null) {
      promps.push({
        type: 'input'.name: 'projectName'.message: 'Please enter project name'.validate: input= > {
          if(! input) {return 'Project name cannot be empty';
          }
          // Update the data of attributes in the object
          config.projectName = input;
          return true; }}); }// At this point, all interactions with the user are complete, and answers is all the data that the user has filled in
    // Also, this is where you start, the core code of the CLI tool should start
    inquirer.prompt(promps).then(async (answers) => {
      // do something here
      console.log(answers);
    });
  });

program.parse(process.argv);
Copy the code

0.4. npm link

The problem is that using NPM link in your project root directory is equivalent to installing a global NPM package called Hello-CLI locally. The idea is to make a soft link to your local project in the global node_modules. For example, the global Hello command already points to your local directory. If you want to unmap the test project globally, again go to the root of the project and type NPM unlink.

Then use your first CLI tool with the following command. If an error message is displayed indicating that you do not have permission, add sudo before the command.

hello init
# or
# hello i
Copy the code

1. commander

Commander is a command line interface solution for node. js. In a minute experience example above, we use the command, alias, description, action of the four apis.

  • Command Indicates the command line commands exposed by the CLI tool to users. Using NPM install as an example, command(‘init’) declares a command called init, where init is equivalent to install

  • Alias An alias is a shorter directive to the current command line directive. For example, as you all know, NPM install can be shortened to NPM I. I is the defined alias

  • Description Description is the description of the current command line command. Commander automatically generates the help document for the current CLI tool, and this description is displayed in hello-h. If your one-minute experience item is still available, Type Hello -h on the command line to see the automatically generated help document

  • Action Action is where we register our own callback functions

  • Parse Parse commands parse command lines

The following command, option, is not used in the one-minute experience project. Let me give you an example. Those of you who have used hexo should be familiar with this command.

hexo new post $YOUR_POST_NAME
Copy the code

Never mind, this command is used to create a Markdown document with a custom name. You may notice that the command above contains four words, compared to two in our example. That’s because the optionAPI of commander is not used in the one minute project.

If you want to implement the same command in your Hello project, just call the API in program. .option(‘-p, –post’, ‘add post’), then the option argument can be used to get the value of the user input after -p.

2. inquirer

As you can see, when you type init on the command line, you have to keep interacting with the command line to get the data, but it doesn’t really show up in the code, because we use the Inquirer to do that for us.

With Inquirer, we can implement the input box, get the user’s input data, and also can implement the selection box. For example, having used ANTD-Design-Pro should be familiar with the process of creating a project. Enter yarn create umi on the cli. A list of options is displayed. Just replace the code in the step with the following.

promps.push({
    type: 'list'.name: 'projectName'.message: 'Please enter project name'.choices: [{name: 'ant-design-pro'.value: 'ant-design-pro'
      },
      {
        name: 'dva'.value: 'dva'}}]);Copy the code

In the project, validate is also used to validate user input data. If validation is not needed, simply remove the entire validate code.

3. chalk

Chalk doesn’t have much to say, but the documentation on his website is quite detailed. I’ll just give you a list of examples that we used in the project.

// Use the default font color, bold font
console.log(chalk.default.bold('hello v1.0.0'));
// Prints a blue prompt
console.log(chalk.blue('hello v1.0.0'));
// String template usage to print different styles of information on the same line
console.log(chalk` {white. Bold [1/3]} 🔍 ` + chalk`{default.bold Clone project into local path... } `);
Copy the code

4. The last

If you’re tired of node.js writing back ends and want to use Java’s Spring Boot to do so, but are worried about setting up your environment will take too much time. Try Venus-init, a quick way to set up a Java development environment with a single command.

Happy hacking.