Decoupling

- Eliminated some calls to context.config from Task‥cpp, reducing the coupling.
  If context can be eliminated from Task.cpp, via statically initialized
  variables, then Taskwarrior and the task server can share Task.{ḩ,cpp} which
  would be an enormous saving in effort.

(cherry picked from commit 215b03b1a7f47299a0d3e64331c7e3c962b4caf0)
This commit is contained in:
Paul Beckingham 2013-05-26 10:50:32 -04:00
parent a3f158d399
commit c16a735040
4 changed files with 127 additions and 117 deletions

View file

@ -138,10 +138,6 @@ int Context::initialize (int argc, const char** argv)
// Apply rc overrides to Context::config, capturing raw args for later use. // Apply rc overrides to Context::config, capturing raw args for later use.
a3.apply_overrides (); a3.apply_overrides ();
// Now that the final RC is in place, initialize the urgency coefficients
// to speed the 'next' report.
initializeUrgencyCoefficients ();
// Initialize the color rules, if necessary. // Initialize the color rules, if necessary.
if (color ()) if (color ())
initializeColorRules (); initializeColorRules ();
@ -152,6 +148,9 @@ int Context::initialize (int argc, const char** argv)
// Instantiate built-in column objects. // Instantiate built-in column objects.
Column::factory (columns); Column::factory (columns);
// Static initialization to decouple code.
staticInitialization ();
// Categorize all arguments one more time. THIS IS NECESSARY - it helps the // Categorize all arguments one more time. THIS IS NECESSARY - it helps the
// following inject_defaults method determine whether there needs to be a // following inject_defaults method determine whether there needs to be a
// default command assumed. // default command assumed.
@ -571,6 +570,47 @@ const std::vector <std::string> Context::getCommands () const
return output; return output;
} }
////////////////////////////////////////////////////////////////////////////////
// The 'Task' object, among others, is shared between projects. To make this
// easier, it has been decoupled from Context.
void Context::staticInitialization ()
{
Task::defaultProject = config.get ("default.project");
Task::defaultPriority = config.get ("default.priority");
Task::defaultDue = config.get ("default.due");
Task::searchCaseSensitive = config.getBoolean ("search.case.sensitive");
Task::regex = config.getBoolean ("regex");
std::map <std::string, Column*>::iterator i;
for (i = columns.begin (); i != columns.end (); ++i)
Task::attributes[i->first] = i->second->type ();
Task::urgencyPriorityCoefficient = config.getReal ("urgency.priority.coefficient");
Task::urgencyProjectCoefficient = config.getReal ("urgency.project.coefficient");
Task::urgencyActiveCoefficient = config.getReal ("urgency.active.coefficient");
Task::urgencyScheduledCoefficient = config.getReal ("urgency.scheduled.coefficient");
Task::urgencyWaitingCoefficient = config.getReal ("urgency.waiting.coefficient");
Task::urgencyBlockedCoefficient = config.getReal ("urgency.blocked.coefficient");
Task::urgencyAnnotationsCoefficient = config.getReal ("urgency.annotations.coefficient");
Task::urgencyTagsCoefficient = config.getReal ("urgency.tags.coefficient");
Task::urgencyNextCoefficient = config.getReal ("urgency.next.coefficient");
Task::urgencyDueCoefficient = config.getReal ("urgency.due.coefficient");
Task::urgencyBlockingCoefficient = config.getReal ("urgency.blocking.coefficient");
Task::urgencyAgeCoefficient = config.getReal ("urgency.age.coefficient");
// Tag- and project-specific coefficients.
std::vector <std::string> all;
config.all (all);
std::vector <std::string>::iterator var;
for (var = all.begin (); var != all.end (); ++var)
{
if (var->substr (0, 13) == "urgency.user." ||
var->substr (0, 12) == "urgency.uda.")
Task::coefficients[*var] = config.getReal (*var);
}
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void Context::assumeLocations () void Context::assumeLocations ()
{ {

View file

@ -74,6 +74,7 @@ public:
void decomposeSortField (const std::string&, std::string&, bool&); void decomposeSortField (const std::string&, std::string&, bool&);
private: private:
void staticInitialization ();
void assumeLocations (); void assumeLocations ();
void createDefaultConfig (); void createDefaultConfig ();
void loadAliases (); void loadAliases ();

View file

@ -59,58 +59,30 @@ extern Context context;
static const float epsilon = 0.000001; static const float epsilon = 0.000001;
static std::map <std::string, float> coefficients; std::string Task::defaultProject = "";
float urgencyPriorityCoefficient = 0.0; std::string Task::defaultPriority = "";
float urgencyProjectCoefficient = 0.0; std::string Task::defaultDue = "";
float urgencyActiveCoefficient = 0.0; bool Task::searchCaseSensitive = true;
float urgencyScheduledCoefficient = 0.0; bool Task::regex = false;
float urgencyWaitingCoefficient = 0.0; std::map <std::string, std::string> Task::attributes;
float urgencyBlockedCoefficient = 0.0;
float urgencyAnnotationsCoefficient = 0.0; std::map <std::string, float> Task::coefficients;
float urgencyTagsCoefficient = 0.0; float Task::urgencyPriorityCoefficient = 0.0;
float urgencyNextCoefficient = 0.0; float Task::urgencyProjectCoefficient = 0.0;
float urgencyDueCoefficient = 0.0; float Task::urgencyActiveCoefficient = 0.0;
float urgencyBlockingCoefficient = 0.0; float Task::urgencyScheduledCoefficient = 0.0;
float urgencyAgeCoefficient = 0.0; float Task::urgencyWaitingCoefficient = 0.0;
float Task::urgencyBlockedCoefficient = 0.0;
float Task::urgencyAnnotationsCoefficient = 0.0;
float Task::urgencyTagsCoefficient = 0.0;
float Task::urgencyNextCoefficient = 0.0;
float Task::urgencyDueCoefficient = 0.0;
float Task::urgencyBlockingCoefficient = 0.0;
float Task::urgencyAgeCoefficient = 0.0;
#endif #endif
static const std::string dummy (""); static const std::string dummy ("");
#ifdef PRODUCT_TASKWARRIOR
////////////////////////////////////////////////////////////////////////////////
// Non-method.
//
// This is essentialy a cache of float values to save iteration and hash lookup
// in the whole config at time of Task::urgency_C.
void initializeUrgencyCoefficients ()
{
urgencyPriorityCoefficient = context.config.getReal ("urgency.priority.coefficient");
urgencyProjectCoefficient = context.config.getReal ("urgency.project.coefficient");
urgencyActiveCoefficient = context.config.getReal ("urgency.active.coefficient");
urgencyScheduledCoefficient = context.config.getReal ("urgency.scheduled.coefficient");
urgencyWaitingCoefficient = context.config.getReal ("urgency.waiting.coefficient");
urgencyBlockedCoefficient = context.config.getReal ("urgency.blocked.coefficient");
urgencyAnnotationsCoefficient = context.config.getReal ("urgency.annotations.coefficient");
urgencyTagsCoefficient = context.config.getReal ("urgency.tags.coefficient");
urgencyNextCoefficient = context.config.getReal ("urgency.next.coefficient");
urgencyDueCoefficient = context.config.getReal ("urgency.due.coefficient");
urgencyBlockingCoefficient = context.config.getReal ("urgency.blocking.coefficient");
urgencyAgeCoefficient = context.config.getReal ("urgency.age.coefficient");
// Tag- and project-specific coefficients.
std::vector <std::string> all;
context.config.all (all);
std::vector <std::string>::iterator var;
for (var = all.begin (); var != all.end (); ++var)
{
if (var->substr (0, 13) == "urgency.user." ||
var->substr (0, 12) == "urgency.uda.")
coefficients[*var] = context.config.getReal (*var);
}
}
#endif
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
Task::Task () Task::Task ()
: id (0) : id (0)
@ -502,10 +474,9 @@ void Task::parseJSON (const std::string& line)
i != root_obj->_data.end (); i != root_obj->_data.end ();
++i) ++i)
{ {
#ifdef PRODUCT_TASKWARRIOR
// If the attribute is a recognized column. // If the attribute is a recognized column.
Column* col = context.columns[i->first]; std::string type = Task::attributes[i->first];
if (col) if (type != "")
{ {
// Any specified id is ignored. // Any specified id is ignored.
if (i->first == "id") if (i->first == "id")
@ -516,7 +487,7 @@ void Task::parseJSON (const std::string& line)
; ;
// Dates are converted from ISO to epoch. // Dates are converted from ISO to epoch.
else if (col->type () == "date") else if (type == "date")
{ {
Date d (unquoteText (i->second->dump ())); Date d (unquoteText (i->second->dump ()));
set (i->first, d.toEpochString ()); set (i->first, d.toEpochString ());
@ -540,20 +511,6 @@ void Task::parseJSON (const std::string& line)
else else
set (i->first, unquoteText (i->second->dump ())); set (i->first, unquoteText (i->second->dump ()));
} }
#else
if (i->first == "tags")
{
json::array* tags = (json::array*)i->second;
json_array_iter t;
for (t = tags->_data.begin ();
t != tags->_data.end ();
++t)
{
json::string* tag = (json::string*)*t;
addTag (tag->_data);
}
}
#endif
// UDA orphans and annotations do not have columns. // UDA orphans and annotations do not have columns.
else else
@ -1175,18 +1132,16 @@ void Task::substitute (
std::map <std::string, std::string> annotations; std::map <std::string, std::string> annotations;
getAnnotations (annotations); getAnnotations (annotations);
bool sensitive = context.config.getBoolean ("search.case.sensitive");
// Count the changes, so we know whether to proceed to annotations, after // Count the changes, so we know whether to proceed to annotations, after
// modifying description. // modifying description.
int changes = 0; int changes = 0;
bool done = false; bool done = false;
// Regex support is optional. // Regex support is optional.
if (context.config.getBoolean ("regex")) if (Task::regex)
{ {
// Create the regex. // Create the regex.
RX rx (from, sensitive); RX rx (from, Task::searchCaseSensitive);
std::vector <int> start; std::vector <int> start;
std::vector <int> end; std::vector <int> end;
@ -1236,7 +1191,7 @@ void Task::substitute (
std::string::size_type pos = 0; std::string::size_type pos = 0;
int skew = 0; int skew = 0;
while ((pos = ::find (description, from, pos, sensitive)) != std::string::npos && !done) while ((pos = ::find (description, from, pos, Task::searchCaseSensitive)) != std::string::npos && !done)
{ {
description.replace (pos + skew, from.length (), to); description.replace (pos + skew, from.length (), to);
skew += to.length () - from.length (); skew += to.length () - from.length ();
@ -1260,7 +1215,7 @@ void Task::substitute (
{ {
pos = 0; pos = 0;
skew = 0; skew = 0;
while ((pos = ::find (i->second, from, pos, sensitive)) != std::string::npos && !done) while ((pos = ::find (i->second, from, pos, Task::searchCaseSensitive)) != std::string::npos && !done)
{ {
i->second.replace (pos + skew, from.length (), to); i->second.replace (pos + skew, from.length (), to);
skew += to.length () - from.length (); skew += to.length () - from.length ();
@ -1335,28 +1290,25 @@ void Task::validate (bool applyDefault /* = true */)
// Override with default.project, if not specified. // Override with default.project, if not specified.
if (applyDefault && ! has ("project")) if (applyDefault && ! has ("project"))
{ {
std::string defaultProject = context.config.get ("default.project"); if (Task::defaultProject != "" &&
if (defaultProject != "" && context.columns["project"]->validate (Task::defaultProject))
context.columns["project"]->validate (defaultProject)) set ("project", Task::defaultProject);
set ("project", defaultProject);
} }
// Override with default.priority, if not specified. // Override with default.priority, if not specified.
if (applyDefault && get ("priority") == "") if (applyDefault && get ("priority") == "")
{ {
std::string defaultPriority = context.config.get ("default.priority"); if (Task::defaultPriority != "" &&
if (defaultPriority != "" && context.columns["priority"]->validate (Task::defaultPriority))
context.columns["priority"]->validate (defaultPriority)) set ("priority", Task::defaultPriority);
set ("priority", defaultPriority);
} }
// Override with default.due, if not specified. // Override with default.due, if not specified.
if (applyDefault && get ("due") == "") if (applyDefault && get ("due") == "")
{ {
std::string defaultDue = context.config.get ("default.due"); if (Task::defaultDue != "" &&
if (defaultDue != "" && context.columns["due"]->validate (Task::defaultDue))
context.columns["due"]->validate (defaultDue)) set ("due", Date (Task::defaultDue).toEpoch ());
set ("due", Date (defaultDue).toEpoch ());
} }
// If a UDA has a default value in the configuration, // If a UDA has a default value in the configuration,
@ -1548,39 +1500,39 @@ int Task::determineVersion (const std::string& line)
float Task::urgency_c () const float Task::urgency_c () const
{ {
float value = 0.0; float value = 0.0;
value += fabsf (urgencyPriorityCoefficient) > epsilon ? (urgency_priority () * urgencyPriorityCoefficient) : 0.0; value += fabsf (Task::urgencyPriorityCoefficient) > epsilon ? (urgency_priority () * Task::urgencyPriorityCoefficient) : 0.0;
value += fabsf (urgencyProjectCoefficient) > epsilon ? (urgency_project () * urgencyProjectCoefficient) : 0.0; value += fabsf (Task::urgencyProjectCoefficient) > epsilon ? (urgency_project () * Task::urgencyProjectCoefficient) : 0.0;
value += fabsf (urgencyActiveCoefficient) > epsilon ? (urgency_active () * urgencyActiveCoefficient) : 0.0; value += fabsf (Task::urgencyActiveCoefficient) > epsilon ? (urgency_active () * Task::urgencyActiveCoefficient) : 0.0;
value += fabsf (urgencyScheduledCoefficient) > epsilon ? (urgency_scheduled () * urgencyScheduledCoefficient) : 0.0; value += fabsf (Task::urgencyScheduledCoefficient) > epsilon ? (urgency_scheduled () * Task::urgencyScheduledCoefficient) : 0.0;
value += fabsf (urgencyWaitingCoefficient) > epsilon ? (urgency_waiting () * urgencyWaitingCoefficient) : 0.0; value += fabsf (Task::urgencyWaitingCoefficient) > epsilon ? (urgency_waiting () * Task::urgencyWaitingCoefficient) : 0.0;
value += fabsf (urgencyBlockedCoefficient) > epsilon ? (urgency_blocked () * urgencyBlockedCoefficient) : 0.0; value += fabsf (Task::urgencyBlockedCoefficient) > epsilon ? (urgency_blocked () * Task::urgencyBlockedCoefficient) : 0.0;
value += fabsf (urgencyAnnotationsCoefficient) > epsilon ? (urgency_annotations () * urgencyAnnotationsCoefficient) : 0.0; value += fabsf (Task::urgencyAnnotationsCoefficient) > epsilon ? (urgency_annotations () * Task::urgencyAnnotationsCoefficient) : 0.0;
value += fabsf (urgencyTagsCoefficient) > epsilon ? (urgency_tags () * urgencyTagsCoefficient) : 0.0; value += fabsf (Task::urgencyTagsCoefficient) > epsilon ? (urgency_tags () * Task::urgencyTagsCoefficient) : 0.0;
value += fabsf (urgencyNextCoefficient) > epsilon ? (urgency_next () * urgencyNextCoefficient) : 0.0; value += fabsf (Task::urgencyNextCoefficient) > epsilon ? (urgency_next () * Task::urgencyNextCoefficient) : 0.0;
value += fabsf (urgencyDueCoefficient) > epsilon ? (urgency_due () * urgencyDueCoefficient) : 0.0; value += fabsf (Task::urgencyDueCoefficient) > epsilon ? (urgency_due () * Task::urgencyDueCoefficient) : 0.0;
value += fabsf (urgencyBlockingCoefficient) > epsilon ? (urgency_blocking () * urgencyBlockingCoefficient) : 0.0; value += fabsf (Task::urgencyBlockingCoefficient) > epsilon ? (urgency_blocking () * Task::urgencyBlockingCoefficient) : 0.0;
value += fabsf (urgencyAgeCoefficient) > epsilon ? (urgency_age () * urgencyAgeCoefficient) : 0.0; value += fabsf (Task::urgencyAgeCoefficient) > epsilon ? (urgency_age () * Task::urgencyAgeCoefficient) : 0.0;
/* /*
// Very useful for debugging urgency problems. // Very useful for debugging urgency problems.
std::cout << "# Urgency for " << get ("uuid") << ":\n" std::cout << "# Urgency for " << get ("uuid") << ":\n"
<< "# pri " << (urgency_priority () * urgencyPriorityCoefficient) << "\n" << "# pri " << (urgency_priority () * Task::urgencyPriorityCoefficient) << "\n"
<< "# pro " << (urgency_project () * urgencyProjectCoefficient) << "\n" << "# pro " << (urgency_project () * Task::urgencyProjectCoefficient) << "\n"
<< "# act " << (urgency_active () * urgencyActiveCoefficient) << "\n" << "# act " << (urgency_active () * Task::urgencyActiveCoefficient) << "\n"
<< "# sch " << (urgency_scheduled () * urgencyScheduledCoefficient) << "\n" << "# sch " << (urgency_scheduled () * Task::urgencyScheduledCoefficient) << "\n"
<< "# wai " << (urgency_waiting () * urgencyWaitingCoefficient) << "\n" << "# wai " << (urgency_waiting () * Task::urgencyWaitingCoefficient) << "\n"
<< "# blk " << (urgency_blocked () * urgencyBlockedCoefficient) << "\n" << "# blk " << (urgency_blocked () * Task::urgencyBlockedCoefficient) << "\n"
<< "# ann " << (urgency_annotations () * urgencyAnnotationsCoefficient) << "\n" << "# ann " << (urgency_annotations () * Task::urgencyAnnotationsCoefficient) << "\n"
<< "# tag " << (urgency_tags () * urgencyTagsCoefficient) << "\n" << "# tag " << (urgency_tags () * Task::urgencyTagsCoefficient) << "\n"
<< "# nex " << (urgency_next () * urgencyNextCoefficient) << "\n" << "# nex " << (urgency_next () * Task::urgencyNextCoefficient) << "\n"
<< "# due " << (urgency_due () * urgencyDueCoefficient) << "\n" << "# due " << (urgency_due () * Task::urgencyDueCoefficient) << "\n"
<< "# bkg " << (urgency_blocking () * urgencyBlockingCoefficient) << "\n" << "# bkg " << (urgency_blocking () * Task::urgencyBlockingCoefficient) << "\n"
<< "# age " << (urgency_age () * urgencyAgeCoefficient) << "\n"; << "# age " << (urgency_age () * Task::urgencyAgeCoefficient) << "\n";
*/ */
// Tag- and project-specific coefficients. // Tag- and project-specific coefficients.
std::map <std::string, float>::iterator var; std::map <std::string, float>::iterator var;
for (var = coefficients.begin (); var != coefficients.end (); ++var) for (var = Task::coefficients.begin (); var != Task::coefficients.end (); ++var)
{ {
if (fabs (var->second) > epsilon) if (fabs (var->second) > epsilon)
{ {

View file

@ -34,12 +34,29 @@
#include <string> #include <string>
#include <stdio.h> #include <stdio.h>
#ifdef PRODUCT_TASKWARRIOR
void initializeUrgencyCoefficients ();
#endif
class Task : public std::map <std::string, std::string> class Task : public std::map <std::string, std::string>
{ {
public:
static std::string defaultProject;
static std::string defaultPriority;
static std::string defaultDue;
static bool searchCaseSensitive;
static bool regex;
static std::map <std::string, std::string> attributes; // name -> type
static std::map <std::string, float> coefficients;
static float urgencyPriorityCoefficient;
static float urgencyProjectCoefficient;
static float urgencyActiveCoefficient;
static float urgencyScheduledCoefficient;
static float urgencyWaitingCoefficient;
static float urgencyBlockedCoefficient;
static float urgencyAnnotationsCoefficient;
static float urgencyTagsCoefficient;
static float urgencyNextCoefficient;
static float urgencyDueCoefficient;
static float urgencyBlockingCoefficient;
static float urgencyAgeCoefficient;
public: public:
Task (); // Default constructor Task (); // Default constructor
Task (const Task&); // Copy constructor Task (const Task&); // Copy constructor