diff --git a/ChangeLog b/ChangeLog index d0cec8f2f..add15c0e5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -24,6 +24,32 @@ (thanks to Federico Hernandez). + Removed obsolete DEVELOPERS file. The online support forums at http://taskwarrior.org will provide better information. + + Fixed bug that kept some deleted tasks showing up on the calendar report + (thanks to Federico Hernandez). + + Now asks the user to confirm large changes if configuration variable + 'confirmation' is set to 'yes'. A large change is one that completely + replaces a task description, or operates on a large number of tasks, + which defaults to 4 but is configurable via the 'bulk' configuration + variable (thanks to John Florian). + + Now echoes back the new task ID on 'add' (thanks to Bruce Dillahunty). + + The new "shell" command provides an interactive shell for task. All + commands are supported (thanks to Bruce Dillahunty, Federico Hernandez, + and John Florian). + + New "recurring" report to list all recurring tasks. + + New, more flexible, more consistent, grep-able file format. + +Add: + att mods + new custom reports + new custom report fields + aliases + limit: + wait: + report.waiting + report.all + debug mode + new colorization support + many, many new unit tests ------ old releases ------------------------------ @@ -358,7 +384,7 @@ + Rules-based colorization. 0.8.1 (1/28/2008) - 0.8.16 (3/13/2008) - + autoconf conversion (many builds). + + autoconf conversion 0.8.0 Polish (1/25/2008) + Code cleanup, reorganization. diff --git a/src/tests/.gitignore b/src/tests/.gitignore index ffffbf248..1bfbd5509 100644 --- a/src/tests/.gitignore +++ b/src/tests/.gitignore @@ -15,4 +15,5 @@ subst.t filt.t cmd.t config.t +util.t *.log diff --git a/src/tests/Makefile b/src/tests/Makefile index 9d96dfdcf..f6476bb0c 100644 --- a/src/tests/Makefile +++ b/src/tests/Makefile @@ -1,6 +1,6 @@ PROJECT = t.t tdb.t date.t duration.t t.benchmark.t text.t autocomplete.t \ config.t seq.t att.t stringtable.t record.t nibbler.t subst.t filt.t \ - cmd.t + cmd.t util.t CFLAGS = -I. -I.. -Wall -pedantic -ggdb3 -fno-rtti LFLAGS = -L/usr/local/lib -lncurses OBJECTS = ../TDB.o ../Task.o ../valid.o ../text.o ../Date.o ../Table.o \ @@ -72,3 +72,6 @@ cmd.t: cmd.t.o $(OBJECTS) test.o config.t: config.t.o $(OBJECTS) test.o g++ config.t.o $(OBJECTS) test.o $(LFLAGS) -o config.t +util.t: util.t.o $(OBJECTS) test.o + g++ util.t.o $(OBJECTS) test.o $(LFLAGS) -o util.t + diff --git a/src/tests/util.t.cpp b/src/tests/util.t.cpp new file mode 100644 index 000000000..260116866 --- /dev/null +++ b/src/tests/util.t.cpp @@ -0,0 +1,96 @@ +//////////////////////////////////////////////////////////////////////////////// +// task - a command line task list manager. +// +// Copyright 2006 - 2009, Paul Beckingham. +// All rights reserved. +// +// This program is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free Software +// Foundation; either version 2 of the License, or (at your option) any later +// version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +// details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the +// +// Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, +// Boston, MA +// 02110-1301 +// USA +// +//////////////////////////////////////////////////////////////////////////////// +#include +#include "main.h" +#include "util.h" +#include "test.h" + +Context context; + +//////////////////////////////////////////////////////////////////////////////// +int main (int argc, char** argv) +{ + UnitTest t (17); + + // TODO bool confirm (const std::string&); + // TODO int confirm3 (const std::string&); + // TODO void delay (float); + // TODO std::string formatSeconds (time_t); + // TODO std::string formatSecondsCompact (time_t); + + // std::string formatBytes (size_t); + t.is (formatBytes (0), "0 B", "0 -> 0 B"); + + t.is (formatBytes (999), "999 B", "999 -> 999 B"); + t.is (formatBytes (1000), "1.0 KiB", "1000 -> 1.0 KiB"); + t.is (formatBytes (1001), "1.0 KiB", "1001 -> 1.0 KiB"); + + t.is (formatBytes (999999), "1.0 MiB", "999999 -> 1.0 MiB"); + t.is (formatBytes (1000000), "1.0 MiB", "1000000 -> 1.0 MiB"); + t.is (formatBytes (1000001), "1.0 MiB", "1000001 -> 1.0 MiB"); + + t.is (formatBytes (999999999), "1.0 GiB", "999999999 -> 1.0 GiB"); + t.is (formatBytes (1000000000), "1.0 GiB", "1000000000 -> 1.0 GiB"); + t.is (formatBytes (1000000001), "1.0 GiB", "1000000001 -> 1.0 GiB"); + + // TODO const std::string uuid (); + + // std::string expandPath (const std::string&); + t.ok (expandPath ("foo") == "foo", "expandPath nop"); + t.ok (expandPath ("~/") != "~/", "expandPath ~/"); + + // TODO bool slurp (const std::string&, std::vector &, bool trimLines = false); + // TODO bool slurp (const std::string&, std::string&, bool trimLines = false); + // TODO void spit (const std::string&, const std::string&); + + // std::string taskDiff (const Task&, const Task&); + Task left; + left.set ("zero", "0"); + left.set ("one", 1); + left.set ("two", 2); + + Task right; + right.set ("zero", "00"); + right.set ("two", 2); + right.set ("three", 3); + + Task rightAgain (right); + + std::string output = taskDiff (left, right); + t.ok (output.find ("zero was changed from '0' to '00'.\n") != std::string::npos, "Detected change zero:0 -> zero:00"); + t.ok (output.find ("one was deleted.\n") != std::string::npos, "Detected deletion one:1 ->"); + t.ok (output.find ("two") == std::string::npos, "Detected no change two:2 -> two:2"); + t.ok (output.find ("three was set to '3'.\n") != std::string::npos, "Detected addition -> three:3"); + + output = taskDiff (right, rightAgain); + t.ok (output.find ("No changes were made.\n") != std::string::npos, "No changes detected"); + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// + diff --git a/src/util.cpp b/src/util.cpp index 9c59002c8..260379d64 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -26,6 +26,7 @@ //////////////////////////////////////////////////////////////////////////////// #include #include +#include #include #include #include @@ -183,10 +184,10 @@ std::string formatBytes (size_t bytes) { char formatted[24]; - if (bytes > 1000000000) sprintf (formatted, "%.1f GiB", (bytes / 1000000000.0)); - else if (bytes > 1000000) sprintf (formatted, "%.1f MiB", (bytes / 1000000.0)); - else if (bytes > 1000) sprintf (formatted, "%.1f KiB", (bytes / 1000.0)); - else sprintf (formatted, "%d B", (int)bytes ); + if (bytes >= 1000000000) sprintf (formatted, "%.1f GiB", (bytes / 1000000000.0)); + else if (bytes >= 1000000) sprintf (formatted, "%.1f MiB", (bytes / 1000000.0)); + else if (bytes >= 1000) sprintf (formatted, "%.1f KiB", (bytes / 1000.0)); + else sprintf (formatted, "%d B", (int)bytes ); return commify (formatted); } @@ -426,3 +427,54 @@ void spit (const std::string& file, const std::string& contents) } //////////////////////////////////////////////////////////////////////////////// +std::string taskDiff (const Task& before, const Task& after) +{ + // Attributes are all there is, so figure the different attribute names + // between before and after. + std::vector beforeAtts; + foreach (att, before) + beforeAtts.push_back (att->first); + + std::vector afterAtts; + foreach (att, after) + afterAtts.push_back (att->first); + + std::vector beforeOnly; + std::vector afterOnly; + listDiff (beforeAtts, afterAtts, beforeOnly, afterOnly); + + // Now start generating a description of the differences. + std::stringstream out; + foreach (name, beforeOnly) + out << *name + << " was deleted." + << std::endl; + + foreach (name, afterOnly) + out << *name + << " was set to '" + << after.get (*name) + << "'." + << std::endl; + + foreach (name, beforeAtts) + if (*name != "uuid" && + after.get (*name) != "" && + before.get (*name) != after.get (*name)) + out << *name + << " was changed from '" + << before.get (*name) + << "' to '" + << after.get (*name) + << "'." + << std::endl; + + // Can't just say nothing. + if (out.str ().length () == 0) + out << "No changes were made." + << std::endl; + + return out.str (); +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/util.h b/src/util.h index 19f7af6f2..2d59cf22d 100644 --- a/src/util.h +++ b/src/util.h @@ -31,6 +31,7 @@ #include #include #include +#include "Task.h" #include "../auto.h" #ifndef min @@ -58,7 +59,6 @@ std::string formatSecondsCompact (time_t); std::string formatBytes (size_t); int autoComplete (const std::string&, const std::vector&, std::vector&); const std::string uuid (); -int convertDuration (const std::string&); std::string expandPath (const std::string&); #ifdef SOLARIS @@ -73,6 +73,7 @@ std::string expandPath (const std::string&); bool slurp (const std::string&, std::vector &, bool trimLines = false); bool slurp (const std::string&, std::string&, bool trimLines = false); void spit (const std::string&, const std::string&); +std::string taskDiff (const Task&, const Task&); #endif ////////////////////////////////////////////////////////////////////////////////