- Extended DOM.
This commit is contained in:
Paul Beckingham
2014-06-05 17:55:24 -04:00
parent 117c31b322
commit 61dab3eeb9
2 changed files with 148 additions and 76 deletions

View File

@@ -190,6 +190,25 @@ bool DOM::get (const std::string& name, std::string& value)
// <id>.<attribute> // <id>.<attribute>
// <uuid>.<attribute> // <uuid>.<attribute>
// //
// For certain attributes:
// <date>.year
// <date>.month
// <date>.day
// <date>.hour
// <date>.minute
// <date>.second
//
// <tag>.<literal> Includes virtual tags
//
// <annotation>.<N>.entry
// <annotation>.<N>.entry.year
// <annotation>.<N>.entry.month
// <annotation>.<N>.entry.day
// <annotation>.<N>.entry.hour
// <annotation>.<N>.entry.minute
// <annotation>.<N>.entry.second
// <annotation>.<N>.description
//
bool DOM::get (const std::string& name, const Task& task, std::string& value) bool DOM::get (const std::string& name, const Task& task, std::string& value)
{ {
// <attr> // <attr>
@@ -205,83 +224,109 @@ bool DOM::get (const std::string& name, const Task& task, std::string& value)
return true; return true;
} }
std::string canonical; // split name on '.'
if (task.size () && context.parser.canonicalize (canonical, "attribute", name)) std::vector <std::string> elements;
{ split (elements, name, '.');
value = task.get (canonical);
return true;
}
// <id>.<name> if (elements.size () == 1)
Nibbler n (name);
n.save ();
int id;
if (n.getInt (id))
{ {
if (n.skip ('.')) std::string canonical;
if (task.size () && context.parser.canonicalize (canonical, "attribute", name))
{ {
Task ref; value = task.get (canonical);
if (id == task.id) return true;
ref = task; }
}
else if (elements.size () > 1)
{
Task ref;
Nibbler n (elements[0]);
n.save ();
int id;
std::string uuid;
bool proceed = false;
if (n.getInt (id))
{
if (n.skip ('.'))
{
if (id == task.id)
ref = task;
else
context.tdb2.get (id, ref);
proceed = true;
}
else else
context.tdb2.get (id, ref); n.restore ();
}
else if (n.getUUID (uuid))
{
if (n.skip ('.'))
{
if (uuid == task.get ("uuid"))
ref = task;
else
context.tdb2.get (uuid, ref);
std::string attr; proceed = true;
n.getUntilEOS (attr); }
}
if (attr == "id") if (proceed)
{
if (elements[1] == "id")
{ {
value = format (ref.id); value = format (ref.id);
return true; return true;
} }
else if (attr == "urgency") else if (elements[1] == "urgency")
{ {
value = format (ref.urgency_c ()); value = format (ref.urgency_c ());
return true; return true;
} }
else if (context.parser.canonicalize (canonical, "attribute", attr))
std::string canonical;
if (context.parser.canonicalize (canonical, "attribute", elements[1]))
{ {
value = ref.get (canonical); if (elements.size () == 2)
return true; {
value = ref.get (canonical);
return true;
}
else if (elements.size () == 3)
{
// <date>.year
// <date>.month
// <date>.day
// <date>.hour
// <date>.minute
// <date>.second
// <tag>.<literal>
if (elements[1] == "tag")
{
value = ref.hasTag (elements[2]) ? elements[2] : "";
return true;
}
}
else if (elements.size () == 3)
{
// <annotation>.<N>.entry
// <annotation>.<N>.description
}
else if (elements.size () == 4)
{
// <annotation>.<N>.entry.year
// <annotation>.<N>.entry.month
// <annotation>.<N>.entry.day
// <annotation>.<N>.entry.hour
// <annotation>.<N>.entry.minute
// <annotation>.<N>.entry.second
}
} }
} }
n.restore ();
}
// <uuid>.<name>
std::string uuid;
if (n.getUUID (uuid))
{
if (n.skip ('.'))
{
Task ref;
if (uuid == task.get ("uuid"))
ref = task;
else
context.tdb2.get (uuid, ref);
std::string attr;
n.getUntilEOS (attr);
if (attr == "id")
{
value = format (ref.id);
return true;
}
else if (attr == "urgency")
{
value = format (ref.urgency_c (), 4, 3);
return true;
}
else if (context.parser.canonicalize (canonical, "attribute", attr))
{
value = ref.get (canonical);
return true;
}
}
n.restore ();
} }
// Delegate to the context-free version of DOM::get. // Delegate to the context-free version of DOM::get.

View File

@@ -27,44 +27,71 @@
use strict; use strict;
use warnings; use warnings;
use Test::More tests => 5; use Test::More tests => 12;
# Ensure environment has no influence. # Ensure environment has no influence.
delete $ENV{'TASKDATA'}; delete $ENV{'TASKDATA'};
delete $ENV{'TASKRC'}; delete $ENV{'TASKRC'};
use File::Basename;
my $ut = basename ($0);
my $rc = $ut . '.rc';
# Create the rc file. # Create the rc file.
if (open my $fh, '>', 'dom.rc') if (open my $fh, '>', $rc)
{ {
print $fh "data.location=.\n", print $fh "data.location=.\n",
"dateformat=YMD\n", "dateformat=YMD\n",
"dateformat.info=YMD\n"; "dateformat.info=YMD\n",
"confirmation=off\n";
close $fh; close $fh;
} }
# DOM reference to other task. # DOM reference to other task.
qx{../src/task rc:dom.rc add one due:20110901 2>&1}; qx{../src/task rc:$rc add one due:20110901 2>&1};
qx{../src/task rc:dom.rc add two due:1.due 2>&1}; qx{../src/task rc:$rc add two due:1.due 2>&1};
my $output = qx{../src/task rc:dom.rc 2 info 2>&1}; my $output = qx{../src/task rc:$rc 2 info 2>&1};
like ($output, qr/Due\s+20110901/, 'Found due date duplicated via dom'); like ($output, qr/Due\s+20110901/, "$ut: Found due date duplicated via dom");
# DOM reference to the current task. # DOM reference to the current task.
qx{../src/task rc:dom.rc add three due:20110901 wait:due 2>&1}; qx{../src/task rc:$rc add three due:20110901 wait:due +tag1 +tag2 2>&1};
$output = qx{../src/task rc:dom.rc 3 info 2>&1}; $output = qx{../src/task rc:$rc 3 info 2>&1};
like ($output, qr/Waiting until\s+20110901/, 'Found wait date duplicated from due date'); like ($output, qr/Waiting until\s+20110901/, "$ut: Found wait date duplicated from due date");
# ID <--> UUID <--> ID round trip via DOM. # ID <--> UUID <--> ID round trip via DOM.
$output = qx{../src/task rc:dom.rc _get 1.uuid 2>&1}; $output = qx{../src/task rc:$rc _get 1.uuid 2>&1};
like ($output, qr/^.{36}$/, 'DOM id --> uuid'); like ($output, qr/^.{36}$/, "$ut: DOM id --> uuid");
my $uuid = chomp $output; my $uuid = chomp $output;
$output = qx{../src/task rc:dom.rc _get ${uuid}.id 2>&1}; $output = qx{../src/task rc:$rc _get ${uuid}.id 2>&1};
like ($output, qr/^1$/, 'DOM uuid --> id'); like ($output, qr/^1$/, "$ut: DOM uuid --> id");
# Failed DOM lookup returns blank. # Failed DOM lookup returns blank.
$output = qx{../src/task rc:dom.rc _get 4.description 2>&1}; $output = qx{../src/task rc:$rc _get 4.description 2>&1};
like ($output, qr/^$/, "DOM 4.description --> ''"); like ($output, qr/^$/, "DOM 4.description --> ''");
# Test extended DOM support (2.4.0)
$output = qx{../src/task rc:$rc _get 3.tags 2>&1};
like ($output, qr/^tag1,tag2$/, "$ut: <id>.<tags>");
$output = qx{../src/task rc:$rc _get 3.tag.tag1 2>&1};
like ($output, qr/^tag1,tag2$/, "$ut: <id>.tag.tag1");
$output = qx{../src/task rc:$rc _get 3.tag.OVERDUE 2>&1};
like ($output, qr/^OVERDUE$/, "$ut: <id>.tag.<tag>");
$output = qx{../src/task rc:$rc _get 3.due.year 2>&1};
like ($output, qr/^\d{4}$/, "$ut: <id>.due.year");
qx{../src/task rc:$rc 3 annotate note 2>&1};
ok ($? == 0, "$ut: add annotation");
$output = qx{../src/task rc:$rc _get 3.annotation.1.entry 2>&1};
like ($output, qr/^\d+$/, "$ut: <id>.annotation.1.entry");
$output = qx{../src/task rc:$rc _get 3.annotation.1.description 2>&1};
like ($output, qr/^note$/, "$ut: <id>.annotation.1.description");
# Cleanup. # Cleanup.
unlink qw(pending.data completed.data undo.data backlog.data dom.rc); unlink qw(pending.data completed.data undo.data backlog.data), $rc;
exit 0; exit 0;