Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e7304e86ce | ||
|
|
d7b95cb2e1 | ||
|
|
45ed7dcdaa | ||
|
|
d809b6dae7 | ||
|
|
a1cc4e5774 | ||
|
|
21c33f7030 | ||
|
|
2e32457032 | ||
|
|
e4ed873d60 | ||
|
|
e35dcd0e42 | ||
|
|
ec15dc9342 | ||
|
|
fb87039d8c | ||
|
|
e9a71b7db9 | ||
|
|
df215f228d | ||
|
|
4f8f044644 | ||
|
|
4380c7c712 | ||
|
|
4abc722eff | ||
|
|
11225eb599 | ||
|
|
e16bd057d8 | ||
|
|
29a152edb0 | ||
|
|
e99e6832f2 | ||
|
|
ff4e8dbef1 | ||
|
|
d265ac6c2d | ||
|
|
dc1760769f | ||
|
|
c6eb09cd63 | ||
|
|
ceffdca8a2 |
6
AUTHORS
6
AUTHORS
@@ -3,6 +3,8 @@ Principal Author:
|
||||
|
||||
Contributing Authors:
|
||||
Damian Glenny
|
||||
Andy Lester
|
||||
H. İbrahim Güngör
|
||||
|
||||
With thanks to:
|
||||
Eugene Kramer
|
||||
@@ -12,7 +14,7 @@ With thanks to:
|
||||
Thomas Engel
|
||||
Nishiishii
|
||||
galvanizd
|
||||
H. İbrahim Güngör
|
||||
Stas Antons
|
||||
Andy Lester
|
||||
Vincent Fleuranceau
|
||||
T. Charles Yun
|
||||
|
||||
|
||||
30
ChangeLog
30
ChangeLog
@@ -7,12 +7,36 @@ represents a feature release, and the Z represents a patch.
|
||||
|
||||
------ current release ---------------------------
|
||||
|
||||
1.4.1 (7/?/2008)
|
||||
1.4.2 (9/18/2008)
|
||||
+ "task undo" can now retract a "task done" command, provided no reports
|
||||
have been run (and therefore TDB::gc run)
|
||||
+ Task now correctly sorts on entire strings, instead of just the first
|
||||
character (thanks to Andy Lester)
|
||||
+ Task now uses dashes (-----) to column underlines when color is disabled
|
||||
(thanks to Vincent Fleuranceau)
|
||||
+ Task now allows mixed case attribute names (pri:, PRI:, Pri: ...) and
|
||||
commands (add, ADD, Add ...) (thanks to Vincent Fleuranceau)
|
||||
+ Task now supports a default project and priority for new tasks, via
|
||||
the new "default.project" and "default.priority" configuration variables
|
||||
(thanks to Vincent Fleuranceau)
|
||||
+ Task supports improved word-wrapping to the terminal width
|
||||
+ Task now supports "default.command" configuration variable (for example
|
||||
it could contain "list due:tomorrow") that is the command that is run
|
||||
whenever task is invoked with no arguments.
|
||||
+ Task supports modifying the existing description of a task, with the
|
||||
following syntax: task <id> "new description ...".
|
||||
+ Bug: Now properly supports relative dates in filters (task list due:eom,
|
||||
task list due:tomorrow, task list due:23rd ...)
|
||||
+ Bug: Source now properly includes <string.h> in order to build clean
|
||||
using gcc 4.3 (thanks to H. İbrahim Güngör)
|
||||
|
||||
------ old releases ------------------------------
|
||||
|
||||
1.4.1 (7/18/2008)
|
||||
+ Bug: Descriptions can not be altered with "task 123 New description"
|
||||
+ Tweak: For "task calendar" month names are now centered over the month
|
||||
+ Removed TUTORIAL file contents in favor of online version
|
||||
|
||||
------ old releases ------------------------------
|
||||
+ Provided Mac .pkg binary
|
||||
|
||||
1.4.0 (7/10/2008)
|
||||
+ New recurring tasks feature
|
||||
|
||||
1
NEWS
1
NEWS
@@ -7,6 +7,7 @@ Task has been built and tested on the following configurations:
|
||||
- Fedora Core 8
|
||||
- Fedora Core 9
|
||||
- Ubuntu 8 Hardy Heron
|
||||
- Ubuntu 9 Feisty Fawn
|
||||
- Solaris 10
|
||||
- Cygwin 1.5.25-14
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ(2.61)
|
||||
AC_INIT(task, 1.4.1, bugs@beckingham.net)
|
||||
AC_INIT(task, 1.4.2, bugs@beckingham.net)
|
||||
AM_INIT_AUTOMAKE
|
||||
AC_CONFIG_SRCDIR([src/task.cpp])
|
||||
AC_CONFIG_HEADER([auto.h])
|
||||
|
||||
@@ -43,6 +43,25 @@
|
||||
lists all these commands.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
However, if the following configuration variable is specified:
|
||||
</p>
|
||||
|
||||
<pre><code>default.command=list pri:H</code></pre>
|
||||
|
||||
<p>
|
||||
Then this command will be run whenever task is run without arguments.
|
||||
This means that your most common task command can be run simply
|
||||
with the command:
|
||||
</p>
|
||||
|
||||
<pre><code>% task
|
||||
[task list project:foo]
|
||||
|
||||
ID Project Pri Description
|
||||
1 foo H Design the thing
|
||||
2 foo Build the thing</code></pre>
|
||||
|
||||
<strong>% task projects</strong>
|
||||
<p>
|
||||
This report generates a list of all the different projects that you
|
||||
@@ -337,6 +356,14 @@ ID Project Pri Description
|
||||
% wtask list
|
||||
...</code></pre>
|
||||
|
||||
<strong>% task <id> "new description"</strong>
|
||||
<p>
|
||||
Not strictly a command, the replacement of the description can
|
||||
be achieved by quoting the entire description. The quotes are
|
||||
necessary in case one of the description words looks like a task
|
||||
command.
|
||||
</p>
|
||||
|
||||
<strong>% task <id> fg:... bg:...</strong>
|
||||
<p>
|
||||
Not strictly a command, the setting of the fg and bg (foreground
|
||||
|
||||
@@ -210,6 +210,8 @@
|
||||
<dt>color</dt>
|
||||
<dd>
|
||||
May be "on" or "off". Determines whether task uses color.
|
||||
When "off", task will use dashes (-----) to underline column
|
||||
headings.
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
@@ -246,6 +248,44 @@
|
||||
<dd>
|
||||
Colors any task where the description contains X.
|
||||
</dd>
|
||||
|
||||
<dt>default.project</dt>
|
||||
<dd>
|
||||
Provides a default project name for the "task add ..." command.
|
||||
</dd>
|
||||
|
||||
<dt>default.priority</dt>
|
||||
<dd>
|
||||
Provides a default priority for the "task add ..." command.
|
||||
</dd>
|
||||
|
||||
<dt>default.command</dt>
|
||||
<dd>
|
||||
<p>
|
||||
Provides a default command that is run every time task is
|
||||
invoked with no arguments. For example, if set to:
|
||||
</p>
|
||||
|
||||
<pre><code>default.command=list project:foo</code></pre>
|
||||
|
||||
<p>
|
||||
Then task will run the "list project:foo" command if no
|
||||
command is specified. This means that by merely typing:
|
||||
</p>
|
||||
|
||||
<pre><code>% task
|
||||
[task list project:foo]
|
||||
|
||||
ID Project Pri Description
|
||||
1 foo H Design the thing
|
||||
2 foo Build the thing</code></pre>
|
||||
|
||||
<p>
|
||||
Note that the value of this variable is simply the command
|
||||
line that you would ordinarily type, but without the
|
||||
preceding "task" program name.
|
||||
</p>
|
||||
</dd>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!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 1.4.1</title>
|
||||
<title>Task 1.4.2</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<link rel="stylesheet" href="task.css" type="text/css" />
|
||||
</head>
|
||||
@@ -75,29 +75,49 @@
|
||||
<table>
|
||||
<tr>
|
||||
<td>Source:</td>
|
||||
<td><a href="http://www.beckingham.net/task-1.4.1.tar.gz">task-1.4.1.tar.gz</a></td>
|
||||
<td><a href="http://www.beckingham.net/task-1.4.2.tar.gz">task-1.4.2.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.4.1.pkg">task-1.4.1.pkg</a></td>
|
||||
<td><a href="http://www.beckingham.net/task-1.4.2.pkg">task-1.4.2.pkg</a></td>
|
||||
</tr>
|
||||
-->
|
||||
<!--
|
||||
<tr>
|
||||
<td>
|
||||
Debian package:
|
||||
(Thanks to <a href="http://blog.rfquerin.org">Richard Querin</a>):
|
||||
</td>
|
||||
<td><a href="http://www.beckingham.net/task_1.4.1-1_i386.deb">task_1.4.1-1_i386.deb</a></td>
|
||||
<td><a href="http://www.beckingham.net/task_1.4.2-1_i386.deb">task_1.4.2-1_i386.deb</a></td>
|
||||
</tr>
|
||||
-->
|
||||
</table>
|
||||
|
||||
<h4>New in version 1.4.1 (7/18/2008)</h4>
|
||||
<h4>New in version 1.4.2 (9/18/2008)</h4>
|
||||
<ul>
|
||||
<li>Fixed bug: Descriptions could not be altered with "task 123 New description"
|
||||
<li>Tweak: For "task calendar" month names are now centered over the month
|
||||
<li>Removed TUTORIAL file contents in favor of online version
|
||||
<li>New Mac Intel-only Leopard (10.5) binary package
|
||||
<li>"task undo" can now retract a "task done" command, provided no
|
||||
reports have been run.
|
||||
<li>Task now correctly sorts on entire strings, instead of just the
|
||||
first character (thanks to Andy Lester).
|
||||
<li>Task now uses dashes (-----) to underline column headings when
|
||||
color is disabled (thanks to Vincent Fleuranceau).
|
||||
<li>Task now allows mixed case attribute names (pri:, PRI:, Pri: ...)
|
||||
and commands (add, ADD, Add ...) (thanks to Vincent Fleuranceau).
|
||||
<li>Task now supports a default project and priority for new tasks, via
|
||||
the new "default.project" and "default.priority" configuration variables
|
||||
(thanks to Vincent Fleuranceau).
|
||||
<li>Task supports improved word-wrapping to the terminal width.
|
||||
<li>Task now supports "default.command" configuration variable (for example
|
||||
it could contain "list due:tomorrow") which is the command that is run
|
||||
whenever task is invoked with no arguments.
|
||||
<li>Task supports modifying the existing description of a task, with the
|
||||
following syntax: task <id> "new description ...".
|
||||
<li>Fixed bug so that relative dates in filters (task list due:eom,
|
||||
task list due:tomorrow, task list due:23rd ...) are now properly
|
||||
supported.
|
||||
<li>Fixed bug so that source now properly includes <string.h> in
|
||||
order to build clean using gcc 4.3 (thanks to H. İbrahim Güngör)
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
@@ -114,6 +134,7 @@
|
||||
<li>OS X 10.5 Leopard
|
||||
<li>Fedora Core 8
|
||||
<li>Fedora Core 9
|
||||
<li>Ubuntu 7 Feisty Fawn
|
||||
<li>Ubuntu 8 Hardy Heron
|
||||
<li>Solaris 10
|
||||
<li>Cygwin 1.5.25-14
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
task long [tags] [attrs] desc...
|
||||
task ls [tags] [attrs] desc...
|
||||
task completed [tags] [attrs] desc...
|
||||
task ID [tags] [attrs] [desc...]
|
||||
task ID [tags] [attrs] ["desc..."]
|
||||
task ID /from/to/
|
||||
task delete ID
|
||||
task undelete ID
|
||||
|
||||
@@ -35,6 +35,21 @@
|
||||
<br />
|
||||
|
||||
<div class="content">
|
||||
<p>
|
||||
<h4>New in version 1.4.1 (7/18/2008)</h4>
|
||||
<a href="http://www.beckingham.net/task-1.4.1.tar.gz">task-1.4.1.tar.gz</a>
|
||||
<br />
|
||||
Mac OS X 10.5 (Leopard) Intel-only:
|
||||
<a href="http://www.beckingham.net/task-1.4.1.pkg">task-1.4.1.pkg</a>
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Fixed bug: Descriptions could not be altered with "task 123 New description"
|
||||
<li>Tweak: For "task calendar" month names are now centered over the month
|
||||
<li>Removed TUTORIAL file contents in favor of online version
|
||||
<li>New Mac Intel-only Leopard (10.5) binary package
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<h4>New in version 1.4.0 (7/10/2008)</h4>
|
||||
Source: <a href="http://www.beckingham.net/task-1.4.0.tar.gz">task-1.4.0.tar.gz</a>
|
||||
|
||||
48
ideas.txt
48
ideas.txt
@@ -20,51 +20,3 @@ Test Suite
|
||||
- debug=on to cause all cout to be csv
|
||||
- regression tests for every bug, command, feature
|
||||
|
||||
Recurrence
|
||||
+ new T::status recurring (stored as R)
|
||||
+ new user-specifiable attributes - recur:<duration> [until:<date>]
|
||||
+ duration:
|
||||
daily, day, 1d
|
||||
Nd
|
||||
weekly, 1w
|
||||
Nw
|
||||
biweekly
|
||||
monthly, 1m
|
||||
bimonthly
|
||||
Nm
|
||||
quarterly, 1q
|
||||
Nq
|
||||
biannual, biyearly
|
||||
annual, yearly, 1y
|
||||
Na, Ny
|
||||
+ recur: without due: => Error
|
||||
+ until: without recur: => Error
|
||||
+ New file format: supports status R, recur:, until:, base:, range:
|
||||
- on TDB.gc, adjust base: and compress range: for T::status == recurring
|
||||
- all recurring tasks are removed from lists by T::*pendingT, and a synthetic
|
||||
addendum is generated
|
||||
- when a recurring task is completed, range: is updated, and a synthetic
|
||||
task is added to completed.data that retains the attributes of the root
|
||||
|
||||
- Scenario:
|
||||
# Today = 6/22/2008
|
||||
% task add Friday due:6/15/2008 recur:weekly until 8/1/2008
|
||||
# task must generate a base and range
|
||||
# base:6/15/2008
|
||||
# range:-------
|
||||
# ^6/15
|
||||
# ^6/22
|
||||
# ^6/29
|
||||
# ^7/6
|
||||
# ^7/13
|
||||
# ^7/20
|
||||
# ^7/27
|
||||
% task ls
|
||||
1 Friday 6/15/2008 .lte. today (overdue)
|
||||
2 Friday 6/22/2008 .lte. today (due)
|
||||
3 Friday 6/29/2008 one recurrence
|
||||
4 Friday 7/6/2008 (not shown)
|
||||
5 Friday 7/13/2008 (not shown)
|
||||
6 Friday 7/20/2008 (not shown)
|
||||
7 Friday 7/27/2008 (not shown)
|
||||
|
||||
|
||||
21
src/Date.cpp
21
src/Date.cpp
@@ -543,22 +543,35 @@ bool Date::isRelativeDate (const std::string& input)
|
||||
else
|
||||
today += (dow - today.dayOfWeek ()) * 86400;
|
||||
|
||||
mT = today.mT;
|
||||
int m, d, y;
|
||||
today.toMDY (m, d, y);
|
||||
Date then (m, d, y);
|
||||
|
||||
mT = then.mT;
|
||||
return true;
|
||||
}
|
||||
else if (found == "today")
|
||||
{
|
||||
mT = today.mT;
|
||||
Date then (today.month (),
|
||||
today.day (),
|
||||
today.year ());
|
||||
mT = then.mT;
|
||||
return true;
|
||||
}
|
||||
else if (found == "tomorrow")
|
||||
{
|
||||
mT = today.mT + 86400;
|
||||
Date then (today.month (),
|
||||
today.day (),
|
||||
today.year ());
|
||||
mT = then.mT + 86400;
|
||||
return true;
|
||||
}
|
||||
else if (found == "yesterday")
|
||||
{
|
||||
mT = today.mT - 86400;
|
||||
Date then (today.month (),
|
||||
today.day (),
|
||||
today.year ());
|
||||
mT = then.mT - 86400;
|
||||
return true;
|
||||
}
|
||||
else if (found == "eom")
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
Table::Table ()
|
||||
: mRows (0)
|
||||
, mIntraPadding (1)
|
||||
, mDashedUnderline (false)
|
||||
, mTablePadding (0)
|
||||
, mTableWidth (0)
|
||||
, mSuppressWS (false)
|
||||
@@ -103,6 +104,12 @@ void Table::setTableWidth (int width)
|
||||
mTableWidth = width;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setTableDashedUnderline ()
|
||||
{
|
||||
mDashedUnderline = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int Table::addColumn (const std::string& col)
|
||||
{
|
||||
@@ -582,7 +589,57 @@ const std::string Table::formatHeader (
|
||||
fg, bg,
|
||||
Text::colorize (
|
||||
decoration, Text::nocolor,
|
||||
pad + preJust+ data + postJust + pad) + intraPad);
|
||||
pad + preJust + data + postJust + pad) + intraPad);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// data One Data to be rendered
|
||||
// width 8 Max data width for column/specified width
|
||||
// padding 1 Extra padding around data
|
||||
// intraPadding 0 Extra padding between columns only
|
||||
// justification right Alignment withing padding
|
||||
//
|
||||
// Returns:
|
||||
// "------- "
|
||||
// ------- data
|
||||
// ^ ^ padding
|
||||
// ^ intraPadding
|
||||
// ^^^^^^^^ width
|
||||
// ^ ^ fg/bg
|
||||
//
|
||||
const std::string Table::formatHeaderDashedUnderline (
|
||||
int col,
|
||||
int width,
|
||||
int padding)
|
||||
{
|
||||
assert (width > 0);
|
||||
|
||||
Text::color fg = getHeaderFg (col);
|
||||
Text::color bg = getHeaderBg (col);
|
||||
Text::color decoration = getHeaderUnderline (col);
|
||||
|
||||
std::string data = "";
|
||||
for (int i = 0; i < width; ++i)
|
||||
data += '-';
|
||||
|
||||
std::string pad = "";
|
||||
std::string intraPad = "";
|
||||
std::string attrOn = "";
|
||||
std::string attrOff = "";
|
||||
|
||||
for (int i = 0; i < padding; ++i)
|
||||
pad += " ";
|
||||
|
||||
// Place the value within the available space - justify.
|
||||
if (col < (signed) mColumns.size () - 1)
|
||||
for (int i = 0; i < getIntraPadding (); ++i)
|
||||
intraPad += " ";
|
||||
|
||||
return Text::colorize (
|
||||
fg, bg,
|
||||
Text::colorize (
|
||||
decoration, Text::nocolor,
|
||||
pad + data + pad) + intraPad);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -758,12 +815,12 @@ void Table::sort (std::vector <int>& order)
|
||||
break;
|
||||
|
||||
case ascendingCharacter:
|
||||
if ((char)*left > (char)*right)
|
||||
if ((std::string)*left > (std::string)*right)
|
||||
SWAP
|
||||
break;
|
||||
|
||||
case descendingCharacter:
|
||||
if ((char)*left < (char)*right)
|
||||
if ((std::string)*left < (std::string)*right)
|
||||
SWAP
|
||||
break;
|
||||
|
||||
@@ -861,13 +918,24 @@ const std::string Table::render ()
|
||||
|
||||
// Print column headers in column order.
|
||||
std::string output;
|
||||
std::string underline;
|
||||
for (size_t col = 0; col < mColumns.size (); ++col)
|
||||
{
|
||||
output += formatHeader (
|
||||
col,
|
||||
mCalculatedWidth[col],
|
||||
mColumnPadding[col]);
|
||||
|
||||
if (mDashedUnderline)
|
||||
underline += formatHeaderDashedUnderline (
|
||||
col,
|
||||
mCalculatedWidth[col],
|
||||
mColumnPadding[col]);
|
||||
}
|
||||
|
||||
output += "\n";
|
||||
if (underline.length ())
|
||||
output += underline + "\n";
|
||||
|
||||
// Determine row order, according to sort options.
|
||||
std::vector <int> order;
|
||||
|
||||
@@ -51,6 +51,7 @@ public:
|
||||
void setTablePadding (int);
|
||||
void setTableIntraPadding (int);
|
||||
void setTableWidth (int);
|
||||
void setTableDashedUnderline ();
|
||||
|
||||
int addColumn (const std::string&);
|
||||
void setColumnColor (int, Text::color, Text::color);
|
||||
@@ -98,6 +99,7 @@ private:
|
||||
just getJustification (const int, const int);
|
||||
just getHeaderJustification (const int);
|
||||
const std::string formatHeader (const int, const int, const int);
|
||||
const std::string formatHeaderDashedUnderline (const int, const int, const int);
|
||||
void formatCell (const int, const int, const int, const int, std::vector <std::string>&, std::string&);
|
||||
void optimize (std::string&);
|
||||
void sort (std::vector <int>&);
|
||||
@@ -110,6 +112,7 @@ private:
|
||||
std::map <std::string, std::string> mFg;
|
||||
std::map <std::string, std::string> mBg;
|
||||
std::map <std::string, std::string> mUnderline;
|
||||
bool mDashedUnderline;
|
||||
|
||||
// Padding...
|
||||
int mTablePadding;
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "Config.h"
|
||||
#include "Date.h"
|
||||
#include "Table.h"
|
||||
#include "color.h"
|
||||
#include "TDB.h"
|
||||
#include "T.h"
|
||||
#include "task.h"
|
||||
@@ -66,6 +67,20 @@ void handleAdd (const 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", ""));
|
||||
|
||||
// Override with default.priority, if not specified.
|
||||
if (task.getAttribute ("priority") == "")
|
||||
{
|
||||
std::string defaultPriority = conf.get ("default.priority", "");
|
||||
if (validPriority (defaultPriority))
|
||||
task.setAttribute ("priority", defaultPriority);
|
||||
}
|
||||
/**/
|
||||
|
||||
if (task.getDescription () == "")
|
||||
throw std::string ("Cannot add a blank task.");
|
||||
|
||||
@@ -203,6 +218,49 @@ void handleUndelete (TDB& tdb, T& task, Config& conf)
|
||||
<< "command is run immediately after the errant delete command." << std::endl;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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::vector <T> all;
|
||||
tdb.allPendingT (all);
|
||||
|
||||
int id = task.getId ();
|
||||
std::vector <T>::iterator it;
|
||||
for (it = all.begin (); it != all.end (); ++it)
|
||||
{
|
||||
if (it->getId () == id)
|
||||
{
|
||||
if (it->getStatus () == T::completed)
|
||||
{
|
||||
if (it->getAttribute ("recur") != "")
|
||||
{
|
||||
std::cout << "Task does not support 'undo' for recurring tasks." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
T restored (*it);
|
||||
restored.setStatus (T::pending);
|
||||
restored.removeAttribute ("end");
|
||||
tdb.modifyT (restored);
|
||||
|
||||
std::cout << "Task " << id << " successfully undone." << std::endl;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Task " << id << " is not done - therefore cannot be undone." << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void handleVersion (Config& conf)
|
||||
{
|
||||
@@ -217,6 +275,26 @@ void handleVersion (Config& conf)
|
||||
}
|
||||
#endif
|
||||
|
||||
// Create a table for the disclaimer.
|
||||
Table disclaimer;
|
||||
disclaimer.setTableWidth (width);
|
||||
disclaimer.addColumn (" ");
|
||||
disclaimer.setColumnWidth (0, Table::flexible);
|
||||
disclaimer.setColumnJustification (0, Table::left);
|
||||
disclaimer.addCell (disclaimer.addRow (), 0,
|
||||
"Task comes with ABSOLUTELY NO WARRANTY; for details read the COPYING file "
|
||||
"included. This is free software, and you are welcome to redistribute it "
|
||||
"under certain conditions; again, see the COPYING file for details.");
|
||||
|
||||
// Create a table for the URL.
|
||||
Table link;
|
||||
link.setTableWidth (width);
|
||||
link.addColumn (" ");
|
||||
link.setColumnWidth (0, Table::flexible);
|
||||
link.setColumnJustification (0, Table::left);
|
||||
link.addCell (link.addRow (), 0,
|
||||
"See http://www.beckingham.net/task.html for the latest releases and a full tutorial.");
|
||||
|
||||
// Create a table for output.
|
||||
Table table;
|
||||
table.setTableWidth (width);
|
||||
@@ -229,6 +307,8 @@ void handleVersion (Config& conf)
|
||||
table.setColumnUnderline (0);
|
||||
table.setColumnUnderline (1);
|
||||
}
|
||||
else
|
||||
table.setTableDashedUnderline ();
|
||||
|
||||
table.setColumnWidth (0, Table::minimum);
|
||||
table.setColumnWidth (1, Table::flexible);
|
||||
@@ -251,22 +331,14 @@ void handleVersion (Config& conf)
|
||||
|
||||
std::cout << "Copyright (C) 2006 - 2008, P. Beckingham."
|
||||
<< std::endl
|
||||
<< PACKAGE
|
||||
<< (conf.get ("color", true) ? Text::colorize (Text::bold, Text::nocolor, PACKAGE) : PACKAGE)
|
||||
<< " "
|
||||
<< VERSION
|
||||
<< std::endl
|
||||
<< std::endl
|
||||
<< "Task comes with ABSOLUTELY NO WARRANTY; for details read the COPYING file"
|
||||
<< std::endl
|
||||
<< "included. This is free software, and you are welcome to redistribute it"
|
||||
<< std::endl
|
||||
<< "under certain conditions; again, see the COPYING file for details."
|
||||
<< (conf.get ("color", true) ? Text::colorize (Text::bold, Text::nocolor, VERSION) : VERSION)
|
||||
<< std::endl
|
||||
<< disclaimer.render ()
|
||||
<< std::endl
|
||||
<< table.render ()
|
||||
<< std::endl
|
||||
<< "See http://www.beckingham.net/task.html for the latest releases and a full tutorial."
|
||||
<< std::endl
|
||||
<< link.render ()
|
||||
<< std::endl;
|
||||
|
||||
// Verify installation. This is mentioned in the documentation as the way to
|
||||
|
||||
@@ -141,6 +141,7 @@ static const char* commands[] =
|
||||
"summary",
|
||||
"tags",
|
||||
"undelete",
|
||||
"undo",
|
||||
"usage",
|
||||
"version",
|
||||
"",
|
||||
@@ -207,7 +208,7 @@ bool validDate (std::string& date, Config& conf)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static bool validPriority (const std::string& input)
|
||||
bool validPriority (const std::string& input)
|
||||
{
|
||||
if (input != "H" &&
|
||||
input != "M" &&
|
||||
@@ -370,8 +371,8 @@ void parse (
|
||||
std::string to;
|
||||
|
||||
// An id is the first argument found that contains all digits.
|
||||
if (command != "add" && // "add" doesn't require an ID
|
||||
task.getId () == 0 &&
|
||||
if (lowerCase (command) != "add" && // "add" doesn't require an ID
|
||||
task.getId () == 0 &&
|
||||
validId (arg))
|
||||
task.setId (::atoi (arg.c_str ()));
|
||||
|
||||
@@ -388,7 +389,7 @@ void parse (
|
||||
// value.
|
||||
else if ((colon = arg.find (":")) != std::string::npos)
|
||||
{
|
||||
std::string name = arg.substr (0, colon);
|
||||
std::string name = lowerCase (arg.substr (0, colon));
|
||||
std::string value = arg.substr (colon + 1, std::string::npos);
|
||||
|
||||
if (validAttribute (name, value, conf))
|
||||
@@ -412,11 +413,11 @@ void parse (
|
||||
// Command.
|
||||
else if (command == "")
|
||||
{
|
||||
if (isCommand (arg) && validCommand (arg))
|
||||
command = arg;
|
||||
std::string l = lowerCase (arg);
|
||||
if (isCommand (l) && validCommand (l))
|
||||
command = l;
|
||||
else
|
||||
descCandidate += arg;
|
||||
// throw std::string ("'") + arg + "' is not a valid command.";
|
||||
}
|
||||
|
||||
// Anything else is just considered description.
|
||||
|
||||
@@ -79,6 +79,7 @@ void filter (std::vector<T>& all, T& task)
|
||||
// Apply attribute filter.
|
||||
matches = 0;
|
||||
foreach (a, attrList)
|
||||
{
|
||||
if (a->first == "project")
|
||||
{
|
||||
if (a->second.length () <= refTask.getAttribute (a->first).length ())
|
||||
@@ -87,6 +88,7 @@ void filter (std::vector<T>& all, T& task)
|
||||
}
|
||||
else if (a->second == refTask.getAttribute (a->first))
|
||||
++matches;
|
||||
}
|
||||
|
||||
if (matches == attrList.size ())
|
||||
{
|
||||
@@ -143,7 +145,7 @@ void handleList (TDB& tdb, T& task, Config& conf)
|
||||
if (showAge) table.addColumn ("Age");
|
||||
table.addColumn ("Description");
|
||||
|
||||
if (conf.get ("color", true))
|
||||
if (conf.get (std::string ("color"), true))
|
||||
{
|
||||
table.setColumnUnderline (0);
|
||||
table.setColumnUnderline (1);
|
||||
@@ -153,6 +155,8 @@ void handleList (TDB& tdb, T& task, Config& conf)
|
||||
table.setColumnUnderline (5);
|
||||
if (showAge) table.setColumnUnderline (6);
|
||||
}
|
||||
else
|
||||
table.setTableDashedUnderline ();
|
||||
|
||||
table.setColumnWidth (0, Table::minimum);
|
||||
table.setColumnWidth (1, Table::minimum);
|
||||
@@ -291,6 +295,8 @@ void handleSmallList (TDB& tdb, T& task, Config& conf)
|
||||
table.setColumnUnderline (2);
|
||||
table.setColumnUnderline (3);
|
||||
}
|
||||
else
|
||||
table.setTableDashedUnderline ();
|
||||
|
||||
table.setColumnWidth (0, Table::minimum);
|
||||
table.setColumnWidth (1, Table::minimum);
|
||||
@@ -414,6 +420,8 @@ void handleCompleted (TDB& tdb, T& task, Config& conf)
|
||||
table.setColumnUnderline (1);
|
||||
table.setColumnUnderline (2);
|
||||
}
|
||||
else
|
||||
table.setTableDashedUnderline ();
|
||||
|
||||
table.setColumnWidth (0, Table::minimum);
|
||||
table.setColumnWidth (1, Table::minimum);
|
||||
@@ -493,6 +501,8 @@ void handleInfo (TDB& tdb, T& task, Config& conf)
|
||||
table.setColumnUnderline (0);
|
||||
table.setColumnUnderline (1);
|
||||
}
|
||||
else
|
||||
table.setTableDashedUnderline ();
|
||||
|
||||
table.setColumnWidth (0, Table::minimum);
|
||||
table.setColumnWidth (1, Table::minimum);
|
||||
@@ -710,6 +720,8 @@ void handleLongList (TDB& tdb, T& task, Config& conf)
|
||||
table.setColumnUnderline (7);
|
||||
if (showAge) table.setColumnUnderline (8);
|
||||
}
|
||||
else
|
||||
table.setTableDashedUnderline ();
|
||||
|
||||
table.setColumnWidth (0, Table::minimum);
|
||||
table.setColumnWidth (1, Table::minimum);
|
||||
@@ -913,6 +925,8 @@ void handleReportSummary (TDB& tdb, T& task, Config& conf)
|
||||
table.setColumnUnderline (2);
|
||||
table.setColumnUnderline (3);
|
||||
}
|
||||
else
|
||||
table.setTableDashedUnderline ();
|
||||
|
||||
table.setColumnJustification (1, Table::right);
|
||||
table.setColumnJustification (2, Table::right);
|
||||
@@ -1056,6 +1070,8 @@ void handleReportNext (TDB& tdb, T& task, Config& conf)
|
||||
table.setColumnUnderline (5);
|
||||
if (showAge) table.setColumnUnderline (6);
|
||||
}
|
||||
else
|
||||
table.setTableDashedUnderline ();
|
||||
|
||||
table.setColumnWidth (0, Table::minimum);
|
||||
table.setColumnWidth (1, Table::minimum);
|
||||
@@ -1275,6 +1291,8 @@ void handleReportHistory (TDB& tdb, T& task, Config& conf)
|
||||
table.setColumnUnderline (4);
|
||||
table.setColumnUnderline (5);
|
||||
}
|
||||
else
|
||||
table.setTableDashedUnderline ();
|
||||
|
||||
table.setColumnJustification (2, Table::right);
|
||||
table.setColumnJustification (3, Table::right);
|
||||
@@ -1462,6 +1480,8 @@ void handleReportGHistory (TDB& tdb, T& task, Config& conf)
|
||||
table.setColumnUnderline (0);
|
||||
table.setColumnUnderline (1);
|
||||
}
|
||||
else
|
||||
table.setTableDashedUnderline ();
|
||||
|
||||
// Determine the longest line.
|
||||
int maxLine = 0;
|
||||
@@ -1623,6 +1643,8 @@ void handleReportUsage (const TDB& tdb, T& task, Config& conf)
|
||||
table.setColumnUnderline (0);
|
||||
table.setColumnUnderline (1);
|
||||
}
|
||||
else
|
||||
table.setTableDashedUnderline ();
|
||||
|
||||
table.setColumnJustification (1, Table::right);
|
||||
table.sortOn (1, Table::descendingNumeric);
|
||||
@@ -1681,6 +1703,8 @@ std::string renderMonths (
|
||||
table.setColumnUnderline (i + 6);
|
||||
table.setColumnUnderline (i + 7);
|
||||
}
|
||||
else
|
||||
table.setTableDashedUnderline ();
|
||||
|
||||
table.setColumnJustification (i + 0, Table::right);
|
||||
table.setColumnJustification (i + 1, Table::right);
|
||||
@@ -1896,6 +1920,8 @@ void handleReportActive (TDB& tdb, T& task, Config& conf)
|
||||
table.setColumnUnderline (3);
|
||||
table.setColumnUnderline (4);
|
||||
}
|
||||
else
|
||||
table.setTableDashedUnderline ();
|
||||
|
||||
table.setColumnWidth (0, Table::minimum);
|
||||
table.setColumnWidth (1, Table::minimum);
|
||||
@@ -2011,6 +2037,8 @@ void handleReportOverdue (TDB& tdb, T& task, Config& conf)
|
||||
table.setColumnUnderline (3);
|
||||
table.setColumnUnderline (4);
|
||||
}
|
||||
else
|
||||
table.setTableDashedUnderline ();
|
||||
|
||||
table.setColumnWidth (0, Table::minimum);
|
||||
table.setColumnWidth (1, Table::minimum);
|
||||
@@ -2126,6 +2154,8 @@ void handleReportOldest (TDB& tdb, T& task, Config& conf)
|
||||
table.setColumnUnderline (5);
|
||||
if (showAge) table.setColumnUnderline (6);
|
||||
}
|
||||
else
|
||||
table.setTableDashedUnderline ();
|
||||
|
||||
table.setColumnWidth (0, Table::minimum);
|
||||
table.setColumnWidth (1, Table::minimum);
|
||||
@@ -2269,6 +2299,8 @@ void handleReportNewest (TDB& tdb, T& task, Config& conf)
|
||||
table.setColumnUnderline (5);
|
||||
if (showAge) table.setColumnUnderline (6);
|
||||
}
|
||||
else
|
||||
table.setTableDashedUnderline ();
|
||||
|
||||
table.setColumnWidth (0, Table::minimum);
|
||||
table.setColumnWidth (1, Table::minimum);
|
||||
|
||||
25
src/task.cpp
25
src/task.cpp
@@ -29,6 +29,7 @@
|
||||
#include <fstream>
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <pwd.h>
|
||||
@@ -125,6 +126,10 @@ static void shortUsage (Config& conf)
|
||||
table.addCell (row, 1, "task done ID");
|
||||
table.addCell (row, 2, "Marks the specified task as completed");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task undo ID");
|
||||
table.addCell (row, 2, "Marks the specified done task as pending, provided a report has not yet been run");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task projects");
|
||||
table.addCell (row, 2, "Shows a list of all project names used, and how many tasks are in each");
|
||||
@@ -295,10 +300,23 @@ int main (int argc, char** argv)
|
||||
if (conf.get ("command.logging") == "on")
|
||||
tdb.logCommand (argc, argv);
|
||||
|
||||
// Parse the command line.
|
||||
// If argc == 1 and the default.command configuration variable is set,
|
||||
// then use that, otherwise stick with argc/argv.
|
||||
std::vector <std::string> args;
|
||||
for (int i = 1; i < argc; ++i)
|
||||
args.push_back (argv[i]);
|
||||
std::string defaultCommand = conf.get ("default.command");
|
||||
if (argc == 1 && defaultCommand != "")
|
||||
{
|
||||
// Stuff the command line.
|
||||
split (args, defaultCommand, ' ');
|
||||
std::cout << "[task " << defaultCommand << "]" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Parse the command line.
|
||||
for (int i = 1; i < argc; ++i)
|
||||
args.push_back (argv[i]);
|
||||
}
|
||||
|
||||
std::string command;
|
||||
T task;
|
||||
parse (args, command, task, conf);
|
||||
@@ -316,6 +334,7 @@ int main (int argc, char** argv)
|
||||
else if (command == "delete") handleDelete (tdb, task, conf);
|
||||
else if (command == "start") handleStart (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);
|
||||
|
||||
@@ -55,6 +55,7 @@ for (typeof (c) *foreach_p = & (c); \
|
||||
|
||||
// parse.cpp
|
||||
void parse (std::vector <std::string>&, std::string&, T&, Config&);
|
||||
bool validPriority (const std::string&);
|
||||
bool validDate (std::string&, Config&);
|
||||
|
||||
// task.cpp
|
||||
@@ -76,6 +77,7 @@ void handleExport (TDB&, T&, Config&);
|
||||
void handleDelete (TDB&, T&, Config&);
|
||||
void handleStart (TDB&, T&, Config&);
|
||||
void handleDone (TDB&, T&, Config&);
|
||||
void handleUndo (TDB&, T&, Config&);
|
||||
void handleModify (TDB&, T&, Config&);
|
||||
void handleColor (Config&);
|
||||
|
||||
|
||||
15
src/tests/in
Executable file
15
src/tests/in
Executable file
@@ -0,0 +1,15 @@
|
||||
./task add monday due:monday
|
||||
./task add tuesday due:tuesday
|
||||
./task add wednesday due:wednesday
|
||||
./task add thursday due:thursday
|
||||
./task add friday due:friday
|
||||
./task add saturday due:saturday
|
||||
./task add sunday due:sunday
|
||||
./task add yesterday due:yesterday
|
||||
./task add today due:today
|
||||
./task add tomorrow due:tomorrow
|
||||
./task add eow due:eow
|
||||
./task add eom due:eom
|
||||
./task add eoy due:eoy
|
||||
./task add 21st due:21st
|
||||
|
||||
15
src/tests/out
Executable file
15
src/tests/out
Executable file
@@ -0,0 +1,15 @@
|
||||
./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
|
||||
|
||||
Reference in New Issue
Block a user