hw-howm.rb 0.0.4

前回上げたやつバグってました。すみません。
バグ修正したやつ上げときます。


機能的にはこれでほぼ完成。あとはバグ潰しとリファクタくらいかな。


以下スクリプト

#!/usr/bin/ruby -w
#
# hw-howm.rb -- howmメモをhw.plで扱える形式にする.
#
require "optparse"
require "fileutils"
require "find"

begin
  opt = OptionParser.new
  OPTS = {}
  opt.banner= "usage: #$0 [options] src_dir target_dir"
  opt.on_tail("-h", "--help", "show this message") {puts opt; exit 0}
  opt.on("-t", "--timestamp=FILE", "use FILE as timestamp(default: none)") {|v| OPTS[:t] = v} # touch file path
  opt.on("-g", "--group=GROUP", "assume group name"){|v| OPTS[:g] = v}
  opt.version = "0.0.4"
  opt.release = nil
  opt.parse!(ARGV)
rescue OptionParser::InvalidOption, OptionParser::MissingArgument
  puts $!
  puts opt
  exit 1
end

srcdir = ARGV[0]
updir = ARGV[1]

if !srcdir or !updir
  puts opt
  exit 1
end

[srcdir, updir].each do |dir|
  unless FileTest.directory? dir
    puts "invalid directory: #{dir}"
    puts opt
    exit 1
  end
end

touch_file = ""
if OPTS.key?(:t) && FileTest.file?(OPTS[:t])
  touch_file = OPTS[:t]
end
TOUCH_MTIME = (touch_file == "") ? Time.at(0) : File.mtime(touch_file)

ARG_GROUP = OPTS.key?(:g) ? OPTS[:g] : ""

# howmファイルの読み込み
def readhowm (path, def_date)

  howm_content = Hash.new("")
  date = ""
  File.open(path, "r") do |io|
    break if io.eof? 
    io.readlines.join('').scan(/^= [^\n]*\{hw(?:\:([^\n\}]*))?\}(?:(?!\n).)*\n(?:(?!^\=[ \n]|^%%%).)*\n%%%(?:(?!\n).)*\n((?:(?!(?:^\=[ \n])).)*)/m) do |(options, body)|
      (howm_content[date] = ""; next) if body == ""
      date = def_date
      group = ""
      if !options.nil? 
        options.split(',').each do |opt|
          opt.strip!
          if opt =~ /(\d{4}-\d{2}-\d{2})/
            date = $1
          elsif opt =~ /g=(.*)/
            group = $1.strip
          end
        end
      end

      body += "\n" if body[-1] != ?\n
      howm_content[date] = body
    end
  end

  return howm_content
end

# メインの処理
Find.find(srcdir) do |path|
  next unless FileTest.readable?(path)

  # touchファイルより新しいか
  next if TOUCH_MTIME > File.mtime(path)

  # *.howmファイルのみ対象
  next unless /\.howm$/ =~ path

  filename = File.basename(path)  

  # ファイル名の先頭がYYYY-MM-DDならその日付を日記日付のデフォルトとして使用
  if /^(\d{4}-\d{2}-\d{2}).*\.howm$/ =~ filename
    def_date = $1
  else
    def_date = File.mtime(path).strftime("%Y-%m-%d")
  end

  # howmファイルの内容をハッシュに読みこみ
  howm_content = readhowm(path, def_date)

  howm_content.keys.each do |date|
    # はてダラファイル記事格納用ハッシュ
    hatena_content = Hash.new("")

    # はてダラファイルの先頭部分はhatena_content["0"]に格納
    key = "0"
    # はてダラファイルの内容をハッシュに格納
    uppath = "#{updir}/#{date}.txt"
    if FileTest.file?(uppath)
      File.foreach(uppath) do |line|
        if /^><!--(\d{4}-\d{2}-\d{2}.*\.howm)--><$/ =~ line
          key = $1
          next
        end
        hatena_content[key] += line
      end
    elsif FileTest.exist?(uppath)
      puts "#{uppath} is not file."
      next
    end

    # はてダラファイルがなかったとき
    # とりあえずファイルの先頭は空行にしておく
    hatena_content["0"] = "\n" unless hatena_content.key?("0")

    if !hatena_content.key?(filename) or hatena_content[filename] != howm_content[date]
      hatena_content[filename] = howm_content[date]
      # はてダラファイルへ書き込み
      File.open(uppath, "w+") do |io|
        io << hatena_content["0"]
        hatena_content.keys.sort.each do |key|
          if key != "0" && hatena_content[key] != ""
            io << "><!--#{key}--><\n"
            io << hatena_content[key]
          end
        end
      end
    end
  end

end

# touch
if OPTS.key?(:t)
    FileUtils.touch(OPTS[:t])
end

exit 0

howmファイルを正規表現でいっきに処理するようにした。コードは短くなったけど正規表現みにくいなぁ…
あとhowmファイルの検索にFindモジュールを使うようにした。