diff --git a/ChangeLog b/ChangeLog index d5d5a90d9..0e5414388 100644 --- a/ChangeLog +++ b/ChangeLog @@ -24,6 +24,8 @@ + Added feature #574, default due dates (thanks to Erlan Sergaziev). + Added feature #575, including Danish holidays (thanks to Irfan Siddiqui). + Eliminated dependency on ncurses. + + Added _query helper command for script writers, which accepts a filter like + any other report, but returns only full JSON. + Fixed bug #515, which displayed an incorrect message after duplicating a non-existent task (thanks to Peter De Poorter). + Fixed bug #529, where the 'depends' attribute was not mentioned in the diff --git a/NEWS b/NEWS index 576763890..010703679 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,8 @@ New Features in taskwarrior 1.9.4 - The first month in the calendar report can now be changed with an offset value. - No more dependency on ncurses. + - New '_query helper command for script writers, which accepts a filter like + any other report, but returns unformatted JSON. - Assorted bug fixes. Please refer to the ChangeLog file for full details. There are too many to diff --git a/src/Cmd.cpp b/src/Cmd.cpp index fb2774bcf..0bcd0800d 100644 --- a/src/Cmd.cpp +++ b/src/Cmd.cpp @@ -135,6 +135,7 @@ void Cmd::load () commands.push_back ("_config"); commands.push_back ("_version"); commands.push_back ("_urgency"); + commands.push_back ("_query"); commands.push_back ("export.csv"); commands.push_back ("export.ical"); commands.push_back ("export.yaml"); @@ -241,6 +242,7 @@ bool Cmd::isReadOnlyCommand () command == "_config" || command == "_version" || command == "_urgency" || + command == "_query" || command == "export.csv" || command == "export.ical" || command == "export.yaml" || diff --git a/src/Context.cpp b/src/Context.cpp index e22f3d1fe..427f55697 100644 --- a/src/Context.cpp +++ b/src/Context.cpp @@ -259,6 +259,7 @@ int Context::dispatch (std::string &out) else if (cmd.command == "_config") { rc = handleCompletionConfig (out); } else if (cmd.command == "_version") { rc = handleCompletionVersion (out); } else if (cmd.command == "_urgency") { rc = handleUrgency (out); } + else if (cmd.command == "_query") { rc = handleQuery (out); } else if (cmd.command == "" && sequence.size ()) { rc = handleModify (out); } diff --git a/src/Task.cpp b/src/Task.cpp index 6b4e787fe..432db9d99 100644 --- a/src/Task.cpp +++ b/src/Task.cpp @@ -423,6 +423,29 @@ std::string Task::composeYAML () const return out.str (); } +//////////////////////////////////////////////////////////////////////////////// +std::string Task::composeJSON () const +{ + std::stringstream out; + out << "{"; + + std::map ::const_iterator i; + for (i = this->begin (); i != this->end (); ++i) + { + if (i != this->begin ()) + out << ","; + + out << "\"" + << i->second.name () + << "\":\"" + << i->second.value () + << "\""; + } + + out << "}"; + return out.str (); +} + //////////////////////////////////////////////////////////////////////////////// void Task::getAnnotations (std::vector & annotations) const { diff --git a/src/Task.h b/src/Task.h index df28cee29..d2e567312 100644 --- a/src/Task.h +++ b/src/Task.h @@ -45,6 +45,7 @@ public: void parse (const std::string&); std::string composeCSV () const; std::string composeYAML () const; + std::string composeJSON () const; // Status values. enum status {pending, completed, deleted, recurring, waiting}; diff --git a/src/command.cpp b/src/command.cpp index cad16611d..7a5007c7a 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -552,6 +552,46 @@ int handleUrgency (std::string& outs) return 0; } +//////////////////////////////////////////////////////////////////////////////// +int handleQuery (std::string& outs) +{ + int rc = 0; + + if (context.hooks.trigger ("pre-query-command")) + { + // Get all the tasks. + std::vector tasks; + context.tdb.lock (context.config.getBoolean ("locking")); + handleRecurrence (); + context.tdb.load (tasks, context.filter); + context.tdb.commit (); + context.tdb.unlock (); + + // Filter sequence. + if (context.sequence.size ()) + context.filter.applySequence (tasks, context.sequence); + + // Note: "limit:" feature not supported. + + // Compose output. + outs = "{"; + std::vector ::iterator t; + for (t = tasks.begin (); t != tasks.end (); ++t) + { + if (t != tasks.begin ()) + outs += ",\n"; + + outs += t->composeJSON (); + } + + outs += "}\n"; + + context.hooks.trigger ("post-query-command"); + } + + return rc; +} + //////////////////////////////////////////////////////////////////////////////// int handleCompletionIDs (std::string& outs) { diff --git a/src/main.h b/src/main.h index 87c8c02bb..23094931c 100644 --- a/src/main.h +++ b/src/main.h @@ -68,6 +68,7 @@ int handleCompletionIDs (std::string&); int handleCompletionConfig (std::string&); int handleCompletionVersion (std::string&); int handleUrgency (std::string&); +int handleQuery (std::string&); int handleVersion (std::string&); int handleConfig (std::string&); int handleShow (std::string&);