Compare commits

..

3 Commits
4.0.0 ... 4.0.3

Author SHA1 Message Date
28569a643e Added Dormant state, auto-create task dirs.
The Dormant state is for tasks that are still outstanding but not of
immediate importance. The main different between Dormant and Todo is
that dormant tasks are not listed by default. You must
`pit list dormant` to see them.
2018-05-14 09:53:15 -05:00
97eb286e32 Reorganize project folder structure to work according to nimble package expectations. 2018-05-14 09:36:23 -05:00
fcab7a4cc6 Added add (alias for new) and delete. 2018-05-14 09:28:50 -05:00
3 changed files with 38 additions and 12 deletions

View File

@ -1,6 +1,6 @@
# Package # Package
version = "4.0.0" version = "4.0.3"
author = "Jonathan Bernard" author = "Jonathan Bernard"
description = "Personal issue tracker." description = "Personal issue tracker."
license = "MIT" license = "MIT"

View File

@ -5,8 +5,8 @@
import cliutils, docopt, json, logging, options, os, ospaths, sequtils, import cliutils, docopt, json, logging, options, os, ospaths, sequtils,
tables, terminal, times, unicode, uuids tables, terminal, times, unicode, uuids
import strutils except capitalize import strutils except capitalize, toUpper, toLower
import pit/private/libpit import pitpkg/private/libpit
export libpit export libpit
type type
@ -225,10 +225,11 @@ when isMainModule:
try: try:
let doc = """ let doc = """
Usage: Usage:
pit new <summary> [<state>] [options] pit ( new | add) <summary> [<state>] [options]
pit list [<state>] [options] pit list [<state>] [options]
pit ( start | done | pending | do-today | todo ) <id>... pit ( start | done | pending | do-today | todo | suspend ) <id>...
pit edit <id> pit edit <id>
pit delete <id>...
Options: Options:
@ -245,6 +246,8 @@ Options:
-F, --future Limit to future issues. -F, --future Limit to future issues.
-y, --yes Automatically answer "yes" to any prompts.
-C, --config <cfgFile> Location of the config file (defaults to $HOME/.pitrc) -C, --config <cfgFile> Location of the config file (defaults to $HOME/.pitrc)
-E, --echo-args Echo arguments (for debug purposes). -E, --echo-args Echo arguments (for debug purposes).
@ -258,7 +261,7 @@ Options:
logging.addHandler(newConsoleLogger()) logging.addHandler(newConsoleLogger())
# Parse arguments # Parse arguments
let args = docopt(doc, version = "pit 4.0.0") let args = docopt(doc, version = "pit 4.0.3")
if args["--echo-args"]: stderr.writeLine($args) if args["--echo-args"]: stderr.writeLine($args)
@ -268,8 +271,13 @@ Options:
let ctx = initContext(args) let ctx = initContext(args)
# Create our tasks directory structure if needed
for s in IssueState:
if not existsDir(ctx.tasksDir / $s):
(ctx.tasksDir / $s).createDir
## Actual command runners ## Actual command runners
if args["new"]: if args["new"] or args["add"]:
let state = let state =
if args["<state>"]: parseEnum[IssueState]($args["<state>"]) if args["<state>"]: parseEnum[IssueState]($args["<state>"])
else: TodoToday else: TodoToday
@ -292,7 +300,7 @@ Options:
edit(ctx.tasksDir.loadIssueById(issueId)) edit(ctx.tasksDir.loadIssueById(issueId))
elif args["start"] or args["do-today"] or args["done"] or elif args["start"] or args["do-today"] or args["done"] or
args["pending"] or args["todo"]: args["pending"] or args["todo"] or args["suspend"]:
var targetState: IssueState var targetState: IssueState
if args["done"]: targetState = Done if args["done"]: targetState = Done
@ -300,9 +308,10 @@ Options:
elif args["pending"]: targetState = Todo elif args["pending"]: targetState = Todo
elif args["start"]: targetState = Current elif args["start"]: targetState = Current
elif args["todo"]: targetState = Todo elif args["todo"]: targetState = Todo
elif args["suspend"]: targetState = Dormant
for id in @(args["<id>"]): for id in @(args["<id>"]):
ctx.tasksDir.moveIssue(ctx.tasksDir.loadIssueById(id), targetState) ctx.tasksDir.loadIssueById(id).changeState(ctx.tasksDir, targetState)
if ctx.triggerPtk: if ctx.triggerPtk:
if targetState == Current: if targetState == Current:
@ -313,6 +322,18 @@ Options:
discard execShellCmd(cmd) discard execShellCmd(cmd)
elif targetState == Done: discard execShellCmd("ptk stop") elif targetState == Done: discard execShellCmd("ptk stop")
elif args["delete"]:
for id in @(args["<id>"]):
let issue = ctx.tasksDir.loadIssueById(id)
if not args["--yes"]:
stderr.write("Delete '" & issue.summary & "' (y/n)? ")
if not "yes".startsWith(stdin.readLine.toLower):
continue
issue.delete
elif args["list"]: elif args["list"]:
let filter = initFilter() let filter = initFilter()

View File

@ -15,6 +15,7 @@ type
Pending = "pending", Pending = "pending",
Done = "done", Done = "done",
Todo = "todo" Todo = "todo"
Dormant = "dormant"
IssueFilter* = ref object IssueFilter* = ref object
properties*: TableRef[string, string] properties*: TableRef[string, string]
@ -27,8 +28,9 @@ let ISSUE_FILE_PATTERN = re"[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f
proc displayName*(s: IssueState): string = proc displayName*(s: IssueState): string =
case s case s
of Current: result = "Current" of Current: result = "Current"
of Pending: result = "Pending"
of Done: result = "Done" of Done: result = "Done"
of Dormant: result = "Dormant"
of Pending: result = "Pending"
of Todo: result = "Todo" of Todo: result = "Todo"
of TodoToday: result = "Todo" of TodoToday: result = "Todo"
@ -160,10 +162,13 @@ proc loadIssues*(path: string): seq[Issue] =
if extractFilename(path).match(ISSUE_FILE_PATTERN).isSome(): if extractFilename(path).match(ISSUE_FILE_PATTERN).isSome():
result.add(loadIssue(path)) result.add(loadIssue(path))
proc moveIssue*(tasksDir: string, issue: Issue, newState: IssueState) = proc changeState*(issue: Issue, tasksDir: string, newState: IssueState) =
removeFile(issue.filepath) let oldFilepath = issue.filepath
if newState == Done: issue.setDateTime("completed", getTime().local) if newState == Done: issue.setDateTime("completed", getTime().local)
tasksDir.store(issue, newState) tasksDir.store(issue, newState)
removeFile(oldFilepath)
proc delete*(issue: Issue) = removeFile(issue.filepath)
## Utilities for working with issue collections. ## Utilities for working with issue collections.
proc groupBy*(issues: seq[Issue], propertyKey: string): TableRef[string, seq[Issue]] = proc groupBy*(issues: seq[Issue], propertyKey: string): TableRef[string, seq[Issue]] =