Chienomi

PureDocの自動since入れ

ヘッダに使用し、これまで手動で書いてきたsinceプロパティだが、本来であれば「書き始めた時」でなく「はじめて生成された時」であるべきだし、それは自動で行われるべきものだ。

そこで、実際にそのような機能を追加してみた。PureDocトランスレータ本体ではなく、トランスレーションユーティリティ(puredoc-translation)が処理する。

# Process META DATA # META DATA is start and end line beginning ##--. # Lines between them is proceed as YAML after strip beginning "# " . argv_first = ARGV[0] docstr = ARGF.read # Content begin if docstr =~ /^##--.*$/ && $' =~ /^##--.*$/ yax = $`.each_line.map {|i| i.sub(/^# /, "") }.join header_meta = YAML.load(yax) || Hash.new # Set since timestamp if a document generation is first time. (And update Last update time stamp.) if ! argv_first.empty? File.open(argv_first, "r+") do |f| content = f.read # Set since Time object if since is not set. if ! header_meta.key?("since") since = Time.now header_meta["since"] = since end content.sub!(/^##--.*?^##--.*?$/m) do el = $&.each_line.reject {|i| i =~ /^# last-update/ }.to_a # Get header texts but except last-update. el.insert(1, "# since : #{since.strftime '%Y-%m-%d %H:%M:%S %:z'}\n") if since # Add since if since is not exist. el.insert(1, "# last-update : #{File.mtime(argv_first).strftime '%Y-%m-%d %H:%M:%S %:z'}\n") # Add last update timestamp el.to_s end or next f.seek(0) f.truncate(0) f.write( content ) end end DOC.meta = header_meta end rescue DOC.meta = {} end

従来は単にヘッダーを読んでいたところだが、ヘッダーがある場合に限り別の処理をしている。

最初のARGVを保存しているのは、ARGFをよんでしまうとARGVが変化するため。もともとSTDOUTに吐くプログラムなので、処理するのは最初に引数として与えられたファイルに対してだけ、もしSTDINから入れた場合も触らない。

last-updateはmtimeに設定している。YAMLから作られるタイムスタンプスカラーがTimeなのかDateTimeなのか、実験してみたら、Timeだった。DateTimeにしてくれたほうがいいのに…

last-updateは更新するため、ヘッダー文字列を分解する時点で除外している。sinceプロパティが存在するかどうかについてはYAMLとして理解した上でやっているが、書き換え操作は純粋に文字列処理となっていて、別物だ。

ファイルの書き換えは、seek, truncate, writeの順が正しいらしい。まぁ、seekしてwriteしてからfile.truncate(file.pos)でも問題ないとは思うが。

ともかく、これで自動的にsinceとlast-updateが入るようになった。

Wrote on: 2014-11-11T00:00:00+09:00