Compare commits
4 Commits
40cb602362
...
8b0c751344
Author | SHA1 | Date | |
---|---|---|---|
8b0c751344 | |||
0f7e257f76 | |||
76225d1c50 | |||
0361d1b869 |
@ -1,6 +1,6 @@
|
|||||||
# Package
|
# Package
|
||||||
|
|
||||||
version = "4.28.0"
|
version = "4.29.0"
|
||||||
author = "Jonathan Bernard"
|
author = "Jonathan Bernard"
|
||||||
description = "Personal issue tracker."
|
description = "Personal issue tracker."
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
25
src/pit.nim
25
src/pit.nim
@ -67,6 +67,9 @@ when isMainModule:
|
|||||||
if args["--debug"]:
|
if args["--debug"]:
|
||||||
consoleLogger.levelThreshold = lvlDebug
|
consoleLogger.levelThreshold = lvlDebug
|
||||||
|
|
||||||
|
if args["--silent"]:
|
||||||
|
consoleLogger.levelThreshold = lvlNone
|
||||||
|
|
||||||
if args["--echo-args"]: stderr.writeLine($args)
|
if args["--echo-args"]: stderr.writeLine($args)
|
||||||
|
|
||||||
if args["help"]:
|
if args["help"]:
|
||||||
@ -78,6 +81,7 @@ when isMainModule:
|
|||||||
|
|
||||||
trace "context initiated"
|
trace "context initiated"
|
||||||
|
|
||||||
|
var updatedIssues = newSeq[Issue]()
|
||||||
var propertiesOption = none(TableRef[string,string])
|
var propertiesOption = none(TableRef[string,string])
|
||||||
var exclPropsOption = none(TableRef[string,seq[string]])
|
var exclPropsOption = none(TableRef[string,seq[string]])
|
||||||
var tagsOption = none(seq[string])
|
var tagsOption = none(seq[string])
|
||||||
@ -133,7 +137,7 @@ when isMainModule:
|
|||||||
else: newSeq[string]())
|
else: newSeq[string]())
|
||||||
|
|
||||||
ctx.cfg.tasksDir.store(issue, state)
|
ctx.cfg.tasksDir.store(issue, state)
|
||||||
|
updatedIssues.add(issue)
|
||||||
stdout.writeLine formatIssue(issue)
|
stdout.writeLine formatIssue(issue)
|
||||||
|
|
||||||
elif args["reorder"]:
|
elif args["reorder"]:
|
||||||
@ -160,6 +164,7 @@ when isMainModule:
|
|||||||
for k,v in propsOption.get:
|
for k,v in propsOption.get:
|
||||||
issue[k] = v
|
issue[k] = v
|
||||||
edit(issue)
|
edit(issue)
|
||||||
|
updatedIssues.add(issue)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
let issue = ctx.cfg.tasksDir.loadIssueById(editRef)
|
let issue = ctx.cfg.tasksDir.loadIssueById(editRef)
|
||||||
@ -167,6 +172,7 @@ when isMainModule:
|
|||||||
for k,v in propertiesOption.get:
|
for k,v in propertiesOption.get:
|
||||||
issue[k] = v
|
issue[k] = v
|
||||||
edit(issue)
|
edit(issue)
|
||||||
|
updatedIssues.add(issue)
|
||||||
|
|
||||||
elif args["tag"]:
|
elif args["tag"]:
|
||||||
if tagsOption.isNone: raise newException(Exception, "no tags given")
|
if tagsOption.isNone: raise newException(Exception, "no tags given")
|
||||||
@ -177,6 +183,7 @@ when isMainModule:
|
|||||||
var issue = ctx.cfg.tasksDir.loadIssueById(id)
|
var issue = ctx.cfg.tasksDir.loadIssueById(id)
|
||||||
issue.tags = deduplicate(issue.tags & newTags)
|
issue.tags = deduplicate(issue.tags & newTags)
|
||||||
issue.store()
|
issue.store()
|
||||||
|
updatedIssues.add(issue)
|
||||||
|
|
||||||
elif args["untag"]:
|
elif args["untag"]:
|
||||||
let tagsToRemove: seq[string] =
|
let tagsToRemove: seq[string] =
|
||||||
@ -190,6 +197,7 @@ when isMainModule:
|
|||||||
proc (tag: string): bool = not tagsToRemove.anyIt(it == tag))
|
proc (tag: string): bool = not tagsToRemove.anyIt(it == tag))
|
||||||
else: issue.tags = @[]
|
else: issue.tags = @[]
|
||||||
issue.store()
|
issue.store()
|
||||||
|
updatedIssues.add(issue)
|
||||||
|
|
||||||
elif args["start"] or args["todo-today"] or args["done"] or
|
elif args["start"] or args["todo-today"] or args["done"] or
|
||||||
args["pending"] or args["todo"] or args["suspend"]:
|
args["pending"] or args["todo"] or args["suspend"]:
|
||||||
@ -213,10 +221,12 @@ when isMainModule:
|
|||||||
let nextIssue = ctx.cfg.tasksDir.nextRecurrence(issue.getRecurrence.get, issue)
|
let nextIssue = ctx.cfg.tasksDir.nextRecurrence(issue.getRecurrence.get, issue)
|
||||||
ctx.cfg.tasksDir.store(nextIssue, TodoToday)
|
ctx.cfg.tasksDir.store(nextIssue, TodoToday)
|
||||||
info "created the next recurrence:"
|
info "created the next recurrence:"
|
||||||
|
updatedIssues.add(nextIssue)
|
||||||
stdout.writeLine formatIssue(nextIssue)
|
stdout.writeLine formatIssue(nextIssue)
|
||||||
|
|
||||||
|
|
||||||
issue.changeState(ctx.cfg.tasksDir, targetState)
|
issue.changeState(ctx.cfg.tasksDir, targetState)
|
||||||
|
updatedIssues.add(issue)
|
||||||
|
|
||||||
if ctx.triggerPtk or args["--ptk"]:
|
if ctx.triggerPtk or args["--ptk"]:
|
||||||
if targetState == Current:
|
if targetState == Current:
|
||||||
@ -241,6 +251,7 @@ when isMainModule:
|
|||||||
issue.setDateTime("hide-until", parseDate($args["<date>"]))
|
issue.setDateTime("hide-until", parseDate($args["<date>"]))
|
||||||
|
|
||||||
issue.store()
|
issue.store()
|
||||||
|
updatedIssues.add(issue)
|
||||||
|
|
||||||
elif args["delegate"]:
|
elif args["delegate"]:
|
||||||
|
|
||||||
@ -248,6 +259,7 @@ when isMainModule:
|
|||||||
issue["delegated-to"] = $args["<delegated-to>"]
|
issue["delegated-to"] = $args["<delegated-to>"]
|
||||||
|
|
||||||
issue.store()
|
issue.store()
|
||||||
|
updatedIssues.add(issue)
|
||||||
|
|
||||||
elif args["delete"] or args["rm"]:
|
elif args["delete"] or args["rm"]:
|
||||||
for id in @(args["<id>"]):
|
for id in @(args["<id>"]):
|
||||||
@ -260,6 +272,7 @@ when isMainModule:
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
issue.delete
|
issue.delete
|
||||||
|
updatedIssues.add(issue)
|
||||||
|
|
||||||
elif args["list"]:
|
elif args["list"]:
|
||||||
|
|
||||||
@ -382,6 +395,7 @@ when isMainModule:
|
|||||||
finally: close(propIn)
|
finally: close(propIn)
|
||||||
|
|
||||||
issue.store()
|
issue.store()
|
||||||
|
updatedIssues.add(issue)
|
||||||
|
|
||||||
elif args["get-binary-property"]:
|
elif args["get-binary-property"]:
|
||||||
let issue = ctx.cfg.tasksDir.loadIssueById($(args["<id>"]))
|
let issue = ctx.cfg.tasksDir.loadIssueById($(args["<id>"]))
|
||||||
@ -422,6 +436,15 @@ when isMainModule:
|
|||||||
|
|
||||||
sync(syncCtx, args["--dry-run"])
|
sync(syncCtx, args["--dry-run"])
|
||||||
|
|
||||||
|
# after doing stuff, sync if auto-sync is requested
|
||||||
|
if ctx.cfg.autoSync:
|
||||||
|
for syncTarget in ctx.cfg.syncTargets:
|
||||||
|
let syncCtx = initSyncContext(ctx.cfg, syncTarget)
|
||||||
|
if anyIt(
|
||||||
|
updatedIssues,
|
||||||
|
it.hasProp("context") and it["context"] == syncCtx.issueContext):
|
||||||
|
sync(syncCtx, false)
|
||||||
|
|
||||||
except CatchableError:
|
except CatchableError:
|
||||||
fatal getCurrentExceptionMsg()
|
fatal getCurrentExceptionMsg()
|
||||||
debug getCurrentException().getStackTrace()
|
debug getCurrentException().getStackTrace()
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
const PIT_VERSION* = "4.28.0"
|
const PIT_VERSION* = "4.29.0"
|
||||||
|
|
||||||
const USAGE* = """Usage:
|
const USAGE* = """Usage:
|
||||||
pit ( new | add) <summary> [<state>] [options]
|
pit ( new | add) <summary> [<state>] [options]
|
||||||
@ -82,6 +82,8 @@ Options:
|
|||||||
--dry-run Currently only supported by the `sync` command:
|
--dry-run Currently only supported by the `sync` command:
|
||||||
only print the changes that would be made, but do
|
only print the changes that would be made, but do
|
||||||
not actually make them.
|
not actually make them.
|
||||||
|
|
||||||
|
-s, --silent Suppress all logging and status output.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
const ONLINE_HELP* = """Issue States:
|
const ONLINE_HELP* = """Issue States:
|
||||||
|
@ -3,6 +3,8 @@ import cliutils, uuids
|
|||||||
import std/strutils except alignLeft, capitalize, strip, toLower, toUpper
|
import std/strutils except alignLeft, capitalize, strip, toLower, toUpper
|
||||||
import ./libpit
|
import ./libpit
|
||||||
|
|
||||||
|
proc adjustedTerminalWidth(): int = min(terminalWidth(), 80)
|
||||||
|
|
||||||
proc getIssueContextDisplayName*(ctx: CliContext, context: string): string =
|
proc getIssueContextDisplayName*(ctx: CliContext, context: string): string =
|
||||||
if not ctx.contexts.hasKey(context):
|
if not ctx.contexts.hasKey(context):
|
||||||
if context.isEmptyOrWhitespace: return "<default>"
|
if context.isEmptyOrWhitespace: return "<default>"
|
||||||
@ -128,11 +130,11 @@ proc formatSectionIssueList*(
|
|||||||
|
|
||||||
proc formatSection(ctx: CliContext, issues: seq[Issue], state: IssueState,
|
proc formatSection(ctx: CliContext, issues: seq[Issue], state: IssueState,
|
||||||
indent = "", verbose = false): string =
|
indent = "", verbose = false): string =
|
||||||
let innerWidth = terminalWidth() - (indent.len * 2)
|
let innerWidth = adjustedTerminalWidth() - (indent.len * 2)
|
||||||
|
|
||||||
result = termColor(fgBlue) &
|
result = termColor(fgBlue) &
|
||||||
(indent & ".".repeat(innerWidth)) & "\n" &
|
(indent & ".".repeat(innerWidth)) & "\n" &
|
||||||
state.displayName.center(terminalWidth()) & "\n\n" &
|
state.displayName.center(adjustedTerminalWidth()) & "\n\n" &
|
||||||
termReset
|
termReset
|
||||||
|
|
||||||
let issuesByContext = issues.groupBy("context")
|
let issuesByContext = issues.groupBy("context")
|
||||||
@ -152,9 +154,9 @@ proc formatSection(ctx: CliContext, issues: seq[Issue], state: IssueState,
|
|||||||
|
|
||||||
proc writeHeader*(ctx: CliContext, header: string) =
|
proc writeHeader*(ctx: CliContext, header: string) =
|
||||||
stdout.setForegroundColor(fgRed, true)
|
stdout.setForegroundColor(fgRed, true)
|
||||||
stdout.writeLine('_'.repeat(terminalWidth()))
|
stdout.writeLine('_'.repeat(adjustedTerminalWidth()))
|
||||||
stdout.writeLine(header.center(terminalWidth()))
|
stdout.writeLine(header.center(adjustedTerminalWidth()))
|
||||||
stdout.writeLine('~'.repeat(terminalWidth()))
|
stdout.writeLine('~'.repeat(adjustedTerminalWidth()))
|
||||||
stdout.resetAttributes
|
stdout.resetAttributes
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ type
|
|||||||
PitConfig* = ref object
|
PitConfig* = ref object
|
||||||
tasksDir*: string
|
tasksDir*: string
|
||||||
contexts*: TableRef[string, string]
|
contexts*: TableRef[string, string]
|
||||||
|
autoSync*: bool
|
||||||
syncTargets*: seq[JsonNode]
|
syncTargets*: seq[JsonNode]
|
||||||
cfg*: CombinedConfig
|
cfg*: CombinedConfig
|
||||||
|
|
||||||
@ -459,6 +460,7 @@ proc loadConfig*(args: Table[string, Value] = initTable[string, Value]()): PitCo
|
|||||||
|
|
||||||
result = PitConfig(
|
result = PitConfig(
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
|
autoSync: parseBool(cfg.getVal("auto-sync", "false")),
|
||||||
contexts: newTable[string,string](),
|
contexts: newTable[string,string](),
|
||||||
tasksDir: cfg.getVal("tasks-dir", ""),
|
tasksDir: cfg.getVal("tasks-dir", ""),
|
||||||
syncTargets: cfg.getJson("sync-targets", newJArray()).getElems)
|
syncTargets: cfg.getJson("sync-targets", newJArray()).getElems)
|
||||||
|
@ -4,11 +4,11 @@ import timeutils, uuids, zero_functional
|
|||||||
import ./formatting, ./libpit
|
import ./formatting, ./libpit
|
||||||
|
|
||||||
type
|
type
|
||||||
PbmVsbSyncContext = object
|
PbmVsbSyncContext* = object
|
||||||
|
apiBaseUrl*: string
|
||||||
|
apiToken*: string
|
||||||
|
issueContext*: string
|
||||||
pit: PitConfig
|
pit: PitConfig
|
||||||
apiBaseUrl: string
|
|
||||||
apiToken: string
|
|
||||||
issueContext: string
|
|
||||||
http: HttpClient
|
http: HttpClient
|
||||||
|
|
||||||
ServerTask* = object
|
ServerTask* = object
|
||||||
@ -117,7 +117,6 @@ proc sync*(
|
|||||||
dryRun = true,
|
dryRun = true,
|
||||||
batchSize = 100): void =
|
batchSize = 100): void =
|
||||||
|
|
||||||
if not dryRun: echo "NOT DRY RUN"
|
|
||||||
# We're going to do a uni-directional sync, pushing local issues to the
|
# We're going to do a uni-directional sync, pushing local issues to the
|
||||||
# server. However, we only want to update issues that have changed since
|
# server. However, we only want to update issues that have changed since
|
||||||
# the last sync based on the *last-updated* property.
|
# the last sync based on the *last-updated* property.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user