diff --git a/src/Context.cpp b/src/Context.cpp index 0c3fb8729..13c3e8e60 100644 --- a/src/Context.cpp +++ b/src/Context.cpp @@ -173,8 +173,8 @@ std::string Context::dispatch () else if (cmd.command == "help") { out = longUsage (); } else if (cmd.command == "stats") { out = handleReportStats (); } else if (cmd.command == "info") { out = handleInfo (); } -/* else if (cmd.command == "history") { out = handleReportHistory (); } +/* else if (cmd.command == "ghistory") { out = handleReportGHistory (); } else if (cmd.command == "calendar") { out = handleReportCalendar (); } else if (cmd.command == "summary") { out = handleReportSummary (); } @@ -365,6 +365,7 @@ std::cout << "# parse tag addition '" << *arg << "'" << std::endl; foundSomethingAfterSequence = true; tagAdditions.push_back (arg->substr (1, std::string::npos)); + task.addTag (arg->substr (1, std::string::npos)); } // Tags to remove begin with '-'. @@ -451,7 +452,7 @@ std::cout << "# parse post-termination description '" << *arg << "'" } } - if (noVerticalSpace (descCandidate)) + if (descCandidate != "" && noVerticalSpace (descCandidate)) task.set ("description", descCandidate); // TODO task.validate () @@ -484,16 +485,46 @@ std::cout << "# parse post-termination description '" << *arg << "'" void Context::constructFilter () { foreach (att, task) - if (att->first != "uuid") - filter.push_back (att->second); - - // TODO this doesn't work. - if (task.has ("description")) { - std::vector words; - split (words, task.get ("description"), ' '); - foreach (word, words) - filter.push_back (Att ("description", "contains", *word)); + + // TODO this doesn't work. + if (att->first == "description") + { + std::vector words; + split (words, att->second.value (), ' '); + foreach (word, words) + { + filter.push_back (Att ("description", "has", *word)); + std::cout << "Context::constructFilter " << att->first << "=" << att->second.value () << std::endl; + } + } + + // TODO Don't create a uuid for every task? + // Every task has a unique uuid by default, and it shouldn't be included. + // The mechanism for filtering on tags is +/-, not tags:foo which + // means that there can only be one tag, "foo". + else if (att->first != "uuid" && + att->first != "tags") + { + filter.push_back (att->second); + std::cout << "Context::constructFilter " << att->first << "=" << att->second.value () << std::endl; + } + } + + // TODO Include Annotations as part of the description? + + // Include tagAdditions. + foreach (tag, tagAdditions) + { + filter.push_back (Att ("tags", "has", *tag)); + std::cout << "Context::constructFilter tags=+" << *tag << std::endl; + } + + // TODO Include tagRemovals. + foreach (tag, tagRemovals) + { + filter.push_back (Att ("tags", "hasnt", *tag)); + std::cout << "Context::constructFilter tags=-" << *tag << std::endl; } } diff --git a/src/Context.h b/src/Context.h index b63669482..765de97a9 100644 --- a/src/Context.h +++ b/src/Context.h @@ -72,7 +72,7 @@ public: std::string program; std::vector args; Cmd cmd; - std::vector tagAdditions; + std::vector tagAdditions; // TODO This is redundant, remove. std::vector tagRemovals; private: diff --git a/src/Filter.cpp b/src/Filter.cpp index 4fa91419c..efdab9a28 100644 --- a/src/Filter.cpp +++ b/src/Filter.cpp @@ -25,6 +25,7 @@ // //////////////////////////////////////////////////////////////////////////////// +#include // TODO Remove #include #include "Filter.h" #include "util.h" @@ -41,6 +42,8 @@ bool Filter::pass (const Record& record) const // but it doesn't match, fail. foreach (att, (*this)) { +// TODO std::cout << "Filter::pass " << att->name () << "=" << att->value () << std::endl; + // If the record doesn't have the attribute, match against a default one. // This is because "att" may contain a modifier like "name.not:X". if ((r = record.find (att->name ())) == record.end ()) diff --git a/src/Task.h b/src/Task.h index f1df36b87..bd1c4bbf2 100644 --- a/src/Task.h +++ b/src/Task.h @@ -74,12 +74,6 @@ public: private: int determineVersion (const std::string&); void legacyParse (const std::string&); - -private: -/* - std::vector mTags; - std::vector mRemoveTags; -*/ }; #endif diff --git a/src/command.cpp b/src/command.cpp index 4636d0fb1..1e79461fd 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -73,6 +73,10 @@ std::string handleAdd () context.task.set ("priority", defaultPriority); } + // Include tags. + foreach (tag, context.tagAdditions) + context.task.addTag (*tag); + // Only valid tasks can be added. context.task.validate (); diff --git a/src/custom.cpp b/src/custom.cpp index c34890076..9c3df54a0 100644 --- a/src/custom.cpp +++ b/src/custom.cpp @@ -88,22 +88,7 @@ std::string handleCustomReport (const std::string& report) context.tdb.load (tasks, context.filter); context.tdb.unlock (); -/* - // Load all pending tasks. - std::vector tasks; - tdb.allPendingT (tasks); - handleRecurrence (tdb, tasks); - - // Apply filters. - { - std::string ignore; - T filterTask; - parse (filterArgs, ignore, filterTask); - - filter (tasks, filterTask); // Filter from custom report - filter (tasks, task); // Filter from command line - } -*/ + // TODO handleRecurrence (tdb, tasks); // Initialize colorization for subsequent auto colorization. initializeColorRules (); diff --git a/src/report.cpp b/src/report.cpp index 75fdd98ea..ce0e7a6b8 100644 --- a/src/report.cpp +++ b/src/report.cpp @@ -818,7 +818,8 @@ std::string handleReportNext () //////////////////////////////////////////////////////////////////////////////// // Year Month Added Completed Deleted // 2006 November 87 63 14 -// 2006 December 21 6 1 +// December 21 6 1 +// 2007 January 3 12 0 time_t monthlyEpoch (const std::string& date) { // Convert any date in epoch form to m/d/y, then convert back @@ -839,92 +840,51 @@ time_t monthlyEpoch (const std::string& date) std::string handleReportHistory () { - std::stringstream out; -/* - std::map groups; - std::map addedGroup; - std::map completedGroup; - std::map deletedGroup; + std::map groups; // Represents any month with data + std::map addedGroup; // Additions by month + std::map completedGroup; // Completions by month + std::map deletedGroup; // Deletions by month // Scan the pending tasks. - std::vector pending; - tdb.allPendingT (pending); - handleRecurrence (tdb, pending); - filter (pending, task); - for (unsigned int i = 0; i < pending.size (); ++i) + std::vector tasks; + context.tdb.lock (context.config.get ("locking", true)); + context.tdb.load (tasks, context.filter); + context.tdb.unlock (); + // TODO handleRecurrence (tdb, tasks); + + foreach (task, tasks) { - T task (pending[i]); - time_t epoch = monthlyEpoch (task.getAttribute ("entry")); - if (epoch) + time_t epoch = monthlyEpoch (task->get ("entry")); + groups[epoch] = 0; + + // Every task has an entry date. + if (addedGroup.find (epoch) != addedGroup.end ()) + addedGroup[epoch] = addedGroup[epoch] + 1; + else + addedGroup[epoch] = 1; + + // All deleted tasks have an end date. + if (task->getStatus () == Task::deleted) { + epoch = monthlyEpoch (task->get ("end")); groups[epoch] = 0; - if (addedGroup.find (epoch) != addedGroup.end ()) - addedGroup[epoch] = addedGroup[epoch] + 1; + if (deletedGroup.find (epoch) != deletedGroup.end ()) + deletedGroup[epoch] = deletedGroup[epoch] + 1; else - addedGroup[epoch] = 1; - - if (task.getStatus () == T::deleted) - { - epoch = monthlyEpoch (task.getAttribute ("end")); - groups[epoch] = 0; - - if (deletedGroup.find (epoch) != deletedGroup.end ()) - deletedGroup[epoch] = deletedGroup[epoch] + 1; - else - deletedGroup[epoch] = 1; - } - else if (task.getStatus () == T::completed) - { - epoch = monthlyEpoch (task.getAttribute ("end")); - groups[epoch] = 0; - - if (completedGroup.find (epoch) != completedGroup.end ()) - completedGroup[epoch] = completedGroup[epoch] + 1; - else - completedGroup[epoch] = 1; - } + deletedGroup[epoch] = 1; } - } - // Scan the completed tasks. - std::vector completed; - tdb.allCompletedT (completed); - filter (completed, task); - for (unsigned int i = 0; i < completed.size (); ++i) - { - T task (completed[i]); - time_t epoch = monthlyEpoch (task.getAttribute ("entry")); - if (epoch) + // All completed tasks have an end date. + else if (task->getStatus () == Task::completed) { + epoch = monthlyEpoch (task->get ("end")); groups[epoch] = 0; - if (addedGroup.find (epoch) != addedGroup.end ()) - addedGroup[epoch] = addedGroup[epoch] + 1; + if (completedGroup.find (epoch) != completedGroup.end ()) + completedGroup[epoch] = completedGroup[epoch] + 1; else - addedGroup[epoch] = 1; - - epoch = monthlyEpoch (task.getAttribute ("end")); - if (task.getStatus () == T::deleted) - { - epoch = monthlyEpoch (task.getAttribute ("end")); - groups[epoch] = 0; - - if (deletedGroup.find (epoch) != deletedGroup.end ()) - deletedGroup[epoch] = deletedGroup[epoch] + 1; - else - deletedGroup[epoch] = 1; - } - else if (task.getStatus () == T::completed) - { - epoch = monthlyEpoch (task.getAttribute ("end")); - groups[epoch] = 0; - - if (completedGroup.find (epoch) != completedGroup.end ()) - completedGroup[epoch] = completedGroup[epoch] + 1; - else - completedGroup[epoch] = 1; - } + completedGroup[epoch] = 1; } } @@ -1013,19 +973,20 @@ std::string handleReportHistory () table.addCell (row, 1, "Average"); if (context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false)) table.setRowFg (row, Text::bold); - table.addCell (row, 2, totalAdded / (table.rowCount () - 2)); + table.addCell (row, 2, totalAdded / (table.rowCount () - 2)); table.addCell (row, 3, totalCompleted / (table.rowCount () - 2)); - table.addCell (row, 4, totalDeleted / (table.rowCount () - 2)); + table.addCell (row, 4, totalDeleted / (table.rowCount () - 2)); table.addCell (row, 5, (totalAdded - totalCompleted - totalDeleted) / (table.rowCount () - 2)); } + std::stringstream out; if (table.rowCount ()) out << optionalBlankLine () << table.render () << std::endl; else out << "No tasks." << std::endl; -*/ + return out.str (); }