From acb6e3cfdc1fb89b760b5647449500b1f09e1e0c Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 23 Jun 2009 09:56:31 -0400 Subject: [PATCH 1/7] Enhancement - timers - Timers now only use fixed precision for even very small numbers. --- src/Timer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Timer.cpp b/src/Timer.cpp index e934ac06d..9461b0f5b 100644 --- a/src/Timer.cpp +++ b/src/Timer.cpp @@ -52,6 +52,7 @@ Timer::~Timer () << mDescription << " " << std::setprecision (6) + << std::fixed << ((end.tv_sec - mStart.tv_sec) + ((end.tv_usec - mStart.tv_usec ) / 1000000.0)); From b6bc72c449f22ff158252f6599b235b55f533e33 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 23 Jun 2009 14:56:15 -0400 Subject: [PATCH 2/7] Enhancement - confirm3 - Added a tri-state confirmation function for confirming bulk operations allowing the user to answer yes/no/all to and optionally allow, disallow or bulk-allow big changes. --- src/util.cpp | 34 ++++++++++++++++++++++++++++++++++ src/util.h | 1 + 2 files changed, 35 insertions(+) diff --git a/src/util.cpp b/src/util.cpp index fdf934ac3..9c59002c8 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -74,6 +74,40 @@ bool confirm (const std::string& question) return (answer == "y" || answer == "ye" || answer == "yes") ? true : false; // TODO i18n } +//////////////////////////////////////////////////////////////////////////////// +// 0 = no +// 1 = yes +// 2 = all +int confirm3 (const std::string& question) +{ + std::vector options; + options.push_back ("yes"); + options.push_back ("no"); + options.push_back ("all"); + + std::string answer; + std::vector matches; + + do + { + std::cout << question + << " (" + << options[0] << "/" + << options[1] << "/" + << options[2] + << ") "; + + std::getline (std::cin, answer); + answer = trim (answer); + autoComplete (answer, options, matches); + } + while (matches.size () != 1); + + if (matches[0] == "yes") return 1; + else if (matches[0] == "all") return 2; + else return 0; +} + //////////////////////////////////////////////////////////////////////////////// void delay (float f) { diff --git a/src/util.h b/src/util.h index b72e8303f..19f7af6f2 100644 --- a/src/util.h +++ b/src/util.h @@ -51,6 +51,7 @@ for (typeof (c) *foreach_p = & (c); \ // util.cpp bool confirm (const std::string&); +int confirm3 (const std::string&); void delay (float); std::string formatSeconds (time_t); std::string formatSecondsCompact (time_t); From 78afa4e110b70ec49a7685504b2f69dfe299ae29 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 23 Jun 2009 17:38:58 -0400 Subject: [PATCH 3/7] Enhancement - Aliases - Moved alias mapping to Context. - Added Context::canonicalize to resolve aliases. - Added Context::loadAliases to reload on config file change. - Removed old alias processing from Cmd. - Doesn't work yet, but the data is loaded. --- src/Cmd.cpp | 24 ------------------------ src/Cmd.h | 3 --- src/Context.cpp | 39 +++++++++++++++++++++++++++++++++++++++ src/Context.h | 6 +++++- 4 files changed, 44 insertions(+), 28 deletions(-) diff --git a/src/Cmd.cpp b/src/Cmd.cpp index 554b2b5e8..9a3d2b6f7 100644 --- a/src/Cmd.cpp +++ b/src/Cmd.cpp @@ -165,30 +165,6 @@ void Cmd::load () } } } - -/* - // Now load the aliases. - foreach (i, all) - { - if (i->substr (0, 6) == "alias.") - { - std::string name = i->substr (6, std::string::npos); - std::string alias = context.config.get (name); - - // Make sure a custom report does not clash with a built-in - // command. - if (std::find (commands.begin (), commands.end (), report) != commands.end ()) - throw std::string ("Alias '") + name + - "' conflicts with built-in task command."; - - if (std::find (customReports.begin (), customReports.end (), report) != customReports.end ()) - throw std::string ("Alias '") + name + - "' conflicts with custom report."; - - aliases[name] = alias; - } - } -*/ } } diff --git a/src/Cmd.h b/src/Cmd.h index 15ff7aaa8..314a6802d 100644 --- a/src/Cmd.h +++ b/src/Cmd.h @@ -27,10 +27,8 @@ #ifndef INCLUDED_CMD #define INCLUDED_CMD -//#include #include #include -#include "Cmd.h" class Cmd { @@ -59,7 +57,6 @@ private: private: std::vector commands; std::vector customReports; -// std::map aliases; }; #endif diff --git a/src/Context.cpp b/src/Context.cpp index 54e4a850e..6b4c043c6 100644 --- a/src/Context.cpp +++ b/src/Context.cpp @@ -93,6 +93,7 @@ void Context::initialize () // Load the configuration file from the home directory. If the file cannot // be found, offer to create a sample one. loadCorrectConfigFile (); + loadAliases (); // When redirecting output to a file, do not use color, curses. if (!isatty (fileno (stdout))) @@ -289,6 +290,24 @@ void Context::shadow () } } +//////////////////////////////////////////////////////////////////////////////// +// Only allows aliases 10 deep. +std::string Context::canonicalize (const std::string& input) const +{ + std::string canonical = input; + + // Follow the chain. + int i = 10; // Safety valve. + std::map ::const_iterator found; + while ((found = aliases.find (canonical)) != aliases.end () && i-- > 0) + canonical = found->second; + + if (i < 1) + return input; + + return canonical; +} + //////////////////////////////////////////////////////////////////////////////// void Context::loadCorrectConfigFile () { @@ -352,6 +371,26 @@ void Context::loadCorrectConfigFile () args = filtered; } +//////////////////////////////////////////////////////////////////////////////// +void Context::loadAliases () +{ + aliases.clear (); + + std::vector vars; + config.all (vars); + foreach (var, vars) + { + if (var->substr (0, 6) == "alias.") + { + std::string alias = var->substr (6, std::string::npos); + std::string canonical = config.get (*var); + + aliases[alias] = canonical; + debug (std::string ("Alias ") + alias + " -> " + canonical); + } + } +} + //////////////////////////////////////////////////////////////////////////////// void Context::parse () { diff --git a/src/Context.h b/src/Context.h index da55ec719..23003e2db 100644 --- a/src/Context.h +++ b/src/Context.h @@ -65,8 +65,11 @@ public: void parse (std::vector &, Cmd&, Task&, Sequence&, Subst&, Filter&); void clear (); + std::string canonicalize (const std::string&) const; + private: void loadCorrectConfigFile (); + void loadAliases (); void autoFilter (Task&, Filter&); public: @@ -81,7 +84,8 @@ public: std::string program; std::vector args; Cmd cmd; - std::vector tagAdditions; // TODO This is redundant, remove. + std::map aliases; + std::vector tagAdditions; std::vector tagRemovals; private: From 5632c49945e2f753e6858c64adbc55a089a04d35 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 24 Jun 2009 21:55:44 -0400 Subject: [PATCH 4/7] Code Cleanup - Removed references to ::strcmp. Thanks Fredde. --- src/Att.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Att.cpp b/src/Att.cpp index c3b1734ba..f7e92adcd 100644 --- a/src/Att.cpp +++ b/src/Att.cpp @@ -571,7 +571,7 @@ bool Att::match (const Att& other) const } else if (which == "text") { - if (::strcmp (mValue.c_str (), other.mValue.c_str ()) <= 0) + if (mValue <= other.mValue) return false; } } @@ -601,7 +601,7 @@ bool Att::match (const Att& other) const } else if (which == "text") { - if (::strcmp (mValue.c_str (), other.mValue.c_str ()) >= 0) + if (mValue >= other.mValue) return false; } } From f31f068322301ea00ecc9d7d0eca3165b96ee50f Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 24 Jun 2009 21:56:31 -0400 Subject: [PATCH 5/7] Code Cleanup - Broke out the guts of handleCustomReport into runCustomReport, so that the next report can generate it's own task list, then allow the custom report handling to render it. This means the next report is essentially (but not quite) a custom report. --- src/custom.cpp | 87 +++++++++++++++++++++++++++++++++++++------------- src/main.h | 3 ++ 2 files changed, 68 insertions(+), 22 deletions(-) diff --git a/src/custom.cpp b/src/custom.cpp index b9b378970..b38692268 100644 --- a/src/custom.cpp +++ b/src/custom.cpp @@ -55,29 +55,10 @@ std::string handleCustomReport (const std::string& report) { // Load report configuration. std::string columnList = context.config.get ("report." + report + ".columns"); - std::vector columns; - split (columns, columnList, ','); - validReportColumns (columns); - - std::string labelList = context.config.get ("report." + report + ".labels"); - std::vector labels; - split (labels, labelList, ','); - - if (columns.size () != labels.size () && labels.size () != 0) - throw std::string ("There are a different number of columns than labels ") + - "for report '" + report + "'."; - - std::map columnLabels; - if (labels.size ()) - for (unsigned int i = 0; i < columns.size (); ++i) - columnLabels[columns[i]] = labels[i]; - - std::string sortList = context.config.get ("report." + report + ".sort"); - std::vector sortOrder; - split (sortOrder, sortList, ','); - validSortColumns (columns, sortOrder); - + std::string labelList = context.config.get ("report." + report + ".labels"); + std::string sortList = context.config.get ("report." + report + ".sort"); std::string filterList = context.config.get ("report." + report + ".filter"); + std::vector filterArgs; split (filterArgs, filterList, ' '); { @@ -106,6 +87,68 @@ std::string handleCustomReport (const std::string& report) context.tdb.commit (); context.tdb.unlock (); + return runCustomReport ( + report, + columnList, + labelList, + sortList, + filterList, + tasks); +} + +//////////////////////////////////////////////////////////////////////////////// +// This report will eventually become the one report that many others morph into +// via the .taskrc file. + +std::string runCustomReport ( + const std::string& report, + const std::string& columnList, + const std::string& labelList, + const std::string& sortList, + const std::string& filterList, + std::vector & tasks) +{ + // Load report configuration. + std::vector columns; + split (columns, columnList, ','); + validReportColumns (columns); + + std::vector labels; + split (labels, labelList, ','); + + if (columns.size () != labels.size () && labels.size () != 0) + throw std::string ("There are a different number of columns than labels ") + + "for report '" + report + "'."; + + std::map columnLabels; + if (labels.size ()) + for (unsigned int i = 0; i < columns.size (); ++i) + columnLabels[columns[i]] = labels[i]; + + std::vector sortOrder; + split (sortOrder, sortList, ','); + validSortColumns (columns, sortOrder); + + std::vector filterArgs; + split (filterArgs, filterList, ' '); + { + Cmd cmd (report); + Task task; + Sequence sequence; + Subst subst; + Filter filter; + context.parse (filterArgs, cmd, task, sequence, subst, filter); + + context.sequence.combine (sequence); + + // Allow limit to be overridden by the command line. + if (!context.task.has ("limit") && task.has ("limit")) + context.task.set ("limit", task.get ("limit")); + + foreach (att, filter) + context.filter.push_back (*att); + } + // Filter sequence. if (context.sequence.size ()) context.filter.applySequence (tasks, context.sequence); diff --git a/src/main.h b/src/main.h index deb4ec7a0..72a048c8a 100644 --- a/src/main.h +++ b/src/main.h @@ -101,6 +101,9 @@ std::string getDueDate (Task&); // custom.cpp std::string handleCustomReport (const std::string&); +std::string runCustomReport (const std::string&, const std::string&, + const std::string&, const std::string&, + const std::string&, std::vector &); // rules.cpp void initializeColorRules (); From a32263e7ead83545681d2383f04ea85cf8291e95 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Thu, 25 Jun 2009 00:47:07 -0400 Subject: [PATCH 6/7] Enhancement - next - The next report is now a custom report. There is also a nasty piece of logic that lets the next report exist as a custom report, and also with it's own handleReportNext function to prep and filter the tasks, then hand off to runCustomReport. --- src/Cmd.cpp | 9 +- src/Config.cpp | 22 ++++ src/TDB.cpp | 16 +-- src/TDB.h | 1 - src/main.h | 2 +- src/report.cpp | 282 +++++++++++++++---------------------------- src/tests/.gitignore | 1 + 7 files changed, 134 insertions(+), 199 deletions(-) diff --git a/src/Cmd.cpp b/src/Cmd.cpp index 9a3d2b6f7..1e6919e54 100644 --- a/src/Cmd.cpp +++ b/src/Cmd.cpp @@ -147,12 +147,19 @@ void Cmd::load () if (i->substr (0, 7) == "report.") { std::string report = i->substr (7, std::string::npos); + + // Oh, what a massive hack. Shame. Shame. + // The "next" report is in limbo between being a built-in report and + // a custom report. The projection is defined as a custom report, but + // the restriction is different. + if (report.substr (0, 4) == "next") + continue; + std::string::size_type columns = report.find (".columns"); if (columns != std::string::npos) { report = report.substr (0, columns); - // Make sure a custom report does not clash with a built-in // command. if (std::find (commands.begin (), commands.end (), report) != commands.end ()) diff --git a/src/Config.cpp b/src/Config.cpp index b8106d65a..0f67e8c6f 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -224,6 +224,17 @@ void Config::createDefault (const std::string& home) fprintf (out, "report.waiting.sort=wait+,priority-,project+\n"); // TODO i18n fprintf (out, "report.waiting.filter=status:waiting\n"); // TODO i18n + fprintf (out, "report.all.description=Lists all tasks matching the specified criteria\n"); // TODO i18n + fprintf (out, "report.all.columns=id,project,priority,due,active,age,description\n"); // TODO i18n + fprintf (out, "report.all.labels=ID,Project,Pri,Due,Active,Age,Description\n"); // TODO i18n + fprintf (out, "report.all.sort=due+,priority-,project+\n"); // TODO i18n + + fprintf (out, "report.next.description=Lists all tasks matching the specified criteria\n"); // TODO i18n + fprintf (out, "report.next.columns=id,project,priority,due,active,age,description\n"); // TODO i18n + fprintf (out, "report.next.labels=ID,Project,Pri,Due,Active,Age,Description\n"); // TODO i18n + fprintf (out, "report.next.sort=due+,priority-,project+\n"); // TODO i18n + fprintf (out, "report.next.filter=status:pending\n"); // TODO i18n + fclose (out); std::cout << "Done." << std::endl; // TODO i18n @@ -302,6 +313,17 @@ void Config::setDefaults () set ("report.waiting.labels", "ID,Project,Pri,Wait,Age,Description"); // TODO i18n set ("report.waiting.sort", "wait+,priority-,project+"); // TODO i18n set ("report.waiting.filter", "status:waiting"); // TODO i18n + + set ("report.all.description", "Lists all tasks matching the specified criteria"); // TODO i18n + set ("report.all.columns", "id,project,priority,due,active,age,description"); // TODO i18n + set ("report.all.labels", "ID,Project,Pri,Due,Active,Age,Description"); // TODO i18n + set ("report.all.sort", "due+,priority-,project+"); // TODO i18n + + set ("report.next.description", "Lists all tasks matching the specified criteria"); // TODO i18n + set ("report.next.columns", "id,project,priority,due,active,age,description"); // TODO i18n + set ("report.next.labels", "ID,Project,Pri,Due,Active,Age,Description"); // TODO i18n + set ("report.next.sort", "due+,priority-,project+"); // TODO i18n + set ("report.next.filter", "status:pending"); // TODO i18n } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/TDB.cpp b/src/TDB.cpp index 413d62141..f5efb43f0 100644 --- a/src/TDB.cpp +++ b/src/TDB.cpp @@ -382,19 +382,6 @@ int TDB::commit () return quantity; } -//////////////////////////////////////////////////////////////////////////////// -// TODO -> FF4 -void TDB::upgrade () -{ - // TODO Read all pending - // TODO Write out all pending - - // TODO Read all completed - // TODO Write out all completed - - throw std::string ("unimplemented TDB::upgrade"); -} - //////////////////////////////////////////////////////////////////////////////// // Scans the pending tasks for any that are completed or deleted, and if so, // moves them to the completed.data file. Returns a count of tasks moved. @@ -435,7 +422,10 @@ int TDB::gc () // Wake up tasks that are waiting. Date wait_date (::atoi (task->get ("wait").c_str ())); if (now > wait_date) + { task->setStatus (Task::pending); + task->remove ("wait"); + } still_pending.push_back (*task); } diff --git a/src/TDB.h b/src/TDB.h index 3ca81c404..5112e4ad9 100644 --- a/src/TDB.h +++ b/src/TDB.h @@ -59,7 +59,6 @@ public: void add (const Task&); // Single task add to pending void update (const Task&); // Single task update to pending int commit (); // Write out all tasks - void upgrade (); // Convert both files to FF4 int gc (); // Clean up pending int nextId (); diff --git a/src/main.h b/src/main.h index 72a048c8a..cb3b07bb0 100644 --- a/src/main.h +++ b/src/main.h @@ -45,7 +45,7 @@ void validSortColumns (const std::vector &, const std::vector &, std::vector &); +void gatherNextTasks (std::vector &); void onChangeCallback (); // recur.cpp diff --git a/src/report.cpp b/src/report.cpp index 643719ecf..bae306c96 100644 --- a/src/report.cpp +++ b/src/report.cpp @@ -679,138 +679,50 @@ std::string handleReportSummary () // std::string handleReportNext () { + // Load report configuration. + std::string columnList = context.config.get ("report.next.columns"); + std::string labelList = context.config.get ("report.next.labels"); + std::string sortList = context.config.get ("report.next.sort"); + std::string filterList = context.config.get ("report.next.filter"); + + std::vector filterArgs; + split (filterArgs, filterList, ' '); + { + Cmd cmd ("next"); + Task task; + Sequence sequence; + Subst subst; + Filter filter; + context.parse (filterArgs, cmd, task, sequence, subst, filter); + + context.sequence.combine (sequence); + + // Allow limit to be overridden by the command line. + if (!context.task.has ("limit") && task.has ("limit")) + context.task.set ("limit", task.get ("limit")); + + foreach (att, filter) + context.filter.push_back (*att); + } + // Get all the tasks. std::vector tasks; context.tdb.lock (context.config.get ("locking", true)); handleRecurrence (); - context.tdb.loadPending (tasks, context.filter); + context.tdb.load (tasks, context.filter); context.tdb.commit (); context.tdb.unlock (); // Restrict to matching subset. - std::vector matching; - gatherNextTasks (tasks, matching); + gatherNextTasks (tasks); - initializeColorRules (); - - // Create a table for output. - Table table; - table.setTableWidth (context.getWidth ()); - table.setDateFormat (context.config.get ("dateformat", "m/d/Y")); - table.addColumn ("ID"); - table.addColumn ("Project"); - table.addColumn ("Pri"); - table.addColumn ("Due"); - table.addColumn ("Active"); - table.addColumn ("Age"); - table.addColumn ("Description"); - - if ((context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false)) && - context.config.get (std::string ("fontunderline"), "true")) - { - table.setColumnUnderline (0); - table.setColumnUnderline (1); - table.setColumnUnderline (2); - table.setColumnUnderline (3); - table.setColumnUnderline (4); - table.setColumnUnderline (5); - table.setColumnUnderline (6); - } - else - table.setTableDashedUnderline (); - - table.setColumnWidth (0, Table::minimum); - table.setColumnWidth (1, Table::minimum); - table.setColumnWidth (2, Table::minimum); - table.setColumnWidth (3, Table::minimum); - table.setColumnWidth (4, Table::minimum); - table.setColumnWidth (5, Table::minimum); - table.setColumnWidth (6, Table::flexible); - - table.setColumnJustification (0, Table::right); - table.setColumnJustification (3, Table::right); - table.setColumnJustification (5, Table::right); - - table.sortOn (3, Table::ascendingDate); - table.sortOn (2, Table::descendingPriority); - table.sortOn (1, Table::ascendingCharacter); - - // Iterate over each task, and apply selection criteria. - foreach (i, matching) - { - Date now; - - // Now format the matching task. - bool imminent = false; - bool overdue = false; - std::string due = tasks[*i].get ("due"); - if (due.length ()) - { - switch (getDueState (due)) - { - case 2: overdue = true; break; - case 1: imminent = true; break; - case 0: - default: break; - } - - Date dt (::atoi (due.c_str ())); - due = dt.toString (context.config.get ("dateformat", "m/d/Y")); - } - - std::string active; - if (tasks[*i].has ("start")) - active = "*"; - - std::string age; - std::string created = tasks[*i].get ("entry"); - if (created.length ()) - { - Date dt (::atoi (created.c_str ())); - age = formatSeconds ((time_t) (now - dt)); - } - - // All criteria match, so add tasks[*i] to the output table. - int row = table.addRow (); - table.addCell (row, 0, tasks[*i].id); - table.addCell (row, 1, tasks[*i].get ("project")); - table.addCell (row, 2, tasks[*i].get ("priority")); - table.addCell (row, 3, due); - table.addCell (row, 4, active); - table.addCell (row, 5, age); - table.addCell (row, 6, getFullDescription (tasks[*i])); - - if (context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false)) - { - Text::color fg = Text::colorCode (tasks[*i].get ("fg")); - Text::color bg = Text::colorCode (tasks[*i].get ("bg")); - autoColorize (tasks[*i], fg, bg); - table.setRowFg (row, fg); - table.setRowBg (row, bg); - - if (fg == Text::nocolor) - { - if (overdue) - table.setCellFg (row, 3, Text::colorCode (context.config.get ("color.overdue", "red"))); - else if (imminent) - table.setCellFg (row, 3, Text::colorCode (context.config.get ("color.due", "yellow"))); - } - } - } - - std::stringstream out; - if (table.rowCount ()) - out << optionalBlankLine () - << table.render () - << optionalBlankLine () - << table.rowCount () - << (table.rowCount () == 1 ? " task" : " tasks") - << std::endl; - else - out << "No matches." - << std::endl; - - return out.str (); + return runCustomReport ( + "next", + columnList, + labelList, + sortList, + filterList, + tasks); } //////////////////////////////////////////////////////////////////////////////// @@ -1848,34 +1760,33 @@ std::string handleReportStats () } //////////////////////////////////////////////////////////////////////////////// -void gatherNextTasks ( - std::vector & tasks, - std::vector & all) +void gatherNextTasks (std::vector & tasks) { // For counting tasks by project. std::map countByProject; std::map matching; - + std::vector filtered; Date now; // How many items per project? Default 3. int limit = context.config.get ("next", 3); // due:< 1wk, pri:* - for (unsigned int i = 0; i < tasks.size (); ++i) + foreach (task, tasks) { - if (tasks[i].getStatus () == Task::pending) + if (task->getStatus () == Task::pending) { - if (tasks[i].has ("due")) + if (task->has ("due")) { - Date d (::atoi (tasks[i].get ("due").c_str ())); + Date d (::atoi (task->get ("due").c_str ())); if (d < now + (7 * 24 * 60 * 60)) // if due:< 1wk { - std::string project = tasks[i].get ("project"); - if (countByProject[project] < limit && matching.find (i) == matching.end ()) + std::string project = task->get ("project"); + if (countByProject[project] < limit && matching.find (task->id) == matching.end ()) { ++countByProject[project]; - matching[i] = true; + matching[task->id] = true; + filtered.push_back (*task); } } } @@ -1883,20 +1794,21 @@ void gatherNextTasks ( } // due:*, pri:H - for (unsigned int i = 0; i < tasks.size (); ++i) + foreach (task, tasks) { - if (tasks[i].getStatus () == Task::pending) + if (task->getStatus () == Task::pending) { - if (tasks[i].has ("due")) + if (task->has ("due")) { - std::string priority = tasks[i].get ("priority"); + std::string priority = task->get ("priority"); if (priority == "H") { - std::string project = tasks[i].get ("project"); - if (countByProject[project] < limit && matching.find (i) == matching.end ()) + std::string project = task->get ("project"); + if (countByProject[project] < limit && matching.find (task->id) == matching.end ()) { ++countByProject[project]; - matching[i] = true; + matching[task->id] = true; + filtered.push_back (*task); } } } @@ -1904,38 +1816,40 @@ void gatherNextTasks ( } // pri:H - for (unsigned int i = 0; i < tasks.size (); ++i) + foreach (task, tasks) { - if (tasks[i].getStatus () == Task::pending) + if (task->getStatus () == Task::pending) { - std::string priority = tasks[i].get ("priority"); + std::string priority = task->get ("priority"); if (priority == "H") { - std::string project = tasks[i].get ("project"); - if (countByProject[project] < limit && matching.find (i) == matching.end ()) + std::string project = task->get ("project"); + if (countByProject[project] < limit && matching.find (task->id) == matching.end ()) { ++countByProject[project]; - matching[i] = true; + matching[task->id] = true; + filtered.push_back (*task); } } } } // due:*, pri:M - for (unsigned int i = 0; i < tasks.size (); ++i) + foreach (task, tasks) { - if (tasks[i].getStatus () == Task::pending) + if (task->getStatus () == Task::pending) { - if (tasks[i].has ("due")) + if (task->has ("due")) { - std::string priority = tasks[i].get ("priority"); + std::string priority = task->get ("priority"); if (priority == "M") { - std::string project = tasks[i].get ("project"); - if (countByProject[project] < limit && matching.find (i) == matching.end ()) + std::string project = task->get ("project"); + if (countByProject[project] < limit && matching.find (task->id) == matching.end ()) { ++countByProject[project]; - matching[i] = true; + matching[task->id] = true; + filtered.push_back (*task); } } } @@ -1943,38 +1857,40 @@ void gatherNextTasks ( } // pri:M - for (unsigned int i = 0; i < tasks.size (); ++i) + foreach (task, tasks) { - if (tasks[i].getStatus () == Task::pending) + if (task->getStatus () == Task::pending) { - std::string priority = tasks[i].get ("priority"); + std::string priority = task->get ("priority"); if (priority == "M") { - std::string project = tasks[i].get ("project"); - if (countByProject[project] < limit && matching.find (i) == matching.end ()) + std::string project = task->get ("project"); + if (countByProject[project] < limit && matching.find (task->id) == matching.end ()) { ++countByProject[project]; - matching[i] = true; + matching[task->id] = true; + filtered.push_back (*task); } } } } // due:*, pri:L - for (unsigned int i = 0; i < tasks.size (); ++i) + foreach (task, tasks) { - if (tasks[i].getStatus () == Task::pending) + if (task->getStatus () == Task::pending) { - if (tasks[i].has ("due")) + if (task->has ("due")) { - std::string priority = tasks[i].get ("priority"); + std::string priority = task->get ("priority"); if (priority == "L") { - std::string project = tasks[i].get ("project"); - if (countByProject[project] < limit && matching.find (i) == matching.end ()) + std::string project = task->get ("project"); + if (countByProject[project] < limit && matching.find (task->id) == matching.end ()) { ++countByProject[project]; - matching[i] = true; + matching[task->id] = true; + filtered.push_back (*task); } } } @@ -1982,47 +1898,47 @@ void gatherNextTasks ( } // pri:L - for (unsigned int i = 0; i < tasks.size (); ++i) + foreach (task, tasks) { - if (tasks[i].getStatus () == Task::pending) + if (task->getStatus () == Task::pending) { - std::string priority = tasks[i].get ("priority"); + std::string priority = task->get ("priority"); if (priority == "L") { - std::string project = tasks[i].get ("project"); - if (countByProject[project] < limit && matching.find (i) == matching.end ()) + std::string project = task->get ("project"); + if (countByProject[project] < limit && matching.find (task->id) == matching.end ()) { ++countByProject[project]; - matching[i] = true; + matching[task->id] = true; + filtered.push_back (*task); } } } } // due:, pri: - for (unsigned int i = 0; i < tasks.size (); ++i) + foreach (task, tasks) { - if (tasks[i].getStatus () == Task::pending) + if (task->getStatus () == Task::pending) { - if (tasks[i].has ("due")) + if (task->has ("due")) { - std::string priority = tasks[i].get ("priority"); + std::string priority = task->get ("priority"); if (priority == "") { - std::string project = tasks[i].get ("project"); - if (countByProject[project] < limit && matching.find (i) == matching.end ()) + std::string project = task->get ("project"); + if (countByProject[project] < limit && matching.find (task->id) == matching.end ()) { ++countByProject[project]; - matching[i] = true; + matching[task->id] = true; + filtered.push_back (*task); } } } } } - // Convert map to vector. - foreach (i, matching) - all.push_back (i->first); + tasks = filtered; } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/tests/.gitignore b/src/tests/.gitignore index dd6441689..ffffbf248 100644 --- a/src/tests/.gitignore +++ b/src/tests/.gitignore @@ -15,3 +15,4 @@ subst.t filt.t cmd.t config.t +*.log From 104ad5a5b5b0db3a528c38766cf64f5f07b257b3 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Thu, 25 Jun 2009 01:24:48 -0400 Subject: [PATCH 7/7] Enhancement - timer - Now displays " sec" after timing display. --- src/Timer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Timer.cpp b/src/Timer.cpp index 9461b0f5b..5d25dd4f4 100644 --- a/src/Timer.cpp +++ b/src/Timer.cpp @@ -54,7 +54,8 @@ Timer::~Timer () << std::setprecision (6) << std::fixed << ((end.tv_sec - mStart.tv_sec) + ((end.tv_usec - mStart.tv_usec ) - / 1000000.0)); + / 1000000.0)) + << " sec"; context.debug (s.str ()); }