mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-06-26 10:54:26 +02:00
Refactor getDOM to use a pointer for the optional context
It's possible to call getDOM without a contextual task. Previously, this was done by referencing a "dummy" task which necessitated a way to distinguish such dummy tasks. This switches to using a pointer and treating the NULL value as meaning there is no context. Note that this cannot use `std::optional<&Task>`, as optional does not support reference types.
This commit is contained in:
parent
3af5ceadc1
commit
2812a8c77a
11 changed files with 76 additions and 82 deletions
64
src/DOM.cpp
64
src/DOM.cpp
|
@ -239,24 +239,25 @@ bool getDOM (const std::string& name, Variant& value)
|
||||||
//
|
//
|
||||||
// This code emphasizes speed, hence 'id' and 'urgency' being evaluated first
|
// This code emphasizes speed, hence 'id' and 'urgency' being evaluated first
|
||||||
// as special cases.
|
// as special cases.
|
||||||
bool getDOM (const std::string& name, const Task& task, Variant& value)
|
//
|
||||||
|
// If task is NULL, then the contextual task will be determined from the DOM
|
||||||
|
// string, if any exists.
|
||||||
|
bool getDOM (const std::string& name, const Task* task, Variant& value)
|
||||||
{
|
{
|
||||||
// Special case, blank refs cause problems.
|
// Special case, blank refs cause problems.
|
||||||
if (name == "")
|
if (name == "")
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto have_task = !task.is_empty();
|
|
||||||
|
|
||||||
// Quickly deal with the most common cases.
|
// Quickly deal with the most common cases.
|
||||||
if (have_task && name == "id")
|
if (task && name == "id")
|
||||||
{
|
{
|
||||||
value = Variant (static_cast<int> (task.id));
|
value = Variant (static_cast<int> (task->id));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (have_task && name == "urgency")
|
if (task && name == "urgency")
|
||||||
{
|
{
|
||||||
value = Variant (task.urgency_c ());
|
value = Variant (task->urgency_c ());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,11 +265,10 @@ bool getDOM (const std::string& name, const Task& task, Variant& value)
|
||||||
auto elements = split (name, '.');
|
auto elements = split (name, '.');
|
||||||
Task loaded_task;
|
Task loaded_task;
|
||||||
|
|
||||||
// Use a lambda to decide whether the reference is going to be the passed
|
// decide whether the reference is going to be the passed
|
||||||
// "task" or whether it's going to be a newly loaded task (if id/uuid was
|
// "task" or whether it's going to be a newly loaded task (if id/uuid was
|
||||||
// given).
|
// given).
|
||||||
const Task& ref = [&]() -> const Task&
|
const Task* ref = task;
|
||||||
{
|
|
||||||
Lexer lexer (elements[0]);
|
Lexer lexer (elements[0]);
|
||||||
std::string token;
|
std::string token;
|
||||||
Lexer::Type type;
|
Lexer::Type type;
|
||||||
|
@ -282,9 +282,9 @@ bool getDOM (const std::string& name, const Task& task, Variant& value)
|
||||||
if (type == Lexer::Type::uuid &&
|
if (type == Lexer::Type::uuid &&
|
||||||
token.length () == elements[0].length ())
|
token.length () == elements[0].length ())
|
||||||
{
|
{
|
||||||
if (token != task.get ("uuid"))
|
if (!task || token != task->get ("uuid"))
|
||||||
{
|
{
|
||||||
Context::getContext ().tdb2.get (token, loaded_task);
|
if (Context::getContext ().tdb2.get (token, loaded_task))
|
||||||
reloaded = true;
|
reloaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,9 +295,9 @@ bool getDOM (const std::string& name, const Task& task, Variant& value)
|
||||||
token.find ('.') == std::string::npos)
|
token.find ('.') == std::string::npos)
|
||||||
{
|
{
|
||||||
auto id = strtol (token.c_str (), nullptr, 10);
|
auto id = strtol (token.c_str (), nullptr, 10);
|
||||||
if (id && id != task.id)
|
if (id && (!task || id != task->id))
|
||||||
{
|
{
|
||||||
Context::getContext ().tdb2.get (id, loaded_task);
|
if (Context::getContext ().tdb2.get (id, loaded_task))
|
||||||
reloaded = true;
|
reloaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,18 +306,14 @@ bool getDOM (const std::string& name, const Task& task, Variant& value)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reloaded)
|
if (reloaded)
|
||||||
return loaded_task;
|
ref = &loaded_task;
|
||||||
}
|
}
|
||||||
|
|
||||||
return task;
|
|
||||||
|
|
||||||
} ();
|
|
||||||
|
|
||||||
// The remainder of this method requires a contextual task, so if we do not
|
// The remainder of this method requires a contextual task, so if we do not
|
||||||
// have one, delegate to the two-argument getDOM
|
// have one, delegate to the two-argument getDOM
|
||||||
if (ref.is_empty ()) {
|
if (!ref)
|
||||||
return getDOM (name, value);
|
return getDOM (name, value);
|
||||||
}
|
|
||||||
|
|
||||||
auto size = elements.size ();
|
auto size = elements.size ();
|
||||||
|
|
||||||
|
@ -328,13 +324,13 @@ bool getDOM (const std::string& name, const Task& task, Variant& value)
|
||||||
// elements vector, DOM resolution is now simple.
|
// elements vector, DOM resolution is now simple.
|
||||||
if (size == 1 && canonical == "id")
|
if (size == 1 && canonical == "id")
|
||||||
{
|
{
|
||||||
value = Variant (static_cast<int> (ref.id));
|
value = Variant (static_cast<int> (ref->id));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size == 1 && canonical == "urgency")
|
if (size == 1 && canonical == "urgency")
|
||||||
{
|
{
|
||||||
value = Variant (ref.urgency_c ());
|
value = Variant (ref->urgency_c ());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,7 +338,7 @@ bool getDOM (const std::string& name, const Task& task, Variant& value)
|
||||||
// implementation. Remove in 3.0.0.
|
// implementation. Remove in 3.0.0.
|
||||||
if (size == 1 && canonical == "status")
|
if (size == 1 && canonical == "status")
|
||||||
{
|
{
|
||||||
value = Variant (ref.statusToText (ref.getStatus ()));
|
value = Variant (ref->statusToText (ref->getStatus ()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,7 +346,7 @@ bool getDOM (const std::string& name, const Task& task, Variant& value)
|
||||||
|
|
||||||
if (size == 1 && column)
|
if (size == 1 && column)
|
||||||
{
|
{
|
||||||
if (column->is_uda () && ! ref.has (canonical))
|
if (column->is_uda () && ! ref->has (canonical))
|
||||||
{
|
{
|
||||||
value = Variant ("");
|
value = Variant ("");
|
||||||
return true;
|
return true;
|
||||||
|
@ -358,7 +354,7 @@ bool getDOM (const std::string& name, const Task& task, Variant& value)
|
||||||
|
|
||||||
if (column->type () == "date")
|
if (column->type () == "date")
|
||||||
{
|
{
|
||||||
auto numeric = ref.get_date (canonical);
|
auto numeric = ref->get_date (canonical);
|
||||||
if (numeric == 0)
|
if (numeric == 0)
|
||||||
value = Variant ("");
|
value = Variant ("");
|
||||||
else
|
else
|
||||||
|
@ -366,32 +362,32 @@ bool getDOM (const std::string& name, const Task& task, Variant& value)
|
||||||
}
|
}
|
||||||
else if (column->type () == "duration" || canonical == "recur")
|
else if (column->type () == "duration" || canonical == "recur")
|
||||||
{
|
{
|
||||||
auto period = ref.get (canonical);
|
auto period = ref->get (canonical);
|
||||||
|
|
||||||
Duration iso;
|
Duration iso;
|
||||||
std::string::size_type cursor = 0;
|
std::string::size_type cursor = 0;
|
||||||
if (iso.parse (period, cursor))
|
if (iso.parse (period, cursor))
|
||||||
value = Variant (iso.toTime_t (), Variant::type_duration);
|
value = Variant (iso.toTime_t (), Variant::type_duration);
|
||||||
else
|
else
|
||||||
value = Variant (Duration (ref.get (canonical)).toTime_t (), Variant::type_duration);
|
value = Variant (Duration (ref->get (canonical)).toTime_t (), Variant::type_duration);
|
||||||
}
|
}
|
||||||
else if (column->type () == "numeric")
|
else if (column->type () == "numeric")
|
||||||
value = Variant (ref.get_float (canonical));
|
value = Variant (ref->get_float (canonical));
|
||||||
else
|
else
|
||||||
value = Variant (ref.get (canonical));
|
value = Variant (ref->get (canonical));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size == 2 && canonical == "tags")
|
if (size == 2 && canonical == "tags")
|
||||||
{
|
{
|
||||||
value = Variant (ref.hasTag (elements[1]) ? elements[1] : "");
|
value = Variant (ref->hasTag (elements[1]) ? elements[1] : "");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size == 2 && column && column->type () == "date")
|
if (size == 2 && column && column->type () == "date")
|
||||||
{
|
{
|
||||||
Datetime date (ref.get_date (canonical));
|
Datetime date (ref->get_date (canonical));
|
||||||
if (elements[1] == "year") { value = Variant (static_cast<int> (date.year ())); return true; }
|
if (elements[1] == "year") { value = Variant (static_cast<int> (date.year ())); return true; }
|
||||||
else if (elements[1] == "month") { value = Variant (static_cast<int> (date.month ())); return true; }
|
else if (elements[1] == "month") { value = Variant (static_cast<int> (date.month ())); return true; }
|
||||||
else if (elements[1] == "day") { value = Variant (static_cast<int> (date.day ())); return true; }
|
else if (elements[1] == "day") { value = Variant (static_cast<int> (date.day ())); return true; }
|
||||||
|
@ -406,13 +402,13 @@ bool getDOM (const std::string& name, const Task& task, Variant& value)
|
||||||
|
|
||||||
if (size == 2 && elements[0] == "annotations" && elements[1] == "count")
|
if (size == 2 && elements[0] == "annotations" && elements[1] == "count")
|
||||||
{
|
{
|
||||||
value = Variant (static_cast<int> (ref.getAnnotationCount ()));
|
value = Variant (static_cast<int> (ref->getAnnotationCount ()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size == 3 && elements[0] == "annotations")
|
if (size == 3 && elements[0] == "annotations")
|
||||||
{
|
{
|
||||||
auto annos = ref.getAnnotations ();
|
auto annos = ref->getAnnotations ();
|
||||||
|
|
||||||
int a = strtol (elements[1].c_str (), nullptr, 10);
|
int a = strtol (elements[1].c_str (), nullptr, 10);
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
@ -440,7 +436,7 @@ bool getDOM (const std::string& name, const Task& task, Variant& value)
|
||||||
|
|
||||||
if (size == 4 && elements[0] == "annotations" && elements[2] == "entry")
|
if (size == 4 && elements[0] == "annotations" && elements[2] == "entry")
|
||||||
{
|
{
|
||||||
auto annos = ref.getAnnotations ();
|
auto annos = ref->getAnnotations ();
|
||||||
|
|
||||||
int a = strtol (elements[1].c_str (), nullptr, 10);
|
int a = strtol (elements[1].c_str (), nullptr, 10);
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
|
|
||||||
// 2017-04-22 Deprecated, use DOM::get.
|
// 2017-04-22 Deprecated, use DOM::get.
|
||||||
bool getDOM (const std::string&, Variant&);
|
bool getDOM (const std::string&, Variant&);
|
||||||
bool getDOM (const std::string&, const Task&, Variant&);
|
bool getDOM (const std::string&, const Task*, Variant&);
|
||||||
|
|
||||||
class DOM
|
class DOM
|
||||||
{
|
{
|
||||||
|
|
|
@ -36,9 +36,8 @@
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Const iterator that can be derefenced into a Task by domSource.
|
// Context for DOM evaluations
|
||||||
static Task dummy;
|
const Task* contextTask = NULL;
|
||||||
Task& contextTask = dummy;
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
bool domSource (const std::string& identifier, Variant& value)
|
bool domSource (const std::string& identifier, Variant& value)
|
||||||
|
@ -79,7 +78,7 @@ void Filter::subset (const std::vector <Task>& input, std::vector <Task>& output
|
||||||
for (auto& task : input)
|
for (auto& task : input)
|
||||||
{
|
{
|
||||||
// Set up context for any DOM references.
|
// Set up context for any DOM references.
|
||||||
contextTask = task;
|
contextTask = &task;
|
||||||
|
|
||||||
Variant var;
|
Variant var;
|
||||||
eval.evaluateCompiledExpression (var);
|
eval.evaluateCompiledExpression (var);
|
||||||
|
@ -131,7 +130,7 @@ void Filter::subset (std::vector <Task>& output)
|
||||||
for (auto& task : pending)
|
for (auto& task : pending)
|
||||||
{
|
{
|
||||||
// Set up context for any DOM references.
|
// Set up context for any DOM references.
|
||||||
contextTask = task;
|
contextTask = &task;
|
||||||
|
|
||||||
Variant var;
|
Variant var;
|
||||||
eval.evaluateCompiledExpression (var);
|
eval.evaluateCompiledExpression (var);
|
||||||
|
@ -150,7 +149,7 @@ void Filter::subset (std::vector <Task>& output)
|
||||||
for (auto& task : completed)
|
for (auto& task : completed)
|
||||||
{
|
{
|
||||||
// Set up context for any DOM references.
|
// Set up context for any DOM references.
|
||||||
contextTask = task;
|
contextTask = &task;
|
||||||
|
|
||||||
Variant var;
|
Variant var;
|
||||||
eval.evaluateCompiledExpression (var);
|
eval.evaluateCompiledExpression (var);
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
#include <utf8.h>
|
#include <utf8.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
|
||||||
extern Task& contextTask;
|
extern Task* contextTask;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
ColumnProject::ColumnProject ()
|
ColumnProject::ColumnProject ()
|
||||||
|
@ -121,7 +121,7 @@ void ColumnProject::modify (Task& task, const std::string& value)
|
||||||
{
|
{
|
||||||
Eval e;
|
Eval e;
|
||||||
e.addSource (domSource);
|
e.addSource (domSource);
|
||||||
contextTask = task;
|
contextTask = &task;
|
||||||
|
|
||||||
Variant v;
|
Variant v;
|
||||||
e.evaluateInfixExpression (value, v);
|
e.evaluateInfixExpression (value, v);
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <utf8.h>
|
#include <utf8.h>
|
||||||
|
|
||||||
extern Task& contextTask;
|
extern Task* contextTask;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
ColumnRecur::ColumnRecur ()
|
ColumnRecur::ColumnRecur ()
|
||||||
|
@ -108,7 +108,7 @@ void ColumnRecur::modify (Task& task, const std::string& value)
|
||||||
{
|
{
|
||||||
Eval e;
|
Eval e;
|
||||||
e.addSource (domSource);
|
e.addSource (domSource);
|
||||||
contextTask = task;
|
contextTask = &task;
|
||||||
e.evaluateInfixExpression (value, evaluatedValue);
|
e.evaluateInfixExpression (value, evaluatedValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
#include <utf8.h>
|
#include <utf8.h>
|
||||||
#include <main.h>
|
#include <main.h>
|
||||||
|
|
||||||
extern Task& contextTask;
|
extern Task* contextTask;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
ColumnTags::ColumnTags ()
|
ColumnTags::ColumnTags ()
|
||||||
|
@ -162,7 +162,7 @@ void ColumnTags::modify (Task& task, const std::string& value)
|
||||||
{
|
{
|
||||||
Eval e;
|
Eval e;
|
||||||
e.addSource (domSource);
|
e.addSource (domSource);
|
||||||
contextTask = task;
|
contextTask = &task;
|
||||||
|
|
||||||
Variant v;
|
Variant v;
|
||||||
e.evaluateInfixExpression (value, v);
|
e.evaluateInfixExpression (value, v);
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
#include <Filter.h>
|
#include <Filter.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
|
|
||||||
extern Task& contextTask;
|
extern Task* contextTask;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
ColumnTypeDate::ColumnTypeDate ()
|
ColumnTypeDate::ColumnTypeDate ()
|
||||||
|
@ -213,7 +213,7 @@ void ColumnTypeDate::modify (Task& task, const std::string& value)
|
||||||
{
|
{
|
||||||
Eval e;
|
Eval e;
|
||||||
e.addSource (domSource);
|
e.addSource (domSource);
|
||||||
contextTask = task;
|
contextTask = &task;
|
||||||
e.evaluateInfixExpression (value, evaluatedValue);
|
e.evaluateInfixExpression (value, evaluatedValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
#include <Filter.h>
|
#include <Filter.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
|
|
||||||
extern Task& contextTask;
|
extern Task* contextTask;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
ColumnTypeDuration::ColumnTypeDuration ()
|
ColumnTypeDuration::ColumnTypeDuration ()
|
||||||
|
@ -55,7 +55,7 @@ void ColumnTypeDuration::modify (Task& task, const std::string& value)
|
||||||
{
|
{
|
||||||
Eval e;
|
Eval e;
|
||||||
e.addSource (domSource);
|
e.addSource (domSource);
|
||||||
contextTask = task;
|
contextTask = &task;
|
||||||
e.evaluateInfixExpression (value, evaluatedValue);
|
e.evaluateInfixExpression (value, evaluatedValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
#include <Filter.h>
|
#include <Filter.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
|
|
||||||
extern Task& contextTask;
|
extern Task* contextTask;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
ColumnTypeNumeric::ColumnTypeNumeric ()
|
ColumnTypeNumeric::ColumnTypeNumeric ()
|
||||||
|
@ -55,7 +55,7 @@ void ColumnTypeNumeric::modify (Task& task, const std::string& value)
|
||||||
{
|
{
|
||||||
Eval e;
|
Eval e;
|
||||||
e.addSource (domSource);
|
e.addSource (domSource);
|
||||||
contextTask = task;
|
contextTask = &task;
|
||||||
e.evaluateInfixExpression (value, evaluatedValue);
|
e.evaluateInfixExpression (value, evaluatedValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
|
|
||||||
#define STRING_INVALID_MOD "The '{1}' attribute does not allow a value of '{2}'."
|
#define STRING_INVALID_MOD "The '{1}' attribute does not allow a value of '{2}'."
|
||||||
|
|
||||||
extern Task& contextTask;
|
extern Task* contextTask;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
ColumnTypeString::ColumnTypeString ()
|
ColumnTypeString::ColumnTypeString ()
|
||||||
|
@ -67,7 +67,7 @@ void ColumnTypeString::modify (Task& task, const std::string& value)
|
||||||
{
|
{
|
||||||
Eval e;
|
Eval e;
|
||||||
e.addSource (domSource);
|
e.addSource (domSource);
|
||||||
contextTask = task;
|
contextTask = &task;
|
||||||
|
|
||||||
Variant v;
|
Variant v;
|
||||||
e.evaluateInfixExpression (value, v);
|
e.evaluateInfixExpression (value, v);
|
||||||
|
|
|
@ -64,9 +64,8 @@ int CmdGet::execute (std::string& output)
|
||||||
{
|
{
|
||||||
case Lexer::Type::dom:
|
case Lexer::Type::dom:
|
||||||
{
|
{
|
||||||
Task t;
|
|
||||||
Variant result;
|
Variant result;
|
||||||
if (getDOM (arg.attribute ("raw"), t, result))
|
if (getDOM (arg.attribute ("raw"), NULL, result))
|
||||||
results.emplace_back (result);
|
results.emplace_back (result);
|
||||||
else
|
else
|
||||||
results.emplace_back ("");
|
results.emplace_back ("");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue