diff options
| author | historia <[not public]> | 2025-02-28 01:01:01 -0500 |
|---|---|---|
| committer | historia <[not public]> | 2025-02-28 01:01:01 -0500 |
| commit | a3e3aae87e8f159749863987dfaff336a9ef89fe (patch) | |
| tree | ba1a9aeb29eb77c4b183b58679f03b1307be6d50 /src | |
| parent | bb3ef24f8db4e1a02649c06c6d0b5015562cd869 (diff) | |
| download | soon-a3e3aae87e8f159749863987dfaff336a9ef89fe.tar.gz | |
feat: implemented various cli arguments
Diffstat (limited to 'src')
| -rw-r--r-- | src/soon.nim | 51 | ||||
| -rw-r--r-- | src/soon/agenda.nim | 16 | ||||
| -rw-r--r-- | src/soon/columnize.nim | 30 | ||||
| -rw-r--r-- | src/soon/todos.nim | 34 |
4 files changed, 91 insertions, 40 deletions
diff --git a/src/soon.nim b/src/soon.nim index 2c5f109..61ac16d 100644 --- a/src/soon.nim +++ b/src/soon.nim @@ -1,4 +1,4 @@ -import std/[os, strutils, strtabs, sequtils, parseopt] +import std/[os, strutils, strtabs, sequtils, osproc, parseopt] import soon/[config, agenda, todos] const VERSION = "0.1" @@ -10,14 +10,15 @@ proc printHelp(badCmd: string) = Usage: soon [options] Options: --a print agenda (default behavior if no options) +-a print agenda -c print reference calendar -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 --d print today's date +-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 @@ -44,9 +45,15 @@ proc getFileLines(file: string): seq[string] = 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) @@ -67,15 +74,51 @@ proc parseArgs(config: StringTableRef): seq[string] = 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) - processCalendars(conf["calendarPath"], 0 - parseInt(conf["past"]), parseInt(conf["future"])) + processCommands(commands, conf) when isMainModule: main() diff --git a/src/soon/agenda.nim b/src/soon/agenda.nim index 29adf28..1c2ce11 100644 --- a/src/soon/agenda.nim +++ b/src/soon/agenda.nim @@ -1,4 +1,4 @@ -import std/[times, strutils, strbasics, strscans, sequtils, tables, algorithm, re] +import std/[times, strutils, sequtils, tables, algorithm] import conditionchecker, typechecker, parsetime, columnize type Event = object @@ -87,11 +87,11 @@ proc getCalendarForDate(cal: seq[string], date: DateTime): Calendar = proc compare(a, b: string): int = cmp(a.len, b.len) -proc startWithDate(datePrinted: bool, date: DateTime, format: string): seq[string] = +proc startWithDate(datePrinted: bool, date: DateTime, format: string): seq[Column] = if datePrinted: - result.add("") + result.add(Column(text: "", color: fgWhite)) else: - result.add(date.format(format)) + result.add(Column(text: date.format(format), color: fgYellow)) proc eventTime(event: Event): string = if event.time.monthday != 1: @@ -106,15 +106,15 @@ proc getDaysEvents(cal: seq[string], date: DateTime, format: string): seq[Line] for event in events: var columns = startWithDate(datePrinted, date, format) datePrinted = true - columns.add(eventTime(event)) - columns.add(event.name) + 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 i in past..future: - let curDay = today + i.days + for day in past..future: + let curDay = today + day.days agenda = agenda.concat(getDaysEvents(calendar, curDay, "ddd yyyy MMM dd")) columnize.echo(agenda) diff --git a/src/soon/columnize.nim b/src/soon/columnize.nim index 0fba176..a9074f1 100644 --- a/src/soon/columnize.nim +++ b/src/soon/columnize.nim @@ -1,18 +1,22 @@ -import std/[strutils, enumerate, sequtils] +import std/[strutils, enumerate, sequtils, terminal] + +type Column* = object + text*: string + color*: ForegroundColor type Line* = object - columns*: seq[string] + columns*: seq[Column] attachments*: seq[string] -proc prefixSpaceCount(s: seq[string]): int = - return foldl(s[0..s.len-2], a + b.len, 0) + (2 * s.len-2) +proc prefixSpaceCount(s: seq[Column]): int = + return foldl(s[0..s.len-2], a + b.text.len, 0) + (2 * s.len-2) proc pad(table: seq[Line], max: seq[int]): seq[Line] = for line in table: - var resLine = newSeq[string]() + var resLine = newSeq[Column]() var resAttach = newSeq[string]() for i, field in enumerate(line.columns): - resLine.add(field & repeat(' ', max[i] - field.len)) + resLine.add(Column(text:field.text & repeat(' ', max[i] - field.text.len), color: field.color)) if line.attachments.len > 0: let spaces = prefixSpaceCount(resLine) for attachment in line.attachments: @@ -23,13 +27,19 @@ proc columnize(table: seq[Line]): seq[Line] = var max = newSeq[int](table[0].columns.len) for line in table: for i, field in enumerate(line.columns): - if field.len > max[i]: - max[i] = field.len + if field.text.len > max[i]: + max[i] = field.text.len result = pad(table, max) +proc writeColumns(line: Line) = + for column in line.columns[0 .. ^2]: + stdout.styledWrite(column.color, column.text & " ") + stdout.styledWrite(line.columns[^1].color, line.columns[^1].text) + proc echo*(table: seq[Line]) = let lines = columnize(table) for line in lines: - echo line.columns.join(" ") + writeColumns(line) + stdout.writeLine("") for attachment in line.attachments: - echo attachment + stdout.styledWriteLine(fgMagenta, attachment) diff --git a/src/soon/todos.nim b/src/soon/todos.nim index 569bb8f..cac8c90 100644 --- a/src/soon/todos.nim +++ b/src/soon/todos.nim @@ -1,4 +1,4 @@ -import std/[times, strutils, tables, strtabs, re, options] +import std/[times, strutils, re, options, terminal] import conditionchecker, columnize type @@ -50,35 +50,33 @@ proc splitRegularAndDeadlineTodos(todos: seq[Todo]): (seq[Todo], seq[Todo]) = else: result[0].add(todo) -proc printRegularTodos(todos: seq[Todo]) = - if todos.len == 0: return - echo "\nTodo List:" - for todo in todos: - echo todo.name - for attachment in todo.attachments: - echo attachment - proc toLine(todo: Todo): Line = - result.columns = @[todo.deadline.format("ddd yyyy MMM dd")] + result.columns = @[Column(text: todo.deadline.format("ddd yyyy MMM dd"), color: fgYellow)] let due = (todo.deadline - now()).inDays if due > 0: - result.columns.add("(Due in " & due.intToStr & " days)") + result.columns.add(Column(text: "(Due in " & due.intToStr & " days)", color: fgGreen)) else: - result.columns.add("(OVERDUE)") - result.columns.add(todo.name) + result.columns.add(Column(text: "(OVERDUE)", color: fgRed)) + result.columns.add(Column(text: todo.name, color: fgWhite)) result.attachments = todo.attachments # TODO: Sort on deadlines -proc printDeadlineTodos(todos: seq[Todo]) = - if todos.len == 0: return +proc printDeadlineTodos*(calendar: seq[string]) = + let todos = getTodosFromCalendar(calendar) + var (regulars, deadlines) = splitRegularAndDeadlineTodos(todos) + if deadlines.len == 0: return echo "\nUpcoming Deadlines:" var lines = newSeq[Line]() - for todo in todos: + for todo in deadlines: lines.add(todo.toLine) columnize.echo(lines) proc printTodos*(calendar: seq[string]) = let todos = getTodosFromCalendar(calendar) var (regulars, deadlines) = splitRegularAndDeadlineTodos(todos) - printRegularTodos(regulars) - printDeadlineTodos(deadlines) + if todos.len == 0: return + echo "\nTodo List:" + for todo in todos: + echo todo.name + for attachment in todo.attachments: + stdout.styledWriteLine(fgMagenta, attachment) |
