From 9b3f9ee4ffcc4296dc3756ac3afcd9ddcb399ae7 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 10 Jul 2011 01:48:21 -0400 Subject: [PATCH] Feature #514 - Added feature #514, which allows duplication of tasks based on a generalized filter, rather than just IDs (thanks to Peter De Poorter). --- ChangeLog | 4 ++ NEWS | 2 + src/commands/CmdDuplicate.cpp | 78 ++++++++++++++--------------------- 3 files changed, 38 insertions(+), 46 deletions(-) diff --git a/ChangeLog b/ChangeLog index fb7199c8d..0d23a5770 100644 --- a/ChangeLog +++ b/ChangeLog @@ -43,6 +43,8 @@ + Added feature #330, which supports the 'inverse' color attribute. + Added feature #340, which implements new color rules 'color.completed' and 'color.deleted'. + + Added feature #422, which allows task modifications during 'done', 'delete', + 'start' and 'stop' commands. + Added feature #479, which enables filtering for the 'calendar' command. + Added feature #496, which allows rc.default.command to be supplemented with a filter, so that 'task project:Home' applies the project filter to the @@ -50,6 +52,8 @@ + Added feature #507, which provides an alternative mechanism for inverting attribute modifiers, in the form of new algebraic filters (thanks to Michelle Crane). + + Added feature #514, which allows duplication of tasks based on a generalized + filter, rather than just IDs (thanks to Peter De Poorter). + Added feature #523 & #659, adding 'status' as a reportable field (thanks to Peter De Poorter and Bryce Harrington). + Added feature #545, #610, #611, #646, which support complex aliases. diff --git a/NEWS b/NEWS index 4e52919b8..e54fa05bf 100644 --- a/NEWS +++ b/NEWS @@ -21,6 +21,8 @@ New Features in taskwarrior 2.0.0 - New 'reports' command that lists reports and their descriptions. - New complex aliases. - Filtering now available on most read-only commands. + - The done, delete, start and stop commands now allow modification to the + task and annotations. Please refer to the ChangeLog file for full details. There are too many to list here. diff --git a/src/commands/CmdDuplicate.cpp b/src/commands/CmdDuplicate.cpp index 78a09ec00..b3baf4ebf 100644 --- a/src/commands/CmdDuplicate.cpp +++ b/src/commands/CmdDuplicate.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -37,9 +38,9 @@ extern Context context; //////////////////////////////////////////////////////////////////////////////// CmdDuplicate::CmdDuplicate () { - _keyword = "dulicate"; - _usage = "task duplicate ID [tags] [attrs] [desc...]"; - _description = "Duplicates the specified task, and allows modifications."; + _keyword = "duplicate"; + _usage = "task duplicate []"; + _description = "Duplicates the specified tasks, and allows modifications."; _read_only = false; _displays_id = false; } @@ -48,31 +49,35 @@ CmdDuplicate::CmdDuplicate () int CmdDuplicate::execute (std::string& output) { int rc = 0; -/* - std::stringstream out; int count = 0; + std::stringstream out; std::vector tasks; context.tdb.lock (context.config.getBoolean ("locking")); - Filter filter; - context.tdb.loadPending (tasks, filter); + context.tdb.loadPending (tasks); - // Filter sequence. - context.filter.applySequence (tasks, context.sequence); - if (tasks.size () == 0) + // Apply filter. + std::vector filtered; + filter (tasks, filtered); + + if (filtered.size () == 0) { - context.footnote ("No tasks specified."); + context.footnote (STRING_FEEDBACK_NO_TASKS_SP); return 1; } + // Apply the command line modifications to the completed task. + Arguments modifications = context.args.extract_modifications (); + std::vector ::iterator task; - for (task = tasks.begin (); task != tasks.end (); ++task) + for (task = filtered.begin (); task != filtered.end (); ++task) { Task dup (*task); - dup.set ("uuid", uuid ()); // Needs a new UUID. - dup.setStatus (Task::pending); - dup.remove ("start"); // Does not inherit start date. - dup.remove ("end"); // Does not inherit end date. + dup.set ("uuid", uuid ()); // Needs a new UUID. + dup.setStatus (Task::pending); // Does not inherit status. + dup.remove ("start"); // Does not inherit start date. + dup.remove ("end"); // Does not inherit end date. + dup.remove ("entry"); // Does not inherit entry date. // Recurring tasks are duplicated and downgraded to regular tasks. if (task->getStatus () == Task::recurring) @@ -85,24 +90,17 @@ int CmdDuplicate::execute (std::string& output) out << "Note: task " << task->id - << " was a recurring task. The new task is not.\n"; + << " was a recurring task. The duplicate task is not.\n"; } - // Apply deltas. - deltaDescription (dup); - deltaTags (dup); - deltaAttributes (dup); - deltaSubstitutions (dup); - - // A New task needs a new entry time. - char entryTime[16]; - sprintf (entryTime, "%u", (unsigned int) time (NULL)); - dup.set ("entry", entryTime); + modify_task_annotate (dup, modifications); + apply_defaults (dup); // Only allow valid tasks. dup.validate (); context.tdb.add (dup); + ++count; if (context.config.getBoolean ("echo.command")) out << "Duplicated " @@ -111,32 +109,20 @@ int CmdDuplicate::execute (std::string& output) << task->get ("description") << "'.\n"; + // TODO This should be a call in to feedback.cpp. + out << format (STRING_CMD_ADD_FEEDBACK, context.tdb.nextId ()) + "\n"; + context.footnote (onProjectChange (dup)); - - ++count; } - if (tasks.size () == 0) - { - out << "No matches.\n"; - rc = 1; - } - else if (context.config.getBoolean ("echo.command")) - { -#ifdef FEATURE_NEW_ID - // All this, just for an id number. - std::vector all; - Filter none; - context.tdb.loadPending (all, none); - out << "Created task " << context.tdb.nextId () << ".\n"; -#endif - } + if (count) + context.tdb.commit (); - context.tdb.commit (); context.tdb.unlock (); + // TODO Add count summary, like the 'done' command. + output = out.str (); -*/ return rc; }