Node.js でコンソールアプリを作る

この記事は OUCC Advent Calendar 2016 の 21 日目の記事です.

www.adventar.org

こんにちは, @susisu2413 です.

みなさんは JavaScript でコンソールアプリを作りたくありませんか? 私は作りたいです.

この記事では Node.js (+ NPM) を使って JavaScript でコンソールアプリを作成する方法を紹介します.

コンソールアプリケーションはあんまり見栄えしませんね。

そんなことないよ! f:id:susisu:20151224004353g:plain

用意するもの

公式サイトからダウンロードしてくる以外の方法もありますが, ここでは割愛.

NPM は Node.js をインストールするとたぶん勝手についてきます.

作ってみる

まずはディレクトリを作りましょう. 適当に名前は myconsoleapp とかで.

$ mkdir myconsoleapp
$ cd myconsoleapp

次に Node.js (NPM) の初期設定をします.

$ npm init

適当にエンターキーを連打していると, 以下のような内容の package.json が作成されます.

{
  "name": "myconsoleapp",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Susisu <susisu2413@yahoo.co.jp> (https://github.com/susisu)",
  "license": "MIT"
}

次に実行ファイルを配置するディレクトリを作成します. 後で作成する実体は JavaScript ですが, bin という名前にしておきます.

$ mkdir bin

続いて package.json に以下のように directories という項目を追加します. こうすることで NPM が実行ファイルのあるディレクトリを認識してくれるというわけですね.

{
  "name": "myconsoleapp",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Susisu <susisu2413@yahoo.co.jp> (https://github.com/susisu)",
  "license": "MIT",
  "directories": {
    "bin": "bin"
  }
}

さて, ようやくですが実行ファイル本体を作成しましょう. とりあえず bin/myconsoleapp に以下のような何の面白みもない "Hello, world!" を表示するだけのプログラムを作成します.

#!/usr/bin/env node

// 呪い
"use strict";

process.stdout.write("Hello, world!\n");

ShebangWindows では動かないんじゃないかとか chmod +x しないといけないんじゃないかといった心配は必要ありません. 全て NPM がいい感じにやってくれます. 便利ですね.

実際にインストールして動かしてみましょう.

$ npm link
$ myconsoleapp
Hello, world!

めでたい.

もし command not fount などと言われた場合は NPM のグローバルインストールのディレクトリにパスが通っているか確認しましょう.

さらに変更を加える場合はそのまま bin/myconsoleapp を編集すれば, 再度 npm link をしなくても変更が反映されます (リンク (ショートカット) なので).

ライブラリを使う

NPM は名前から察しがつく通りパッケージマネージャなので, ライブラリの管理を行うこともできます.

ここでは Commander.js というコマンドラインパーサのライブラリを依存パッケージに加えてみましょう.

まずはパッケージを今作っているコンソールアプリの環境にインストールします. package.json に依存関係を保存するため, --save というオプションをつけています.

npm install --save commander

次に bin/myconsoleapp を以下のように変更します. ここでは --name <name> というオプションを追加しています.

#!/usr/bin/env node

"use strict";

var program = require("commander");
// -n <name> あるいは --name <name> というオプションを作成
program.option("-n, --name <name>", "name");
// 引数を読み取る
program.parse(process.argv);

if (typeof program.name === "string") {
  // name が指定されていればその人に挨拶
  process.stdout.write("Hello, " + program.name + "!\n");
}
else {
  process.stdout.write("Hello, world!\n");
}

実行してみましょう. 既に上の手順で npm link してあればそのまま実行できます.

$ myconsoleapp
Hello, world!
$ myconsoleapp --name Shinobu
Hello, Shinobu!

よかったですね.

Commander.js の詳しい使い方は API documentation などを参考にしてください. なんとなく不安なところはあるけど良いライブラリです.

この他にも NPM には大量に便利なライブラリがあるので, 何かがほしい時は探せば大抵何か見つかると思います. 個人的にコンソールアプリを作るときに便利だと思うものを紹介すると,

  • chalk: 簡単に出力する文字に色をつけられたりするやつ
  • blessed: curses 的な

等々. 実際にこれらを使っている例はこんな感じ.

配布する

良い感じのコンソールアプリができたら配布したくなることでしょう.

作成したコンソールアプリを配布するには例えば以下のような方法があります.

  1. GitHubリポジトリを配置する
  2. NPM にパブリッシュする

GitHubリポジトリを配置する

最も簡単な方法として, GitHubリポジトリを配置する方法があります.

ここでは git や GitHub の使い方は説明しませんので, わからなければググりましょう.

例えば私 (susisu) が myconsoleapp という名前のリポジトリを作成した場合,

$ npm install --global susisu/myconsoleapp

で他の環境にもインストールできるようになります.

例として一つ置いておきます: https://github.com/susisu/kinmosa-gen

NPM にパブリッシュする

GitHubリポジトリを配置した場合の欠点として, バージョン管理がしにくいということがあります.

きちんとバージョン管理をする必要が出るくらいまともなものを作った時は NPM にパブリッシュするようにしましょう.

注意: 以下のコマンドを実行すると, NPM のレジストリ上の名前を専有し, ついでに削除することも基本的にはできませんので, 実行する際は慎重に. 名前を専有するほどでもない場合は, 以下の scoped package についてを参照してください.

予め NPM のアカウントを作った状態で,

$ npm publish

を実行すると, 他の環境にも

$ npm install --global myconsoleapp

でインストールできるようになります (このときの名前は package.json 内の name が使われます).

scoped package

上でも書きましたが, 普通に NPM にパブリッシュすると名前を専有してしまい, 他の人が同じ名前のものをパブリッシュできなくなってしまいます.

名前を専有するほどでもない場合や, 他の人が既に作成したものと名前が被っているときは, scope という仕組みがあるのでそれを使うようにしましょう.

まずは package.json 内の name を以下のように変更します (私の場合ユーザー名が susisu なので, 前に @susisu をつける).

{
  "name": "@susisu/myconsoleapp",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Susisu <susisu2413@yahoo.co.jp> (https://github.com/susisu)",
  "license": "MIT",
  "directories": {
    "bin": "bin"
  }
}

初回にパブリッシュする時は,

$ npm publish --access public

のように --access public というフラグを付けます (元は private なパッケージのための仕組みだったため?).

こうすると, 他の環境へのインストールは,

$ npm install --global @susisu/myconsoleapp

のようにできるようになります. ユーザー名以下のスコープを使うのでなんとなく気が楽で良い感じ.

まとめ

というわけで Node.js でコンソールアプリを作成する方法でした.

Node.js でコンソールアプリを作成する利点は, 作成も配布も簡単に行えて, Node.js がインストールされていればどこでも動くといったところでしょうか. とにかく何でも JavaScript で書きたい人にとってはこの上ない環境だと思います.

OUCCM

OUCC ではとにかく何でも JavaScript で書きたい部員を募集しております.

oucc.org

npm view をいい感じに整形してくれるやつを作った

ググってもいい感じのが無さそうだったので作りました (既にあったら教えてください).

npm i -g npm-sum

github.com

なにこれ

npm にはパッケージの情報を取得する npm view (あるいは show, info, v) というコマンドがありますが, これは全ての情報を含む巨大な JSON を返してくるので, 欲しい情報を探すにも時間がかかります. (そもそも人間が読むものではない気がする. ご丁寧にハイライトまでしてくれるけれど.)

もちろん, 欲しい情報だけを取り出すこともできて, 例えば npm の最新バージョンを知りたいとかなら npm view npm version などとすれば良いのですが, なんかそれも面倒なので必要そうな情報をまとめて表示してくれるのを作りました.

要するに brew info みたいなのが欲しかったのです.

例えば npm の情報を見てみるとこんな感じになります (ターミナル上では色もつく).

$ npm-sum npm
  Name        : npm
  Version     : 4.0.2 (2016-11-4 11:38:17)
  Homepage    : https://docs.npmjs.com/
  Author      : Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me)
  License     : Artistic-2.0
  Description : a package manager for JavaScript
  Keywords    : install, modules, package manager, package.json
  Tags        :
    3.x-latest  : 3.10.9 (2016-10-7 13:38:58)
    3.x-next    : 3.10.10 (2016-11-5 10:18:12)
    latest      : 4.0.2 (2016-11-4 11:38:17)
    latest-1    : 1.4.29 (2015-10-30 10:52:42)
    latest-2    : 2.15.11 (2016-9-9 11:52:01)
    latest-3    : 3.10.10 (2016-11-5 10:18:12)
    lts         : 2.15.11 (2016-9-9 11:52:01)
    next        : 4.0.3 (2016-11-18 08:28:08)
    next-2      : 2.15.11 (2016-9-9 11:52:01)
    next-3      : 3.10.10 (2016-11-5 10:18:12)
    v3.x-latest : 3.10.9 (2016-10-7 13:38:58)
    v3.x-next   : 3.10.10 (2016-11-5 10:18:12)
  Binaries    : npm

わかりやすいですね.

依存パッケージは異常な数になってしまっていることがあるのでとりあえず表示していません. 気が向いたときにオプションとかでつけるかも. けど表示するようにしました. 意外と見た目的にはそんなにって感じだったのでデフォルトで表示します.

f:id:susisu:20161202165732p:plain:w441