Capにblock, inject, extends文を実装した
目次
Capに新機能を追加した
Capというシェル型のスニペットマネージャーを作っています。
このCapにはテンプレート言語が実装されています。
今回はこのテンプレート言語の新機能3つを紹介したいと思います。
新機能3つ↓
- extendsキーワード
- block文
- inject文
extendsキーワード
extends
キーワードは関数と一緒に使います。
これは関数に他の関数を継承させるキーワードです。
たとえばf1
という関数があって、f2
という関数にf1
を継承させたい場合は下のようにします。
{@ def f1(): end def f2() extends f1: end @}
これで関数f2
は関数f1
を継承できました。
関数f2
から親の関数、つまりf1
を呼びたいときはsuper
を使います。
{@ def f2() extends f1: super() end @}
これらの機能はこれから紹介するblock
文とinject
文で必要な機能です。
block文
関数内の処理は「ブロック」という単位で区切ることが出来ます。
ブロックを区切るにはblock
文を使います。
{@ def f1(): block contents: end end @}
↑の場合、contents
という識別子のブロックが関数内に作成されます。
このブロックは複数作ることが出来ます。
{@ def f1(): block header: end block contents: end block footer: end end @}
ブロックは、関数をテンプレートとして使いたい時に、その構成を記述するのに使われます。
↑の場合はheader
, contents
, footer
という3つのブロックを作っているので、ここに外から別の処理を流し込むことが出来るようになります。
別の処理を流し込むにはinject
文を使います。
inject文
inject
文はblock
文で区切られたブロック内に、別の処理を注入するのに使われます。
例えば↓のような関数f1
があったとして、
{@ def f1(): block contents: puts(1) end end @}
関数f1
内のブロックcontents
に別の処理を流し込みたい場合は、まず関数f1
を継承した関数を定義します。
{@ def f2() extends f1: end @}
それからinject
文で親のcontents
ブロックに別の処理を注入します。
{@ def f2() extends f1: inject contents: puts(2) end end @}
これで関数f2
から関数f1
のcontents
ブロックに、puts(2)
という処理を注入できました。
あとはf2
内でsuper
を呼びます。
{@ def f2() extends f1: inject contents: puts(2) end super() end @}
これで関数f2
から関数f1
が実行されます。
あとはスコープの一番外で関数f2
を呼び出します。
{@ f2() @}
これの出力結果は「2
」になります。
これらの機能の使いみち
フレームワークやテンプレート言語を使っている人はピンと来たと思いますが、これらはテンプレート言語の基本的な機能と言えます。
たとえばベースとなるHTMLを作っておき、そのHTMLの部分的なブロックに別のHTMLを注入したいときなどに、これらの新機能は使うことが出来ます。
例えば↓のようにです。
{@ def base(): puts("header") block contents: end puts("footer") end def index() extends base: inject contents: puts("contents") end super() end index() @}
イメージとしては雛形に外部から鉛(HTML)を流し込み、新しい部品を作るという感じですね。
実装期間としては4日ぐらいでだいたい実装できました。思ったより時間がかかりました。
おわりに
CapはMITライセンスで公開されているので良かったら使ってみてください(^^)
姉妹ブログを見に行く。