Merge branch '1.9.3' of tasktools.org:task into 1.9.3

This commit is contained in:
Johannes Schlatow
2010-10-04 02:20:52 +02:00
21 changed files with 309 additions and 250 deletions

View File

@@ -13,6 +13,9 @@
+ Added feature #391, now the 'task color legend' command will show + Added feature #391, now the 'task color legend' command will show
samples of all the defined colors and color rules from your .taskrc samples of all the defined colors and color rules from your .taskrc
and theme. and theme.
+ Added feature #410, and now task supports dependencies between tasks
with the syntax 'task 1 depends:2' to add a dependency, or 'task 1
depends:-2' to remove a dependency.
+ Added feature #421, and now task can sync data files from two sources + Added feature #421, and now task can sync data files from two sources
via the 'merge' command. via the 'merge' command.
+ Added feature #423, now custom report filters allow rc overrides. + Added feature #423, now custom report filters allow rc overrides.

4
NEWS
View File

@@ -51,6 +51,10 @@ New configuration options in taskwarrior 1.9.3
(e.g. merge.default.uri). (e.g. merge.default.uri).
- push.*.uri to configure target locations for the push command. - push.*.uri to configure target locations for the push command.
- pull.*.uri to configure source locations for the pull command. - pull.*.uri to configure source locations for the pull command.
- dependency.confirm controls whether dependency chain repair needs to be
confirmed.
- dependency.reminder controls whether the user is nagged about dependency
chain violations.
Newly deprecated features in taskwarrior 1.9.3 Newly deprecated features in taskwarrior 1.9.3

View File

@@ -520,6 +520,10 @@ specified, taskwarrior will only show as many that will fit.
.B dependency.reminder=on .B dependency.reminder=on
Determines whether dependency chain violations generate reminders. Determines whether dependency chain violations generate reminders.
.TP
.B dependency.confirm=yes
Determines whether dependency chain repair requires confirmation.
.SS COLOR CONTROLS .SS COLOR CONTROLS
.TP .TP

View File

@@ -104,6 +104,7 @@ std::string Config::defaults =
"\n" "\n"
"# Dependency controls\n" "# Dependency controls\n"
"dependency.reminder=on # Nags on dependency chain violations\n" "dependency.reminder=on # Nags on dependency chain violations\n"
"dependency.confirmation=on # Should dependency chain repair be confirmed?\n"
"\n" "\n"
"# Urgency Coefficients\n" "# Urgency Coefficients\n"
"urgency.next.coefficient=10.0 # Urgency coefficients for 'next' special tag\n" "urgency.next.coefficient=10.0 # Urgency coefficients for 'next' special tag\n"
@@ -649,13 +650,12 @@ std::string Config::checkForDeprecatedColor ()
if (deprecated.size ()) if (deprecated.size ())
{ {
out << "Your .taskrc file contains color settings that use deprecated " out << "Your .taskrc file contains color settings that use deprecated "
<< "underscores. Please check:" << "underscores. Please check:\n";
<< std::endl;
foreach (i, deprecated) foreach (i, deprecated)
out << " " << *i << "=" << get (*i) << std::endl; out << " " << *i << "=" << get (*i) << "\n";
out << std::endl; out << "\n";
} }
return out.str (); return out.str ();
@@ -678,18 +678,17 @@ std::string Config::checkForDeprecatedColumns ()
} }
std::stringstream out; std::stringstream out;
out << std::endl; out << "\n";
if (deprecated.size ()) if (deprecated.size ())
{ {
out << "Your .taskrc file contains reports with deprecated columns. " out << "Your .taskrc file contains reports with deprecated columns. "
<< "Please check for entry_time, start_time or end_time in:" << "Please check for entry_time, start_time or end_time in:\n";
<< std::endl;
foreach (i, deprecated) foreach (i, deprecated)
out << " " << *i << std::endl; out << " " << *i << "\n";
out << std::endl; out << "\n";
} }
return out.str (); return out.str ();

View File

@@ -161,9 +161,9 @@ int Context::run ()
if (config.getBoolean ("debug")) if (config.getBoolean ("debug"))
foreach (d, debugMessages) foreach (d, debugMessages)
if (config.getBoolean ("color") || config.getBoolean ("_forcecolor")) if (config.getBoolean ("color") || config.getBoolean ("_forcecolor"))
std::cout << colorizeDebug (*d) << std::endl; std::cout << colorizeDebug (*d) << "\n";
else else
std::cout << *d << std::endl; std::cout << *d << "\n";
hooks.trigger ("post-debug"); hooks.trigger ("post-debug");
// Dump all headers. // Dump all headers.
@@ -171,9 +171,9 @@ int Context::run ()
if (config.getBoolean ("verbose")) if (config.getBoolean ("verbose"))
foreach (h, headers) foreach (h, headers)
if (config.getBoolean ("color") || config.getBoolean ("_forcecolor")) if (config.getBoolean ("color") || config.getBoolean ("_forcecolor"))
std::cout << colorizeHeader (*h) << std::endl; std::cout << colorizeHeader (*h) << "\n";
else else
std::cout << *h << std::endl; std::cout << *h << "\n";
hooks.trigger ("post-header"); hooks.trigger ("post-header");
// Dump the report output. // Dump the report output.
@@ -186,9 +186,9 @@ int Context::run ()
if (config.getBoolean ("verbose")) if (config.getBoolean ("verbose"))
foreach (f, footnotes) foreach (f, footnotes)
if (config.getBoolean ("color") || config.getBoolean ("_forcecolor")) if (config.getBoolean ("color") || config.getBoolean ("_forcecolor"))
std::cout << colorizeFootnote (*f) << std::endl; std::cout << colorizeFootnote (*f) << "\n";
else else
std::cout << *f << std::endl; std::cout << *f << "\n";
hooks.trigger ("post-footnote"); hooks.trigger ("post-footnote");
hooks.trigger ("pre-exit"); hooks.trigger ("pre-exit");
@@ -764,7 +764,7 @@ void Context::parse (
else if (!foundNonSequence && else if (!foundNonSequence &&
(parseTask.id != 0 || parseSequence.size () != 0)) (parseTask.id != 0 || parseSequence.size () != 0))
{ {
std::cout << "No command - assuming 'info'." << std::endl; std::cout << "No command - assuming 'info'.\n";
parseCmd.command = "info"; parseCmd.command = "info";
} }
} }

View File

@@ -56,8 +56,7 @@ bool Permission::confirmed (const Task& task, const std::string& question)
if (allConfirmed) if (allConfirmed)
return true; return true;
std::cout << std::endl std::cout << "\nTask "
<< "Task "
<< task.id << task.id
<< " \"" << " \""
<< task.get ("description") << task.get ("description")
@@ -69,7 +68,7 @@ bool Permission::confirmed (const Task& task, const std::string& question)
std::cout << " (Recurring)"; std::cout << " (Recurring)";
} }
std::cout << std::endl; std::cout << std::endl; // Flush.
int answer = confirm4 (question); int answer = confirm4 (question);
if (answer == 2) if (answer == 2)

View File

@@ -416,7 +416,7 @@ void Table::calculateColumnWidths ()
} }
// Try again, treating minimum columns as flexible. // Try again, treating minimum columns as flexible.
// std::cout << "# no flexible columns. Now what?" << std::endl; // std::cout << "# no flexible columns. Now what?\n";
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@@ -314,7 +314,7 @@ void Tree::dumpNode (Tree* t, int depth)
if (tags.length ()) if (tags.length ())
std::cout << " \033[32m" << tags << "\033[0m"; std::cout << " \033[32m" << tags << "\033[0m";
std::cout << std::endl; std::cout << "\n";
// Recurse for branches. // Recurse for branches.
for (int i = 0; i < t->branches (); ++i) for (int i = 0; i < t->branches (); ++i)
@@ -324,7 +324,7 @@ void Tree::dumpNode (Tree* t, int depth)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void Tree::dump () void Tree::dump ()
{ {
std::cout << "Tree (" << count () << " nodes)" << std::endl; std::cout << "Tree (" << count () << " nodes)\n";
dumpNode (this, 1); dumpNode (this, 1);
} }

View File

@@ -885,14 +885,15 @@ int handleShow (std::string &outs)
"color.undo.after confirmation curses data.location dateformat " "color.undo.after confirmation curses data.location dateformat "
"dateformat.holiday dateformat.report dateformat.annotation debug " "dateformat.holiday dateformat.report dateformat.annotation debug "
"default.command default.priority default.project defaultwidth due " "default.command default.priority default.project defaultwidth due "
"dependency.reminder locale displayweeknumber export.ical.class " "dependency.confirmation dependency.reminder locale displayweeknumber "
"echo.command fontunderline locking monthsperline nag next journal.time " "export.ical.class echo.command fontunderline locking monthsperline nag "
"journal.time.start.annotation journal.time.stop.annotation project " "next journal.time journal.time.start.annotation "
"shadow.command shadow.file shadow.notify weekstart editor " "journal.time.stop.annotation project shadow.command shadow.file "
"import.synonym.id import.synonym.uuid complete.all.projects " "shadow.notify weekstart editor import.synonym.id import.synonym.uuid "
"complete.all.tags search.case.sensitive hooks active.indicator " "complete.all.projects complete.all.tags search.case.sensitive hooks "
"tag.indicator recurrence.indicator recurrence.limit list.all.projects " "active.indicator tag.indicator recurrence.indicator recurrence.limit "
"list.all.tags undo.style verbose rule.precedence.color merge.autopush " "list.all.projects list.all.tags undo.style verbose rule.precedence.color "
"merge.autopush "
#ifdef FEATURE_SHELL #ifdef FEATURE_SHELL
"shell.prompt " "shell.prompt "
#endif #endif

View File

@@ -533,12 +533,19 @@ int handleCustomReport (const std::string& report, std::string &outs)
table.setColumnJustification (columnCount, Table::left); table.setColumnJustification (columnCount, Table::left);
int row = 0; int row = 0;
std::vector <int> all; std::vector <Task> blocked;
std::vector <int> blocked_ids;
std::string deps; std::string deps;
foreach (task, tasks) foreach (task, tasks)
{ {
task->getDependencies (all); dependencyGetBlocking (*task, blocked);
join (deps, ", ", all); foreach (b, blocked)
blocked_ids.push_back (b->id);
join (deps, ",", blocked_ids);
blocked_ids.clear ();
blocked.clear ();
context.hooks.trigger ("format-depends", "depends", deps); context.hooks.trigger ("format-depends", "depends", deps);
table.addCell (row++, columnCount, deps); table.addCell (row++, columnCount, deps);
} }

View File

@@ -31,16 +31,16 @@
#include <Context.h> #include <Context.h>
#include <text.h> #include <text.h>
#include <util.h> #include <util.h>
#include <main.h>
extern Context context; extern Context context;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
static bool followUpstream (const Task&, const Task&, const std::vector <Task>&, static bool followUpstream (const Task&, const Task&, std::vector <std::string>&);
std::vector <std::string>&);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// A task is blocked if it depends on tasks that are pending or waiting. // A task is blocked if it depends on tasks that are pending or waiting.
bool dependencyIsBlocked (Task& task) bool dependencyIsBlocked (const Task& task)
{ {
if (task.has ("depends")) if (task.has ("depends"))
{ {
@@ -58,26 +58,25 @@ bool dependencyIsBlocked (Task& task)
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void dependencyGetBlocked (Task& task, std::vector <Task>& blocked) void dependencyGetBlocked (const Task& task, std::vector <Task>& blocked)
{ {
std::string depends = task.get ("depends"); std::string uuid = task.get ("uuid");
if (depends != "")
{ const std::vector <Task>& all = context.tdb.getAllPending ();
const std::vector <Task>& all = context.tdb.getAllPending (); std::vector <Task>::const_iterator it;
std::vector <Task>::const_iterator it; for (it = all.begin (); it != all.end (); ++it)
for (it = all.begin (); it != all.end (); ++it) if ((it->getStatus () == Task::pending ||
if ((it->getStatus () == Task::pending || it->getStatus () == Task::waiting) &&
it->getStatus () == Task::waiting) && it->has ("depends") &&
depends.find (it->get ("uuid")) != std::string::npos) it->get ("depends").find (uuid) != std::string::npos)
blocked.push_back (*it); blocked.push_back (*it);
}
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// To be a blocking task, there must be at least one other task that depends on // To be a blocking task, there must be at least one other task that depends on
// this task, that is either pending or waiting. // this task, that is either pending or waiting.
bool dependencyIsBlocking (Task& task) bool dependencyIsBlocking (const Task& task)
{ {
std::string uuid = task.get ("uuid"); std::string uuid = task.get ("uuid");
@@ -94,18 +93,19 @@ bool dependencyIsBlocking (Task& task)
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void dependencyGetBlocking (Task& task, std::vector <Task>& blocking) void dependencyGetBlocking (const Task& task, std::vector <Task>& blocking)
{ {
std::string uuid = task.get ("uuid"); std::string depends = task.get ("depends");
if (depends != "")
const std::vector <Task>& all = context.tdb.getAllPending (); {
std::vector <Task>::const_iterator it; const std::vector <Task>& all = context.tdb.getAllPending ();
for (it = all.begin (); it != all.end (); ++it) std::vector <Task>::const_iterator it;
if ((it->getStatus () == Task::pending || for (it = all.begin (); it != all.end (); ++it)
it->getStatus () == Task::waiting) && if ((it->getStatus () == Task::pending ||
it->has ("depends") && it->getStatus () == Task::waiting) &&
it->get ("depends").find (uuid) != std::string::npos) depends.find (it->get ("uuid")) != std::string::npos)
blocking.push_back (*it); blocking.push_back (*it);
}
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -118,12 +118,10 @@ void dependencyGetBlocking (Task& task, std::vector <Task>& blocking)
// Keep walking the chain, recording the links (a --> b, b --> c, ...) until // Keep walking the chain, recording the links (a --> b, b --> c, ...) until
// either the end of the chain is found (therefore not circular), or the chain // either the end of the chain is found (therefore not circular), or the chain
// loops and a repeat link is spotted (therefore circular). // loops and a repeat link is spotted (therefore circular).
bool dependencyIsCircular (Task& task) bool dependencyIsCircular (const Task& task)
{ {
std::vector <std::string> links; std::vector <std::string> seen;
const std::vector <Task>& all = context.tdb.getAllPending (); return followUpstream (task, task, seen);
return followUpstream (task, task, all, links);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -132,50 +130,27 @@ bool dependencyIsCircular (Task& task)
static bool followUpstream ( static bool followUpstream (
const Task& task, const Task& task,
const Task& original, const Task& original,
const std::vector <Task>& all, std::vector <std::string>& seen)
std::vector <std::string>& links)
{ {
if (task.has ("depends")) std::vector <Task> blocking;
dependencyGetBlocking (task, blocking);
foreach (b, blocking)
{ {
std::vector <std::string> uuids; std::string link = task.get ("uuid") + " -> " + b->get ("uuid");
split (uuids, task.get ("depends"), ',');
std::vector <std::string>::iterator outer; // Have we seen this link before? If so, circularity has been detected.
for (outer = uuids.begin (); outer != uuids.end (); ++outer) if (std::find (seen.begin (), seen.end (), link) != seen.end ())
{ return true;
// Check that link has not already been seen.
// This is the actual circularity check - the rest of this function is seen.push_back (link);
// just chain-walking.
std::string link = task.get ("uuid") + " -> " + *outer;
if (std::find (links.begin (), links.end (), link) != links.end ())
return true;
links.push_back (link); // Use 'original' over '*b' if they both refer to the same task, otherwise
// '*b' is from TDB's committed list, and lacks recent modifications.
// Recurse up the chain. if (followUpstream (
std::vector <Task>::const_iterator inner; (b->get ("uuid") == original.get ("uuid") ? original : *b),
for (inner = all.begin (); inner != all.end (); ++inner) original,
{ seen))
if (*outer == inner->get ("uuid")) return true;
{
// Use the newly modified "task", not "*inner", which is the old
// unmodified version.
if (*outer == original.get ("uuid"))
{
if (followUpstream (task, original, all, links))
return true;
}
else
{
if (followUpstream (*inner, original, all, links))
return true;
}
break;
}
}
}
} }
return false; return false;
@@ -215,35 +190,49 @@ void dependencyChainOnComplete (Task& task)
std::vector <Task> blocking; std::vector <Task> blocking;
dependencyGetBlocking (task, blocking); dependencyGetBlocking (task, blocking);
std::cout << "# Task " << task.id << "\n";
foreach (t, blocking)
std::cout << "# blocking " << t->id << " " << t->get ("uuid") << "\n";
// If the task is anything but the tail end of a dependency chain. // If the task is anything but the tail end of a dependency chain.
if (blocking.size ()) if (blocking.size ())
{ {
std::vector <Task> blocked; std::vector <Task> blocked;
dependencyGetBlocked (task, blocked); dependencyGetBlocked (task, blocked);
foreach (t, blocked) // Nag about broken chain.
std::cout << "# blocked by " << t->id << " " << t->get ("uuid") << "\n"; if (context.config.getBoolean ("dependency.reminder"))
{
std::cout << "Task " << task.id << " is blocked by:\n";
foreach (b, blocking)
std::cout << " " << b->id << " " << b->get ("description") << "\n";
}
// If there are both blocking and blocked tasks, the chain is broken. // If there are both blocking and blocked tasks, the chain is broken.
if (blocked.size ()) if (blocked.size ())
{ {
// TODO Nag about broken chain. if (context.config.getBoolean ("dependency.reminder"))
std::cout << "# Chain broken - offer to repair\n";
// TODO Confirm that the chain should be repaired.
// Repair the chain - everything in blocked should now depend on
// everything in blocking, instead of task.id.
foreach (left, blocked)
{ {
left->removeDependency (task.id); std::cout << "and is blocking:\n";
foreach (b, blocked)
std::cout << " " << b->id << " " << b->get ("description") << "\n";
}
if (!context.config.getBoolean ("dependency.confirmation") ||
confirm ("Would you like the dependency chain fixed?"))
{
// Repair the chain - everything in blocked should now depend on
// everything in blocking, instead of task.id.
foreach (left, blocked)
{
left->removeDependency (task.id);
foreach (right, blocking)
left->addDependency (right->id);
}
// Now update TDB, now that the updates have all occurred.
foreach (left, blocked)
context.tdb.update (*left);
foreach (right, blocking) foreach (right, blocking)
left->addDependency (right->id); context.tdb.update (*right);
} }
} }
} }
@@ -252,27 +241,64 @@ void dependencyChainOnComplete (Task& task)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void dependencyChainOnStart (Task& task) void dependencyChainOnStart (Task& task)
{ {
std::stringstream out; if (context.config.getBoolean ("dependency.reminder"))
if (context.config.getBoolean ("dependency.reminder") /* &&
TODO check that task is actually blocked */)
{ {
out << "# dependencyChainScan nag! " std::vector <Task> blocking;
<< task.id dependencyGetBlocking (task, blocking);
<< " "
<< task.get ("uuid")
<< "\n";
context.footnote (out.str ()); // If the task is anything but the tail end of a dependency chain, nag about
// broken chain.
if (blocking.size ())
{
std::cout << "Task " << task.id << " is blocked by:\n";
foreach (b, blocking)
std::cout << " " << b->id << " " << b->get ("description") << "\n";
}
} }
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Iff a dependency is being removed, is there something to do.
void dependencyChainOnModify (Task& before, Task& after) void dependencyChainOnModify (Task& before, Task& after)
{ {
// TODO Iff a dependency is being removed, is there anything to do. // TODO It is not clear that this should even happen. TBD.
/*
// Get the dependencies from before.
std::string depends = before.get ("depends");
std::vector <std::string> before_depends;
split (before_depends, depends, ',');
std::cout << "# dependencyChainOnModify before has " << before_depends.size () << "\n";
// Get the dependencies from after.
depends = after.get ("depends");
std::vector <std::string> after_depends;
split (after_depends, depends, ',');
std::cout << "# dependencyChainOnModify after has " << after_depends.size () << "\n";
// listDiff
std::vector <std::string> before_only;
std::vector <std::string> after_only;
listDiff (before_depends, after_depends, before_only, after_only);
// Any dependencies in before_only indicates that a dependency was removed.
if (before_only.size ())
{
std::cout << "# dependencyChainOnModify detected a dependency removal\n";
// before dep:2,3
// after dep:2
//
// any tasks blocked by after might should be repaired to depend on 3.
std::vector <Task> blocked;
dependencyGetBlocked (after, blocked);
foreach (b, blocked)
{
std::cout << "# dependencyChainOnModify\n";
}
}
*/
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@@ -338,8 +338,7 @@ static std::string importTask_1_4_3 (const std::vector <std::string>& lines)
<< (lines.size () - failed.size () - 1) << (lines.size () - failed.size () - 1)
<< " tasks successfully, with " << " tasks successfully, with "
<< failed.size () << failed.size ()
<< " errors." << " errors.\n";
<< std::endl;
if (failed.size ()) if (failed.size ())
{ {
@@ -500,8 +499,7 @@ static std::string importTask_1_5_0 (const std::vector <std::string>& lines)
<< (lines.size () - failed.size () - 1) << (lines.size () - failed.size () - 1)
<< " tasks successfully, with " << " tasks successfully, with "
<< failed.size () << failed.size ()
<< " errors." << " errors.\n";
<< std::endl;
if (failed.size ()) if (failed.size ())
{ {
@@ -663,8 +661,7 @@ static std::string importTask_1_6_0 (const std::vector <std::string>& lines)
<< (lines.size () - failed.size () - 1) << (lines.size () - failed.size () - 1)
<< " tasks successfully, with " << " tasks successfully, with "
<< failed.size () << failed.size ()
<< " errors." << " errors.\n";
<< std::endl;
if (failed.size ()) if (failed.size ())
{ {
@@ -711,8 +708,7 @@ static std::string importTaskCmdLine (const std::vector <std::string>& lines)
<< (lines.size () - failed.size ()) << (lines.size () - failed.size ())
<< " tasks successfully, with " << " tasks successfully, with "
<< failed.size () << failed.size ()
<< " errors." << " errors.\n";
<< std::endl;
if (failed.size ()) if (failed.size ())
{ {
@@ -840,8 +836,7 @@ static std::string importTodoSh_2_0 (const std::vector <std::string>& lines)
<< (lines.size () - failed.size ()) << (lines.size () - failed.size ())
<< " tasks successfully, with " << " tasks successfully, with "
<< failed.size () << failed.size ()
<< " errors." << " errors.\n";
<< std::endl;
if (failed.size ()) if (failed.size ())
{ {
@@ -904,8 +899,7 @@ static std::string importText (const std::vector <std::string>& lines)
<< count << count
<< " tasks successfully, with " << " tasks successfully, with "
<< failed.size () << failed.size ()
<< " errors." << " errors.\n";
<< std::endl;
if (failed.size ()) if (failed.size ())
{ {
@@ -1150,8 +1144,7 @@ static std::string importCSV (const std::vector <std::string>& lines)
<< (lines.size () - failed.size () - 1) << (lines.size () - failed.size () - 1)
<< " tasks successfully, with " << " tasks successfully, with "
<< failed.size () << failed.size ()
<< " errors." << " errors.\n";
<< std::endl;
if (failed.size ()) if (failed.size ())
{ {
@@ -1255,8 +1248,7 @@ static std::string importYAML (const std::vector <std::string>& lines)
std::stringstream out; std::stringstream out;
out << "Imported " out << "Imported "
<< count << count
<< " tasks successfully." << " tasks successfully.\n";
<< std::endl;
return out.str (); return out.str ();
} }

View File

@@ -76,13 +76,13 @@ int main (int argc, char** argv)
catch (std::string& error) catch (std::string& error)
{ {
std::cout << error << std::endl; std::cout << error << "\n";
return -1; return -1;
} }
catch (...) catch (...)
{ {
std::cerr << context.stringtable.get (100, "Unknown error.") << std::endl; std::cerr << context.stringtable.get (100, "Unknown error.") << "\n";
return -2; return -2;
} }

View File

@@ -135,11 +135,11 @@ int handleExportiCal (std::string &);
int handleExportYAML (std::string &); int handleExportYAML (std::string &);
// dependency.cpp // dependency.cpp
bool dependencyIsBlocked (Task&); bool dependencyIsBlocked (const Task&);
void dependencyGetBlocked (Task&, std::vector <Task>&); void dependencyGetBlocked (const Task&, std::vector <Task>&);
bool dependencyIsBlocking (Task&); bool dependencyIsBlocking (const Task&);
void dependencyGetBlocking (Task&, std::vector <Task>&); void dependencyGetBlocking (const Task&, std::vector <Task>&);
bool dependencyIsCircular (Task&); bool dependencyIsCircular (const Task&);
void dependencyChainOnComplete (Task&); void dependencyChainOnComplete (Task&);
void dependencyChainOnStart (Task&); void dependencyChainOnStart (Task&);
void dependencyChainOnModify (Task&, Task&); void dependencyChainOnModify (Task&, Task&);

View File

@@ -74,8 +74,7 @@ void handleRecurrence ()
{ {
std::cout << "Task (" std::cout << "Task ("
<< trim (t->get ("description")) << trim (t->get ("description"))
<< ") has past its 'until' date, and has been deleted." << ") has past its 'until' date, and has been deleted.\n";
<< std::endl;
// Determine the end date. // Determine the end date.
char endTime[16]; char endTime[16];
@@ -472,11 +471,12 @@ bool nag (Task& task)
} }
// General form is "if there are no more deserving tasks", suppress the nag. // General form is "if there are no more deserving tasks", suppress the nag.
if (isOverdue ) return false; if (isOverdue ) return false;
if (pri == 'H' && !overdue ) return false; if (pri == 'H' && !overdue ) return false;
if (pri == 'M' && !overdue && !high ) return false; if (pri == 'M' && !overdue && !high ) return false;
if (pri == 'L' && !overdue && !high && !medium ) return false; if (pri == 'L' && !overdue && !high && !medium ) return false;
if (pri == ' ' && !overdue && !high && !medium && !low) return false; if (pri == ' ' && !overdue && !high && !medium && !low ) return false;
if (dependencyIsBlocking (task) && !dependencyIsBlocked (task)) return false;
// All the excuses are made, all that remains is to nag the user. // All the excuses are made, all that remains is to nag the user.
context.footnote (nagMessage); context.footnote (nagMessage);

View File

@@ -444,7 +444,7 @@ int handleInfo (std::string &outs)
// dependencies: blocked // dependencies: blocked
{ {
std::vector <Task> blocked; std::vector <Task> blocked;
dependencyGetBlocked (*task, blocked); dependencyGetBlocking (*task, blocked);
if (blocked.size ()) if (blocked.size ())
{ {
std::stringstream message; std::stringstream message;
@@ -461,7 +461,7 @@ int handleInfo (std::string &outs)
// dependencies: blocking // dependencies: blocking
{ {
std::vector <Task> blocking; std::vector <Task> blocking;
dependencyGetBlocking (*task, blocking); dependencyGetBlocked (*task, blocking);
if (blocking.size ()) if (blocking.size ())
{ {
std::stringstream message; std::stringstream message;
@@ -2633,6 +2633,22 @@ void gatherNextTasks (std::vector <Task>& tasks)
} }
} }
// blocking, not blocked
foreach (task, tasks)
{
if (dependencyIsBlocking (*task) &&
! dependencyIsBlocked (*task))
{
std::string project = task->get ("project");
if (countByProject[project] < limit && matching.find (task->id) == matching.end ())
{
++countByProject[project];
matching[task->id] = true;
filtered.push_back (*task);
}
}
}
// due:*, pri:H // due:*, pri:H
foreach (task, tasks) foreach (task, tasks)
{ {

View File

@@ -81,7 +81,7 @@ void initializeColorRules ()
static void colorizeBlocked (Task& task, const std::string& rule, Color& c) static void colorizeBlocked (Task& task, const std::string& rule, Color& c)
{ {
if (gsColor[rule].nontrivial ()) if (gsColor[rule].nontrivial ())
if (task.get ("depends") != "") if (dependencyIsBlocked (task))
c.blend (gsColor[rule]); c.blend (gsColor[rule]);
} }

View File

@@ -28,59 +28,71 @@
use strict; use strict;
use warnings; use warnings;
use Test::More tests => 39; use Test::More tests => 41;
# Create the rc file. # Create the rc file.
if (open my $fh, '>', 'dep.rc') if (open my $fh, '>', 'dep.rc')
{ {
print $fh "data.location=.\n"; print $fh "data.location=.\n";
print $fh "dependency.confirm=yes\n"; print $fh "dependency.confirmation=yes\n";
print $fh "report.depreport.columns=id,depends,description\n"; print $fh "report.depreport.columns=id,depends,description\n";
print $fh "report.depreport.labels=ID,Depends,Description\n"; print $fh "report.depreport.labels=ID,Depends,Description\n";
print $fh "report.depreport.filter=status:pending\n"; print $fh "report.depreport.filter=status:pending\n";
print $fh "report.depreport.sort=depends+\n"; print $fh "report.depreport.sort=depends+\n";
print $fh "nag=NAG";
close $fh; close $fh;
# [1]
ok (-r 'dep.rc', 'Created dep.rc'); ok (-r 'dep.rc', 'Created dep.rc');
} }
qx{../task rc:dep.rc add One}; qx{../task rc:dep.rc add One};
qx{../task rc:dep.rc add Two}; qx{../task rc:dep.rc add Two};
# [2]
my $output = qx{../task rc:dep.rc 1 dep:-2}; my $output = qx{../task rc:dep.rc 1 dep:-2};
like ($output, qr/Modified 0 tasks\./, 'dependencies - remove nonexistent dependency'); like ($output, qr/Modified 0 tasks\./, 'dependencies - remove nonexistent dependency');
# [3]
$output = qx{../task rc:dep.rc 1 dep:99}; $output = qx{../task rc:dep.rc 1 dep:99};
like ($output, qr/Could not create a dependency on task 99 - not found\./, 'dependencies - add dependency for nonexistent task'); like ($output, qr/Could not create a dependency on task 99 - not found\./, 'dependencies - add dependency for nonexistent task');
# [4]
$output = qx{../task rc:dep.rc 99 dep:1}; $output = qx{../task rc:dep.rc 99 dep:1};
like ($output, qr/Task 99 not found\./, 'dependencies - add dependency to nonexistent task'); like ($output, qr/Task 99 not found\./, 'dependencies - add dependency to nonexistent task');
# t 1 dep:2; t info 1 => blocked by 2 # [5,6] t 1 dep:2; t info 1 => blocked by 2
$output = qx{../task rc:dep.rc 1 dep:2; ../task rc:dep.rc info 1}; $output = qx{../task rc:dep.rc 1 dep:2; ../task rc:dep.rc info 1};
like ($output, qr/This task blocked by\s+2 Two\nUUID/, 'dependencies - trivial blocked'); like ($output, qr/This task blocked by\s+2 Two\nUUID/, 'dependencies - trivial blocked');
unlike ($output, qr/This task is blocking\n/, 'dependencies - trivial blocked'); unlike ($output, qr/This task is blocking\n/, 'dependencies - trivial blocked');
# t info 2 => blocking 1 # [7,8] t info 2 => blocking 1
$output = qx{../task rc:dep.rc info 2}; $output = qx{../task rc:dep.rc info 2};
unlike ($output, qr/This task blocked by/, 'dependencies - trivial blocking'); unlike ($output, qr/This task blocked by/, 'dependencies - trivial blocking');
like ($output, qr/This task is blocking\s+1 One\nUUID/, 'dependencies - trivial blocking'); like ($output, qr/This task is blocking\s+1 One\nUUID/, 'dependencies - trivial blocking');
# t 1 dep:2 (again) # [9] t 1 dep:2 (again)
$output = qx{../task rc:dep.rc 1 dep:2}; $output = qx{../task rc:dep.rc 1 dep:2};
like ($output, qr/Task 1 already depends on task 2\./, 'dependencies - add already existing dependency'); like ($output, qr/Task 1 already depends on task 2\./, 'dependencies - add already existing dependency');
# t 1 dep:1 => error # [10,11] t 1 dep:1 => error
$output = qx{../task rc:dep.rc 1 dep:1}; $output = qx{../task rc:dep.rc 1 dep:1};
like ($output, qr/A task cannot be dependent on itself\./, 'dependencies - cannot depend on self'); like ($output, qr/A task cannot be dependent on itself\./, 'dependencies - cannot depend on self');
unlike ($output, qr/Modified 1 task\./, 'dependencies - cannot depend on self'); unlike ($output, qr/Modified 1 task\./, 'dependencies - cannot depend on self');
# t 1 dep:2; t 2 dep:1 => error # [12,13] t 1 dep:2; t 2 dep:1 => error
$output = qx{../task rc:dep.rc 2 dep:1}; $output = qx{../task rc:dep.rc 2 dep:1};
like ($output, qr/Circular dependency detected and disallowed\./, 'dependencies - trivial circular'); like ($output, qr/Circular dependency detected and disallowed\./, 'dependencies - trivial circular');
unlike ($output, qr/Modified 1 task\./, 'dependencies - trivial circular'); unlike ($output, qr/Modified 1 task\./, 'dependencies - trivial circular');
# [14,15] t 1 dep:2; t 2 dep:3; t 1 dep:3 => not circular
qx{../task rc:dep.rc 1 dep:2};
qx{../task rc:dep.rc add Three};
qx{../task rc:dep.rc 2 dep:3};
$output = qx{../task rc:dep.rc 1 dep:3};
unlike ($output, qr/Circular dependency detected and disallowed\./, 'dependencies - diamond, non-circular');
like ($output, qr/Modified 1 task\./, 'dependencies - diamond, non-circular');
# [16]
unlink 'pending.data'; unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data for a fresh start'); ok (!-r 'pending.data', 'Removed pending.data for a fresh start');
@@ -92,11 +104,12 @@ qx{../task rc:dep.rc add Five};
qx{../task rc:dep.rc 5 dep:4; ../task rc:dep.rc 4 dep:3; ../task rc:dep.rc 3 dep:2; ../task rc:dep.rc 2 dep:1}; qx{../task rc:dep.rc 5 dep:4; ../task rc:dep.rc 4 dep:3; ../task rc:dep.rc 3 dep:2; ../task rc:dep.rc 2 dep:1};
# 5 dep 4 dep 3 dep 2 dep 1 dep 5 => error # [17,18] 5 dep 4 dep 3 dep 2 dep 1 dep 5 => error
$output = qx{../task rc:dep.rc 1 dep:5}; $output = qx{../task rc:dep.rc 1 dep:5};
like ($output, qr/Circular dependency detected and disallowed\./, 'dependencies - nontrivial circular'); like ($output, qr/Circular dependency detected and disallowed\./, 'dependencies - nontrivial circular');
unlike ($output, qr/Modified 1 task\./, 'dependencies - nontrivial circular'); unlike ($output, qr/Modified 1 task\./, 'dependencies - nontrivial circular');
# [19]
unlink 'pending.data'; unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data for a fresh start'); ok (!-r 'pending.data', 'Removed pending.data for a fresh start');
@@ -107,23 +120,28 @@ qx{../task rc:dep.rc add Four};
qx{../task rc:dep.rc add Five}; qx{../task rc:dep.rc add Five};
qx{../task rc:dep.rc add Six recurring due:tomorrow recur:daily}; qx{../task rc:dep.rc add Six recurring due:tomorrow recur:daily};
# [20]
$output = qx{../task rc:dep.rc 6 dep:5}; $output = qx{../task rc:dep.rc 6 dep:5};
unlike ($output,qr/Modified \d+ task/, 'dependencies - recurring task depending on another task'); like ($output, qr/Modified \d+ task/, 'dependencies - recurring task depending on another task');
# [21]
$output = qx{../task rc:dep.rc 5 dep:6}; $output = qx{../task rc:dep.rc 5 dep:6};
like ($output,qr/Modified \d+ task/, 'dependencies - task depending on recurring task'); like ($output, qr/Modified \d+ task/, 'dependencies - task depending on recurring task');
# t 1 dep:2,3,4; t 1 dep:-2,-4,5; t info 1 => blocked by 3,5 # [22] t 1 dep:2,3,4; t 1 dep:-2,-4,5; t info 1 => blocked by 3,5
$output = qx{../task rc:dep.rc 1 dep:2,3,4; ../task rc:dep.rc 1 dep:-2,-4,5; ../task rc:dep.rc info 1}; $output = qx{../task rc:dep.rc 1 dep:2,3,4; ../task rc:dep.rc 1 dep:-2,-4,5; ../task rc:dep.rc info 1};
like ($output, qr/This task blocked by\s+3 Three\n\s+5 Five\nThis task is blocking/, 'dependencies - multiple dependencies modified'); like ($output, qr/This task blocked by\s+3 Three\n\s+5 Five\nUUID/, 'dependencies - multiple dependencies modified');
# [23,24]
$output = qx{../task rc:dep.rc do 3,5; ../task rc:dep.rc info 1}; $output = qx{../task rc:dep.rc do 3,5; ../task rc:dep.rc info 1};
unlike ($output, qr/This task blocked by/, 'dependencies - task info reflects completed dependencies'); unlike ($output, qr/This task blocked by/, 'dependencies - task info reflects completed dependencies');
unlike ($output, qr/This task is blocking/, 'dependencies - task info reflects completed dependencies'); unlike ($output, qr/This task is blocking/, 'dependencies - task info reflects completed dependencies');
# [25]
$output = qx{../task rc:dep.rc depreport}; $output = qx{../task rc:dep.rc depreport};
like ($output, qr/\s1\s+One\s+/, 'dependencies - depends report column reflects completed dependencies'); like ($output, qr/\s1\s+One\s+/, 'dependencies - depends report column reflects completed dependencies');
# [26]
unlink 'pending.data'; unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data for a fresh start'); ok (!-r 'pending.data', 'Removed pending.data for a fresh start');
@@ -135,12 +153,16 @@ qx{../task rc:dep.rc add Four};
qx{../task rc:dep.rc 1 dep:3,4}; qx{../task rc:dep.rc 1 dep:3,4};
qx{../task rc:dep.rc do 2}; qx{../task rc:dep.rc do 2};
# [27]
$output = qx{../task rc:dep.rc depreport}; $output = qx{../task rc:dep.rc depreport};
like ($output, qr/\s1\s+2, 3\s+One\s+/, 'dependencies - depends report column reflects changed IDs'); like ($output, qr/\s1\s+2,3\s+One\s+/, 'dependencies - depends report column reflects changed IDs');
# [28]
qx{../task rc:dep.rc do 3};
$output = qx{../task rc:dep.rc depreport}; $output = qx{../task rc:dep.rc depreport};
like ($output, qr/\s1\s+One\s+/, 'dependencies - depends report column reflects completed dependencies'); like ($output, qr/\s1\s+2\s+One\s+/, 'dependencies - depends report column reflects completed dependencies');
# [29]
unlink 'pending.data'; unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data for a fresh start'); ok (!-r 'pending.data', 'Removed pending.data for a fresh start');
@@ -151,17 +173,20 @@ qx{../task rc:dep.rc add Four};
qx{../task rc:dep.rc 2 dep:1; ../task rc:dep.rc 3 dep:2; ../task rc:dep.rc 4 dep:3}; qx{../task rc:dep.rc 2 dep:1; ../task rc:dep.rc 3 dep:2; ../task rc:dep.rc 4 dep:3};
# [30,31]
$output = qx{echo y | ../task rc:dep.rc do 2}; $output = qx{echo y | ../task rc:dep.rc do 2};
like ($output, qr/fixed/, 'dependencies - user prompted to fix broken chain after completing a blocked task'); like ($output, qr/fixed/, 'dependencies - user prompted to fix broken chain after completing a blocked task');
like ($output, qr/is blocked by/, 'dependencies - user nagged for completing a blocked task');
like ($output, qr/NAG/, 'dependencies - user nagged for completing a blocked task'); # [32]
$output = qx{echo y | ../task rc:dep.rc do 1}; $output = qx{echo y | ../task rc:dep.rc do 1};
unlike ($output, qr/fixed/, 'dependencies - user not prompted to fix broken chain when the head of the chain is marked as complete'); unlike ($output, qr/fixed/, 'dependencies - user not prompted to fix broken chain when the head of the chain is marked as complete');
# [33]
$output = qx{echo y | ../task rc:dep.rc del 4}; $output = qx{echo y | ../task rc:dep.rc del 4};
unlike ($output, qr/fixed/, 'dependencies - user not prompted to fix broken chain when the tail of the chain is deleted'); unlike ($output, qr/fixed/, 'dependencies - user not prompted to fix broken chain when the tail of the chain is deleted');
# [34]
unlink 'pending.data'; unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data for a fresh start'); ok (!-r 'pending.data', 'Removed pending.data for a fresh start');
@@ -176,20 +201,22 @@ qx{../task rc:dep.rc 3 dep:2};
qx{../task rc:dep.rc 4 dep:3}; qx{../task rc:dep.rc 4 dep:3};
qx{../task rc:dep.rc 5 dep:4}; qx{../task rc:dep.rc 5 dep:4};
# [35]
qx{echo y | ../task rc:dep.rc do 2}; qx{echo y | ../task rc:dep.rc do 2};
$output = qx{../task rc:dep.rc depreport}; $output = qx{../task rc:dep.rc depreport};
like ($output, qr/\s1\s+One\s*\n\s2\s+1\s+Three\s*\n\s3\s+2\s+Four\s*\n\s4\s+3\s+Five/, 'dependencies - fixed chain after completing a blocked task'); like ($output, qr/\s1\s+One\s*\n\s2\s+1\s+Three\s*\n\s3\s+2\s+Four\s*\n\s4\s+3\s+Five/, 'dependencies - fixed chain after completing a blocked task');
# [36]
qx{printf "Y\nY\n" | ../task rc:dep.rc del 2}; qx{printf "Y\nY\n" | ../task rc:dep.rc del 2};
$output = qx{../task rc:dep.rc depreport}; $output = qx{../task rc:dep.rc depreport};
like ($output, qr/\s1\s+One\s*\n\s2\s+1\s+Four\s*\n\s3\s+2\s+Five/, 'dependencies - fixed chain after deleting a blocked task'); like ($output, qr/\s1\s+One\s*\n\s2\s+1\s+Four\s*\n\s3\s+2\s+Five/, 'dependencies - fixed chain after deleting a blocked task');
# [37]
qx{../task rc:dep.rc 2 dep:-1}; qx{../task rc:dep.rc 2 dep:-1};
$output = qx{../task rc:dep.rc depreport}; $output = qx{../task rc:dep.rc depreport};
like ($output, qr/\s1\s+One\s*\n\s2\s+Four\s*\n\s3\s+2\s+Five/, 'dependencies - chain should not be automatically repaired after manually removing a dependency'); like ($output, qr/\s1\s+One\s*\n\s2\s+Four\s*\n\s3\s+2\s+Five/, 'dependencies - chain should not be automatically repaired after manually removing a dependency');
# TODO - test dependency.confirm config variable # TODO - test dependency.confirmation config variable
# TODO - test undo on backing out chain gap repair # TODO - test undo on backing out chain gap repair
# TODO - test undo on backing out choice to not perform chain gap repair # TODO - test undo on backing out choice to not perform chain gap repair
# TODO - test blocked task completion nag # TODO - test blocked task completion nag

View File

@@ -50,7 +50,7 @@ int main (int argc, char** argv)
std::ofstream one ("./sensor.foo", std::ios_base::out | std::ios_base::app); std::ofstream one ("./sensor.foo", std::ios_base::out | std::ios_base::app);
if (one.good ()) if (one.good ())
{ {
one << "touch" << std::endl; one << "touch\n";
one.close (); one.close ();
} }
@@ -65,7 +65,7 @@ int main (int argc, char** argv)
std::ofstream two ("./sensor.foo", std::ios_base::out | std::ios_base::app); std::ofstream two ("./sensor.foo", std::ios_base::out | std::ios_base::app);
if (two.good ()) if (two.good ())
{ {
two << "touch" << std::endl; two << "touch\n";
two.close (); two.close ();
} }

View File

@@ -50,7 +50,7 @@ UnitTest::UnitTest (int planned)
, mFailed (0) , mFailed (0)
, mSkipped (0) , mSkipped (0)
{ {
std::cout << "1.." << mPlanned << std::endl; std::cout << "1.." << mPlanned << "\n";
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@@ -66,8 +66,7 @@ UnitTest::~UnitTest ()
<< mCounter << mCounter
<< " tests, out of a planned " << " tests, out of a planned "
<< mPlanned << mPlanned
<< " were run." << " were run.\n";
<< std::endl;
mSkipped += mPlanned - mCounter; mSkipped += mPlanned - mCounter;
} }
@@ -76,8 +75,7 @@ UnitTest::~UnitTest ()
<< mCounter << mCounter
<< " tests were run, but only " << " tests were run, but only "
<< mPlanned << mPlanned
<< " were planned." << " were planned.\n";
<< std::endl;
std::cout << "# " std::cout << "# "
<< mPassed << mPassed
@@ -87,8 +85,7 @@ UnitTest::~UnitTest ()
<< mSkipped << mSkipped
<< " skipped. " << " skipped. "
<< std::setprecision (3) << percentPassed << std::setprecision (3) << percentPassed
<< "% passed." << "% passed.\n";
<< std::endl;
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@@ -100,14 +97,14 @@ void UnitTest::plan (int planned)
mFailed = 0; mFailed = 0;
mSkipped = 0; mSkipped = 0;
std::cout << "1.." << mPlanned << std::endl; std::cout << "1.." << mPlanned << "\n";
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
void UnitTest::planMore (int extra) void UnitTest::planMore (int extra)
{ {
mPlanned += extra; mPlanned += extra;
std::cout << "1.." << mPlanned << std::endl; std::cout << "1.." << mPlanned << "\n";
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@@ -122,7 +119,7 @@ void UnitTest::ok (bool expression, const std::string& name)
<< mCounter << mCounter
<< " - " << " - "
<< name << name
<< std::endl; << "\n";
} }
else else
{ {
@@ -131,7 +128,7 @@ void UnitTest::ok (bool expression, const std::string& name)
<< mCounter << mCounter
<< " - " << " - "
<< name << name
<< std::endl; << "\n";
} }
} }
@@ -147,7 +144,7 @@ void UnitTest::notok (bool expression, const std::string& name)
<< mCounter << mCounter
<< " - " << " - "
<< name << name
<< std::endl; << "\n";
} }
else else
{ {
@@ -156,7 +153,7 @@ void UnitTest::notok (bool expression, const std::string& name)
<< mCounter << mCounter
<< " - " << " - "
<< name << name
<< std::endl; << "\n";
} }
} }
@@ -171,7 +168,7 @@ void UnitTest::is (bool actual, bool expected, const std::string& name)
<< mCounter << mCounter
<< " - " << " - "
<< name << name
<< std::endl; << "\n";
} }
else else
{ {
@@ -180,13 +177,11 @@ void UnitTest::is (bool actual, bool expected, const std::string& name)
<< mCounter << mCounter
<< " - " << " - "
<< name << name
<< std::endl << "\n# expected: "
<< "# expected: "
<< expected << expected
<< std::endl << "\n# got: "
<< "# got: "
<< actual << actual
<< std::endl; << "\n";
} }
} }
@@ -201,7 +196,7 @@ void UnitTest::is (size_t actual, size_t expected, const std::string& name)
<< mCounter << mCounter
<< " - " << " - "
<< name << name
<< std::endl; << "\n";
} }
else else
{ {
@@ -210,13 +205,11 @@ void UnitTest::is (size_t actual, size_t expected, const std::string& name)
<< mCounter << mCounter
<< " - " << " - "
<< name << name
<< std::endl << "\n# expected: "
<< "# expected: "
<< expected << expected
<< std::endl << "\n# got: "
<< "# got: "
<< actual << actual
<< std::endl; << "\n";
} }
} }
@@ -231,7 +224,7 @@ void UnitTest::is (int actual, int expected, const std::string& name)
<< mCounter << mCounter
<< " - " << " - "
<< name << name
<< std::endl; << "\n";
} }
else else
{ {
@@ -240,13 +233,11 @@ void UnitTest::is (int actual, int expected, const std::string& name)
<< mCounter << mCounter
<< " - " << " - "
<< name << name
<< std::endl << "\n# expected: "
<< "# expected: "
<< expected << expected
<< std::endl << "\n# got: "
<< "# got: "
<< actual << actual
<< std::endl; << "\n";
} }
} }
@@ -261,7 +252,7 @@ void UnitTest::is (double actual, double expected, const std::string& name)
<< mCounter << mCounter
<< " - " << " - "
<< name << name
<< std::endl; << "\n";
} }
else else
{ {
@@ -270,13 +261,11 @@ void UnitTest::is (double actual, double expected, const std::string& name)
<< mCounter << mCounter
<< " - " << " - "
<< name << name
<< std::endl << "\n# expected: "
<< "# expected: "
<< expected << expected
<< std::endl << "\n# got: "
<< "# got: "
<< actual << actual
<< std::endl; << "\n";
} }
} }
@@ -291,7 +280,7 @@ void UnitTest::is (char actual, char expected, const std::string& name)
<< mCounter << mCounter
<< " - " << " - "
<< name << name
<< std::endl; << "\n";
} }
else else
{ {
@@ -300,13 +289,11 @@ void UnitTest::is (char actual, char expected, const std::string& name)
<< mCounter << mCounter
<< " - " << " - "
<< name << name
<< std::endl << "\n# expected: "
<< "# expected: "
<< expected << expected
<< std::endl << "\n# got: "
<< "# got: "
<< actual << actual
<< std::endl; << "\n";
} }
} }
@@ -324,7 +311,7 @@ void UnitTest::is (
<< mCounter << mCounter
<< " - " << " - "
<< name << name
<< std::endl; << "\n";
} }
else else
{ {
@@ -333,15 +320,12 @@ void UnitTest::is (
<< mCounter << mCounter
<< " - " << " - "
<< name << name
<< std::endl << "\n# expected: '"
<< "# expected: '"
<< expected << expected
<< "'" << "'"
<< std::endl << "\n# got: '"
<< "# got: '"
<< actual << actual
<< "'" << "'\n";
<< std::endl;
} }
} }
@@ -359,7 +343,7 @@ void UnitTest::is (
<< mCounter << mCounter
<< " - " << " - "
<< name << name
<< std::endl; << "\n";
} }
else else
{ {
@@ -368,15 +352,12 @@ void UnitTest::is (
<< mCounter << mCounter
<< " - " << " - "
<< name << name
<< std::endl << "\n# expected: '"
<< "# expected: '"
<< expected << expected
<< "'" << "'"
<< std::endl << "\n# got: '"
<< "# got: '"
<< actual << actual
<< "'" << "'\n";
<< std::endl;
} }
} }
@@ -385,7 +366,7 @@ void UnitTest::diag (const std::string& text)
{ {
std::string trimmed = trim (text, " \t\n\r\f"); std::string trimmed = trim (text, " \t\n\r\f");
std::cout << "# " << trimmed << std::endl; std::cout << "# " << trimmed << "\n";
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@@ -397,7 +378,7 @@ void UnitTest::pass (const std::string& text)
<< mCounter << mCounter
<< " " << " "
<< text << text
<< std::endl; << "\n";
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@@ -409,7 +390,7 @@ void UnitTest::fail (const std::string& text)
<< mCounter << mCounter
<< " " << " "
<< text << text
<< std::endl; << "\n";
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@@ -421,7 +402,7 @@ void UnitTest::skip (const std::string& text)
<< mCounter << mCounter
<< " " << " "
<< text << text
<< std::endl; << "\n";
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@@ -68,10 +68,10 @@ int Context::handleInteractive ()
} }
// TODO Integrate regular task error handling, using Context::debug. // TODO Integrate regular task error handling, using Context::debug.
catch (int e) { std::cout << e << std::endl; } catch (int e) { std::cout << e << "\n"; }
catch (const char* e) { std::cout << e << std::endl; } catch (const char* e) { std::cout << e << "\n"; }
catch (std::string& e) { std::cout << e << std::endl; } catch (std::string& e) { std::cout << e << "\n"; }
catch (...) { std::cout << "Unknown error." << std::endl; } catch (...) { std::cout << "Unknown error.\n"; }
logWrite ("---"); logWrite ("---");