2015-11-08

OS X の JavaScript for Automation で、外部ライブラリを読み込む

OS X Yosemite 以降オートメーションのスクリプトをApple Script ではなくてJavaScript でも書けるようになった JavaScript for Automation または JXA と呼ぶらしい

単純な自動化だとシェルスクリプトなり Python なりで書けばいいんだけどアプリケーションと通信するときにはオートメーションを使えると便利だたとえばカレンダーアプリや iTunes の API にアクセスするようなとき

今回、JXA で日付文字列のパースやフォーマットがしたくなった。Node.js なんかだと、moment.js なるライブラリがある。

JXA で外部ライブラリを取り込むには、いくつかやりかたがあるらしいけれど、browserify を使うことにした。

手順


まず、browserify と、取り込むライブラリをインストールする。

npm install -g browserify
npm install moment

moment.js を使うコードを書く

// main.js
var moment = require("moment");
console.log(moment().format('MMMM Do YYYY, h:mm:ss a'));
browserify を使って出力したコードを、JXA 環境で実行する。

$ (echo 'window = this;'; browserify main.js; echo ';ObjC.import("stdlib");$.exit(0)') | osascript -l JavaScript
2015-11-08T16:26:55+09:00

実行コードをファイル保存


エラーが出たりすると、どの行だよ!ってなるので、browserify の出力をファイルにする。Makefile で。cake や gulp じゃなくてすみません。

bundle.js: *.js
    (echo 'window = this;'; browserify main.js; echo ';ObjC.import("stdlib");$$.exit(0)') > bundle.js

run: bundle.js
    osascript -l JavaScript bundle.js

JXA 環境特有の調整


Node.js と JXA との環境の違いを吸収するため、 browserify の出力前後に、数行追加してある。

JXA には window がない。ただし、this でグローバルなオブジェクトにアクセスできる。window = this することで、window オブジェクトが使える風にする。今回のスクリプトでは不要。

browserify で生成した関数を実行すると最後に評価された式の値がプリントされる結果を標準出力に出してパイプでつなぐような用途だと困る

ObjC.import("stdlib");
で、なんかライブラリを読み込む。らしい。ObjC.foo または $.foo で、読み込んだ関数にアクセスできる。というわけで、
$.exit(0);
して、何も表示させずに終了している。