> もっと良いものがあるかもしれないと考え,実例集に載せられるよ
> うなrubyスクリプトを募集します.

自分しか使えないようなスクリプトを書き散らしているだけなので、
ネタがなくて困っていたのですが、mailing-listに参加していて応
募しないのも残念なので、とりあえず。

EmacsのM-x diaryで使うスケジュールファイルを日付順にソートす
るスクリプトです。diaryに書けるすべてのスタイルに対応してい
るわけではなく、私が使っているスタイルしかサポートしていませ
ん(このあたりがいい加減。万が一ご要望があれば対応します)。

標準入力から読んで標準出力に書くのですが、.emacsで次のような
設定をして使うことを想定しています。

(global-set-key "\C-zc"
                (function
                 (lambda ()
                   (interactive)
                   (widen)
                   (shell-command-on-region
                    (point-min) (point-max) "sort-schedule.rb" t t))))

---------- ここから ----------
#!/usr/local/bin/ruby

# 次の形式のスケジュールをソートする
# 
# day   style: Month day, year [time] text
# week  style: Week [time] text
# year  style: Month day [time] text
# month style: * day [time] text
# 
# これらの形式をこの順に並べ、各形式の中では日付が若いものほど前に並べ
# る。ただし、day styleの過去のスケジュールは末尾に配置する。各形式間
# は空行で区切る。

class Schedule
    # kind以外はソートのためにpublicにする
    attr("year")
    attr("month")
    attr("day")
    attr("week")
    attr("hour")
    attr("min")
    attr("past")                # 過去のデータなら1
    attr("kind")

    def initialize(line)
        @year = 9999
        @month = 12
        @day = 32
        @week = 8
        @hour = 0
        @min = 0
        @past = 0
        @line = line

        a = line.sub(/^&/,"").split(' ')
        case s = a.shift
        when /^\*$/
            @kind = "month"
            @day = a.shift.to_i
        when /^(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)$/
            @month = {"Jan" => 1, "Feb" => 2, "Mar" =>3, "Apr" => 4,
                "May" => 5, "Jun" => 6, "Jul" =>7, "Aug" => 8,
                "Sep" => 9, "Oct" => 10, "Nov" =>11, "Dec" => 12}[s]
            s = a.shift
            @kind = "year"
            if s =~ /.*,/
                @kind = "day"
                s.chop!
                @year = a.shift.to_i
                @past = 1 if Time.now >= Time.local(@year,@month,s.to_i+1)
            end
            @day = s.to_i
        when /^(Sun|Mon|Tues|Wednes|Thirs|Fri|Satur)day$/
            @kind = "week"
            @week = {"Sunday" => 0, "Monday" => 1, "Tuesday" => 2,
                "Wednesday" => 3, "Thirsday" => 4, "Friday" => 5,
                "Saturday" => 6}[s]
        else
            $stderr.print $0, " :illeagal line: ", line
        end
        if a[0] =~ /^(\d\d):(\d\d)$/
            @hour = $1.to_i
            @min = $2.to_i
        end
    end

    def <=>(other)
        ret = past - other.past
        ret = year - other.year if ret == 0
        ret = week - other.week if ret == 0
        ret = month - other.month if ret == 0
        ret = day - other.day if ret == 0
        ret = hour - other.hour if ret == 0
        ret = min - other.min if ret == 0
        ret
    end

    def to_s
        @line
    end
end

schedules = []
while gets
    schedules.push(Schedule.new($_)) unless /^$/
end

schedules.sort!

lastKind = nil
schedules.each do |x|
    print "\n" if x.kind != lastKind
    print x
    lastKind = x.kind
end
---------- ここまで ----------

-- 
川村 尚生 / 鳥取大学 工学部 知能情報工学科