Posted at

Node.jsでサクッとCLIアプリ作るなら cacjs が便利だよ

More than 1 year has passed since last update.

こんにちは、Pちゃんです。

この記事は、DeNA IPプラットフォーム事業部 Advent Calendar 2017 18日目の記事です。

@koooootake に勧誘されて、うっかりアドベントカレンダーに登録してしまいました。


さて、今日はNode.jsを使ってサクッとCUIアプリケーションを作る方法を紹介していきたいと思います。


技術選定

一見、CLIアプリケーションの一つや二つくらい、素のNode.jsでも書くことができそうだと考えがちです。

しかし、サブコマンドの処理やオプションの処理、ヘルプを出すことなどを考えると、意外と面倒だったりします。

そこで、何かしらのフレームワークに乗っかるのが合理的です。

Node.jsでCUIアプリケーションをつくるためのフレームワークは、わりと数年前からデファクトが決まっています。

自分の観測範囲では、以下の2つがよく使われている気がします。

しかし、今回は敢えて cacjs を紹介しようと思います。

cacjs は、@egoist がつくった、シンプルでパワフルなコマンドラインインターフェイスをつくるためのフレームワークです。

特徴としては、


  • 一つのコマンドに関する処理を一箇所にまとめて書けるので、直感的に書きやすい

  • プラグイン機構を備えているため、本気でカスタマイズしていくことも可能である

などがあります。


cacjs でCLIアプリをつくる


1. cacjs をインストールする

$ mkdir cli-app-sample && cd cli-app-sample

$ npm init
$ npm install cac


2. コードを書く

index.js をつくって、以下を書きます。

以下、敬称略です。


index.js

const cac = require('cac')

const cli = cac()

const managers = ['ラミレス', '中畑', '尾花', '大矢', '牛島']

cli.command('managers', {
desc: '横浜DeNAベイスターズの今の監督を表示します'
}, () => {
console.log(`今の監督は${managers[0]}です`)
})

cli.parse()



3. 実行してみる

実はもうさっき書いた十数行でCLIアプリができています。

試しに managers を実行してみます。

$ node index.js managers

今の監督はラミレスです

次に --help とかも試してみます。

$ node index.js --help

index.js 1.0.0

USAGE

index.js <command> [options]

COMMANDS

managers 横浜DeNAベイスターズの今の監督を表示します

GLOBAL OPTIONS

-v, --version Display version [Type: boolean]
-h, --help Display help (You're already here) [Type: boolean]

$ node index.js --version
1.0.0

すげえ、簡単すぎる。


4. サブコマンドを試してみる

先ほどのサンプルを改造して、過去の監督も取得できるようにしてみたいと思います。

cli.command のコールバックで input が返ってくるので、それを利用します。


index.js

const cac = require('cac')

const cli = cac()

const managers = ['ラミレス', '中畑', '尾花', '大矢', '牛島']

cli.command('managers', {
desc: '横浜DeNAベイスターズの過去の監督を表示します'
}, (input) => {
if (input[0] > 0) {
console.log(`${input[0]}人前の監督は${managers[input[0]]}です`)
} else {
console.log(`今の監督は${managers[0]}です`)
}
})

cli.parse()


$ node index.js managers 1

1人前の監督は中畑です


5. フラグを試してみる

さて、先ほどのサンプルをさらに改造して、監督のフルネームも取得できるようにしてみようと思います。

今回の場合、$ node index.js managers 3 --fullname などとすると、3人前の監督がフルネームで取得できるようにします。

cli.command のコールバックで flag が返ってくるので、それを利用します。


index.js

const cac = require('cac')

const cli = cac()

const managers = [
['アレックス', 'ラミレス'],
['中畑', ''],
['尾花', '高夫'],
['大矢', '明彦'],
['牛島', '和彦']
]

cli.command('managers', {
desc: '横浜DeNAベイスターズの過去の監督を表示します'
}, (input, flag) => {

let managerNum = input[0] || 0

if (managerNum > managers.length - 1 ) {
console.log(`${managers.length}人以上前の監督のデータはありません...`)
process.exit(1)
}

let managerName = managers[managerNum][0]

// ここで flag.fullname を見て true ならフルネームにする
if (flag.fullname) {
managerName += ' ' + managers[managerNum][1]
}

if (!managerNum) {
console.log(`今の監督は${managerName}です`)
} else if (managers.length > managerNum) {
console.log(`${managerNum}人前の監督は${managerName}です`)
}
})

cli.parse()


$ node index.js managers 4 --fullname

4人前の監督は牛島 和彦です


まとめ


  • Node.jsで、サクッとCLIアプリ作るなら「cacjs」が便利だ

  • ラミちゃんの本名は「アレキサンダー・ラモン・ラミレス・キニョーネス」