5 Commits
v0.6 ... v1.1

2 changed files with 84 additions and 13 deletions

View File

@ -1,7 +1,8 @@
#Wed, 01 May 2013 14:36:31 -0500 #Mon, 05 Aug 2013 10:16:09 -0500
lib.local=true lib.local=true
name=jdb-gtd name=jdb-gtd
version=0.6 version=1.1
nailgun.classpath.dir=/home/jdbernard/programs/nailgun/classpath nailgun.classpath.dir=/home/jdbernard/programs/nailgun/classpath
executable.jar=true
build.number=1 main.class=com.jdblabs.gtd.cli.GTDCLI
build.number=2

View File

@ -10,7 +10,7 @@ import org.joda.time.DateTime
public class GTDCLI { public class GTDCLI {
public static final String VERSION = "0.6" public static final String VERSION = "1.1"
private static String EOL = System.getProperty("line.separator") private static String EOL = System.getProperty("line.separator")
private static GTDCLI nailgunInst private static GTDCLI nailgunInst
@ -96,7 +96,9 @@ public class GTDCLI {
case ~/cal|calendar/: calendar(parsedArgs); break case ~/cal|calendar/: calendar(parsedArgs); break
case ~/process/: process(parsedArgs); break case ~/process/: process(parsedArgs); break
case ~/list-copies/: listCopies(parsedArgs); break case ~/list-copies/: listCopies(parsedArgs); break
case ~/new/: newAction(parsedArgs); case ~/new/: newAction(parsedArgs); break
case ~/tickler/: tickler(parsedArgs); break
case ~/ls|list/: ls(parsedArgs); break;
default: default:
println "Unrecognized command: ${command}" println "Unrecognized command: ${command}"
break } } } break } } }
@ -259,7 +261,7 @@ public class GTDCLI {
if (inPath(gtdDirs.projects, oldFile)) { if (inPath(gtdDirs.projects, oldFile)) {
// Delete any copies of this item in the next actions folder. // Delete any copies of this item in the next actions folder.
findAllCopies(oldFile, gtdDrs."next-actions").each { file -> findAllCopies(oldFile, gtdDirs."next-actions").each { file ->
println "Deleting duplicate entry from the " + println "Deleting duplicate entry from the " +
"${file.parentFile.name} context." "${file.parentFile.name} context."
file.delete() } file.delete() }
@ -338,8 +340,10 @@ public class GTDCLI {
protected void newAction(LinkedList args) { protected void newAction(LinkedList args) {
def response = prompt("Next action?", "") def response = prompt(["Next action?", ""])
def item = new Item(new File(workingDir, stringToFilename(response))) def file = new File(workingDir, stringToFilename(response))
file.createNewFile()
def item = new Item(file)
item.action = response item.action = response
@ -348,7 +352,7 @@ public class GTDCLI {
println "End with an empty line." println "End with an empty line."
print "> " print "> "
while (response = stdin.readLine().trim()) { while (response = stdin.nextLine().trim()) {
if (!(response =~ /[:=]/)) continue if (!(response =~ /[:=]/)) continue
def parts = response.split(/[:=]/) def parts = response.split(/[:=]/)
item[parts[0].trim().toLowerCase()] = item[parts[0].trim().toLowerCase()] =
@ -357,6 +361,53 @@ public class GTDCLI {
item.save() } item.save() }
protected void tickler(LinkedList args) {
gtdDirs.tickler.eachFileRecurse { file ->
def item = new Item(file)
def today = new DateMidnight()
// If the item is scheduled to be tickled today (or in the past)
// then move it into the next-actions folder
if ((item.tickle as DateMidnight) <= today) {
println "Moving '${item.action}' out of the tickler."
def oldFile = item.file
item.file = new File(gtdDirs."next-actions",
stringToFilename(item.action))
item.gtdProperties.remove("tickle")
item.save()
oldFile.delete() }}}
protected void ls(LinkedList args) {
def target = args.poll()
def printItems = { dir ->
if (!dir.exists() || !dir.isDirectory()) return
println "-- ${getRelativePath(gtdDirs.root, dir)} --"
dir.eachFile { file ->
if (!file.exists() || !file.isFile() || file.isHidden())
return
def item = new Item(file)
println item.action }
println "" }
// If we have a named context or project, look for those items
// specifically
if (target) {
printItems(new File(gtdDirs['next-actions'], target))
printItems(new File(gtdDirs.waiting, target))
printItems(new File(gtdDirs.projects, target)) }
else {
printItems(gtdDirs['next-actions'])
printItems(gtdDirs['waiting'])
gtdDirs['next-actions'].eachDir(printItems)
gtdDirs['waiting'].eachDir(printItems) } }
protected void printUsage(LinkedList args) { protected void printUsage(LinkedList args) {
if (!args) { if (!args) {
@ -383,7 +434,10 @@ top-level commands:
there the same item is filed (cross-reference there the same item is filed (cross-reference
with a project folder, for example). with a project folder, for example).
new Interactively create a new action item in the new Interactively create a new action item in the
current folder.""" current folder.
tickler Search the tickler file for items that need to be
delivered and move them to the *next-actions*
folder."""
} else { } else {
def command = args.poll() def command = args.poll()
@ -466,6 +520,22 @@ future?). It prompts the user for the next action and any extended properties
that should be associated with it, then creates the action file in the current that should be associated with it, then creates the action file in the current
directory.""" directory."""
break break
case ~/tickler/: println """\
usage: gtd tickler
This command should be scheduled for execution once a day. It checks the tickler
file for any items that should become active (based on their <tickle> property)
and moves them out of the tickler file and into the next-actions file."""
break
case ~/ls|list-context/: println """\
usage gtd ls [<context> ...]
This command lists all the tasks for a given context or project. The purpose is
to list in one place items that are sitting in the next-actions folder or the
waiting folder for a specific context or list items for a given project. If no
context or project is named, all contexts are listed."""
} }
} }
} }
@ -500,7 +570,7 @@ directory."""
// parent path. // parent path.
return true } return true }
protected String getRelativePath(File parent, File child) { protected static String getRelativePath(File parent, File child) {
def parentPath = parent.canonicalPath.split("/") def parentPath = parent.canonicalPath.split("/")
def childPath = child.canonicalPath.split("/") def childPath = child.canonicalPath.split("/")
@ -530,7 +600,7 @@ directory."""
return [:] } return [:] }
protected String prompt(String message) { protected String prompt(def msg) {
if (msg instanceof List) msg = msg.join(EOL) if (msg instanceof List) msg = msg.join(EOL)
msg += "> " msg += "> "
print msg print msg