diff --git a/src/Cmd.cpp b/src/Cmd.cpp index 461346beb..d0858e01b 100644 --- a/src/Cmd.cpp +++ b/src/Cmd.cpp @@ -133,7 +133,6 @@ void Cmd::load () commands.push_back ("calendar"); commands.push_back ("delete"); commands.push_back ("done"); - commands.push_back ("duplicate"); commands.push_back ("import"); commands.push_back ("summary"); commands.push_back ("timesheet"); @@ -215,7 +214,6 @@ bool Cmd::isWriteCommand () if (command == "merge" || command == "delete" || command == "done" || - command == "duplicate" || command == "import" || command == "pull" || command == "undo") diff --git a/src/Context.cpp b/src/Context.cpp index 3bf9269d5..70784891e 100644 --- a/src/Context.cpp +++ b/src/Context.cpp @@ -255,7 +255,6 @@ int Context::dispatch (std::string &out) else if (cmd.command == "done") { rc = handleDone (out); } else if (cmd.command == "delete") { rc = handleDelete (out); } else if (cmd.command == "import") { rc = handleImport (out); } - else if (cmd.command == "duplicate") { rc = handleDuplicate (out); } else if (cmd.command == "undo") { handleUndo ( ); } else if (cmd.command == "merge") { tdb.gc (); handleMerge (out); } diff --git a/src/command.cpp b/src/command.cpp index 5088311c4..80ee1ed72 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -659,99 +659,6 @@ int handleModify (std::string& outs) return 0; } -//////////////////////////////////////////////////////////////////////////////// -int handleDuplicate (std::string& outs) -{ - int rc = 0; - std::stringstream out; - int count = 0; - - std::vector tasks; - context.tdb.lock (context.config.getBoolean ("locking")); - Filter filter; - context.tdb.loadPending (tasks, filter); - - // Filter sequence. - context.filter.applySequence (tasks, context.sequence); - if (tasks.size () == 0) - { - std::cout << "No tasks specified.\n"; - return 1; - } - - foreach (task, tasks) - { - 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. - - // Recurring tasks are duplicated and downgraded to regular tasks. - if (task->getStatus () == Task::recurring) - { - dup.remove ("parent"); - dup.remove ("recur"); - dup.remove ("until"); - dup.remove ("imak"); - dup.remove ("imask"); - - out << "Note: task " - << task->id - << " was a recurring task. The new 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); - - // Only allow valid tasks. - dup.validate (); - - context.tdb.add (dup); - - if (context.config.getBoolean ("echo.command")) - out << "Duplicated " - << task->id - << " '" - << task->get ("description") - << "'.\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 - } - - context.tdb.commit (); - context.tdb.unlock (); - - outs = out.str (); - return rc; -} - //////////////////////////////////////////////////////////////////////////////// int deltaAppend (Task& task) { diff --git a/src/commands/CMakeLists.txt b/src/commands/CMakeLists.txt index b25cd516f..ffb95b52e 100644 --- a/src/commands/CMakeLists.txt +++ b/src/commands/CMakeLists.txt @@ -17,6 +17,7 @@ set (commands_SRCS Command.cpp Command.h CmdCustom.cpp CmdCustom.h CmdDenotate.cpp CmdDenotate.h CmdDiagnostics.cpp CmdDiagnostics.h + CmdDuplicate.cpp CmdDuplicate.h CmdEdit.cpp CmdEdit.h CmdExec.cpp CmdExec.h CmdHelp.cpp CmdHelp.h diff --git a/src/commands/CmdDuplicate.cpp b/src/commands/CmdDuplicate.cpp new file mode 100644 index 000000000..7e2b64186 --- /dev/null +++ b/src/commands/CmdDuplicate.cpp @@ -0,0 +1,141 @@ +//////////////////////////////////////////////////////////////////////////////// +// taskwarrior - a command line task list manager. +// +// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez. +// All rights reserved. +// +// This program is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free Software +// Foundation; either version 2 of the License, or (at your option) any later +// version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +// details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the +// +// Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, +// Boston, MA +// 02110-1301 +// USA +// +//////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include + +extern Context context; + +//////////////////////////////////////////////////////////////////////////////// +CmdDuplicate::CmdDuplicate () +{ + _keyword = "dulicate"; + _usage = "task duplicate ID [tags] [attrs] [desc...]"; + _description = "Duplicates the specified task, and allows modifications."; + _read_only = false; + _displays_id = false; +} + +//////////////////////////////////////////////////////////////////////////////// +int CmdDuplicate::execute (const std::string&, std::string& output) +{ + int rc = 0; + std::stringstream out; + int count = 0; + + std::vector tasks; + context.tdb.lock (context.config.getBoolean ("locking")); + Filter filter; + context.tdb.loadPending (tasks, filter); + + // Filter sequence. + context.filter.applySequence (tasks, context.sequence); + if (tasks.size () == 0) + { + context.footnote ("No tasks specified."); + return 1; + } + + std::vector ::iterator task; + for (task = tasks.begin (); task != tasks.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. + + // Recurring tasks are duplicated and downgraded to regular tasks. + if (task->getStatus () == Task::recurring) + { + dup.remove ("parent"); + dup.remove ("recur"); + dup.remove ("until"); + dup.remove ("imak"); + dup.remove ("imask"); + + out << "Note: task " + << task->id + << " was a recurring task. The new 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); + + // Only allow valid tasks. + dup.validate (); + + context.tdb.add (dup); + + if (context.config.getBoolean ("echo.command")) + out << "Duplicated " + << task->id + << " '" + << task->get ("description") + << "'.\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 + } + + context.tdb.commit (); + context.tdb.unlock (); + + output = out.str (); + return rc; +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/commands/CmdDuplicate.h b/src/commands/CmdDuplicate.h new file mode 100644 index 000000000..662a2855c --- /dev/null +++ b/src/commands/CmdDuplicate.h @@ -0,0 +1,42 @@ +//////////////////////////////////////////////////////////////////////////////// +// taskwarrior - a command line task list manager. +// +// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez. +// All rights reserved. +// +// This program is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free Software +// Foundation; either version 2 of the License, or (at your option) any later +// version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +// details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the +// +// Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, +// Boston, MA +// 02110-1301 +// USA +// +//////////////////////////////////////////////////////////////////////////////// +#ifndef INCLUDED_CMDDUPLICATE +#define INCLUDED_CMDDUPLICATE +#define L10N // Localization complete. + +#include +#include + +class CmdDuplicate : public Command +{ +public: + CmdDuplicate (); + int execute (const std::string&, std::string&); +}; + +#endif +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/commands/CmdHelp.cpp b/src/commands/CmdHelp.cpp index d26851c28..bb3fef578 100644 --- a/src/commands/CmdHelp.cpp +++ b/src/commands/CmdHelp.cpp @@ -107,10 +107,6 @@ int CmdHelp::execute (const std::string&, std::string& output) view.set (row, 1, "task undo"); view.set (row, 2, "Reverts the most recent action."); - row = view.addRow (); - view.set (row, 1, "task duplicate ID [tags] [attrs] [desc...]"); - view.set (row, 2, "Duplicates the specified task, and allows modifications."); - row = view.addRow (); view.set (row, 1, "task delete ID"); view.set (row, 2, "Deletes the specified task."); diff --git a/src/commands/Command.cpp b/src/commands/Command.cpp index 7dd396a39..028055cdd 100644 --- a/src/commands/Command.cpp +++ b/src/commands/Command.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -86,6 +87,7 @@ void Command::factory (std::map & all) c = new CmdCount (); all[c->keyword ()] = c; c = new CmdDenotate (); all[c->keyword ()] = c; c = new CmdDiagnostics (); all[c->keyword ()] = c; + c = new CmdDuplicate (); all[c->keyword ()] = c; c = new CmdEdit (); all[c->keyword ()] = c; c = new CmdExec (); all[c->keyword ()] = c; c = new CmdGHistoryMonthly (); all[c->keyword ()] = c; diff --git a/src/main.h b/src/main.h index 5e0bd906c..135c35d45 100644 --- a/src/main.h +++ b/src/main.h @@ -54,7 +54,6 @@ int handleDone (std::string&); int handleModify (std::string&); int handleQuery (std::string&); int handleDelete (std::string&); -int handleDuplicate (std::string&); void handleUndo (); void handleMerge (std::string&); void handlePush (std::string&);