diff --git a/ChangeLog b/ChangeLog
index 794dc591a..39ef33c31 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,12 @@
------ current release ---------------------------
+1.6.0 (?)
+ + Added support for new "append" command that adds more description text to
+ an existing task.
+
+------ old releases ------------------------------
+
1.5.0 (3/15/2009)
+ Removed deprecated TUTORIAL file.
+ Removed "showage" configuration variable.
@@ -43,8 +49,6 @@
+ Fixed bug that prevented the summary report from properly reporting
recently completed tasks.
------- old releases ------------------------------
-
1.4.3 (11/1/2008) 8639e9260646c8c9224e0fc47e5d2443b46eecfc
+ Fixed misleading task count at bottom on "info" report.
+ Added support for a shadow file that contains a plain text task report,
diff --git a/html/task.html b/html/task.html
index 184f155d0..05a90bb6a 100644
--- a/html/task.html
+++ b/html/task.html
@@ -77,70 +77,32 @@
- New in version 1.5.0 (3/15/2009)
+ New in version 1.6.0 (?)
- - Removed deprecated TUTORIAL file.
-
- Removed support for the "showage" configuration variable.
-
- "task stop" can remove the start time from a started task.
-
- "task ghistory" now displays a differently aligned graph, allowing
- easier comparison by month of tasks added versus completed and deleted.
-
- "task version" command now reports unrecognized configuration variables,
- which may be spelling mistakes or deprecated variables.
-
- "configure --enable-debug" now supported to suppress compiler optimization
- to allow debugging.
-
- Allow lower case priorities, and automatically upper case them.
-
- Added support for "due" configuration variable which defines the number
- of days in the future when a task is considered due.
-
- Added support for custom reports, comprised of a set of column names and
- sort order, with optional filtering in the configuration file. This
- means user-defined reports can be written, and the reports currently
- in the configuration file can be renamed. Several of task's built in
- reports have been converted to user-defined reports.
-
- New online documentation for custom reports.
-
- New algorithm for determining when the "nag" message is displayed.
-
- Fixed bug where task hangs with a certain combination of recurring tasks
- and shadow files.
-
- Fixed bug with the task sort algorithm, which led to an unstable sequence
- when there were only a handful of tasks.
-
- Performance enhanced by eliminating unnecessary sorting.
-
- Task now has a large (and growing) test suite and bug regression tests
- to help ensure higher quality releases.
-
- Fixed bug that caused large performance hit during table rendering.
-
- Fixed bug that concatenated a modified description without spaces.
-
- Added new column 'recur' that displays the recurrence period of any
- recurring tasks. This column can be added to any custom report.
-
- Added support for "color.recurring" configuration variable which
- specifies the color of recurring tasks.
-
- Added support for "locking" configuration variable that controls whether
- file locking is used.
-
- Task export feature now includes recurrence information, removes nested
- quotes, and limits output to pending tasks.
-
- Task no longer includes deleted tasks in the summary report (thanks to
- Benjamin Tegarden).
-
- Fixed bug that prevented the summary report from properly reporting
- recently completed tasks.
+
- Added support for new "append" command that adds more description text to
+ an existing task.
(Find out what was new in prior versions)
diff --git a/src/command.cpp b/src/command.cpp
index 72724f668..696f51ae0 100644
--- a/src/command.cpp
+++ b/src/command.cpp
@@ -724,6 +724,100 @@ std::string handleModify (TDB& tdb, T& task, Config& conf)
return out.str ();
}
+////////////////////////////////////////////////////////////////////////////////
+std::string handleAppend (TDB& tdb, T& task, Config& conf)
+{
+ std::stringstream out;
+ std::vector all;
+ tdb.pendingT (all);
+
+ std::vector ::iterator it;
+ for (it = all.begin (); it != all.end (); ++it)
+ {
+ if (it->getId () == task.getId ())
+ {
+ T original (*it);
+
+ // A non-zero value forces a file write.
+ int changes = 0;
+
+ // Apply a new description, if any.
+ if (task.getDescription () != "")
+ {
+ original.setDescription (original.getDescription () +
+ " " +
+ task.getDescription ());
+ ++changes;
+ }
+
+ // Apply or remove tags, if any.
+ std::vector tags;
+ task.getTags (tags);
+ for (unsigned int i = 0; i < tags.size (); ++i)
+ {
+ if (tags[i][0] == '+')
+ original.addTag (tags[i].substr (1, std::string::npos));
+ else
+ original.addTag (tags[i]);
+
+ ++changes;
+ }
+
+ task.getRemoveTags (tags);
+ for (unsigned int i = 0; i < tags.size (); ++i)
+ {
+ if (tags[i][0] == '-')
+ original.removeTag (tags[i].substr (1, std::string::npos));
+ else
+ original.removeTag (tags[i]);
+
+ ++changes;
+ }
+
+ // Apply or remove attributes, if any.
+ std::map attributes;
+ task.getAttributes (attributes);
+ foreach (i, attributes)
+ {
+ if (i->second == "")
+ original.removeAttribute (i->first);
+ else
+ original.setAttribute (i->first, i->second);
+
+ ++changes;
+ }
+
+ std::string from;
+ std::string to;
+ task.getSubstitution (from, to);
+ if (from != "")
+ {
+ std::string description = original.getDescription ();
+ size_t pattern = description.find (from);
+ if (pattern != std::string::npos)
+ {
+ description = description.substr (0, pattern) +
+ to +
+ description.substr (pattern + from.length (), std::string::npos);
+ original.setDescription (description);
+ ++changes;
+ }
+ }
+
+ if (changes)
+ {
+ original.setId (task.getId ());
+ tdb.modifyT (original);
+ }
+
+ return out.str ();
+ }
+ }
+
+ throw std::string ("Task not found.");
+ return out.str ();
+}
+
////////////////////////////////////////////////////////////////////////////////
std::string handleColor (Config& conf)
{
diff --git a/src/parse.cpp b/src/parse.cpp
index a8e41a914..bcda9e778 100644
--- a/src/parse.cpp
+++ b/src/parse.cpp
@@ -120,6 +120,7 @@ static const char* commands[] =
{
"active",
"add",
+ "append",
"calendar",
"colors",
"completed",
@@ -188,7 +189,6 @@ void guess (const std::string& type, std::vector& options, std::str
candidate = matches[0];
else if (0 == matches.size ())
-// throw std::string ("Unrecognized ") + type + " '" + candidate + "'";
candidate = "";
else
diff --git a/src/task.cpp b/src/task.cpp
index d31952f02..226a96318 100644
--- a/src/task.cpp
+++ b/src/task.cpp
@@ -84,6 +84,10 @@ static std::string shortUsage (Config& conf)
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 append [tags] [attrs] desc...");
+ table.addCell (row, 2, "Appends more description to an existing task");
+
row = table.addRow ();
table.addCell (row, 1, "task completed [tags] [attrs] desc...");
table.addCell (row, 2, "Chronological listing of all completed tasks matching the specified criteria");
@@ -816,6 +820,7 @@ std::string runTaskCommand (
// Commands that cause updates.
else if (command == "" && task.getId ()) { cmdMod = true; out = handleModify (tdb, task, conf); }
else if (command == "add") { cmdMod = true; out = handleAdd (tdb, task, conf); }
+ else if (command == "append") { cmdMod = true; out = handleAppend (tdb, task, conf); }
else if (command == "done") { cmdMod = true; out = handleDone (tdb, task, conf); }
else if (command == "undelete") { cmdMod = true; out = handleUndelete (tdb, task, conf); }
else if (command == "delete") { cmdMod = true; out = handleDelete (tdb, task, conf); }
diff --git a/src/task.h b/src/task.h
index 5ddd81f6f..6290cfb68 100644
--- a/src/task.h
+++ b/src/task.h
@@ -75,6 +75,7 @@ std::string runTaskCommand (std::vector &, TDB&, Config&, bool gc =
// command.cpp
std::string handleAdd (TDB&, T&, Config&);
+std::string handleAppend (TDB&, T&, Config&);
std::string handleExport (TDB&, T&, Config&);
std::string handleDone (TDB&, T&, Config&);
std::string handleModify (TDB&, T&, Config&);
diff --git a/src/tests/append.t b/src/tests/append.t
new file mode 100755
index 000000000..54225dd86
--- /dev/null
+++ b/src/tests/append.t
@@ -0,0 +1,55 @@
+#! /usr/bin/perl
+################################################################################
+## task - a command line task list manager.
+##
+## Copyright 2006 - 2009, 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 => 4;
+
+# Create the rc file.
+if (open my $fh, '>', 'append.rc')
+{
+ print $fh "data.location=.\n";
+ close $fh;
+ ok (-r 'append.rc', 'Created append.rc');
+}
+
+# Add a task, then append more decsription.
+qx{../task rc:append.rc add foo};
+qx{../task rc:append.rc 1 append bar};
+my $output = qx{../task rc:append.rc info 1};
+like ($output, qr/Description\s+foo\sbar\n/, 'append worked');
+
+# Cleanup.
+unlink 'pending.data';
+ok (!-r 'pending.data', 'Removed pending.data');
+
+unlink 'append.rc';
+ok (!-r 'append.rc', 'Removed append.rc');
+
+exit 0;
+