mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-06-26 10:54:26 +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
|
@ -100,8 +100,9 @@
|
|||
- "import" can now import JSON arrays, the new default "export" output.
|
||||
- The '_tags' helper command now includes virtual tags (thanks to Daniel
|
||||
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).
|
||||
- New 'UDA' and 'ORPHAN' virtual tags.
|
||||
|
||||
------ 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"
|
||||
- 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
|
||||
|
||||
|
|
|
@ -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
|
||||
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
|
||||
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
|
||||
TAGGED Matches if the task has tags
|
||||
PENDING Matches if the task has pending status
|
||||
BLOCKED Matches if the task is blocked
|
||||
BLOCKING Matches if the task is blocking
|
||||
CHILD Matches if the task has a parent
|
||||
COMPLETED Matches if the task has completed 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.
|
||||
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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
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
|
||||
{
|
||||
|
@ -1120,6 +1143,8 @@ bool Task::hasTag (const std::string& tag) const
|
|||
if (tag == "PENDING") return get ("status") == "pending";
|
||||
if (tag == "COMPLETED") return get ("status") == "completed";
|
||||
if (tag == "DELETED") return get ("status") == "deleted";
|
||||
if (tag == "UDA") return is_udaPresent();
|
||||
if (tag == "ORPHAN") return is_orphanPresent();
|
||||
|
||||
// Concrete tags.
|
||||
std::vector <std::string> tags;
|
||||
|
|
|
@ -111,6 +111,8 @@ public:
|
|||
bool is_duemonth () const;
|
||||
bool is_dueyear () const;
|
||||
bool is_overdue () const;
|
||||
bool is_udaPresent () const;
|
||||
bool is_orphanPresent () const;
|
||||
#endif
|
||||
|
||||
status getStatus () const;
|
||||
|
|
|
@ -316,6 +316,7 @@ int CmdInfo::execute (std::string& output)
|
|||
if (task.hasTag ("DUE")) virtualTags += "DUE ";
|
||||
if (task.hasTag ("DUETODAY")) virtualTags += "DUETODAY ";
|
||||
if (task.hasTag ("MONTH")) virtualTags += "MONTH ";
|
||||
if (task.hasTag ("ORPHAN")) virtualTags += "ORPHAN ";
|
||||
if (task.hasTag ("OVERDUE")) virtualTags += "OVERDUE ";
|
||||
if (task.hasTag ("PARENT")) virtualTags += "PARENT ";
|
||||
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 ("TODAY")) virtualTags += "TODAY ";
|
||||
if (task.hasTag ("TOMORROW")) virtualTags += "TOMORROW ";
|
||||
if (task.hasTag ("UDA")) virtualTags += "UDA ";
|
||||
if (task.hasTag ("UNBLOCKED")) virtualTags += "UNBLOCKED ";
|
||||
if (task.hasTag ("UNTIL")) virtualTags += "UNTIL ";
|
||||
if (task.hasTag ("WAITING")) virtualTags += "WAITING ";
|
||||
if (task.hasTag ("WEEK")) virtualTags += "WEEK ";
|
||||
if (task.hasTag ("YEAR")) virtualTags += "YEAR ";
|
||||
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 ();
|
||||
view.set (row, 0, STRING_CMD_INFO_VIRTUAL_TAGS);
|
||||
|
|
|
@ -177,31 +177,33 @@ int CmdCompletionTags::execute (std::string& output)
|
|||
unique["nonag"] = 0;
|
||||
unique["nocal"] = 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["SCHEDULED"] = 0;
|
||||
unique["READY"] = 0;
|
||||
unique["PARENT"] = 0;
|
||||
unique["CHILD"] = 0;
|
||||
unique["UNTIL"] = 0;
|
||||
unique["WAITING"] = 0;
|
||||
unique["ANNOTATED"] = 0;
|
||||
unique["TAGGED"] = 0;
|
||||
unique["PENDING"] = 0;
|
||||
unique["BLOCKED"] = 0;
|
||||
unique["BLOCKING"] = 0;
|
||||
unique["CHILD"] = 0;
|
||||
unique["COMPLETED"] = 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;
|
||||
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_eow", out)
|
||||
|
||||
|
||||
def test_virtual_tags_helper(self):
|
||||
"""Verify '_tags' shows appropriate tags"""
|
||||
code, out, err = self.t("_tags")
|
||||
|
@ -366,6 +365,36 @@ class TestVirtualTags(TestCase):
|
|||
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):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue