5 Commits
v1.8 ... v1.10

Author SHA1 Message Date
2c8180d9b2 Upgraded to jdb-util-3.2 2014-11-19 12:52:03 -06:00
12f87afe63 Added jlp-docs and target to generate documentation. 2014-06-21 14:32:48 -05:00
3496e21af5 Added online help and documentation for delegate command. 2014-04-16 21:37:30 -05:00
40906eebf8 Updated web.xml for current deployed config. 2014-04-15 20:45:00 +00:00
acaf58f456 Added delegate command to delegate existing actions.
* Created `delegate`. This will move an action from a next actions context
  folder to the waiting folder. Any duplicate items in project folders will be
  renamed and updated to reflect any action change.
* Updated `ls` to take multiple named contexts or projects and list them all.
2013-11-05 08:46:06 -06:00
8 changed files with 153 additions and 28 deletions

View File

@ -8,6 +8,16 @@
<mkdir dir="${build.dir}/main/classes"/>
</target>
<target name="jlp-docs">
<exec executable="jlp">
<arg value="--no-source"/>
<arg value="--output-dir"/>
<arg value="doc"/>
<arg value="src"/>
<arg value="README.md"/>
</exec>
</target>
<target name="ng-deploy" depends="build">
<!-- Stop the Nailgun Server -->
<exec executable="cmd" os="Windows XP">

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,8 +1,8 @@
#Sat, 02 Nov 2013 23:33:05 -0500
#Wed, 19 Nov 2014 12:50:01 -0600
lib.local=true
name=jdb-gtd
version=1.8
version=1.10
nailgun.classpath.dir=/home/jdbernard/programs/nailgun/classpath
executable.jar=true
main.class=com.jdblabs.gtd.cli.GTDCLI
build.number=72
build.number=1

View File

@ -9,7 +9,7 @@
<init-param>
<param-name>gtdRootDir</param-name>
<param-value>/home/jdbernard/Dropbox/gtd</param-value>
<param-value>/home/jdbernard/gtd</param-value>
</init-param>
</servlet>

View File

@ -31,7 +31,7 @@ import static com.jdblabs.gtd.Util.*
* @org gtd.jdb-labs.com/cli/GTDCLI */
public class GTDCLI {
public static final String VERSION = "1.8"
public static final String VERSION = "1.9"
private static String EOL = System.getProperty("line.separator")
/// We have a persistent instance when we are in the context of a Nailgun
@ -203,7 +203,7 @@ public class GTDCLI {
if (opts.h) { printUsage(null); return }
if (opts.v) { println "GTD CLI v$VERSION"; return }
if (opts.d) workingDir = new File(opts.d)
if (opts.d) workingDir = new File(opts.d[0])
/// View the arguments as a [`LinkedList`][1] so we can use [`peek`][2]
/// and [`poll`][3].
@ -242,6 +242,7 @@ public class GTDCLI {
case ~/tickler/: tickler(parsedArgs); break
case ~/ls|list/: ls(parsedArgs); break;
case ~/debug/: debug(parsedArgs); break;
case ~/delegate/: delegateAction(parsedArgs); break;
default:
log.error "Unrecognized command: ${command}"
break } } }
@ -349,7 +350,7 @@ public class GTDCLI {
if (response =~ /del/) {
item.action = prompt([
"Next action (who needs to do what).", ""])
"Next action (who needs to do what)?", ""])
item.file = new File(promptContext(gtdDirs.waiting),
stringToFilename(item.toString())) }
@ -357,14 +358,14 @@ public class GTDCLI {
/// Defer, move to the *next-actions* folder.
else if (response =~ /def/) {
item.action = prompt(["Next action.", ""])
item.action = prompt(["Next action?", ""])
item.file = new File(promptContext(gtdDirs["next-actions"]),
stringToFilename(item.toString())) }
/// Forget for now, move it to the *tickler* folder.
else {
item.action = prompt(["Next action.", ""])
item.action = prompt(["Next action?", ""])
item.tickle = prompt([
"When do you want it to become active?",
"(YYYY-MM-DD)"])
@ -399,13 +400,13 @@ public class GTDCLI {
*/
protected void done(LinkedList args) {
def selectedFilePath = args.poll()
def selectedFilePath
if (!selectedFilePath) {
log.error "gtd done command requires a <action-file> parameter."
if (!args) {
log.error "The 'gtd done' command requires an <action-file> parameter."
return }
while (selectedFilePath) {
while ((selectedFilePath = args.poll())) {
def item
def selectedFile = new File(selectedFilePath)
@ -429,7 +430,7 @@ public class GTDCLI {
if (inPath(gtdDirs.projects, oldFile)) {
/// Delete any copies of this item from the next actions folder.
findAllCopies(oldFile, gtdDirs."next-actions").each { file ->
findAllCopies(oldFile, gtdDirs["next-actions"]).each { file ->
println "Deleting duplicate entry from the " +
"${file.parentFile.name} context."
if (file.exists()) file.delete() }
@ -453,7 +454,6 @@ public class GTDCLI {
/// Delete the original
oldFile.delete()
selectedFilePath = args.poll()
println "'$item' marked as done." } }
/** #### `calendar`
@ -614,7 +614,7 @@ public class GTDCLI {
*/
protected void ls(LinkedList args) {
def target = args.poll()
def target
/// Temporary helper function to print all the items in a given
/// directory.
@ -631,21 +631,20 @@ public class GTDCLI {
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)) }
/// Otherwise print all items in the *next-actions* and *waiting*
/// folders and all their subfolders.
else {
/// If we have no named context or project, print all items in the
/// *next-actions* and *waiting* folders and all their subfolders.
if (!args) {
printItems(gtdDirs['next-actions'])
printItems(gtdDirs['waiting'])
gtdDirs['next-actions'].eachDir(printItems)
gtdDirs['waiting'].eachDir(printItems) } }
gtdDirs['waiting'].eachDir(printItems) }
/// For every name we do have, look for a project or context and
/// recursively print their contents.
else while ((target = args.poll())) {
printItems(new File(gtdDirs['next-actions'], target))
printItems(new File(gtdDirs.waiting, target))
printItems(new File(gtdDirs.projects, target)) } }
/** #### `debug`
* Print out debug information. Currently this prints out the internal
@ -682,6 +681,112 @@ public class GTDCLI {
else setLoggingThreshold(level) }
else log.error "Unrecognized debug command: '${command}'." }
/** #### `delegate`
* Implement the `delegate` command. This allows you to move an action
* from the next action list to the delegate list, providing the name of
* the responsible party and optionally renaming the item. For detailed
* information see the [online help][help-delegate] by running
* `gtd help delegate`.
*
* [help-delegate]: jlp://gtd.jdb-labs.com/cli/GTDCLI/help/delegate
*/
protected void delegateAction(LinkedList args) {
def selectedFilePath
if (!args) {
log.error("The 'gtd delegate' command requires an " +
"<action-file> parameter.")
return }
while ((selectedFilePath = args.poll())) {
Item item
File oldFile, newContextDir
File selectedFile = new File(selectedFilePath)
if (!selectedFile.isAbsolute())
selectedFile = new File(workingDir, selectedFilePath)
if (!selectedFile.exists() || !selectedFile.isFile()) {
log.error "File does not exist or is a directory:"
log.error "\t" + selectedFile.canonicalPath
continue }
item = new Item(selectedFile)
oldFile = item.file
/// Move to the waiting folder, with the name of the delegatee and
/// optionally a new next action.
def delegatee = prompt(
["Who is responsible for the next action? You may also update the next action",
"by including it after a colon (e.g. 'Delegatee Name: New next action.').",
""])
if (delegatee.indexOf(':') > 0) item.action = delegatee
else item.action = delegatee + ': ' + item.action
/// Check if this item was in a project folder.
if (inPath(gtdDirs.projects, oldFile)) {
/// Rename the file in the project folder
item.file = new File(oldFile.parentFile,
stringToFilename(item.toString()))
item.save()
/// Move any copies of this item from the next actions folder
/// to the waiting folder.
findAllCopies(oldFile, gtdDirs['next-actions']).each { dupFile ->
println "Moving duplicate entry from the " +
"${dupFile.parentFile.name} context."
/// Retain the item's context if possible
newContextDir = new File(gtdDirs.waiting,
dupFile.parentFile.name)
/// Instead of creating a new Item object, let's just
/// create a copy of the existing one on the filesystem by
/// saving the existing object to a the new location.
if (newContextDir.exists() && newContextDir.isDirectory()) {
item.file = new File(newContextDir,
stringToFilename(item.toString())) }
else { item.file = new File(gtdDirs.waiting,
stringToFilename(item.toString())) }
item.save()
dupfile.delete() }}
/// Check if this item was in the next-action folder.
else if (inPath(gtdDirs["next-actions"], oldFile) ||
inPath(gtdDirs.waiting, oldFile)) {
/// Retain the item's context if possible.
newContextDir = new File(gtdDirs.waiting,
oldFile.parentFile.name)
/// Move the file to the waiting folder.
if (newContextDir.exists() && newContextDir.isDirectory()) {
item.file = new File(newContextDir,
stringToFilename(item.toString())) }
else { item.file = new File(gtdDirs.waiting,
stringToFilename(item.toString())) }
item.save()
/// Rename any copies of this item from the projects folder.
findAllCopies(oldFile, gtdDirs.projects).each { dupFile ->
println "Renaming duplicate entry from the " +
"${dupFile.parentFile.name} project."
item.file = new File(dupFile.parentFile,
stringToFilename(item.toString()))
item.save()
dupFile.delete() } }
/// Delete the original file.
oldFile.delete() } }
private void print(String msg) { log.info(msg) }
private void println(String line) { log.info(line + EOL) }
@ -830,6 +935,16 @@ 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."""
/// Online help for the `delegate` command.
/// @org gtd.jdb-labs.com/cli/GTDCLI/help/delegate
case ~/delegate/: println """\
usage gtd delegate [<action-file> ...]
This command moves an action item from a next-action context or project folder
to the delegate folder. It allows the user to attach the name of the newly
responsible party and optionally rename the item."""
}
}
}