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
96
src/Att.cpp
96
src/Att.cpp
|
@ -27,7 +27,8 @@
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <text.h>
|
#include "text.h"
|
||||||
|
#include "util.h"
|
||||||
#include "Att.h"
|
#include "Att.h"
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -159,41 +160,78 @@ 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
|
bool Att::match (const Att& other) const
|
||||||
{
|
{
|
||||||
// No modifier means automatic pass.
|
// Assume a match, and short-circuit on mismatch.
|
||||||
/*
|
foreach (mod, mMods)
|
||||||
if (*this == "") // i18n: no
|
{
|
||||||
return true;
|
// is = equal.
|
||||||
*/
|
if (*mod == "is")
|
||||||
|
if (mValue != other.mValue)
|
||||||
|
return false;
|
||||||
|
|
||||||
// TODO before
|
// isnt = not equal.
|
||||||
// TODO after
|
if (*mod == "isnt")
|
||||||
// TODO not
|
if (mValue == other.mValue)
|
||||||
// TODO none
|
return false;
|
||||||
// TODO any
|
|
||||||
// TODO synth
|
|
||||||
// TODO under
|
|
||||||
// TODO over
|
|
||||||
// TODO first
|
|
||||||
// TODO last
|
|
||||||
// TODO this
|
|
||||||
// TODO next
|
|
||||||
|
|
||||||
/*
|
// any = any value, but not empty value.
|
||||||
if (*this == "is") // i18n: TODO
|
if (*mod == "any")
|
||||||
return *this == other ? true : false;
|
if (other.mValue == "")
|
||||||
|
return false;
|
||||||
|
|
||||||
if (*this == "isnt") // i18n: TODO
|
// none = must have empty value.
|
||||||
return *this != other ? true : false;
|
if (*mod == "none")
|
||||||
*/
|
if (other.mValue != "")
|
||||||
|
return false;
|
||||||
|
|
||||||
// TODO has
|
// startswith = first characters must match.
|
||||||
// TODO hasnt
|
if (*mod == "startswith")
|
||||||
// TODO startswith
|
{
|
||||||
// TODO endswith
|
if (other.mValue.length () < mValue.length ())
|
||||||
|
return false;
|
||||||
|
|
||||||
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 <-- could be a problem
|
||||||
|
// TODO synth
|
||||||
|
// TODO under
|
||||||
|
// TODO over
|
||||||
|
// TODO first
|
||||||
|
// TODO last
|
||||||
|
// TODO this
|
||||||
|
// TODO next
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
// If record doesn't have the attribute, fail. If it does have the attribute
|
||||||
// but it doesn't match, fail.
|
// but it doesn't match, fail.
|
||||||
foreach (att, (*this))
|
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;
|
return false;
|
||||||
|
}
|
||||||
|
else if (! att->match (r->second))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ Context context;
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
int main (int argc, char** argv)
|
int main (int argc, char** argv)
|
||||||
{
|
{
|
||||||
UnitTest test (6);
|
UnitTest test (14);
|
||||||
|
|
||||||
// Create a filter consisting of two Att criteria.
|
// Create a filter consisting of two Att criteria.
|
||||||
Filter f;
|
Filter f;
|
||||||
|
@ -63,7 +63,78 @@ int main (int argc, char** argv)
|
||||||
partial.set ("name1", "value1");
|
partial.set ("name1", "value1");
|
||||||
test.notok (f.pass (no0), "no match against partial T2");
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue