LoginSignup
38
36

More than 5 years have passed since last update.

node.jsでCLI

Last updated at Posted at 2016-07-20

コマンドラインツールまたはシェルスクリプト相当を書こうというお話。node.jsで書く利点はWindowsでもOSXでもLinuxデスクトップでも全く同じように実行可能だから。node.jsが入っているという前提条件だけど。

前準備

オフィシャルサイトやQiitaを参考にnode.jsとnpmが使えるようにする。

プロジェクトの作成

特別なことは何もなくいつも通り npm init で。

shebang

#!/usr/bin/env node

shebangはUnix系の実行に必要。Windowだとこれは無視される。詳しくは https://docs.npmjs.com/files/package.json で。

オプションパーサー

コマンド引数を素のnode.jsで扱うのはちょっと辛いので commander パッケージを利用する。

入力プロンプト

これもやはり便利な co-prompt co パッケージを使う。

Unixライクコマンド実行

shelljs を使うとnode.jsで lsecho っぽいコードが簡単に書ける素晴らしいパッケージ。勿論Windowsでも使えます。

package.json

上記のパッケージをプロジェクトにインストール。

$ npm i commander co-prompt co shelljs --save
$ npm list --depth=0
+-- co@4.6.0
+-- co-prompt@1.0.0
+-- commander@2.9.0
`-- shelljs@0.7.0

サンプルコード

プロジェクト名はmycliで。

package.json
{
  "name": "mycli",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "bin": {
    "mycli": "./index.js"
  },
  "dependencies": {
    "co": "^4.6.0",
    "co-prompt": "^1.0.0",
    "commander": "^2.9.0",
    "shelljs": "^0.7.0"
  }
}

今回は紹介だけなので index.js をこんな風に。ファイル名指定とユーザー名パスワード入力ができます。

index.js
#!/usr/bin/env node
require('shelljs/global')

program = require('commander')
prompt = require('co-prompt')
co = require('co')

program
  .arguments('<file>')
  .option('-u, --username <username>', 'The user to authenticate as')
  .option('-p, --password <password>', 'The user\'s password')
  .action(function(file) {
    co(function *() {
      var username, password
      if (program.username) {
        username = program.username
      } else {
        username = yield prompt('username: ')
      }
      password = yield prompt.password('password: ')
      display(username, password, file)
    })
  })
  .parse(process.argv)

display = (username, password, file) => {
  echo(`user: ${username} pass: ${password} file: ${file}`)
}

index.jsに実行権を付与して実行。まずはヘルプから。

$ index.js --help

  Usage: index [options] <file>

  Options:

    -h, --help                 output usage information
    -u, --username <username>  The user to authenticate as
    -p, --password <password>  The user's password

オプション関連はcommanderが全部処理してくれてヘルプも自動的に生成される。すごく便利。

実際の実行イメージはこんな感じ。

$ index.js hoge.txt
username: foo     
password: ***
user: foo pass: bar file: hoge.txt

$ index.js hoge.txt -u foo
password: ***
user: foo pass: bar file: hoge.txt

入力関連はco-promptで実現。パスワードに***とマスクをかけて入力するのも簡単。オプションで直接指定する時はさすがにマスクかからないけど実用性抜群。

shelljsは今回echo()だけ使ったが、基本的なUnixコマンドライクな関数が揃っててこれもまた便利。npmのscriptsでも使えるので簡単なことならタスクマネージャーよりこっちがフットワーク軽いです。

shelljs で使える関数の例。

cd([dir])
pwd()
ls([options,] [path, ...])
ls([options,] path_array)
find(path [, path ...])
find(path_array)
cp([options,] source [, source ...], dest)
cp([options,] source_array, dest)
rm([options,] file [, file ...])
rm([options,] file_array)
mv([options ,] source [, source ...], dest')
mv([options ,] source_array, dest')
mkdir([options,] dir [, dir ...])
mkdir([options,] dir_array)
test(expression)
cat(file [, file ...])
cat(file_array)
head([{'-n', },] file [, file ...])
head([{'-n', },] file_array)
tail([{'-n', },] file [, file ...])
tail([{'-n', },] file_array)
〜

shelljsサンプルコード。

shelljs-example.js
require('shelljs/global');

if (!which('git')) {
  echo('Sorry, this script requires git');
  exit(1);
}

// Copy files to release dir
rm('-rf', 'out/Release');
cp('-R', 'stuff/', 'out/Release');

// Replace macros in each .js file
cd('lib');
ls('*.js').forEach(function(file) {
  sed('-i', 'BUILD_VERSION', 'v0.1.2', file);
  sed('-i', /^.*REMOVE_THIS_LINE.*$/, '', file);
  sed('-i', /.*REPLACE_LINE_WITH_MACRO.*\n/, cat('macro.js'), file);
});
cd('..');

// Run external tool synchronously
if (exec('git commit -am "Auto-commit"').code !== 0) {
  echo('Error: Git commit failed');
  exit(1);
}

他にもおすすめのnode.jsパッケージは出力テキストをカラーリングするchalkや進捗を出力するprogressなどなど。

おすすめパッケージがあればコメント下さい🙇

mycliインストール

パッケージのルートにてnpm linkを実行する。

$ npm link
npm WARN mycli@1.0.0 No description
npm WARN mycli@1.0.0 No repository field.
/usr/local/bin/mycli -> /usr/local/lib/node_modules/mycli/index.js
/usr/local/lib/node_modules/mycli -> /Users/uchcode/Desktop/mycli
$ mycli --help

  Usage: mycli [options] <file>

  Options:

    -h, --help                 output usage information
    -u, --username <username>  The user to authenticate as
    -p, --password <password>  The user's password

パッケージを公開すればどの環境でも簡単にインストール実行ができます。

node.jsすごいね。

38
36
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
38
36