aboutsummaryrefslogtreecommitdiff
path: root/src/soon.nim
diff options
context:
space:
mode:
Diffstat (limited to 'src/soon.nim')
-rw-r--r--src/soon.nim136
1 files changed, 136 insertions, 0 deletions
diff --git a/src/soon.nim b/src/soon.nim
new file mode 100644
index 0000000..3040f84
--- /dev/null
+++ b/src/soon.nim
@@ -0,0 +1,136 @@
+import std/[times, os, strutils, strbasics, strscans, sets, strtabs, tables], parseopt
+import soon/[conditions, config, typechecker]
+
+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 != "":
+ echo badCmd & " is not a valid option\n"
+ echo """
+Usage:
+ soon [options] [commands]
+
+OPTIONS
+ -h, --help show list of CLI options
+ -v, --version show soon version
+ --future=DAYS set future
+ --past=DAYS set past
+
+COMMANDS
+ a print upcoming agenda (default command)
+ e open default calendar file in $EDITOR
+ j print the modified julian day
+ """
+ quit()
+
+proc printVersion() =
+ echo "soon " & VERSION
+ quit()
+
+# 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 getEvents(cal: seq[string], date: DateTime): seq[string] =
+ var events: seq[string] = newSeq[string]()
+ for line in cal:
+ var (success, dateConditions, event) = scanTuple(line, "$*,$*")
+ if success:
+ dateConditions.strip
+ event.strip
+ let conditions = parseDateToTable(dateConditions)
+ var match = true
+ # key = Condition Type (e.g. month), cs = Seq of conditions
+ for k,cs in conditions:
+ var keyMatched = false
+ for c in cs:
+ if checkCond(c, date) == true:
+ keyMatched = true
+ break
+ if not keyMatched:
+ match = false
+ break
+ if match:
+ events.add(event)
+ else:
+ echo "WARNING: Cannot parse line: ", line
+ return events
+
+proc printEvents(cal: seq[string], date: DateTime, format: string) =
+ let events = getEvents(cal, date)
+ if events.len > 0:
+ for e in events:
+ echo date.format(format), " ", e
+
+proc openCal(file: string): seq[string] =
+ let f = open(file)
+ var cal: seq[string]
+ for line in f.lines:
+ if line == "": continue
+ if line.strip[0] == '#': continue
+ cal.add(line)
+ f.close()
+ return cal
+
+proc printCalendar() =
+ let cal = openCal(defaultCalendarFile)
+ var past = -3
+ var future = 7
+ let now = now()
+
+ for i in past..future:
+ let curDay = now + i.days
+ printEvents(cal, curDay, "ddd yyyy MMM dd")
+
+proc parseArgs(config: StringTableRef): StringTableRef =
+ for kind, key, val in getopt():
+ case kind
+ of cmdLongOption, cmdShortOption:
+ case key
+ of "help", "h":
+ printHelp("")
+ of "version", "v":
+ printVersion()
+ else:
+ printHelp(key)
+ else:
+ discard
+
+proc main() =
+ var config = loadConfig()
+ config = parseArgs(config)
+ var noArg: bool = true
+
+ if noArg:
+ printCalendar()
+
+when isMainModule:
+ main()