mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-07-07 20:06:36 +02:00
- Factored out filtering code.
This commit is contained in:
parent
7fb3ab0c3d
commit
9bca303113
2 changed files with 298 additions and 483 deletions
|
@ -12,6 +12,7 @@ Configurable columns in reports
|
|||
1.3.0 (?)
|
||||
+ "task calendar" now displays multiple months per line, adjustable by the
|
||||
"monthsperline" configuration variable. Feature added by Damian Glenny
|
||||
+ "task export" can now filter tasks like the reports.
|
||||
+ Bug: Segmentation fault when no "dateformat" configuration variable
|
||||
specified
|
||||
+ Bug: Fixed bug whereby if you have more than one task with a due date, 7
|
||||
|
|
328
src/task.cpp
328
src/task.cpp
|
@ -285,6 +285,66 @@ int main (int argc, char** argv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static void filter (std::vector<T>& all, T& task)
|
||||
{
|
||||
std::vector <T> filtered;
|
||||
|
||||
// Split any description specified into words.
|
||||
std::vector <std::string> descWords;
|
||||
split (descWords, lowerCase (task.getDescription ()), ' ');
|
||||
|
||||
// Get all the tags to match against.
|
||||
std::vector <std::string> tagList;
|
||||
task.getTags (tagList);
|
||||
|
||||
// Get all the attributes to match against.
|
||||
std::map <std::string, std::string> attrList;
|
||||
task.getAttributes (attrList);
|
||||
|
||||
// Iterate over each task, and apply selection criteria.
|
||||
for (unsigned int i = 0; i < all.size (); ++i)
|
||||
{
|
||||
T refTask (all[i]);
|
||||
|
||||
// Apply description filter.
|
||||
std::string desc = lowerCase (refTask.getDescription ());
|
||||
unsigned int matches = 0;
|
||||
for (unsigned int w = 0; w < descWords.size (); ++w)
|
||||
if (desc.find (descWords[w]) != std::string::npos)
|
||||
++matches;
|
||||
|
||||
if (matches == descWords.size ())
|
||||
{
|
||||
// Apply attribute filter.
|
||||
matches = 0;
|
||||
foreach (a, attrList)
|
||||
if (a->first == "project")
|
||||
{
|
||||
if (a->second.length () <= refTask.getAttribute (a->first).length ())
|
||||
if (a->second == refTask.getAttribute (a->first).substr (0, a->second.length ()))
|
||||
++matches;
|
||||
}
|
||||
else if (a->second == refTask.getAttribute (a->first))
|
||||
++matches;
|
||||
|
||||
if (matches == attrList.size ())
|
||||
{
|
||||
// Apply tag filter.
|
||||
matches = 0;
|
||||
for (unsigned int t = 0; t < tagList.size (); ++t)
|
||||
if (refTask.hasTag (tagList[t]))
|
||||
++matches;
|
||||
|
||||
if (matches == tagList.size ())
|
||||
filtered.push_back (refTask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
all = filtered;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void handleAdd (const TDB& tdb, T& task, Config& conf)
|
||||
{
|
||||
|
@ -446,56 +506,11 @@ void handleList (const TDB& tdb, T& task, Config& conf)
|
|||
|
||||
table.setDateFormat (conf.get ("dateformat", "m/d/Y"));
|
||||
|
||||
// Split any description specified into words.
|
||||
std::vector <std::string> descWords;
|
||||
split (descWords, lowerCase (task.getDescription ()), ' ');
|
||||
|
||||
// Get all the tags to match against.
|
||||
std::vector <std::string> tagList;
|
||||
task.getTags (tagList);
|
||||
|
||||
// Get all the attributes to match against.
|
||||
std::map <std::string, std::string> attrList;
|
||||
task.getAttributes (attrList);
|
||||
|
||||
// Iterate over each task, and apply selection criteria.
|
||||
filter (tasks, task);
|
||||
for (unsigned int i = 0; i < tasks.size (); ++i)
|
||||
{
|
||||
T refTask (tasks[i]);
|
||||
|
||||
// Apply description filter.
|
||||
std::string desc = lowerCase (refTask.getDescription ());
|
||||
unsigned int matches = 0;
|
||||
for (unsigned int w = 0; w < descWords.size (); ++w)
|
||||
if (desc.find (descWords[w]) != std::string::npos)
|
||||
++matches;
|
||||
|
||||
if (matches == descWords.size ())
|
||||
{
|
||||
// Apply attribute filter.
|
||||
matches = 0;
|
||||
foreach (a, attrList)
|
||||
{
|
||||
if (a->first == "project")
|
||||
{
|
||||
if (a->second.length () <= refTask.getAttribute (a->first).length ())
|
||||
if (a->second == refTask.getAttribute (a->first).substr (0, a->second.length ()))
|
||||
++matches;
|
||||
}
|
||||
else if (a->second == refTask.getAttribute (a->first))
|
||||
++matches;
|
||||
}
|
||||
|
||||
if (matches == attrList.size ())
|
||||
{
|
||||
// Apply tag filter.
|
||||
matches = 0;
|
||||
for (unsigned int t = 0; t < tagList.size (); ++t)
|
||||
if (refTask.hasTag (tagList[t]))
|
||||
++matches;
|
||||
|
||||
if (matches == tagList.size ())
|
||||
{
|
||||
// Now format the matching task.
|
||||
bool imminent = false;
|
||||
bool overdue = false;
|
||||
|
@ -550,9 +565,6 @@ void handleList (const TDB& tdb, T& task, Config& conf)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (table.rowCount ())
|
||||
std::cout << optionalBlankLine (conf)
|
||||
|
@ -616,56 +628,12 @@ void handleSmallList (const TDB& tdb, T& task, Config& conf)
|
|||
table.sortOn (2, Table::descendingPriority);
|
||||
table.sortOn (1, Table::ascendingCharacter);
|
||||
|
||||
// Split any description specified into words.
|
||||
std::vector <std::string> descWords;
|
||||
split (descWords, lowerCase (task.getDescription ()), ' ');
|
||||
|
||||
// Get all the tags to match against.
|
||||
std::vector <std::string> tagList;
|
||||
task.getTags (tagList);
|
||||
|
||||
// Get all the attributes to match against.
|
||||
std::map <std::string, std::string> attrList;
|
||||
task.getAttributes (attrList);
|
||||
|
||||
// Iterate over each task, and apply selection criteria.
|
||||
filter (tasks, task);
|
||||
for (unsigned int i = 0; i < tasks.size (); ++i)
|
||||
{
|
||||
T refTask (tasks[i]);
|
||||
|
||||
// Apply description filter.
|
||||
std::string desc = lowerCase (refTask.getDescription ());
|
||||
unsigned int matches = 0;
|
||||
for (unsigned int w = 0; w < descWords.size (); ++w)
|
||||
if (desc.find (descWords[w]) != std::string::npos)
|
||||
++matches;
|
||||
|
||||
if (matches == descWords.size ())
|
||||
{
|
||||
// Apply attribute filter.
|
||||
matches = 0;
|
||||
foreach (a, attrList)
|
||||
{
|
||||
if (a->first == "project")
|
||||
{
|
||||
if (a->second.length () <= refTask.getAttribute (a->first).length ())
|
||||
if (a->second == refTask.getAttribute (a->first).substr (0, a->second.length ()))
|
||||
++matches;
|
||||
}
|
||||
else if (a->second == refTask.getAttribute (a->first))
|
||||
++matches;
|
||||
}
|
||||
|
||||
if (matches == attrList.size ())
|
||||
{
|
||||
// Apply tag filter.
|
||||
matches = 0;
|
||||
for (unsigned int t = 0; t < tagList.size (); ++t)
|
||||
if (refTask.hasTag (tagList[t]))
|
||||
++matches;
|
||||
|
||||
if (matches == tagList.size ())
|
||||
{
|
||||
// Now format the matching task.
|
||||
bool imminent = false;
|
||||
bool overdue = false;
|
||||
|
@ -717,9 +685,6 @@ void handleSmallList (const TDB& tdb, T& task, Config& conf)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (table.rowCount ())
|
||||
std::cout << optionalBlankLine (conf)
|
||||
|
@ -779,56 +744,12 @@ void handleCompleted (const TDB& tdb, T& task, Config& conf)
|
|||
|
||||
table.sortOn (0, Table::ascendingDate);
|
||||
|
||||
// Split any description specified into words.
|
||||
std::vector <std::string> descWords;
|
||||
split (descWords, lowerCase (task.getDescription ()), ' ');
|
||||
|
||||
// Get all the tags to match against.
|
||||
std::vector <std::string> tagList;
|
||||
task.getTags (tagList);
|
||||
|
||||
// Get all the attributes to match against.
|
||||
std::map <std::string, std::string> attrList;
|
||||
task.getAttributes (attrList);
|
||||
|
||||
// Iterate over each task, and apply selection criteria.
|
||||
filter (tasks, task);
|
||||
for (unsigned int i = 0; i < tasks.size (); ++i)
|
||||
{
|
||||
T refTask (tasks[i]);
|
||||
|
||||
// Apply description filter.
|
||||
std::string desc = lowerCase (refTask.getDescription ());
|
||||
unsigned int matches = 0;
|
||||
for (unsigned int w = 0; w < descWords.size (); ++w)
|
||||
if (desc.find (descWords[w]) != std::string::npos)
|
||||
++matches;
|
||||
|
||||
if (matches == descWords.size ())
|
||||
{
|
||||
// Apply attribute filter.
|
||||
matches = 0;
|
||||
foreach (a, attrList)
|
||||
{
|
||||
if (a->first == "project")
|
||||
{
|
||||
if (a->second.length () <= refTask.getAttribute (a->first).length ())
|
||||
if (a->second == refTask.getAttribute (a->first).substr (0, a->second.length ()))
|
||||
++matches;
|
||||
}
|
||||
else if (a->second == refTask.getAttribute (a->first))
|
||||
++matches;
|
||||
}
|
||||
|
||||
if (matches == attrList.size ())
|
||||
{
|
||||
// Apply tag filter.
|
||||
matches = 0;
|
||||
for (unsigned int t = 0; t < tagList.size (); ++t)
|
||||
if (refTask.hasTag (tagList[t]))
|
||||
++matches;
|
||||
|
||||
if (matches == tagList.size ())
|
||||
{
|
||||
// Now format the matching task.
|
||||
Date end (::atoi (refTask.getAttribute ("end").c_str ()));
|
||||
|
||||
|
@ -848,9 +769,6 @@ void handleCompleted (const TDB& tdb, T& task, Config& conf)
|
|||
table.setRowBg (row, bg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (table.rowCount ())
|
||||
std::cout << optionalBlankLine (conf)
|
||||
|
@ -1097,56 +1015,12 @@ void handleLongList (const TDB& tdb, T& task, Config& conf)
|
|||
table.sortOn (2, Table::descendingPriority);
|
||||
table.sortOn (1, Table::ascendingCharacter);
|
||||
|
||||
// Split any description specified into words.
|
||||
std::vector <std::string> descWords;
|
||||
split (descWords, lowerCase (task.getDescription ()), ' ');
|
||||
|
||||
// Get all the tags to match against.
|
||||
std::vector <std::string> tagList;
|
||||
task.getTags (tagList);
|
||||
|
||||
// Get all the attributes to match against.
|
||||
std::map <std::string, std::string> attrList;
|
||||
task.getAttributes (attrList);
|
||||
|
||||
// Iterate over each task, and apply selection criteria.
|
||||
filter (tasks, task);
|
||||
for (unsigned int i = 0; i < tasks.size (); ++i)
|
||||
{
|
||||
T refTask (tasks[i]);
|
||||
|
||||
// Apply description filter.
|
||||
std::string desc = lowerCase (refTask.getDescription ());
|
||||
unsigned int matches = 0;
|
||||
for (unsigned int w = 0; w < descWords.size (); ++w)
|
||||
if (desc.find (descWords[w]) != std::string::npos)
|
||||
++matches;
|
||||
|
||||
if (matches == descWords.size ())
|
||||
{
|
||||
// Apply attribute filter.
|
||||
matches = 0;
|
||||
foreach (a, attrList)
|
||||
{
|
||||
if (a->first == "project")
|
||||
{
|
||||
if (a->second.length () <= refTask.getAttribute (a->first).length ())
|
||||
if (a->second == refTask.getAttribute (a->first).substr (0, a->second.length ()))
|
||||
++matches;
|
||||
}
|
||||
else if (a->second == refTask.getAttribute (a->first))
|
||||
++matches;
|
||||
}
|
||||
|
||||
if (matches == attrList.size ())
|
||||
{
|
||||
// Apply tag filter.
|
||||
matches = 0;
|
||||
for (unsigned int t = 0; t < tagList.size (); ++t)
|
||||
if (refTask.hasTag (tagList[t]))
|
||||
++matches;
|
||||
|
||||
if (matches == tagList.size ())
|
||||
{
|
||||
Date now;
|
||||
|
||||
std::string started = refTask.getAttribute ("start");
|
||||
|
@ -1220,9 +1094,6 @@ void handleLongList (const TDB& tdb, T& task, Config& conf)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (table.rowCount ())
|
||||
std::cout << optionalBlankLine (conf)
|
||||
|
@ -1468,56 +1339,11 @@ void handleReportNext (const TDB& tdb, T& task, Config& conf)
|
|||
table.sortOn (2, Table::descendingPriority);
|
||||
table.sortOn (1, Table::ascendingCharacter);
|
||||
|
||||
// Split any description specified into words.
|
||||
std::vector <std::string> descWords;
|
||||
split (descWords, lowerCase (task.getDescription ()), ' ');
|
||||
|
||||
// Get all the tags to match against.
|
||||
std::vector <std::string> tagList;
|
||||
task.getTags (tagList);
|
||||
|
||||
// Get all the attributes to match against.
|
||||
std::map <std::string, std::string> attrList;
|
||||
task.getAttributes (attrList);
|
||||
|
||||
// Iterate over each task, and apply selection criteria.
|
||||
foreach (i, matching)
|
||||
{
|
||||
T refTask (pending[*i]);
|
||||
|
||||
// Apply description filter.
|
||||
std::string desc = lowerCase (refTask.getDescription ());
|
||||
unsigned int matches = 0;
|
||||
for (unsigned int w = 0; w < descWords.size (); ++w)
|
||||
if (desc.find (descWords[w]) != std::string::npos)
|
||||
++matches;
|
||||
|
||||
if (matches == descWords.size ())
|
||||
{
|
||||
// Apply attribute filter.
|
||||
matches = 0;
|
||||
foreach (a, attrList)
|
||||
{
|
||||
if (a->first == "project")
|
||||
{
|
||||
if (a->second.length () <= refTask.getAttribute (a->first).length ())
|
||||
if (a->second == refTask.getAttribute (a->first).substr (0, a->second.length ()))
|
||||
++matches;
|
||||
}
|
||||
else if (a->second == refTask.getAttribute (a->first))
|
||||
++matches;
|
||||
}
|
||||
|
||||
if (matches == attrList.size ())
|
||||
{
|
||||
// Apply tag filter.
|
||||
matches = 0;
|
||||
for (unsigned int t = 0; t < tagList.size (); ++t)
|
||||
if (refTask.hasTag (tagList[t]))
|
||||
++matches;
|
||||
|
||||
if (matches == tagList.size ())
|
||||
{
|
||||
// Now format the matching task.
|
||||
bool imminent = false;
|
||||
bool overdue = false;
|
||||
|
@ -1572,9 +1398,6 @@ void handleReportNext (const TDB& tdb, T& task, Config& conf)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (table.rowCount ())
|
||||
std::cout << optionalBlankLine (conf)
|
||||
|
@ -2087,15 +1910,8 @@ void handleReportActive (const TDB& tdb, T& task, Config& conf)
|
|||
table.sortOn (2, Table::descendingPriority);
|
||||
table.sortOn (1, Table::ascendingCharacter);
|
||||
|
||||
// Get all the tags to match against.
|
||||
std::vector <std::string> tagList;
|
||||
task.getTags (tagList);
|
||||
|
||||
// Get all the attributes to match against.
|
||||
std::map <std::string, std::string> attrList;
|
||||
task.getAttributes (attrList);
|
||||
|
||||
// Iterate over each task, and apply selection criteria.
|
||||
filter (tasks, task);
|
||||
for (unsigned int i = 0; i < tasks.size (); ++i)
|
||||
{
|
||||
T refTask (tasks[i]);
|
||||
|
@ -2202,17 +2018,10 @@ void handleReportOverdue (const TDB& tdb, T& task, Config& conf)
|
|||
table.sortOn (2, Table::descendingPriority);
|
||||
table.sortOn (1, Table::ascendingCharacter);
|
||||
|
||||
// Get all the tags to match against.
|
||||
std::vector <std::string> tagList;
|
||||
task.getTags (tagList);
|
||||
|
||||
// Get all the attributes to match against.
|
||||
std::map <std::string, std::string> attrList;
|
||||
task.getAttributes (attrList);
|
||||
|
||||
Date now;
|
||||
|
||||
// Iterate over each task, and apply selection criteria.
|
||||
filter (tasks, task);
|
||||
for (unsigned int i = 0; i < tasks.size (); ++i)
|
||||
{
|
||||
T refTask (tasks[i]);
|
||||
|
@ -2479,7 +2288,11 @@ void handleDone (const TDB& tdb, T& task, Config& conf)
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
void handleExport (const TDB& tdb, T& task, Config& conf)
|
||||
{
|
||||
// Use the description as a file name, then clobber the description so the
|
||||
// file name isn't used for filtering.
|
||||
std::string file = trim (task.getDescription ());
|
||||
task.setDescription ("");
|
||||
|
||||
if (file.length () > 0)
|
||||
{
|
||||
std::ofstream out (file.c_str ());
|
||||
|
@ -2501,6 +2314,7 @@ void handleExport (const TDB& tdb, T& task, Config& conf)
|
|||
|
||||
std::vector <T> all;
|
||||
tdb.allT (all);
|
||||
filter (all, task);
|
||||
foreach (t, all)
|
||||
{
|
||||
out << t->composeCSV ().c_str ();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue