aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/then.nim123
1 files changed, 104 insertions, 19 deletions
diff --git a/src/then.nim b/src/then.nim
index 67700a4..be3e813 100644
--- a/src/then.nim
+++ b/src/then.nim
@@ -1,15 +1,20 @@
-import std/[times, os, strutils, strbasics, strscans, sets], parseopt
+import std/[times, os, strutils, strbasics, strscans, sets, re, deques], parseopt
const VERSION = "0.1"
-const defaultConfigDir = expandTilde("~/.config/then/")
-const defaultConfigFile = defaultConfigDir & "then.toml"
-const defaultCalendarFile = defaultConfigDir & "calendar.then"
+const configDir = expandTilde("~/.config/then/")
+const defaultConfigFile = configDir & "then.toml"
+const defaultCalendarFile = configDir & "calendar.then"
+
+type
+ Token = object
+ token: string
+ precedence: int
# Creates a default configuration file if it doesn't exist
proc createDefaultConfigFile() =
if not fileExists(defaultConfigFile):
- if not dirExists(defaultConfigDir):
- createDir(defaultConfigDir)
+ if not dirExists(configDir):
+ createDir(configDir)
writeFile(defaultConfigFile, """
[config]
directory = "~/.config/then/"
@@ -18,10 +23,9 @@ proc createDefaultConfigFile() =
# Creates a default calendar file if it doesn't exist
proc createDefaultCalendarFile() =
if not fileExists(defaultCalendarFile):
- if not dirExists(defaultConfigDir):
- createDir(defaultConfigDir)
+ if not dirExists(configDir):
+ createDir(configDir)
writeFile(defaultCalendarFile, """
- # Default calendar file
# Add your events here
""")
@@ -52,7 +56,12 @@ proc printVersion() =
proc checkType(cond: string): string =
if cond.len == 4 and parseInt(cond) != 0: return "year"
if cond.len in [1, 2] and parseInt(cond) != 0: return "day"
- if cond in ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"].toHashSet: return "month"
+ if cond in DefaultLocale.MMM.toHashSet or cond in DefaultLocale.MMMM.toHashSet: return "month"
+ if cond in DefaultLocale.ddd.toHashSet or cond in DefaultLocale.dddd.toHashSet: return "dayofweek"
+ if find(cond, re"\d{1,2}:\d{2}") > -1: return "time"
+ if find(cond, re"\dw") > -1: return "firstweek"
+ if find(cond, re"\dl") > -1: return "lastweek"
+ if find(cond, re"J%\d([-+]\d)?") > -1: return "julian"
return "unknown"
proc checkCond(cond: string, day: DateTime): bool =
@@ -65,6 +74,15 @@ proc checkCond(cond: string, day: DateTime): bool =
of "month":
if cond == day.format("MMM"): return true
if cond == day.format("MMMM"): return true
+ of "dayofweek":
+ if cond == day.format("ddd"): return true
+ if cond == day.format("dddd"): return true
+ of "time":
+ return true
+ of "firstweek":
+ discard
+# Uh oh we didn't think about this hard enough
+
of "unknown":
echo "UNKNOWN THING ", cond
return false
@@ -74,21 +92,88 @@ proc getConditions(dateStr: string): seq[string] =
conditions = dateStr.rsplit(' ')
return conditions
+# TODO simplify?? Would it be easier to identify conditions and replace them with TRUE/FALSE then just process the string?
+
+# Shunting yard to parse conditions, parens, and logical operators
+# Does NOT parse out individual conditions yet because some individual
+# conditions (like 1W) require context of surrounding conditions.
+# The logic around parentheses is a little weird because conditions like
+# "<(March 15)" contain parentheses that we don't want to throw out
+proc parseDateToEvents(dateStr: string): seq[string] =
+ var holdingStack = initDeque[Token]()
+ var resultStack = initDeque[Token]()
+ var newToken: string = ""
+ for c in dateStr:
+ echo c
+ case c:
+ of '(':
+ if newToken.len == 1:
+ if newToken[0] == '>' or newToken[0] == '<':
+ newToken.add(c)
+ else
+ echo "ERROR: newToken exists but we got an open paren?"
+ else:
+ holdingStack.addLast(Token(token: "(", precedence: 0))
+ of ')':
+ if newToken.len > 0: # Closing token like <(March 15). Push the token.
+ resultStack.addLast(Token(token: newToken, precedence: 0))
+ newToken = ""
+ else: # Logical closing paren. Pop stack until (.
+ while holdingStack.len > 0 and holdingStack.peekLast.token != "(":
+ if holdingStack.len == 0:
+ echo "UH OH, ERROR MISMATCHED PARENS"
+ resultStack.addLast(holdingStack.popLast)
+ discard holdingStack.popLast # Pop the (
+ of '!':
+ holdingStack.addLast(Token(token: "!", precedence: 3))
+ of '|':
+ while holdingStack.len > 0 and holdingStack.peekLast.precedence > 2:
+ resultStack.addLast(holdingStack.popLast)
+ holdingStack.addLast(Token(token: "|", precedence: 2))
+ of ' ':
+ if newToken.len > 1 and newToken[1] == '(' and newToken[newToken.len-1] != ')': # Middle of token like <(March 15).
+ newToken.add(c)
+ else: # End of new token, implicit &
+ # Add newToken to result
+ resultStack.addLast(Token(token: newToken, precedence: 0))
+ newToken = ""
+ # Add implicit & to holding
+ while holdingStack.len > 0 and holdingStack.peekLast.precedence > 1:
+ resultStack.addLast(holdingStack.popLast)
+ holdingStack.addLast(Token(token:"&", precedence: 1))
+ of '>','<',':','-','a'..'z','A'..'Z','0'..'9':
+ newToken.add(c)
+ else:
+ echo "Weird character in dateStr: ", c
+ discard
+ # Push last token
+ if newToken.len > 0:
+ resultStack.addLast(Token(token: newToken, precedence: 0))
+ # Clear the holding stack
+ while holdingStack.len > 0:
+ var t = holdingStack.popLast
+ if t.token != "(":
+ resultStack.addLast(t)
+ echo resultStack
+
+
proc getEvents(cal: seq[string], day: DateTime): seq[string] =
var events: seq[string]
for line in cal:
- var (success, dateStr, eventStr) = scanTuple(line, "$+,$*")
+ var (success, dateStr, eventStr) = scanTuple(line, "$*,$*")
if success:
dateStr.strip
eventStr.strip
- let conditions = getConditions(dateStr)
- var match = true
- for c in conditions:
- if checkCond(c, day) == false:
- match = false
- break
- if match:
- events.add(eventStr)
+ discard parseDateToEvents(dateStr)
+ #let conditions = getConditions(dateStr)
+ # var match = true
+ # for c in conditions:
+ # c = c.toLower.capitalizeAscii
+ # if checkCond(c, day) == false:
+ # match = false
+ # break
+ # if match:
+ # events.add(eventStr)
else:
echo "WARNING: Cannot parse line: ", line
return events