arrow-righthamburgerlogo-marksocial-facebooksocial-githubsocial-twitter
2016.10.05

Node.jsでコマンドラインツール作るときに使いやすいreadline-sync

のびすけ

Node.js Magazine
   このエントリーをはてなブックマークに追加  

こんにちは、代表ののびすけです。 Node.js Magazineという連載を作ったのでNode.js系のTipsを紹介していく予定です。

今日はNode.jsでコマンドラインツールを作る際に役立つreadline-syncというパッケージを紹介します。

実際にサンプルを動かして見ましょう。

執筆時点のマシンスペック

何か不具合があったときに参照してください。

インストール

URL: https://www.npmjs.com/package/readline-sync

npm i readline-sync

サンプルを動かしてみる

まずは基本的なサンプルです。.question()で質問して入力結果をそのまま変数に入れ込めます。このサンプルでいうとuserNamefavFoodの変数に入力した値が入ります。

//app.js
const readlineSync = require('readline-sync');

let userName = readlineSync.question('あなたの名前は? ');
console.log(`->こんにちは ${userName}!`);

let favFood = readlineSync.question('好きな食べ物は? ', {hideEchoBack: true});
console.log(`->${userName}は${favFood}が好きなんだね!`);

{hideEchoBack: true}というオプションをつけると入力時は*で表示されます。

選択肢を出して選ばせる

選択肢を提示してユーザーに選ばせる方法もよく使われます。

keyInSelectメソッドを使います。

//app.js
const readlineSync = require('readline-sync');

let animals = ['のびすけ', 'うらら', 'ちゃちゃまる', 'うこ', 'ギャル電'];
let index = readlineSync.keyInSelect(animals, '誰に連絡しますか?');
console.log(`${animals[index]}に連絡します。`);

人の名前を選択肢して、その人に連絡をするみたいなインターフェイスを作って見ました。変数がanimalsなのは気にしません。

CLIループでサブコマンドを作る

コマンド終了のタイミングをユーザーに委ねたいときに使えます。

promptCLLoopメソッドで関数を引数に渡すと関数をループ実行してくれます。

このサンプルだとbyeというサブコマンドを入力すると終了します。

逆に言えばbyeを入力するまではずっとその他コマンドの入力を待ち受けます。

//app.js

const readlineSync = require('readline-sync');
readlineSync.promptCLLoop({
  add: (target, into) => {
    console.log(`${target}を${into}に追加します。`);
    // Do something...
  },
  remove: (target) => {
    console.log(`${target}を削除します。`);
    // Do something...
  },
  bye: () => { return true; }
});
console.log('終了します。');

こんな感じで

> コマンド名 変数1 変数2 ...

という入力を受け付けて紐づけられている関数の引数として変数が渡されます。

キー入力で値を選んでもらう

この表現がいいのか分からないですけど、、、見ればわかります。

keyInメソッドでキー入力の待ち受けを実現しています。

//app.js

const readlineSync = require('readline-sync');

const MAX = 60, MIN = 0;
let value = 30, key;
console.log(`\n\n${(new Array(20)).join(' ')}[Z] <- -> [X]  決定: [SPACE]\n`);
while (true) {
  console.log('\x1B[1A\x1B[K|' +
    (new Array(value + 1)).join('-') + 'O' +
    (new Array(MAX - value + 1)).join('-') + '| ' + value);
  key = readlineSync.keyIn('',
    {hideEchoBack: true, mask: '', limit: 'zx '});
  if (key === 'z') { if (value > MIN) { value--; } }
  else if (key === 'x') { if (value < MAX) { value++; } }
  else { break; }
}
console.log(`\nあなたが決めた値: ${value}`);

zとxで値を調節してスペースで決定です。

まとめ

簡単でしたが以上になります。

いかがでしたでしょうか。 非同期が基本になっているJavaScriptでコマンドラインからの入力受付を同期的にやる場合にはかなり使いやすいパッケージだと思います。

readline-syncでコマンドラインツールを作って見ましょう!

もっとこっちの方がオススメだよ!ってものがあれば是非@n0bisukeに教えてください :)

   このエントリーをはてなブックマークに追加