class TaskGroup
attr_reader :file, :path, :tasks
def initialize(file, path)
@file = file
@path = path
@tasks = []
end
def add_task(text)
@tasks.push text
end
end
class TodoSummaryBuilder
def initialize
@groups = []
@warnings = []
@scanner = DirectoryScanner.new
@scanner.on_file { |file, path|
next if /\.svn-base$/.match(file)
next unless FileTest.readable? path
fi = File.open(path, 'r')
begin
group = nil
fi.readlines.each { |line|
parts = /\/\/\s*TODO\s*(\S.*)/.match(line)
unless parts.nil?
if group.nil?
group = TaskGroup.new(file,path)
@groups.push group
end
group.add_task parts[1]
end
}
rescue
@warnings.push "Warning: error reading file #{path}"
ensure
fi.close
end
}
end
def scan_subtree(parentDir)
@scanner.scan_subtree(parentDir)
end
def save_report(path)
out = File.new(path, File::CREAT|File::TRUNC|File::RDWR)
begin
out.puts <<END_HTML
<html>
<head>
<title>TODOs</title>
<style>
body {
font-family: Verdana;
}
div.file {
font-size: 14px;
font-weigtht: bold;
}
div.path {
font-size: 10px;
}
li.group {
margin-top: 12px;
}
li.task {
font-size: 12px;
}
p.warning {
font-size: 12px;
color: red;
}
</style>
</head>
<body>
<ul>
END_HTML
@groups.each { |group|
out.puts "<li class='group'><div class='file'>#{group.file}</div><div class='path'>#{group.path}</div><ul>"
group.tasks.each { |task|
out.puts "<li class='todo'>#{task}"
}
out.puts("</ul>")
}
out.puts("</ul>");
@warnings.each { |text|
out.puts("<p class='warning'>#{text}</p>")
}
out.puts("</body></html>")
ensure
out.close
end
end
end
builder = TodoSummaryBuilder.new
builder.scan_subtree('c:\project1')
builder.scan_subtree('c:\project2')
builder.scan_subtree('c:\project3')
builder.save_report('c:\result.html')