From 407ef39c54ccbc35206330eb08c171ffe1df2deb Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 10 May 2009 01:54:43 -0400 Subject: [PATCH] Enhancement - edit command - Mere beginnings of the edit command. No functionality yet. --- src/command.cpp | 70 +++++++++++++++++++++++++++++++++++++++++++++++++ src/parse.cpp | 1 + src/task.cpp | 5 ++++ src/task.h | 2 ++ src/util.cpp | 13 +++++++++ 5 files changed, 91 insertions(+) diff --git a/src/command.cpp b/src/command.cpp index 3dbc6f2d9..a8e3a03a7 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -860,6 +860,76 @@ std::string handleDuplicate (TDB& tdb, T& task, Config& conf) return out.str (); } +//////////////////////////////////////////////////////////////////////////////// +// Introducing the Silver Bullet. This feature is the catch-all fixative for +// various other ills. This is like opening up the hood and going in with a +// wrench. To be used sparingly. +std::string handleEdit (TDB& tdb, T& task, Config& conf) +{ + std::stringstream out; + std::vector all; + tdb.pendingT (all); + + filterSequence (all, task); + foreach (seq, all) + { + // Check for file permissions. + std::string dataLocation = expandPath (conf.get ("data.location")); + if (access (dataLocation.c_str (), X_OK)) + throw std::string ("Your data.location directory is not writable."); + + // TODO Create a temp file name in data.location. + std::stringstream pattern; + pattern << dataLocation + << "/task." + << seq->getId () + << ".XXXXXX"; + std::cout << "# pattern=" << pattern << std::endl; + char cpattern [PATH_MAX]; + strcpy (cpattern, pattern.str ().c_str ()); + + char* file = mktemp (cpattern); + std::cout << "# file=" << file << std::endl; + + // TODO Format the contents, T -> text. + std::stringstream before; + before << "# Edit only the items within the chevrons << >>. " + << "All other edits will be ignored." << std::endl + << "ID: " << seq->getId () << std::endl + << "Project: <<" << seq->getAttribute ("project") << ">>" << std::endl + << "Priority: <<" << seq->getAttribute ("priority") << ">>" << std::endl + << "Description: <<" << seq->getDescription () << ">>" << std::endl; + + // Write to file. + spit (file, before.str ()); + + // TODO Determine correct editor: $EDITOR > $VISUAL > vi + std::string editor = "/usr/bin/vi"; + + // system ("$EDITOR $file"); + std::string command = editor + " " + file; + system (command.c_str ()); + + // Slurp file. + std::vector after; + slurp (file, after, true); + + // TODO Parse file, text -> T. + foreach (line, after) + { + // TODO Handle each type of line. + } + + // Modify task. + tdb.modifyT (*seq); + + // Cleanup. + unlink (file); + } + + return out.str (); +} + //////////////////////////////////////////////////////////////////////////////// std::string handleColor (Config& conf) { diff --git a/src/parse.cpp b/src/parse.cpp index bb5dbdc45..e141139b8 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -129,6 +129,7 @@ static const char* commands[] = "delete", "done", "duplicate", + "edit", "export", "help", "history", diff --git a/src/task.cpp b/src/task.cpp index 92c34ed4b..b93835aaf 100644 --- a/src/task.cpp +++ b/src/task.cpp @@ -108,6 +108,10 @@ static std::string shortUsage (Config& conf) table.addCell (row, 1, "task ID /from/to/g"); table.addCell (row, 2, "Performs all substitutions on the task description, for fixing mistakes"); + row = table.addRow (); + table.addCell (row, 1, "task edit ID"); + table.addCell (row, 2, "Launches an editor to let you modify all aspects of a task directly, therefore it is to be used carefully"); + row = table.addRow (); table.addCell (row, 1, "task duplicate ID [tags] [attrs] [desc...]"); table.addCell (row, 2, "Duplicates the specified task, and allows modifications"); @@ -889,6 +893,7 @@ std::string runTaskCommand ( else if (command == "undo") { cmdMod = true; out = handleUndo (tdb, task, conf); } else if (command == "import") { cmdMod = true; out = handleImport (tdb, task, conf); } else if (command == "duplicate") { cmdMod = true; out = handleDuplicate (tdb, task, conf); } + else if (command == "edit") { cmdMod = true; out = handleEdit (tdb, task, conf); } // Command that display IDs and therefore need TDB::gc first. else if (command == "completed") { if (gc) gcMod = tdb.gc (); out = handleCompleted (tdb, task, conf); } diff --git a/src/task.h b/src/task.h index a2b60c69d..bb727ad15 100644 --- a/src/task.h +++ b/src/task.h @@ -90,6 +90,7 @@ std::string handleUndo (TDB&, T&, Config&); std::string handleColor (Config&); std::string handleAnnotate (TDB&, T&, Config&); std::string handleDuplicate (TDB&, T&, Config&); +std::string handleEdit (TDB&, T&, Config&); T findT (int, const std::vector &); int deltaAppend (T&, T&); int deltaDescription (T&, T&); @@ -151,6 +152,7 @@ std::string expandPath (const std::string&); #endif bool slurp (const std::string&, std::vector &, bool trimLines = false); +void spit (const std::string&, const std::string&); // rules.cpp void initializeColorRules (Config&); diff --git a/src/util.cpp b/src/util.cpp index 1fe260c89..87d0368f7 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -430,3 +430,16 @@ bool slurp ( } //////////////////////////////////////////////////////////////////////////////// +void spit (const std::string& file, const std::string& contents) +{ + std::ofstream out (file.c_str ()); + if (out.good ()) + { + out << contents; + out.close (); + } + else + throw std::string ("Could not write file '") + file + "'"; +} + +////////////////////////////////////////////////////////////////////////////////