|
|
|
@ -6,7 +6,7 @@
|
|
|
|
|
import algorithm, docopt, json, langutils, logging, os, nre, sequtils,
|
|
|
|
|
sets, strutils, tempfile, terminal, times, timeutils, uuids
|
|
|
|
|
|
|
|
|
|
import ptkutil
|
|
|
|
|
import private/ptkutil
|
|
|
|
|
|
|
|
|
|
type
|
|
|
|
|
Mark* = tuple[id: UUID, time: TimeInfo, summary: string, notes: string, tags: seq[string]]
|
|
|
|
@ -154,6 +154,9 @@ proc writeMarks(timeline: Timeline, indices: seq[int], includeNotes = false): vo
|
|
|
|
|
|
|
|
|
|
if prefix.len > longestPrefix: longestPrefix = prefix.len
|
|
|
|
|
|
|
|
|
|
let colWidth = 80
|
|
|
|
|
let notesPrefixLen = 4
|
|
|
|
|
|
|
|
|
|
for w in toWrite:
|
|
|
|
|
if w.mark.summary == STOP_MSG: continue
|
|
|
|
|
|
|
|
|
@ -174,7 +177,11 @@ proc writeMarks(timeline: Timeline, indices: seq[int], includeNotes = false): vo
|
|
|
|
|
writeLine(stdout, "")
|
|
|
|
|
|
|
|
|
|
if includeNotes and len(w.mark.notes.strip) > 0:
|
|
|
|
|
writeLine(stdout, spaces(longestPrefix) & w.mark.notes)
|
|
|
|
|
writeLine(stdout, "")
|
|
|
|
|
let wrappedNotes = wordWrap(s = w.mark.notes,
|
|
|
|
|
maxLineWidth = colWidth)
|
|
|
|
|
for line in splitLines(wrappedNotes):
|
|
|
|
|
writeLine(stdout, spaces(notesPrefixLen) & line)
|
|
|
|
|
writeLine(stdout, "")
|
|
|
|
|
|
|
|
|
|
proc formatMark(mark: Mark, nextMark = NO_MARK, timeFormat = ISO_TIME_FORMAT, includeNotes = false): string =
|
|
|
|
@ -190,13 +197,12 @@ proc formatMark(mark: Mark, nextMark = NO_MARK, timeFormat = ISO_TIME_FORMAT, in
|
|
|
|
|
# TODO: pick up here calculating the time between marks
|
|
|
|
|
|
|
|
|
|
let prefix = ($mark.id)[0..<8] & " " & mark.time.format(timeFormat) & " (" & duration & ") -- "
|
|
|
|
|
let prefixLen = len(($mark.id)[0..<8] & " " & mark.time.format(timeFormat) & " (" & duration & ") -- ")
|
|
|
|
|
|
|
|
|
|
result = prefix & mark.summary
|
|
|
|
|
if includeNotes and len(mark.notes.strip()) > 0:
|
|
|
|
|
let wrappedNotes = wordWrap(s = mark.notes, maxLineWidth = 80 - prefixLen)
|
|
|
|
|
let wrappedNotes = wordWrap(s = mark.notes, maxLineWidth = 80 - prefix.len)
|
|
|
|
|
for line in splitLines(wrappedNotes):
|
|
|
|
|
result &= "\x0D\x0A" & spaces(prefixLen) & line
|
|
|
|
|
result &= "\x0D\x0A" & spaces(prefix.len) & line
|
|
|
|
|
result &= "\x0D\x0A"
|
|
|
|
|
|
|
|
|
|
proc findById(marks: seq[Mark], id: string): int =
|
|
|
|
@ -338,8 +344,8 @@ when isMainModule:
|
|
|
|
|
let doc = """
|
|
|
|
|
Usage:
|
|
|
|
|
ptk init [options]
|
|
|
|
|
ptk add [options]
|
|
|
|
|
ptk add [options] <summary>
|
|
|
|
|
ptk (add | start) [options]
|
|
|
|
|
ptk (add | start) [options] <summary>
|
|
|
|
|
ptk resume [options] [<id>]
|
|
|
|
|
ptk amend [options] [<id>] [<summary>]
|
|
|
|
|
ptk merge <timeline> [<timeline>...]
|
|
|
|
@ -347,6 +353,8 @@ Usage:
|
|
|
|
|
ptk continue
|
|
|
|
|
ptk delete <id>
|
|
|
|
|
ptk (list | ls) [options]
|
|
|
|
|
ptk (list | ls) tags
|
|
|
|
|
ptk current
|
|
|
|
|
ptk sum-time --ids <ids>...
|
|
|
|
|
ptk sum-time [options] [<firstId>] [<lastId>]
|
|
|
|
|
ptk (-V | --version)
|
|
|
|
@ -379,7 +387,7 @@ Options:
|
|
|
|
|
let now = getLocalTime(getTime())
|
|
|
|
|
|
|
|
|
|
# Parse arguments
|
|
|
|
|
let args = docopt(doc, version = "ptk 0.8.0")
|
|
|
|
|
let args = docopt(doc, version = "ptk 0.11.3")
|
|
|
|
|
|
|
|
|
|
if args["--echo-args"]: echo $args
|
|
|
|
|
|
|
|
|
@ -464,7 +472,7 @@ Options:
|
|
|
|
|
time: if args["--time"]: parseTime($args["--time"]) else: now,
|
|
|
|
|
summary: STOP_MSG,
|
|
|
|
|
notes: args["--notes"] ?: "",
|
|
|
|
|
tags: (args["--tags"] ?: "").split({',', ';'}))
|
|
|
|
|
tags: (args["--tags"] ?: "").split({',', ';'}).filterIt(not it.isNilOrWhitespace))
|
|
|
|
|
|
|
|
|
|
timeline.marks.add(newMark)
|
|
|
|
|
|
|
|
|
@ -499,21 +507,22 @@ Options:
|
|
|
|
|
|
|
|
|
|
saveTimeline(timeline, timelineLocation)
|
|
|
|
|
|
|
|
|
|
if args["add"]:
|
|
|
|
|
if args["add"] or args["start"]:
|
|
|
|
|
|
|
|
|
|
var newMark: Mark = (
|
|
|
|
|
id: genUUID(),
|
|
|
|
|
time: if args["--time"]: parseTime($args["--time"]) else: now,
|
|
|
|
|
summary: args["<summary>"] ?: "",
|
|
|
|
|
notes: args["--notes"] ?: "",
|
|
|
|
|
tags: (args["--tags"] ?: "").split({',', ';'}))
|
|
|
|
|
tags: (args["--tags"] ?: "").split({',', ';'}).filterIt(not it.isNilOrWhitespace))
|
|
|
|
|
|
|
|
|
|
if args["--edit"]: edit(newMark)
|
|
|
|
|
|
|
|
|
|
let prevLastIdx = timeline.marks.getLastIndex()
|
|
|
|
|
timeline.marks.add(newMark)
|
|
|
|
|
timeline.writeMarks(
|
|
|
|
|
indices = @[prevLastIdx, timeline.marks.len - 1],
|
|
|
|
|
indices = if prevLastIdx < 0: @[0]
|
|
|
|
|
else: @[prevLastIdx, timeline.marks.len - 1],
|
|
|
|
|
includeNotes = args["--verbose"])
|
|
|
|
|
|
|
|
|
|
saveTimeline(timeline, timelineLocation)
|
|
|
|
@ -525,7 +534,9 @@ Options:
|
|
|
|
|
if args["<id>"]:
|
|
|
|
|
markToResumeIdx = timeline.marks.findById($args["<id>"])
|
|
|
|
|
if markToResumeIdx == -1: exitErr "Cannot find a mark matching " & $args["<id>"]
|
|
|
|
|
else: markToResumeIdx = timeline.marks.getLastIndex()
|
|
|
|
|
else:
|
|
|
|
|
markToResumeIdx = timeline.marks.getLastIndex()
|
|
|
|
|
if markToResumeIdx < 0: exitErr "No mark to resume."
|
|
|
|
|
var markToResume = timeline.marks[markToResumeIdx]
|
|
|
|
|
|
|
|
|
|
var newMark: Mark = (
|
|
|
|
@ -552,7 +563,9 @@ Options:
|
|
|
|
|
if args["<id>"]:
|
|
|
|
|
markIdx = timeline.marks.findById($args["<id>"])
|
|
|
|
|
if markIdx == -1: exitErr "Cannot find a mark matching " & $args["<id>"]
|
|
|
|
|
else: markIdx = timeline.marks.getLastIndex()
|
|
|
|
|
else:
|
|
|
|
|
markIdx = timeline.marks.getLastIndex()
|
|
|
|
|
if markIdx < 0: exitErr "No mark to amend."
|
|
|
|
|
|
|
|
|
|
var mark = timeline.marks[markIdx]
|
|
|
|
|
|
|
|
|
@ -590,11 +603,27 @@ Options:
|
|
|
|
|
|
|
|
|
|
if args["list"] or args["ls"]:
|
|
|
|
|
|
|
|
|
|
var selectedIndices = timeline.filterMarkIndices(args)
|
|
|
|
|
if args["tags"]:
|
|
|
|
|
|
|
|
|
|
timeline.writeMarks(
|
|
|
|
|
indices = selectedIndices,
|
|
|
|
|
includeNotes = args["--version"])
|
|
|
|
|
echo $(timeline.marks.mapIt(it.tags)
|
|
|
|
|
.flatten().deduplicate().sorted(system.cmp).join("\n"))
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
var selectedIndices = timeline.filterMarkIndices(args)
|
|
|
|
|
|
|
|
|
|
timeline.writeMarks(
|
|
|
|
|
indices = selectedIndices,
|
|
|
|
|
includeNotes = args["--verbose"])
|
|
|
|
|
|
|
|
|
|
if args["current"]:
|
|
|
|
|
|
|
|
|
|
let idx = timeline.marks.len - 1
|
|
|
|
|
if timeline.marks[idx].summary == STOP_MSG:
|
|
|
|
|
echo "ptk: no current task"
|
|
|
|
|
else:
|
|
|
|
|
timeline.writeMarks(
|
|
|
|
|
indices = @[idx],
|
|
|
|
|
includeNotes = true)
|
|
|
|
|
|
|
|
|
|
if args["sum-time"]:
|
|
|
|
|
|
|
|
|
|