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
|
import std/[times, strutils, sequtils, tables, algorithm]
import conditionchecker, typechecker, parsetime, columnize
type Event = object
name: string
time: DateTime
attachments: seq[string]
type Calendar = object
events: seq[Event]
readyForAttachments: bool
type ConditionTable = Table[string, seq[string]]
proc allDay(): DateTime =
return parse("0000", "HHmm", utc())
proc splitWhitespaceExceptParens(str:string): seq[string] =
# Splits a string on whitespace, but maintains whitespace in date groups like (Jan 15)
var inParens = false
for token in str.splitWhitespace:
if inParens:
result.add(result.pop & ' ' & token)
else:
result.add(token)
for c in token:
if c == '(': inParens = true
if c == ')': inParens = false
proc parseDateToTable(date: string): ConditionTable =
var table = initTable[string,seq[string]]()
let conditions = splitWhitespaceExceptParens(date)
for c in conditions:
let condType = typechecker.checkType(c)
if not table.hasKey(condType):
table[condType] = @[]
table[condType].add(c)
return table
proc allConditionsMet(conditions: ConditionTable, date: DateTime): bool =
if conditions.hasKey("unknown"): return false
for cs in conditions.values:
if not any(cs, proc(x: string): bool = conditionchecker.checkCond(x, date)):
return false
return true
proc newEvents(e: string, conditions: ConditionTable): seq[Event] =
let event = e.strip
if conditions.hasKey("time"):
for t in conditions["time"]:
result.add(Event(name: event, time: parsetime.toDateTime(t), attachments: @[]))
else:
result.add(Event(name: event, time: allDay(), attachments: @[]))
proc processEventLine(line: string, date: DateTime, cal: Calendar): Calendar =
result = cal
let split = line.split(",", maxsplit = 1)
var eventDate = split[0].strip
var eventName = split[1].strip
let conditions = parseDateToTable(eventDate)
if allConditionsMet(conditions, date):
result.events = result.events.concat(newEvents(eventName, conditions))
result.readyForAttachments = true
else:
result.readyForAttachments = false
proc processLine(line: string, date: DateTime, cal: Calendar): Calendar =
result = cal
let stripped = line.strip
if stripped.startsWith('+'):
if result.events.len > 0 and result.readyForAttachments:
result.events[^1].attachments.add(line)
elif stripped.startsWith('-'):
result.readyForAttachments = false
else:
result = processEventLine(line, date, cal)
proc getCalendarForDate(cal: seq[string], date: DateTime): Calendar =
result.readyForAttachments = false
for line in cal:
result = processLine(line, date, result)
#proc sortTable(t: ConditionTable) =
# for
# Check nim-lang algorithm basic usage
proc compare(a, b: string): int =
cmp(a.len, b.len)
proc startWithDate(datePrinted: bool, date: DateTime, format: string): seq[Column] =
if datePrinted:
result.add(Column(text: "", color: fgWhite))
else:
result.add(Column(text: date.format(format), color: fgYellow))
proc eventTime(event: Event): string =
if event.time.monthday != 1:
result = event.time.format("HH:mm")
else:
result = ""
# TODO: Sort me
proc getDaysEvents(cal: seq[string], date: DateTime, format: string): seq[Line] =
var events = getCalendarForDate(cal, date).events
var datePrinted = false
for event in events:
var columns = startWithDate(datePrinted, date, format)
datePrinted = true
columns.add(Column(text: eventTime(event), color: fgBlue))
columns.add(Column(text: event.name, color: fgWhite))
result.add(Line(columns: columns, attachments: event.attachments))
proc printAgenda*(calendar: seq[string], past: int, future: int) =
let now = now()
let today = dateTime(now.year, now.month, now.monthday, 00, 00, 00, 00, local())
var agenda = newSeq[Line]()
for day in past..future:
let curDay = today + day.days
agenda = agenda.concat(getDaysEvents(calendar, curDay, "ddd yyyy MMM dd"))
columnize.echo(agenda)
|