Enhancements - task diff

- Implemented util.cpp/taskDiff to generate a proxy description of the
  difference between two tasks.
- Implemented unit tests for taskDiff.
This commit is contained in:
Paul Beckingham 2009-06-25 16:58:58 -04:00
parent c5d7b41d98
commit a56eeb9ec2
6 changed files with 186 additions and 7 deletions

View file

@ -24,6 +24,32 @@
(thanks to Federico Hernandez). (thanks to Federico Hernandez).
+ Removed obsolete DEVELOPERS file. The online support forums at + Removed obsolete DEVELOPERS file. The online support forums at
http://taskwarrior.org will provide better information. 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 ------------------------------ ------ old releases ------------------------------
@ -358,7 +384,7 @@
+ Rules-based colorization. + Rules-based colorization.
0.8.1 (1/28/2008) - 0.8.16 (3/13/2008) 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) 0.8.0 Polish (1/25/2008)
+ Code cleanup, reorganization. + Code cleanup, reorganization.

View file

@ -15,4 +15,5 @@ subst.t
filt.t filt.t
cmd.t cmd.t
config.t config.t
util.t
*.log *.log

View file

@ -1,6 +1,6 @@
PROJECT = t.t tdb.t date.t duration.t t.benchmark.t text.t autocomplete.t \ 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 \ 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 CFLAGS = -I. -I.. -Wall -pedantic -ggdb3 -fno-rtti
LFLAGS = -L/usr/local/lib -lncurses LFLAGS = -L/usr/local/lib -lncurses
OBJECTS = ../TDB.o ../Task.o ../valid.o ../text.o ../Date.o ../Table.o \ 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 config.t: config.t.o $(OBJECTS) test.o
g++ config.t.o $(OBJECTS) test.o $(LFLAGS) -o config.t 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

96
src/tests/util.t.cpp Normal file
View file

@ -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 <iostream>
#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 <std::string>&, 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;
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -26,6 +26,7 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <sstream>
#include <vector> #include <vector>
#include <string> #include <string>
#include <sys/types.h> #include <sys/types.h>
@ -183,10 +184,10 @@ std::string formatBytes (size_t bytes)
{ {
char formatted[24]; char formatted[24];
if (bytes > 1000000000) sprintf (formatted, "%.1f GiB", (bytes / 1000000000.0)); if (bytes >= 1000000000) sprintf (formatted, "%.1f GiB", (bytes / 1000000000.0));
else if (bytes > 1000000) sprintf (formatted, "%.1f MiB", (bytes / 1000000.0)); else if (bytes >= 1000000) sprintf (formatted, "%.1f MiB", (bytes / 1000000.0));
else if (bytes > 1000) sprintf (formatted, "%.1f KiB", (bytes / 1000.0)); else if (bytes >= 1000) sprintf (formatted, "%.1f KiB", (bytes / 1000.0));
else sprintf (formatted, "%d B", (int)bytes ); else sprintf (formatted, "%d B", (int)bytes );
return commify (formatted); 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 <std::string> beforeAtts;
foreach (att, before)
beforeAtts.push_back (att->first);
std::vector <std::string> afterAtts;
foreach (att, after)
afterAtts.push_back (att->first);
std::vector <std::string> beforeOnly;
std::vector <std::string> 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 ();
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -31,6 +31,7 @@
#include <vector> #include <vector>
#include <map> #include <map>
#include <sys/types.h> #include <sys/types.h>
#include "Task.h"
#include "../auto.h" #include "../auto.h"
#ifndef min #ifndef min
@ -58,7 +59,6 @@ std::string formatSecondsCompact (time_t);
std::string formatBytes (size_t); std::string formatBytes (size_t);
int autoComplete (const std::string&, const std::vector<std::string>&, std::vector<std::string>&); int autoComplete (const std::string&, const std::vector<std::string>&, std::vector<std::string>&);
const std::string uuid (); const std::string uuid ();
int convertDuration (const std::string&);
std::string expandPath (const std::string&); std::string expandPath (const std::string&);
#ifdef SOLARIS #ifdef SOLARIS
@ -73,6 +73,7 @@ std::string expandPath (const std::string&);
bool slurp (const std::string&, std::vector <std::string>&, bool trimLines = false); bool slurp (const std::string&, std::vector <std::string>&, bool trimLines = false);
bool slurp (const std::string&, std::string&, bool trimLines = false); bool slurp (const std::string&, std::string&, bool trimLines = false);
void spit (const std::string&, const std::string&); void spit (const std::string&, const std::string&);
std::string taskDiff (const Task&, const Task&);
#endif #endif
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////