anti scroll

ブラウザと小説の新しい関係を模索する

jingoo 1.4.0 をリリースしました

jingoo 1.4.0をリリースしました。

github.com

新しくなった点

  • Jg_templateモジュールを部分的に改良したJg_template2というモジュールが追加されました。

サンプル

これまでJg_templateモジュールは、次のようにmodels連想リストを与えていました。

open Jingoo
open Jg_types

let result = Jg_template.from_string "{{ msg }}" ~models:[
 ("msg", Tstr "hello, world!");
]

Jg_template2モジュールからは、models名前を与えたら値を返す関数を渡します。

open Jingoo
open Jg_types

let alist = [("msg", Tstr "hello, world!")]
let result = Jg_template2.from_string "{{ msg }}" ~models:(fun key ->
  try List.assoc key alist with Not_found -> Tnull
)

これの何が良いのかというと、string -> tvalueという型の関数にさえなっていれば、データソースは何でも良くなることです。

例えばデータソースを(連想配列より高速な)Hashtblにすることもできます。

open Jingoo
open Jg_types

let htbl = Hashtbl.create 1 in
let () = Hashtbl.add htbl "msg" (Tstr "hello, world!") in
let result = Jg_template2.from_string "{{ msg }}" ~models:(fun key ->
  try Hashtbl.find htbl key with Not_found -> Tnull
)

データソースなしで、単なる関数にしてしまうと、さらに高速です。

open Jingoo
open Jg_types

let result = Jg_template2.from_string "{{ msg }}" ~models:(function
 | "msg" -> Tstr "hello, world!"
 | _ -> Tnull
)

関数にすることで、乱数値みたいなものを扱うこともできます。

open Jingoo
open Jg_types

let result = Jg_template2.from_string "{{ msg }}, {{ rand }}" ~models:(function
 | "msg" -> Tstr "hello, world!"
 | "rand" -> Tint (Random.int 100) (* 0 ~ 100 の値をランダムに返す *)
 | _ -> Tnull
)

将来的にはこっちをメインのAPIとして使用したいのですが、旧版のAPIで既に広く使用されてしまっているので、今回はモジュールを別名で分けることで対応しました。

参考

In Jingoo.Jg_template, provide a function for the getting variables · Issue #112 · tategakibunko/jingoo · GitHub

jingoo v1.3.1をリリース

久しぶりになりますが、jingooのv1.3.1をリリースしました。

Release v1.3.1 · tategakibunko/jingoo · GitHub

変更点

  • 演算子として、新たに+=, -=,*=, /=,%= がサポートされました。
  • 匿名関数がサポートされました。
  • 条件分岐の構文にて、elseif だけではなく、else ifを使うこともできるようになりました。
  • macro ~ endmacro構文にて、endmacroの後に、macro名を付け足すことができるようになりました。

匿名関数はこんなふうに使います。

{# 2と表示される #}
{{ ((i) => i + 1)(1) }}

最後のmacro~endmacroについては、こんな風に使います。

{% macro li (content) %}<li>{{content}}</li>{% endmacro %}

{# v1.3.1からは、こういうふうにも書ける #}
{% macro li (content) %}<li>{{content}}</li>{% endmacro li %}

マクロの中身が長くなったときに「あれ、これってなんのマクロの宣言だっけ?」とかならないように、endmacroの部分で、メモ代わりみたいな感覚でマクロ名を付け足すこともできるようになった、ということです。

ただし次のように、宣言したマクロ名と違う名前を付け足すと、構文エラーになります。

{# エラー(マクロ名はliであって、fooではない) #}
{% macro li (content) %}<li>{{content}}</li>{% endmacro foo %}

jingoo v1.2.13 release

jingoo version 1.2.13 をリリースしました。

https://github.com/tategakibunko/jingoo/releases/tag/v1.2.13

前々から「UTF8モジュールのためにBatteriesは大きすぎる」という声が多かったので、それに応えてuutfというライブラリを採用したPull Requestを取り込みました。

https://github.com/dbuenzli/uutf

uutfはopamからじゃないとインストール出来ないのですが、事情があってopamを使えない人は、Makefileを付与したものを自分がforkしてるので、よかったら使って下さい。

https://github.com/tategakibunko/cmdliner

https://github.com/tategakibunko/uutf

ちなみにcmdlinerは、uutfの依存パッケージです。先にcmdlinerをインストールしてから、uutfをインストールして下さい。

どちらのパッケージも、srcディレクトリに入って、make; make installでいけますが、ポータビリティは考慮してないので、問題があるようならMakefileを編集して下さい。

jingoo v1.2.5 release

jingooのv1.2.5をリリースしました。

ひょんなことからjingoov1.2.4にバグ(割りとでかい)を見つけてしまい…緊急でリリースしました。

旧バージョンを使用中の方は、アップデートすることをおすすめします。

バグの詳細

具体的なバグは何かというと、オブジェクトをドットで展開する際に、対象が以下の様な入れ子のオブジェクトだったとき、evalが失敗して例外が投げられていたことです。

{{ user.image.filename }}

原因

原因はASTの評価処理で、ドットでプロパティにアクセスする評価式を、次のようなパターンマッチでのみ受け取っていたからでした。

| DotExpr(Ident(name), Ident(prop)) ->
  jg_obj_lookup_by_name env ctx name prop

オブジェクトのドット展開は左結合で、右にドットが2つ以上続く場合は左辺が再帰的にオブジェクトを返すはずですが、DotExprの評価式で左辺がIdentのみの評価しかしていなかったので、左辺がobjectを返すようなASTだったときにマッチするパターンがなく、SyntaxErrorがthrowされていたわけです。

今までこれに気づかなかったのは、単に入れ子のオブジェクトを扱っていなかったからなんですが、今回キャラクタ機能というのをリリースした際に、キャラクタオブジェクトの画像オブジェクト、という入れ子のオブジェクトを展開する必要があって、初めてバグに気づきました。

修正

対応自体は簡単で、パターンマッチのケースを一つ追加するだけで大丈夫でした。

| DotExpr(Ident(name), Ident(prop) ->
  jg_obj_lookup_by_name env ctx name prop

(** 左辺がオブジェクト *)
| DotExpr(left, Ident(prop)) ->
  jg_obj_lookup env ctx (eval_expr env ctx left) prop

おまけ

久しぶりのソースだったので「思い出せるかなあ」と憂鬱だったのですが、OCamlってコンパイラに型エラーで怒られているうちに、徐々に思い出すんですよね。

改めて型システムは偉大だなあ…などと思いました。

jingooの更新(white space controll用のシンタックス追加、およびスレッド版パッケージの分離)

ほぼjinja2互換なocaml template engineであるところのjingooなのですが、久しぶりにいくつかの修正を加えました。

  1. {%- と -%} のサポート(white space controll)
  2. マルチスレッドバージョンとノーマルバーションのパッケージを分離

1.{%- と -%}のサポート(white space controll)

{%-は、このマーク「以前」にある空白改行を削除し、-%} は、このマーク「以後」にある空白改行を削除するためのシンタックスです。

参考:http://jinja.pocoo.org/docs/templates/#whitespace-control

だから例えば

aaa
{% for i in [1,2,3] -%}
{{i}}
{% endfor -%}
bbb

とすれば、

aaa
1
2
3
bbb

と出力するし、

aaa
{%- for i in [1,2,3] -%}
{{i}}
{%- endfor -%}
bbb

とすれば、

aaa123bbb

と一切の改行空白が無い表示が出力されます。

これでまた一歩、jinja2に近づいたかな……

マルチスレッドバージョンとのパッケージ分離

次にマルチスレッド対応パッケージを分離したことについてですが、今まではスレッドを使わないプログラムでもコンパイル時に「-thread」というコマンドラインオプションを強要してました。

これがスレッドを使わないプログラムでjingooをリンクしたい人にとって不満だったらしく、これに対応した形です。

今後は「-thread」をつけなかったときはjingoo.cm[x]aがリンクされ、つけたときはjingoo.threads.cm[x]aがリンクされるようになります。