2015年5月18日

.bstはクソで,TeX言語も()なので,俺言語でやってみたって話.いや.言語はLuaなんですが,俺俺式フォーマットでも書けるという話.ともかく成果物.ところでLuaがPrism.jsでハイライトされません.

使い方はbibtexをtexlua luabibtex.luaに変更すればできるはず.kpathseaもきちんと見ます.スタイルはplain_bst.luaみたいな形.とりあえずplainとamsalphaのarticleとbookだけ書いて力尽きました.(.bst読むのがつらい.)スタイルの書き方の基本形は

-- (ここで前準備をする)
BibTeX:outputline("\\begin{thebibliography}{" .. #BibTeX.cites .. "}")
-- (ここで文献一覧の出力をする)
BibTeX:outputline("\\end{thebibliography}")
となる.このBibTeXはグローバルに定義された変数で,現在の状態を格納している.BibTeX:outputlineは.bblに直接出力する命令.前準備は一覧の並び替えくらいでしょうか.(あまりなさそうだけど)タイトルで並び替えるならばこんな感じ.

table.sort(BibTeX.cites,
    function(a,b)
        at = a.fields["title"]
        if at == nil then at = "" end
        bt = b.fields["title"]
        if bt == nil then bt = "" end
        return at < bt
    end
)

BibTeX.citesが引用されている文献一覧が配列で入っている.まぁ大体上でアクセス方法は明らかですかね.文献一覧出力はさっきのBibTeX:outputlineでもでもできるけど,こういう感じでもできるようにしてみた.

LuaBibTeX.Template.blockseparator[1] = ".\n\\newblock "
LuaBibTeX.Template.blocklast[1] = "."

styles = {}
styles["article"] = "[$<author>:<{\\em |$<title>|}>]"
funcs = {}
function funcs.author(cite)
    s = cite.fields["author"]
    if s == nil then return "" end
    a = LuaBibTeX.split_names(s)
    for i = 1,#a do
        a[i] = LuaBibTeX.format_name(a[i],"{ff~}{vv~}{ll}{, jj}")
    end
    r = a[1]
    for i = 2,#a do
        r = r .. ", " .. a[i]
    end
    return r
end

table.sort(BibTeX.cites,
    function(a,b)
        at = a.fields["title"]
        if at == nil then at = "" end
        bt = b.fields["title"]
        if bt == nil then bt = "" end
        return at < bt
    end
)

BibTeX:outputline("\\begin{thebibliography}{" .. #BibTeX.cites .. "}")
f = LuaBibTeX.Template.Make(styles,funcs)
BibTeX:outputcites(f)
BibTeX:outputline("\\end{thebibliography}")

LuaBibTeX.Template.Makeで出力を整形する関数群を作り,BibTeX:outputcitesで処理する.LuaBibTeX.Template.Makeは引数を二つとり,一つ目がスタイルの指定を文字列で行い,二つ目が必要ならば呼び出される関数群を指定する.この第一引数は次の構文が使える(ここが俺俺).ネストできそうなのはネスト可能.

  • [A:B:C:...]は「ブロック」(ととりあえず呼ぶことにした)を表す.基本的にはA<sep>B<sep>C<sep>...<last>と出力される.sepはLuaBibTeX.Template.blockseparator[nestlevel]で,lastはLuaBibTeX.Template.blocklast[nestlevel]で指定できる.A,B,Cはもし空になれば無視される.(例えばBが空ならばA<sep>C<sep>...となる.)もし<sep>や<last>がピリオドから始まり,Aなどがピリオドで終わった場合,ピリオドが一つ除去される.
  • <A|B|C>は,まずBを調べ,それが空でなければABCを,そうでなければ空に変化する.
  • $<A|B|C...>は関数呼び出しを表す.まずfuncs.Aを呼び出し,戻り値が空(またはnil)ならばfuncs.Bを呼び出し……と続け,最初に空でなかったものを出力する.もしfuncs.Aがなかったらば,Aというフィールドとして扱われる.
  • エスケープは%を頭につける.

二つ目と三つ目がほぼ同じ構文なのは深い理由があるわけじゃなくて,どちらかというと記号がないという理由だったり.{}や()は使いたくないので,もう余っている括弧がない.あまり関数を書きたくないので(面倒だし)ある程度の表現力を持たせたいのだけど,何があればいいかよくわからないなぁ.とりあえず既存.bstを書き直してみるか.なんだかまだまだ色々やっていません.例えばこんなん.

  • crossrefは無視される(実装していない).
  • @article(key,author="author")だと読めない.@article{}なら大丈夫.@commentも@stringも動かない..bibの仕様がよくわからないので,適当実装です.
  • format_nameの空白挿入(" "か"~"か)がよくわかっていません.色々試してみます.
  • 日本語を全く考慮していません.UTF-8なら大丈夫だと思うけど…….
  • エラー処理がゼロです.ミスると多分Lua自身が謎のメッセージを出します.

0 件のコメント:

コメントを投稿

コメントの追加にはサードパーティーCookieの許可が必要です