diff --git a/ChangeLog b/ChangeLog index 1df489c9b..71550c681 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,8 @@ 1.9.2 () + Added feature #320, so the command "task 123" is interpreted as an implicit "task info 123" command (thanks to John Florian). + + Added feature #326, allowing tasks to be added in the completed state, + by using the 'log' command in place of 'add' (thanks to Cory Donnelly). ------ old releases ------------------------------ diff --git a/NEWS b/NEWS index e5705a00c..ab8acde77 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,7 @@ New Features in task 1.9 task list project.not:foo project.not:bar - Ability to do case-sensitive or case-insensitive search for keywords, and substitutions in the description and annotations. + - New 'log' command to add tasks that are already completed. - Task is now part of Debian Please refer to the ChangeLog file for full details. There are too many to diff --git a/doc/man/task-tutorial.5 b/doc/man/task-tutorial.5 index 6f52bd62c..f9c5343bf 100644 --- a/doc/man/task-tutorial.5 +++ b/doc/man/task-tutorial.5 @@ -358,6 +358,15 @@ To remove a tag from a task, use the minus sign: $ task 3 \-john .RE +To add a task that you have already completed, use the log command: +.br +.RS +$ task log Notify postal service +.RE + +This is equivalent to first adding a new task, then marking that new task +as done. It is simple a shortcut. + .SH Advanced usage of task Advanced examples of the usage of task can be found at the official site at diff --git a/doc/man/task.1 b/doc/man/task.1 index 153a01425..efa90920b 100644 --- a/doc/man/task.1 +++ b/doc/man/task.1 @@ -17,6 +17,10 @@ has a rich list of subcommands that allow you to do various things with it. .B add [tags] [attrs] description Adds a new task to the task list. +.TP +.B log [tags] [attrs] description +Adds a new task that is already completed, to the task list. + .TP .B append [tags] [attrs] description Appends information to an existing task. diff --git a/i18n/strings.en-US b/i18n/strings.en-US index 478c92afd..597faab08 100644 --- a/i18n/strings.en-US +++ b/i18n/strings.en-US @@ -55,7 +55,7 @@ 223 summary 224 tags 225 timesheet - +226 log 227 undo 228 version 229 shell diff --git a/src/Cmd.cpp b/src/Cmd.cpp index b7d06f185..0e049f4f2 100644 --- a/src/Cmd.cpp +++ b/src/Cmd.cpp @@ -127,6 +127,7 @@ void Cmd::load () commands.push_back (context.stringtable.get (CMD_GHISTORY, "ghistory")); commands.push_back (context.stringtable.get (CMD_IMPORT, "import")); commands.push_back (context.stringtable.get (CMD_INFO, "info")); + commands.push_back (context.stringtable.get (CMD_LOG, "log")); commands.push_back (context.stringtable.get (CMD_PREPEND, "prepend")); commands.push_back (context.stringtable.get (CMD_PROJECTS, "projects")); #ifdef FEATURE_SHELL @@ -228,6 +229,7 @@ bool Cmd::isWriteCommand () command == context.stringtable.get (CMD_DUPLICATE, "duplicate") || command == context.stringtable.get (CMD_EDIT, "edit") || command == context.stringtable.get (CMD_IMPORT, "import") || + command == context.stringtable.get (CMD_LOG, "log") || command == context.stringtable.get (CMD_PREPEND, "prepend") || command == context.stringtable.get (CMD_START, "start") || command == context.stringtable.get (CMD_STOP, "stop") || diff --git a/src/Context.cpp b/src/Context.cpp index c53f8b554..54da86a74 100644 --- a/src/Context.cpp +++ b/src/Context.cpp @@ -219,6 +219,7 @@ int Context::dispatch (std::string &out) else if (cmd.command == "calendar") { rc = handleReportCalendar (out); } else if (cmd.command == "timesheet") { rc = handleReportTimesheet (out); } else if (cmd.command == "add") { rc = handleAdd (out); } + else if (cmd.command == "log") { rc = handleLog (out); } else if (cmd.command == "append") { rc = handleAppend (out); } else if (cmd.command == "prepend") { rc = handlePrepend (out); } else if (cmd.command == "annotate") { rc = handleAnnotate (out); } diff --git a/src/command.cpp b/src/command.cpp index 6609aac5b..b97b6044e 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -123,6 +123,62 @@ int handleAdd (std::string &outs) return rc; } +//////////////////////////////////////////////////////////////////////////////// +int handleLog (std::string &outs) +{ + int rc = 0; + + if (context.hooks.trigger ("pre-log-command")) + { + std::stringstream out; + + context.task.setStatus (Task::completed); + context.task.set ("uuid", uuid ()); + context.task.setEntry (); + + // Add an end date. + char entryTime[16]; + sprintf (entryTime, "%u", (unsigned int) time (NULL)); + context.task.set ("end", entryTime); + + // Recurring tasks get a special status. + if (context.task.has ("recur")) + throw std::string ("You cannot log recurring tasks."); + + if (context.task.has ("wait")) + throw std::string ("You cannot log waiting tasks."); + + // Override with default.project, if not specified. + if (context.task.get ("project") == "") + context.task.set ("project", context.config.get ("default.project")); + + // Override with default.priority, if not specified. + if (context.task.get ("priority") == "") + { + std::string defaultPriority = context.config.get ("default.priority"); + if (Att::validNameValue ("priority", "", defaultPriority)) + context.task.set ("priority", defaultPriority); + } + + // Include tags. + foreach (tag, context.tagAdditions) + context.task.addTag (*tag); + + // Only valid tasks can be added. + context.task.validate (); + + context.tdb.lock (context.config.getBoolean ("locking")); + context.tdb.add (context.task); + context.tdb.commit (); + context.tdb.unlock (); + + outs = out.str (); + context.hooks.trigger ("post-log-command"); + } + + return rc; +} + //////////////////////////////////////////////////////////////////////////////// int handleProjects (std::string &outs) { diff --git a/src/i18n.h b/src/i18n.h index e1c6a72e5..22aea4737 100644 --- a/src/i18n.h +++ b/src/i18n.h @@ -92,7 +92,7 @@ #define CMD_SUMMARY 223 #define CMD_TAGS 224 #define CMD_TIMESHEET 225 - +#define CMD_LOG 226 #define CMD_UNDO 227 #define CMD_VERSION 228 #define CMD_SHELL 229 diff --git a/src/main.h b/src/main.h index a6451f7f1..9666de9a3 100644 --- a/src/main.h +++ b/src/main.h @@ -56,6 +56,7 @@ bool nag (Task&); // command.cpp int handleAdd (std::string &); +int handleLog (std::string &); int handleAppend (std::string &); int handlePrepend (std::string &); int handleExport (std::string &); diff --git a/src/report.cpp b/src/report.cpp index a04dcb438..3db83f3b8 100644 --- a/src/report.cpp +++ b/src/report.cpp @@ -77,6 +77,10 @@ int shortUsage (std::string &outs) table.addCell (row, 1, "task add [tags] [attrs] desc..."); table.addCell (row, 2, "Adds a new task."); + row = table.addRow (); + table.addCell (row, 1, "task log [tags] [attrs] desc..."); + table.addCell (row, 2, "Adds a new task that is already completed."); + row = table.addRow (); table.addCell (row, 1, "task append [tags] [attrs] desc..."); table.addCell (row, 2, "Appends more description to an existing task."); diff --git a/src/tests/log.t b/src/tests/log.t new file mode 100755 index 000000000..32f1ba8fb --- /dev/null +++ b/src/tests/log.t @@ -0,0 +1,61 @@ +#! /usr/bin/perl +################################################################################ +## task - a command line task list manager. +## +## Copyright 2006 - 2010, Paul Beckingham. +## 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 +## +################################################################################ + +use strict; +use warnings; +use Test::More tests => 8; + +# Create the rc file. +if (open my $fh, '>', 'log.rc') +{ + print $fh "data.location=.\n", + "confirmation=off\n"; + close $fh; + ok (-r 'log.rc', 'Created log.rc'); +} + +# Test the log command. +qx{../task rc:log.rc log This is a test}; +my $output = qx{../task rc:log.rc info 1}; +like ($output, qr/ID\s+1\n/, 'log ID'); +like ($output, qr/Description\s+This is a test\n/, 'log ID'); +like ($output, qr/Status\s+Completed\n/, 'log Completed'); +like ($output, qr/UUID\s+[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}\n/, 'log UUID'); + +# Cleanup. +unlink 'pending.data'; +ok (!-r 'pending.data', 'Removed pending.data'); + +unlink 'undo.data'; +ok (!-r 'undo.data', 'Removed undo.data'); + +unlink 'log.rc'; +ok (!-r 'log.rc', 'Removed log.rc'); + +exit 0; +