mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-08-26 06:37:20 +02:00
Merge branch '2.4.2' into lexer2
This commit is contained in:
commit
a75c293286
23 changed files with 141 additions and 219 deletions
|
@ -1,5 +1,9 @@
|
||||||
2.4.2 () -
|
2.4.2 () -
|
||||||
|
|
||||||
|
- TW-41 Tasks in subprojects are not counted in project completion (thanks
|
||||||
|
to Renato Alves).
|
||||||
|
- TW-1450 Projects command should trigger running garbage collector (thanks to
|
||||||
|
Tomas Babej).
|
||||||
- TW-1535 move default listing-break from list to ls (thanks to David Patrick).
|
- TW-1535 move default listing-break from list to ls (thanks to David Patrick).
|
||||||
- TW-1545 cc1plus: error: unrecognized command line option '-std=c++11' (thanks
|
- TW-1545 cc1plus: error: unrecognized command line option '-std=c++11' (thanks
|
||||||
to Petteri).
|
to Petteri).
|
||||||
|
@ -17,6 +21,7 @@
|
||||||
- Closed dangling pipes in execute (), resolving problems when a hook script
|
- Closed dangling pipes in execute (), resolving problems when a hook script
|
||||||
forks (thanks to Jens Erat).
|
forks (thanks to Jens Erat).
|
||||||
- Re-enabled hook script feedback when exiting with 0 exit status.
|
- Re-enabled hook script feedback when exiting with 0 exit status.
|
||||||
|
- The 'info' command now shows virtual tags.
|
||||||
|
|
||||||
------ current release ---------------------------
|
------ current release ---------------------------
|
||||||
|
|
||||||
|
|
1
NEWS
1
NEWS
|
@ -2,6 +2,7 @@
|
||||||
New Features in taskwarrior 2.4.2
|
New Features in taskwarrior 2.4.2
|
||||||
|
|
||||||
- Ability to set context, which serves as a permanent user-defined filter.
|
- Ability to set context, which serves as a permanent user-defined filter.
|
||||||
|
- The 'info' command now shows virtual tags.
|
||||||
|
|
||||||
New commands in taskwarrior 2.4.2
|
New commands in taskwarrior 2.4.2
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,12 @@ _task_offer_projects() {
|
||||||
COMPREPLY=( $(compgen -W "$($taskcommand _projects)" -- ${cur/*:/}) )
|
COMPREPLY=( $(compgen -W "$($taskcommand _projects)" -- ${cur/*:/}) )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_task_offer_contexts() {
|
||||||
|
COMPREPLY=( $(compgen -W "$($taskcommand _context) define delete list none show" -- $cur) )
|
||||||
|
}
|
||||||
|
|
||||||
|
_task_context_alias=$($taskcommand show | grep alias.*context | cut -d' ' -f1 | cut -d. -f2)
|
||||||
|
|
||||||
_task()
|
_task()
|
||||||
{
|
{
|
||||||
local cur prev opts base
|
local cur prev opts base
|
||||||
|
@ -91,6 +97,10 @@ _task()
|
||||||
opts="$commands_aliases $($taskcommand _columns)"
|
opts="$commands_aliases $($taskcommand _columns)"
|
||||||
|
|
||||||
case "${prev}" in
|
case "${prev}" in
|
||||||
|
$_task_context_alias|cont|conte|contex|context)
|
||||||
|
_task_offer_contexts
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
:)
|
:)
|
||||||
case "${prev2}" in
|
case "${prev2}" in
|
||||||
pri|prior|priori|priorit|priority)
|
pri|prior|priori|priorit|priority)
|
||||||
|
|
|
@ -275,7 +275,7 @@ int Context::initialize (int argc, const char** argv)
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// [8] Run on.launch hooks.
|
// [8] Initialize hooks.
|
||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
|
@ -61,31 +61,48 @@ static struct
|
||||||
{"fortnight", 14 * DAY, true},
|
{"fortnight", 14 * DAY, true},
|
||||||
{"hours", 1 * HOUR, false},
|
{"hours", 1 * HOUR, false},
|
||||||
{"hour", 1 * HOUR, true},
|
{"hour", 1 * HOUR, true},
|
||||||
|
{"hrs", 1 * HOUR, true},
|
||||||
|
{"hr", 1 * HOUR, true},
|
||||||
{"h", 1 * HOUR, false},
|
{"h", 1 * HOUR, false},
|
||||||
{"minutes", 1 * MINUTE, false},
|
{"minutes", 1 * MINUTE, false},
|
||||||
{"minute", 1 * MINUTE, false},
|
{"minute", 1 * MINUTE, false},
|
||||||
|
{"mins", 1 * MINUTE, false},
|
||||||
{"min", 1 * MINUTE, false},
|
{"min", 1 * MINUTE, false},
|
||||||
{"monthly", 30 * DAY, true},
|
{"monthly", 30 * DAY, true},
|
||||||
{"months", 30 * DAY, false},
|
{"months", 30 * DAY, false},
|
||||||
{"month", 30 * DAY, true},
|
{"month", 30 * DAY, true},
|
||||||
|
{"mnths", 30 * DAY, false},
|
||||||
|
{"mths", 30 * DAY, false},
|
||||||
|
{"mth", 30 * DAY, false},
|
||||||
|
{"mos", 30 * DAY, false},
|
||||||
{"mo", 30 * DAY, false},
|
{"mo", 30 * DAY, false},
|
||||||
|
{"m", 30 * DAY, false},
|
||||||
{"quarterly", 91 * DAY, true},
|
{"quarterly", 91 * DAY, true},
|
||||||
{"quarters", 91 * DAY, false},
|
{"quarters", 91 * DAY, false},
|
||||||
{"quarter", 91 * DAY, true},
|
{"quarter", 91 * DAY, true},
|
||||||
|
{"qrtrs", 91 * DAY, false},
|
||||||
|
{"qtrs", 91 * DAY, false},
|
||||||
|
{"qtr", 91 * DAY, false},
|
||||||
{"q", 91 * DAY, false},
|
{"q", 91 * DAY, false},
|
||||||
{"semiannual", 183 * DAY, true},
|
{"semiannual", 183 * DAY, true},
|
||||||
{"sennight", 14 * DAY, false},
|
{"sennight", 14 * DAY, false},
|
||||||
{"seconds", 1 * SECOND, false},
|
{"seconds", 1 * SECOND, false},
|
||||||
{"second", 1 * SECOND, true},
|
{"second", 1 * SECOND, true},
|
||||||
|
{"secs", 1 * SECOND, true},
|
||||||
|
{"sec", 1 * SECOND, true},
|
||||||
{"s", 1 * SECOND, false},
|
{"s", 1 * SECOND, false},
|
||||||
{"weekdays", 1 * DAY, true},
|
{"weekdays", 1 * DAY, true},
|
||||||
{"weekly", 7 * DAY, true},
|
{"weekly", 7 * DAY, true},
|
||||||
{"weeks", 7 * DAY, false},
|
{"weeks", 7 * DAY, false},
|
||||||
{"week", 7 * DAY, true},
|
{"week", 7 * DAY, true},
|
||||||
|
{"wks", 7 * DAY, true},
|
||||||
|
{"wk", 7 * DAY, true},
|
||||||
{"w", 7 * DAY, false},
|
{"w", 7 * DAY, false},
|
||||||
{"yearly", 365 * DAY, true},
|
{"yearly", 365 * DAY, true},
|
||||||
{"years", 365 * DAY, false},
|
{"years", 365 * DAY, false},
|
||||||
{"year", 365 * DAY, true},
|
{"year", 365 * DAY, true},
|
||||||
|
{"yrs", 365 * DAY, true},
|
||||||
|
{"yr", 365 * DAY, true},
|
||||||
{"y", 365 * DAY, false},
|
{"y", 365 * DAY, false},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
22
src/TDB2.cpp
22
src/TDB2.cpp
|
@ -572,7 +572,7 @@ void TDB2::add (Task& task, bool add_to_backlog /* = true */)
|
||||||
if (add_to_backlog)
|
if (add_to_backlog)
|
||||||
context.hooks.onAdd (task);
|
context.hooks.onAdd (task);
|
||||||
|
|
||||||
update (uuid, task, add_to_backlog);
|
update (uuid, task, add_to_backlog, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -580,7 +580,6 @@ void TDB2::modify (Task& task, bool add_to_backlog /* = true */)
|
||||||
{
|
{
|
||||||
// Ensure the task is consistent, and provide defaults if necessary.
|
// Ensure the task is consistent, and provide defaults if necessary.
|
||||||
task.validate (false);
|
task.validate (false);
|
||||||
task.upgradeLegacyValues ();
|
|
||||||
std::string uuid = task.get ("uuid");
|
std::string uuid = task.get ("uuid");
|
||||||
|
|
||||||
// Get the unmodified task as reference, so the hook can compare.
|
// Get the unmodified task as reference, so the hook can compare.
|
||||||
|
@ -598,14 +597,15 @@ void TDB2::modify (Task& task, bool add_to_backlog /* = true */)
|
||||||
void TDB2::update (
|
void TDB2::update (
|
||||||
const std::string& uuid,
|
const std::string& uuid,
|
||||||
Task& task,
|
Task& task,
|
||||||
const bool add_to_backlog)
|
const bool add_to_backlog,
|
||||||
|
const bool addition)
|
||||||
{
|
{
|
||||||
// Validate to add metadata.
|
// Validate to add metadata.
|
||||||
task.validate (false);
|
task.validate (false);
|
||||||
|
|
||||||
// If the task already exists, it is a modification, else addition.
|
// If the task already exists, it is a modification, else addition.
|
||||||
Task original;
|
Task original;
|
||||||
if (get (task.get ("uuid"), original))
|
if (not addition && get (task.get ("uuid"), original))
|
||||||
{
|
{
|
||||||
// Update the task, wherever it is.
|
// Update the task, wherever it is.
|
||||||
if (!pending.modify_task (task))
|
if (!pending.modify_task (task))
|
||||||
|
@ -1179,18 +1179,21 @@ int TDB2::gc ()
|
||||||
// Allowed as an override, but not recommended.
|
// Allowed as an override, but not recommended.
|
||||||
if (context.config.getBoolean ("gc"))
|
if (context.config.getBoolean ("gc"))
|
||||||
{
|
{
|
||||||
std::vector <Task> pending_tasks = pending.get_tasks ();
|
std::vector <Task> pending_tasks = pending.get_tasks ();
|
||||||
|
|
||||||
|
// TODO Thread.
|
||||||
std::vector <Task> completed_tasks = completed.get_tasks ();
|
std::vector <Task> completed_tasks = completed.get_tasks ();
|
||||||
|
|
||||||
|
// TODO Assume pending < completed, therefore there is room here to process
|
||||||
|
// data before joining with the completed.data thread.
|
||||||
|
|
||||||
bool pending_changes = false;
|
bool pending_changes = false;
|
||||||
bool completed_changes = false;
|
bool completed_changes = false;
|
||||||
|
|
||||||
std::vector <Task> pending_tasks_after;
|
std::vector <Task> pending_tasks_after;
|
||||||
std::vector <Task> completed_tasks_after;
|
std::vector <Task> completed_tasks_after;
|
||||||
|
|
||||||
// Reduce unnecessary allocation/copies.
|
// Reduce unnecessary allocation/copies.
|
||||||
pending_tasks_after.reserve (pending_tasks.size ());
|
pending_tasks_after.reserve (pending_tasks.size ());
|
||||||
completed_tasks_after.reserve (completed_tasks.size ());
|
|
||||||
|
|
||||||
// Scan all pending tasks, looking for any that need to be relocated to
|
// Scan all pending tasks, looking for any that need to be relocated to
|
||||||
// completed, or need to be 'woken'.
|
// completed, or need to be 'woken'.
|
||||||
|
@ -1227,6 +1230,11 @@ int TDB2::gc ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO Join completed.data thread.
|
||||||
|
|
||||||
|
// Reduce unnecessary allocation/copies.
|
||||||
|
completed_tasks_after.reserve (completed_tasks.size ());
|
||||||
|
|
||||||
// Scan all completed tasks, looking for any that need to be relocated to
|
// Scan all completed tasks, looking for any that need to be relocated to
|
||||||
// pending.
|
// pending.
|
||||||
for (task = completed_tasks.begin ();
|
for (task = completed_tasks.begin ();
|
||||||
|
|
|
@ -128,7 +128,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void gather_changes ();
|
void gather_changes ();
|
||||||
void update (const std::string&, Task&, const bool);
|
void update (const std::string&, Task&, const bool, const bool addition = false);
|
||||||
bool verifyUniqueUUID (const std::string&);
|
bool verifyUniqueUUID (const std::string&);
|
||||||
void show_diff (const std::string&, const std::string&, const std::string&);
|
void show_diff (const std::string&, const std::string&, const std::string&);
|
||||||
void revert_undo (std::vector <std::string>&, std::string&, std::string&, std::string&, std::string&);
|
void revert_undo (std::vector <std::string>&, std::string&, std::string&, std::string&, std::string&);
|
||||||
|
|
81
src/Task.cpp
81
src/Task.cpp
|
@ -565,7 +565,6 @@ void Task::parse (const std::string& input)
|
||||||
nl.getQuoted ('"', value))
|
nl.getQuoted ('"', value))
|
||||||
{
|
{
|
||||||
legacyAttributeMap (name);
|
legacyAttributeMap (name);
|
||||||
legacyValueMap (name, value);
|
|
||||||
|
|
||||||
if (name.substr (0, 11) == "annotation_")
|
if (name.substr (0, 11) == "annotation_")
|
||||||
++annotation_count;
|
++annotation_count;
|
||||||
|
@ -586,8 +585,6 @@ void Task::parse (const std::string& input)
|
||||||
parseJSON (copy);
|
parseJSON (copy);
|
||||||
else
|
else
|
||||||
throw std::string (STRING_RECORD_NOT_FF4);
|
throw std::string (STRING_RECORD_NOT_FF4);
|
||||||
|
|
||||||
upgradeLegacyValues ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (const std::string&)
|
catch (const std::string&)
|
||||||
|
@ -719,8 +716,6 @@ void Task::parseJSON (const std::string& line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
upgradeLegacyValues ();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1105,6 +1100,7 @@ int Task::getTagCount () const
|
||||||
bool Task::hasTag (const std::string& tag) const
|
bool Task::hasTag (const std::string& tag) const
|
||||||
{
|
{
|
||||||
// Synthetic tags - dynamically generated, but do not occupy storage space.
|
// Synthetic tags - dynamically generated, but do not occupy storage space.
|
||||||
|
// Note: This list must match that in CmdInfo::execute.
|
||||||
if (tag == "BLOCKED") return is_blocked;
|
if (tag == "BLOCKED") return is_blocked;
|
||||||
if (tag == "UNBLOCKED") return !is_blocked;
|
if (tag == "UNBLOCKED") return !is_blocked;
|
||||||
if (tag == "BLOCKING") return is_blocking;
|
if (tag == "BLOCKING") return is_blocking;
|
||||||
|
@ -2214,78 +2210,3 @@ void Task::modify (modType type, bool text_required /* = false */)
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void Task::upgradeLegacyValues ()
|
|
||||||
{
|
|
||||||
// 2.4.0 Update recurrence values.
|
|
||||||
if (has ("recur"))
|
|
||||||
{
|
|
||||||
std::string value = get ("recur");
|
|
||||||
if (value != "")
|
|
||||||
{
|
|
||||||
std::string new_value = value;
|
|
||||||
upgradeLegacyValue (new_value);
|
|
||||||
|
|
||||||
if (new_value != value)
|
|
||||||
{
|
|
||||||
set ("recur", new_value);
|
|
||||||
context.debug (format ("Legacy upgrade: recur {1} --> {2}", value, new_value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2.4.0 Update UDA duration values.
|
|
||||||
Config::const_iterator name;
|
|
||||||
for (name = context.config.begin (); name != context.config.end (); ++name)
|
|
||||||
{
|
|
||||||
if (name->first.substr (0, 4) == "uda." &&
|
|
||||||
name->first.find (".type") != std::string::npos)
|
|
||||||
{
|
|
||||||
if (name->second == "duration")
|
|
||||||
{
|
|
||||||
std::string::size_type period = name->first.find ('.', 4);
|
|
||||||
if (period != std::string::npos)
|
|
||||||
{
|
|
||||||
std::string uda = name->first.substr (4, period - 4);
|
|
||||||
std::string value = get (uda);
|
|
||||||
std::string new_value = value;
|
|
||||||
upgradeLegacyValue (new_value);
|
|
||||||
|
|
||||||
if (new_value != value)
|
|
||||||
{
|
|
||||||
set ("recur", new_value);
|
|
||||||
context.debug (format ("Legacy upgrade: UDA {1}, {2} --> {3}", uda, value, new_value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
void Task::upgradeLegacyValue (std::string& value)
|
|
||||||
{
|
|
||||||
std::string::size_type len = value.length ();
|
|
||||||
std::string::size_type p;
|
|
||||||
|
|
||||||
if (value == "-") value = "0s";
|
|
||||||
else if ((p = value.find ("hr")) != std::string::npos && p == len - 2) value = value.substr (0, p) + "h";
|
|
||||||
else if ((p = value.find ("hrs")) != std::string::npos && p == len - 3) value = value.substr (0, p) + "h";
|
|
||||||
else if ((p = value.find ("mins")) != std::string::npos && p == len - 4) value = value.substr (0, p) + "min";
|
|
||||||
else if ((p = value.find ("mnths")) != std::string::npos && p == len - 5) value = value.substr (0, p) + "mo";
|
|
||||||
else if ((p = value.find ("mos")) != std::string::npos && p == len - 3) value = value.substr (0, p) + "mo";
|
|
||||||
else if ((p = value.find ("mth")) != std::string::npos && p == len - 3) value = value.substr (0, p) + "mo";
|
|
||||||
else if ((p = value.find ("mths")) != std::string::npos && p == len - 4) value = value.substr (0, p) + "mo";
|
|
||||||
else if ((p = value.find ("qrtrs")) != std::string::npos && p == len - 5) value = value.substr (0, p) + "q";
|
|
||||||
else if ((p = value.find ("qtr")) != std::string::npos && p == len - 3) value = value.substr (0, p) + "q";
|
|
||||||
else if ((p = value.find ("qtrs")) != std::string::npos && p == len - 4) value = value.substr (0, p) + "q";
|
|
||||||
else if ((p = value.find ("sec")) != std::string::npos && p == len - 3) value = value.substr (0, p) + "s";
|
|
||||||
else if ((p = value.find ("secs")) != std::string::npos && p == len - 4) value = value.substr (0, p) + "s";
|
|
||||||
else if ((p = value.find ("wk")) != std::string::npos && p == len - 2) value = value.substr (0, p) + "w";
|
|
||||||
else if ((p = value.find ("wks")) != std::string::npos && p == len - 3) value = value.substr (0, p) + "w";
|
|
||||||
else if ((p = value.find ("yr")) != std::string::npos && p == len - 2) value = value.substr (0, p) + "y";
|
|
||||||
else if ((p = value.find ("yrs")) != std::string::npos && p == len - 3) value = value.substr (0, p) + "y";
|
|
||||||
|
|
||||||
// It is not an error to have a non-legacy value.
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
|
@ -154,7 +154,6 @@ public:
|
||||||
|
|
||||||
enum modType {modReplace, modPrepend, modAppend, modAnnotate};
|
enum modType {modReplace, modPrepend, modAppend, modAnnotate};
|
||||||
void modify (modType, bool text_required = false);
|
void modify (modType, bool text_required = false);
|
||||||
void upgradeLegacyValues ();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int determineVersion (const std::string&);
|
int determineVersion (const std::string&);
|
||||||
|
@ -163,7 +162,6 @@ private:
|
||||||
void validate_before (const std::string&, const std::string&);
|
void validate_before (const std::string&, const std::string&);
|
||||||
const std::string encode (const std::string&) const;
|
const std::string encode (const std::string&) const;
|
||||||
const std::string decode (const std::string&) const;
|
const std::string decode (const std::string&) const;
|
||||||
void upgradeLegacyValue (std::string&);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
float urgency_priority () const;
|
float urgency_priority () const;
|
||||||
|
|
|
@ -314,6 +314,40 @@ int CmdInfo::execute (std::string& output)
|
||||||
view.set (row, 1, allTags);
|
view.set (row, 1, allTags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Virtual tags.
|
||||||
|
{
|
||||||
|
// Note: This list must match that in Task::hasTag.
|
||||||
|
std::string virtualTags = "";
|
||||||
|
if (task->hasTag ("ACTIVE")) virtualTags += "ACTIVE ";
|
||||||
|
if (task->hasTag ("ANNOTATED")) virtualTags += "ANNOTATED ";
|
||||||
|
if (task->hasTag ("BLOCKED")) virtualTags += "BLOCKED ";
|
||||||
|
if (task->hasTag ("BLOCKING")) virtualTags += "BLOCKING ";
|
||||||
|
if (task->hasTag ("CHILD")) virtualTags += "CHILD ";
|
||||||
|
if (task->hasTag ("COMPLETED")) virtualTags += "COMPLETED ";
|
||||||
|
if (task->hasTag ("DELETED")) virtualTags += "DELETED ";
|
||||||
|
if (task->hasTag ("DUE")) virtualTags += "DUE ";
|
||||||
|
if (task->hasTag ("DUETODAY")) virtualTags += "DUETODAY ";
|
||||||
|
if (task->hasTag ("MONTH")) virtualTags += "MONTH ";
|
||||||
|
if (task->hasTag ("OVERDUE")) virtualTags += "OVERDUE ";
|
||||||
|
if (task->hasTag ("PARENT")) virtualTags += "PARENT ";
|
||||||
|
if (task->hasTag ("PENDING")) virtualTags += "PENDING ";
|
||||||
|
if (task->hasTag ("READY")) virtualTags += "READY ";
|
||||||
|
if (task->hasTag ("SCHEDULED")) virtualTags += "SCHEDULED ";
|
||||||
|
if (task->hasTag ("TAGGED")) virtualTags += "TAGGED ";
|
||||||
|
if (task->hasTag ("TODAY")) virtualTags += "TODAY ";
|
||||||
|
if (task->hasTag ("TOMORROW")) virtualTags += "TOMORROW ";
|
||||||
|
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 ";
|
||||||
|
|
||||||
|
row = view.addRow ();
|
||||||
|
view.set (row, 0, STRING_CMD_INFO_VIRTUAL_TAGS);
|
||||||
|
view.set (row, 1, virtualTags);
|
||||||
|
}
|
||||||
|
|
||||||
// uuid
|
// uuid
|
||||||
row = view.addRow ();
|
row = view.addRow ();
|
||||||
view.set (row, 0, STRING_COLUMN_LABEL_UUID);
|
view.set (row, 0, STRING_COLUMN_LABEL_UUID);
|
||||||
|
|
|
@ -53,6 +53,9 @@ int CmdProjects::execute (std::string& output)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
|
// Enforce the garbage collector to show correct task counts
|
||||||
|
context.tdb2.gc ();
|
||||||
|
|
||||||
// Get all the tasks.
|
// Get all the tasks.
|
||||||
handleRecurrence ();
|
handleRecurrence ();
|
||||||
std::vector <Task> tasks = context.tdb2.pending.get_tasks ();
|
std::vector <Task> tasks = context.tdb2.pending.get_tasks ();
|
||||||
|
@ -89,8 +92,16 @@ int CmdProjects::execute (std::string& output)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Increase the count for the project the task belongs to and all
|
||||||
|
// its super-projects
|
||||||
project = task->get ("project");
|
project = task->get ("project");
|
||||||
unique[project] += 1;
|
|
||||||
|
std::vector <std::string> projects = extractParents (project);
|
||||||
|
projects.push_back (project);
|
||||||
|
|
||||||
|
std::vector <std::string>::const_iterator parent;
|
||||||
|
for (parent = projects.begin (); parent != projects.end (); ++parent)
|
||||||
|
unique[*parent] += 1;
|
||||||
|
|
||||||
if (project == "")
|
if (project == "")
|
||||||
no_project = true;
|
no_project = true;
|
||||||
|
|
|
@ -92,27 +92,34 @@ int CmdSummary::execute (std::string& output)
|
||||||
for (task = filtered.begin (); task != filtered.end (); ++task)
|
for (task = filtered.begin (); task != filtered.end (); ++task)
|
||||||
{
|
{
|
||||||
std::string project = task->get ("project");
|
std::string project = task->get ("project");
|
||||||
++counter[project];
|
std::vector <std::string> projects = extractParents (project);
|
||||||
|
projects.push_back (project);
|
||||||
|
|
||||||
|
std::vector <std::string>::const_iterator parent;
|
||||||
|
for (parent = projects.begin (); parent != projects.end (); ++parent)
|
||||||
|
++counter[*parent];
|
||||||
|
|
||||||
if (task->getStatus () == Task::pending ||
|
if (task->getStatus () == Task::pending ||
|
||||||
task->getStatus () == Task::waiting)
|
task->getStatus () == Task::waiting)
|
||||||
{
|
for (parent = projects.begin (); parent != projects.end (); ++parent)
|
||||||
++countPending[project];
|
{
|
||||||
|
++countPending[*parent];
|
||||||
|
|
||||||
time_t entry = strtol (task->get ("entry").c_str (), NULL, 10);
|
time_t entry = strtol (task->get ("entry").c_str (), NULL, 10);
|
||||||
if (entry)
|
if (entry)
|
||||||
sumEntry[project] = sumEntry[project] + (double) (now - entry);
|
sumEntry[*parent] = sumEntry[*parent] + (double) (now - entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (task->getStatus () == Task::completed)
|
else if (task->getStatus () == Task::completed)
|
||||||
{
|
for (parent = projects.begin (); parent != projects.end (); ++parent)
|
||||||
++countCompleted[project];
|
{
|
||||||
|
++countCompleted[*parent];
|
||||||
|
|
||||||
time_t entry = strtol (task->get ("entry").c_str (), NULL, 10);
|
time_t entry = strtol (task->get ("entry").c_str (), NULL, 10);
|
||||||
time_t end = strtol (task->get ("end").c_str (), NULL, 10);
|
time_t end = strtol (task->get ("end").c_str (), NULL, 10);
|
||||||
if (entry && end)
|
if (entry && end)
|
||||||
sumEntry[project] = sumEntry[project] + (double) (end - entry);
|
sumEntry[*parent] = sumEntry[*parent] + (double) (end - entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -296,6 +296,7 @@
|
||||||
#define STRING_CMD_INFO_UNTIL "Bis"
|
#define STRING_CMD_INFO_UNTIL "Bis"
|
||||||
#define STRING_CMD_INFO_MODIFICATION "Änderung"
|
#define STRING_CMD_INFO_MODIFICATION "Änderung"
|
||||||
#define STRING_CMD_INFO_MODIFIED "Letzte Änderung"
|
#define STRING_CMD_INFO_MODIFIED "Letzte Änderung"
|
||||||
|
#define STRING_CMD_INFO_VIRTUAL_TAGS "Virtual tags"
|
||||||
#define STRING_CMD_UNDO_USAGE "Macht die letzte Änderung an einer Aufgabe Rückgängig"
|
#define STRING_CMD_UNDO_USAGE "Macht die letzte Änderung an einer Aufgabe Rückgängig"
|
||||||
#define STRING_CMD_UNDO_MODS "Der undo-Befehl erlaubt keine weitere Aufgaben-Änderung."
|
#define STRING_CMD_UNDO_MODS "Der undo-Befehl erlaubt keine weitere Aufgaben-Änderung."
|
||||||
#define STRING_CMD_STATS_USAGE "Zeigt Statistiken zur Aufgaben-Datenbank"
|
#define STRING_CMD_STATS_USAGE "Zeigt Statistiken zur Aufgaben-Datenbank"
|
||||||
|
|
|
@ -296,6 +296,7 @@
|
||||||
#define STRING_CMD_INFO_UNTIL "Until"
|
#define STRING_CMD_INFO_UNTIL "Until"
|
||||||
#define STRING_CMD_INFO_MODIFICATION "Modification"
|
#define STRING_CMD_INFO_MODIFICATION "Modification"
|
||||||
#define STRING_CMD_INFO_MODIFIED "Last modified"
|
#define STRING_CMD_INFO_MODIFIED "Last modified"
|
||||||
|
#define STRING_CMD_INFO_VIRTUAL_TAGS "Virtual tags"
|
||||||
#define STRING_CMD_UNDO_USAGE "Reverts the most recent change to a task"
|
#define STRING_CMD_UNDO_USAGE "Reverts the most recent change to a task"
|
||||||
#define STRING_CMD_UNDO_MODS "The undo command does not allow further task modification."
|
#define STRING_CMD_UNDO_MODS "The undo command does not allow further task modification."
|
||||||
#define STRING_CMD_STATS_USAGE "Shows task database statistics"
|
#define STRING_CMD_STATS_USAGE "Shows task database statistics"
|
||||||
|
|
|
@ -296,6 +296,7 @@
|
||||||
#define STRING_CMD_INFO_UNTIL "Ĝis"
|
#define STRING_CMD_INFO_UNTIL "Ĝis"
|
||||||
#define STRING_CMD_INFO_MODIFICATION "Modifado"
|
#define STRING_CMD_INFO_MODIFICATION "Modifado"
|
||||||
#define STRING_CMD_INFO_MODIFIED "Modifado lasta"
|
#define STRING_CMD_INFO_MODIFIED "Modifado lasta"
|
||||||
|
#define STRING_CMD_INFO_VIRTUAL_TAGS "Virtual tags"
|
||||||
#define STRING_CMD_UNDO_USAGE "Malfaras la plej malfrua modifado al tasko"
|
#define STRING_CMD_UNDO_USAGE "Malfaras la plej malfrua modifado al tasko"
|
||||||
#define STRING_CMD_UNDO_MODS "La komando 'undo' ne permesos, ke oni pli modifus la taskojn."
|
#define STRING_CMD_UNDO_MODS "La komando 'undo' ne permesos, ke oni pli modifus la taskojn."
|
||||||
#define STRING_CMD_STATS_USAGE "Montras statistikon de la taska datumbazo"
|
#define STRING_CMD_STATS_USAGE "Montras statistikon de la taska datumbazo"
|
||||||
|
|
|
@ -298,6 +298,7 @@
|
||||||
#define STRING_CMD_INFO_UNTIL "Hasta"
|
#define STRING_CMD_INFO_UNTIL "Hasta"
|
||||||
#define STRING_CMD_INFO_MODIFICATION "Modificación"
|
#define STRING_CMD_INFO_MODIFICATION "Modificación"
|
||||||
#define STRING_CMD_INFO_MODIFIED "Modificada por última vez"
|
#define STRING_CMD_INFO_MODIFIED "Modificada por última vez"
|
||||||
|
#define STRING_CMD_INFO_VIRTUAL_TAGS "Virtual tags"
|
||||||
#define STRING_CMD_UNDO_USAGE "Revierte el cambio más reciente a una tarea"
|
#define STRING_CMD_UNDO_USAGE "Revierte el cambio más reciente a una tarea"
|
||||||
#define STRING_CMD_UNDO_MODS "El comando undo no permite más modificación a la tarea."
|
#define STRING_CMD_UNDO_MODS "El comando undo no permite más modificación a la tarea."
|
||||||
#define STRING_CMD_STATS_USAGE "Muestra estadísticas de la base de datos de tareas"
|
#define STRING_CMD_STATS_USAGE "Muestra estadísticas de la base de datos de tareas"
|
||||||
|
|
|
@ -296,6 +296,7 @@
|
||||||
#define STRING_CMD_INFO_UNTIL "Jusqu'au"
|
#define STRING_CMD_INFO_UNTIL "Jusqu'au"
|
||||||
#define STRING_CMD_INFO_MODIFICATION "Modification"
|
#define STRING_CMD_INFO_MODIFICATION "Modification"
|
||||||
#define STRING_CMD_INFO_MODIFIED "Dernier modifié"
|
#define STRING_CMD_INFO_MODIFIED "Dernier modifié"
|
||||||
|
#define STRING_CMD_INFO_VIRTUAL_TAGS "Virtual tags"
|
||||||
#define STRING_CMD_UNDO_USAGE "Annule les changements les plus récents sur une tâche"
|
#define STRING_CMD_UNDO_USAGE "Annule les changements les plus récents sur une tâche"
|
||||||
#define STRING_CMD_UNDO_MODS "The undo command does not allow further task modification."
|
#define STRING_CMD_UNDO_MODS "The undo command does not allow further task modification."
|
||||||
#define STRING_CMD_STATS_USAGE "Affiche les statistiques de la base de donnée"
|
#define STRING_CMD_STATS_USAGE "Affiche les statistiques de la base de donnée"
|
||||||
|
|
|
@ -295,6 +295,7 @@
|
||||||
#define STRING_CMD_INFO_UNTIL "Fino a"
|
#define STRING_CMD_INFO_UNTIL "Fino a"
|
||||||
#define STRING_CMD_INFO_MODIFICATION "Modifica"
|
#define STRING_CMD_INFO_MODIFICATION "Modifica"
|
||||||
#define STRING_CMD_INFO_MODIFIED "Ultima modifica"
|
#define STRING_CMD_INFO_MODIFIED "Ultima modifica"
|
||||||
|
#define STRING_CMD_INFO_VIRTUAL_TAGS "Virtual tags"
|
||||||
#define STRING_CMD_UNDO_USAGE "Ritorna alla più recente modifica di un task"
|
#define STRING_CMD_UNDO_USAGE "Ritorna alla più recente modifica di un task"
|
||||||
#define STRING_CMD_UNDO_MODS "Il comando undo non ammette ulteriori modifiche al task."
|
#define STRING_CMD_UNDO_MODS "Il comando undo non ammette ulteriori modifiche al task."
|
||||||
#define STRING_CMD_STATS_USAGE "Mostra le statistiche sul task"
|
#define STRING_CMD_STATS_USAGE "Mostra le statistiche sul task"
|
||||||
|
|
|
@ -296,6 +296,7 @@
|
||||||
#define STRING_CMD_INFO_UNTIL "Do"
|
#define STRING_CMD_INFO_UNTIL "Do"
|
||||||
#define STRING_CMD_INFO_MODIFICATION "Modyfikacja"
|
#define STRING_CMD_INFO_MODIFICATION "Modyfikacja"
|
||||||
#define STRING_CMD_INFO_MODIFIED "Ostatnio zmodyfikowane"
|
#define STRING_CMD_INFO_MODIFIED "Ostatnio zmodyfikowane"
|
||||||
|
#define STRING_CMD_INFO_VIRTUAL_TAGS "Virtual tags"
|
||||||
#define STRING_CMD_UNDO_USAGE "Odwraca ostatnią zmianę w zadaniu"
|
#define STRING_CMD_UNDO_USAGE "Odwraca ostatnią zmianę w zadaniu"
|
||||||
#define STRING_CMD_UNDO_MODS "Polecenie cofnij nie pozwala na późniejsze modyfikacje zadania."
|
#define STRING_CMD_UNDO_MODS "Polecenie cofnij nie pozwala na późniejsze modyfikacje zadania."
|
||||||
#define STRING_CMD_STATS_USAGE "Pokazuje statystyki bazy danych zadań"
|
#define STRING_CMD_STATS_USAGE "Pokazuje statystyki bazy danych zadań"
|
||||||
|
|
|
@ -296,6 +296,7 @@
|
||||||
#define STRING_CMD_INFO_UNTIL "Até"
|
#define STRING_CMD_INFO_UNTIL "Até"
|
||||||
#define STRING_CMD_INFO_MODIFICATION "Modificação"
|
#define STRING_CMD_INFO_MODIFICATION "Modificação"
|
||||||
#define STRING_CMD_INFO_MODIFIED "Última modificação"
|
#define STRING_CMD_INFO_MODIFIED "Última modificação"
|
||||||
|
#define STRING_CMD_INFO_VIRTUAL_TAGS "Virtual tags"
|
||||||
#define STRING_CMD_UNDO_USAGE "Reverte a mais recente modificação a uma tarefa"
|
#define STRING_CMD_UNDO_USAGE "Reverte a mais recente modificação a uma tarefa"
|
||||||
#define STRING_CMD_UNDO_MODS "O comando undo não permite outras modificações simultâneas."
|
#define STRING_CMD_UNDO_MODS "O comando undo não permite outras modificações simultâneas."
|
||||||
#define STRING_CMD_STATS_USAGE "Exibe estatísticas da base de dados de tarefas"
|
#define STRING_CMD_STATS_USAGE "Exibe estatísticas da base de dados de tarefas"
|
||||||
|
|
|
@ -166,48 +166,3 @@ void legacyAttributeMap (std::string& name)
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// TODO Is this needed, given Task::upgradeLegacyValues?
|
|
||||||
void legacyValueMap (const std::string& name, std::string& value)
|
|
||||||
{
|
|
||||||
// 2014-07-03: One-time initialization value mapping.
|
|
||||||
static std::map <std::string, std::string> mapping;
|
|
||||||
if (mapping.size () == 0)
|
|
||||||
{
|
|
||||||
mapping["hrs"] = "hours";
|
|
||||||
mapping["hr"] = "hours";
|
|
||||||
mapping["mins"] = "minutes";
|
|
||||||
mapping["mnths"] = "months";
|
|
||||||
mapping["mths"] = "months";
|
|
||||||
mapping["mth"] = "months";
|
|
||||||
mapping["mos"] = "months";
|
|
||||||
mapping["m"] = "months"; // ?
|
|
||||||
mapping["qrtrs"] = "quarters";
|
|
||||||
mapping["qtrs"] = "quarters";
|
|
||||||
mapping["qtr"] = "quarters";
|
|
||||||
mapping["secs"] = "seconds";
|
|
||||||
mapping["sec"] = "seconds";
|
|
||||||
mapping["s"] = "seconds"; // ?
|
|
||||||
mapping["wks"] = "weeks";
|
|
||||||
mapping["wk"] = "weeks";
|
|
||||||
mapping["yrs"] = "years";
|
|
||||||
mapping["yr"] = "years";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name == "recur")
|
|
||||||
{
|
|
||||||
std::size_t letter = value.find_first_not_of ("0123456789.");
|
|
||||||
if (letter == std::string::npos)
|
|
||||||
letter = 0;
|
|
||||||
|
|
||||||
std::map <std::string, std::string>::iterator i = mapping.find (value.substr (letter));
|
|
||||||
if (i != mapping.end ())
|
|
||||||
{
|
|
||||||
if (letter)
|
|
||||||
value = value.substr (0, letter) + i->second;
|
|
||||||
else
|
|
||||||
value = i->second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
|
@ -86,7 +86,6 @@ std::string legacyCheckForDeprecatedColor ();
|
||||||
std::string legacyCheckForDeprecatedVariables ();
|
std::string legacyCheckForDeprecatedVariables ();
|
||||||
std::string legacyCheckForDeprecatedColumns ();
|
std::string legacyCheckForDeprecatedColumns ();
|
||||||
void legacyAttributeMap (std::string&);
|
void legacyAttributeMap (std::string&);
|
||||||
void legacyValueMap (const std::string&, std::string&);
|
|
||||||
|
|
||||||
// list template
|
// list template
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -84,78 +84,26 @@ qx{../src/task rc:$rc add testing project:.myProject. 2>&1 >/dev/null};
|
||||||
$output = qx{../src/task rc:$rc projects 2>&1};
|
$output = qx{../src/task rc:$rc projects 2>&1};
|
||||||
my @lines = split ('\n',$output);
|
my @lines = split ('\n',$output);
|
||||||
|
|
||||||
# It's easier to make a pattern for the end than the beginning because priority
|
my ($project_name_column) = $lines[4] =~ /^(\s*\S+)/;
|
||||||
# counts are more predictable than project names.
|
like ($project_name_column, qr/^\.myProject$/, "$ut: '.myProject' not indented");
|
||||||
my $project_name_column;
|
|
||||||
if ($lines[4] =~ s/\d+$//)
|
|
||||||
{
|
|
||||||
$project_name_column = $lines[4];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$project_name_column = "error";
|
|
||||||
}
|
|
||||||
like ($project_name_column, qr/^\.myProject\s*$/, "$ut: '.myProject' not indented");
|
|
||||||
|
|
||||||
if ($lines[5] =~ s/\d+$//)
|
($project_name_column) = $lines[5] =~ /^(\s*\S+)/;
|
||||||
{
|
like ($project_name_column, qr/^\.myProject\.$/, "$ut: '.myProject.' not indented");
|
||||||
$project_name_column = $lines[5];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$project_name_column = "error";
|
|
||||||
}
|
|
||||||
like ($project_name_column, qr/^\.myProject\.\s*$/, "$ut: '.myProject.' not indented");
|
|
||||||
|
|
||||||
if ($lines[6] =~ s/\d+$//)
|
($project_name_column) = $lines[6] =~ /^(\s*\S+)/;
|
||||||
{
|
like ($project_name_column, qr/^abstractParent$/, "$ut: abstract parent not indented");
|
||||||
$project_name_column = "error";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$project_name_column = $lines[6];
|
|
||||||
}
|
|
||||||
like ($project_name_column, qr/^abstractParent\s*$/, "$ut: abstract parent not indented and no priority columns");
|
|
||||||
|
|
||||||
if ($lines[7] =~ s/\d+$//)
|
($project_name_column) = $lines[7] =~ /^(\s*\S+)/;
|
||||||
{
|
like ($project_name_column, qr/^ kid$/, "$ut: child indented and without parent name");
|
||||||
$project_name_column = $lines[7];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$project_name_column = "error";
|
|
||||||
}
|
|
||||||
like ($project_name_column, qr/^ kid\s*$/, "$ut: child indented and without parent name");
|
|
||||||
|
|
||||||
if ($lines[8] =~ s/\d+$//)
|
($project_name_column) = $lines[8] =~ /^(\s*\S+)/;
|
||||||
{
|
like ($project_name_column, qr/^existingParent$/, "$ut: existing parent not indented");
|
||||||
$project_name_column = $lines[8];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$project_name_column = "error";
|
|
||||||
}
|
|
||||||
like ($project_name_column, qr/^existingParent\s*$/, "$ut: existing parent not indented and has priority columns");
|
|
||||||
|
|
||||||
if ($lines[9] =~ s/\d+$//)
|
($project_name_column) = $lines[9] =~ /^(\s*\S+)/;
|
||||||
{
|
like ($project_name_column, qr/^ child$/, "$ut: child of existing parent indented and without parent name");
|
||||||
$project_name_column = $lines[9];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$project_name_column = "error";
|
|
||||||
}
|
|
||||||
like ($project_name_column, qr/^ child\s*$/, "$ut: child of existing parent indented and without parent name");
|
|
||||||
|
|
||||||
if ($lines[12] =~ s/\d+$//)
|
($project_name_column) = $lines[12] =~ /^(\s*\S+)/;
|
||||||
{
|
like ($project_name_column, qr/^myProject\.$/, "$ut: 'myProject.' not indented");
|
||||||
$project_name_column = $lines[12];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$project_name_column = "error";
|
|
||||||
}
|
|
||||||
like ($project_name_column, qr/^myProject\.\s*$/, "$ut: 'myProject.' not indented");
|
|
||||||
|
|
||||||
# Cleanup.
|
# Cleanup.
|
||||||
unlink qw(pending.data completed.data undo.data backlog.data), $rc;
|
unlink qw(pending.data completed.data undo.data backlog.data), $rc;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue