Merge branch 'master' into 1.5.0

Conflicts:
	ChangeLog
	NEWS
	configure.ac
	html/task.html
	src/task.cpp
	src/task.h
This commit is contained in:
Paul Beckingham 2008-11-02 22:29:38 -05:00
commit ee961daef6
29 changed files with 813 additions and 447 deletions

View file

@ -11,14 +11,18 @@
------ old releases ------------------------------
1.4.3 (10/9/2008)
1.4.3 (11/1/2008)
+ Fixed misleading task count at bottom on "info" report.
+ Added support for a shadow file that contains a plain text task report,
with the "shadow.file" and "shadow.command" configuration variables.
with the "shadow.file" and "shadow.command" configuration variables
The shadow file is automatically updated whenever the task database
changes. Useful for integrating with "Samurize".
------ old releases ------------------------------
changes. Useful for integrating with "Samurize"
+ Task now displays a message whenever a shadow file is updated, if the
"shadow.notify" configuration variable is set "on"
+ Bug: adding a task with a \n, \r or \f in it now fails properly
+ Removed "task usage" command.
+ Added documentation for Shadow files.
+ Added documentation for task filters.
1.4.2 (9/18/2008)
+ "task undo" can now retract a "task done" command, provided no reports

View file

@ -1,36 +0,0 @@
Some considerable time ago - longer than I had hoped - I demonstrated an
alternate implementation of the todo script, called task, in the form of a
YouTube movie:
http://www.youtube.com/watch?v=l68LCl6BYvs
A lot has happened since then, and the task program has been slowly improving
thanks to feedback from some early testers, and continuous use by me. Today,
I have uploaded a new movie:
http://www.youtube.com/watch?v=D2Kn4DMOVSw
This movie includes most of the changes and improvements to task, but behind
the scenes are the biggest changes. There was a rewrite of the underlying
storage mechanism yielding a clean API for the front end, and the code was
reviewed for portability and converted to use GNU autoconf/automake.
Task has been released under GPL, and so far has been tested on:
Max OS X 10.4 (Tiger)
Max OS X 10.5 (Leopard)
Fedora 8
Fedora 9
Ubuntu 8 (Hardy Heron)
Solaris 10
Task has been making me more organized and productive for some time now.
Perhaps some of you might find it useful, and I welcome feedback of all kinds.
You can find the task source code at:
http://www.beckingham.net/task-1.0.0.tar.gz
Thank you.
Paul Beckingham

View file

@ -19,7 +19,7 @@ AC_CHECK_LIB(ncurses,endwin)
# Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS([stdlib.h sys/file.h sys/stat.h sys/time.h unistd.h])
AC_CHECK_HEADERS([string vector map])
AC_CHECK_HEADERS([sstream string vector map])
# Checks for typedefs, structures, and compiler characteristics.
AC_HEADER_STDBOOL

View file

@ -25,6 +25,7 @@
<a href="date.html">Date Handling</a>
<a href="troubleshooting.html">Troubleshooting</a>
<a href="versions.html">Old Versions</a>
<a href="links.html">Task on the Web</a>
</div>
<div id="content">

View file

@ -25,6 +25,7 @@
<a href="date.html">Date Handling</a>
<a href="troubleshooting.html">Troubleshooting</a>
<a href="versions.html">Old Versions</a>
<a href="links.html">Task on the Web</a>
</div>
<div id="content">

View file

@ -25,6 +25,7 @@
<a href="date.html">Date Handling</a>
<a href="troubleshooting.html">Troubleshooting</a>
<a href="versions.html">Old Versions</a>
<a href="links.html">Task on the Web</a>
</div>
<div id="content">

View file

@ -25,6 +25,7 @@
<a href="date.html">Date Handling</a>
<a href="troubleshooting.html">Troubleshooting</a>
<a href="versions.html">Old Versions</a>
<a href="links.html">Task on the Web</a>
</div>
<div id="content">
@ -315,6 +316,12 @@ ID Project Pri Description
</p>
</dd>
<dt>shadow.notify</dt>
<dd>
When this value is set to "on", task will display a message
whenever the shadow file is updated by some task command.
</dd>
</div>
<br />

View file

@ -25,6 +25,7 @@
<a href="date.html">Date Handling</a>
<a href="troubleshooting.html">Troubleshooting</a>
<a href="versions.html">Old Versions</a>
<a href="links.html">Task on the Web</a>
</div>
<div id="content">

View file

@ -25,6 +25,7 @@
<a href="date.html">Date Handling</a>
<a href="troubleshooting.html">Troubleshooting</a>
<a href="versions.html">Old Versions</a>
<a href="links.html">Task on the Web</a>
</div>
<div id="content">
@ -34,10 +35,49 @@
<h2 class="title">Task Filters</h2>
<div class="content">
<p>
A task filter is a means of reducing a task report to a
subset that may consist of all tasks that have a specific
project, priority, tag, or part of the description.
</p>
<p>
A task filter consists of additional command line options,
that are specified in the same way as when a task is added.
</p>
<p>
All task reports can make use of filters.
</p>
<p>
For example, the report:
</p>
<code><pre>% task list</pre></code>
<p>
Lists all tasks.
</p>
<code><pre>% task list the</pre></code>
<p>
Lists only tasks with "the" in the task description.
</p>
<code><pre>% task list project:Home priority:H</pre></code>
<p>
Lists only tasks with both the "Home" project and "H" priority.
</p>
<code><pre>% task list +shopping</pre></code>
<p>
Lists only tasks with the "shopping" tag.
</p>
</div>
<br />
<br />
<div class="content">

188
html/links.html Normal file
View file

@ -0,0 +1,188 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Task on the Web</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="task.css" type="text/css" />
</head>
<body>
<div id="container">
<table>
<tr>
<td>
<div id="toolbar">
<a href="task.html">Home</a>
<a href="setup.html">Setup</a>
<a href="30second.html">30-second Tutorial</a>
<a href="simple.html">Simple</a>
<a href="advanced.html">Advanced</a>
<a href="shell.html">Shell</a>
<a href="config.html">Configuration</a>
<a href="color.html">Colors</a>
<a href="usage.html">Usage</a>
<a href="recur.html">Recurrence</a>
<a href="date.html">Date Handling</a>
<a href="troubleshooting.html">Troubleshooting</a>
<a href="versions.html">Old Versions</a>
<a href="links.html">Task on the Web</a>
</div>
<div id="content">
<br />
<br />
<br />
<h1 class="title">Task on the Web</h1>
<p>
Task links from around the web...
</p>
<dt>
November 2008, <a href="http://github.com/pbeckingham/task/tree/master/">Task repository on GitHub</a>
</dt>
<dd>
For developers: the task git repository on github.com is now public.
</dd>
<br>
<dt>
October 2008, <a href="http://blog.rfquerin.org/2008/10/07/using-task-and-dropbox-to-manage-your-to-do-list/">Using Task and Dropbox to manage your To-Do list</a>
</dt>
<dd>
by Richard Querin. Richard discusses the ease of setting up task to
use DropBox to share todo lists between work and home.
</dd>
<br>
<dt>
September 2008, <a href="http://stasantons.blogspot.com/2008/09/task-program-visually-simple.html">Task visualization</a>
</dt>
<dd>
by Stas Antons. Stas - a colleague of mine - presents a visualization
of the simplicity of task.
</dd>
<br>
<dt>
June 2008, <a href="http://blog.rfquerin.org/2008/06/17/building-debian-packages-for-task/">Building Debian Packages For Task</a>
</dt>
<dd>
by Richard Querin. Richard has been providing Debian packages for the
various task releases, and discusses how he got up to speed.
</dd>
<br>
<dt>
June 2008, <a href="http://blog.rfquerin.org/2008/06/06/task-101-an-attempt-at-a-cygwin-build-how-to/">Task 1.0.1 - an attempt at a Cygwin Build How-To</a>
</dt>
<dd>
by Richard Querin. Richard shows us how to build task using Cygwin, after
a cry for help on the todo.txt mailing list.
</dd>
<br>
<dt>
June 2008, <a href="http://www.youtube.com/watch?v=D2Kn4DMOVSw">The second task movie</a>
</dt>
<dd>
This YouTube movie was made to illustrate some of the features of the task
program, back when task 1.0.0 was released. While task has grown
significantly since then, the commands shown are still valid. It will
soon be time for a new movie!
<p>
This movie has a voice-over that explains what is going on.
<p>
For a higher-quality version, download the whole
<a href="http://www.beckingham.net/todo2.mov">movie file (10MB)</a>.
</dd>
<br>
<dt>
December 2006, <a href="http://www.youtube.com/watch?v=l68LCl6BYvs">The first task movie</a>
</dt>
<dd>
This original YouTube task movie was made to illustrate the features of the
then-unreleased task program. The idea was to get some feedback and see
whether anyone was interested in a new implementation of todo.sh, that added
features that are not easily possible with a shell implementation.
<p>
This movie has no voice-over, and you may notice that it exactly duplicates
the commands used in the original todo.sh movie (below). That is, until it
deviates because of new task commands.
</dd>
<br>
<dt>
June 2006, <a href="http://www.youtube.com/watch?v=daJ1Hs_y738">The original todo.sh movie</a>
</dt>
<dd>
by Gina Trapani. This is the original YouTube todo.sh movie, made to
illustrate the power and simplicity of the original todo.sh program.
</dd>
<br>
<dt>
June 2006, <a href="http://todotxt.com/">Todo.sh, the inspiration for task</a>
</dt>
<dd>
by Gina Trapani. The website that introduced me to the power and
simplicity of the original todo.sh program. Contains useful links
and resources - take a look!
</dd>
<br />
<br />
<div class="content">
<p>
Copyright 2006-2008, P. Beckingham. All rights reserved.
</p>
</div>
</div>
</td>
<td align="right" valign="top" width="200px">
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<script type="text/javascript"><!--
google_ad_client = "pub-9709799404235424";
/* Task Main */
google_ad_slot = "8660617875";
google_ad_width = 120;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</td>
</tr>
</table>
</div>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
var pageTracker = _gat._getTracker("UA-4737637-1");
pageTracker._initData();
pageTracker._trackPageview();
</script>
</body>
</html>

View file

@ -25,6 +25,7 @@
<a href="date.html">Date Handling</a>
<a href="troubleshooting.html">Troubleshooting</a>
<a href="versions.html">Old Versions</a>
<a href="links.html">Task on the Web</a>
</div>
<div id="content">

View file

@ -25,6 +25,7 @@
<a href="date.html">Date Handling</a>
<a href="troubleshooting.html">Troubleshooting</a>
<a href="versions.html">Old Versions</a>
<a href="links.html">Task on the Web</a>
</div>
<div id="content">

View file

@ -25,6 +25,7 @@
<a href="date.html">Date Handling</a>
<a href="troubleshooting.html">Troubleshooting</a>
<a href="versions.html">Old Versions</a>
<a href="links.html">Task on the Web</a>
</div>
<div id="content">
@ -34,10 +35,42 @@
<h2 class="title">Task Shadow Files</h2>
<div class="content">
<p>
A shadow file is a text file containing a copy of a task
report. It is automatically maintained by task whenever
something changes in the task database.
</p>
<p>
This means there is always a current version of the task
report kept in a text file. Products such as
<a href="www.samurize.com">Samurize</a>,
<a href="http://www.mulle-kybernetik.com/software/MkConsole/">MkConsole</a>,
or
<a href="http://projects.tynsoe.org/en/geektool/">GeekTool</a>
can display this file on the computer desktop, so that it
is readily visible.
</p>
<p>
To use a shadow file, edit your .taskrc configuration file,
and add two entries as shown:
</p>
<pre><code>shadow.file=/path/to/file
shadow.command=list pri:H</code></pre>
<p>
In this example the shadow file contains a report equivalent
to running "task list pri:H".
</p>
<p>
You can use any task command that generates a report, and of
course, you can specify any file name, provided the directory
it resides in already exists.
</p>
</div>
<br />
<br />
<div class="content">

View file

@ -25,6 +25,7 @@
<a href="date.html">Date Handling</a>
<a href="troubleshooting.html">Troubleshooting</a>
<a href="versions.html">Old Versions</a>
<a href="links.html">Task on the Web</a>
</div>
<div id="content">

View file

@ -25,6 +25,7 @@
<a href="date.html">Date Handling</a>
<a href="troubleshooting.html">Troubleshooting</a>
<a href="versions.html">Old Versions</a>
<a href="links.html">Task on the Web</a>
</div>
<div id="content">

View file

@ -25,6 +25,7 @@
<a href="date.html">Date Handling</a>
<a href="troubleshooting.html">Troubleshooting</a>
<a href="versions.html">Old Versions</a>
<a href="links.html">Task on the Web</a>
</div>
<div id="content">
@ -54,8 +55,8 @@
<li><a href="date.html">Date Handling</a>
<li><a href="troubleshooting.html">Troubleshooting</a>
<li><a href="versions.html">Old Versions</a>
<li><a href="filter.html">Filters (coming soon)</a>
<li><a href="shadow.html">Shadow Files (coming soon)</a>
<li><a href="filter.html">Filters</a>
<li><a href="shadow.html">Shadow Files</a>
</ul>
<p>
@ -77,6 +78,7 @@
<td>Source:</td>
<td><a href="http://www.beckingham.net/task-1.5.0.tar.gz">task-1.5.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>
@ -88,13 +90,12 @@
</td>
<td><a href="http://www.beckingham.net/task_1.5.0-1_i386.deb">task_1.5.0-1_i386.deb</a></td>
</tr>
-->
</table>
<h4>New in version 1.5.0 (?)</h4>
<ul>
<li>Removed deprecated TUTORIAL file.
<li>Removed "usage" command, and support for "command.logging" 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.

View file

@ -25,6 +25,7 @@
<a href="date.html">Date Handling</a>
<a href="troubleshooting.html">Troubleshooting</a>
<a href="versions.html">Old Versions</a>
<a href="links.html">Task on the Web</a>
</div>
<div id="content">

View file

@ -25,6 +25,7 @@
<a href="date.html">Date Handling</a>
<a href="troubleshooting.html">Troubleshooting</a>
<a href="versions.html">Old Versions</a>
<a href="links.html">Task on the Web</a>
</div>
<div id="content">

View file

@ -25,6 +25,7 @@
<a href="date.html">Date Handling</a>
<a href="troubleshooting.html">Troubleshooting</a>
<a href="versions.html">Old Versions</a>
<a href="links.html">Task on the Web</a>
</div>
<div id="content">
@ -35,6 +36,32 @@
<br />
<div class="content">
<p>
<h4>New in version 1.4.3 (11/1/2008)</h4>
<a href="http://www.beckingham.net/task-1.4.3.tar.gz">task-1.4.3.tar.gz</a>
<br />
Mac OS X 10.5 (Leopard) Intel-only:
<a href="http://www.beckingham.net/task-1.4.3.pkg">task-1.4.3.pkg</a>
<br />
Debian package: <a href="http://www.beckingham.net/task_1.4.3-1_i386.deb">task_1.4.3-1_i386.deb</a>
(Thanks to <a href="http://blog.rfquerin.org">Richard Querin</a>)
</p>
<ul>
<li>Fixed misleading task count at bottom of "info" report.
<li>Added support for a shadow file that contains a plain text task report,
with the "shadow.file" and "shadow.command" configuration variables.
The shadow file is automatically updated whenever the task database
changes. Useful for integrating with "Samurize".
<li>Task now displays a message whenever a shadow file is updated, if the
"shadow.notify" configuration variable is set "on".
<li>Fixed bug whereby adding a task with a \n, \r or \f dit not fail properly.
<li>Removed "task usage" command.
<li>Added documentation for Shadow files.
<li>Added documentation for task filters.
</ul>
</p>
<p>
<h4>New in version 1.4.2 (9/18/2008)</h4>
<a href="http://www.beckingham.net/task-1.4.2.tar.gz">task-1.4.2.tar.gz</a>

1
src/.gitignore vendored
View file

@ -1,2 +1 @@
./Makefile
*.o

View file

@ -130,6 +130,10 @@ void Config::createDefault (const std::string& home)
fprintf (out, "#color.tag.bug=yellow\n");
fprintf (out, "#color.project.home=on_green\n");
fprintf (out, "#color.keyword.car=on_blue\n");
fprintf (out, "#shadow.file=%s/shadow.txt\n", dataDir.c_str ());
fprintf (out, "#shadow.command=list\n");
fprintf (out, "#shadow.notify=on\n");
fprintf (out, "#default.command=list\n");
fclose (out);

View file

@ -204,9 +204,7 @@ bool TDB::deleteT (const T& t)
sprintf (endTime, "%u", (unsigned int) time (NULL));
it->setAttribute ("end", endTime);
bool status = overwritePending (all);
dbChanged ();
return status;
return overwritePending (all);
}
return false;
@ -230,9 +228,7 @@ bool TDB::completeT (const T& t)
sprintf (endTime, "%u", (unsigned int) time (NULL));
it->setAttribute ("end", endTime);
bool status = overwritePending (all);
dbChanged ();
return status;
return overwritePending (all);
}
return false;
@ -259,14 +255,10 @@ bool TDB::addT (const T& t)
if (task.getStatus () == T::pending ||
task.getStatus () == T::recurring)
{
bool status = writePending (task);
dbChanged ();
return status;
return writePending (task);
}
bool status = writeCompleted (task);
dbChanged ();
return status;
return writeCompleted (task);
}
////////////////////////////////////////////////////////////////////////////////
@ -291,9 +283,7 @@ bool TDB::modifyT (const T& t)
pending.push_back (*it);
}
bool status = overwritePending (pending);
dbChanged ();
return status;
return overwritePending (pending);
}
////////////////////////////////////////////////////////////////////////////////
@ -324,6 +314,7 @@ bool TDB::overwritePending (std::vector <T>& all)
fputs (it->compose ().c_str (), out);
fclose (out);
dbChanged ();
return true;
}
@ -331,7 +322,7 @@ bool TDB::overwritePending (std::vector <T>& all)
}
////////////////////////////////////////////////////////////////////////////////
bool TDB::writePending (const T& t) const
bool TDB::writePending (const T& t)
{
// Write a single task to the pending file
FILE* out;
@ -346,6 +337,7 @@ bool TDB::writePending (const T& t) const
fputs (t.compose ().c_str (), out);
fclose (out);
dbChanged ();
return true;
}
@ -353,7 +345,7 @@ bool TDB::writePending (const T& t) const
}
////////////////////////////////////////////////////////////////////////////////
bool TDB::writeCompleted (const T& t) const
bool TDB::writeCompleted (const T& t)
{
// Write a single task to the pending file
FILE* out;
@ -368,6 +360,8 @@ bool TDB::writeCompleted (const T& t) const
fputs (t.compose ().c_str (), out);
fclose (out);
// Note: No call to dbChanged here because this call never occurs by itself.
// It is always accompanied by an overwritePending call.
return true;
}
@ -439,8 +433,11 @@ int TDB::gc ()
}
}
// Dump all clean tasks into pending.
overwritePending (pending);
// Dump all clean tasks into pending. But don't bother unless at least one
// task was transferred.
if (count)
overwritePending (pending);
return count;
}

View file

@ -56,8 +56,8 @@ public:
private:
bool lock (FILE*) const;
bool overwritePending (std::vector <T>&);
bool writePending (const T&) const;
bool writeCompleted (const T&) const;
bool writePending (const T&);
bool writeCompleted (const T&);
bool readLockedFile (const std::string&, std::vector <std::string>&) const;
void dbChanged ();

View file

@ -26,6 +26,7 @@
////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <iomanip>
#include <sstream>
#include <fstream>
#include <sys/types.h>
#include <stdio.h>
@ -67,7 +68,6 @@ void handleAdd (TDB& tdb, T& task, Config& conf)
task.setAttribute ("mask", "");
}
/**/
// Override with default.project, if not specified.
if (task.getAttribute ("project") == "")
task.setAttribute ("project", conf.get ("default.project", ""));
@ -79,18 +79,20 @@ void handleAdd (TDB& tdb, T& task, Config& conf)
if (validPriority (defaultPriority))
task.setAttribute ("priority", defaultPriority);
}
/**/
// Disallow blank descriptions.
if (task.getDescription () == "")
throw std::string ("Cannot add a blank task.");
throw std::string ("Cannot add a task that is blank, or contains <CR> or <LF> characters.");
if (!tdb.addT (task))
throw std::string ("Could not create new task.");
}
////////////////////////////////////////////////////////////////////////////////
void handleProjects (TDB& tdb, T& task, Config& conf)
std::string handleProjects (TDB& tdb, T& task, Config& conf)
{
std::stringstream out;
// Get all the tasks, including deleted ones.
std::vector <T> tasks;
tdb.pendingT (tasks);
@ -127,21 +129,25 @@ void handleProjects (TDB& tdb, T& task, Config& conf)
table.addCell (row, 1, i->second);
}
std::cout << optionalBlankLine (conf)
<< table.render ()
<< optionalBlankLine (conf)
<< unique.size ()
<< (unique.size () == 1 ? " project" : " projects")
<< std::endl;
out << optionalBlankLine (conf)
<< table.render ()
<< optionalBlankLine (conf)
<< unique.size ()
<< (unique.size () == 1 ? " project" : " projects")
<< std::endl;
}
else
std::cout << "No projects."
<< std::endl;
out << "No projects."
<< std::endl;
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
void handleTags (TDB& tdb, T& task, Config& conf)
std::string handleTags (TDB& tdb, T& task, Config& conf)
{
std::stringstream out;
// Get all the tasks.
std::vector <T> tasks;
tdb.pendingT (tasks);
@ -166,20 +172,23 @@ void handleTags (TDB& tdb, T& task, Config& conf)
std::cout << i->first << std::endl;
if (unique.size ())
std::cout << optionalBlankLine (conf)
<< unique.size ()
<< (unique.size () == 1 ? " tag" : " tags")
<< std::endl;
out << optionalBlankLine (conf)
<< unique.size ()
<< (unique.size () == 1 ? " tag" : " tags")
<< std::endl;
else
std::cout << "No tags."
<< std::endl;
out << "No tags."
<< std::endl;
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
// If a task is deleted, but is still in the pending file, then it may be
// undeleted simply by changing it's status.
void handleUndelete (TDB& tdb, T& task, Config& conf)
std::string handleUndelete (TDB& tdb, T& task, Config& conf)
{
std::stringstream out;
std::vector <T> all;
tdb.allPendingT (all);
@ -193,8 +202,8 @@ void handleUndelete (TDB& tdb, T& task, Config& conf)
{
if (it->getAttribute ("recur") != "")
{
std::cout << "Task does not support 'undelete' for recurring tasks." << std::endl;
return;
out << "Task does not support 'undelete' for recurring tasks." << std::endl;
return out.str ();
}
T restored (*it);
@ -202,27 +211,31 @@ void handleUndelete (TDB& tdb, T& task, Config& conf)
restored.removeAttribute ("end");
tdb.modifyT (restored);
std::cout << "Task " << id << " successfully undeleted." << std::endl;
return;
out << "Task " << id << " successfully undeleted." << std::endl;
return out.str ();
}
else
{
std::cout << "Task " << id << " is not deleted - therefore cannot undelete." << std::endl;
return;
out << "Task " << id << " is not deleted - therefore cannot undelete." << std::endl;
return out.str ();
}
}
}
std::cout << "Task " << id
<< " not found - tasks can only be reliably undeleted if the undelete" << std::endl
<< "command is run immediately after the errant delete command." << std::endl;
out << "Task " << id
<< " not found - tasks can only be reliably undeleted if the undelete" << std::endl
<< "command is run immediately after the errant delete command." << std::endl;
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
// If a task is done, but is still in the pending file, then it may be undone
// simply by changing it's status.
void handleUndo (TDB& tdb, T& task, Config& conf)
std::string handleUndo (TDB& tdb, T& task, Config& conf)
{
std::stringstream out;
std::vector <T> all;
tdb.allPendingT (all);
@ -235,35 +248,36 @@ void handleUndo (TDB& tdb, T& task, Config& conf)
if (it->getStatus () == T::completed)
{
if (it->getAttribute ("recur") != "")
{
std::cout << "Task does not support 'undo' for recurring tasks." << std::endl;
return;
}
return std::string ("Task does not support 'undo' for recurring tasks.\n");
T restored (*it);
restored.setStatus (T::pending);
restored.removeAttribute ("end");
tdb.modifyT (restored);
std::cout << "Task " << id << " successfully undone." << std::endl;
return;
out << "Task " << id << " successfully undone." << std::endl;
return out.str ();
}
else
{
std::cout << "Task " << id << " is not done - therefore cannot be undone." << std::endl;
return;
out << "Task " << id << " is not done - therefore cannot be undone." << std::endl;
return out.str ();
}
}
}
std::cout << "Task " << id
<< " not found - tasks can only be reliably undone if the undo" << std::endl
<< "command is run immediately after the errant done command." << std::endl;
out << "Task " << id
<< " not found - tasks can only be reliably undone if the undo" << std::endl
<< "command is run immediately after the errant done command." << std::endl;
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
void handleVersion (Config& conf)
std::string handleVersion (Config& conf)
{
std::stringstream out;
// Determine window size, and set table accordingly.
int width = conf.get ("defaultwidth", 80);
#ifdef HAVE_LIBNCURSES
@ -329,40 +343,42 @@ void handleVersion (Config& conf)
}
}
std::cout << "Copyright (C) 2006 - 2008, P. Beckingham."
<< std::endl
<< (conf.get ("color", true) ? Text::colorize (Text::bold, Text::nocolor, PACKAGE) : PACKAGE)
<< " "
<< (conf.get ("color", true) ? Text::colorize (Text::bold, Text::nocolor, VERSION) : VERSION)
<< std::endl
<< disclaimer.render ()
<< std::endl
<< table.render ()
<< link.render ()
<< std::endl;
out << "Copyright (C) 2006 - 2008, P. Beckingham."
<< std::endl
<< (conf.get ("color", true) ? Text::colorize (Text::bold, Text::nocolor, PACKAGE) : PACKAGE)
<< " "
<< (conf.get ("color", true) ? Text::colorize (Text::bold, Text::nocolor, VERSION) : VERSION)
<< std::endl
<< disclaimer.render ()
<< std::endl
<< table.render ()
<< link.render ()
<< std::endl;
// Verify installation. This is mentioned in the documentation as the way to
// ensure everything is properly installed.
if (all.size () == 0)
std::cout << "Configuration error: .taskrc contains no entries"
<< std::endl;
out << "Configuration error: .taskrc contains no entries"
<< std::endl;
else
{
if (conf.get ("data.location") == "")
std::cout << "Configuration error: data.location not specified in .taskrc "
"file."
<< std::endl;
out << "Configuration error: data.location not specified in .taskrc "
"file."
<< std::endl;
if (access (expandPath (conf.get ("data.location")).c_str (), X_OK))
std::cout << "Configuration error: data.location contains a directory name"
" that doesn't exist, or is unreadable."
<< std::endl;
out << "Configuration error: data.location contains a directory name"
" that doesn't exist, or is unreadable."
<< std::endl;
}
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
void handleDelete (TDB& tdb, T& task, Config& conf)
std::string handleDelete (TDB& tdb, T& task, Config& conf)
{
if (conf.get ("confirmation") != "yes" || confirm ("Permanently delete task?"))
{
@ -386,7 +402,7 @@ void handleDelete (TDB& tdb, T& task, Config& conf)
sibling->getUUID () == parent)
tdb.deleteT (*sibling);
return;
return std::string ("");
}
else
{
@ -394,7 +410,7 @@ void handleDelete (TDB& tdb, T& task, Config& conf)
t->setStatus (T::deleted);
updateRecurrenceMask (tdb, all, *t);
tdb.deleteT (*t);
return;
return std::string ("");
}
}
else
@ -405,11 +421,13 @@ void handleDelete (TDB& tdb, T& task, Config& conf)
}
}
else
std::cout << "Task not deleted." << std::endl;
return std::string ("Task not deleted.\n");
return std::string ("");
}
////////////////////////////////////////////////////////////////////////////////
void handleStart (TDB& tdb, T& task, Config& conf)
std::string handleStart (TDB& tdb, T& task, Config& conf)
{
std::vector <T> all;
tdb.pendingT (all);
@ -431,18 +449,23 @@ void handleStart (TDB& tdb, T& task, Config& conf)
tdb.modifyT (original);
nag (tdb, task, conf);
return;
return std::string ("");
}
else
std::cout << "Task " << task.getId () << " already started." << std::endl;
{
std::stringstream out;
out << "Task " << task.getId () << " already started." << std::endl;
return out.str ();
}
}
}
throw std::string ("Task not found.");
return std::string (""); // To satisfy gcc.
}
////////////////////////////////////////////////////////////////////////////////
void handleStop (TDB& tdb, T& task, Config& conf)
std::string handleStop (TDB& tdb, T& task, Config& conf)
{
std::vector <T> all;
tdb.pendingT (all);
@ -461,14 +484,19 @@ void handleStop (TDB& tdb, T& task, Config& conf)
tdb.modifyT (original);
nag (tdb, task, conf);
return;
return std::string ("");
}
else
std::cout << "Task " << task.getId () << " not started." << std::endl;
{
std::stringstream out;
out << "Task " << task.getId () << " not started." << std::endl;
return out.str ();
}
}
}
throw std::string ("Task not found.");
return std::string (""); // To satisfy gcc.
}
////////////////////////////////////////////////////////////////////////////////
@ -627,87 +655,91 @@ void handleModify (TDB& tdb, T& task, Config& conf)
}
////////////////////////////////////////////////////////////////////////////////
void handleColor (Config& conf)
std::string handleColor (Config& conf)
{
std::stringstream out;
if (conf.get ("color", true))
{
std::cout << optionalBlankLine (conf) << "Foreground" << std::endl
<< " "
<< Text::colorize (Text::bold, Text::nocolor, "bold") << " "
<< Text::colorize (Text::underline, Text::nocolor, "underline") << " "
<< Text::colorize (Text::bold_underline, Text::nocolor, "bold_underline") << std::endl
out << optionalBlankLine (conf) << "Foreground" << std::endl
<< " "
<< Text::colorize (Text::bold, Text::nocolor, "bold") << " "
<< Text::colorize (Text::underline, Text::nocolor, "underline") << " "
<< Text::colorize (Text::bold_underline, Text::nocolor, "bold_underline") << std::endl
<< " " << Text::colorize (Text::black, Text::nocolor, "black") << " "
<< Text::colorize (Text::bold_black, Text::nocolor, "bold_black") << " "
<< Text::colorize (Text::underline_black, Text::nocolor, "underline_black") << " "
<< Text::colorize (Text::bold_underline_black, Text::nocolor, "bold_underline_black") << std::endl
<< " " << Text::colorize (Text::black, Text::nocolor, "black") << " "
<< Text::colorize (Text::bold_black, Text::nocolor, "bold_black") << " "
<< Text::colorize (Text::underline_black, Text::nocolor, "underline_black") << " "
<< Text::colorize (Text::bold_underline_black, Text::nocolor, "bold_underline_black") << std::endl
<< " " << Text::colorize (Text::red, Text::nocolor, "red") << " "
<< Text::colorize (Text::bold_red, Text::nocolor, "bold_red") << " "
<< Text::colorize (Text::underline_red, Text::nocolor, "underline_red") << " "
<< Text::colorize (Text::bold_underline_red, Text::nocolor, "bold_underline_red") << std::endl
<< " " << Text::colorize (Text::red, Text::nocolor, "red") << " "
<< Text::colorize (Text::bold_red, Text::nocolor, "bold_red") << " "
<< Text::colorize (Text::underline_red, Text::nocolor, "underline_red") << " "
<< Text::colorize (Text::bold_underline_red, Text::nocolor, "bold_underline_red") << std::endl
<< " " << Text::colorize (Text::green, Text::nocolor, "green") << " "
<< Text::colorize (Text::bold_green, Text::nocolor, "bold_green") << " "
<< Text::colorize (Text::underline_green, Text::nocolor, "underline_green") << " "
<< Text::colorize (Text::bold_underline_green, Text::nocolor, "bold_underline_green") << std::endl
<< " " << Text::colorize (Text::green, Text::nocolor, "green") << " "
<< Text::colorize (Text::bold_green, Text::nocolor, "bold_green") << " "
<< Text::colorize (Text::underline_green, Text::nocolor, "underline_green") << " "
<< Text::colorize (Text::bold_underline_green, Text::nocolor, "bold_underline_green") << std::endl
<< " " << Text::colorize (Text::yellow, Text::nocolor, "yellow") << " "
<< Text::colorize (Text::bold_yellow, Text::nocolor, "bold_yellow") << " "
<< Text::colorize (Text::underline_yellow, Text::nocolor, "underline_yellow") << " "
<< Text::colorize (Text::bold_underline_yellow, Text::nocolor, "bold_underline_yellow") << std::endl
<< " " << Text::colorize (Text::yellow, Text::nocolor, "yellow") << " "
<< Text::colorize (Text::bold_yellow, Text::nocolor, "bold_yellow") << " "
<< Text::colorize (Text::underline_yellow, Text::nocolor, "underline_yellow") << " "
<< Text::colorize (Text::bold_underline_yellow, Text::nocolor, "bold_underline_yellow") << std::endl
<< " " << Text::colorize (Text::blue, Text::nocolor, "blue") << " "
<< Text::colorize (Text::bold_blue, Text::nocolor, "bold_blue") << " "
<< Text::colorize (Text::underline_blue, Text::nocolor, "underline_blue") << " "
<< Text::colorize (Text::bold_underline_blue, Text::nocolor, "bold_underline_blue") << std::endl
<< " " << Text::colorize (Text::blue, Text::nocolor, "blue") << " "
<< Text::colorize (Text::bold_blue, Text::nocolor, "bold_blue") << " "
<< Text::colorize (Text::underline_blue, Text::nocolor, "underline_blue") << " "
<< Text::colorize (Text::bold_underline_blue, Text::nocolor, "bold_underline_blue") << std::endl
<< " " << Text::colorize (Text::magenta, Text::nocolor, "magenta") << " "
<< Text::colorize (Text::bold_magenta, Text::nocolor, "bold_magenta") << " "
<< Text::colorize (Text::underline_magenta, Text::nocolor, "underline_magenta") << " "
<< Text::colorize (Text::bold_underline_magenta, Text::nocolor, "bold_underline_magenta") << std::endl
<< " " << Text::colorize (Text::magenta, Text::nocolor, "magenta") << " "
<< Text::colorize (Text::bold_magenta, Text::nocolor, "bold_magenta") << " "
<< Text::colorize (Text::underline_magenta, Text::nocolor, "underline_magenta") << " "
<< Text::colorize (Text::bold_underline_magenta, Text::nocolor, "bold_underline_magenta") << std::endl
<< " " << Text::colorize (Text::cyan, Text::nocolor, "cyan") << " "
<< Text::colorize (Text::bold_cyan, Text::nocolor, "bold_cyan") << " "
<< Text::colorize (Text::underline_cyan, Text::nocolor, "underline_cyan") << " "
<< Text::colorize (Text::bold_underline_cyan, Text::nocolor, "bold_underline_cyan") << std::endl
<< " " << Text::colorize (Text::cyan, Text::nocolor, "cyan") << " "
<< Text::colorize (Text::bold_cyan, Text::nocolor, "bold_cyan") << " "
<< Text::colorize (Text::underline_cyan, Text::nocolor, "underline_cyan") << " "
<< Text::colorize (Text::bold_underline_cyan, Text::nocolor, "bold_underline_cyan") << std::endl
<< " " << Text::colorize (Text::white, Text::nocolor, "white") << " "
<< Text::colorize (Text::bold_white, Text::nocolor, "bold_white") << " "
<< Text::colorize (Text::underline_white, Text::nocolor, "underline_white") << " "
<< Text::colorize (Text::bold_underline_white, Text::nocolor, "bold_underline_white") << std::endl
<< " " << Text::colorize (Text::white, Text::nocolor, "white") << " "
<< Text::colorize (Text::bold_white, Text::nocolor, "bold_white") << " "
<< Text::colorize (Text::underline_white, Text::nocolor, "underline_white") << " "
<< Text::colorize (Text::bold_underline_white, Text::nocolor, "bold_underline_white") << std::endl
<< std::endl << "Background" << std::endl
<< " " << Text::colorize (Text::nocolor, Text::on_black, "on_black") << " "
<< Text::colorize (Text::nocolor, Text::on_bright_black, "on_bright_black") << std::endl
<< std::endl << "Background" << std::endl
<< " " << Text::colorize (Text::nocolor, Text::on_black, "on_black") << " "
<< Text::colorize (Text::nocolor, Text::on_bright_black, "on_bright_black") << std::endl
<< " " << Text::colorize (Text::nocolor, Text::on_red, "on_red") << " "
<< Text::colorize (Text::nocolor, Text::on_bright_red, "on_bright_red") << std::endl
<< " " << Text::colorize (Text::nocolor, Text::on_red, "on_red") << " "
<< Text::colorize (Text::nocolor, Text::on_bright_red, "on_bright_red") << std::endl
<< " " << Text::colorize (Text::nocolor, Text::on_green, "on_green") << " "
<< Text::colorize (Text::nocolor, Text::on_bright_green, "on_bright_green") << std::endl
<< " " << Text::colorize (Text::nocolor, Text::on_green, "on_green") << " "
<< Text::colorize (Text::nocolor, Text::on_bright_green, "on_bright_green") << std::endl
<< " " << Text::colorize (Text::nocolor, Text::on_yellow, "on_yellow") << " "
<< Text::colorize (Text::nocolor, Text::on_bright_yellow, "on_bright_yellow") << std::endl
<< " " << Text::colorize (Text::nocolor, Text::on_yellow, "on_yellow") << " "
<< Text::colorize (Text::nocolor, Text::on_bright_yellow, "on_bright_yellow") << std::endl
<< " " << Text::colorize (Text::nocolor, Text::on_blue, "on_blue") << " "
<< Text::colorize (Text::nocolor, Text::on_bright_blue, "on_bright_blue") << std::endl
<< " " << Text::colorize (Text::nocolor, Text::on_blue, "on_blue") << " "
<< Text::colorize (Text::nocolor, Text::on_bright_blue, "on_bright_blue") << std::endl
<< " " << Text::colorize (Text::nocolor, Text::on_magenta, "on_magenta") << " "
<< Text::colorize (Text::nocolor, Text::on_bright_magenta, "on_bright_magenta") << std::endl
<< " " << Text::colorize (Text::nocolor, Text::on_magenta, "on_magenta") << " "
<< Text::colorize (Text::nocolor, Text::on_bright_magenta, "on_bright_magenta") << std::endl
<< " " << Text::colorize (Text::nocolor, Text::on_cyan, "on_cyan") << " "
<< Text::colorize (Text::nocolor, Text::on_bright_cyan, "on_bright_cyan") << std::endl
<< " " << Text::colorize (Text::nocolor, Text::on_cyan, "on_cyan") << " "
<< Text::colorize (Text::nocolor, Text::on_bright_cyan, "on_bright_cyan") << std::endl
<< " " << Text::colorize (Text::nocolor, Text::on_white, "on_white") << " "
<< Text::colorize (Text::nocolor, Text::on_bright_white, "on_bright_white") << std::endl
<< " " << Text::colorize (Text::nocolor, Text::on_white, "on_white") << " "
<< Text::colorize (Text::nocolor, Text::on_bright_white, "on_bright_white") << std::endl
<< optionalBlankLine (conf);
<< optionalBlankLine (conf);
}
else
{
std::cout << "Color is currently turned off in your .taskrc file." << std::endl;
out << "Color is currently turned off in your .taskrc file." << std::endl;
}
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -284,10 +284,21 @@ static bool validTag (const std::string& input)
////////////////////////////////////////////////////////////////////////////////
static bool validDescription (const std::string& input)
{
if (input.length () > 0)
/*
if (input.length () > 0 &&
input.find ("\r") == std::string::npos &&
input.find ("\f") == std::string::npos &&
input.find ("\n") == std::string::npos)
return true;
return false;
*/
if (input.length () == 0) return false;
if (input.find ("\r") != std::string::npos) return false;
if (input.find ("\f") != std::string::npos) return false;
if (input.find ("\n") != std::string::npos) return false;
return true;
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -26,6 +26,7 @@
////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <iomanip>
#include <sstream>
#include <fstream>
#include <sys/types.h>
#include <stdio.h>
@ -110,8 +111,10 @@ void filter (std::vector<T>& all, T& task)
////////////////////////////////////////////////////////////////////////////////
// Successively apply filters based on the task object built from the command
// line. Tasks that match all the specified criteria are listed.
void handleList (TDB& tdb, T& task, Config& conf)
std::string handleList (TDB& tdb, T& task, Config& conf)
{
std::stringstream out;
// Determine window size, and set table accordingly.
int width = conf.get ("defaultwidth", 80);
#ifdef HAVE_LIBNCURSES
@ -124,7 +127,6 @@ void handleList (TDB& tdb, T& task, Config& conf)
#endif
// Get the pending tasks.
tdb.gc ();
std::vector <T> tasks;
tdb.allPendingT (tasks);
handleRecurrence (tdb, tasks);
@ -242,23 +244,27 @@ void handleList (TDB& tdb, T& task, Config& conf)
}
if (table.rowCount ())
std::cout << optionalBlankLine (conf)
<< table.render ()
<< optionalBlankLine (conf)
<< table.rowCount ()
<< (table.rowCount () == 1 ? " task" : " tasks")
<< std::endl;
out << optionalBlankLine (conf)
<< table.render ()
<< optionalBlankLine (conf)
<< table.rowCount ()
<< (table.rowCount () == 1 ? " task" : " tasks")
<< std::endl;
else
std::cout << "No matches."
<< std::endl;
out << "No matches."
<< std::endl;
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
// Successively apply filters based on the task object built from the command
// line. Tasks that match all the specified criteria are listed. Show a narrow
// list that works better on mobile devices.
void handleSmallList (TDB& tdb, T& task, Config& conf)
std::string handleSmallList (TDB& tdb, T& task, Config& conf)
{
std::stringstream out;
// Determine window size, and set table accordingly.
int width = conf.get ("defaultwidth", 80);
#ifdef HAVE_LIBNCURSES
@ -271,7 +277,6 @@ void handleSmallList (TDB& tdb, T& task, Config& conf)
#endif
// Get the pending tasks.
tdb.gc ();
std::vector <T> tasks;
tdb.allPendingT (tasks);
handleRecurrence (tdb, tasks);
@ -371,22 +376,26 @@ void handleSmallList (TDB& tdb, T& task, Config& conf)
}
if (table.rowCount ())
std::cout << optionalBlankLine (conf)
<< table.render ()
<< optionalBlankLine (conf)
<< table.rowCount ()
<< (table.rowCount () == 1 ? " task" : " tasks")
<< std::endl;
out << optionalBlankLine (conf)
<< table.render ()
<< optionalBlankLine (conf)
<< table.rowCount ()
<< (table.rowCount () == 1 ? " task" : " tasks")
<< std::endl;
else
std::cout << "No matches."
<< std::endl;
out << "No matches."
<< std::endl;
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
// Successively apply filters based on the task object built from the command
// line. Tasks that match all the specified criteria are listed.
void handleCompleted (TDB& tdb, T& task, Config& conf)
std::string handleCompleted (TDB& tdb, T& task, Config& conf)
{
std::stringstream out;
// Determine window size, and set table accordingly.
int width = conf.get ("defaultwidth", 80);
#ifdef HAVE_LIBNCURSES
@ -399,7 +408,6 @@ void handleCompleted (TDB& tdb, T& task, Config& conf)
#endif
// Get the pending tasks.
tdb.gc ();
std::vector <T> tasks;
tdb.completedT (tasks);
filter (tasks, task);
@ -459,21 +467,25 @@ void handleCompleted (TDB& tdb, T& task, Config& conf)
}
if (table.rowCount ())
std::cout << optionalBlankLine (conf)
<< table.render ()
<< optionalBlankLine (conf)
<< table.rowCount ()
<< (table.rowCount () == 1 ? " task" : " tasks")
<< std::endl;
out << optionalBlankLine (conf)
<< table.render ()
<< optionalBlankLine (conf)
<< table.rowCount ()
<< (table.rowCount () == 1 ? " task" : " tasks")
<< std::endl;
else
std::cout << "No matches."
<< std::endl;
out << "No matches."
<< std::endl;
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
// Display all information for the given task.
void handleInfo (TDB& tdb, T& task, Config& conf)
std::string handleInfo (TDB& tdb, T& task, Config& conf)
{
std::stringstream out;
// Determine window size, and set table accordingly.
int width = conf.get ("defaultwidth", 80);
#ifdef HAVE_LIBNCURSES
@ -657,18 +669,22 @@ void handleInfo (TDB& tdb, T& task, Config& conf)
}
if (table.rowCount ())
std::cout << optionalBlankLine (conf)
<< table.render ()
<< std::endl;
out << optionalBlankLine (conf)
<< table.render ()
<< std::endl;
else
std::cout << "No matches." << std::endl;
out << "No matches." << std::endl;
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
// Successively apply filters based on the task object built from the command
// line. Tasks that match all the specified criteria are listed.
void handleLongList (TDB& tdb, T& task, Config& conf)
std::string handleLongList (TDB& tdb, T& task, Config& conf)
{
std::stringstream out;
// Determine window size, and set table accordingly.
int width = conf.get ("defaultwidth", 80);
#ifdef HAVE_LIBNCURSES
@ -681,7 +697,6 @@ void handleLongList (TDB& tdb, T& task, Config& conf)
#endif
// Get all the tasks.
tdb.gc ();
std::vector <T> tasks;
tdb.allPendingT (tasks);
handleRecurrence (tdb, tasks);
@ -824,24 +839,27 @@ void handleLongList (TDB& tdb, T& task, Config& conf)
}
if (table.rowCount ())
std::cout << optionalBlankLine (conf)
<< table.render ()
<< optionalBlankLine (conf)
<< table.rowCount ()
<< (table.rowCount () == 1 ? " task" : " tasks")
<< std::endl;
out << optionalBlankLine (conf)
<< table.render ()
<< optionalBlankLine (conf)
<< table.rowCount ()
<< (table.rowCount () == 1 ? " task" : " tasks")
<< std::endl;
else
std::cout << "No matches." << std::endl;
out << "No matches." << std::endl;
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
// Project Tasks Avg Age Status
// A 12 13d XXXXXXXX------
// B 109 3d 12h XX------------
void handleReportSummary (TDB& tdb, T& task, Config& conf)
std::string handleReportSummary (TDB& tdb, T& task, Config& conf)
{
std::stringstream out;
// Generate unique list of project names.
tdb.gc ();
std::map <std::string, bool> allProjects;
std::vector <T> pending;
tdb.allPendingT (pending);
@ -981,14 +999,16 @@ void handleReportSummary (TDB& tdb, T& task, Config& conf)
}
if (table.rowCount ())
std::cout << optionalBlankLine (conf)
<< table.render ()
<< optionalBlankLine (conf)
<< table.rowCount ()
<< (table.rowCount () == 1 ? " project" : " projects")
<< std::endl;
out << optionalBlankLine (conf)
<< table.render ()
<< optionalBlankLine (conf)
<< table.rowCount ()
<< (table.rowCount () == 1 ? " project" : " projects")
<< std::endl;
else
std::cout << "No projects." << std::endl;
out << "No projects." << std::endl;
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
@ -1010,10 +1030,11 @@ void handleReportSummary (TDB& tdb, T& task, Config& conf)
//
// Make the "three" tasks a configurable number
//
void handleReportNext (TDB& tdb, T& task, Config& conf)
std::string handleReportNext (TDB& tdb, T& task, Config& conf)
{
std::stringstream out;
// Load all pending.
tdb.gc ();
std::vector <T> pending;
tdb.allPendingT (pending);
handleRecurrence (tdb, pending);
@ -1034,8 +1055,6 @@ void handleReportNext (TDB& tdb, T& task, Config& conf)
}
#endif
tdb.gc ();
// Get the pending tasks.
std::vector <T> tasks;
tdb.pendingT (tasks);
@ -1151,15 +1170,17 @@ void handleReportNext (TDB& tdb, T& task, Config& conf)
}
if (table.rowCount ())
std::cout << optionalBlankLine (conf)
<< table.render ()
<< optionalBlankLine (conf)
<< table.rowCount ()
<< (table.rowCount () == 1 ? " task" : " tasks")
<< std::endl;
out << optionalBlankLine (conf)
<< table.render ()
<< optionalBlankLine (conf)
<< table.rowCount ()
<< (table.rowCount () == 1 ? " task" : " tasks")
<< std::endl;
else
std::cout << "No matches."
<< std::endl;
out << "No matches."
<< std::endl;
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
@ -1184,15 +1205,16 @@ time_t monthlyEpoch (const std::string& date)
return 0;
}
void handleReportHistory (TDB& tdb, T& task, Config& conf)
std::string handleReportHistory (TDB& tdb, T& task, Config& conf)
{
std::stringstream out;
std::map <time_t, int> groups;
std::map <time_t, int> addedGroup;
std::map <time_t, int> completedGroup;
std::map <time_t, int> deletedGroup;
// Scan the pending tasks.
tdb.gc ();
std::vector <T> pending;
tdb.allPendingT (pending);
handleRecurrence (tdb, pending);
@ -1360,16 +1382,20 @@ void handleReportHistory (TDB& tdb, T& task, Config& conf)
}
if (table.rowCount ())
std::cout << optionalBlankLine (conf)
<< table.render ()
<< std::endl;
out << optionalBlankLine (conf)
<< table.render ()
<< std::endl;
else
std::cout << "No tasks." << std::endl;
out << "No tasks." << std::endl;
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
void handleReportGHistory (TDB& tdb, T& task, Config& conf)
std::string handleReportGHistory (TDB& tdb, T& task, Config& conf)
{
std::stringstream out;
// Determine window size, and set table accordingly.
int width = conf.get ("defaultwidth", 80);
#ifdef HAVE_LIBNCURSES
@ -1388,7 +1414,6 @@ void handleReportGHistory (TDB& tdb, T& task, Config& conf)
std::map <time_t, int> deletedGroup;
// Scan the pending tasks.
tdb.gc ();
std::vector <T> pending;
tdb.allPendingT (pending);
handleRecurrence (tdb, pending);
@ -1583,24 +1608,26 @@ void handleReportGHistory (TDB& tdb, T& task, Config& conf)
if (table.rowCount ())
{
std::cout << optionalBlankLine (conf)
<< table.render ()
<< std::endl;
out << optionalBlankLine (conf)
<< table.render ()
<< std::endl;
if (conf.get ("color", true))
std::cout << "Legend: "
<< Text::colorize (Text::black, Text::on_red, "added")
<< ", "
<< Text::colorize (Text::black, Text::on_green, "completed")
<< ", "
<< Text::colorize (Text::black, Text::on_yellow, "deleted")
<< optionalBlankLine (conf)
<< std::endl;
out << "Legend: "
<< Text::colorize (Text::black, Text::on_red, "added")
<< ", "
<< Text::colorize (Text::black, Text::on_green, "completed")
<< ", "
<< Text::colorize (Text::black, Text::on_yellow, "deleted")
<< optionalBlankLine (conf)
<< std::endl;
else
std::cout << "Legend: + added, X completed, - deleted" << std::endl;
out << "Legend: + added, X completed, - deleted" << std::endl;
}
else
std::cout << "No tasks." << std::endl;
out << "No tasks." << std::endl;
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
@ -1728,10 +1755,11 @@ std::string renderMonths (
}
////////////////////////////////////////////////////////////////////////////////
void handleReportCalendar (TDB& tdb, T& task, Config& conf)
std::string handleReportCalendar (TDB& tdb, T& task, Config& conf)
{
std::stringstream out;
// Load all the pending tasks.
tdb.gc ();
std::vector <T> pending;
tdb.allPendingT (pending);
handleRecurrence (tdb, pending);
@ -1760,7 +1788,7 @@ void handleReportCalendar (TDB& tdb, T& task, Config& conf)
int mTo = newest.month ();
int yTo = newest.year ();
std::cout << std::endl;
out << std::endl;
std::string output;
int monthsPerLine = (conf.get ("monthsperline", 1));
@ -1777,11 +1805,11 @@ void handleReportCalendar (TDB& tdb, T& task, Config& conf)
int left = (18 - month.length ()) / 2 + 1;
int right = 18 - left - month.length ();
std::cout << std::setw (left) << ' '
<< month
<< ' '
<< nextY
<< std::setw (right) << ' ';
out << std::setw (left) << ' '
<< month
<< ' '
<< nextY
<< std::setw (right) << ' ';
if (++nextM > 12)
{
@ -1790,10 +1818,10 @@ void handleReportCalendar (TDB& tdb, T& task, Config& conf)
}
}
std::cout << std::endl
<< optionalBlankLine (conf)
<< renderMonths (mFrom, yFrom, today, pending, conf)
<< std::endl;
out << std::endl
<< optionalBlankLine (conf)
<< renderMonths (mFrom, yFrom, today, pending, conf)
<< std::endl;
mFrom += monthsPerLine;
if (mFrom > 12)
@ -1803,20 +1831,24 @@ void handleReportCalendar (TDB& tdb, T& task, Config& conf)
}
}
std::cout << "Legend: "
<< Text::colorize (Text::cyan, Text::nocolor, "today")
<< ", "
<< Text::colorize (Text::black, Text::on_yellow, "due")
<< ", "
<< Text::colorize (Text::black, Text::on_red, "overdue")
<< "."
<< optionalBlankLine (conf)
<< std::endl;
out << "Legend: "
<< Text::colorize (Text::cyan, Text::nocolor, "today")
<< ", "
<< Text::colorize (Text::black, Text::on_yellow, "due")
<< ", "
<< Text::colorize (Text::black, Text::on_red, "overdue")
<< "."
<< optionalBlankLine (conf)
<< std::endl;
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
void handleReportActive (TDB& tdb, T& task, Config& conf)
std::string handleReportActive (TDB& tdb, T& task, Config& conf)
{
std::stringstream out;
// Determine window size, and set table accordingly.
int width = conf.get ("defaultwidth", 80);
#ifdef HAVE_LIBNCURSES
@ -1829,7 +1861,6 @@ void handleReportActive (TDB& tdb, T& task, Config& conf)
#endif
// Get all the tasks.
tdb.gc ();
std::vector <T> tasks;
tdb.pendingT (tasks);
filter (tasks, task);
@ -1922,19 +1953,23 @@ void handleReportActive (TDB& tdb, T& task, Config& conf)
}
if (table.rowCount ())
std::cout << optionalBlankLine (conf)
<< table.render ()
<< optionalBlankLine (conf)
<< table.rowCount ()
<< (table.rowCount () == 1 ? " task" : " tasks")
<< std::endl;
out << optionalBlankLine (conf)
<< table.render ()
<< optionalBlankLine (conf)
<< table.rowCount ()
<< (table.rowCount () == 1 ? " task" : " tasks")
<< std::endl;
else
std::cout << "No active tasks." << std::endl;
out << "No active tasks." << std::endl;
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
void handleReportOverdue (TDB& tdb, T& task, Config& conf)
std::string handleReportOverdue (TDB& tdb, T& task, Config& conf)
{
std::stringstream out;
// Determine window size, and set table accordingly.
int width = conf.get ("defaultwidth", 80);
#ifdef HAVE_LIBNCURSES
@ -2029,21 +2064,25 @@ void handleReportOverdue (TDB& tdb, T& task, Config& conf)
}
if (table.rowCount ())
std::cout << optionalBlankLine (conf)
<< table.render ()
<< optionalBlankLine (conf)
<< table.rowCount ()
<< (table.rowCount () == 1 ? " task" : " tasks")
<< std::endl;
out << optionalBlankLine (conf)
<< table.render ()
<< optionalBlankLine (conf)
<< table.rowCount ()
<< (table.rowCount () == 1 ? " task" : " tasks")
<< std::endl;
else
std::cout << "No overdue tasks." << std::endl;
out << "No overdue tasks." << std::endl;
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
// Successively apply filters based on the task object built from the command
// line. Tasks that match all the specified criteria are listed.
void handleReportOldest (TDB& tdb, T& task, Config& conf)
std::string handleReportOldest (TDB& tdb, T& task, Config& conf)
{
std::stringstream out;
// Determine window size, and set table accordingly.
int width = conf.get ("defaultwidth", 80);
#ifdef HAVE_LIBNCURSES
@ -2056,7 +2095,6 @@ void handleReportOldest (TDB& tdb, T& task, Config& conf)
#endif
// Get the pending tasks.
tdb.gc ();
std::vector <T> tasks;
tdb.allPendingT (tasks);
handleRecurrence (tdb, tasks);
@ -2173,22 +2211,26 @@ void handleReportOldest (TDB& tdb, T& task, Config& conf)
}
if (table.rowCount ())
std::cout << optionalBlankLine (conf)
<< table.render ()
<< optionalBlankLine (conf)
<< table.rowCount ()
<< (table.rowCount () == 1 ? " task" : " tasks")
<< std::endl;
out << optionalBlankLine (conf)
<< table.render ()
<< optionalBlankLine (conf)
<< table.rowCount ()
<< (table.rowCount () == 1 ? " task" : " tasks")
<< std::endl;
else
std::cout << "No matches."
<< std::endl;
out << "No matches."
<< std::endl;
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
// Successively apply filters based on the task object built from the command
// line. Tasks that match all the specified criteria are listed.
void handleReportNewest (TDB& tdb, T& task, Config& conf)
std::string handleReportNewest (TDB& tdb, T& task, Config& conf)
{
std::stringstream out;
// Determine window size, and set table accordingly.
int width = conf.get ("defaultwidth", 80);
#ifdef HAVE_LIBNCURSES
@ -2201,7 +2243,6 @@ void handleReportNewest (TDB& tdb, T& task, Config& conf)
#endif
// Get the pending tasks.
tdb.gc ();
std::vector <T> tasks;
tdb.allPendingT (tasks);
handleRecurrence (tdb, tasks);
@ -2319,21 +2360,25 @@ void handleReportNewest (TDB& tdb, T& task, Config& conf)
}
if (table.rowCount ())
std::cout << optionalBlankLine (conf)
<< table.render ()
<< optionalBlankLine (conf)
<< table.rowCount ()
<< (table.rowCount () == 1 ? " task" : " tasks")
<< std::endl;
out << optionalBlankLine (conf)
<< table.render ()
<< optionalBlankLine (conf)
<< table.rowCount ()
<< (table.rowCount () == 1 ? " task" : " tasks")
<< std::endl;
else
std::cout << "No matches."
<< std::endl;
out << "No matches."
<< std::endl;
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
void handleReportStats (TDB& tdb, T& task, Config& conf)
std::string handleReportStats (TDB& tdb, T& task, Config& conf)
{
std::stringstream out;
// Get all the tasks.
std::vector <T> tasks;
tdb.allT (tasks);
@ -2380,40 +2425,42 @@ void handleReportStats (TDB& tdb, T& task, Config& conf)
if (tags.size ()) ++taggedT;
}
std::cout << "Pending " << pendingT << std::endl
<< "Recurring " << recurringT << std::endl
<< "Completed " << completedT << std::endl
<< "Deleted " << deletedT << std::endl
<< "Total " << totalT << std::endl;
out << "Pending " << pendingT << std::endl
<< "Recurring " << recurringT << std::endl
<< "Completed " << completedT << std::endl
<< "Deleted " << deletedT << std::endl
<< "Total " << totalT << std::endl;
if (tasks.size ())
{
Date e (earliest);
std::cout << "Oldest task " << e.toString (conf.get ("dateformat", "m/d/Y")) << std::endl;
out << "Oldest task " << e.toString (conf.get ("dateformat", "m/d/Y")) << std::endl;
Date l (latest);
std::cout << "Newest task " << l.toString (conf.get ("dateformat", "m/d/Y")) << std::endl;
std::cout << "Task used for " << formatSeconds (latest - earliest) << std::endl;
out << "Newest task " << l.toString (conf.get ("dateformat", "m/d/Y")) << std::endl;
out << "Task used for " << formatSeconds (latest - earliest) << std::endl;
}
if (totalT)
std::cout << "Task added every " << formatSeconds ((latest - earliest) / totalT) << std::endl;
out << "Task added every " << formatSeconds ((latest - earliest) / totalT) << std::endl;
if (completedT)
std::cout << "Task completed every " << formatSeconds ((latest - earliest) / completedT) << std::endl;
out << "Task completed every " << formatSeconds ((latest - earliest) / completedT) << std::endl;
if (deletedT)
std::cout << "Task deleted every " << formatSeconds ((latest - earliest) / deletedT) << std::endl;
out << "Task deleted every " << formatSeconds ((latest - earliest) / deletedT) << std::endl;
if (pendingT || completedT)
std::cout << "Average time pending "
out << "Average time pending "
<< formatSeconds ((int) ((daysPending / (pendingT + completedT)) * 86400))
<< std::endl;
if (totalT)
{
std::cout << "Average desc length " << (int) (descLength / totalT) << " characters" << std::endl;
std::cout << "Tasks tagged " << std::setprecision (3) << (100.0 * taggedT / totalT) << "%" << std::endl;
out << "Average desc length " << (int) (descLength / totalT) << " characters" << std::endl;
out << "Tasks tagged " << std::setprecision (3) << (100.0 * taggedT / totalT) << "%" << std::endl;
}
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -319,18 +319,18 @@ int main (int argc, char** argv)
tdb.onChange (&onChangeCallback);
}
runTaskCommand (argc, argv, tdb, conf);
std::cout << runTaskCommand (argc, argv, tdb, conf);
}
catch (std::string& error)
{
std::cout << error << std::endl;
std::cerr << error << std::endl;
return -1;
}
catch (...)
{
std::cout << "Unknown error." << std::endl;
std::cerr << "Unknown error." << std::endl;
return -2;
}
@ -679,16 +679,14 @@ void onChangeCallback ()
{
if (gConf && gTdb)
{
gConf->set ("curses", "off");
gConf->set ("color", "off");
// Determine if shadow file is enabled.
std::string shadowFile = expandPath (gConf->get ("shadow.file"));
if (shadowFile != "")
{
// Capture std::cout for the shadow file.
std::ofstream shadow (shadowFile.c_str ());
std::streambuf* original = std::cout.rdbuf (shadow.rdbuf ());
std::string oldCurses = gConf->get ("curses");
std::string oldColor = gConf->get ("color");
gConf->set ("curses", "off");
gConf->set ("color", "off");
// Run report. Use shadow.command, using default.command as a fallback
// with "list" as a default.
@ -696,13 +694,26 @@ void onChangeCallback ()
gConf->get ("default.command", "list"));
std::vector <std::string> args;
split (args, command, ' ');
runTaskCommand (args, *gTdb, *gConf);
std::string result = runTaskCommand (args, *gTdb, *gConf);
// Restore std::cout.
std::cout.rdbuf (original);
std::ofstream out (shadowFile.c_str ());
if (out.good ())
{
out << result;
out.close ();
}
else
throw std::string ("Could not write file '") + shadowFile + "'";
gConf->set ("curses", oldCurses);
gConf->set ("color", oldColor);
}
else
throw std::string ("Could not write to '") + shadowFile + "'.";
throw std::string ("No specified shadow file '") + shadowFile + "'.";
// Optionally display a notification that the shadow file was updated.
if (gConf->get (std::string ("shadow.notify"), false))
std::cout << "[Shadow file '" << shadowFile << "' updated]" << std::endl;
}
else
throw std::string ("Internal error (TDB/Config).");
@ -720,24 +731,26 @@ void onChangeCallback ()
}
////////////////////////////////////////////////////////////////////////////////
void runTaskCommand (
std::string runTaskCommand (
int argc,
char** argv,
TDB& tdb,
Config& conf)
Config& conf,
bool gc /* = true */)
{
std::vector <std::string> args;
for (int i = 1; i < argc; ++i)
args.push_back (argv[i]);
runTaskCommand (args, tdb, conf);
return runTaskCommand (args, tdb, conf, gc);
}
////////////////////////////////////////////////////////////////////////////////
void runTaskCommand (
std::string runTaskCommand (
std::vector <std::string>& args,
TDB& tdb,
Config& conf)
Config& conf,
bool gc /* = false */)
{
// If argc == 1 and the default.command configuration variable is set,
// then use that, otherwise stick with argc/argv.
@ -754,36 +767,40 @@ void runTaskCommand (
T task;
parse (args, command, task, conf);
if (command == "add") handleAdd (tdb, task, conf);
else if (command == "projects") handleProjects (tdb, task, conf);
else if (command == "tags") handleTags (tdb, task, conf);
else if (command == "list") handleList (tdb, task, conf);
else if (command == "info") handleInfo (tdb, task, conf);
else if (command == "undelete") handleUndelete (tdb, task, conf);
else if (command == "long") handleLongList (tdb, task, conf);
else if (command == "ls") handleSmallList (tdb, task, conf);
else if (command == "colors") handleColor ( conf);
else if (command == "completed") handleCompleted (tdb, task, conf);
else if (command == "delete") handleDelete (tdb, task, conf);
else if (command == "start") handleStart (tdb, task, conf);
else if (command == "stop") handleStop (tdb, task, conf);
else if (command == "done") handleDone (tdb, task, conf);
else if (command == "undo") handleUndo (tdb, task, conf);
else if (command == "export") handleExport (tdb, task, conf);
else if (command == "version") handleVersion ( conf);
else if (command == "summary") handleReportSummary (tdb, task, conf);
else if (command == "next") handleReportNext (tdb, task, conf);
else if (command == "history") handleReportHistory (tdb, task, conf);
else if (command == "ghistory") handleReportGHistory (tdb, task, conf);
else if (command == "calendar") handleReportCalendar (tdb, task, conf);
else if (command == "active") handleReportActive (tdb, task, conf);
else if (command == "overdue") handleReportOverdue (tdb, task, conf);
else if (command == "oldest") handleReportOldest (tdb, task, conf);
else if (command == "newest") handleReportNewest (tdb, task, conf);
else if (command == "stats") handleReportStats (tdb, task, conf);
else if (command == "" && task.getId ()) handleModify (tdb, task, conf);
else if (command == "help") longUsage (conf);
else shortUsage (conf);
std::string out = "";
if (command == "" && task.getId ()) { handleModify (tdb, task, conf); }
else if (command == "add") { handleAdd (tdb, task, conf); }
else if (command == "done") { handleDone (tdb, task, conf); }
else if (command == "export") { handleExport (tdb, task, conf); }
else if (command == "projects") { out = handleProjects (tdb, task, conf); }
else if (command == "tags") { out = handleTags (tdb, task, conf); }
else if (command == "info") { out = handleInfo (tdb, task, conf); }
else if (command == "undelete") { out = handleUndelete (tdb, task, conf); }
else if (command == "delete") { out = handleDelete (tdb, task, conf); }
else if (command == "start") { out = handleStart (tdb, task, conf); }
else if (command == "stop") { out = handleStop (tdb, task, conf); }
else if (command == "undo") { out = handleUndo (tdb, task, conf); }
else if (command == "stats") { out = handleReportStats (tdb, task, conf); }
else if (command == "list") { if (gc) tdb.gc (); out = handleList (tdb, task, conf); }
else if (command == "long") { if (gc) tdb.gc (); out = handleLongList (tdb, task, conf); }
else if (command == "ls") { if (gc) tdb.gc (); out = handleSmallList (tdb, task, conf); }
else if (command == "completed") { if (gc) tdb.gc (); out = handleCompleted (tdb, task, conf); }
else if (command == "summary") { if (gc) tdb.gc (); out = handleReportSummary (tdb, task, conf); }
else if (command == "next") { if (gc) tdb.gc (); out = handleReportNext (tdb, task, conf); }
else if (command == "history") { if (gc) tdb.gc (); out = handleReportHistory (tdb, task, conf); }
else if (command == "ghistory") { if (gc) tdb.gc (); out = handleReportGHistory (tdb, task, conf); }
else if (command == "calendar") { if (gc) tdb.gc (); out = handleReportCalendar (tdb, task, conf); }
else if (command == "active") { if (gc) tdb.gc (); out = handleReportActive (tdb, task, conf); }
else if (command == "overdue") { if (gc) tdb.gc (); out = handleReportOverdue (tdb, task, conf); }
else if (command == "oldest") { if (gc) tdb.gc (); out = handleReportOldest (tdb, task, conf); }
else if (command == "newest") { if (gc) tdb.gc (); out = handleReportNewest (tdb, task, conf); }
else if (command == "colors") { out = handleColor ( conf); }
else if (command == "version") { out = handleVersion ( conf); }
else if (command == "help") { longUsage ( conf); }
else { shortUsage ( conf); }
return out;
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -67,41 +67,41 @@ bool generateDueDates (T&, std::vector <Date>&);
Date getNextRecurrence (Date&, std::string&);
void updateRecurrenceMask (TDB&, std::vector <T>&, T&);
void onChangeCallback ();
void runTaskCommand (int, char**, TDB&, Config&);
void runTaskCommand (std::vector <std::string>&, TDB&, Config&);
std::string runTaskCommand (int, char**, TDB&, Config&, bool gc = true);
std::string runTaskCommand (std::vector <std::string>&, TDB&, Config&, bool gc = false);
// command.cpp
void handleAdd (TDB&, T&, Config&);
void handleProjects (TDB&, T&, Config&);
void handleTags (TDB&, T&, Config&);
void handleUndelete (TDB&, T&, Config&);
void handleVersion (Config&);
void handleExport (TDB&, T&, Config&);
void handleDelete (TDB&, T&, Config&);
void handleStart (TDB&, T&, Config&);
void handleStop (TDB&, T&, Config&);
void handleDone (TDB&, T&, Config&);
void handleUndo (TDB&, T&, Config&);
void handleModify (TDB&, T&, Config&);
void handleColor (Config&);
std::string handleProjects (TDB&, T&, Config&);
std::string handleTags (TDB&, T&, Config&);
std::string handleUndelete (TDB&, T&, Config&);
std::string handleVersion (Config&);
std::string handleDelete (TDB&, T&, Config&);
std::string handleStart (TDB&, T&, Config&);
std::string handleStop (TDB&, T&, Config&);
std::string handleUndo (TDB&, T&, Config&);
std::string handleColor (Config&);
// report.cpp
void filter (std::vector<T>&, T&);
void handleList (TDB&, T&, Config&);
void handleInfo (TDB&, T&, Config&);
void handleLongList (TDB&, T&, Config&);
void handleSmallList (TDB&, T&, Config&);
void handleCompleted (TDB&, T&, Config&);
void handleReportSummary (TDB&, T&, Config&);
void handleReportNext (TDB&, T&, Config&);
void handleReportHistory (TDB&, T&, Config&);
void handleReportGHistory (TDB&, T&, Config&);
void handleReportCalendar (TDB&, T&, Config&);
void handleReportActive (TDB&, T&, Config&);
void handleReportOverdue (TDB&, T&, Config&);
void handleReportStats (TDB&, T&, Config&);
void handleReportOldest (TDB&, T&, Config&);
void handleReportNewest (TDB&, T&, Config&);
std::string handleList (TDB&, T&, Config&);
std::string handleInfo (TDB&, T&, Config&);
std::string handleLongList (TDB&, T&, Config&);
std::string handleSmallList (TDB&, T&, Config&);
std::string handleCompleted (TDB&, T&, Config&);
std::string handleReportSummary (TDB&, T&, Config&);
std::string handleReportNext (TDB&, T&, Config&);
std::string handleReportHistory (TDB&, T&, Config&);
std::string handleReportGHistory (TDB&, T&, Config&);
std::string handleReportCalendar (TDB&, T&, Config&);
std::string handleReportActive (TDB&, T&, Config&);
std::string handleReportOverdue (TDB&, T&, Config&);
std::string handleReportStats (TDB&, T&, Config&);
std::string handleReportOldest (TDB&, T&, Config&);
std::string handleReportNewest (TDB&, T&, Config&);
// util.cpp
bool confirm (const std::string&);

View file

@ -1,15 +0,0 @@
./task li due:monday
./task li due:tuesday
./task li due:wednesday
./task li due:thursday
./task li due:friday
./task li due:saturday
./task li due:sunday
./task li due:yesterday
./task li due:today
./task li due:tomorrow
./task li due:eow
./task li due:eom
./task li due:eoy
./task li due:21st