Luaの文法がまだ覚えきれていないのでまずはそっちを固めるべき
ひとまず、公式のマニュアルを読んだ。
例はココにあるらしいが、まだ読んでいない。
また、通常のフィルターも少しだけ目を通したが、フィルタの実行環境を持っていない人にどうやって環境を渡すのかを考えるのが面倒なので、Pandoc2.0から本体に組み込まれ、そして他の言語よりも動作が速いと書かれていたLuaのフィルターを使うこととした。
最近Luaの勉強をしていたのはそのためである ^[もうひとつ、FlashAirのためでもあるのだが]
マニュアルに書かれていないことが多くないですかね…。
とりあえずマニュアル読んだだけだと非常に簡単なものしか作れない。ちょっと習作ということで、強調を斜体に変更し、間にあるスペースを削除して詰めるフィルタを書いた。結果としてそうなったというだけで、はじめからそうしたかったわけではないのだが。
function Strong(elem) t = "" for k, v in pairs(elem.content) do if v.tag == "Str" then t = t .. v.text end end return {pandoc.Emph(t)} end
これで、**HU HU HU HU**
と書いたものが*HUHUHUHU*
と等価な出力となった。
この変換前の一文は
"C:/Program Files/RStudio/bin/pandoc/pandoc" -f markdown hoge.md -t native
のようにnative形式で出力すると
Para [Strong [Str "HU",Space,Str "HU",Space,Str "HU",Space,Str "HU"]]
に対応する。ここで、elem.contentはこの[Str "HU",Space,Str "HU",Space,Str "HU",Space,Str "HU"]
を受け取ることになる。
さて、コードについて。function Strong(elem)
でStrongが見つかったらこの関数をcallするような挙動 ^[実装がそうなっているのかは確認していない。]となる。ここでelemを引数に入れないとどうなるんだろ?あとでやってみる。
for文で各要素を見ていく。ここでkは要素のindex、vが実体になるようだ。この場合、ipairsの方が良いのかもしれない。あとでやってみる。
Spaceはtextを要素に持っていないのでnilが返る。nilと文字列は結合できないので先にvのtagがStrであることを確認している。もっと良い実装があるだろうけど。
t = "" for k, v in pairs(elem.content) do if v.tag == "Str" then t = t .. v.text end end
で、テキストを結合している。最初に空の文字列を与えないとこれまたnilとの結合になるので注意。Luaはundefinedは全部nilだ。
最後はtableにして返さないとダメっぽいが、ここは理由がちょっとよくわからない。他の例では大丈夫だったはずなのに。
return {pandoc.Emph(t)}
ということで、はじめてのLuaフィルタの完成なのでした。
Word出力にする際にちょっとあれこれいじりたいところがあるので、Luaのfilterを使って何とかしたかったのですが、これならすぐできるかもしれないね。
Enjoy!!