是時候擁有一個你自己的命令行工具了

本篇博客主要介紹瞭如何使用commander, inquirer以及chalk從零開始,創建屬於自己的命令行工具。

0. 一分鐘體驗

首先我們先花一分鐘的時間,體驗一下創建自己的命令行cli工具是什麼感覺。

0.1. 新建項目目錄

假如我們的項目名稱叫hello-cli,使用如下命令新建項目目錄。

mkdir hello-cli && cd hello-cli

0.2. 初始化項目

接下里使用npm-init命令來初始化一個簡單的package.json文件。

npm init -y

-y命令表示接受npm的一切默認參數設置。然後替換package.json爲如下代碼。

{
  "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"
  }
}

然後使用npm install安裝依賴。

0.3. 新建入口文件

在項目根目錄下新建名爲hello的文件,不需要任何後綴,值得注意的是此時的文件名就是你的cli工具第一個鍵入的命令,例如npm install,那麼hello就等價於npm。並將代碼替換如下。

#! /usr/bin/env node

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

program
  .command('init')
  .alias('i')
  .description('初始化項目')
  .action(option => {
    // 該對象用於存儲所有與用戶交互的數據
    let config = {
      // 假設我們需要用戶自定義項目名稱
      projectName: null
    };
    // 使用chalk打印美化的版本信息
    console.log(chalk.default.bold('hello v1.0.0'));

    // 用於存儲所有的交互步驟,例如讓用戶輸入項目名稱就是其中一個步驟
    let promps = [];
    if (config.projectName === null) {
      promps.push({
        type: 'input',
        name: 'projectName',
        message: '請輸入項目名稱',
        validate: input => {
          if (!input) {
            return '項目名稱不能爲空';
          }
          // 更新對象中屬性的數據
          config.projectName = input;
          return true;
        }
      });
    }

    // 至此,與用戶的所有交互均已完成,answers是收集到的用戶所填的所有數據
    // 同時,這也是你開始操作的地方,這個cli工具的核心代碼應該從這個地方開始
    inquirer.prompt(promps).then(async (answers) => {
      // do something here
      console.log(answers);
    });
  });

program.parse(process.argv);

0.4. npm link

那麼問題來了,
在你的項目根目錄下使用npm link,然後在你本地上就相當於安裝了名爲hello-cli這樣的一個全局npm包了。其原理是將你本地的項目在全局的node_modules中做了一個軟鏈接,拿此項目舉例,全局的hello命令已經指向了你的本地目錄。如果你想取消測試項目在全局中的映射,同樣的進入項根目錄,輸入命令npm unlink即可。

然後搭配以下命令食用你的第一個cli工具吧。如果報錯提示沒有權限,在命令前加上sudo即可。

hello init
# 或者
# hello i

1. commander

commander是一個Node.js環境下的命令行接口解決方案。在上面的一分鐘體驗例子中,我們用到了command,alias,description,action這四個API。

  • command command代表了這個cli工具向用戶暴露的命令行指令。我們還是拿npm install來舉例子,command('init')聲明瞭一個叫init的命令,在此處,init等價於install
  • alias alias是對於當前命令行指令的更短的指令。例如大家都知道,npm install可以簡寫爲npm ii就是定義的alias
  • description description是對當前命令行指令的描述,commander會自動的生成當前cli工具的幫助文檔,而該描述就會在hello -h中展示,如果你的一分鐘體驗項目還在的話,在命令行中輸入hello -h就可以看到自動生成的幫助文檔了
  • action action是我們註冊我們自己回調函數的地方
  • parse parse命令則是解析命令行

下面是一分鐘體驗項目中沒有使用的命令,option。還是舉一個例子。如果有用過hexo的應該熟悉這個命令。

hexo new post $YOUR_POST_NAME

沒用過也沒關係,這個命令是用於創建一個可以自定義名字的Markdown的文檔的。大家可能會發現,上面的命令包含了4個單詞,而我們的例子中只有兩個。那是因爲一分鐘項目中沒有使用commander的optionAPI。

如果你想在hello項目中實現一樣的命令,那麼只需要在program中調用該API即可。.option('-p, --post', 'add post'),然後就可以通過option參數獲取到-p後面,用戶輸入的參數的值。

2. inquirer

大家也發現了,在命令行輸入init命令後,我們需要不停地與命令行進行交互拿到數據,但是在代碼裏並沒有怎麼體現,這是因爲我們用了inquirer來幫我們做這些事情。

通過inquirer,我們可以實現輸入框,獲取用戶的輸入數據,還可以實現選擇框。舉個例子,用過antd-design-pro應該熟悉創建項目的流程。在命令行中輸入命令yarn create umi,在之後的流程中就會出現一個可選擇的list。只需要將步驟中的代碼替換成如下即可。

promps.push({
    type: 'list',
    name: 'projectName',
    message: '請輸入項目名稱',
    choices: [
      {
        name: 'ant-design-pro',
        value: 'ant-design-pro'
      },
      {
        name: 'dva',
        value: 'dva'
      }
    ]
});

在項目中,還使用了validate來對用戶的輸入數據進行驗證,如果不需要驗證的話,直接把validate整個代碼刪除掉就好。

3. chalk

chalk沒有什麼好介紹的,官網上的文檔已經寫的很詳細了。給大家列一下項目中使用的例子就好。

// 使用默認的字體顏色,加粗字體
console.log(chalk.default.bold('hello v1.0.0'));
// 打印藍色的提示信息
console.log(chalk.blue('hello v1.0.0'));
// 字符串模板用法,在同一行中打印不同樣式的信息
console.log(chalk`{white.bold [1/3]} 🔍` + chalk`{default.bold Clone project into local path...}`);

4. 最後

如果你厭倦了Node.js寫後端,想用Java的Spring Boot來寫,但是又擔心環境的搭建浪費太多時間。那麼你可以試試venus-init,只需要一行命令便可以快速搭建Java的開發環境。

Happy hacking.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章