diff options
| -rw-r--r-- | src/soon.nim | 84 | ||||
| -rw-r--r-- | src/soon/agenda.nim | 72 | ||||
| -rw-r--r-- | src/soon/conditionchecker.nim (renamed from src/soon/conditions.nim) | 0 | ||||
| -rw-r--r-- | src/soon/todos.nim | 49 |
4 files changed, 126 insertions, 79 deletions
diff --git a/src/soon.nim b/src/soon.nim index d154846..cede38c 100644 --- a/src/soon.nim +++ b/src/soon.nim @@ -1,13 +1,7 @@ -import std/[times, os, strutils, strbasics, sequtils, strscans, sets, strtabs, tables], parseopt -import soon/[conditions, config, typechecker] +import std/[os, strutils, strtabs, sequtils, parseopt] +import soon/[config, agenda, todos] const VERSION = "0.1" -const configDir = expandTilde("~/.config/soon/") -const defaultConfigFile = configDir & "soon.toml" -const defaultCalendarFile = configDir & "calendar.soon" - -const MONTHS = DefaultLocale.MMM.toHashSet + DefaultLocale.MMMM.toHashSet -const WEEKDAYS = DefaultLocale.ddd.toHashSet + DefaultLocale.dddd.toHashSet proc printHelp(badCmd: string) = if badCmd != "": @@ -41,73 +35,6 @@ proc createDefaultCalendarFile(file: string) = if not fileExists(file): writeFile(file, "# This is your first calendar file. Put events and todos in here.") -# Splits a string on whitespace, but maintains whitespace in date groups -proc splitWhitespaceExceptParens(str:string): seq[string] = - var output: seq[string] = newSeq[string]() - var inParens = false - for token in str.splitWhitespace: - if inParens: - output.add(output.pop & ' ' & token) - else: - output.add(token) - for c in token: - if c == '(': inParens = true - if c == ')': inParens = false - return output - -# Returns Table[conditionType, seq of conditions] -proc parseDateToTable(date:string): Table[string, seq[string]] = - var table = initTable[string,seq[string]]() - let conditions = splitWhitespaceExceptParens(date) - for c in conditions: - let condType = checkType(c) - if not table.hasKey(condType): - table[condType] = @[] - table[condType].add(c) - return table - -proc checkAllConditions(dateConditions: string, date: DateTime): bool = - let conditions = parseDateToTable(dateConditions.strip) - for k,cs in conditions: - var keyMatched = false - for c in cs: - if checkCond(c, date) == true: - keyMatched = true - break - if not keyMatched: - return false - return true - -# Returns Table[eventName, eventAttachedLines] -proc getEventsForDate(cal: seq[string], date: DateTime): Table[string, seq[string]] = - var lastInsertion = "" - for line in cal: - var (success, dateConditions, event) = scanTuple(line, "$*,$*") - if success: - if checkAllConditions(dateConditions, date) == true: - event.strip - result[event] = @[] - lastInsertion = event - elif line.strip[0] == '+': - if result.hasKey(lastInsertion): - result[lastInsertion].add(line) - else: - echo "WARNING: Cannot parse line: ", line - -proc printEvents(cal: seq[string], date: DateTime, format: string) = - let events = getEventsForDate(cal, date) - if events.len > 0: - for e in events.keys: - echo date.format(format), " ", e - for attachment in events[e]: - echo attachment.indent(date.format(format).len + 2) - -proc printAgenda(calendar: seq[string], past: int, future: int) = - let now = now() - for i in past..future: - let curDay = now + i.days - printEvents(calendar, curDay, "ddd yyyy MMM dd") - proc getCalendarFileLines(file: string): seq[string] = let f = open(file) for line in f.lines: @@ -121,7 +48,8 @@ proc processCalendars(calendarPath: string, past: int, future: int) = for file in os.walkDirRec(calendarPath): if file.toLower().endsWith(".soon"): calendar = calendar.concat(getCalendarFileLines(file)) - printAgenda(calendar, past, future) + agenda.printAgenda(calendar, past, future) + todos.printTodos(calendar) proc parseArgs(config: StringTableRef): seq[string] = for kind, key, val in getopt(): @@ -145,9 +73,7 @@ proc main() = var conf = config.loadConfig() let commands = parseArgs(conf) validateConfig(conf) - let past = 0 - parseInt(conf["past"]) - let future = parseInt(conf["future"]) - processCalendars(conf["calendarPath"], past, future) + processCalendars(conf["calendarPath"], 0 - parseInt(conf["past"]), parseInt(conf["future"])) when isMainModule: main() diff --git a/src/soon/agenda.nim b/src/soon/agenda.nim new file mode 100644 index 0000000..014be1e --- /dev/null +++ b/src/soon/agenda.nim @@ -0,0 +1,72 @@ +import std/[times, strutils, strbasics, strscans, tables] +import conditionchecker, typechecker + +# Splits a string on whitespace, but maintains whitespace in date groups +proc splitWhitespaceExceptParens(str:string): seq[string] = + var output: seq[string] = newSeq[string]() + var inParens = false + for token in str.splitWhitespace: + if inParens: + output.add(output.pop & ' ' & token) + else: + output.add(token) + for c in token: + if c == '(': inParens = true + if c == ')': inParens = false + return output + +# Returns Table[conditionType, seq of conditions] +proc parseDateToTable(date:string): Table[string, seq[string]] = + 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(dateConditions: string, date: DateTime): bool = + let conditions = parseDateToTable(dateConditions.strip) + for k,cs in conditions: + var keyMatched = false + for c in cs: + if conditionchecker.checkCond(c, date) == true: + keyMatched = true + break + if not keyMatched: + return false + return true + +# Returns Table[event, attachments] +proc getEventsForDate(cal: seq[string], date: DateTime): Table[string, seq[string]] = + var lastInsertion = "" + for line in cal: + var (success, dateConditions, event) = scanTuple(line, "$*,$*") + if success: + if allConditionsMet(dateConditions, date) == true: + event.strip + result[event] = @[] + lastInsertion = event + elif line.strip[0] == '+': + if result.hasKey(lastInsertion): + result[lastInsertion].add(line) + elif line.strip[0] == '-': + lastInsertion = "" + else: + echo "WARNING: Cannot parse line: ", line + +proc printEvents(cal: seq[string], date: DateTime, format: string) = + let events = getEventsForDate(cal, date) + if events.len > 0: + for e in events.keys: + echo date.format(format), " ", e + for attachment in events[e]: + let space = date.format(format).len + 2 + echo attachment.indent(space) + +proc printAgenda*(calendar: seq[string], past: int, future: int) = + let now = now() + for i in past..future: + let curDay = now + i.days + printEvents(calendar, curDay, "ddd yyyy MMM dd") diff --git a/src/soon/conditions.nim b/src/soon/conditionchecker.nim index 1880d42..1880d42 100644 --- a/src/soon/conditions.nim +++ b/src/soon/conditionchecker.nim diff --git a/src/soon/todos.nim b/src/soon/todos.nim new file mode 100644 index 0000000..2129ec1 --- /dev/null +++ b/src/soon/todos.nim @@ -0,0 +1,49 @@ +import std/[times, strutils, tables, re] + +# Returns Table[todo, attachments] +proc getTodosFromCalendar(calendar: seq[string]): Table[string, seq[string]] = + var lastInsertion = "" + for l in calendar: + let line: string = l.strip + if line[0] == '-': + result[line] = @[] + lastInsertion = line + elif line[0] == '+': + if result.hasKey(lastInsertion): + result[lastInsertion].add(l) + else: + lastInsertion = "" + +proc splitRegularAndDeadlineTodos(todos: Table[string, seq[string]]): (Table[string, seq[string]], Table[string, seq[string]]) = + for todo in todos.keys: + var attachments = newSeq[string]() + var hasDeadline = false + for attach in todos[todo]: + if match(attach, re("^\\s*\\+\\s*Due:", flags = {reIgnoreCase})): + hasDeadline = true + attachments.add(attach) + if hasDeadline: + result[1][todo] = attachments + else: + result[0][todo] = attachments + +proc printRegularTodos(todos: Table[string, seq[string]]) = + if todos.len > 0: + echo "\nTodo List:" + for todo in todos.keys: + echo todo + for attachment in todos[todo]: + echo attachment + +proc printDeadlineTodos(todos: Table[string, seq[string]]) = + if todos.len > 0: + echo "\nUpcoming Deadlines:" + for todo in todos.keys: + echo todo + echo "Deadline logic not yet implemented" + +proc printTodos*(calendar: seq[string]) = + let todos = getTodosFromCalendar(calendar) + var (regular, deadline) = splitRegularAndDeadlineTodos(todos) + printRegularTodos(regular) + printDeadlineTodos(deadline) |
