diff --git a/src/Subst.cpp b/src/Subst.cpp index 32e1c9f9f..35a8bf007 100644 --- a/src/Subst.cpp +++ b/src/Subst.cpp @@ -103,10 +103,54 @@ bool Subst::parse (const std::string& input) } //////////////////////////////////////////////////////////////////////////////// -void Subst::apply (Record& record) const +void Subst::apply ( + std::string& description, + std::vector & annotations) const { - // TODO Apply /mFrom/mTo/mGlobal to record.get ("description") - // TODO Apply /mFrom/mTo/mGlobal to record.get ("annotation...") + if (mFrom != "") + { + std::string::size_type pattern; + + if (mGlobal) + { + // Perform all subs on description. + while ((pattern = description.find (mFrom)) != std::string::npos) + description.replace (pattern, mFrom.length (), mTo); + + // Perform all subs on annotations. + std::vector ::iterator i; + for (i = annotations.begin (); i != annotations.end (); ++i) + { + std::string description = i->value (); + while ((pattern = description.find (mFrom)) != std::string::npos) + { + description.replace (pattern, mFrom.length (), mTo); + i->value (description); + } + } + } + else + { + // Perform first description substitution. + if ((pattern = description.find (mFrom)) != std::string::npos) + description.replace (pattern, mFrom.length (), mTo); + + // Failing that, perform the first annotation substitution. + else + { + std::vector ::iterator i; + for (i = annotations.begin (); i != annotations.end (); ++i) + { + std::string description = i->value (); + if ((pattern = description.find (mFrom)) != std::string::npos) + { + description.replace (pattern, mFrom.length (), mTo); + break; + } + } + } + } + } } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/Subst.h b/src/Subst.h index 07ef967e8..b57924e00 100644 --- a/src/Subst.h +++ b/src/Subst.h @@ -28,7 +28,7 @@ #define INCLUDED_SUBST #include -#include +#include "Att.h" class Subst { @@ -40,7 +40,7 @@ public: ~Subst (); // Destructor bool parse (const std::string&); - void apply (Record&) const; + void apply (std::string&, std::vector &) const; public: std::string mFrom; diff --git a/src/T.h b/src/T.h index 125718d26..9c981f60a 100644 --- a/src/T.h +++ b/src/T.h @@ -58,7 +58,6 @@ public: const std::string getDescription () const { return mDescription; } void setDescription (const std::string& description) { mDescription = description; } - int getAnnotationCount () const { return mAnnotations.size (); } void getSubstitution (std::string&, std::string&, bool&) const; void setSubstitution (const std::string&, const std::string&, bool); diff --git a/src/T2.cpp b/src/T2.cpp index d56b6983d..25d77441e 100644 --- a/src/T2.cpp +++ b/src/T2.cpp @@ -25,22 +25,33 @@ // //////////////////////////////////////////////////////////////////////////////// +#include #include #include "Nibbler.h" #include "T2.h" +#include "util.h" //////////////////////////////////////////////////////////////////////////////// T2::T2 () { -/* - mUUID = uuid (); -*/ + // Each new task gets a uuid. + set ("uuid", uuid ()); } //////////////////////////////////////////////////////////////////////////////// +// Attempt an FF4 parse first, using Record::parse, and in the event of an error +// try a legacy parse (F3, FF2). Note that FF1 is no longer supported. T2::T2 (const std::string& input) { - parse (input); + try + { + parse (input); + } + + catch (std::string& e) + { + legacyParse (input); + } } //////////////////////////////////////////////////////////////////////////////// @@ -49,7 +60,7 @@ T2& T2::operator= (const T2& other) throw std::string ("unimplemented T2::operator="); if (this != &other) { -// mOne = other.mOne; + mId = other.mId; } return *this; @@ -61,18 +72,11 @@ T2::~T2 () } //////////////////////////////////////////////////////////////////////////////// +// Support FF2, FF3. void T2::legacyParse (const std::string& input) { } -//////////////////////////////////////////////////////////////////////////////// -// [name:value, name:"value",name:[name:value,name:value]] -std::string T2::composeF4 () -{ - throw std::string ("unimplemented T2::composeF4"); - return ""; -} - //////////////////////////////////////////////////////////////////////////////// std::string T2::composeCSV () { @@ -80,6 +84,43 @@ std::string T2::composeCSV () return ""; } +//////////////////////////////////////////////////////////////////////////////// +void T2::getAnnotations (std::vector & annotations) const +{ + annotations.clear (); + + Record::const_iterator ci; + for (ci = this->begin (); ci != this->end (); ++ci) + if (ci->first.substr (0, 11) == "annotation_") + annotations.push_back (ci->second); +} + +//////////////////////////////////////////////////////////////////////////////// +void T2::setAnnotations (const std::vector & annotations) +{ + // Erase old annotations. + Record::iterator i; + for (i = this->begin (); i != this->end (); ++i) + if (i->first.substr (0, 11) == "annotation_") + this->erase (i); + + std::vector ::const_iterator ci; + for (ci = annotations.begin (); ci != annotations.end (); ++ci) + (*this)[ci->name ()] = *ci; +} + +//////////////////////////////////////////////////////////////////////////////// +// The timestamp is part of the name: +// annotation_1234567890:"..." +// +void T2::addAnnotation (const std::string& description) +{ + std::stringstream s; + s << "annotation_" << time (NULL); + + (*this)[s.str ()] = Att (s.str (), description); +} + //////////////////////////////////////////////////////////////////////////////// bool T2::validate () const { diff --git a/src/T2.h b/src/T2.h index 933285feb..3def633b1 100644 --- a/src/T2.h +++ b/src/T2.h @@ -29,42 +29,38 @@ #include #include "Record.h" +#include "Subst.h" +#include "Sequence.h" class T2 : public Record { public: - T2 (); // Default constructor - T2 (const std::string&); // Parse + T2 (); // Default constructor + T2 (const std::string&); // Parse T2& operator= (const T2&); // Assignment operator - ~T2 (); // Destructor + ~T2 (); // Destructor void legacyParse (const std::string&); - std::string composeF4 (); std::string composeCSV (); + // Status values. + enum status {pending, completed, deleted, recurring}; - // TODO Series of helper functions. -// enum status {pending, completed, deleted, recurring}; + // Public data. + Sequence sequence; + Subst subst; + + // Series of helper functions. + int getId () const { return mId; } + void setId (int id) { mId = id; sequence.push_back (id); } /* - std::string getUUID () const { return mUUID; } - void setUUID (const std::string& uuid) { mUUID = uuid; } - - int getId () const { return mId; } - void setId (int id) { mId = id; mSequence.push_back (id); } std::vector getAllIds () const { return mSequence; } void addId (int id) { if (mId == 0) mId = id; mSequence.push_back (id); } status getStatus () const { return mStatus; } void setStatus (status s) { mStatus = s; } - const std::string getDescription () const { return mDescription; } - void setDescription (const std::string& description) { mDescription = description; } - int getAnnotationCount () const { return mAnnotations.size (); } - - void getSubstitution (std::string&, std::string&, bool&) const; - void setSubstitution (const std::string&, const std::string&, bool); - bool hasTag (const std::string&) const; void getRemoveTags (std::vector&); // SPECIAL void addRemoveTag (const std::string&); // SPECIAL @@ -74,40 +70,27 @@ public: void addTags (const std::vector &); void removeTag (const std::string&); void removeTags (); - - void getAttributes (std::map&); - const std::string getAttribute (const std::string&); - void setAttribute (const std::string&, const std::string&); - void removeAttribute (const std::string&); - - void getAnnotations (std::map &) const; - void setAnnotations (const std::map &); - void addAnnotation (const std::string&); - - const std::string compose () const; - const std::string composeCSV (); - void parse (const std::string&); */ + void getAnnotations (std::vector &) const; + void setAnnotations (const std::vector &); + void addAnnotation (const std::string&); + bool validate () const; private: +/* int determineVersion (const std::string&); +*/ private: /* status mStatus; - std::string mUUID; +*/ int mId; - std::vector mSequence; - std::string mDescription; +/* std::vector mTags; std::vector mRemoveTags; - std::map mAttributes; - std::string mFrom; - std::string mTo; - bool mGlobal; - std::map mAnnotations; */ }; diff --git a/src/report.cpp b/src/report.cpp index 0a77cc7d1..168201db2 100644 --- a/src/report.cpp +++ b/src/report.cpp @@ -2145,7 +2145,9 @@ std::string handleReportStats (TDB& tdb, T& task, Config& conf) descLength += it->getDescription ().length (); - annotationsT += it->getAnnotationCount (); + std::map annotations; + it->getAnnotations (annotations); + annotationsT += annotations.size (); std::vector tags; it->getTags (tags); diff --git a/src/tests/.gitignore b/src/tests/.gitignore index 4d70d59a2..f12269bc7 100644 --- a/src/tests/.gitignore +++ b/src/tests/.gitignore @@ -12,3 +12,4 @@ mod.t record.t stringtable.t nibbler.t +subst.t diff --git a/src/tests/Makefile b/src/tests/Makefile index bf6eac54b..d95ee1490 100644 --- a/src/tests/Makefile +++ b/src/tests/Makefile @@ -1,10 +1,11 @@ PROJECT = t.t tdb.t date.t duration.t t.benchmark.t text.t autocomplete.t \ - parse.t seq.t att.t mod.t stringtable.t record.t nibbler.t # subst.t + parse.t seq.t att.t mod.t stringtable.t record.t nibbler.t subst.t CFLAGS = -I. -I.. -Wall -pedantic -ggdb3 -fno-rtti LFLAGS = -L/usr/local/lib -OBJECTS = ../TDB.o ../T.o ../parse.o ../text.o ../Date.o ../Duration.o \ - ../util.o ../Config.o ../Sequence.o ../Att.o ../Record.o ../Mod.o \ - ../StringTable.o ../Subst.o ../Nibbler.o +OBJECTS = ../TDB.o ../TDB2.o ../T.o ../T2.o ../parse.o ../text.o ../Date.o \ + ../Duration.o ../util.o ../Config.o ../Sequence.o ../Att.o \ + ../Record.o ../Mod.o ../StringTable.o ../Subst.o ../Nibbler.o \ + ../Filter.o ../Location.o all: $(PROJECT) diff --git a/src/tests/subst.t.cpp b/src/tests/subst.t.cpp index 18dc0df47..67622a873 100644 --- a/src/tests/subst.t.cpp +++ b/src/tests/subst.t.cpp @@ -24,7 +24,7 @@ // USA // //////////////////////////////////////////////////////////////////////////////// -#include +#include #include #include @@ -33,14 +33,18 @@ int main (int argc, char** argv) { UnitTest t (2); - T task; + T2 task; task.set ("description", "one two three four"); Subst s; if (s.parse ("/two/TWO/")) { - s.apply (task); - t.is (task.get ("description"), "one TWO three four", "single word subst"); + std::string description = task.get ("description"); + std::vector annotations; + task.getAnnotations (annotations); + + s.apply (description, annotations); + t.is (description, "one TWO three four", "single word subst"); } else { @@ -49,8 +53,12 @@ int main (int argc, char** argv) if (s.parse ("/e /E /g")) { - s.apply (task); - t.is (task.get ("description"), "onE TWO threE four", "multiple word subst"); + std::string description = task.get ("description"); + std::vector annotations; + task.getAnnotations (annotations); + + s.apply (description, annotations); + t.is (description, "onE two threE four", "multiple word subst"); } else { diff --git a/src/tests/t.t.cpp b/src/tests/t.t.cpp index 64f11031a..484866fa9 100644 --- a/src/tests/t.t.cpp +++ b/src/tests/t.t.cpp @@ -32,7 +32,7 @@ //////////////////////////////////////////////////////////////////////////////// int main (int argc, char** argv) { - UnitTest test (10); + UnitTest test (9); T t; std::string s = t.compose (); @@ -88,7 +88,6 @@ int main (int argc, char** argv) std::string format = t.compose (); test.is (format.substr (36, 20), " - [foo] [bar:baz] [", "compose tag, attribute"); test.is (format.substr (66, 16), ":\"woof\"] sample\n", "compose annotation"); - test.is (t.getAnnotationCount (), 1, "annotation count"); return 0; }