[node.js] 打造美觀的互動式 CLI 介面

前陣子在 Youtube 上看到了一部影片,介紹了好幾個 node.js 的套件,來幫助我們打造漂亮的 CLI,才後知後覺的發現一直在使用的 Angular CLI、Schematics 等等,許多由 node.js 開發的 CLI 工具,背後那些美觀的畫面都是基於這些套件,而不是自己刻的,所以整理了一下這些套件的介紹與示範!

範例程式:https://github.com/wellwind/resume-builder-cli-demo

影片支援

chalk

chalk 套件可以讓我們輕易的輸出各種五顏六色的內容到畫面上,而不再只是死死的黑底白字,眼前立刻就亮了起來。

寫這篇文章時,chalk 是 5.0.0 版,而 TypeScript 是 4.6.0,目前會有不相容的問題,導致 chalk 新版不支援 TypeScript,因此若要使用 TypeScript 的話,目前需要安裝 [email protected]

相關 issue 參考

要印出有顏色的文字,只要使用 chalk 指定顏色即可:

import chalk from 'chalk';

console.log(chalk.red('Hello World'));

如果要指定背景顏色,可以使用 bg* 系列的方法,

console.log(chalk.bgRed('Hello World'));

當然,也可以同時指定文字顏色與背景顏色,可以先指定背景,再指定顏色;也可以反過來,先指定顏色,再指定背景。

console.log(chalk.red.bgBlue('Hello World'));
console.log(chalk.bgBlue.red('Hello World'));

不論是文字顏色還是背景顏色,除了內建顏色外,也能夠自己指定色碼:

console.log(chalk.bgHex('#DEADED')('Hello World'));
console.log(chalk.hex('#DEADED')('Hello World'));

另外,以可以設定底線:

// 藍色底線文字
console.log(chalk.underline.blue('Hello World'));

也可以設定文字顏色和背景顏色反轉

// 文字藍色+背景紅色 -> 反轉:文字紅色+背景藍色
console.log(chalk.bgRed.blue.inverse('Hello World'));

透過 chalk,就可以自由的輸出各種顏色的文字啦!

gradient-string

chalk 只可以產出單一顏色,而 gradient-string 更酷,可以產生漸層的顏色。

我們可以直接使用內建的漸層顏色:

import gradient from 'gradient-string';
console.log(gradient.rainbow('Hello World'));

也可以自己定義漸層顏色:

// Using varargs
let coolGradient = gradient('red', 'green', 'blue');

// Using array
let coolGradient = gradient(['#FF0000', '#00FF00', '#0000FF']);

如果產生的文字是多行文字,預設是從上到下逐行變色:

console.log(gradient.mind('Line 1\nLine 2\nLine 3'));

如果希望每一行都是從左到右逐漸變色,可以使用 .multiline

console.log(gradient.mind.multiline('Line 1\nLine 2\nLine 3'));

figlet.js

figlet.js 可以把一段文字轉成圖片,當然,在 console 輸出的不是真的圖片,而是將一堆 ascii 文字組合起來,讓他看起來像原始指定的文字內容,例如:

figlet.js 實作了 FIGFonts,這是一個規範文件,也是一種產生出這種圖形文字的規則,裡面說明了產生出這種文字的方法。

使用方式也很簡單,安裝後呼叫 figlet 即可,產生出來的結果會在 callback 方法內。

figlet.text('Hello World', (error, result) => {
    console.log(result);
});

由於產生這種文字需要一時間運算,因此 flglet.text 是非同步執行的,如果想要同步執行,也可以使用 figlet.textSync

var result = figlet.textSync('Hello World');
console.log(result);

搭配 chalk 或 gradient-string 套件,就成了許多 CLI 工具剛啟動時的 banner 畫面了!

當然,這只支援一般的 ASCII code 文字,並不支援中文。

inquire.js

Inquirer.js 可以幫助我們打造互動式的介面,提供了許多簡單的參數,來讓使用者輸入答案、選擇選項等等,藉由互動的方式協助使用者完成各種設定。

安裝完成後,可以使用 inquirer.prompt() 開始進行提問,基本架構:

inquirer.prompt([
  // 題目
]).then(result => {
    // 回答內容
});

其中提供了很多的提目類型:

{% asset_ing 05.png %}

例如文字類型:

inquirer.prompt([
  {
    type: 'input',
    name: 'Name',
    message: 'Your Name?'
  },
  {
      type: 'list',
    name:'sex',
    message: 'Your Sex?',
    choices: [
        'Male',
      'Female'
    ]
  }
]).then(result => {
    console.log(result);
});

單選類型:(可以使用上下方向鍵選擇)

inquirer.prompt([{
    type: 'list',
    name: 'sex',
    message: 'Your Sex?',
    choices: [
      { name: 'Male', value: 'M' },
      { name: 'Female', value: 'F' },
    ],
    default: 'M'
}])

複選類型:(使用放下方向鍵切換選項,空白鍵選擇)

inquirer.prompt([{
    type: 'checkbox',
    name: 'Interest',
    message: 'Your Interest (Multiple)',
    choices:[
        { name: 'Angular', value: 'angular' },
        { name: 'HTML', value: 'html' },
        { name: 'CSS', value: 'css' },
        { name: 'React', value: 'react' },
        { name: 'Vue', value: 'vue' },
    ]
}])

更多選項可以到 GitHub 上參考。

inquirer.js 也可以搭配 RxJs 的 subject 使用,像我這麼愛熱 RxJS 的人,一定要特別提出來!

inquirer.prompt(prompts).ui.process.subscribe(answers => {
    console.log(answers);
})

prompts.next({
  type: 'input',
  name: 'Name',
  message: 'Your Name?',
});

prompts.next({
  type: 'list',
  name: 'sex',
  message: 'Your Sex?',
  choices: [
    { name: 'Male', value: 'M' },
    { name: 'Female', value: 'F' },
  ],
  default: 'M',
});

prompts.complete();

所有顯示的文字,都可以透過 chalk 等套件改變顏色。

nanospinner

nanospinner 可以建立一個 spinner 的小動畫,讓我們能「感覺」程式還在處理中。

建立一個 spinner,並呼叫 start(),就可以看到一個小動畫

const spinner = nanospinner.createSpinner('Processing').start();

完成後,呼叫 success() 即可,會提示成功的 icon

spinner.success({ text: 'Done' });

當然,如果發生錯誤,也可以呼叫 error(),會提示錯誤的 icon

spinner.error({ text: 'Error' });

一樣的,所有顯示的文字,都可以透過 chalk 等套件改變顏色。

本日小結

第一次看到這麼花俏的介面,是剛接觸 Angular CLI 的時候,隨著 schematics 的發展,也出現了非常具有互動式的功能,後來又看到 Firebase CLI 工具,也都有類似的功能,原本以為都是這些 CLI 自己刻的,沒想到早就有相關的套件可以幫助我們達到一樣的目標了。對於要使用 node.js 實作一些小工具來說真的是非常方便啊!!

如果您覺得我的文章有幫助,歡迎免費成為 LikeCoin 會員,幫我的文章拍手 5 次表示支持!