mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-06-26 10:54:26 +02:00
FF4/JSON Interop
- Removed the \n characters from Task::composeFF4 and Task::ComposeJSON. - Tasks in backlog.data file are now written as JSON. - Tasks are recognized in FF4 or JSON format.
This commit is contained in:
parent
29e9dbcea6
commit
4133d29cca
5 changed files with 59 additions and 59 deletions
24
src/TDB2.cpp
24
src/TDB2.cpp
|
@ -223,7 +223,7 @@ void TF2::commit ()
|
||||||
task != _added_tasks.end ();
|
task != _added_tasks.end ();
|
||||||
++task)
|
++task)
|
||||||
{
|
{
|
||||||
_file.append (task->composeF4 ());
|
_file.append (task->composeF4 () + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
_added_tasks.clear ();
|
_added_tasks.clear ();
|
||||||
|
@ -255,7 +255,7 @@ void TF2::commit ()
|
||||||
task != _tasks.end ();
|
task != _tasks.end ();
|
||||||
++task)
|
++task)
|
||||||
{
|
{
|
||||||
_file.append (task->composeF4 ());
|
_file.append (task->composeF4 () + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write out all the added lines.
|
// Write out all the added lines.
|
||||||
|
@ -565,12 +565,12 @@ void TDB2::add (Task& task, bool add_to_backlog /* = true */)
|
||||||
// new <task>
|
// new <task>
|
||||||
// ---
|
// ---
|
||||||
undo.add_line ("time " + Date ().toEpochString () + "\n");
|
undo.add_line ("time " + Date ().toEpochString () + "\n");
|
||||||
undo.add_line ("new " + task.composeF4 ());
|
undo.add_line ("new " + task.composeF4 () + "\n");
|
||||||
undo.add_line ("---\n");
|
undo.add_line ("---\n");
|
||||||
|
|
||||||
// Add task to backlog.
|
// Add task to backlog.
|
||||||
if (add_to_backlog)
|
if (add_to_backlog)
|
||||||
backlog.add_task (task);
|
backlog.add_line (task.composeJSON () + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -597,13 +597,13 @@ void TDB2::modify (Task& task, bool add_to_backlog /* = true */)
|
||||||
// new <task>
|
// new <task>
|
||||||
// ---
|
// ---
|
||||||
undo.add_line ("time " + Date ().toEpochString () + "\n");
|
undo.add_line ("time " + Date ().toEpochString () + "\n");
|
||||||
undo.add_line ("old " + original.composeF4 ());
|
undo.add_line ("old " + original.composeF4 () + "\n");
|
||||||
undo.add_line ("new " + task.composeF4 ());
|
undo.add_line ("new " + task.composeF4 () + "\n");
|
||||||
undo.add_line ("---\n");
|
undo.add_line ("---\n");
|
||||||
|
|
||||||
// Add modified task to backlog.
|
// Add modified task to backlog.
|
||||||
if (add_to_backlog)
|
if (add_to_backlog)
|
||||||
backlog.add_task (task);
|
backlog.add_line (task.composeJSON () + "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1112,9 +1112,7 @@ void TDB2::merge (const std::string& mergeFile)
|
||||||
<< "\n";
|
<< "\n";
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// remove the \n from composeF4() string
|
|
||||||
std::string newline = tmod.getAfter ().composeF4 ();
|
std::string newline = tmod.getAfter ().composeF4 ();
|
||||||
newline = newline.substr (0, newline.length ()-1);
|
|
||||||
|
|
||||||
// does the tasks move to pending data?
|
// does the tasks move to pending data?
|
||||||
// this taskmod will not arise from
|
// this taskmod will not arise from
|
||||||
|
@ -1154,10 +1152,7 @@ void TDB2::merge (const std::string& mergeFile)
|
||||||
cutOff (tmod.getBefore ().get ("description"), 10))
|
cutOff (tmod.getBefore ().get ("description"), 10))
|
||||||
<< "\n";
|
<< "\n";
|
||||||
|
|
||||||
// remove the \n from composeF4() string
|
|
||||||
// which will replace the current line
|
|
||||||
std::string newline = tmod.getAfter ().composeF4 ();
|
std::string newline = tmod.getAfter ().composeF4 ();
|
||||||
newline = newline.substr (0, newline.length ()-1);
|
|
||||||
|
|
||||||
// does the tasks move to completed data
|
// does the tasks move to completed data
|
||||||
if ( (statusAfter == Task::completed)
|
if ( (statusAfter == Task::completed)
|
||||||
|
@ -1215,10 +1210,7 @@ void TDB2::merge (const std::string& mergeFile)
|
||||||
cutOff (tmod.getAfter ().get ("description"), 10))
|
cutOff (tmod.getAfter ().get ("description"), 10))
|
||||||
<< "\n";
|
<< "\n";
|
||||||
|
|
||||||
// remove the \n from composeF4() string
|
pending_lines.push_back (tmod.getAfter ().composeF4 ());
|
||||||
std::string newline = tmod.getAfter ().composeF4 ();
|
|
||||||
newline = newline.substr (0, newline.length ()-1);
|
|
||||||
pending_lines.push_back (newline);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
76
src/Task.cpp
76
src/Task.cpp
|
@ -399,49 +399,53 @@ void Task::parse (const std::string& input)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// File format version 4, from 2009-5-16 - now, v1.7.1+
|
// File format version 4, from 2009-5-16 - now, v1.7.1+
|
||||||
|
// This is the parse format tried first, because it is most used.
|
||||||
clear ();
|
clear ();
|
||||||
|
|
||||||
Nibbler n (copy);
|
if (copy[0] == '[')
|
||||||
std::string line;
|
|
||||||
if (n.skip ('[') &&
|
|
||||||
n.getUntil (']', line) &&
|
|
||||||
n.skip (']') &&
|
|
||||||
n.depleted ())
|
|
||||||
{
|
{
|
||||||
if (line.length () == 0)
|
Nibbler n (copy);
|
||||||
throw std::string (STRING_RECORD_EMPTY);
|
std::string line;
|
||||||
|
if (n.skip ('[') &&
|
||||||
Nibbler nl (line);
|
n.getUntil (']', line) &&
|
||||||
std::string name;
|
n.skip (']') &&
|
||||||
std::string value;
|
n.depleted ())
|
||||||
while (!nl.depleted ())
|
|
||||||
{
|
{
|
||||||
if (nl.getUntil (':', name) &&
|
if (line.length () == 0)
|
||||||
nl.skip (':') &&
|
throw std::string (STRING_RECORD_EMPTY);
|
||||||
nl.getQuoted ('"', value))
|
|
||||||
|
Nibbler nl (line);
|
||||||
|
std::string name;
|
||||||
|
std::string value;
|
||||||
|
while (!nl.depleted ())
|
||||||
{
|
{
|
||||||
// Experimental legacy value translation of 'recur:m' --> 'recur:mo'.
|
if (nl.getUntil (':', name) &&
|
||||||
if (name == "recur" &&
|
nl.skip (':') &&
|
||||||
digitsOnly (value.substr (0, value.length () - 1)) &&
|
nl.getQuoted ('"', value))
|
||||||
value[value.length () - 1] == 'm')
|
{
|
||||||
value += 'o';
|
// Experimental legacy value translation of 'recur:m' --> 'recur:mo'.
|
||||||
|
if (name == "recur" &&
|
||||||
|
digitsOnly (value.substr (0, value.length () - 1)) &&
|
||||||
|
value[value.length () - 1] == 'm')
|
||||||
|
value += 'o';
|
||||||
|
|
||||||
if (name.substr (0, 11) == "annotation_")
|
if (name.substr (0, 11) == "annotation_")
|
||||||
++annotation_count;
|
++annotation_count;
|
||||||
|
|
||||||
(*this)[name] = decode (json::decode (value));
|
(*this)[name] = decode (json::decode (value));
|
||||||
|
}
|
||||||
|
|
||||||
|
nl.skip (' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
nl.skip (' ');
|
std::string remainder;
|
||||||
|
nl.getUntilEOS (remainder);
|
||||||
|
if (remainder.length ())
|
||||||
|
throw std::string (STRING_RECORD_JUNK_AT_EOL);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string remainder;
|
|
||||||
nl.getUntilEOS (remainder);
|
|
||||||
if (remainder.length ())
|
|
||||||
throw std::string (STRING_RECORD_JUNK_AT_EOL);
|
|
||||||
}
|
}
|
||||||
else if (input[0] == '{')
|
else if (copy[0] == '{')
|
||||||
parseJSON (input);
|
parseJSON (copy);
|
||||||
else
|
else
|
||||||
throw std::string (STRING_RECORD_NOT_FF4);
|
throw std::string (STRING_RECORD_NOT_FF4);
|
||||||
}
|
}
|
||||||
|
@ -686,7 +690,7 @@ void Task::parseLegacy (const std::string& line)
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// The format is:
|
// The format is:
|
||||||
//
|
//
|
||||||
// [ <name>:<value> ... ] \n
|
// [ <name>:<value> ... ]
|
||||||
//
|
//
|
||||||
std::string Task::composeF4 () const
|
std::string Task::composeF4 () const
|
||||||
{
|
{
|
||||||
|
@ -705,7 +709,7 @@ std::string Task::composeF4 () const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ff4 += "]\n";
|
ff4 += "]";
|
||||||
return ff4;
|
return ff4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -728,6 +732,10 @@ std::string Task::composeJSON (bool decorate /*= false*/) const
|
||||||
if (attributes_written)
|
if (attributes_written)
|
||||||
out << ",";
|
out << ",";
|
||||||
|
|
||||||
|
// Annotations are not written out here.
|
||||||
|
if (i->first.substr (0, 11) == "annotation_")
|
||||||
|
continue;
|
||||||
|
|
||||||
std::string type = Task::attributes[i->first];
|
std::string type = Task::attributes[i->first];
|
||||||
if (type == "")
|
if (type == "")
|
||||||
type = "string";
|
type = "string";
|
||||||
|
|
|
@ -182,10 +182,10 @@ std::string Taskmod::toString ()
|
||||||
|
|
||||||
if (_bBeforeSet)
|
if (_bBeforeSet)
|
||||||
{
|
{
|
||||||
stream << STRING_TASKMOD_OLD << _before.composeF4();
|
stream << STRING_TASKMOD_OLD << _before.composeF4() << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
stream << STRING_TASKMOD_NEW << _after.composeF4();
|
stream << STRING_TASKMOD_NEW << _after.composeF4() << "\n";
|
||||||
stream << "---\n";
|
stream << "---\n";
|
||||||
|
|
||||||
return stream.str ();
|
return stream.str ();
|
||||||
|
|
|
@ -77,7 +77,7 @@ int main (int argc, char** argv)
|
||||||
// Task::set
|
// Task::set
|
||||||
task.clear ();
|
task.clear ();
|
||||||
task.set ("name", "value");
|
task.set ("name", "value");
|
||||||
t.is (task.composeF4 (), "[name:\"value\"]\n", "Task::set");
|
t.is (task.composeF4 (), "[name:\"value\"]", "Task::set");
|
||||||
|
|
||||||
// Task::has
|
// Task::has
|
||||||
t.ok (task.has ("name"), "Task::has");
|
t.ok (task.has ("name"), "Task::has");
|
||||||
|
@ -85,18 +85,18 @@ int main (int argc, char** argv)
|
||||||
|
|
||||||
// Task::get_int
|
// Task::get_int
|
||||||
task.set ("one", 1);
|
task.set ("one", 1);
|
||||||
t.is (task.composeF4 (), "[name:\"value\" one:\"1\"]\n", "Task::set");
|
t.is (task.composeF4 (), "[name:\"value\" one:\"1\"]", "Task::set");
|
||||||
t.is (task.get_int ("one"), 1, "Task::get_int");
|
t.is (task.get_int ("one"), 1, "Task::get_int");
|
||||||
|
|
||||||
// Task::get_ulong
|
// Task::get_ulong
|
||||||
task.set ("two", "4294967295");
|
task.set ("two", "4294967295");
|
||||||
t.is (task.composeF4 (), "[name:\"value\" one:\"1\" two:\"4294967295\"]\n", "Task::set");
|
t.is (task.composeF4 (), "[name:\"value\" one:\"1\" two:\"4294967295\"]", "Task::set");
|
||||||
t.is ((size_t)task.get_ulong ("two"), (size_t)4294967295UL, "Task::get_ulong");
|
t.is ((size_t)task.get_ulong ("two"), (size_t)4294967295UL, "Task::get_ulong");
|
||||||
|
|
||||||
// Task::remove
|
// Task::remove
|
||||||
task.remove ("one");
|
task.remove ("one");
|
||||||
task.remove ("two");
|
task.remove ("two");
|
||||||
t.is (task.composeF4 (), "[name:\"value\"]\n", "Task::remove");
|
t.is (task.composeF4 (), "[name:\"value\"]", "Task::remove");
|
||||||
|
|
||||||
// Task::all
|
// Task::all
|
||||||
t.is (task.size (), (size_t)1, "Task::all size");
|
t.is (task.size (), (size_t)1, "Task::all size");
|
||||||
|
|
|
@ -57,7 +57,7 @@ int main (int argc, char** argv)
|
||||||
std::vector <Task> pending = context.tdb2.pending.get_tasks ();
|
std::vector <Task> pending = context.tdb2.pending.get_tasks ();
|
||||||
std::vector <Task> completed = context.tdb2.completed.get_tasks ();
|
std::vector <Task> completed = context.tdb2.completed.get_tasks ();
|
||||||
std::vector <std::string> undo = context.tdb2.undo.get_lines ();
|
std::vector <std::string> undo = context.tdb2.undo.get_lines ();
|
||||||
std::vector <Task> backlog = context.tdb2.backlog.get_tasks ();
|
std::vector <std::string> backlog = context.tdb2.backlog.get_lines ();
|
||||||
|
|
||||||
t.is ((int) pending.size (), 0, "TDB2 Read empty pending");
|
t.is ((int) pending.size (), 0, "TDB2 Read empty pending");
|
||||||
t.is ((int) completed.size (), 0, "TDB2 Read empty completed");
|
t.is ((int) completed.size (), 0, "TDB2 Read empty completed");
|
||||||
|
@ -71,7 +71,7 @@ int main (int argc, char** argv)
|
||||||
pending = context.tdb2.pending.get_tasks ();
|
pending = context.tdb2.pending.get_tasks ();
|
||||||
completed = context.tdb2.completed.get_tasks ();
|
completed = context.tdb2.completed.get_tasks ();
|
||||||
undo = context.tdb2.undo.get_lines ();
|
undo = context.tdb2.undo.get_lines ();
|
||||||
backlog = context.tdb2.backlog.get_tasks ();
|
backlog = context.tdb2.backlog.get_lines ();
|
||||||
|
|
||||||
t.is ((int) pending.size (), 1, "TDB2 after add, 1 pending task");
|
t.is ((int) pending.size (), 1, "TDB2 after add, 1 pending task");
|
||||||
t.is ((int) completed.size (), 0, "TDB2 after add, 0 completed tasks");
|
t.is ((int) completed.size (), 0, "TDB2 after add, 0 completed tasks");
|
||||||
|
@ -84,7 +84,7 @@ int main (int argc, char** argv)
|
||||||
pending = context.tdb2.pending.get_tasks ();
|
pending = context.tdb2.pending.get_tasks ();
|
||||||
completed = context.tdb2.completed.get_tasks ();
|
completed = context.tdb2.completed.get_tasks ();
|
||||||
undo = context.tdb2.undo.get_lines ();
|
undo = context.tdb2.undo.get_lines ();
|
||||||
backlog = context.tdb2.backlog.get_tasks ();
|
backlog = context.tdb2.backlog.get_lines ();
|
||||||
|
|
||||||
t.is ((int) pending.size (), 1, "TDB2 after add, 1 pending task");
|
t.is ((int) pending.size (), 1, "TDB2 after add, 1 pending task");
|
||||||
t.is ((int) completed.size (), 0, "TDB2 after add, 0 completed tasks");
|
t.is ((int) completed.size (), 0, "TDB2 after add, 0 completed tasks");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue