diff --git a/src/Att.cpp b/src/Att.cpp index 9727fc1ee..083cef676 100644 --- a/src/Att.cpp +++ b/src/Att.cpp @@ -35,8 +35,28 @@ Att::Att () : mName ("") , mValue ("") +, mMod ("") { - mMods.clear (); +} + +//////////////////////////////////////////////////////////////////////////////// +Att::Att (const std::string& name, const std::string& mod, const std::string& value) +{ + mName = name; + mValue = value; + mMod = mod; +} + +//////////////////////////////////////////////////////////////////////////////// +Att::Att (const std::string& name, const std::string& mod, int value) +{ + mName = name; + + std::stringstream s; + s << value; + mValue = s.str (); + + mMod = mod; } //////////////////////////////////////////////////////////////////////////////// @@ -44,8 +64,7 @@ Att::Att (const std::string& name, const std::string& value) { mName = name; mValue = value; - - mMods.clear (); + mMod = ""; } //////////////////////////////////////////////////////////////////////////////// @@ -57,7 +76,7 @@ Att::Att (const std::string& name, int value) s << value; mValue = s.str (); - mMods.clear (); + mMod = ""; } //////////////////////////////////////////////////////////////////////////////// @@ -65,7 +84,7 @@ Att::Att (const Att& other) { mName = other.mName; mValue = other.mValue; - mMods = other.mMods; + mMod = other.mMod; } //////////////////////////////////////////////////////////////////////////////// @@ -75,7 +94,7 @@ Att& Att::operator= (const Att& other) { mName = other.mName; mValue = other.mValue; - mMods = other.mMods; + mMod = other.mMod; } return *this; @@ -116,8 +135,8 @@ bool Att::valid (const std::string& input) const //////////////////////////////////////////////////////////////////////////////// // // start --> name --> . --> mod --> : --> " --> value --> " --> end -// ^ | -// |__________| +// | ^ +// |_____________________| // void Att::parse (const std::string& input) { @@ -128,22 +147,22 @@ void Att::parse (const std::string& input) void Att::parse (Nibbler& n) { // Ensure a clean object first. - mName = ""; + mName = ""; mValue = ""; - mMods.clear (); + mMod = ""; if (n.getUntilOneOf (".:", mName)) { if (mName.length () == 0) throw std::string ("Missing attribute name"); // TODO i18n - while (n.skip ('.')) + if (n.skip ('.')) { std::string mod; - if (n.getUntilOneOf (".:", mod)) + if (n.getUntil (":", mod)) { if (validMod (mod)) - mMods.push_back (mod); + mMod = mod; else throw std::string ("The name '") + mod + "' is not a valid modifier"; // TODO i18n } @@ -174,15 +193,12 @@ void Att::parse (Nibbler& n) bool Att::validMod (const std::string& mod) const { if (mod == "before" || mod == "after" || // i18n: TODO - mod == "not" || // i18n: TODO mod == "none" || mod == "any" || // i18n: TODO - mod == "synth" || // i18n: TODO mod == "under" || mod == "over" || // i18n: TODO mod == "first" || mod == "last" || // i18n: TODO - mod == "this" || // i18n: TODO - mod == "next" || // i18n: TODO mod == "is" || mod == "isnt" || // i18n: TODO mod == "has" || mod == "hasnt" || // i18n: TODO + mod == "contains" || // i18n: TODO mod == "startswith" || mod == "endswith") // i18n: TODO return true; @@ -194,77 +210,75 @@ bool Att::validMod (const std::string& mod) const // Record that does not have modifiers, but may have a value. bool Att::match (const Att& other) const { - // If there are no mods, just perform a straight compares on value. - if (mMods.size () == 0) - if (mName != other.mName || mValue != other.mValue) - return false; + // If there are no mods, just perform a straight compare on value. + if (mMod == "" && mValue != other.mValue) + return false; // Assume a match, and short-circuit on mismatch. - foreach (mod, mMods) + + // is = equal. Nop. + else if (mMod == "is") // TODO i18n + if (mValue != other.mValue) + return false; + + // isnt = not equal. + else if (mMod == "isnt") // TODO i18n + if (mValue == other.mValue) + return false; + + // any = any value, but not empty value. + else if (mMod == "any") // TODO i18n + if (other.mValue == "") + return false; + + // none = must have empty value. + else if (mMod == "none") // TODO i18n + if (other.mValue != "") + return false; + + // startswith = first characters must match. + else if (mMod == "startswith") // TODO i18n { - // is = equal. - if (*mod == "is") // TODO i18n - if (mValue != other.mValue) - return false; + if (other.mValue.length () < mValue.length ()) + return false; - // isnt = not equal. - if (*mod == "isnt") // TODO i18n - if (mValue == other.mValue) - return false; + if (mValue != other.mValue.substr (0, mValue.length ())) + return false; + } - // any = any value, but not empty value. - if (*mod == "any") // TODO i18n - if (other.mValue == "") - return false; + // endswith = last characters must match. + else if (mMod == "endswith") // TODO i18n + { + if (other.mValue.length () < mValue.length ()) + return false; - // none = must have empty value. - if (*mod == "none") // TODO i18n - if (other.mValue != "") - return false; + if (mValue != other.mValue.substr ( + other.mValue.length () - mValue.length (), + std::string::npos)) + return false; + } - // startswith = first characters must match. - if (*mod == "startswith") // TODO i18n - { - if (other.mValue.length () < mValue.length ()) - return false; + // has = contains as a substring. + else if (mMod == "has" || mMod == "contains") // TODO i18n + if (other.mValue.find (mValue) == std::string::npos) + return false; - if (mValue != other.mValue.substr (0, mValue.length ())) - return false; - } + // hasnt = does not contain as a substring. + else if (mMod == "hasnt") // TODO i18n + if (other.mValue.find (mValue) != std::string::npos) + return false; - // endswith = last characters must match. - if (*mod == "endswith") // TODO i18n - { - if (other.mValue.length () < mValue.length ()) - return false; - - if (mValue != other.mValue.substr ( - other.mValue.length () - mValue.length (), - std::string::npos)) - return false; - } - - // has = contains as a substring. - if (*mod == "has") // TODO i18n - if (other.mValue.find (mValue) == std::string::npos) - return false; - - // hasnt = does not contain as a substring. - if (*mod == "hasnt") // TODO i18n - if (other.mValue.find (mValue) != std::string::npos) - return false; - - // TODO before - // TODO after - // TODO not <-- could be a problem - // TODO synth + // Harder: + // TODO before/after // TODO under/below // TODO over/above - // TODO first - // TODO last + + // Impossible? + // TODO synth // TODO this // TODO next - } + // TODO first + // TODO last return true; } @@ -288,18 +302,18 @@ std::string Att::composeF4 () const } //////////////////////////////////////////////////////////////////////////////// -void Att::addMod (const std::string& mod) +void Att::mod (const std::string& input) { - if (validMod (mod)) - mMods.push_back (mod); - else - throw std::string ("The name '") + mod + "' is not a valid modifier"; // TODO i18n + if (!validMod (input)) + throw std::string ("The name '") + input + "' is not a valid modifier"; // TODO i18n + + mMod = input; } //////////////////////////////////////////////////////////////////////////////// -void Att::mods (std::vector & all) const +std::string Att::mod () const { - all = mMods; + return mMod; } //////////////////////////////////////////////////////////////////////////////// @@ -419,4 +433,5 @@ void Att::decode (std::string& value) const while ((i = value.find (":")) != std::string::npos) // no i18n value.replace (i, 7, ":"); } + //////////////////////////////////////////////////////////////////////////////// diff --git a/src/Att.h b/src/Att.h index 1d736a0a3..3ce94bd94 100644 --- a/src/Att.h +++ b/src/Att.h @@ -34,12 +34,14 @@ class Att { public: - Att (); // Default constructor - Att (const std::string&, const std::string&); // Simple constructor - Att (const std::string&, int); // Simple constructor - Att (const Att&); // Copy constructor - Att& operator= (const Att&); // Assignment operator - ~Att (); // Destructor + Att (); + Att (const std::string&, const std::string&, const std::string&); + Att (const std::string&, const std::string&, int); + Att (const std::string&, const std::string&); + Att (const std::string&, int); + Att (const Att&); + Att& operator= (const Att&); + ~Att (); bool valid (const std::string&) const; void parse (const std::string&); @@ -49,8 +51,8 @@ public: std::string composeF4 () const; - void addMod (const std::string&); - void mods (std::vector &) const; + void mod (const std::string&); + std::string mod () const; std::string name () const; void name (const std::string&); @@ -70,7 +72,7 @@ private: private: std::string mName; std::string mValue; - std::vector mMods; + std::string mMod; }; #endif diff --git a/src/Context.cpp b/src/Context.cpp index c491f6a83..1b1671d7d 100644 --- a/src/Context.cpp +++ b/src/Context.cpp @@ -479,6 +479,15 @@ void Context::constructFilter () foreach (att, task) if (att->first != "uuid") filter.push_back (att->second); + + // TODO this doesn't work. + if (task.has ("description")) + { + std::vector words; + split (words, task.get ("description"), ' '); + foreach (word, words) + filter.push_back (Att ("description", "contains", *word)); + } } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/TDB2.cpp b/src/TDB2.cpp index 1a231abfc..347347aba 100644 --- a/src/TDB2.cpp +++ b/src/TDB2.cpp @@ -159,8 +159,6 @@ int TDB2::loadPending (std::vector & tasks, Filter& filter) char line[T_LINE_MAX]; foreach (location, mLocations) { - std::cout << "# location.path: " << location->path << "" << std::endl; - line_number = 1; file = location->path + "/pending.data"; @@ -208,8 +206,6 @@ int TDB2::loadCompleted (std::vector & tasks, Filter& filter) char line[T_LINE_MAX]; foreach (location, mLocations) { - std::cout << "# location.path: " << location->path << "" << std::endl; - // TODO If the filter contains Status:x where x is not deleted or // completed, then this can be skipped. diff --git a/src/Task.cpp b/src/Task.cpp index 4486ccef6..cf8a5c903 100644 --- a/src/Task.cpp +++ b/src/Task.cpp @@ -430,6 +430,15 @@ void Task::removeTag (const std::string& tag) //////////////////////////////////////////////////////////////////////////////// void Task::validate () const { + // Every task needs an ID. +/* + if (sequence[0] == 0) + throw std::string ("Every task needs an ID."); +*/ + + // TODO Every task needs an ID, entry and description attribute. + + // TODO Verify until > due // TODO Verify entry < until, due, start, end // TODO If name == "recur", then Duration::valid (value). diff --git a/src/tests/att.t.cpp b/src/tests/att.t.cpp index 7ae61823b..e22020a82 100644 --- a/src/tests/att.t.cpp +++ b/src/tests/att.t.cpp @@ -33,7 +33,7 @@ Context context; //////////////////////////////////////////////////////////////////////////////// int main (int argc, char** argv) { - UnitTest t (74); + UnitTest t (67); Att a; t.notok (a.valid ("name"), "Att::valid name -> fail"); @@ -85,88 +85,70 @@ int main (int argc, char** argv) t.is (a6.value_int (), 7, "Att::value_int set/get"); t.is (a6.value (), "7", "Att::value 7"); - // Att::addMod + // Att::mod bool good = true; - try {a6.addMod ("is");} catch (...) {good = false;} - t.ok (good, "Att::addMod (is)"); + try {a6.mod ("is");} catch (...) {good = false;} + t.ok (good, "Att::mod (is)"); good = true; - try {a6.addMod ("before");} catch (...) {good = false;} - t.ok (good, "Att::addMod (before)"); + try {a6.mod ("before");} catch (...) {good = false;} + t.ok (good, "Att::mod (before)"); good = true; - try {a6.addMod ("after");} catch (...) {good = false;} - t.ok (good, "Att::addMod (after)"); + try {a6.mod ("after");} catch (...) {good = false;} + t.ok (good, "Att::mod (after)"); good = true; - try {a6.addMod ("not");} catch (...) {good = false;} - t.ok (good, "Att::addMod (not)"); + try {a6.mod ("none");} catch (...) {good = false;} + t.ok (good, "Att::mod (none)"); good = true; - try {a6.addMod ("none");} catch (...) {good = false;} - t.ok (good, "Att::addMod (none)"); + try {a6.mod ("any");} catch (...) {good = false;} + t.ok (good, "Att::mod (any)"); good = true; - try {a6.addMod ("any");} catch (...) {good = false;} - t.ok (good, "Att::addMod (any)"); + try {a6.mod ("over");} catch (...) {good = false;} + t.ok (good, "Att::mod (over)"); good = true; - try {a6.addMod ("over");} catch (...) {good = false;} - t.ok (good, "Att::addMod (over)"); + try {a6.mod ("under");} catch (...) {good = false;} + t.ok (good, "Att::mod (under)"); good = true; - try {a6.addMod ("under");} catch (...) {good = false;} - t.ok (good, "Att::addMod (under)"); + try {a6.mod ("first");} catch (...) {good = false;} + t.ok (good, "Att::mod (first)"); good = true; - try {a6.addMod ("synth");} catch (...) {good = false;} - t.ok (good, "Att::addMod (synth)"); + try {a6.mod ("last");} catch (...) {good = false;} + t.ok (good, "Att::mod (last)"); good = true; - try {a6.addMod ("first");} catch (...) {good = false;} - t.ok (good, "Att::addMod (first)"); + try {a6.mod ("isnt");} catch (...) {good = false;} + t.ok (good, "Att::mod (isnt)"); good = true; - try {a6.addMod ("last");} catch (...) {good = false;} - t.ok (good, "Att::addMod (last)"); + try {a6.mod ("has");} catch (...) {good = false;} + t.ok (good, "Att::mod (has)"); good = true; - try {a6.addMod ("this");} catch (...) {good = false;} - t.ok (good, "Att::addMod (this)"); + try {a6.mod ("contains");} catch (...) {good = false;} + t.ok (good, "Att::mod (contains)"); good = true; - try {a6.addMod ("next");} catch (...) {good = false;} - t.ok (good, "Att::addMod (next)"); + try {a6.mod ("hasnt");} catch (...) {good = false;} + t.ok (good, "Att::mod (hasnt)"); good = true; - try {a6.addMod ("isnt");} catch (...) {good = false;} - t.ok (good, "Att::addMod (isnt)"); + try {a6.mod ("startswith");} catch (...) {good = false;} + t.ok (good, "Att::mod (startswith)"); good = true; - try {a6.addMod ("has");} catch (...) {good = false;} - t.ok (good, "Att::addMod (has)"); + try {a6.mod ("endswith");} catch (...) {good = false;} + t.ok (good, "Att::mod (endswith)"); good = true; - try {a6.addMod ("hasnt");} catch (...) {good = false;} - t.ok (good, "Att::addMod (hasnt)"); - - good = true; - try {a6.addMod ("startswith");} catch (...) {good = false;} - t.ok (good, "Att::addMod (startswith)"); - - good = true; - try {a6.addMod ("endswith");} catch (...) {good = false;} - t.ok (good, "Att::addMod (endswith)"); - - good = true; - try {a6.addMod ("fartwizzle");} catch (...) {good = false;} - t.notok (good, "Att::addMod (fartwizzle)"); - - // Att::mods - std::vector mods; - a6.mods (mods); - t.is (mods.size (), (size_t)18, "Att::mods () size == 18"); - t.is (mods[0], "is", "Att::mods [0] == 'is'"); + try {a6.mod ("fartwizzle");} catch (...) {good = false;} + t.notok (good, "Att::mod (fartwizzle)"); // Att::parse Nibbler n (""); @@ -260,12 +242,6 @@ int main (int argc, char** argv) t.ok (good, "Att::parse (name.any:\"value\")"); t.is (a7.composeF4 (), "name:\"value\"", "Att::composeF4 -> name:\"value\""); - n = Nibbler ("name.any.none:\"value\""); - good = true; - try {a7.parse (n);} catch (...) {good = false;} - t.ok (good, "Att::parse (name.any.none:\"value\")"); - t.is (a7.composeF4 (), "name:\"value\"", "Att::composeF4 -> name:\"value\""); - n = Nibbler ("name.bogus:\"value\""); good = true; try {a7.parse (n);} catch (...) {good = false;}