New Command - append

- New "append" command concatenates additional text onto an existing
  task description.
- Added unit tests to append command.
This commit is contained in:
Paul Beckingham 2009-03-16 08:28:34 -04:00
parent 7238d1f1c9
commit c69c3bb090
7 changed files with 170 additions and 49 deletions

View file

@ -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,

View file

@ -77,70 +77,32 @@
<table>
<tr>
<td>Source:</td>
<td><a href="http://www.beckingham.net/task-1.5.0.tar.gz">task-1.5.0.tar.gz</a></td>
<td><a href="http://www.beckingham.net/task-1.6.0.tar.gz">task-1.6.0.tar.gz</a></td>
</tr>
<tr>
<td>Mac OS X 10.5 (Leopard) Intel-only:</td>
<td><a href="http://www.beckingham.net/task-1.5.0.pkg">task-1.5.0.pkg</a></td>
<td><a href="http://www.beckingham.net/task-1.6.0.pkg">task-1.6.0.pkg</a></td>
</tr>
<tr>
<td>
Debian package:
(Thanks to <a href="http://blog.rfquerin.org">Richard Querin</a>):
</td>
<td><a href="http://www.beckingham.net/task_1.5.0-1_i386.deb">task_1.5.0-1_i386.deb</a></td>
<td><a href="http://www.beckingham.net/task_1.6.0-1_i386.deb">task_1.6.0-1_i386.deb</a></td>
</tr>
</table>
<h4>New in version 1.5.0 (3/15/2009)</h4>
<h4>New in version 1.6.0 (?)</h4>
<ul>
<li>Removed deprecated TUTORIAL file.
<li>Removed support for the "showage" configuration variable.
<li>"task stop" can remove the start time from a started task.
<li>"task ghistory" now displays a differently aligned graph, allowing
easier comparison by month of tasks added versus completed and deleted.
<li>"task version" command now reports unrecognized configuration variables,
which may be spelling mistakes or deprecated variables.
<li>"configure --enable-debug" now supported to suppress compiler optimization
to allow debugging.
<li>Allow lower case priorities, and automatically upper case them.
<li>Added support for "due" configuration variable which defines the number
of days in the future when a task is considered due.
<li>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.
<li>New online documentation for custom reports.
<li>New algorithm for determining when the "nag" message is displayed.
<li>Fixed bug where task hangs with a certain combination of recurring tasks
and shadow files.
<li>Fixed bug with the task sort algorithm, which led to an unstable sequence
when there were only a handful of tasks.
<li>Performance enhanced by eliminating unnecessary sorting.
<li>Task now has a large (and growing) test suite and bug regression tests
to help ensure higher quality releases.
<li>Fixed bug that caused large performance hit during table rendering.
<li>Fixed bug that concatenated a modified description without spaces.
<li>Added new column 'recur' that displays the recurrence period of any
recurring tasks. This column can be added to any custom report.
<li>Added support for "color.recurring" configuration variable which
specifies the color of recurring tasks.
<li>Added support for "locking" configuration variable that controls whether
file locking is used.
<li>Task export feature now includes recurrence information, removes nested
quotes, and limits output to pending tasks.
<li>Task no longer includes deleted tasks in the summary report (thanks to
Benjamin Tegarden).
<li>Fixed bug that prevented the summary report from properly reporting
recently completed tasks.
<li>Added support for new "append" command that adds more description text to
an existing task.
</ul>
<p>
(Find out <a href="versions.html">what was new in prior versions</a>)
</p>
<!--
<h2>Task 1.5.0 Beta</h2>
<h2>Task 1.6.0 Beta</h2>
<p>
The next version of task is in beta. This means it is approaching the
end of the current development and testing cycle, and feedback from
@ -160,7 +122,7 @@
<table>
<tr>
<td>Source:</td>
<td><a href="http://www.beckingham.net/task-1.5.0beta.tar.gz">task-1.5.0beta.tar.gz</a></td>
<td><a href="http://www.beckingham.net/task-1.6.0beta.tar.gz">task-1.6.0beta.tar.gz</a></td>
</tr>
</table>
-->

View file

@ -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 <T> all;
tdb.pendingT (all);
std::vector <T>::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 <std::string> 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 <std::string, std::string> 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)
{

View file

@ -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<std::string>& options, std::str
candidate = matches[0];
else if (0 == matches.size ())
// throw std::string ("Unrecognized ") + type + " '" + candidate + "'";
candidate = "";
else

View file

@ -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); }

View file

@ -75,6 +75,7 @@ std::string runTaskCommand (std::vector <std::string>&, 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&);

55
src/tests/append.t Executable file
View file

@ -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;