CoffeeScriptはMakefileの様な機能を提供しています。
それがCakefileです。
Cakefileの文法はCoffeeScriptと全く同じなのでMakefileの様に新たな記述ルールを覚えないといけない、ということがないのでその分は楽です。
なお、基本的にWindowsユーザー向けに書いてあります。LinuxやMacユーザーはコマンドプロンプトを端末やターミナルに読み替えてください。
Cakefileを作って実行する
何はともあれ、Cakefileを作って使ってみるのが一番でしょう。
Cakefile作成手順
- 空のディレクトリを一つ用意しておきます。(別に空じゃなくても良いんだけどね)
- そこにCakefileという名前(拡張子はなし。.txtとかくっつけないように)のファイルを作り以下の内容を書き込みます
#Heloi Word!を出力
console.log "Heloi Word!"
はい、以上です。
実行手順
コマンドプロンプト上で、Cakefileを作ったディレクトリに移動し、以下をタイプするとCakefileを実行することが出来ます
cake
そうすると、Heloi Word!と表示されるはずです。
CakefileでHello World!も表示する
先ほどはHeloi Wordと文句たれてみましたが、Hello Worldとも言ってみたいですね。言ってみたいんです。
でも、一つのディレクトリにCakefileは一つしかおくことが出来ません。
そこで、Cakefileに複数の機能を持たせてみます。
taskの設定
その複数の機能はtaskという関数を使って登録することが出来ます。
以下の様な関数です
task コマンド文字列,説明文,呼ばれたときに実行する関数
なんだかんだと説明するより、実際にどうなるのか見た方が早い。
以下の様にCakefileを保存します。
task 'word','ワードへの文句',(options)->
console.log "Heloi Word"
さて、先ほどと同じようにcakeと打って実行してみます。
すると、このようになります。
>cake今使えるタスクとその説明が表示されたのです。
word #ワードへの文句
では、wordタスクを実行してみましょう。cakeコマンドの後にスペースを入れてタスク名を入力することで実行できます。
>cake word
Heloi Word
ちゃんとHeloi Wordと表示されました。
さて、最初の目的、一つのCakefileでHello Worldと表示するCakefileを作ってみましょう。
#↓単に面倒くさかっただけです
log = console.logtask 'word','ワードへの文句',(options)->
log "Heloi Word"
task 'hello','世界の決まり文句',(options)->
log "Hello World!"
タスクから別のタスクを実行する
「invoke」関数を用いると、あるタスクから、別のタスクを起動することができます。
log = console.logtask 'main','メインです',(options)->
log "main"task 'test','mainを呼び出してから、testと書き出します',(options)->
#mainタスクを実行します
invoke "main"
log "test"
testタスクを実行してみるとこうなります
>cake test
main
test
タスクにオプションを付ける
先ほどまでの例にでは、タスクで実行する関数に全てoptionsという引数を定義しておきました。そう、タスクには実行時にオプションを渡すことができるんです。
オプションを渡す為に、最初にどのようなオプションを渡すことができるのかを定義しておく必要があります。そのための関数が「option」関数です。
option "省略オプション名","長いオプション名 [引数名]","説明"
まぁ、物は試しです。実際の例で見てみましょう。
log = console.log#option関数で使える物を定義します
option "-o","--OPTION","引数なしオプションです"
option "-v","--value [V]","引数を持つオプションです"task "test","test",(options)->
if options.OPTION? then log "--OPTION #{options.OPTION}"
else log "No --OPTION"
if options.value? then log "--value #{options.value}"
else log "No --value"
実行例です。
>cake -o -v nodamushi test --OPTION true --value nodamushi
上の例のように、「cake オプション タスク名」の順で起動します。なお、存在しないオプションを渡すとエラーになります。
「--value [V]」という風に[V]によって引数があることを定義していますが、この文字列は[]でくくっていれば何でも良いようで、[DIR]だろうと[T]だろうとそれによる変化は特にないようです。
タスク内でオプションの値を参照するときは、「options.OPTION」や「options.value」などの様に、長い名前で定義したオプション名でアクセスできます。
「invoke」関数で別タスクを呼び出した場合も、同じオプションを受け取ることができます。
requireについて
さて、次にcoffeeスクリプトのコンパイルをしてみようと思いますが、どうやってコンパイルしたらいいのでしょうか?外部プロセスとしてcoffeeコマンドを実行できればいいのですが、CoffeeScriptにはそんな機能はありません。
そこで、node.jsのモジュールを用います。
いままで目をつむってきましたが、console.logはnode.jsの機能で、node.jsのconsoleモジュールのlog関数を使ったのです。
コマンドを実行するために必要なモジュールは「child_process」にあります。consoleモジュールは最初から読み込まれているので、いつでも使うことができますが、このモジュールは標準で読み込まれていないので、スクリプト内部から読み込む必要があります。
そのための関数が「require」です。使い方は「require "読み込むモジュール名"」で、連想配列が返ってきます。
child_process以外にも、ファイル入出力をするための「fs」などいろいろあります。
私はnode.jsに明るくないのでどのようなモジュールがどんなときに使えるのか答えることはできません。以下のサイトを参考にすると良いでしょう。
Node.js Manual & Documentation
コンパイルをしてみよう。
コンパイルをするためにchild_processモジュールのコマンド実行関数execを利用して、coffeeコマンドを実行します。
{exec} = require 'child_process'
#{exec}は分割代入を使っています
#exec = (require 'child_process').exec と同等です
#コンパイルするファイル群
files=[
'test.coffee'
'test2.coffee'
]#第二引数の関数は実行が終わった後に呼び出されます。
exec "coffee -cj #{files.join ' '}",(err,stdout,stderr)->
#エラーや出力結果を出して終わる。
throw err if err
console.log stdout+stderr
コンパイルをしてみよう(別解)
coffee-scriptモジュールのcompileを利用してコンパイルすることも可能です
{compile} = require "coffee-script"
fs = require "fs"read = fs.readFileSync "test.coffee"
jssrc = compile read.toString(),{bare:true}
fs.writeFileSync "output.js",jssrc,"utf-8"
なお、一行目でエラーが出る場合はNODE_PATHの設定をしてください。Windows7の場合、「C:\Users\ユーザー名\AppData\Roaming\npm\node_modules」です。
以上で基本的なCakefileの説明は終わりです。
後はモジュールの組み合わせと、あなたの発想で便利なCakefileを手早く作ってください。