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
|
import std/[os, strutils, strtabs, sequtils, osproc, parseopt]
import soon/[config, agenda, todos]
const VERSION = "0.1"
proc printHelp(badCmd: string) =
if badCmd != "":
echo badCmd & " is not a valid option\n"
echo """
Usage: soon [options]
Options:
-a print agenda
-c print reference calendar (using 'cal')
-t print todos
-d print deadlines
-e open default calendar file in $EDITOR
-i open TUI in interactive mode to schedule/archive events
-w, -m, -y print agenda for upcoming week, month, or year
-j print the modified julian day
-i, --date print today's date
-p, --past=DAYS days in past to print agenda (default: 1)
-f, --future=DAYS days in future to print agenda (default: 14)
-h, --help show this help
-v, --version print version
Check the docs at https://codeberg.org/historia/soon
"""
quit()
proc printVersion() =
echo "soon " & VERSION
quit()
proc createDefaultCalendarFile(file: string) =
if not fileExists(file):
writeFile(file, "# This is your first calendar file. Put events and todos in here.")
proc getFileLines(file: string): seq[string] =
let f = open(file)
for line in f.lines:
if line == "": continue
if line.strip[0] == '#': continue
result.add(line)
f.close()
proc readAllSoonFiles(path: string): seq[string] =
var soonFileExists = false
for file in os.walkDirRec(path):
if file.toLower().endsWith(".soon"):
soonFileExists = true
result = result.concat(getFileLines(file))
if not soonFileExists:
echo "No .soon files exist at " & path
echo "Check your paths in ~/.config/soon/soon.conf"
quit()
proc processCalendars(path: string, past: int, future: int) =
var calendar = readAllSoonFiles(path)
agenda.printAgenda(calendar, past, future)
todos.printTodos(calendar)
proc parseArgs(config: StringTableRef): seq[string] =
for kind, key, val in getopt():
case kind
of cmdEnd: break
of cmdLongOption, cmdShortOption:
case key
of "past", "p": config["past"] = val
of "future", "f": config["future"] = val
of "help", "h": printHelp("")
of "version", "v": printVersion()
else:
result.add(key)
of cmdArgument:
printHelp(key)
if result.len == 0:
result.add("a")
result.add("t")
result.add("d")
echo "I'm running soon -atd, but I should've checked the user config and run that!"
proc printReference() =
discard execCmd("cal -3")
proc sanitize(str: string): string =
result = ""
for ch in str:
if ch.isAlphaNumeric() or ch in {'/', '~', '.'}:
result.add(ch)
proc openEditor(path: string, file: string) =
var editor = getEnv("EDITOR").sanitize
if editor.isEmptyOrWhitespace: editor = "vim"
let sanePath = path.sanitize
let saneFile = file.sanitize
discard execCmd("$1 $2/$3" % [editor, sanePath, saneFile])
proc validateConfig(config: StringTableRef) =
createDefaultCalendarFile(config["path"] / config["defaultFile"])
proc processCommands(commands: seq[string], conf: StringTableRef) =
var calendar = readAllSoonFiles(conf["calendarPath"])
var past = 0 - parseInt(conf["past"])
var future = parseInt(conf["future"])
for command in commands:
case command
of "a": agenda.printAgenda(calendar, past, future)
of "w": agenda.printAgenda(calendar, 0, 7)
of "m": agenda.printAgenda(calendar, 0, 28)
of "y": agenda.printAgenda(calendar, 0, 365)
of "t": todos.printTodos(calendar)
of "d": todos.printDeadlineTodos(calendar)
of "c": printReference()
of "e": openEditor(conf["calendarPath"], conf["defaultFile"])
proc main() =
var conf = config.loadConfig()
let commands = parseArgs(conf)
validateConfig(conf)
processCommands(commands, conf)
when isMainModule:
main()
|