mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-08-19 19:03:07 +02:00
Tags: New 'UDA' and 'ORPHAN' virtual tags.
This commit is contained in:
parent
297b0c4b04
commit
41a76c6798
8 changed files with 109 additions and 44 deletions
|
|
@ -102,6 +102,7 @@
|
||||||
Shahaf).
|
Shahaf).
|
||||||
- When multiple tasks are 'edit'ed, a failure causes the editing to stop (thanks
|
- When multiple tasks are 'edit'ed, a failure causes the editing to stop (thanks
|
||||||
to Daniel Shahaf).
|
to Daniel Shahaf).
|
||||||
|
- New 'UDA' and 'ORPHAN' virtual tags.
|
||||||
|
|
||||||
------ current release ---------------------------
|
------ current release ---------------------------
|
||||||
|
|
||||||
|
|
|
||||||
1
NEWS
1
NEWS
|
|
@ -3,6 +3,7 @@ New Features in Taskwarrior 2.4.5
|
||||||
|
|
||||||
- The active context, if one is set, is now identified in "task context list"
|
- The active context, if one is set, is now identified in "task context list"
|
||||||
- It is an error to attempt and add or remove of a virtual tag.
|
- It is an error to attempt and add or remove of a virtual tag.
|
||||||
|
- New 'UDA' and 'ORPHAN' virtual tags.
|
||||||
|
|
||||||
New commands in Taskwarrior 2.4.5
|
New commands in Taskwarrior 2.4.5
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -652,31 +652,33 @@ There are also virtual tags, which represent task metadata in tag form. These
|
||||||
tags do not exist, but can be used to filter tasks. The supported virtual tags
|
tags do not exist, but can be used to filter tasks. The supported virtual tags
|
||||||
are:
|
are:
|
||||||
|
|
||||||
BLOCKED Matches if the task is blocked
|
|
||||||
UNBLOCKED Matches if the task is not blocked
|
|
||||||
BLOCKING Matches if the task is blocking
|
|
||||||
YESTERDAY Matches if the task was due sometime yesterday
|
|
||||||
DUE Matches if the task is due
|
|
||||||
DUETODAY Matches if the task is due today
|
|
||||||
TODAY Matches if the task is due today
|
|
||||||
TOMORROW Matches if the task is due sometime tomorrow
|
|
||||||
WEEK Matches if the task is due this week
|
|
||||||
MONTH Matches if the task is due this month
|
|
||||||
YEAR Matches if the task is due this year
|
|
||||||
OVERDUE Matches if the task is overdue
|
|
||||||
ACTIVE Matches if the task is started
|
ACTIVE Matches if the task is started
|
||||||
SCHEDULED Matches if the task is scheduled
|
|
||||||
READY Matches if the task is actionable
|
|
||||||
PARENT Matches if the task is a parent
|
|
||||||
CHILD Matches if the task has a parent
|
|
||||||
UNTIL Matches if the task expires
|
|
||||||
WAITING Matches if the task is waiting
|
|
||||||
ANNOTATED Matches if the task has annotations
|
ANNOTATED Matches if the task has annotations
|
||||||
TAGGED Matches if the task has tags
|
BLOCKED Matches if the task is blocked
|
||||||
PENDING Matches if the task has pending status
|
BLOCKING Matches if the task is blocking
|
||||||
|
CHILD Matches if the task has a parent
|
||||||
COMPLETED Matches if the task has completed status
|
COMPLETED Matches if the task has completed status
|
||||||
DELETED Matches if the task has deleted status
|
DELETED Matches if the task has deleted status
|
||||||
.\" If you update the above list, update src/commands/CmdTags.cpp as well.
|
DUE Matches if the task is due
|
||||||
|
DUETODAY Matches if the task is due today
|
||||||
|
MONTH Matches if the task is due this month
|
||||||
|
ORPHAN Matches if the task has any orphaned UDA values
|
||||||
|
OVERDUE Matches if the task is overdue
|
||||||
|
PARENT Matches if the task is a parent
|
||||||
|
PENDING Matches if the task has pending status
|
||||||
|
READY Matches if the task is actionable
|
||||||
|
SCHEDULED Matches if the task is scheduled
|
||||||
|
TAGGED Matches if the task has tags
|
||||||
|
TODAY Matches if the task is due today
|
||||||
|
TOMORROW Matches if the task is due sometime tomorrow
|
||||||
|
UDA Matches if the task has any UDA values
|
||||||
|
UNBLOCKED Matches if the task is not blocked
|
||||||
|
UNTIL Matches if the task expires
|
||||||
|
WAITING Matches if the task is waiting
|
||||||
|
WEEK Matches if the task is due this week
|
||||||
|
YEAR Matches if the task is due this year
|
||||||
|
YESTERDAY Matches if the task was due sometime yesterday
|
||||||
|
.\" If you update the above list, update src/commands/CmdInfo.cpp and src/commands/CmdTags.cpp as well.
|
||||||
|
|
||||||
You can use +BLOCKED to filter blocked tasks, or -BLOCKED for unblocked tasks.
|
You can use +BLOCKED to filter blocked tasks, or -BLOCKED for unblocked tasks.
|
||||||
Similarly, -BLOCKED is equivalent to +UNBLOCKED. It is an error to attempt to
|
Similarly, -BLOCKED is equivalent to +UNBLOCKED. It is an error to attempt to
|
||||||
|
|
|
||||||
25
src/Task.cpp
25
src/Task.cpp
|
|
@ -495,6 +495,29 @@ bool Task::is_dueyear () const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool Task::is_udaPresent () const
|
||||||
|
{
|
||||||
|
for (auto& col : context.columns)
|
||||||
|
if (col.first.substr (0, 11) != "annotation_")
|
||||||
|
if (col.second->is_uda () &&
|
||||||
|
has (col.first))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool Task::is_orphanPresent () const
|
||||||
|
{
|
||||||
|
for (auto& att : *this)
|
||||||
|
if (att.first.substr (0, 11) != "annotation_")
|
||||||
|
if (context.columns.find (att.first) == context.columns.end ())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
bool Task::is_overdue () const
|
bool Task::is_overdue () const
|
||||||
{
|
{
|
||||||
|
|
@ -1120,6 +1143,8 @@ bool Task::hasTag (const std::string& tag) const
|
||||||
if (tag == "PENDING") return get ("status") == "pending";
|
if (tag == "PENDING") return get ("status") == "pending";
|
||||||
if (tag == "COMPLETED") return get ("status") == "completed";
|
if (tag == "COMPLETED") return get ("status") == "completed";
|
||||||
if (tag == "DELETED") return get ("status") == "deleted";
|
if (tag == "DELETED") return get ("status") == "deleted";
|
||||||
|
if (tag == "UDA") return is_udaPresent();
|
||||||
|
if (tag == "ORPHAN") return is_orphanPresent();
|
||||||
|
|
||||||
// Concrete tags.
|
// Concrete tags.
|
||||||
std::vector <std::string> tags;
|
std::vector <std::string> tags;
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,8 @@ public:
|
||||||
bool is_duemonth () const;
|
bool is_duemonth () const;
|
||||||
bool is_dueyear () const;
|
bool is_dueyear () const;
|
||||||
bool is_overdue () const;
|
bool is_overdue () const;
|
||||||
|
bool is_udaPresent () const;
|
||||||
|
bool is_orphanPresent () const;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
status getStatus () const;
|
status getStatus () const;
|
||||||
|
|
|
||||||
|
|
@ -316,6 +316,7 @@ int CmdInfo::execute (std::string& output)
|
||||||
if (task.hasTag ("DUE")) virtualTags += "DUE ";
|
if (task.hasTag ("DUE")) virtualTags += "DUE ";
|
||||||
if (task.hasTag ("DUETODAY")) virtualTags += "DUETODAY ";
|
if (task.hasTag ("DUETODAY")) virtualTags += "DUETODAY ";
|
||||||
if (task.hasTag ("MONTH")) virtualTags += "MONTH ";
|
if (task.hasTag ("MONTH")) virtualTags += "MONTH ";
|
||||||
|
if (task.hasTag ("ORPHAN")) virtualTags += "ORPHAN ";
|
||||||
if (task.hasTag ("OVERDUE")) virtualTags += "OVERDUE ";
|
if (task.hasTag ("OVERDUE")) virtualTags += "OVERDUE ";
|
||||||
if (task.hasTag ("PARENT")) virtualTags += "PARENT ";
|
if (task.hasTag ("PARENT")) virtualTags += "PARENT ";
|
||||||
if (task.hasTag ("PENDING")) virtualTags += "PENDING ";
|
if (task.hasTag ("PENDING")) virtualTags += "PENDING ";
|
||||||
|
|
@ -324,12 +325,14 @@ int CmdInfo::execute (std::string& output)
|
||||||
if (task.hasTag ("TAGGED")) virtualTags += "TAGGED ";
|
if (task.hasTag ("TAGGED")) virtualTags += "TAGGED ";
|
||||||
if (task.hasTag ("TODAY")) virtualTags += "TODAY ";
|
if (task.hasTag ("TODAY")) virtualTags += "TODAY ";
|
||||||
if (task.hasTag ("TOMORROW")) virtualTags += "TOMORROW ";
|
if (task.hasTag ("TOMORROW")) virtualTags += "TOMORROW ";
|
||||||
|
if (task.hasTag ("UDA")) virtualTags += "UDA ";
|
||||||
if (task.hasTag ("UNBLOCKED")) virtualTags += "UNBLOCKED ";
|
if (task.hasTag ("UNBLOCKED")) virtualTags += "UNBLOCKED ";
|
||||||
if (task.hasTag ("UNTIL")) virtualTags += "UNTIL ";
|
if (task.hasTag ("UNTIL")) virtualTags += "UNTIL ";
|
||||||
if (task.hasTag ("WAITING")) virtualTags += "WAITING ";
|
if (task.hasTag ("WAITING")) virtualTags += "WAITING ";
|
||||||
if (task.hasTag ("WEEK")) virtualTags += "WEEK ";
|
if (task.hasTag ("WEEK")) virtualTags += "WEEK ";
|
||||||
if (task.hasTag ("YEAR")) virtualTags += "YEAR ";
|
if (task.hasTag ("YEAR")) virtualTags += "YEAR ";
|
||||||
if (task.hasTag ("YESTERDAY")) virtualTags += "YESTERDAY ";
|
if (task.hasTag ("YESTERDAY")) virtualTags += "YESTERDAY ";
|
||||||
|
// If you update the above list, update src/commands/CmdInfo.cpp and src/commands/CmdTags.cpp as well.
|
||||||
|
|
||||||
row = view.addRow ();
|
row = view.addRow ();
|
||||||
view.set (row, 0, STRING_CMD_INFO_VIRTUAL_TAGS);
|
view.set (row, 0, STRING_CMD_INFO_VIRTUAL_TAGS);
|
||||||
|
|
|
||||||
|
|
@ -177,31 +177,33 @@ int CmdCompletionTags::execute (std::string& output)
|
||||||
unique["nonag"] = 0;
|
unique["nonag"] = 0;
|
||||||
unique["nocal"] = 0;
|
unique["nocal"] = 0;
|
||||||
unique["next"] = 0;
|
unique["next"] = 0;
|
||||||
unique["BLOCKED"] = 0;
|
|
||||||
unique["UNBLOCKED"] = 0;
|
|
||||||
unique["BLOCKING"] = 0;
|
|
||||||
unique["YESTERDAY"] = 0;
|
|
||||||
unique["DUE"] = 0;
|
|
||||||
unique["DUETODAY"] = 0;
|
|
||||||
unique["TODAY"] = 0;
|
|
||||||
unique["TOMORROW"] = 0;
|
|
||||||
unique["WEEK"] = 0;
|
|
||||||
unique["MONTH"] = 0;
|
|
||||||
unique["YEAR"] = 0;
|
|
||||||
unique["OVERDUE"] = 0;
|
|
||||||
unique["ACTIVE"] = 0;
|
unique["ACTIVE"] = 0;
|
||||||
unique["SCHEDULED"] = 0;
|
|
||||||
unique["READY"] = 0;
|
|
||||||
unique["PARENT"] = 0;
|
|
||||||
unique["CHILD"] = 0;
|
|
||||||
unique["UNTIL"] = 0;
|
|
||||||
unique["WAITING"] = 0;
|
|
||||||
unique["ANNOTATED"] = 0;
|
unique["ANNOTATED"] = 0;
|
||||||
unique["TAGGED"] = 0;
|
unique["BLOCKED"] = 0;
|
||||||
unique["PENDING"] = 0;
|
unique["BLOCKING"] = 0;
|
||||||
|
unique["CHILD"] = 0;
|
||||||
unique["COMPLETED"] = 0;
|
unique["COMPLETED"] = 0;
|
||||||
unique["DELETED"] = 0;
|
unique["DELETED"] = 0;
|
||||||
// If you update this list, update doc/man/task.1.in as well.
|
unique["DUE"] = 0;
|
||||||
|
unique["DUETODAY"] = 0;
|
||||||
|
unique["MONTH"] = 0;
|
||||||
|
unique["ORPHAN"] = 0;
|
||||||
|
unique["OVERDUE"] = 0;
|
||||||
|
unique["PARENT"] = 0;
|
||||||
|
unique["PENDING"] = 0;
|
||||||
|
unique["READY"] = 0;
|
||||||
|
unique["SCHEDULED"] = 0;
|
||||||
|
unique["TAGGED"] = 0;
|
||||||
|
unique["TODAY"] = 0;
|
||||||
|
unique["TOMORROW"] = 0;
|
||||||
|
unique["UDA"] = 0;
|
||||||
|
unique["UNBLOCKED"] = 0;
|
||||||
|
unique["UNTIL"] = 0;
|
||||||
|
unique["WAITING"] = 0;
|
||||||
|
unique["WEEK"] = 0;
|
||||||
|
unique["YEAR"] = 0;
|
||||||
|
unique["YESTERDAY"] = 0;
|
||||||
|
// If you update the above list, update src/commands/CmdInfo.cpp and src/commands/CmdTags.cpp as well.
|
||||||
|
|
||||||
std::stringstream out;
|
std::stringstream out;
|
||||||
for (auto& it : unique)
|
for (auto& it : unique)
|
||||||
|
|
|
||||||
31
test/tag.t
31
test/tag.t
|
|
@ -354,7 +354,6 @@ class TestVirtualTags(TestCase):
|
||||||
self.assertIn("due_eom", out)
|
self.assertIn("due_eom", out)
|
||||||
self.assertIn("due_eow", out)
|
self.assertIn("due_eow", out)
|
||||||
|
|
||||||
|
|
||||||
def test_virtual_tags_helper(self):
|
def test_virtual_tags_helper(self):
|
||||||
"""Verify '_tags' shows appropriate tags"""
|
"""Verify '_tags' shows appropriate tags"""
|
||||||
code, out, err = self.t("_tags")
|
code, out, err = self.t("_tags")
|
||||||
|
|
@ -366,6 +365,36 @@ class TestVirtualTags(TestCase):
|
||||||
self.assertIn("tag", out)
|
self.assertIn("tag", out)
|
||||||
|
|
||||||
|
|
||||||
|
class TestVirtualTagUDA(TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
"""Executed before each test in the class"""
|
||||||
|
self.t = Task()
|
||||||
|
self.t.config("uda.animal.type", "string")
|
||||||
|
self.t.config("uda.animal.label", "Animal")
|
||||||
|
self.t("add one animal:donkey")
|
||||||
|
self.t("add two")
|
||||||
|
|
||||||
|
def test_virtual_tag_UDA(self):
|
||||||
|
"""Verify 'UDA' appears when expected"""
|
||||||
|
code, out, err = self.t("+UDA all")
|
||||||
|
self.assertIn("one", out)
|
||||||
|
self.assertNotIn("two", out)
|
||||||
|
|
||||||
|
|
||||||
|
class TestVirtualTagORPHAN(TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
"""Executed before each test in the class"""
|
||||||
|
self.t = Task()
|
||||||
|
self.t("add one rc.uda.animal.type:string rc.uda.animal.label:Animal animal:donkey")
|
||||||
|
self.t("add two")
|
||||||
|
|
||||||
|
def test_virtual_tag_ORPHAN(self):
|
||||||
|
"""Verify 'ORPHAN' appears when expected"""
|
||||||
|
code, out, err = self.t("+ORPHAN all")
|
||||||
|
self.assertIn("one", out)
|
||||||
|
self.assertNotIn("two", out)
|
||||||
|
|
||||||
|
|
||||||
class Test285(TestCase):
|
class Test285(TestCase):
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue