こんにちは、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
をつくって、以下を書きます。
以下、敬称略です。
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
が返ってくるので、それを利用します。
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
が返ってくるので、それを利用します。
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」が便利だ
- ラミちゃんの本名は「アレキサンダー・ラモン・ラミレス・キニョーネス」