mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-07-07 20:06:36 +02:00
Enhancement - Attribute modifiers
- Implemented half the modifiers. The easy half. - Implemented unit tests that don't all pass yet, and are incomplete.
This commit is contained in:
parent
2aa43fe4fe
commit
0ec3b4b6af
3 changed files with 150 additions and 33 deletions
84
src/Att.cpp
84
src/Att.cpp
|
@ -27,7 +27,8 @@
|
|||
|
||||
#include <sstream>
|
||||
#include <stdlib.h>
|
||||
#include <text.h>
|
||||
#include "text.h"
|
||||
#include "util.h"
|
||||
#include "Att.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -159,19 +160,68 @@ bool Att::validMod (const std::string& mod) const
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// "this" is the attribute that has modifiers. "other" is the attribute from a
|
||||
// Record that does not have modifiers, but may have a value.
|
||||
bool Att::match (const Att& other) const
|
||||
{
|
||||
// No modifier means automatic pass.
|
||||
/*
|
||||
if (*this == "") // i18n: no
|
||||
return true;
|
||||
*/
|
||||
// Assume a match, and short-circuit on mismatch.
|
||||
foreach (mod, mMods)
|
||||
{
|
||||
// is = equal.
|
||||
if (*mod == "is")
|
||||
if (mValue != other.mValue)
|
||||
return false;
|
||||
|
||||
// isnt = not equal.
|
||||
if (*mod == "isnt")
|
||||
if (mValue == other.mValue)
|
||||
return false;
|
||||
|
||||
// any = any value, but not empty value.
|
||||
if (*mod == "any")
|
||||
if (other.mValue == "")
|
||||
return false;
|
||||
|
||||
// none = must have empty value.
|
||||
if (*mod == "none")
|
||||
if (other.mValue != "")
|
||||
return false;
|
||||
|
||||
// startswith = first characters must match.
|
||||
if (*mod == "startswith")
|
||||
{
|
||||
if (other.mValue.length () < mValue.length ())
|
||||
return false;
|
||||
|
||||
if (mValue != other.mValue.substr (0, mValue.length ()))
|
||||
return false;
|
||||
}
|
||||
|
||||
// endswith = last characters must match.
|
||||
if (*mod == "endswith")
|
||||
{
|
||||
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")
|
||||
if (other.mValue.find (mValue) == std::string::npos)
|
||||
return false;
|
||||
|
||||
// hasnt = does not contain as a substring.
|
||||
if (*mod == "hasnt")
|
||||
if (other.mValue.find (mValue) != std::string::npos)
|
||||
return false;
|
||||
|
||||
// TODO before
|
||||
// TODO after
|
||||
// TODO not
|
||||
// TODO none
|
||||
// TODO any
|
||||
// TODO not <-- could be a problem
|
||||
// TODO synth
|
||||
// TODO under
|
||||
// TODO over
|
||||
|
@ -179,21 +229,9 @@ bool Att::match (const Att& other) const
|
|||
// TODO last
|
||||
// TODO this
|
||||
// TODO next
|
||||
}
|
||||
|
||||
/*
|
||||
if (*this == "is") // i18n: TODO
|
||||
return *this == other ? true : false;
|
||||
|
||||
if (*this == "isnt") // i18n: TODO
|
||||
return *this != other ? true : false;
|
||||
*/
|
||||
|
||||
// TODO has
|
||||
// TODO hasnt
|
||||
// TODO startswith
|
||||
// TODO endswith
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -38,9 +38,17 @@ bool Filter::pass (const Record& record) const
|
|||
// If record doesn't have the attribute, fail. If it does have the attribute
|
||||
// but it doesn't match, fail.
|
||||
foreach (att, (*this))
|
||||
if ((r = record.find (att->name ())) == record.end () ||
|
||||
! att->match (r->second))
|
||||
{
|
||||
// If the record doesn't have the attribute, match against a default one.
|
||||
// This is because "att" may contain a modifier like "name.not:X".
|
||||
if ((r = record.find (att->name ())) == record.end ())
|
||||
{
|
||||
if (! att->match (Att ()))
|
||||
return false;
|
||||
}
|
||||
else if (! att->match (r->second))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ Context context;
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
UnitTest test (6);
|
||||
UnitTest test (14);
|
||||
|
||||
// Create a filter consisting of two Att criteria.
|
||||
Filter f;
|
||||
|
@ -63,7 +63,78 @@ int main (int argc, char** argv)
|
|||
partial.set ("name1", "value1");
|
||||
test.notok (f.pass (no0), "no match against partial T2");
|
||||
|
||||
// TODO Modifiers.
|
||||
// Modifiers.
|
||||
T2 mods;
|
||||
mods.set ("name", "value");
|
||||
|
||||
Att a ("name", "value");
|
||||
a.addMod ("is");
|
||||
f.clear ();
|
||||
f.push_back (a);
|
||||
test.ok (f.pass (mods), "name:value -> name.is:value = match");
|
||||
// TODO test inverse.
|
||||
|
||||
a = Att ("name", "value");
|
||||
a.addMod ("isnt");
|
||||
f.clear ();
|
||||
f.push_back (a);
|
||||
test.notok (f.pass (mods), "name:value -> name.isnt:value = no match");
|
||||
// TODO test inverse.
|
||||
|
||||
a = Att ("name", "val");
|
||||
a.addMod ("startswith");
|
||||
f.clear ();
|
||||
f.push_back (a);
|
||||
test.ok (f.pass (mods), "name:value -> name.startswith:val = match");
|
||||
// TODO test inverse.
|
||||
|
||||
a = Att ("name", "lue");
|
||||
a.addMod ("endswith");
|
||||
f.clear ();
|
||||
f.push_back (a);
|
||||
test.ok (f.pass (mods), "name:value -> name.endswith:lue = match");
|
||||
// TODO test inverse.
|
||||
|
||||
a = Att ("name", "value");
|
||||
a.addMod ("has");
|
||||
f.clear ();
|
||||
f.push_back (a);
|
||||
test.ok (f.pass (mods), "name:value -> name.has:alu = match");
|
||||
// TODO test inverse.
|
||||
|
||||
a = Att ("name", "value");
|
||||
a.addMod ("hasnt");
|
||||
f.clear ();
|
||||
f.push_back (a);
|
||||
test.notok (f.pass (mods), "name:value -> name.hasnt:alu = no match");
|
||||
// TODO test inverse.
|
||||
|
||||
a = Att ("name", "");
|
||||
a.addMod ("any");
|
||||
f.clear ();
|
||||
f.push_back (a);
|
||||
test.ok (f.pass (mods), "name:value -> name.any: = match");
|
||||
// TODO test inverse.
|
||||
|
||||
a = Att ("name", "");
|
||||
a.addMod ("none");
|
||||
f.clear ();
|
||||
f.push_back (a);
|
||||
test.notok (f.pass (mods), "name:value -> name.none: = no match");
|
||||
// TODO test inverse.
|
||||
|
||||
/*
|
||||
"before"
|
||||
"after"
|
||||
"not"
|
||||
"synth"
|
||||
"under"
|
||||
"over"
|
||||
"first"
|
||||
"last"
|
||||
"this"
|
||||
"next"
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue