4 Commits
0.3.0 ... 0.6.0

Author SHA1 Message Date
237f5026f2 Added merge command. 2016-10-23 17:31:27 -05:00
3cf76ef382 Add --this-week, --last-week options 2016-10-21 15:42:48 -05:00
e0618f6520 Add some alternate time formats. 2016-10-13 06:31:51 -05:00
915c5b1ea1 Added --today flag. 2016-10-12 16:30:32 -05:00
3 changed files with 58 additions and 10 deletions

60
ptk.nim
View File

@ -4,7 +4,7 @@
## Simple time keeping CLI ## Simple time keeping CLI
import algorithm, docopt, json, langutils, logging, os, nre, sequtils, import algorithm, docopt, json, langutils, logging, os, nre, sequtils,
strutils, tempfile, terminal, times, timeutils, uuids sets, strutils, tempfile, terminal, times, timeutils, uuids
import ptkutil import ptkutil
@ -23,7 +23,8 @@ const ISO_TIME_FORMAT = "yyyy:MM:dd'T'HH:mm:ss"
const TIME_FORMATS = @[ const TIME_FORMATS = @[
"H:mm", "HH:mm", "H:mm:ss", "HH:mm:ss", "H:mm", "HH:mm", "H:mm:ss", "HH:mm:ss",
"yyyy:MM:dd'T'HH:mm:ss", "yyyy:MM:dd'T'HH:mm"] "yyyy:MM:dd'T'HH:mm:ss", "yyyy:MM:dd'T'HH:mm",
"yyyy:MM:dd HH:mm:ss", "yyyy:MM:dd HH:mm"]
#proc `$`*(mark: Mark): string = #proc `$`*(mark: Mark): string =
#return (($mark.uuid)[ #return (($mark.uuid)[
@ -99,10 +100,11 @@ proc writeMarks(timeline: Timeline, indices: seq[int], includeNotes = false): vo
var idxs = indices.sorted( var idxs = indices.sorted(
proc(a, b: int): int = 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 timeFormat = let timeFormat =
if now - marks[idxs.first].time > 1.years: "yyyy-MM-dd HH:mm" if largestInterval > 1.years: "yyyy-MM-dd HH:mm"
elif now - marks[idxs.first].time > 7.days: "MMM dd HH:mm" elif largestInterval > 7.days: "MMM dd HH:mm"
elif now - marks[idxs.first].time > 1.days: "ddd HH:mm" elif largestInterval > 1.days: "ddd HH:mm"
else: "HH:mm" else: "HH:mm"
var toWrite: seq[WriteData] = @[] var toWrite: seq[WriteData] = @[]
@ -254,6 +256,24 @@ proc filterMarkIndices(timeline: Timeline, args: Table[string, Value]): seq[int]
"invalid value for --before: " & getCurrentExceptionMsg()) "invalid value for --before: " & getCurrentExceptionMsg())
result = result.filterIt(marks[it].time < endTime) result = result.filterIt(marks[it].time < endTime)
if args["--today"]:
let now = getLocalTime(getTime())
let b = now.startOfDay
let e = b + 1.days
result = result.filterIt(marks[it].time >= b and marks[it].time < e)
if args["--this-week"]:
let now = getLocalTime(getTime())
let b = now.startOfWeek(dSun)
let e = b + 7.days
result = result.filterIt(marks[it].time >= b and marks[it].time < e)
if args["--last-week"]:
let now = getLocalTime(getTime())
let e = now.startOfWeek(dSun)
let b = e - 7.days
result = result.filterIt(marks[it].time >= b and marks[it].time < e)
if args["--tags"]: if args["--tags"]:
let tags = (args["--tags"] ?: "").split({',', ';'}) let tags = (args["--tags"] ?: "").split({',', ';'})
result = result.filter(proc (i: int): bool = result = result.filter(proc (i: int): bool =
@ -276,6 +296,7 @@ Usage:
ptk add [options] ptk add [options]
ptk add [options] <summary> ptk add [options] <summary>
ptk amend [options] <id> [<summary>] ptk amend [options] <id> [<summary>]
ptk merge <timeline> [<timeline>...]
ptk stop [options] ptk stop [options]
ptk continue ptk continue
ptk delete <id> ptk delete <id>
@ -300,6 +321,9 @@ Options:
-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.
-T --today Restrict the selection to marks during today.
-w --this-week Restrict the selection to marks during this week.
-W --last-week Restrict the selection to marks during the last week.
-v --verbose Include notes in timeline entry output. -v --verbose Include notes in timeline entry output.
""" """
@ -309,7 +333,7 @@ Options:
let now = getLocalTime(getTime()) let now = getLocalTime(getTime())
# Parse arguments # Parse arguments
let args = docopt(doc, version = "ptk 0.3.0") let args = docopt(doc, version = "ptk 0.6.0")
if args["--echo-args"]: echo $args if args["--echo-args"]: echo $args
@ -355,6 +379,30 @@ Options:
if args["init"]: if args["init"]:
doInit(foldl(timelineLocations, if len(a) > 0: a else: b)) doInit(foldl(timelineLocations, if len(a) > 0: a else: b))
elif args["merge"]:
let filesToMerge = args["<timeline>"]
let timelines = filesToMerge.mapIt(loadTimeline(it))
let names = timelines.mapIt(it.name).toSet
let mergedName = sequtils.toSeq(names.items).foldl(a & " + " & b)
var merged: Timeline = (
name: mergedName,
marks: @[])
for timeline in timelines:
for mark in timeline.marks:
var existingMarkIdx = merged.marks.findById($mark.id)
if existingMarkIdx >= 0:
if merged.marks[existingMarkIdx].summary != mark.summary:
merged.marks[existingMarkIdx].summary &= " | " & mark.summary
if merged.marks[existingMarkIdx].notes != mark.notes:
merged.marks[existingMarkIdx].notes &= "\r\n--------\r\b" & mark.notes
else: merged.marks.add(mark)
writeLine(stdout, pretty(%merged))
else: else:
if not fileExists(timelineLocation): if not fileExists(timelineLocation):

View File

@ -1,6 +1,6 @@
# Package # Package
version = "0.3.0" version = "0.6.0"
author = "Jonathan Bernard" author = "Jonathan Bernard"
description = "Personal Time Keeper" description = "Personal Time Keeper"
license = "MIT" license = "MIT"
@ -8,5 +8,5 @@ bin = @["ptk"]
# Dependencies # Dependencies
requires @["nim >= 0.15.0", "docopt >= 0.6.4", "uuids", "langutils", "tempfile", "timeutils"] requires @["nim >= 0.15.0", "docopt >= 0.6.4", "uuids", "langutils", "tempfile", "timeutils >= 0.2.0"]

View File

@ -1,3 +1,3 @@
template first*(s: seq): auto = s[0] template first*(a: openarray): auto = a[0]
template last*(s: seq): auto = s[len(s)-1] template last*(a: openarray): auto = a[len(a)-1]