LoginSignup
5
5

More than 5 years have passed since last update.

Node.js上で存在するかわからない外部コマンド(peco)を実行する

Posted at

インターネッツの海を泳ぎまくっても解決しなかったので自分なりの対応を考えここにまとめておく。
もし、何かアホな事を書いていて、もっと簡単にできるねんで!とかあったら教えていただけると大変ありがたいです。

モチベーション

dtsmを使う時に、何で検索するべきかわからない時が結構ある。
例えば、dtsm install angularとかやると、angular could not be identified. found: 38とか言われてしまいます※1。
こうなると、dtsm search angularなどとして候補一覧を確認し、dtsm install angularjs/angular.d.tsとする必要があります。
だるいですね。
そこで、pecoを使ってインクリメンタルにファイルの指定を行えるようにしたいな!となるわけです。

インクリメンタルに検索の様子

※1 これは、DefinitelyTyped上でangularjs/angular.d.tsというファイル名になっているためです。jqueryの場合はjquery/jquery.d.tsという名前なので、dtsm install jqueryでファイルを同定することができます。

簡単な実装(ただし動かない時がある)

var spawn = require("child_process").spawn;

var cmd = spawn("peco");
var result = [];

cmd.stdout.on("data", function (data) {
    var str = data.toString();
    var newResult = str.split("\n").filter(function (str) { return !!str; });
    result = result.concat(newResult);
});
cmd.stdout.on("end", function () {
    console.log(result);
});
cmd.stdin.write("abc\ndef\nghi\n");

これでOKです。
pecoが存在している環境では、これで正しく動きます。

pecoが存在しない場合の対応

pecoが導入されていない環境では以下のようなエラーになります。

events.js:72
        throw er; // Unhandled 'error' event
              ^
Error: write EPIPE
    at errnoException (net.js:905:11)
    at Object.afterWrite (net.js:721:19)

厄介なのが、このエラーはtry-catchで復帰するのが難しい点です。
めんどくさいので深くは追っていませんが、on("error", ...)などでも捕まえることができません。

エラーの原因として、pecoが存在しないため、ENOENTが発生します(こちらはon("error", ...)でハンドリングできる)。
その状態でcmd.stdin.write(...);を実行すると、EPIPEが発生します。
これを上手くハンドリングする方法はありません。

単純に考えると、とりあえずpecoをspawnしてみてENOENTが発生したら処理を失敗させる、という流れが良さそうです。
しかし、spawnが成功したか、起動したプロセスの標準入力に書き込みができるか、プログラムから確かめる方法がないようなのです。
起動成功確認→標準入力にデータ書き込み ができなくて、とりあえずガッと書くしかない、という状態です。

これを防ぐには、ENOENTが発生しないように取り計らうしかないな!

というわけで、whichを使ってpecoが存在するか調べてから実行します。
whichのAPIはこんな感じで、こういう風に使うことができます。

実際の実装例

まとめ

存在しないコマンドを実行した後にリカバリするの大変だから存在するかしないか先にチェックしてから実行しろ。

5
5
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
5
5