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:
@@ -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,
|
||||||
|
|||||||
@@ -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>
|
||||||
-->
|
-->
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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); }
|
||||||
|
|||||||
@@ -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
55
src/tests/append.t
Executable 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;
|
||||||
|
|
||||||
Reference in New Issue
Block a user