|
|
|
@ -17,13 +17,18 @@ import com.jdblabs.gtd.Item
|
|
|
|
|
import com.jdblabs.gtd.PropertyHelp
|
|
|
|
|
import com.jdbernard.util.LightOptionParser
|
|
|
|
|
import com.martiansoftware.nailgun.NGContext
|
|
|
|
|
import java.io.FileFilter
|
|
|
|
|
import java.nio.file.Files
|
|
|
|
|
import java.nio.file.Path
|
|
|
|
|
import java.security.MessageDigest
|
|
|
|
|
import groovy.io.FileType
|
|
|
|
|
import org.joda.time.DateMidnight
|
|
|
|
|
import org.joda.time.DateTime
|
|
|
|
|
import org.slf4j.Logger as SFL4JLogger
|
|
|
|
|
import org.slf4j.LoggerFactory
|
|
|
|
|
|
|
|
|
|
import static com.jdblabs.gtd.Util.*
|
|
|
|
|
import static java.nio.file.StandardCopyOption.*
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Command-line helper for working with this implementation of the Getting
|
|
|
|
@ -31,7 +36,7 @@ import static com.jdblabs.gtd.Util.*
|
|
|
|
|
* @org gtd.jdb-labs.com/cli/GTDCLI */
|
|
|
|
|
public class GTDCLI {
|
|
|
|
|
|
|
|
|
|
public static final String VERSION = "1.9"
|
|
|
|
|
public static final String VERSION = "1.14"
|
|
|
|
|
private static String EOL = System.getProperty("line.separator")
|
|
|
|
|
|
|
|
|
|
/// We have a persistent instance when we are in the context of a Nailgun
|
|
|
|
@ -107,7 +112,7 @@ public class GTDCLI {
|
|
|
|
|
/// read afresh the configuration file.
|
|
|
|
|
nailgunInst = null
|
|
|
|
|
nailgunInst = new GTDCLI(new File(
|
|
|
|
|
System.getProperty("user.home"), ".gritterrc"))
|
|
|
|
|
System.getProperty("user.home"), ".gtdclirc"))
|
|
|
|
|
|
|
|
|
|
nailgunInst.run(args) } }
|
|
|
|
|
|
|
|
|
@ -240,9 +245,12 @@ public class GTDCLI {
|
|
|
|
|
case ~/list-copies/: listCopies(parsedArgs); break
|
|
|
|
|
case ~/new/: newAction(parsedArgs); break
|
|
|
|
|
case ~/tickler/: tickler(parsedArgs); break
|
|
|
|
|
case ~/list-contexts/: listContexts(parsedArgs); break;
|
|
|
|
|
case ~/list-projects/: listProjects(parsedArgs); break;
|
|
|
|
|
case ~/ls|list/: ls(parsedArgs); break;
|
|
|
|
|
case ~/debug/: debug(parsedArgs); break;
|
|
|
|
|
case ~/delegate/: delegateAction(parsedArgs); break;
|
|
|
|
|
case ~/rp|rename-project/: renameProject(parsedArgs); break;
|
|
|
|
|
default:
|
|
|
|
|
log.error "Unrecognized command: ${command}"
|
|
|
|
|
break } } }
|
|
|
|
@ -621,7 +629,7 @@ public class GTDCLI {
|
|
|
|
|
def printItems = { dir ->
|
|
|
|
|
if (!dir.exists() || !dir.isDirectory()) return
|
|
|
|
|
println "-- ${getRelativePath(gtdDirs.root, dir)} --"
|
|
|
|
|
dir.eachFile { file ->
|
|
|
|
|
dir.listFiles().sort { it.name }.each { file ->
|
|
|
|
|
if (!file.exists() || !file.isFile() || file.isHidden() ||
|
|
|
|
|
file.name.startsWith('.'))
|
|
|
|
|
return
|
|
|
|
@ -646,6 +654,29 @@ public class GTDCLI {
|
|
|
|
|
printItems(new File(gtdDirs.waiting, target))
|
|
|
|
|
printItems(new File(gtdDirs.projects, target)) } }
|
|
|
|
|
|
|
|
|
|
/** #### `listProjects`
|
|
|
|
|
* Implement the `list-projects` command to list all the known projects
|
|
|
|
|
* for this repository. For detailed information see the
|
|
|
|
|
* [online help][help-list-projects] by running `gtd help list-projects`.
|
|
|
|
|
*
|
|
|
|
|
* [help-list-projects]: jlp://gtd.jdb-labs.com/cli/GTDCLI/help/list-projects
|
|
|
|
|
*/
|
|
|
|
|
protected void listProjects(LinkedList args) {
|
|
|
|
|
gtdDirs.projects.eachFile(FileType.DIRECTORIES) { println it.name } }
|
|
|
|
|
|
|
|
|
|
/** #### `listContexts`
|
|
|
|
|
* Implement the `list-contexts` command to list all the known contexts
|
|
|
|
|
* for this repository. For detailed information see the
|
|
|
|
|
* [online help][help-list-contexts] by running `gtd help list-contexts`.
|
|
|
|
|
*
|
|
|
|
|
* [help-list-contexts]: jlp://gtd.jdb-labs.com/cli/GTDCLI/help/list-contexts
|
|
|
|
|
*/
|
|
|
|
|
protected void listContexts(LinkedList args) {
|
|
|
|
|
def ctxNames = []
|
|
|
|
|
gtdDirs["next-actions"].eachFile(FileType.DIRECTORIES) { ctxNames << it.name }
|
|
|
|
|
gtdDirs.waiting.eachFile(FileType.DIRECTORIES) { ctxNames << it.name }
|
|
|
|
|
ctxNames.unique().each { println it } }
|
|
|
|
|
|
|
|
|
|
/** #### `debug`
|
|
|
|
|
* Print out debug information. Currently this prints out the internal
|
|
|
|
|
* state of the CLI. I may add other subcommands if the need arises. */
|
|
|
|
@ -787,6 +818,56 @@ public class GTDCLI {
|
|
|
|
|
/// Delete the original file.
|
|
|
|
|
oldFile.delete() } }
|
|
|
|
|
|
|
|
|
|
/** #### `rename-project`
|
|
|
|
|
* Implement the `rename-project` command. This will rename the project
|
|
|
|
|
* directory in TODO as well as change the project reference in any of the
|
|
|
|
|
* items from the `next-actions` contexts.
|
|
|
|
|
*
|
|
|
|
|
* `gtd help rename-project`.
|
|
|
|
|
*
|
|
|
|
|
* [help-rename-project]: jlp://gtd.jdb-labs.com/cli/GTDCLI/help/rename-project
|
|
|
|
|
*/
|
|
|
|
|
protected void renameProject(LinkedList args) {
|
|
|
|
|
def projectName = args.poll()
|
|
|
|
|
def newName = args.poll()
|
|
|
|
|
|
|
|
|
|
if (!projectName || !newName) {
|
|
|
|
|
log.error "The 'gtd rename-project' command requires two " +
|
|
|
|
|
"parameters: <existing-project-name> and a <new-name>."
|
|
|
|
|
return }
|
|
|
|
|
|
|
|
|
|
def projectDir = new File(gtdDirs.projects, projectName)
|
|
|
|
|
if (!projectDir.exists() || !projectDir.isDirectory()) {
|
|
|
|
|
log.error "There is no directory named '$projectName' in the " +
|
|
|
|
|
"'projects' directory."
|
|
|
|
|
return }
|
|
|
|
|
|
|
|
|
|
def newDir = new File(gtdDirs.projects, newName)
|
|
|
|
|
if (newDir.exists()) {
|
|
|
|
|
log.error "There is already a project named '$newName'."
|
|
|
|
|
return }
|
|
|
|
|
|
|
|
|
|
// Perform the rename of the directory itself.
|
|
|
|
|
try { Files.move(projectDir.toPath(), newDir.toPath(), REPLACE_EXISTING) }
|
|
|
|
|
catch (Exception e) {
|
|
|
|
|
log.error "Unable to rename the project: ${e.localizedMessage}."
|
|
|
|
|
return }
|
|
|
|
|
|
|
|
|
|
// Update all of the items associated with this project.
|
|
|
|
|
def projectFiles = newDir.
|
|
|
|
|
listFiles({ File f ->
|
|
|
|
|
f.exists() && !f.isHidden() &&
|
|
|
|
|
f.isFile() && !f.name.startsWith('.') } as FileFilter)
|
|
|
|
|
|
|
|
|
|
def allProjectItems = projectFiles.collectMany { f ->
|
|
|
|
|
findAllCopies(f, gtdDirs.root).collect { new Item(it) } }
|
|
|
|
|
|
|
|
|
|
allProjectItems.each {
|
|
|
|
|
it.project = newName
|
|
|
|
|
it.save() }
|
|
|
|
|
|
|
|
|
|
println "Project renamed. ${allProjectItems.size()} items updated." }
|
|
|
|
|
|
|
|
|
|
private void print(String msg) { log.info(msg) }
|
|
|
|
|
private void println(String line) { log.info(line + EOL) }
|
|
|
|
|
|
|
|
|
@ -809,20 +890,41 @@ options are:
|
|
|
|
|
top-level commands:
|
|
|
|
|
|
|
|
|
|
help <command> Print detailed help about a command.
|
|
|
|
|
|
|
|
|
|
process Process inbox items systematically.
|
|
|
|
|
|
|
|
|
|
done <action-file> Mark an action as done. This will automatically
|
|
|
|
|
take care of duplicates of the action in project
|
|
|
|
|
or next-actions sub-folders.
|
|
|
|
|
|
|
|
|
|
calendar Show the tasks with specific days assigned to
|
|
|
|
|
them, sorted by date.
|
|
|
|
|
|
|
|
|
|
list-copies <action-file> Given an action item, list all the other places
|
|
|
|
|
there the same item is filed (cross-reference
|
|
|
|
|
with a project folder, for example).
|
|
|
|
|
|
|
|
|
|
new Interactively create a new action item in the
|
|
|
|
|
current folder.
|
|
|
|
|
|
|
|
|
|
tickler Search the tickler file for items that need to be
|
|
|
|
|
delivered and move them to the *next-actions*
|
|
|
|
|
folder."""
|
|
|
|
|
folder.
|
|
|
|
|
|
|
|
|
|
list, ls [<context> ...] List all the tasks for a given set of contexts
|
|
|
|
|
projects.
|
|
|
|
|
|
|
|
|
|
debug n
|
|
|
|
|
|
|
|
|
|
delegate Move an item from a next-action context or a
|
|
|
|
|
project folder to a waiting context and attach
|
|
|
|
|
the name of the party now responsible for the
|
|
|
|
|
item.
|
|
|
|
|
|
|
|
|
|
rename-project, rp <existing-project> <new-name>
|
|
|
|
|
|
|
|
|
|
Rename a project directory and update any task
|
|
|
|
|
items that reference it."""
|
|
|
|
|
} else {
|
|
|
|
|
def command = args.poll()
|
|
|
|
|
|
|
|
|
@ -926,15 +1028,17 @@ 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
|
|
|
|
|
|
|
|
|
|
/// Online help for the `ls`/`list-context` command.
|
|
|
|
|
/// Online help for the `ls`/`list` command.
|
|
|
|
|
/// @org gtd.jdb-labs.com/cli/GTDCLI/help/ls
|
|
|
|
|
case ~/ls|list-context/: println """\
|
|
|
|
|
usage gtd ls [<context> ...]
|
|
|
|
|
case ~/ls|list/: println """\
|
|
|
|
|
usage gtd list [<context> ...]
|
|
|
|
|
or 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."""
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
/// Online help for the `delegate` command.
|
|
|
|
|
/// @org gtd.jdb-labs.com/cli/GTDCLI/help/delegate
|
|
|
|
@ -944,6 +1048,35 @@ 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."""
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
/// Online help for the `list-projects` command.
|
|
|
|
|
/// @org gtd.jdb-labs.com/cli/GTDCLI/hemp/list-projects
|
|
|
|
|
case ~/list-projects/: println """\
|
|
|
|
|
usage gtd list-projects
|
|
|
|
|
|
|
|
|
|
This command lists all of the project folders defined in this repository (all
|
|
|
|
|
the folders in the /projects folder."""
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
/// Online help for the `list-contexts` command.
|
|
|
|
|
/// @org gtd.jdb-labs.com/cli/GTDCLI/hemp/list-contexts
|
|
|
|
|
case ~/list-contexts/: println """\
|
|
|
|
|
usage gtd list-contexts
|
|
|
|
|
|
|
|
|
|
This command lists all of the context folders defined in this repository (all
|
|
|
|
|
the folders in the /next-actions and /waiting folders."""
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
/// Online help for the `rename-project` command.
|
|
|
|
|
/// @org gtd.jdb-labs.com/cli/GTDCLI/help/rename-project
|
|
|
|
|
case ~/delegate/: println """\
|
|
|
|
|
usage gtd rename-project <existing-project> <new-name>
|
|
|
|
|
or gtd rp <existing-project> <new-name>
|
|
|
|
|
|
|
|
|
|
This command renames a project directory and updates any items that reference
|
|
|
|
|
the project."""
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|