4 Commits

4 changed files with 44 additions and 21 deletions

View File

@ -9,6 +9,8 @@ type
Timeline* = tuple[name: string, marks: seq[Mark]] Timeline* = tuple[name: string, marks: seq[Mark]]
## Representation of a timeline: a name and sequence of Marks. ## Representation of a timeline: a name and sequence of Marks.
OffsetFrom = enum Year, Month, Day, None
const STOP_MSG* = "STOP" const STOP_MSG* = "STOP"
let NO_MARK*: Mark = ( let NO_MARK*: Mark = (
@ -20,11 +22,18 @@ const ISO_TIME_FORMAT* = "yyyy-MM-dd'T'HH:mm:ss"
## The canonical time format used by PTK. ## The canonical time format used by PTK.
const TIME_FORMATS* = @[ const TIME_FORMATS* = @[
"yyyy-MM-dd'T'HH:mm:ss", "yyyy-MM-dd HH:mm:ss", (fmtStr: "yyyy-MM-dd'T'HH:mm:ss", offsetFrom: OffsetFrom.None),
"yyyy-MM-dd'T'HH:mm", "yyyy-MM-dd HH:mm", (fmtStr: "yyyy-MM-dd HH:mm:ss", offsetFrom: OffsetFrom.None),
"MM-dd'T'HH:mm:ss", "MM-dd HH:mm:ss", (fmtStr: "yyyy-MM-dd'T'HH:mm", offsetFrom: OffsetFrom.None),
"MM-dd'T'HH:mm", "MM-dd HH:mm", (fmtStr: "yyyy-MM-dd HH:mm", offsetFrom: OffsetFrom.None),
"HH:mm:ss", "H:mm:ss", "H:mm", "HH:mm" ] (fmtStr: "MM-dd'T'HH:mm:ss", offsetFrom: OffsetFrom.Year),
(fmtStr: "MM-dd HH:mm:ss", offsetFrom: OffsetFrom.Year),
(fmtStr: "MM-dd'T'HH:mm", offsetFrom: OffsetFrom.Year),
(fmtStr: "MM-dd HH:mm", offsetFrom: OffsetFrom.Year),
(fmtStr: "HH:mm:ss", offsetFrom: OffsetFrom.Day),
(fmtStr: "H:mm:ss", offsetFrom: OffsetFrom.Day),
(fmtStr: "H:mm", offsetFrom: OffsetFrom.Day),
(fmtStr: "HH:mm", offsetFrom: OffsetFrom.Day) ]
## Other time formats that PTK will accept as input. ## Other time formats that PTK will accept as input.
proc getOrFail*(n: JsonNode, key: string, objName: string = ""): JsonNode = proc getOrFail*(n: JsonNode, key: string, objName: string = ""): JsonNode =
@ -40,7 +49,23 @@ proc getIfExists*(n: JsonNode, key: string): JsonNode =
proc parseTime*(timeStr: string): DateTime = proc parseTime*(timeStr: string): DateTime =
## Helper to parse time strings trying multiple known formats. ## Helper to parse time strings trying multiple known formats.
for fmt in TIME_FORMATS: for fmt in TIME_FORMATS:
try: return parse(timeStr, fmt) try:
let now = now()
let parsed = parse(timeStr, fmt.fmtStr)
case fmt.offsetFrom:
of OffsetFrom.None:
return parsed
of OffsetFrom.Year:
return initDateTime(parsed.monthday, parsed.month, now.year,
parsed.hour, parsed.minute, parsed.second, parsed.nanosecond,
now.timezone)
of OffsetFrom.Month:
return initDateTime(parsed.monthday, now.month, now.year,
parsed.hour, parsed.minute, parsed.second, parsed.nanosecond,
now.timezone)
of OffsetFrom.Day:
return initDateTime(now.monthday, now.month, now.year, parsed.hour,
parsed.minute, parsed.second, parsed.nanosecond, now.timezone)
except: discard nil except: discard nil
raise newException(Exception, "unable to interpret as a date: " & timeStr) raise newException(Exception, "unable to interpret as a date: " & timeStr)
@ -112,5 +137,3 @@ proc getLastIndex*(marks: seq[Mark]): int =
while idx >= 0 and marks[idx].summary == STOP_MSG: idx -= 1 while idx >= 0 and marks[idx].summary == STOP_MSG: idx -= 1
if idx < 0: result = -1 if idx < 0: result = -1
else: result = idx else: result = idx

View File

@ -1 +1 @@
const PTK_VERSION* = "1.0.7" const PTK_VERSION* = "1.0.10"

14
ptk.nim
View File

@ -4,7 +4,7 @@
## Simple time keeping CLI ## Simple time keeping CLI
import algorithm, docopt, json, langutils, logging, os, nre, std/wordwrap, import algorithm, docopt, json, langutils, logging, os, nre, std/wordwrap,
sequtils, sets, strutils, tempfile, terminal, times, uuids sequtils, sets, strutils, sugar, tempfile, terminal, times, uuids
import timeutils except `-` import timeutils except `-`
@ -43,8 +43,7 @@ proc writeMarks(timeline: Timeline, indices: seq[int], includeNotes = false): vo
writeLine(stdout, "No marks match the given criteria.") writeLine(stdout, "No marks match the given criteria.")
return return
var idxs = indices.sorted( var idxs = indices.sorted((a, b) => cmp(marks[a].time, marks[b].time))
proc(a, b: int): int = cmp(marks[a].time, marks[b].time))
let largestInterval = now - marks[idxs.first].time let largestInterval = now - marks[idxs.first].time
let timeFormat = let timeFormat =
@ -149,7 +148,8 @@ proc edit(mark: Mark): Mark =
close(tempFile) close(tempFile)
tempFile = nil tempFile = nil
discard os.execShellCmd "$EDITOR " & tempFileName & " </dev/tty >/dev/tty" let editor = getEnv("EDITOR", "vim")
discard os.execShellCmd editor & " " & tempFileName & " </dev/tty >/dev/tty"
var markPart = Time var markPart = Time
var notes: seq[string] = @[] var notes: seq[string] = @[]
@ -278,8 +278,9 @@ Options:
-e --edit Open the mark in an editor. -e --edit Open the mark in an editor.
-f --file <file> Use the given timeline file. -f --file <file> Use the given timeline file.
-g --tags <tags> Add the given tags (comma-separated) to the selected marks. -g --tags <tags> Add the given tags (comma-separated) to the selected marks.
-G --remove-tags <tagx> Remove the given tag from the selected marks. -G --remove-tags <tags> Remove the given tag from the selected marks.
-h --help Print this usage information. -h --help Print this usage information.
-m --matching <pattern> Restric the selection to marks matching <pattern>. -m --matching <pattern> Restric the selection to marks matching <pattern>.
-n --notes <notes> For add and amend, set the notes for a time mark. -n --notes <notes> For add and amend, set the notes for a time mark.
-t --time <time> For add and amend, use this time instead of the current time. -t --time <time> For add and amend, use this time instead of the current time.
@ -490,8 +491,7 @@ Options:
mark.tags = mark.tags.deduplicate mark.tags = mark.tags.deduplicate
if args["--remove-tags"]: if args["--remove-tags"]:
let tagsToRemove = (args["--remove-tags"] ?: "").split({',', ';'}) let tagsToRemove = (args["--remove-tags"] ?: "").split({',', ';'})
mark.tags = mark.tags.filter(proc (t: string): bool = mark.tags = mark.tags.filter((t) => not anyIt(tagsToRemove, it == t))
anyIt(tagsToRemove, it == t))
if args["--time"]: if args["--time"]:
try: mark.time = parseTime($args["--time"]) try: mark.time = parseTime($args["--time"])
except: raise newException(ValueError, except: raise newException(ValueError,

View File

@ -1,6 +1,6 @@
# Package # Package
version = "1.0.7" version = "1.0.10"
author = "Jonathan Bernard" author = "Jonathan Bernard"
description = "Personal Time Keeper" description = "Personal Time Keeper"
license = "MIT" license = "MIT"
@ -16,10 +16,10 @@ requires @[
"isaac >= 0.1.3", "isaac >= 0.1.3",
"bcrypt", "bcrypt",
"jester 0.5.0", "jester 0.5.0",
"https://git.jdb-labs.com/jdb/nim-lang-utils.git", "https://git.jdb-software.com/jdb/nim-lang-utils.git",
"https://git.jdb-labs.com/jdb/nim-cli-utils.git >= 0.6.5", "https://git.jdb-software.com/jdb/nim-cli-utils.git >= 0.6.5",
"https://git.jdb-labs.com/jdb/nim-time-utils.git >= 0.5.2", "https://git.jdb-software.com/jdb/nim-time-utils.git >= 0.5.2",
"https://git.jdb-labs.com/jdb/update-nim-package-version" "https://git.jdb-software.com/jdb/update-nim-package-version"
] ]
task updateVersion, "Update the version of this package.": task updateVersion, "Update the version of this package.":