#!/usr/bin/env ruby require 'date' TODAY = Date.today class Entry < Struct.new(:depth, :state, :desc, :children) end def parse(io, filename=nil) todos = [Entry.new(-1, "/", "", [])] while line = io.gets if line =~ /\A(?:\s*(?:#|\/\/)\s)?(\s*)([-xX?*])\s+(.*)/ i, state, desc = $1.size, $2, $3 while i <= todos.last.depth todos.pop end e = Entry.new(i, state, desc, []) todos.last.children << e todos << e end end todos.first end def render(e) puts "
" case e.state when "-"; puts "☐" when "x"; puts "☑" when "X"; puts "☒" when "?"; puts "?" # or 2370 when "*"; puts "⊞" end puts e.desc.sub(/(^\s*)\(([A-Z])\)/) { $1 + "" + [$2.ord + 9333].pack("U") + "" }. gsub(/(?<=\s)@\w+/, '\&') puts "
" unless e.children.empty? puts "
" e.children.each { |c| render(c) } puts "
" end puts "
" end puts < EOF render(parse(STDIN))