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 --------------------------- ------ 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) 1.5.0 (3/15/2009)
+ Removed deprecated TUTORIAL file. + Removed deprecated TUTORIAL file.
+ Removed "showage" configuration variable. + Removed "showage" configuration variable.
@@ -43,8 +49,6 @@
+ Fixed bug that prevented the summary report from properly reporting + Fixed bug that prevented the summary report from properly reporting
recently completed tasks. recently completed tasks.
------ old releases ------------------------------
1.4.3 (11/1/2008) 8639e9260646c8c9224e0fc47e5d2443b46eecfc 1.4.3 (11/1/2008) 8639e9260646c8c9224e0fc47e5d2443b46eecfc
+ Fixed misleading task count at bottom on "info" report. + Fixed misleading task count at bottom on "info" report.
+ Added support for a shadow file that contains a plain text task report, + Added support for a shadow file that contains a plain text task report,

View File

@@ -77,70 +77,32 @@
<table> <table>
<tr> <tr>
<td>Source:</td> <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>
<tr> <tr>
<td>Mac OS X 10.5 (Leopard) Intel-only:</td> <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>
<tr> <tr>
<td> <td>
Debian package: Debian package:
(Thanks to <a href="http://blog.rfquerin.org">Richard Querin</a>): (Thanks to <a href="http://blog.rfquerin.org">Richard Querin</a>):
</td> </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> </tr>
</table> </table>
<h4>New in version 1.5.0 (3/15/2009)</h4> <h4>New in version 1.6.0 (?)</h4>
<ul> <ul>
<li>Removed deprecated TUTORIAL file. <li>Added support for new "append" command that adds more description text to
<li>Removed support for the "showage" configuration variable. an existing task.
<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.
</ul> </ul>
<p> <p>
(Find out <a href="versions.html">what was new in prior versions</a>) (Find out <a href="versions.html">what was new in prior versions</a>)
</p> </p>
<!-- <!--
<h2>Task 1.5.0 Beta</h2> <h2>Task 1.6.0 Beta</h2>
<p> <p>
The next version of task is in beta. This means it is approaching the 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 end of the current development and testing cycle, and feedback from
@@ -160,7 +122,7 @@
<table> <table>
<tr> <tr>
<td>Source:</td> <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> </tr>
</table> </table>
--> -->

View File

@@ -724,6 +724,100 @@ std::string handleModify (TDB& tdb, T& task, Config& conf)
return out.str (); 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) std::string handleColor (Config& conf)
{ {

View File

@@ -120,6 +120,7 @@ static const char* commands[] =
{ {
"active", "active",
"add", "add",
"append",
"calendar", "calendar",
"colors", "colors",
"completed", "completed",
@@ -188,7 +189,6 @@ void guess (const std::string& type, std::vector<std::string>& options, std::str
candidate = matches[0]; candidate = matches[0];
else if (0 == matches.size ()) else if (0 == matches.size ())
// throw std::string ("Unrecognized ") + type + " '" + candidate + "'";
candidate = ""; candidate = "";
else 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, 1, "task add [tags] [attrs] desc...");
table.addCell (row, 2, "Adds a new task"); 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 (); row = table.addRow ();
table.addCell (row, 1, "task completed [tags] [attrs] desc..."); table.addCell (row, 1, "task completed [tags] [attrs] desc...");
table.addCell (row, 2, "Chronological listing of all completed tasks matching the specified criteria"); 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. // Commands that cause updates.
else if (command == "" && task.getId ()) { cmdMod = true; out = handleModify (tdb, task, conf); } 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 == "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 == "done") { cmdMod = true; out = handleDone (tdb, task, conf); }
else if (command == "undelete") { cmdMod = true; out = handleUndelete (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); } 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 // command.cpp
std::string handleAdd (TDB&, T&, Config&); std::string handleAdd (TDB&, T&, Config&);
std::string handleAppend (TDB&, T&, Config&);
std::string handleExport (TDB&, T&, Config&); std::string handleExport (TDB&, T&, Config&);
std::string handleDone (TDB&, T&, Config&); std::string handleDone (TDB&, T&, Config&);
std::string handleModify (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;