mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-06-26 10:54:26 +02:00
File Format
- File format 2 (used in version 0.9.3 - 1.5.0) is no longer supported. - Task::parseJSON implemented. - PRODUCT_TASKWARRIOR defined, to facilitate code sharing. - Strings renamed for sharing purposes.
This commit is contained in:
parent
00f8f56c00
commit
6a97017c79
11 changed files with 254 additions and 139 deletions
|
@ -24,6 +24,7 @@ Features
|
||||||
+ The 'due' urgency component now uses seconds, not days, in the calculation.
|
+ The 'due' urgency component now uses seconds, not days, in the calculation.
|
||||||
+ The 'debug.tls' configuration variable takes an integer which corresponds to
|
+ The 'debug.tls' configuration variable takes an integer which corresponds to
|
||||||
the GnuTLS log level. For debugging.
|
the GnuTLS log level. For debugging.
|
||||||
|
+ File format 2 (used in version 0.9.3 - 1.5.0) is no longer supported.
|
||||||
|
|
||||||
Bugs
|
Bugs
|
||||||
+ #1196 Now builds on Hurd (thanks to Jakub Wilk).
|
+ #1196 Now builds on Hurd (thanks to Jakub Wilk).
|
||||||
|
|
2
NEWS
2
NEWS
|
@ -22,7 +22,7 @@ New configuration options in taskwarrior 2.3.0
|
||||||
|
|
||||||
Newly deprecated features in taskwarrior 2.3.0
|
Newly deprecated features in taskwarrior 2.3.0
|
||||||
|
|
||||||
-
|
- File format 2 (used in version 0.9.3 - 1.5.0) is no longer supported.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
/* cmake.h.in. Creates cmake.h during a cmake run */
|
/* cmake.h.in. Creates cmake.h during a cmake run */
|
||||||
|
|
||||||
|
/* Product identification */
|
||||||
|
#define PRODUCT_TASKWARRIOR 1
|
||||||
|
|
||||||
/* Package information */
|
/* Package information */
|
||||||
#define PACKAGE "${PACKAGE}"
|
#define PACKAGE "${PACKAGE}"
|
||||||
#define VERSION "${VERSION}"
|
#define VERSION "${VERSION}"
|
||||||
|
|
279
src/Task.cpp
279
src/Task.cpp
|
@ -25,21 +25,30 @@
|
||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include <cmake.h>
|
||||||
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#endif
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <Context.h>
|
#include <Context.h>
|
||||||
#include <Nibbler.h>
|
#include <Nibbler.h>
|
||||||
|
#endif
|
||||||
#include <Date.h>
|
#include <Date.h>
|
||||||
#include <Duration.h>
|
#include <Duration.h>
|
||||||
#include <Task.h>
|
#include <Task.h>
|
||||||
#include <JSON.h>
|
#include <JSON.h>
|
||||||
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
#include <RX.h>
|
#include <RX.h>
|
||||||
|
#endif
|
||||||
#include <text.h>
|
#include <text.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
|
||||||
#include <i18n.h>
|
#include <i18n.h>
|
||||||
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
#include <main.h>
|
#include <main.h>
|
||||||
|
|
||||||
#define APPROACHING_INFINITY 1000 // Close enough. This isn't rocket surgery.
|
#define APPROACHING_INFINITY 1000 // Close enough. This isn't rocket surgery.
|
||||||
|
@ -96,14 +105,17 @@ void initializeUrgencyCoefficients ()
|
||||||
coefficients[*var] = context.config.getReal (*var);
|
coefficients[*var] = context.config.getReal (*var);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
Task::Task ()
|
Task::Task ()
|
||||||
: id (0)
|
: id (0)
|
||||||
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
, urgency_value (0.0)
|
, urgency_value (0.0)
|
||||||
, recalc_urgency (true)
|
, recalc_urgency (true)
|
||||||
, is_blocked (false)
|
, is_blocked (false)
|
||||||
, is_blocking (false)
|
, is_blocking (false)
|
||||||
|
#endif
|
||||||
, annotation_count (0)
|
, annotation_count (0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -120,13 +132,14 @@ Task& Task::operator= (const Task& other)
|
||||||
if (this != &other)
|
if (this != &other)
|
||||||
{
|
{
|
||||||
std::map <std::string, std::string>::operator= (other);
|
std::map <std::string, std::string>::operator= (other);
|
||||||
|
|
||||||
id = other.id;
|
id = other.id;
|
||||||
|
#ifdef PRODUCT_TASKWARIROR
|
||||||
urgency_value = other.urgency_value;
|
urgency_value = other.urgency_value;
|
||||||
recalc_urgency = other.recalc_urgency;
|
recalc_urgency = other.recalc_urgency;
|
||||||
is_blocked = other.is_blocked;
|
is_blocked = other.is_blocked;
|
||||||
is_blocking = other.is_blocking;
|
is_blocking = other.is_blocking;
|
||||||
annotation_count = other.annotation_count;
|
annotation_count = other.annotation_count;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -152,11 +165,13 @@ bool Task::operator== (const Task& other)
|
||||||
Task::Task (const std::string& input)
|
Task::Task (const std::string& input)
|
||||||
{
|
{
|
||||||
id = 0;
|
id = 0;
|
||||||
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
urgency_value = 0.0;
|
urgency_value = 0.0;
|
||||||
recalc_urgency = true;
|
recalc_urgency = true;
|
||||||
is_blocked = false;
|
is_blocked = false;
|
||||||
is_blocking = false;
|
is_blocking = false;
|
||||||
annotation_count = 0;
|
annotation_count = 0;
|
||||||
|
#endif
|
||||||
parse (input);
|
parse (input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,6 +204,7 @@ std::string Task::statusToText (Task::status s)
|
||||||
return "pending";
|
return "pending";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void Task::setEntry ()
|
void Task::setEntry ()
|
||||||
{
|
{
|
||||||
|
@ -218,6 +234,7 @@ void Task::setStart ()
|
||||||
|
|
||||||
recalc_urgency = true;
|
recalc_urgency = true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void Task::setModified ()
|
void Task::setModified ()
|
||||||
|
@ -258,6 +275,7 @@ const std::string Task::get (const std::string& name) const
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
const std::string& Task::get_ref (const std::string& name) const
|
const std::string& Task::get_ref (const std::string& name) const
|
||||||
{
|
{
|
||||||
|
@ -287,6 +305,7 @@ unsigned long Task::get_ulong (const std::string& name) const
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
time_t Task::get_date (const std::string& name) const
|
time_t Task::get_date (const std::string& name) const
|
||||||
|
@ -303,7 +322,9 @@ void Task::set (const std::string& name, const std::string& value)
|
||||||
{
|
{
|
||||||
(*this)[name] = value;
|
(*this)[name] = value;
|
||||||
|
|
||||||
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
recalc_urgency = true;
|
recalc_urgency = true;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -311,7 +332,9 @@ void Task::set (const std::string& name, int value)
|
||||||
{
|
{
|
||||||
(*this)[name] = format (value);
|
(*this)[name] = format (value);
|
||||||
|
|
||||||
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
recalc_urgency = true;
|
recalc_urgency = true;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -321,7 +344,9 @@ void Task::remove (const std::string& name)
|
||||||
if ((it = this->find (name)) != this->end ())
|
if ((it = this->find (name)) != this->end ())
|
||||||
this->erase (it);
|
this->erase (it);
|
||||||
|
|
||||||
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
recalc_urgency = true;
|
recalc_urgency = true;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -335,9 +360,12 @@ void Task::setStatus (Task::status status)
|
||||||
{
|
{
|
||||||
set ("status", statusToText (status));
|
set ("status", statusToText (status));
|
||||||
|
|
||||||
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
recalc_urgency = true;
|
recalc_urgency = true;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
bool Task::is_due () const
|
bool Task::is_due () const
|
||||||
{
|
{
|
||||||
|
@ -391,10 +419,13 @@ bool Task::is_overdue () const
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Attempt an FF4 parse first, using Task::parse, and in the event of an error
|
// Attempt an FF4 parse first, using Task::parse, and in the event of an error
|
||||||
// try a legacy parse (F3, FF2). Note that FF1 is no longer supported.
|
// try a JSON parse, otherwise a legacy parse (FF3).
|
||||||
|
//
|
||||||
|
// Note that FF1 and FF2 are no longer supported.
|
||||||
//
|
//
|
||||||
// start --> [ --> Att --> ] --> end
|
// start --> [ --> Att --> ] --> end
|
||||||
// ^ |
|
// ^ |
|
||||||
|
@ -410,6 +441,7 @@ void Task::parse (const std::string& input)
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// File format version 4, from 2009-5-16 - now, v1.7.1+
|
||||||
clear ();
|
clear ();
|
||||||
|
|
||||||
Nibbler n (copy);
|
Nibbler n (copy);
|
||||||
|
@ -451,88 +483,141 @@ void Task::parse (const std::string& input)
|
||||||
if (remainder.length ())
|
if (remainder.length ())
|
||||||
throw std::string (STRING_RECORD_JUNK_AT_EOL);
|
throw std::string (STRING_RECORD_JUNK_AT_EOL);
|
||||||
}
|
}
|
||||||
|
else if (input[0] == '{')
|
||||||
|
parseJSON (input);
|
||||||
else
|
else
|
||||||
throw std::string (STRING_RECORD_NOT_FF4);
|
throw std::string (STRING_RECORD_NOT_FF4);
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (const std::string&)
|
catch (const std::string&)
|
||||||
{
|
{
|
||||||
legacyParse (copy);
|
parseLegacy (copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
recalc_urgency = true;
|
recalc_urgency = true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void Task::parseJSON (const std::string& line)
|
||||||
|
{
|
||||||
|
// Parse the whole thing.
|
||||||
|
json::value* root = json::parse (line);
|
||||||
|
if (root->type () == json::j_object)
|
||||||
|
{
|
||||||
|
json::object* root_obj = (json::object*)root;
|
||||||
|
|
||||||
|
// For each object element...
|
||||||
|
json_object_iter i;
|
||||||
|
for (i = root_obj->_data.begin ();
|
||||||
|
i != root_obj->_data.end ();
|
||||||
|
++i)
|
||||||
|
{
|
||||||
|
// If the attribute is a recognized column.
|
||||||
|
Column* col = context.columns[i->first];
|
||||||
|
if (col)
|
||||||
|
{
|
||||||
|
// Any specified id is ignored.
|
||||||
|
if (i->first == "id")
|
||||||
|
;
|
||||||
|
|
||||||
|
// Urgency, if present, is ignored.
|
||||||
|
else if (i->first == "urgency")
|
||||||
|
;
|
||||||
|
|
||||||
|
// Dates are converted from ISO to epoch.
|
||||||
|
else if (col->type () == "date")
|
||||||
|
{
|
||||||
|
Date d (unquoteText (i->second->dump ()));
|
||||||
|
set (i->first, d.toEpochString ());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tags are an array of JSON strings.
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Other types are simply added.
|
||||||
|
else
|
||||||
|
set (i->first, unquoteText (i->second->dump ()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// UDA orphans and annotations do not have columns.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Annotations are an array of JSON objects with 'entry' and
|
||||||
|
// 'description' values and must be converted.
|
||||||
|
if (i->first == "annotations")
|
||||||
|
{
|
||||||
|
std::map <std::string, std::string> annos;
|
||||||
|
|
||||||
|
json::array* atts = (json::array*)i->second;
|
||||||
|
json_array_iter annotations;
|
||||||
|
for (annotations = atts->_data.begin ();
|
||||||
|
annotations != atts->_data.end ();
|
||||||
|
++annotations)
|
||||||
|
{
|
||||||
|
json::object* annotation = (json::object*)*annotations;
|
||||||
|
json::string* when = (json::string*)annotation->_data["entry"];
|
||||||
|
json::string* what = (json::string*)annotation->_data["description"];
|
||||||
|
|
||||||
|
if (! when)
|
||||||
|
throw format (STRING_TASK_NO_ENTRY, line);
|
||||||
|
|
||||||
|
if (! what)
|
||||||
|
throw format (STRING_TASK_NO_DESC, line);
|
||||||
|
|
||||||
|
std::string name = "annotation_" + Date (when->_data).toEpochString ();
|
||||||
|
|
||||||
|
annos.insert (std::make_pair (name, what->_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
setAnnotations (annos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// UDA Orphan - must be preserved.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
|
std::stringstream message;
|
||||||
|
message << "Task::parseJSON found orphan '"
|
||||||
|
<< i->first
|
||||||
|
<< "' with value '"
|
||||||
|
<< i->second
|
||||||
|
<< "' --> preserved\n";
|
||||||
|
context.debug (message.str ());
|
||||||
|
#endif
|
||||||
|
set (i->first, unquoteText (i->second->dump ()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Support FF2, FF3.
|
// Support FF2, FF3.
|
||||||
// Thankfully FF1 is no longer supported.
|
// Thankfully FF1 is no longer supported.
|
||||||
void Task::legacyParse (const std::string& line)
|
void Task::parseLegacy (const std::string& line)
|
||||||
{
|
{
|
||||||
switch (determineVersion (line))
|
switch (determineVersion (line))
|
||||||
{
|
{
|
||||||
// File format version 1, from 2006.11.27 - 2007.12.31
|
// File format version 1, from 2006-11-27 - 2007-12-31, v0.x+ - v0.9.3
|
||||||
case 1:
|
case 1: throw std::string (STRING_TASK_NO_FF1);
|
||||||
throw std::string (STRING_TASK_NO_FF1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// File format version 2, from 2008.1.1 - 2009.3.23
|
// File format version 2, from 2008-1-1 - 2009-3-23, v0.9.3 - v1.5.0
|
||||||
case 2:
|
case 2: throw std::string (STRING_TASK_NO_FF2);
|
||||||
{
|
|
||||||
if (line.length () > 46) // ^.{36} . \[\] \[\] \n
|
|
||||||
{
|
|
||||||
set ("uuid", line.substr (0, 36));
|
|
||||||
|
|
||||||
Task::status status = line[37] == '+' ? completed
|
// File format version 3, from 2009-3-23 - 2009-05-16, v1.6.0 - v1.7.1
|
||||||
: line[37] == 'X' ? deleted
|
|
||||||
: line[37] == 'r' ? recurring
|
|
||||||
: pending;
|
|
||||||
|
|
||||||
set ("status", statusToText (status));
|
|
||||||
|
|
||||||
size_t openTagBracket = line.find ("[");
|
|
||||||
size_t closeTagBracket = line.find ("]", openTagBracket);
|
|
||||||
if (openTagBracket != std::string::npos &&
|
|
||||||
closeTagBracket != std::string::npos)
|
|
||||||
{
|
|
||||||
size_t openAttrBracket = line.find ("[", closeTagBracket);
|
|
||||||
size_t closeAttrBracket = line.find ("]", openAttrBracket);
|
|
||||||
if (openAttrBracket != std::string::npos &&
|
|
||||||
closeAttrBracket != std::string::npos)
|
|
||||||
{
|
|
||||||
std::string tags = line.substr (
|
|
||||||
openTagBracket + 1, closeTagBracket - openTagBracket - 1);
|
|
||||||
std::vector <std::string> tagSet;
|
|
||||||
split (tagSet, tags, ' ');
|
|
||||||
addTags (tagSet);
|
|
||||||
|
|
||||||
std::string attributes = line.substr (
|
|
||||||
openAttrBracket + 1, closeAttrBracket - openAttrBracket - 1);
|
|
||||||
std::vector <std::string> pairs;
|
|
||||||
split (pairs, attributes, ' ');
|
|
||||||
for (size_t i = 0; i < pairs.size (); ++i)
|
|
||||||
{
|
|
||||||
std::vector <std::string> pair;
|
|
||||||
split (pair, pairs[i], ':');
|
|
||||||
if (pair.size () == 2)
|
|
||||||
set (pair[0], pair[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
set ("description", line.substr (closeAttrBracket + 2));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
throw std::string (STRING_TASK_PARSE_ATT_BRACK);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
throw std::string (STRING_TASK_PARSE_TAG_BRACK);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
throw std::string (STRING_TASK_PARSE_TOO_SHORT);
|
|
||||||
|
|
||||||
removeAnnotations ();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// File format version 3, from 2009.3.23
|
|
||||||
case 3:
|
case 3:
|
||||||
{
|
{
|
||||||
if (line.length () > 49) // ^.{36} . \[\] \[\] \[\] \n
|
if (line.length () > 49) // ^.{36} . \[\] \[\] \[\] \n
|
||||||
|
@ -640,7 +725,9 @@ void Task::legacyParse (const std::string& line)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
recalc_urgency = true;
|
recalc_urgency = true;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -669,14 +756,15 @@ std::string Task::composeF4 () const
|
||||||
return ff4;
|
return ff4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
std::string Task::composeJSON (bool include_id /*= false*/) const
|
std::string Task::composeJSON (bool decorate /*= false*/) const
|
||||||
{
|
{
|
||||||
std::stringstream out;
|
std::stringstream out;
|
||||||
out << "{";
|
out << "{";
|
||||||
|
|
||||||
// ID inclusion is optional, not recommended.
|
// ID inclusion is optional, not recommended.
|
||||||
if (include_id)
|
if (decorate)
|
||||||
out << "\"id\":" << id << ",";
|
out << "\"id\":" << id << ",";
|
||||||
|
|
||||||
// First the non-annotations.
|
// First the non-annotations.
|
||||||
|
@ -765,6 +853,7 @@ std::string Task::composeJSON (bool include_id /*= false*/) const
|
||||||
}
|
}
|
||||||
|
|
||||||
// Include urgency.
|
// Include urgency.
|
||||||
|
if (decorate)
|
||||||
out << ","
|
out << ","
|
||||||
<< "\"urgency\":\""
|
<< "\"urgency\":\""
|
||||||
<< urgency_c ()
|
<< urgency_c ()
|
||||||
|
@ -780,31 +869,6 @@ bool Task::hasAnnotations () const
|
||||||
return annotation_count ? true : false;
|
return annotation_count ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
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.insert (*ci);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
void Task::setAnnotations (const std::map <std::string, std::string>& annotations)
|
|
||||||
{
|
|
||||||
// Erase old annotations.
|
|
||||||
removeAnnotations ();
|
|
||||||
|
|
||||||
std::map <std::string, std::string>::const_iterator ci;
|
|
||||||
for (ci = annotations.begin (); ci != annotations.end (); ++ci)
|
|
||||||
this->insert (*ci);
|
|
||||||
|
|
||||||
annotation_count = annotations.size ();
|
|
||||||
recalc_urgency = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// The timestamp is part of the name:
|
// The timestamp is part of the name:
|
||||||
// annotation_1234567890:"..."
|
// annotation_1234567890:"..."
|
||||||
|
@ -847,6 +911,31 @@ void Task::removeAnnotations ()
|
||||||
recalc_urgency = true;
|
recalc_urgency = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
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.insert (*ci);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void Task::setAnnotations (const std::map <std::string, std::string>& annotations)
|
||||||
|
{
|
||||||
|
// Erase old annotations.
|
||||||
|
removeAnnotations ();
|
||||||
|
|
||||||
|
std::map <std::string, std::string>::const_iterator ci;
|
||||||
|
for (ci = annotations.begin (); ci != annotations.end (); ++ci)
|
||||||
|
this->insert (*ci);
|
||||||
|
|
||||||
|
annotation_count = annotations.size ();
|
||||||
|
recalc_urgency = true;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void Task::addDependency (int id)
|
void Task::addDependency (int id)
|
||||||
{
|
{
|
||||||
|
@ -1189,6 +1278,7 @@ void Task::substitute (
|
||||||
recalc_urgency = true;
|
recalc_urgency = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// The purpose of Task::validate is three-fold:
|
// The purpose of Task::validate is three-fold:
|
||||||
|
@ -1224,6 +1314,7 @@ void Task::validate (bool applyDefault /* = true */)
|
||||||
// Store the derived status.
|
// Store the derived status.
|
||||||
setStatus (status);
|
setStatus (status);
|
||||||
|
|
||||||
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
// Provide an entry date unless user already specified one.
|
// Provide an entry date unless user already specified one.
|
||||||
if (!has ("entry"))
|
if (!has ("entry"))
|
||||||
setEntry ();
|
setEntry ();
|
||||||
|
@ -1309,6 +1400,7 @@ void Task::validate (bool applyDefault /* = true */)
|
||||||
validate_before ("scheduled", "start");
|
validate_before ("scheduled", "start");
|
||||||
validate_before ("scheduled", "due");
|
validate_before ("scheduled", "due");
|
||||||
validate_before ("scheduled", "end");
|
validate_before ("scheduled", "end");
|
||||||
|
#endif
|
||||||
|
|
||||||
// 3) To generate errors when the inconsistencies are not fixable
|
// 3) To generate errors when the inconsistencies are not fixable
|
||||||
|
|
||||||
|
@ -1341,6 +1433,8 @@ void Task::validate (bool applyDefault /* = true */)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void Task::validate_before (const std::string& left, const std::string& right)
|
void Task::validate_before (const std::string& left, const std::string& right)
|
||||||
{
|
{
|
||||||
if (has (left) &&
|
if (has (left) &&
|
||||||
|
@ -1674,5 +1768,6 @@ float Task::urgency_blocking () const
|
||||||
|
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
29
src/Task.h
29
src/Task.h
|
@ -28,13 +28,15 @@
|
||||||
#ifndef INCLUDED_TASK
|
#ifndef INCLUDED_TASK
|
||||||
#define INCLUDED_TASK
|
#define INCLUDED_TASK
|
||||||
|
|
||||||
|
#include <cmake.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
void initializeUrgencyCoefficients ();
|
void initializeUrgencyCoefficients ();
|
||||||
|
#endif
|
||||||
|
|
||||||
class Task : public std::map <std::string, std::string>
|
class Task : public std::map <std::string, std::string>
|
||||||
{
|
{
|
||||||
|
@ -48,18 +50,22 @@ public:
|
||||||
|
|
||||||
void parse (const std::string&);
|
void parse (const std::string&);
|
||||||
std::string composeF4 () const;
|
std::string composeF4 () const;
|
||||||
std::string composeJSON (bool include_id = false) const;
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
|
std::string composeJSON (bool decorate = false) const;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Status values.
|
// Status values.
|
||||||
enum status {pending, completed, deleted, recurring, waiting};
|
enum status {pending, completed, deleted, recurring, waiting};
|
||||||
|
|
||||||
// Public data.
|
// Public data.
|
||||||
int id;
|
int id;
|
||||||
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
float urgency_value;
|
float urgency_value;
|
||||||
bool recalc_urgency;
|
bool recalc_urgency;
|
||||||
|
|
||||||
bool is_blocked;
|
bool is_blocked;
|
||||||
bool is_blocking;
|
bool is_blocking;
|
||||||
|
#endif
|
||||||
|
|
||||||
int annotation_count;
|
int annotation_count;
|
||||||
|
|
||||||
|
@ -67,39 +73,50 @@ public:
|
||||||
static status textToStatus (const std::string&);
|
static status textToStatus (const std::string&);
|
||||||
static std::string statusToText (status);
|
static std::string statusToText (status);
|
||||||
|
|
||||||
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
void setEntry ();
|
void setEntry ();
|
||||||
void setEnd ();
|
void setEnd ();
|
||||||
void setStart ();
|
void setStart ();
|
||||||
|
#endif
|
||||||
void setModified ();
|
void setModified ();
|
||||||
|
|
||||||
bool has (const std::string&) const;
|
bool has (const std::string&) const;
|
||||||
std::vector <std::string> all ();
|
std::vector <std::string> all ();
|
||||||
const std::string get (const std::string&) const;
|
const std::string get (const std::string&) const;
|
||||||
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
const std::string& get_ref (const std::string&) const;
|
const std::string& get_ref (const std::string&) const;
|
||||||
int get_int (const std::string&) const;
|
int get_int (const std::string&) const;
|
||||||
unsigned long get_ulong (const std::string&) const;
|
unsigned long get_ulong (const std::string&) const;
|
||||||
|
#endif
|
||||||
time_t get_date (const std::string&) const;
|
time_t get_date (const std::string&) const;
|
||||||
void set (const std::string&, const std::string&);
|
void set (const std::string&, const std::string&);
|
||||||
void set (const std::string&, int);
|
void set (const std::string&, int);
|
||||||
void remove (const std::string&);
|
void remove (const std::string&);
|
||||||
|
|
||||||
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
bool is_due () const;
|
bool is_due () const;
|
||||||
bool is_duetoday () const;
|
bool is_duetoday () const;
|
||||||
bool is_overdue () const;
|
bool is_overdue () const;
|
||||||
|
#endif
|
||||||
|
|
||||||
status getStatus () const;
|
status getStatus () const;
|
||||||
void setStatus (status);
|
void setStatus (status);
|
||||||
|
|
||||||
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
int getTagCount () const;
|
int getTagCount () const;
|
||||||
bool hasTag (const std::string&) const;
|
bool hasTag (const std::string&) const;
|
||||||
|
#endif
|
||||||
void addTag (const std::string&);
|
void addTag (const std::string&);
|
||||||
void addTags (const std::vector <std::string>&);
|
void addTags (const std::vector <std::string>&);
|
||||||
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
void getTags (std::vector<std::string>&) const;
|
void getTags (std::vector<std::string>&) const;
|
||||||
void removeTag (const std::string&);
|
void removeTag (const std::string&);
|
||||||
|
|
||||||
bool hasAnnotations () const;
|
bool hasAnnotations () const;
|
||||||
void getAnnotations (std::map <std::string, std::string>&) const;
|
void getAnnotations (std::map <std::string, std::string>&) const;
|
||||||
|
#endif
|
||||||
void setAnnotations (const std::map <std::string, std::string>&);
|
void setAnnotations (const std::map <std::string, std::string>&);
|
||||||
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
void addAnnotation (const std::string&);
|
void addAnnotation (const std::string&);
|
||||||
void removeAnnotations ();
|
void removeAnnotations ();
|
||||||
|
|
||||||
|
@ -114,15 +131,20 @@ public:
|
||||||
void getUDAOrphans (std::vector <std::string>&) const;
|
void getUDAOrphans (std::vector <std::string>&) const;
|
||||||
|
|
||||||
void substitute (const std::string&, const std::string&, bool);
|
void substitute (const std::string&, const std::string&, bool);
|
||||||
|
#endif
|
||||||
|
|
||||||
void validate (bool applyDefault = true);
|
void validate (bool applyDefault = true);
|
||||||
|
|
||||||
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
float urgency_c () const;
|
float urgency_c () const;
|
||||||
float urgency ();
|
float urgency ();
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int determineVersion (const std::string&);
|
int determineVersion (const std::string&);
|
||||||
void legacyParse (const std::string&);
|
void parseJSON (const std::string&);
|
||||||
|
void parseLegacy (const std::string&);
|
||||||
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
void validate_before (const std::string&, const std::string&);
|
void validate_before (const std::string&, const std::string&);
|
||||||
|
|
||||||
inline float urgency_priority () const;
|
inline float urgency_priority () const;
|
||||||
|
@ -137,6 +159,7 @@ private:
|
||||||
inline float urgency_due () const;
|
inline float urgency_due () const;
|
||||||
inline float urgency_blocking () const;
|
inline float urgency_blocking () const;
|
||||||
inline float urgency_age () const;
|
inline float urgency_age () const;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -172,10 +172,10 @@ int CmdImport::execute (std::string& output)
|
||||||
json::string* what = (json::string*)annotation->_data["description"];
|
json::string* what = (json::string*)annotation->_data["description"];
|
||||||
|
|
||||||
if (! when)
|
if (! when)
|
||||||
throw format (STRING_CMD_IMPORT_NO_ENTRY, *line);
|
throw format (STRING_TASK_NO_ENTRY, *line);
|
||||||
|
|
||||||
if (! what)
|
if (! what)
|
||||||
throw format (STRING_CMD_IMPORT_NO_DESC, *line);
|
throw format (STRING_TASK_NO_DESC, *line);
|
||||||
|
|
||||||
std::string name = "annotation_" + Date (when->_data).toEpochString ();
|
std::string name = "annotation_" + Date (when->_data).toEpochString ();
|
||||||
|
|
||||||
|
|
|
@ -396,8 +396,8 @@
|
||||||
#define STRING_CMD_IMPORT_NOFILE "You must specify a file to import."
|
#define STRING_CMD_IMPORT_NOFILE "You must specify a file to import."
|
||||||
#define STRING_CMD_IMPORT_FILE "Importing '{1}'"
|
#define STRING_CMD_IMPORT_FILE "Importing '{1}'"
|
||||||
#define STRING_CMD_IMPORT_NOT_JSON "Not a JSON object: {1}"
|
#define STRING_CMD_IMPORT_NOT_JSON "Not a JSON object: {1}"
|
||||||
#define STRING_CMD_IMPORT_NO_DESC "Annotation is missing a description: {1}"
|
#define STRING_TASK_NO_DESC "Annotation is missing a description: {1}"
|
||||||
#define STRING_CMD_IMPORT_NO_ENTRY "Annotation is missing an entry date: {1}"
|
#define STRING_TASK_NO_ENTRY "Annotation is missing an entry date: {1}"
|
||||||
#define STRING_CMD_SHELL_HELP1 "Enter any task command (such as 'list'), or hit 'Enter'."
|
#define STRING_CMD_SHELL_HELP1 "Enter any task command (such as 'list'), or hit 'Enter'."
|
||||||
#define STRING_CMD_SHELL_HELP2 "There is no need to include the 'task' command itself."
|
#define STRING_CMD_SHELL_HELP2 "There is no need to include the 'task' command itself."
|
||||||
#define STRING_CMD_SHELL_HELP3 "Enter 'quit' (or 'bye', 'exit') to end the session."
|
#define STRING_CMD_SHELL_HELP3 "Enter 'quit' (or 'bye', 'exit') to end the session."
|
||||||
|
@ -779,6 +779,7 @@
|
||||||
|
|
||||||
// Task
|
// Task
|
||||||
#define STRING_TASK_NO_FF1 "Taskwarrior no longer supports file format 1, originally used between 27 November 2006 and 31 December 2007."
|
#define STRING_TASK_NO_FF1 "Taskwarrior no longer supports file format 1, originally used between 27 November 2006 and 31 December 2007."
|
||||||
|
#define STRING_TASK_NO_FF2 "Taskwarrior no longer supports file format 2, originally used between 1 January 2008 and 12 April 2009."
|
||||||
#define STRING_TASK_PARSE_ANNO_BRACK "Missing annotation brackets."
|
#define STRING_TASK_PARSE_ANNO_BRACK "Missing annotation brackets."
|
||||||
#define STRING_TASK_PARSE_ATT_BRACK "Missing attribute brackets."
|
#define STRING_TASK_PARSE_ATT_BRACK "Missing attribute brackets."
|
||||||
#define STRING_TASK_PARSE_TAG_BRACK "Missing tag brackets."
|
#define STRING_TASK_PARSE_TAG_BRACK "Missing tag brackets."
|
||||||
|
|
|
@ -406,8 +406,8 @@
|
||||||
#define STRING_CMD_IMPORT_NOFILE "Debe especificar un archivo a importar."
|
#define STRING_CMD_IMPORT_NOFILE "Debe especificar un archivo a importar."
|
||||||
#define STRING_CMD_IMPORT_FILE "Importando '{1}'"
|
#define STRING_CMD_IMPORT_FILE "Importando '{1}'"
|
||||||
#define STRING_CMD_IMPORT_NOT_JSON "No es un objeto JSON: {1}"
|
#define STRING_CMD_IMPORT_NOT_JSON "No es un objeto JSON: {1}"
|
||||||
#define STRING_CMD_IMPORT_NO_DESC "La anotación carece de descripción: {1}"
|
#define STRING_TASK_NO_DESC "La anotación carece de descripción: {1}"
|
||||||
#define STRING_CMD_IMPORT_NO_ENTRY "La anotación carece de fecha de entrada: {1}"
|
#define STRING_TASK_NO_ENTRY "La anotación carece de fecha de entrada: {1}"
|
||||||
#define STRING_CMD_SHELL_HELP1 "Escriba un comando de task (como 'list'), o pulse 'Enter'."
|
#define STRING_CMD_SHELL_HELP1 "Escriba un comando de task (como 'list'), o pulse 'Enter'."
|
||||||
#define STRING_CMD_SHELL_HELP2 "No hace falta incluir el propio comando 'task'."
|
#define STRING_CMD_SHELL_HELP2 "No hace falta incluir el propio comando 'task'."
|
||||||
#define STRING_CMD_SHELL_HELP3 "Escriba 'quit' (o 'bye', 'exit') para terminar la sesión."
|
#define STRING_CMD_SHELL_HELP3 "Escriba 'quit' (o 'bye', 'exit') para terminar la sesión."
|
||||||
|
@ -794,6 +794,7 @@
|
||||||
|
|
||||||
// Task
|
// Task
|
||||||
#define STRING_TASK_NO_FF1 "Taskwarrior ya no admite el formato de archivo 1, usado originalmente entre el 27 de noviembre del 2006 y el 31 de diciembre del 2007."
|
#define STRING_TASK_NO_FF1 "Taskwarrior ya no admite el formato de archivo 1, usado originalmente entre el 27 de noviembre del 2006 y el 31 de diciembre del 2007."
|
||||||
|
#define STRING_TASK_NO_FF2 "Taskwarrior no longer supports file format 2, originally used between 1 January 2008 and 12 April 2009."
|
||||||
#define STRING_TASK_PARSE_ANNO_BRACK "Faltan corchetes de anotación."
|
#define STRING_TASK_PARSE_ANNO_BRACK "Faltan corchetes de anotación."
|
||||||
#define STRING_TASK_PARSE_ATT_BRACK "Faltan corchetes de atributo."
|
#define STRING_TASK_PARSE_ATT_BRACK "Faltan corchetes de atributo."
|
||||||
#define STRING_TASK_PARSE_TAG_BRACK "Faltan corchetes de marca."
|
#define STRING_TASK_PARSE_TAG_BRACK "Faltan corchetes de marca."
|
||||||
|
|
|
@ -396,8 +396,8 @@
|
||||||
#define STRING_CMD_IMPORT_NOFILE "You must specify a file to import."
|
#define STRING_CMD_IMPORT_NOFILE "You must specify a file to import."
|
||||||
#define STRING_CMD_IMPORT_FILE "Importing '{1}'"
|
#define STRING_CMD_IMPORT_FILE "Importing '{1}'"
|
||||||
#define STRING_CMD_IMPORT_NOT_JSON "Not a JSON object: {1}"
|
#define STRING_CMD_IMPORT_NOT_JSON "Not a JSON object: {1}"
|
||||||
#define STRING_CMD_IMPORT_NO_DESC "Annotation is missing a description: {1}"
|
#define STRING_TASK_NO_DESC "Annotation is missing a description: {1}"
|
||||||
#define STRING_CMD_IMPORT_NO_ENTRY "Annotation is missing an entry date: {1}"
|
#define STRING_TASK_NO_ENTRY "Annotation is missing an entry date: {1}"
|
||||||
#define STRING_CMD_SHELL_HELP1 "Enter any task command (such as 'list'), or hit 'Enter'."
|
#define STRING_CMD_SHELL_HELP1 "Enter any task command (such as 'list'), or hit 'Enter'."
|
||||||
#define STRING_CMD_SHELL_HELP2 "There is no need to include the 'task' command itself."
|
#define STRING_CMD_SHELL_HELP2 "There is no need to include the 'task' command itself."
|
||||||
#define STRING_CMD_SHELL_HELP3 "Enter 'quit' (or 'bye', 'exit') to end the session."
|
#define STRING_CMD_SHELL_HELP3 "Enter 'quit' (or 'bye', 'exit') to end the session."
|
||||||
|
@ -779,6 +779,7 @@
|
||||||
|
|
||||||
// Task
|
// Task
|
||||||
#define STRING_TASK_NO_FF1 "Taskwarrior no longer supports file format 1, originally used between 27 November 2006 and 31 December 2007."
|
#define STRING_TASK_NO_FF1 "Taskwarrior no longer supports file format 1, originally used between 27 November 2006 and 31 December 2007."
|
||||||
|
#define STRING_TASK_NO_FF2 "Taskwarrior no longer supports file format 2, originally used between 1 January 2008 and 12 April 2009."
|
||||||
#define STRING_TASK_PARSE_ANNO_BRACK "Missing annotation brackets."
|
#define STRING_TASK_PARSE_ANNO_BRACK "Missing annotation brackets."
|
||||||
#define STRING_TASK_PARSE_ATT_BRACK "Missing attribute brackets."
|
#define STRING_TASK_PARSE_ATT_BRACK "Missing attribute brackets."
|
||||||
#define STRING_TASK_PARSE_TAG_BRACK "Missing tag brackets."
|
#define STRING_TASK_PARSE_TAG_BRACK "Missing tag brackets."
|
||||||
|
|
|
@ -397,8 +397,8 @@
|
||||||
#define STRING_CMD_IMPORT_NOFILE "Specificare il file da importare."
|
#define STRING_CMD_IMPORT_NOFILE "Specificare il file da importare."
|
||||||
#define STRING_CMD_IMPORT_FILE "Importazione di '{1}'"
|
#define STRING_CMD_IMPORT_FILE "Importazione di '{1}'"
|
||||||
#define STRING_CMD_IMPORT_NOT_JSON "Non è un oggetto JSON: {1}"
|
#define STRING_CMD_IMPORT_NOT_JSON "Non è un oggetto JSON: {1}"
|
||||||
#define STRING_CMD_IMPORT_NO_DESC "Annotazione senza descrizione: {1}"
|
#define STRING_TASK_NO_DESC "Annotazione senza descrizione: {1}"
|
||||||
#define STRING_CMD_IMPORT_NO_ENTRY "Annotazione senza data di immissione: {1}"
|
#define STRING_TASK_NO_ENTRY "Annotazione senza data di immissione: {1}"
|
||||||
#define STRING_CMD_SHELL_HELP1 "Inserisci un comando (es. 'list'), o premi 'Enter'."
|
#define STRING_CMD_SHELL_HELP1 "Inserisci un comando (es. 'list'), o premi 'Enter'."
|
||||||
#define STRING_CMD_SHELL_HELP2 "Non è necessario includere il comando 'task'."
|
#define STRING_CMD_SHELL_HELP2 "Non è necessario includere il comando 'task'."
|
||||||
#define STRING_CMD_SHELL_HELP3 "Inserisci 'quit' (o 'bye', 'exit') per terminare la sessione."
|
#define STRING_CMD_SHELL_HELP3 "Inserisci 'quit' (o 'bye', 'exit') per terminare la sessione."
|
||||||
|
@ -780,6 +780,7 @@
|
||||||
|
|
||||||
// Task
|
// Task
|
||||||
#define STRING_TASK_NO_FF1 "Taskwarrior non supporta più il formato di file 1, usato tra il 27 Novembre 2006 e il 31 Dicembre 2007."
|
#define STRING_TASK_NO_FF1 "Taskwarrior non supporta più il formato di file 1, usato tra il 27 Novembre 2006 e il 31 Dicembre 2007."
|
||||||
|
#define STRING_TASK_NO_FF2 "Taskwarrior no longer supports file format 2, originally used between 1 January 2008 and 12 April 2009."
|
||||||
#define STRING_TASK_PARSE_ANNO_BRACK "Parentesi di annotazione mancanti."
|
#define STRING_TASK_PARSE_ANNO_BRACK "Parentesi di annotazione mancanti."
|
||||||
#define STRING_TASK_PARSE_ATT_BRACK "Parentesi di attributo mancanti."
|
#define STRING_TASK_PARSE_ATT_BRACK "Parentesi di attributo mancanti."
|
||||||
#define STRING_TASK_PARSE_TAG_BRACK "Parentesi di tag mancanti."
|
#define STRING_TASK_PARSE_TAG_BRACK "Parentesi di tag mancanti."
|
||||||
|
|
47
test/t.t.cpp
47
test/t.t.cpp
|
@ -33,7 +33,7 @@ Context context;
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
int main (int argc, char** argv)
|
int main (int argc, char** argv)
|
||||||
{
|
{
|
||||||
UnitTest test (37);
|
UnitTest test (30);
|
||||||
|
|
||||||
test.is ((int)Task::textToStatus ("pending"), (int)Task::pending, "textToStatus pending");
|
test.is ((int)Task::textToStatus ("pending"), (int)Task::pending, "textToStatus pending");
|
||||||
test.is ((int)Task::textToStatus ("completed"), (int)Task::completed, "textToStatus completed");
|
test.is ((int)Task::textToStatus ("completed"), (int)Task::completed, "textToStatus completed");
|
||||||
|
@ -57,7 +57,7 @@ int main (int argc, char** argv)
|
||||||
after = t3.composeF4 ();
|
after = t3.composeF4 ();
|
||||||
test.is (before, after, "Task::composeF4 -> parse round trip 4 iterations");
|
test.is (before, after, "Task::composeF4 -> parse round trip 4 iterations");
|
||||||
|
|
||||||
// Legacy Format 1
|
// Legacy Format 1 (no longer supported)
|
||||||
// [tags] [attributes] description\n
|
// [tags] [attributes] description\n
|
||||||
// X [tags] [attributes] description\n
|
// X [tags] [attributes] description\n
|
||||||
std::string sample = "[tag1 tag2] [att1:value1 att2:value2] Description";
|
std::string sample = "[tag1 tag2] [att1:value1 att2:value2] Description";
|
||||||
|
@ -69,27 +69,16 @@ int main (int argc, char** argv)
|
||||||
try { Task ff1 (sample); } catch (...) { good = false; }
|
try { Task ff1 (sample); } catch (...) { good = false; }
|
||||||
test.notok (good, "Support for ff1 removed");
|
test.notok (good, "Support for ff1 removed");
|
||||||
|
|
||||||
// Legacy Format 2
|
// Legacy Format 2 (no longer supported)
|
||||||
// uuid status [tags] [attributes] description\n
|
// uuid status [tags] [attributes] description\n
|
||||||
sample = "00000000-0000-0000-0000-000000000000 "
|
sample = "00000000-0000-0000-0000-000000000000 "
|
||||||
"- "
|
"- "
|
||||||
"[tag1 tag2] "
|
"[tag1 tag2] "
|
||||||
"[att1:value1 att2:value2] "
|
"[att1:value1 att2:value2] "
|
||||||
"Description";
|
"Description";
|
||||||
Task ff2 (sample);
|
good = true;
|
||||||
std::string value = ff2.get ("uuid");
|
try { Task ff2 (sample); } catch (...) { good = false; }
|
||||||
test.is (value, "00000000-0000-0000-0000-000000000000", "ff2 uuid");
|
test.notok (good, "Support for ff2 removed");
|
||||||
value = ff2.get ("status");
|
|
||||||
test.is (value, "pending", "ff2 status");
|
|
||||||
test.ok (ff2.hasTag ("tag1"), "ff2 tag1");
|
|
||||||
test.ok (ff2.hasTag ("tag2"), "ff2 tag2");
|
|
||||||
test.is (ff2.getTagCount (), 2, "ff2 # tags");
|
|
||||||
value = ff2.get ("att1");
|
|
||||||
test.is (value, "value1", "ff2 att1");
|
|
||||||
value = ff2.get ("att2");
|
|
||||||
test.is (value, "value2", "ff2 att2");
|
|
||||||
value = ff2.get ("description");
|
|
||||||
test.is (value, "Description", "ff2 description");
|
|
||||||
|
|
||||||
// Legacy Format 3
|
// Legacy Format 3
|
||||||
// uuid status [tags] [attributes] [annotations] description\n
|
// uuid status [tags] [attributes] [annotations] description\n
|
||||||
|
@ -99,13 +88,13 @@ int main (int argc, char** argv)
|
||||||
"[att1:value1 att2:value2] "
|
"[att1:value1 att2:value2] "
|
||||||
"[123:ann1 456:ann2] Description";
|
"[123:ann1 456:ann2] Description";
|
||||||
Task ff3 (sample);
|
Task ff3 (sample);
|
||||||
value = ff2.get ("uuid");
|
std::string value = ff3.get ("uuid");
|
||||||
test.is (value, "00000000-0000-0000-0000-000000000000", "ff3 uuid");
|
test.is (value, "00000000-0000-0000-0000-000000000000", "ff3 uuid");
|
||||||
value = ff2.get ("status");
|
value = ff3.get ("status");
|
||||||
test.is (value, "pending", "ff3 status");
|
test.is (value, "pending", "ff3 status");
|
||||||
test.ok (ff2.hasTag ("tag1"), "ff3 tag1");
|
test.ok (ff3.hasTag ("tag1"), "ff3 tag1");
|
||||||
test.ok (ff2.hasTag ("tag2"), "ff3 tag2");
|
test.ok (ff3.hasTag ("tag2"), "ff3 tag2");
|
||||||
test.is (ff2.getTagCount (), 2, "ff3 # tags");
|
test.is (ff3.getTagCount (), 2, "ff3 # tags");
|
||||||
value = ff3.get ("att1");
|
value = ff3.get ("att1");
|
||||||
test.is (value, "value1", "ff3 att1");
|
test.is (value, "value1", "ff3 att1");
|
||||||
value = ff3.get ("att2");
|
value = ff3.get ("att2");
|
||||||
|
@ -117,20 +106,20 @@ int main (int argc, char** argv)
|
||||||
// [name:"value" ...]\n
|
// [name:"value" ...]\n
|
||||||
sample = "["
|
sample = "["
|
||||||
"uuid:\"00000000-0000-0000-0000-000000000000\" "
|
"uuid:\"00000000-0000-0000-0000-000000000000\" "
|
||||||
"status:\"P\" "
|
"status:\"pending\" "
|
||||||
"tags:\"tag1&commaltag2\" "
|
"tags:\"tag1,tag2\" "
|
||||||
"att1:\"value1\" "
|
"att1:\"value1\" "
|
||||||
"att2:\"value2\" "
|
"att2:\"value2\" "
|
||||||
"description:\"Description\""
|
"description:\"Description\""
|
||||||
"]";
|
"]";
|
||||||
Task ff4 (sample);
|
Task ff4 (sample);
|
||||||
value = ff2.get ("uuid");
|
value = ff4.get ("uuid");
|
||||||
test.is (value, "00000000-0000-0000-0000-000000000000", "ff4 uuid");
|
test.is (value, "00000000-0000-0000-0000-000000000000", "ff4 uuid");
|
||||||
value = ff2.get ("status");
|
value = ff4.get ("status");
|
||||||
test.is (value, "pending", "ff4 status");
|
test.is (value, "pending", "ff4 status");
|
||||||
test.ok (ff2.hasTag ("tag1"), "ff4 tag1");
|
test.ok (ff4.hasTag ("tag1"), "ff4 tag1");
|
||||||
test.ok (ff2.hasTag ("tag2"), "ff4 tag2");
|
test.ok (ff4.hasTag ("tag2"), "ff4 tag2");
|
||||||
test.is (ff2.getTagCount (), 2, "ff4 # tags");
|
test.is (ff4.getTagCount (), 2, "ff4 # tags");
|
||||||
value = ff4.get ("att1");
|
value = ff4.get ("att1");
|
||||||
test.is (value, "value1", "ff4 att1");
|
test.is (value, "value1", "ff4 att1");
|
||||||
value = ff4.get ("att2");
|
value = ff4.get ("att2");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue