/usr/share/howm/contrib/hcal.rb is in howm 1.4.2-2.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 | #!/usr/bin/ruby -sKe
# -*- Ruby -*-
# require 'jcode'
require 'iconv'
require 'date'
def usage
name = File::basename $0
print <<EOU
#{name}: ͽÄê¤ä todo ¤Î°ìÍ÷¤ò½ÐÎÏ
(Îã)
#{name} *.memo ¢ª ¥«¥ì¥ó¥À¡¼(ͽÄꡦ¡ºÀÚ¡¦ºÑ¤ß¤Î°ìÍ÷)¤ò½ÐÎÏ
#{name} -l *.memo ¢ª ½ÜÅÙ½ç¤Î todo °ìÍ÷¤ò½ÐÎÏ
#{name} -i *.memo ¢ª iCalendar ·Á¼°¤Ç½ÐÎÏ (ºîÀ®Ãæ)
#{name} -h ¤Þ¤¿¤Ï #{name} -help ¢ª ¤³¤Î¥á¥Ã¥»¡¼¥¸¤ò½ÐÎÏ
(¹àÌܤνñ¼°)
http://howm.sourceforge.jp/ »²¾È
EOU
end
############################################
# const
$schedule_types ||= '[@!.]'
$type_alias = {'' => '-'}
$date_sep = '-'
def item_regexp(types)
x = $date_sep
if $format == 'old'
$todo_types ||= '[-+~!.]?'
%r|(@\[(\d\d\d\d)#{x}(\d\d)#{x}(\d\d)\](#{types})(\d*)\s+(.*))$|
else
$todo_types ||= '[-+~!.]'
%r|(\[(\d\d\d\d)#{x}(\d\d)#{x}(\d\d)\](#{types})(\d*)\s+(.*))$|
end
end
# calendar
$comment_width ||= 12
$comment_width = $comment_width.to_i
$schedule_mark ||= '@'
$deadline_mark ||= '!'
$done_mark ||= '.'
$type_display = {
'@' => $schedule_mark,
'!' => $deadline_mark,
'.' => $done_mark,
'?' => '¢¥'
}
$type_order = {'@' => 2, '!' => 1, '.' => 3, '?' => 4}
$today_mark ||= ' <<<<##>>>>'
$same_day_mark ||= ' #>>>>'
# todo
$priority_func = {
# '' => lambda{|lt, lz| pr_normal lt, lz},
'-' => lambda{|lt, lz| pr_normal lt, lz},
'+' => lambda{|lt, lz| pr_todo lt, lz},
'~' => lambda{|lt, lz| pr_defer lt, lz},
'!' => lambda{|lt, lz| pr_deadline lt, lz},
'@' => lambda{|lt, lz| pr_schedule lt, lz},
'.' => lambda{|lt, lz| pr_done lt, lz},
'?' => lambda{|lt, lz| 0},
}
# defaults
$lz_normal = 1
$lz_todo = 7
$lz_defer = 30
$lz_deadline = 7
# init
$pr_todo = -7
$pr_defer = -14
$pr_defer_peak = 0
$pr_deadline = -2
$huge = 77777
$huger = 88888
$pr_normal_bottom = - $huge
$pr_todo_bottom = - $huge
$pr_defer_bottom = - $huge
$pr_deadline_bottom = - $huge
$pr_deadline_top = $huge
$pr_done_bottom = - $huger
# misc
$now = Time::now.to_f
$daysec = 60 * 60 * 24
############################################
# func
def late(time)
($now - time.to_f) / $daysec
end
# def late(y, m, d, now)
# ($now - Time::local(y,m,d,0,0,0).to_f) / $daysec
# end
def relative_late(late, laziness, default)
laziness = default if laziness == 0
late / laziness
end
def pr_normal(lt, lz)
r = relative_late lt, lz, $lz_normal
r >= 0 ? - r : $pr_normal_bottom + r
end
def pr_todo(lt, lz)
r = relative_late lt, lz, $lz_todo
c = - $pr_todo
r >= 0 ? c * (r - 1) : $pr_todo_bottom + r
end
def pr_defer(lt, lz)
r = relative_late lt, lz, $lz_defer
c = $pr_defer_peak - $pr_defer
v = 2 * (((r % 1) - 0.5).abs)
r >= 0 ? $pr_defer_peak - c * v : $pr_defer_bottom + r
end
def pr_deadline(lt, lz)
r = relative_late lt, lz, $lz_deadline
c = - $pr_deadline
if r > 0
$pr_deadline_top + r
elsif r < -1
$pr_deadline_bottom + r
else
c * r
end
end
# dummy
def pr_schedule(lt, lz)
0
end
def pr_done(lt, lz)
$pr_done_bottom + lt
end
############################################
# main
if ($help || $h)
usage
exit 0
end
def item(types)
ARGF.grep(item_regexp(types)){|x|
h = Hash::new
h[:text] = $1
y, m, d = [$2, $3, $4].map{|s| s.to_i}
# h[:y] = y = $2.to_i
# h[:m] = m = $3.to_i
# h[:d] = d = $4.to_i
h[:time] = time = Time::mktime(y, m, d)
h[:type] = type = $type_alias[$5] || $5
h[:laziness] = laziness = $6.to_i
h[:comment] = $7
h[:priority] = - $priority_func[type].call(late(time), laziness)
h[:file] = ARGF.filename
h[:line] = ARGF.file.lineno
h
}
end
# def select_type(item, types)
# item.select{|h| types.member? h[:type]}
# end
### todo
def todo()
item($todo_types).sort{
|a, b| a[:priority] <=> b[:priority]
}.each{|a|
puts "#{a[:file]}:#{a[:line]}:#{a[:text]}"
}
end
### ical
$conv = Iconv.new("UTF-8", "EUC-JP")
def ical()
puts <<_EOS_
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//howm.sourceforge.jp//hcal.rb $Revision: 1.12 $//EN
CALSCALE:Gregorian
#{item($schedule_types).map{|h| ical_item h}.select{|z| z}.join.chomp}
END:VCALENDAR
_EOS_
end
def ical_item(h)
# if !Date.valid_date?(h[:y], h[:m], 1)
# $stderr.puts 'Invalid date:#{h[:file]}:#{h[:line]}:#{h[:text]}'
# return nil
# end
# # convert 2005-09-31 to 2005-10-01
# d = Date.new(h[:y], h[:m], 1) + (h[:d] - 1)
# d = Date.new h[:y], h[:m], h[:d]
# s, e = [d, d+1].map{|z| z.strftime '%Y%m%d'}
s, e = [h[:time], h[:time] + 86400].map{|z| z.strftime '%Y%m%d'}
return <<_EOS_
BEGIN:VEVENT
DTSTART:#{s}
DTEND:#{e}
SUMMARY:#{$conv.iconv(h[:type] + h[:comment])}
END:VEVENT
_EOS_
end
### schedule
def schedule()
cal = Hash::new
item($schedule_types).each{|h|
t = h[:time]
cal[t] ||= Array::new
cal[t].push h
# [2004-12-25]@3 ==> [2004-12-25]@ [2004-12-26]@ [2004-12-27]@
if h[:type] == '@' && h[:laziness] > 1
(1...h[:laziness]).each{|d|
td = t + 60 * 60 * 24 * d
cal[td] ||= Array::new
cal[td].push h
}
end
}
min_time = cal.keys.min
max_time = cal.keys.max
t = min_time
while t <= max_time
c = cal[t] || []
puts if t.wday == 0
puts "----------------<#{t.month}>---------------- #{t.year}" if t.day == 1
day = t.strftime '%d %a'
text = c.sort{|a,b|
x, y = [a, b].map{|z| [$type_order[z[:type]], z[:comment]]}
x <=> y
# $type_order[a[:type]] <=> $type_order[b[:type]]
}.map{|h|
h[:comment].sub!(%r|^(cancel)? *\[[#{$date_sep}0-9]+\][!+]?[0-9]*\s*|){|s| $1 ? 'x' : ''} if h[:type] == '.' # adhoc!
$type_display[h[:type]] + h[:comment].split(//)[0, $comment_width].join
}.join ' '
mark = if t.strftime('%Y%m%d') == Time::now.strftime('%Y%m%d')
$today_mark
elsif t.strftime('%m%d') == Time::now.strftime('%m%d')
$same_day_mark
else
''
end
puts "#{day} #{text}#{mark}"
t += 60*60*24
end
end
### main
if $l
todo
elsif $i
ical
else
schedule
end
|