ヘッダに使用し、これまで手動で書いてきた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が入るようになった。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA