スクリプト更新

  • -gオプションでグループ名指定。howm側では{hw:g=グループ名}みたいな感じでグループ名設定。-gオプションが指定されると対応するグループ名の記事のみ取得します。
  • 1ファイル複数タイトルに対応。


こんなふうに書けます。

 = {hw:g=hoge} テスト1

%%%
*test1

 = {hw} テスト2

%%%
*test2

 = {hw:2006-06-22,g=fuga} テスト3

%%%
*test3


以下スクリプト。なんか長い…

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

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.2"
  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] : ""

# ファイルの再帰探索
IGNORE_DIR = %w(. ..)
def scan_files (path, &block)
  if FileTest.directory?(path)
    Dir.foreach(path) do |file|
      next if IGNORE_DIR.include? file
      scan_files("#{path}/#{file}", &block)
    end
  else
    block.call(path)
  end
end

IN_NOOP = :IN_NOOP
IN_BODY = :IN_BODY
IN_DIARY = :IN_DIARY

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

  status = IN_NOOP
  howm_content = Hash.new("")

  date = ""
  File.foreach(path) do |line|    
    case status
    when IN_NOOP
      if line =~ /^= .*\{hw(:(.*))?(?=\})/
        date = def_date
        group = ""
        if !$2.nil? 
          $2.split(',').each do |str|
            str.strip!
            if str =~ /(\d{4}-\d{2}-\d{2})/
              date = $1
            elsif str =~ /g=(.*)/
              group = $1.strip
              puts group
            end
          end
        end
        status = IN_BODY if ARG_GROUP == group
      end

    when IN_BODY
      if line =~ /^=( |$)/
        status = IN_NOOP
        redo
      end

      if line =~ /^%%%/
        status = IN_DIARY
        next
      end

    when IN_DIARY
      if line =~ /^=( |$)/
        status = IN_NOOP
        redo
      end
      howm_content[date] += line
    end
  end

  return howm_content
end

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

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

  # howm形式のファイル名か
  next unless /(\d{4}-\d{2}-\d{2}).*\.howm$/ =~ path
  def_date = $1

  filename = File.basename(path)  

  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