Task Refactoring

- Task is no longer a map of string to Att.  Att is itself a name/
  value pair, so the name was redundant.  Task is now a map of string
  to string.  This brings the obsoletion of Att much closer.
This commit is contained in:
Paul Beckingham 2011-08-07 22:41:25 -04:00
parent 85e77c1958
commit e2a8f85a2f
13 changed files with 120 additions and 128 deletions

View file

@ -836,8 +836,7 @@ void TDB::undo ()
view.addRow ();
// Add rows to table showing diffs.
std::vector <std::string> all;
Att::allNames (all);
std::vector <std::string> all = context.getColumns ();
// Now factor in the annotation attributes.
Task::iterator it;

View file

@ -65,7 +65,7 @@ Task& Task::operator= (const Task& other)
{
if (this != &other)
{
std::map <std::string, Att>::operator= (other);
std::map <std::string, std::string>::operator= (other);
id = other.id;
urgency_value = other.urgency_value;
@ -76,17 +76,17 @@ Task& Task::operator= (const Task& other)
}
////////////////////////////////////////////////////////////////////////////////
// The uuid and id attributes must be exempt for comparison.
// The uuid and id attributes must be exempt from comparison.
bool Task::operator== (const Task& other)
{
if (size () != other.size ())
return false;
Task::iterator att;
for (att = this->begin (); att != this->end (); ++att)
if (att->second.name () != "uuid")
if (att->second.value () != other.get (att->second.name ()))
return false;
Task::iterator i;
for (i = this->begin (); i != this->end (); ++i)
if (i->first != "uuid" &&
i->second != other.get (i->first))
return false;
return true;
}
@ -170,12 +170,12 @@ bool Task::has (const std::string& name) const
}
////////////////////////////////////////////////////////////////////////////////
std::vector <Att> Task::all ()
std::vector <std::string> Task::all ()
{
std::vector <Att> all;
std::vector <std::string> all;
Task::iterator i;
for (i = this->begin (); i != this->end (); ++i)
all.push_back (i->second);
all.push_back (i->first);
return all;
}
@ -185,7 +185,7 @@ const std::string Task::get (const std::string& name) const
{
Task::const_iterator i = this->find (name);
if (i != this->end ())
return i->second.value ();
return i->second;
return "";
}
@ -195,7 +195,7 @@ int Task::get_int (const std::string& name) const
{
Task::const_iterator i = this->find (name);
if (i != this->end ())
return atoi (i->second.value ().c_str ());
return strtol (i->second.c_str (), NULL, 10);
return 0;
}
@ -205,7 +205,7 @@ unsigned long Task::get_ulong (const std::string& name) const
{
Task::const_iterator i = this->find (name);
if (i != this->end ())
return strtoul (i->second.value ().c_str (), NULL, 10);
return strtoul (i->second.c_str (), NULL, 10);
return 0;
}
@ -215,7 +215,7 @@ time_t Task::get_date (const std::string& name) const
{
Task::const_iterator i = this->find (name);
if (i != this->end ())
return (time_t) strtoul (i->second.value ().c_str (), NULL, 10);
return (time_t) strtoul (i->second.c_str (), NULL, 10);
return 0;
}
@ -225,7 +225,7 @@ time_t Task::get_duration (const std::string& name) const
{
Task::const_iterator i = this->find (name);
if (i != this->end ())
return (time_t) strtoul (i->second.value ().c_str (), NULL, 10);
return (time_t) strtoul (i->second.c_str (), NULL, 10);
return 0;
}
@ -233,16 +233,13 @@ time_t Task::get_duration (const std::string& name) const
////////////////////////////////////////////////////////////////////////////////
void Task::set (const std::string& name, const std::string& value)
{
(*this)[name] = Att (name, value);
(*this)[name] = value;
}
////////////////////////////////////////////////////////////////////////////////
void Task::set (const std::string& name, int value)
{
std::stringstream svalue;
svalue << value;
(*this)[name] = Att (name, svalue.str ());
(*this)[name] = format (value);
}
////////////////////////////////////////////////////////////////////////////////
@ -298,11 +295,17 @@ void Task::parse (const std::string& input)
throw std::string (STRING_RECORD_EMPTY);
Nibbler nl (line);
Att a;
std::string name;
std::string value;
while (!nl.depleted ())
{
a.parse (nl);
(*this)[a.name ()] = a;
if (nl.getUntil (':', name) &&
nl.skip (':') &&
nl.getQuoted ('"', value))
{
(*this)[name] = json::decode (value);
}
nl.skip (' ');
}
@ -501,7 +504,7 @@ void Task::legacyParse (const std::string& line)
////////////////////////////////////////////////////////////////////////////////
// The format is:
//
// [ Att::composeF4 ... ] \n
// [ <name>:<value> ... ] \n
//
std::string Task::composeF4 () const
{
@ -511,9 +514,11 @@ std::string Task::composeF4 () const
Task::const_iterator it;
for (it = this->begin (); it != this->end (); ++it)
{
if (it->second.value () != "")
if (it->second != "")
{
ff4 += (first ? "" : " ") + it->second.composeF4 ();
ff4 += (first ? "" : " ")
+ it->first
+ ":\"" + json::encode (it->second) + "\"";
first = false;
}
}
@ -591,8 +596,7 @@ std::string Task::composeYAML () const
out << " task:\n";
// Get all the supported attribute names.
std::vector <std::string> names;
Att::allNames (names);
std::vector <std::string> names = context.getColumns ();
std::sort (names.begin (), names.end ());
// Only include non-trivial attributes.
@ -602,14 +606,14 @@ std::string Task::composeYAML () const
if ((value = get (*name)) != "")
out << " " << *name << ": " << value << "\n";
// Now the annotations, which are not listed by the Att::allNames call.
std::vector <Att> annotations;
// Now the annotations, which are not listed in names.
std::map <std::string, std::string> annotations;
getAnnotations (annotations);
std::vector <Att>::iterator a;
std::map <std::string, std::string>::iterator a;
for (a = annotations.begin (); a != annotations.end (); ++a)
out << " annotation:\n"
<< " entry: " << a->name().substr (11) << "\n"
<< " description: " << a->value () << "\n";
<< " entry: " << a->first.substr (11) << "\n"
<< " description: " << a->second << "\n";
return out.str ();
}
@ -624,9 +628,6 @@ std::string Task::composeJSON (bool include_id /*= false*/) const
if (include_id)
out << "\"id\":" << id << ",";
// Used for determining type.
Att att;
// First the non-annotations.
int attributes_written = 0;
int annotation_count = 0;
@ -636,18 +637,21 @@ std::string Task::composeJSON (bool include_id /*= false*/) const
if (attributes_written)
out << ",";
Column* column = context.columns[i->first];
// Annotations are simply counted.
if (i->second.name ().substr (0, 11) == "annotation_")
if (i->first.substr (0, 11) == "annotation_")
{
++annotation_count;
}
// Date fields are written as ISO 8601.
else if (att.type (i->second.name ()) == "date")
else if (column &&
column->type () == "date")
{
Date d (i->second.value ());
Date d (i->second);
out << "\""
<< i->second.name ()
<< i->second
<< "\":\""
<< d.toISO ()
<< "\"";
@ -656,10 +660,10 @@ std::string Task::composeJSON (bool include_id /*= false*/) const
}
// Tags are converted to an array.
else if (i->second.name () == "tags")
else if (i->first == "tags")
{
std::vector <std::string> tags;
split (tags, i->second.value (), ',');
split (tags, i->second, ',');
out << "\"tags\":[";
@ -679,9 +683,9 @@ std::string Task::composeJSON (bool include_id /*= false*/) const
else
{
out << "\""
<< i->second.name ()
<< i->first
<< "\":\""
<< json::encode (i->second.value ())
<< json::encode (i->second)
<< "\"";
++attributes_written;
@ -697,16 +701,16 @@ std::string Task::composeJSON (bool include_id /*= false*/) const
int annotations_written = 0;
for (i = this->begin (); i != this->end (); ++i)
{
if (i->second.name ().substr (0, 11) == "annotation_")
if (i->first.substr (0, 11) == "annotation_")
{
if (annotations_written)
out << ",";
Date d (i->second.name ().substr (11));
Date d (i->first.substr (11));
out << "{\"entry\":\""
<< d.toISO ()
<< "\",\"description\":\""
<< json::encode (i->second.value ())
<< json::encode (i->second)
<< "\"}";
++annotations_written;
@ -721,25 +725,25 @@ std::string Task::composeJSON (bool include_id /*= false*/) const
}
////////////////////////////////////////////////////////////////////////////////
void Task::getAnnotations (std::vector <Att>& annotations) const
void Task::getAnnotations (std::map <std::string, std::string>& annotations) const
{
annotations.clear ();
Task::const_iterator ci;
for (ci = this->begin (); ci != this->end (); ++ci)
if (ci->first.substr (0, 11) == "annotation_")
annotations.push_back (ci->second);
annotations.insert (*ci);
}
////////////////////////////////////////////////////////////////////////////////
void Task::setAnnotations (const std::vector <Att>& annotations)
void Task::setAnnotations (const std::map <std::string, std::string>& annotations)
{
// Erase old annotations.
removeAnnotations ();
std::vector <Att>::const_iterator ci;
std::map <std::string, std::string>::const_iterator ci;
for (ci = annotations.begin (); ci != annotations.end (); ++ci)
(*this)[ci->name ()] = *ci;
this->insert (*ci);
recalc_urgency = true;
}
@ -753,7 +757,7 @@ void Task::addAnnotation (const std::string& description)
std::stringstream s;
s << "annotation_" << time (NULL);
(*this)[s.str ()] = Att (s.str (), description);
(*this)[s.str ()] = description;
}
////////////////////////////////////////////////////////////////////////////////
@ -922,7 +926,7 @@ void Task::substitute (
{
// Get the data to modify.
std::string description = get ("description");
std::vector <Att> annotations;
std::map <std::string, std::string> annotations;
getAnnotations (annotations);
bool sensitive = context.config.getBoolean ("search.case.sensitive");
@ -962,22 +966,19 @@ void Task::substitute (
if (changes == 0 || global)
{
// Perform all subs on annotations.
std::vector <Att>::iterator it;
std::map <std::string, std::string>::iterator it;
for (it = annotations.begin (); it != annotations.end (); ++it)
{
std::string annotation = it->value ();
start.clear ();
end.clear ();
if (rx.match (start, end, annotation))
if (rx.match (start, end, it->second))
{
int skew = 0;
int limit = global ? (int) start.size () : 1;
for (int i = 0; i < limit && i < RX_MAX_MATCHES; ++i)
{
annotation.replace (start[i + skew], end[i] - start[i], to);
it->second.replace (start[i + skew], end[i] - start[i], to);
skew += to.length () - (end[i] - start[i]);
it->value (annotation);
++changes;
}
}
@ -1007,19 +1008,16 @@ void Task::substitute (
{
// Perform all subs on annotations.
counter = 0;
std::vector <Att>::iterator i;
std::map <std::string, std::string>::iterator i;
for (i = annotations.begin (); i != annotations.end (); ++i)
{
pos = 0;
std::string annotation = i->value ();
while ((pos = ::find (annotation, from, pos, sensitive)) != std::string::npos)
while ((pos = ::find (i->first, from, pos, sensitive)) != std::string::npos)
{
annotation.replace (pos, from.length (), to);
i->second.replace (pos, from.length (), to);
pos += to.length ();
++changes;
i->value (annotation);
if (! global)
break;
@ -1314,7 +1312,7 @@ float Task::urgency_blocked () const
////////////////////////////////////////////////////////////////////////////////
float Task::urgency_annotations () const
{
std::vector <Att> annos;
std::map <std::string, std::string> annos;
getAnnotations (annos);
if (annos.size () >= 3) return 1.0;

View file

@ -32,9 +32,8 @@
#include <map>
#include <string>
#include <stdio.h>
#include <Att.h>
class Task : public std::map <std::string, Att>
class Task : public std::map <std::string, std::string>
{
public:
Task (); // Default constructor
@ -67,7 +66,7 @@ public:
void setStart ();
bool has (const std::string&) const;
std::vector <Att> all ();
std::vector <std::string> all ();
const std::string get (const std::string&) const;
int get_int (const std::string&) const;
unsigned long get_ulong (const std::string&) const;
@ -87,8 +86,8 @@ public:
void getTags (std::vector<std::string>&) const;
void removeTag (const std::string&);
void getAnnotations (std::vector <Att>&) const;
void setAnnotations (const std::vector <Att>&);
void getAnnotations (std::map <std::string, std::string>&) const;
void setAnnotations (const std::map <std::string, std::string>&);
void addAnnotation (const std::string&);
void removeAnnotations ();

View file

@ -106,12 +106,12 @@ void ColumnDescription::measure (Task& task, int& minimum, int& maximum)
minimum = max (min_desc, min_anno);
maximum = description.length ();
std::vector <Att> annos;
std::map <std::string, std::string> annos;
task.getAnnotations (annos);
std::vector <Att>::iterator i;
std::map <std::string, std::string>::iterator i;
for (i = annos.begin (); i != annos.end (); i++)
{
int len = min_anno + 1 + i->value ().length ();
int len = min_anno + 1 + i->second.length ();
if (len > maximum)
maximum = len;
}
@ -136,11 +136,11 @@ void ColumnDescription::measure (Task& task, int& minimum, int& maximum)
minimum = max (min_desc, min_anno);
maximum = description.length ();
std::vector <Att> annos;
std::map <std::string, std::string> annos;
task.getAnnotations (annos);
std::vector <Att>::iterator i;
std::map <std::string, std::string>::iterator i;
for (i = annos.begin (); i != annos.end (); i++)
maximum += i->value ().length () + minimum + 1;
maximum += i->second.length () + minimum + 1;
}
// The te...
@ -153,7 +153,7 @@ void ColumnDescription::measure (Task& task, int& minimum, int& maximum)
// The text [2]
else if (_style == "count")
{
std::vector <Att> annos;
std::map <std::string, std::string> annos;
task.getAnnotations (annos);
// <description> + ' ' + '[' + <count> + ']'
@ -182,7 +182,7 @@ void ColumnDescription::render (
{
int indent = context.config.getInteger ("indent.annotation");
std::vector <Att> annos;
std::map <std::string, std::string> annos;
task.getAnnotations (annos);
if (annos.size ())
{
@ -190,11 +190,11 @@ void ColumnDescription::render (
if (format == "")
format = context.config.get ("dateformat");
std::vector <Att>::iterator i;
std::map <std::string, std::string>::iterator i;
for (i = annos.begin (); i != annos.end (); i++)
{
Date dt (atoi (i->name ().substr (11).c_str ()));
description += "\n" + std::string (indent, ' ') + dt.toString (format) + " " + i->value ();
Date dt (strtol (i->first.substr (11).c_str (), NULL, 10));
description += "\n" + std::string (indent, ' ') + dt.toString (format) + " " + i->second;
}
}
@ -220,7 +220,7 @@ void ColumnDescription::render (
// This is a description <date> <anno> ...
else if (_style == "oneline")
{
std::vector <Att> annos;
std::map <std::string, std::string> annos;
task.getAnnotations (annos);
if (annos.size ())
{
@ -228,11 +228,11 @@ void ColumnDescription::render (
if (format == "")
format = context.config.get ("dateformat");
std::vector <Att>::iterator i;
std::map <std::string, std::string>::iterator i;
for (i = annos.begin (); i != annos.end (); i++)
{
Date dt (atoi (i->name ().substr (11).c_str ()));
description += " " + dt.toString (format) + " " + i->value ();
Date dt (atoi (i->first.substr (11).c_str ()));
description += " " + dt.toString (format) + " " + i->second;
}
}
@ -257,7 +257,7 @@ void ColumnDescription::render (
// This is a description [2]
else if (_style == "count")
{
std::vector <Att> annos;
std::map <std::string, std::string> annos;
task.getAnnotations (annos);
if (annos.size ())

View file

@ -86,19 +86,18 @@ int CmdDenotate::execute (std::string& output)
{
Task before (*task);
std::vector <Att> annotations;
std::map <std::string, std::string> annotations;
task->getAnnotations (annotations);
if (annotations.size () == 0)
throw std::string (STRING_CMD_DENO_NONE);
std::vector <Att>::iterator i;
std::map <std::string, std::string>::iterator i;
std::string anno;
bool match = false;
for (i = annotations.begin (); i != annotations.end (); ++i)
{
anno = i->value ();
if (anno == pattern)
if (i->second == pattern)
{
match = true;
annotations.erase (i);
@ -110,9 +109,7 @@ int CmdDenotate::execute (std::string& output)
{
for (i = annotations.begin (); i != annotations.end (); ++i)
{
anno = i->value ();
std::string::size_type loc = find (anno, pattern, sensitive);
std::string::size_type loc = find (i->second, pattern, sensitive);
if (loc != std::string::npos)
{
annotations.erase (i);

View file

@ -199,14 +199,14 @@ std::string CmdEdit::formatTask (Task task)
<< "# The ' -- ' separator between the date and text field should not be removed.\n"
<< "# A \"blank slot\" for adding an annotation follows for your convenience.\n";
std::vector <Att> annotations;
std::map <std::string, std::string> annotations;
task.getAnnotations (annotations);
std::vector <Att>::iterator anno;
std::map <std::string, std::string>::iterator anno;
for (anno = annotations.begin (); anno != annotations.end (); ++anno)
{
Date dt (strtol (anno->name ().substr (11).c_str (), NULL, 10));
Date dt (strtol (anno->first.substr (11).c_str (), NULL, 10));
before << " Annotation: " << dt.toString (context.config.get ("dateformat.annotation"))
<< " -- " << anno->value () << "\n";
<< " -- " << anno->second << "\n";
}
Date now;
@ -252,7 +252,7 @@ void CmdEdit::parseTask (Task& task, const std::string& after)
{
if (value != "")
{
if (Att::validNameValue ("priority", "", value))
if (context.columns["priority"]->validate (value))
{
context.footnote ("Priority modified.");
task.set ("priority", value);
@ -541,7 +541,7 @@ void CmdEdit::parseTask (Task& task, const std::string& after)
}
// Annotations
std::vector <Att> annotations;
std::map <std::string, std::string> annotations;
std::string::size_type found = 0;
while ((found = after.find ("\n Annotation:", found)) != std::string::npos)
{
@ -567,7 +567,7 @@ void CmdEdit::parseTask (Task& task, const std::string& after)
std::stringstream name;
name << "annotation_" << when.toEpoch ();
std::string text = trim (value.substr (gap + 4), "\t ");
annotations.push_back (Att (name.str (), text));
annotations.insert (std::make_pair (name.str (), text));
}
}
}

View file

@ -137,7 +137,7 @@ int CmdImport::execute (std::string& output)
// 'description' values and must be converted.
if (i->first == "annotations")
{
std::vector <Att> annos;
std::map <std::string, std::string> annos;
json::array* atts = (json::array*)i->second;
json_array_iter annotations;
@ -151,7 +151,7 @@ int CmdImport::execute (std::string& output)
std::string name = "annotation_" + Date (when->_data).toEpochString ();
annos.push_back (Att (name, what->_data));
annos.insert (std::make_pair (name, what->_data));
}
task.setAnnotations (annos);
@ -336,14 +336,14 @@ void CmdImport::decorateTask (Task& task)
std::string defaultPriority = context.config.get ("default.priority");
if (!task.has ("priority") &&
defaultPriority != "" &&
Att::validNameValue ("priority", "", defaultPriority))
context.columns["priority"]->validate (defaultPriority))
task.set ("priority", defaultPriority);
// Override with default.due, if not specified.
std::string defaultDue = context.config.get ("default.due");
if (!task.has ("due") &&
defaultDue != "" &&
Att::validNameValue ("due", "", defaultDue))
context.columns["due"]->validate (defaultDue))
task.set ("due", defaultDue);
}

View file

@ -133,7 +133,7 @@ int CmdStatistics::execute (std::string& output)
descLength += task->get ("description").length ();
std::vector <Att> annotations;
std::map <std::string, std::string> annotations;
task->getAnnotations (annotations);
annotationsT += annotations.size ();

View file

@ -31,7 +31,6 @@
#include <vector>
#include <stdlib.h>
#include <E9.h>
#include <Att.h>
#include <Timer.h>
#include <text.h>
#include <i18n.h>

View file

@ -30,7 +30,6 @@
#include <vector>
#include <stdlib.h>
#include <inttypes.h>
#include <Att.h>
#include <Context.h>
#include <main.h>
#include <text.h>
@ -45,7 +44,7 @@ bool taskDiff (const Task& before, const Task& after)
// Attributes are all there is, so figure the different attribute names
// between before and after.
std::vector <std::string> beforeAtts;
std::map <std::string, Att>::const_iterator att;
Task::const_iterator att;
for (att = before.begin (); att != before.end (); ++att)
beforeAtts.push_back (att->first);
@ -76,7 +75,7 @@ std::string taskDifferences (const Task& before, const Task& after)
// Attributes are all there is, so figure the different attribute names
// between before and after.
std::vector <std::string> beforeAtts;
std::map <std::string, Att>::const_iterator att;
Task::const_iterator att;
for (att = before.begin (); att != before.end (); ++att)
beforeAtts.push_back (att->first);
@ -166,7 +165,7 @@ std::string taskInfoDifferences (const Task& before, const Task& after)
// Attributes are all there is, so figure the different attribute names
// between before and after.
std::vector <std::string> beforeAtts;
std::map <std::string, Att>::const_iterator att;
Task::const_iterator att;
for (att = before.begin (); att != before.end (); ++att)
beforeAtts.push_back (att->first);
@ -283,8 +282,9 @@ std::string taskInfoDifferences (const Task& before, const Task& after)
////////////////////////////////////////////////////////////////////////////////
std::string renderAttribute (const std::string& name, const std::string& value)
{
Att a;
if (a.type (name) == "date" &&
Column* col = context.columns[name];
if (col &&
col->type () == "date" &&
value != "")
{
Date d ((time_t)strtol (value.c_str (), NULL, 10));

View file

@ -57,7 +57,7 @@ std::string getFullDescription (Task& task, const std::string& report)
std::string desc = task.get ("description");
std::string annotationDetails;
std::vector <Att> annotations;
std::map <std::string, std::string> annotations;
task.getAnnotations (annotations);
if (annotations.size () != 0)
@ -76,25 +76,27 @@ std::string getFullDescription (Task& task, const std::string& report)
{
if (annotations.size () > 1)
desc = "+" + desc;
Att anno (annotations.back());
Date dt (atoi (anno.name ().substr (11).c_str ()));
std::map <std::string, std::string>::iterator i = annotations.begin ();
Date dt (strtol (i->first.substr (11).c_str (), NULL, 10));
std::string format = context.config.get ("dateformat.annotation");
if (format == "")
format = context.config.get ("dateformat");
std::string when = dt.toString (format);
desc += "\n" + when + " " + anno.value ();
desc += "\n" + when + " " + i->second;
}
else
{
std::vector <Att>::iterator anno;
std::map <std::string, std::string>::iterator anno;
for (anno = annotations.begin (); anno != annotations.end (); ++anno)
{
Date dt (atoi (anno->name ().substr (11).c_str ()));
Date dt (strtol (anno->first.substr (11).c_str (), NULL, 10));
std::string format = context.config.get ("dateformat.annotation");
if (format == "")
format = context.config.get ("dateformat");
std::string when = dt.toString (format);
desc += "\n" + when + " " + anno->value ();
desc += "\n" + when + " " + anno->second;
}
}
}

View file

@ -194,7 +194,7 @@ static void colorizeKeyword (Task& task, const std::string& rule, Color& c)
for (it = task.begin (); it != task.end (); ++it)
{
if (it->first.substr (0, 11) == "annotation_" &&
find (it->second.value (), rule.substr (14), sensitive) != std::string::npos)
find (it->second, rule.substr (14), sensitive) != std::string::npos)
{
c.blend (gsColor[rule]);
return;

View file

@ -35,7 +35,7 @@ Context context;
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{
UnitTest t (21);
UnitTest t (20);
// (blank)
bool good = true;
@ -105,9 +105,7 @@ int main (int argc, char** argv)
t.is (task.composeF4 (), "[name:\"value\"]\n", "Task::remove");
// Task::all
std::vector <Att> all = task.all ();
t.is (all.size (), (size_t)1, "Task::all size");
t.is (all[0].name (), "name", "Task::all[0].name ()");
t.is (task.size (), (size_t)1, "Task::all size");
return 0;
}