2019/10/10

Nimの黒魔術

Source Code Filters

最近知った機能なのですが、NimにはSource Code Filters(SCF)なるものがあります。名前がSCP(詳しくはウィキペディア等で調べて見て下さい。何やらゲームにもなっているようですが、おじさんはゲームしないので、詳しくはわかりません)に似ているあたりが、何やら謎めいた不気味な雰囲気を醸し出しています。いったいどのようなものなのか。まずは簡単なものをご紹介します。

まず最初にhtml.nimfというファイルを作成します。

#? stdtmpl | standard
#proc generateHtmlHead(lang, charset: string): string =
#  result = ""
<!DOCTYPE HTML>
  < html lang="$lang">
    <head>
      <meta charset="$charset">
    </head>
このような内容の.nimfという拡張子のファイルを作成します。
そして、test.nimという普通のnimファイルを作成し、以下のようにします。

include "html.nimf"

block:
  var
    f: File = open("test.html", FileMode.fmWrite)
    html = generateHtmlHead("ja", "utf-8")
  defer:
    close(f)
  f.writeLine(html)

そしてnim c test.nimとし、./testとすると、以下のようなHTMLファイルが作成されます。

<!DOCTYPE HTML>
  < html lang="$lang">
    <head>
      <meta charset="$charset">
    </head>

何ということでしょう。
NimはPythonで言うならば、jinja2的なものを同梱しているのでした。
ちなみに上記のHTMLコードのlang属性は、Googleの検索エンジンでは無視されるものらしいので、使う必要がないそうです。検索にも影響がないらしい。
.nimfファイル内では行頭に#を付けた部分をNimのコードとして認識するようです。つまり、#が付いていればifなども使うことが可能。
説明によると、「SCFは解析する前に入力文字ストリームをメモリ内出力ストリームに変換」とある。
わからない……
まさに黒魔術……
しかしながら、この機能を信じて使うならば、jinja2のようなテンプレートエンジンとして使うことが可能ではないかと思います。
試しに簡易な静的サイトジェネレータを作成してみて、このSCFを使ってみようとしたところ、ちょっと上手くいかなかったので、まだ完全に使い方を理解できていません。

簡易な静的サイトジェネレータ

その名は「tinbe」。ご存知の方もいらっしゃるかとは思いますが、Nimの名前の起源はどこぞの王様らしいので(確認済)、最初は海外風のそういった感じの名前にしようかと考えていたのですが、おそらく私のプログラミング技術アンド能力では名前負けすること間違いないので、候補から外しました。しかし、何かしらそういった雰囲気と戦いが絡んでいそうで、かつ静的サイトにふさわしいネーミングをと色々調べておりましたら、琉球空手にティンベーという亀の甲羅で作られた盾があるじゃないですか。琉球空手にはティンベー・ローチンという盾と槍を使った戦い方があるようです。これはピッタリ・シックリきましたので、ロゴも作成して早速作成にはいりました。私だけかもしれませんが、ロゴを作成すると「やっぱやめた」となりにくい。
現在tinbeは、./tinbe startコマンドで、以下のようなディレクトリを生成します。

project
|-- config.json
|-- docs/
     |-- index.html
     |-- style/
           |-- style.css
本当はtomlやyamlファイルあたりで、設定ファイルを作成したいと考えていましたが、とりあえずは標準ライブラリのみでできるものにしました。Nimは標準でjsonを扱えるライブラリを持っているので、そちらを使います。
とりあえずSCFの使い方が分かるまでは、strformatを使って、文字列に値を埋め込んでいくというやり方で、HTMLファイルは作成しています。
tinbeはまだまだ開発初期段階ですが、勉強にもなるので、のんびり開発していこうと思います。

追記(2019/10/16)

自作静的サイトジェネレータtinbeにSCFを導入してみました。今のところ問題なくHTMLファイルを作成できております。