ChangeLog.new そのに
id:ha-tan:20060212:1139749716を実装してみました。こんな感じかな。get_chunkまわりが美しくないです。この辺を別クラスに切り出すべきかなー。Raccとか使った方がいいかも(でもRaccが必要なほど複雑ってわけでもないし…)。それから、このコードはライブラリというにはネームスペースに無頓着です。例外も適当だし。
#!/usr/bin/env ruby # -*- ruby -*- class ChangeLogEntry def initialize(date, content) @date, @content = date, content end attr_reader :date, :content def to_s @content end end class ChangeLog def initialize(filename) @date = {} @category = {} @tmpline = '' date = nil each_chunk(filename) do |chunk| if /^(\d\d\d\d-\d\d-\d\d)/ =~ chunk date = $1 @date[date] ||= [] else entries = @date[date] raise "not found date #{date}." unless entries entry = ChangeLogEntry.new(date, chunk) entries.push entry if /^\t\*\s*([^:]*)\s*:/ =~ chunk @category[$1] ||= [] @category[$1].push entry end end end end def each_chunk(filename) open(filename, 'r') do |file| while chunk = get_chunk(file) yield(chunk) end end end private :each_chunk def get_chunk(file) chunk = @tmpline @tmpline = '' while line = file.gets if /^(?:\d\d\d\d-\d\d-\d\d|\t\*)/ !~ line or chunk.size == 0 chunk += line else @tmpline = line return chunk end end (chunk.size > 0) ? chunk : nil end private :get_chunk def each_days @date.keys.sort.reverse.each do |date| yield(date, @date[date]) end end def search_by_date(date) @date[date] end def search_by_category(category) @category[category] end def search(re) result = [] each_days do |date, entries| entries.each do |entry| result.push entry if re =~ entry.content end end result end end if $0 == __FILE__ log = ChangeLog.new('ChangeLog') puts '######## each_day ########' log.each_days do |date, enties| puts '----' puts date enties.each do |entry| puts '--' puts entry end end puts '######## seach_by_date ########' log.search_by_date('2006-02-12').each do |entry| puts '--' puts entry end puts '######## seach_by_category ########' log.search_by_category('hoge').each do |entry| puts '--' puts entry end puts '######## seach ########' log.search(/ruby/).each do |entry| puts '--' puts entry end end