D言語で使えるテンプレートエンジン


[D言語 Advent Calendar 2012](http://qiita.com/advent-calendar/2012/d)の7日目の記事です．自分で実装しておきながら日本語で紹介した記憶もないので，これを気に現状のテンプレートエンジン周りについて書いておきます．

D言語は言語機能としてevalなどを現状提供していないのもあり，テンプレートエンジン界隈は盛んではありません．なので数が少ないです．
今の所存在しているアプローチは以下の4つです

- logic-lessで値を埋め込むやつ (mustache-d)
- D言語のコードにしてしまう (diet, 新jade)
- dmdscriptなど外部の処理系を呼び出す (旧jade)
- 手で頑張る (web.dなど．そもそもテンプレートエンジンではないが…)

上から見ていきます．

## [mustache-d](https://github.com/repeatedly/mustache-d)

俺が書いてるやつです．[mustache](http://mustache.github.com/)はD言語特有のものではなくて，有名なテンプレートフォーマットです．サイトにもたくさんの言語での実装が載っています．

### 使い方

READMEにも載ってますが

- Variables: 値の埋め込み
- Sections: リストの列挙や分岐
- Partials: 別ファイルの読み込み
- Comments: コメント

が使えます．細かく見ると色々書くことが増えるので，必要そうなのを見ていきます．以下のは例として同梱しているbasic.mustacheです:

```mustache
Hello {{name}}
You have just won ${{value}}!
{{#in_ca}}
Well, ${{taxed_value}}, after taxes.
{{/in_ca}}
```

```{{name}}```が値の埋め込みで，nameというキーに対応する値が埋め込まれます．```{{#in_ca}}```がセクションの中の一つ条件分岐で，_in_ca_ に値があれば```{{/in_ca}}```までが処理されます．

これに対応するD言語のコードは以下になります．Contextという連想配列っぽいものに値をセットしてレンダリングします:

```d
// string/dstringに対応しているので，自分の使いたい型を指定する．wstringはちょっとPhobosがバギーなので今は未サポート
alias MustacheEngine!(string) Mustache;

Mustache mustache;
auto context = new Mustache.Context; // これに値を入れる

context["name"] = "Chris";
context["value"] = 10000;
context["taxed_value"] = 10000 - (10000 * 0.4);
context.useSection("in_ca"); // useSectionを使うことで条件分岐をする

mustache.render("basic", context)); // renderString("Hello {{name}}", context)とかも出来ます
```

セクションというのがmustacheでの肝になっていて，キーに対応する値のタイプによって，リストの列挙，条件分岐，コールバック呼び出し，をそれぞれ行います．

例えば，他に同梱しているprojects.mustacheの例では，リストの列挙は以下のようになってます.

```mustache
{{#projects}}
  <a href="{{url}}" class="block">
    <h2> {{name}} </h2>
    <p> {{description}} </p>
  </a>
{{/projects}}
```

```d
Mustache mustache;
auto context = new Mustache.Context;

foreach (ref project; projects) {
    auto sub = context.addSubContext("projects"); // リストを列挙するには新たにコンテキストを追加する
    sub["name"]        = project.name;
    sub["url"]         = project.url;
    sub["description"] = project.description;
}
```

mustache-dでは基本機能は一通り実装してあるので，もう少し知りたい方はDDocやunittestを参照してみてください(Webに上げないと…)．フォーマットに関してはmustache本家にドキュメントがあります．

1ファイルでｻｸｯと使えるからか，メールのテンプレート作成など，ちょくちょくユーザがいるようです.

## [diet](http://vibed.org/templates/diet)

[vibe.d](http://vibed.org/)が提供している[jade](http://jade-lang.com/)シンタックスを持つテンプレートエンジンです．他のvibe.dのモジュールに依存しているので，mustacheのように単独で使える状態にはなってません．

dietの特徴は，アプリケーションのコンパイル時に，テンプレートファイルも一緒にコンパイルして，D言語のコードに変換してしまう所です．そのため，実際にレンダリングする時にパースなどの処理が発生せず，またD言語のコードになっているので，mustacheのContextのような中間オブジェクトが必要になりません．

### 例

良い例が見つからなかったので，vibe.dのサンプルの中のエラー出力のを引用します．

以下は[error.dt](https://github.com/rejectedsoftware/vibe.d/blob/master/examples/app_skeleton/views/error.dt)の内容になります:

```diet
extends layout

block title
        - auto title = "HTTP error " ~ to!string(error.code);

block body
        p An error has occured. We are really sorry about that!
        p Error description: #{error.message}
```

これに対する[D言語のコード](https://github.com/rejectedsoftware/vibe.d/blob/master/examples/app_skeleton/source/app.d#L7)は以下のようになります．render自体はHTTPサーバ側にあるコードで，実質はdietのコードではないんですが，中ではdietのparseDietFile呼んでいるだけです．

```d
void showError(HttpServerRequest req, HttpServerResponse res, HttpServerErrorInfo error)
{
        res.render!("error.dt", req, error);
}
```

この例を見ると分かるのは，```auto title```や```to!string(error.code)```のようにD言語のコードがjadeのコードブロックに直接掛けるのと，renderのテンプレート引数に使われているerrorという変数を，直接テンプレートファイルの中で使えるという所です(templateのaliasパラメータは強力ですね)．

基本dietはこんな感じです．mustacheと違ってそもそもD言語のコードが掛けるので，jadeの構文を覚えてしまえば，後はかなり自由に書けるようになってます．実際，_static if_ で分岐している例や，foreachを使っている例も普通にあります．
正直dietだけを別途公開して欲しい所です…

## その他

使ったことないやつです．

### [jade](https://github.com/sleets/oak/tree/master/src/oak/langs/jade)

これは名前の通り，dietと同じ[jade](http://jade-lang.com/)のD言語実装ですが，これもoakという謎ライブラリに依存してます．
最初google codeで公開されてたやつはdmdscriptかV8が必要で，今のgithubのもpcreが必要だったりと面倒なので試してないです．後なんかdmdへのパッチみたいなのも同梱しているので，ちょっと大がかりかなと．
dietがあるので，今では正直立ち位置がよく分からんという感じです．

### [serenity](https://github.com/mrmonday/serenity)

これ自身はWebフレームワークなんですが，ビューの所にHTMLを出力するクラスみたいなのがあります．DOMベースで，マニュアルでHTMLを生成する感じなので，テンプレートエンジンとは少し違いますね…

### [misc-stuff-including-D-programming-language-web-stuff](https://github.com/adamdruppe/misc-stuff-including-D-programming-language-web-stuff)

Adamがたくさん公開しているWeb向けモジュール群です．serenityと似たような感じでDOMベースで書いたり，html.dでJSとかCSS辺りも操作出来ますが，これもテンプレートエンジンではないですね…
Adamのサイトはここにあるweb.dとかを使って構築されているらしいですが，使いやすさはよく分からんです．

## まとめ

現状俺の知る限り，単独のテンプレートエンジンはmustache-dのみで，他のは何かしらのフレームワークに依存しています．
個人的には本当に必要になった場合には仮想マシンベースのテンプレートエンジンを書きたいと思ってるんですが，まぁ現状mustache-dで困ってないので当分先になりそうです．

次，8日目はまた[@ueshita](http://qiita.com/users/ueshita)さんです！