Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c393d47cdf | ||
|
|
3525b6db2c | ||
|
|
d50efe5e27 | ||
|
|
2c0a1ddb3a | ||
|
|
d7ac37783c | ||
|
|
03bb50c4ea | ||
|
|
1535010ac9 | ||
|
|
8d90035bbc | ||
|
|
fd7bb9daa9 | ||
|
|
88b12bc66a | ||
|
|
a8ac82ca22 | ||
|
|
438f3cb134 | ||
|
|
131693f617 | ||
|
|
07d1f63e31 |
2
AUTHORS
2
AUTHORS
@@ -5,4 +5,6 @@ With thanks to:
|
|||||||
Eugene Kramer
|
Eugene Kramer
|
||||||
SK
|
SK
|
||||||
Damian Glenny
|
Damian Glenny
|
||||||
|
Richard Querin
|
||||||
|
Bruce Israel
|
||||||
|
|
||||||
|
|||||||
16
ChangeLog
16
ChangeLog
@@ -5,11 +5,22 @@ Version numbers are of the form:
|
|||||||
where the x represents a major version number, or architecture. The y
|
where the x represents a major version number, or architecture. The y
|
||||||
represents a feature release, and the z represents a patch.
|
represents a feature release, and the z represents a patch.
|
||||||
|
|
||||||
1.2.0 (?)
|
------ plans -------------------------------------
|
||||||
- Command line specification of alternate .taskrc file
|
|
||||||
|
Configurable columns in reports
|
||||||
|
|
||||||
------ reality -----------------------------------
|
------ reality -----------------------------------
|
||||||
|
|
||||||
|
1.2.0 (6/13/2008)
|
||||||
|
+ Bug: "dateformat" configuration variable used to display dates, but
|
||||||
|
not parse them
|
||||||
|
+ "task list x" now performs a caseless comparison between "x" and the
|
||||||
|
description
|
||||||
|
+ Task sub projects supported
|
||||||
|
+ "showage" confguration determines whether "Age" column appears on the
|
||||||
|
"list" and "next" reports
|
||||||
|
+ Improved TUTORIAL
|
||||||
|
|
||||||
1.1.0 (6/7/2008)
|
1.1.0 (6/7/2008)
|
||||||
+ "blanklines" configuration to stop displaying unnecessary white
|
+ "blanklines" configuration to stop displaying unnecessary white
|
||||||
space and thus work better on small-screen devices
|
space and thus work better on small-screen devices
|
||||||
@@ -127,6 +138,7 @@ represents a feature release, and the z represents a patch.
|
|||||||
+ File locking
|
+ File locking
|
||||||
+ retain deleted tasks
|
+ retain deleted tasks
|
||||||
+ "task info ID" report showing all metadata
|
+ "task info ID" report showing all metadata
|
||||||
|
+ File format v2
|
||||||
|
|
||||||
[Development hiatus while planning for T, TDB API, new features and the future
|
[Development hiatus while planning for T, TDB API, new features and the future
|
||||||
of the project. Seeded to two testers for feedback, suggestions.]
|
of the project. Seeded to two testers for feedback, suggestions.]
|
||||||
|
|||||||
2
NEWS
2
NEWS
@@ -1,4 +1,4 @@
|
|||||||
Welcome to Task 1.1.0.
|
Welcome to Task 1.2.0.
|
||||||
|
|
||||||
Task has been built and tested on the following configurations:
|
Task has been built and tested on the following configurations:
|
||||||
|
|
||||||
|
|||||||
89
TUTORIAL
89
TUTORIAL
@@ -1,4 +1,4 @@
|
|||||||
Task program tutorial, for version 1.1.0
|
Task program tutorial, for version 1.2.0
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
||||||
This guide shows how to quickly set up the task program, and become proficient
|
This guide shows how to quickly set up the task program, and become proficient
|
||||||
@@ -21,10 +21,10 @@ Build the task program according to the directions in the INSTALL file. This
|
|||||||
transcript illustrates a typical installation:
|
transcript illustrates a typical installation:
|
||||||
|
|
||||||
% ls
|
% ls
|
||||||
task-1.1.0.tar.gz
|
task-1.2.0.tar.gz
|
||||||
% gunzip task-1.1.0.tar.gz
|
% gunzip task-1.2.0.tar.gz
|
||||||
% tar xf task-1.1.0.tar
|
% tar xf task-1.2.0.tar
|
||||||
% cd task-1.1.0
|
% cd task-1.2.0
|
||||||
% ./configure
|
% ./configure
|
||||||
...
|
...
|
||||||
% make
|
% make
|
||||||
@@ -67,7 +67,7 @@ interface. Let us take a look at those tasks:
|
|||||||
|
|
||||||
% task ls
|
% task ls
|
||||||
|
|
||||||
ID Project Pri Description
|
ID Project Pri Description
|
||||||
1 Book plane ticket
|
1 Book plane ticket
|
||||||
2 Rent a tux
|
2 Rent a tux
|
||||||
3 Reserve a rental car
|
3 Reserve a rental car
|
||||||
@@ -97,7 +97,7 @@ a project to these tasks:
|
|||||||
% task 4 project:Family
|
% task 4 project:Family
|
||||||
% task ls
|
% task ls
|
||||||
|
|
||||||
ID Project Pri Description
|
ID Project Pri Description
|
||||||
3 Family Send John a birthday card
|
3 Family Send John a birthday card
|
||||||
2 Wedding Reserve a rental car
|
2 Wedding Reserve a rental car
|
||||||
1 Wedding Book plane ticket
|
1 Wedding Book plane ticket
|
||||||
@@ -107,12 +107,46 @@ attributes changed (project, for example), the ids are prone to change. But the
|
|||||||
id numbers will remain valid until the next 'ls' command is run. You should
|
id numbers will remain valid until the next 'ls' command is run. You should
|
||||||
only use the ids from the most recent 'ls' command. The ids change, because
|
only use the ids from the most recent 'ls' command. The ids change, because
|
||||||
task is always trying to use small numbers so that it is easy for you to enter
|
task is always trying to use small numbers so that it is easy for you to enter
|
||||||
them correctly. Now that projects are assigned, we can look at just the Wedding
|
them correctly.
|
||||||
project tasks:
|
|
||||||
|
Subprojects are supported. If you have a project "Wedding", you can specify
|
||||||
|
that a task is a subproject "Transport" of "Wedding" by assigning the project
|
||||||
|
"Wedding.Transport". Let's do this:
|
||||||
|
|
||||||
|
% task 2 project:Wedding.Transport
|
||||||
|
% task ls
|
||||||
|
|
||||||
|
ID Project Pri Description
|
||||||
|
3 Family Send John a birthday card
|
||||||
|
2 Wedding.Transport Reserve a rental car
|
||||||
|
1 Wedding Book plane ticket
|
||||||
|
|
||||||
|
Task matches the leftmost part of the project when searching, so projects
|
||||||
|
may be abbreviated:
|
||||||
|
|
||||||
|
% task ls project:Wedding.Tra
|
||||||
|
|
||||||
|
ID Project Pri Description
|
||||||
|
2 Wedding.Transport Reserve a rental car
|
||||||
|
|
||||||
|
This way of matching projects can be used to see all tasks under the
|
||||||
|
"Wedding" project and all subprojects:
|
||||||
|
|
||||||
% task ls project:Wedding
|
% task ls project:Wedding
|
||||||
|
|
||||||
ID Project Pri Description
|
ID Project Pri Description
|
||||||
|
2 Wedding.Transport Reserve a rental car
|
||||||
|
1 Wedding Book plane ticket
|
||||||
|
|
||||||
|
Let's reassign 2 back to the "Wedding" project:
|
||||||
|
|
||||||
|
% task 2 project:Wedding
|
||||||
|
|
||||||
|
Now that projects are assigned, we can look at just the Wedding project tasks:
|
||||||
|
|
||||||
|
% task ls project:Wedding
|
||||||
|
|
||||||
|
ID Project Pri Description
|
||||||
1 Wedding Book plane ticket
|
1 Wedding Book plane ticket
|
||||||
2 Wedding Reserve a rental car
|
2 Wedding Reserve a rental car
|
||||||
|
|
||||||
@@ -121,14 +155,14 @@ could also have requested:
|
|||||||
|
|
||||||
% task ls ticket plane
|
% task ls ticket plane
|
||||||
|
|
||||||
ID Project Pri Description
|
ID Project Pri Description
|
||||||
1 Wedding Book plane ticket
|
1 Wedding Book plane ticket
|
||||||
|
|
||||||
Now let's prioritize. Priorities can be H, M or L (High, Medium, Low).
|
Now let's prioritize. Priorities can be H, M or L (High, Medium, Low).
|
||||||
|
|
||||||
% task ls
|
% task ls
|
||||||
|
|
||||||
ID Project Pri Description
|
ID Project Pri Description
|
||||||
3 Family Send John a birthday card
|
3 Family Send John a birthday card
|
||||||
2 Wedding Reserve a rental car
|
2 Wedding Reserve a rental car
|
||||||
1 Wedding Book plane ticket
|
1 Wedding Book plane ticket
|
||||||
@@ -140,7 +174,7 @@ Now let's prioritize. Priorities can be H, M or L (High, Medium, Low).
|
|||||||
% task 3 pri:H
|
% task 3 pri:H
|
||||||
% task ls
|
% task ls
|
||||||
|
|
||||||
ID Project Pri Description
|
ID Project Pri Description
|
||||||
3 Family H Send John a birthday card
|
3 Family H Send John a birthday card
|
||||||
1 Wedding H Book plane ticket
|
1 Wedding H Book plane ticket
|
||||||
2 Wedding M Reserve a rental car
|
2 Wedding M Reserve a rental car
|
||||||
@@ -161,7 +195,7 @@ command provides more:
|
|||||||
|
|
||||||
% task list
|
% task list
|
||||||
|
|
||||||
ID Project Pri Due Active Age Description
|
ID Project Pri Due Active Age Description
|
||||||
3 Family H 4 mins Send John a birthday card
|
3 Family H 4 mins Send John a birthday card
|
||||||
1 Wedding H 5 mins Book plane ticket
|
1 Wedding H 5 mins Book plane ticket
|
||||||
2 Wedding M 5 mins Reserve a rental car
|
2 Wedding M 5 mins Reserve a rental car
|
||||||
@@ -173,7 +207,7 @@ sorted by due date, then priority. Let's add due dates:
|
|||||||
% task 1 due:7/31/2008
|
% task 1 due:7/31/2008
|
||||||
% task list
|
% task list
|
||||||
|
|
||||||
ID Project Pri Due Active Age Description
|
ID Project Pri Due Active Age Description
|
||||||
3 Family H 6/25/2008 6 mins Send John a birthday card
|
3 Family H 6/25/2008 6 mins Send John a birthday card
|
||||||
1 Wedding H 7/31/2008 7 mins Book plane ticket
|
1 Wedding H 7/31/2008 7 mins Book plane ticket
|
||||||
2 Wedding M 7 mins Reserve a rental car
|
2 Wedding M 7 mins Reserve a rental car
|
||||||
@@ -212,7 +246,7 @@ labels.
|
|||||||
|
|
||||||
% task list
|
% task list
|
||||||
|
|
||||||
ID Project Pri Due Active Age Description
|
ID Project Pri Due Active Age Description
|
||||||
3 Family H 6/25/2008 8 mins Send John a birthday card
|
3 Family H 6/25/2008 8 mins Send John a birthday card
|
||||||
1 Wedding H 7/31/2008 9 mins Book plane ticket
|
1 Wedding H 7/31/2008 9 mins Book plane ticket
|
||||||
2 Wedding M 9 mins Reserve a rental car
|
2 Wedding M 9 mins Reserve a rental car
|
||||||
@@ -224,7 +258,7 @@ labels.
|
|||||||
|
|
||||||
% task list +phone
|
% task list +phone
|
||||||
|
|
||||||
ID Project Pri Due Active Age Description
|
ID Project Pri Due Active Age Description
|
||||||
1 Wedding H 7/31/2008 9 mins Book plane ticket
|
1 Wedding H 7/31/2008 9 mins Book plane ticket
|
||||||
2 Wedding M 9 mins Reserve a rental car
|
2 Wedding M 9 mins Reserve a rental car
|
||||||
|
|
||||||
@@ -266,7 +300,7 @@ with no arguments will generate a help message that lists all these commands.
|
|||||||
|
|
||||||
% task summary
|
% task summary
|
||||||
|
|
||||||
Project Remaining Avg age Complete 0% 100%
|
Project Remaining Avg age Complete 0% 100%
|
||||||
Errands 1 3 days 50% XXXXXXXXXXXXXXXX
|
Errands 1 3 days 50% XXXXXXXXXXXXXXXX
|
||||||
Birthdays 3 7 mths 0%
|
Birthdays 3 7 mths 0%
|
||||||
Car 2 2 wks 25% XXXXXXXXX
|
Car 2 2 wks 25% XXXXXXXXX
|
||||||
@@ -316,14 +350,14 @@ with no arguments will generate a help message that lists all these commands.
|
|||||||
|
|
||||||
% task list
|
% task list
|
||||||
|
|
||||||
ID Project Pri Due Active Age Description
|
ID Project Pri Due Active Age Description
|
||||||
12 Errand L Remember to deposit check
|
12 Errand L Remember to deposit check
|
||||||
...
|
...
|
||||||
|
|
||||||
% task start 12
|
% task start 12
|
||||||
% task list
|
% task list
|
||||||
|
|
||||||
ID Project Pri Due Active Age Description
|
ID Project Pri Due Active Age Description
|
||||||
12 Errand L * 3 days Remember to deposit check
|
12 Errand L * 3 days Remember to deposit check
|
||||||
...
|
...
|
||||||
|
|
||||||
@@ -351,7 +385,7 @@ with no arguments will generate a help message that lists all these commands.
|
|||||||
This report shows you an overview of how many tasks were added, completed and
|
This report shows you an overview of how many tasks were added, completed and
|
||||||
deleted, by month. It looks like this:
|
deleted, by month. It looks like this:
|
||||||
|
|
||||||
% task history
|
% task history
|
||||||
|
|
||||||
Year Month Added Completed Deleted Net
|
Year Month Added Completed Deleted Net
|
||||||
2008 March 21 16 0 5
|
2008 March 21 16 0 5
|
||||||
@@ -409,14 +443,14 @@ with no arguments will generate a help message that lists all these commands.
|
|||||||
|
|
||||||
% task ls
|
% task ls
|
||||||
|
|
||||||
ID Project Pri Description
|
ID Project Pri Description
|
||||||
12 Errand L Remember to deposit chekc
|
12 Errand L Remember to deposit chekc
|
||||||
...
|
...
|
||||||
|
|
||||||
% task 12 Remember to deposit bonus check
|
% task 12 Remember to deposit bonus check
|
||||||
% task ls
|
% task ls
|
||||||
|
|
||||||
ID Project Pri Description
|
ID Project Pri Description
|
||||||
12 Errand L Remember to deposit bonus check
|
12 Errand L Remember to deposit bonus check
|
||||||
...
|
...
|
||||||
|
|
||||||
@@ -430,14 +464,14 @@ with no arguments will generate a help message that lists all these commands.
|
|||||||
|
|
||||||
% task ls
|
% task ls
|
||||||
|
|
||||||
ID Project Pri Description
|
ID Project Pri Description
|
||||||
12 Errand L Remember to deposit chekc
|
12 Errand L Remember to deposit chekc
|
||||||
...
|
...
|
||||||
|
|
||||||
% task 12 /chekc/check/
|
% task 12 /chekc/check/
|
||||||
% task ls
|
% task ls
|
||||||
|
|
||||||
ID Project Pri Description
|
ID Project Pri Description
|
||||||
12 Errand L Remember to deposit check
|
12 Errand L Remember to deposit check
|
||||||
...
|
...
|
||||||
|
|
||||||
@@ -650,6 +684,9 @@ Configuring Task
|
|||||||
YMD 20080607
|
YMD 20080607
|
||||||
m-d-y 6-7-08
|
m-d-y 6-7-08
|
||||||
|
|
||||||
|
showage May be "yes" or "no". Determines whether the "Age"
|
||||||
|
column appears on the "list" and "next" reports.
|
||||||
|
|
||||||
color May be "on" or "off". Determines whether task uses
|
color May be "on" or "off". Determines whether task uses
|
||||||
color.
|
color.
|
||||||
|
|
||||||
@@ -662,7 +699,7 @@ Configuring Task
|
|||||||
color.active below) and one optional background color.
|
color.active below) and one optional background color.
|
||||||
color.tagged
|
color.tagged
|
||||||
For example, the value may be:
|
For example, the value may be:
|
||||||
|
|
||||||
bold_red on_bright_yellow
|
bold_red on_bright_yellow
|
||||||
|
|
||||||
color.tag.X Colors any task that has the tag X.
|
color.tag.X Colors any task that has the tag X.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# Process this file with autoconf to produce a configure script.
|
# Process this file with autoconf to produce a configure script.
|
||||||
|
|
||||||
AC_PREREQ(2.61)
|
AC_PREREQ(2.61)
|
||||||
AC_INIT(task, 1.1.0, bugs@beckingham.net)
|
AC_INIT(task, 1.2.0, bugs@beckingham.net)
|
||||||
AM_INIT_AUTOMAKE
|
AM_INIT_AUTOMAKE
|
||||||
AC_CONFIG_SRCDIR([src/task.cpp])
|
AC_CONFIG_SRCDIR([src/task.cpp])
|
||||||
AC_CONFIG_HEADER([auto.h])
|
AC_CONFIG_HEADER([auto.h])
|
||||||
|
|||||||
2
src/.gitignore
vendored
2
src/.gitignore
vendored
@@ -1,2 +1,2 @@
|
|||||||
Makefile
|
./Makefile
|
||||||
*.o
|
*.o
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ void Config::createDefault (const std::string& file)
|
|||||||
set ("data.location", taskDir);
|
set ("data.location", taskDir);
|
||||||
set ("command.logging", "off");
|
set ("command.logging", "off");
|
||||||
set ("confirmation", "yes");
|
set ("confirmation", "yes");
|
||||||
set ("next", 2);
|
set ("next", 1);
|
||||||
set ("curses", "on");
|
set ("curses", "on");
|
||||||
set ("color", "on");
|
set ("color", "on");
|
||||||
set ("color.overdue", "red");
|
set ("color.overdue", "red");
|
||||||
|
|||||||
152
src/Date.cpp
152
src/Date.cpp
@@ -57,29 +57,134 @@ Date::Date (const int m, const int d, const int y)
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
Date::Date (const std::string& mdy)
|
Date::Date (const std::string& mdy, const std::string format /* = "m/d/Y" */)
|
||||||
{
|
{
|
||||||
size_t firstSlash = mdy.find ("/");
|
int month = 0;
|
||||||
size_t secondSlash = mdy.find ("/", firstSlash + 1);
|
int day = 0;
|
||||||
if (firstSlash != std::string::npos &&
|
int year = 0;
|
||||||
secondSlash != std::string::npos)
|
|
||||||
{
|
|
||||||
int m = ::atoi (mdy.substr (0, firstSlash ).c_str ());
|
|
||||||
int d = ::atoi (mdy.substr (firstSlash + 1, secondSlash - firstSlash).c_str ());
|
|
||||||
int y = ::atoi (mdy.substr (secondSlash + 1, std::string::npos ).c_str ());
|
|
||||||
if (!valid (m, d, y))
|
|
||||||
throw std::string ("\"") + mdy + "\" is not a valid date.";
|
|
||||||
|
|
||||||
// Duplicate Date::Date (const int, const int, const int);
|
unsigned int i = 0; // Index into mdy.
|
||||||
struct tm t = {0};
|
|
||||||
t.tm_mday = d;
|
for (unsigned int f = 0; f < format.length (); ++f)
|
||||||
t.tm_mon = m - 1;
|
{
|
||||||
t.tm_year = y - 1900;
|
switch (format[f])
|
||||||
|
{
|
||||||
|
// Single or double digit.
|
||||||
|
case 'm':
|
||||||
|
if (i >= mdy.length () ||
|
||||||
|
! ::isdigit (mdy[i]))
|
||||||
|
{
|
||||||
|
throw std::string ("\"") + mdy + "\" is not a valid date.";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i + 1 < mdy.length () &&
|
||||||
|
mdy[i + 0] == '1' &&
|
||||||
|
(mdy[i + 1] == '0' || mdy[i + 1] == '1' || mdy[i + 1] == '2'))
|
||||||
|
{
|
||||||
|
month = ::atoi (mdy.substr (i, 2).c_str ());
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
month = ::atoi (mdy.substr (i, 1).c_str ());
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'd':
|
||||||
|
if (i >= mdy.length () ||
|
||||||
|
! ::isdigit (mdy[i]))
|
||||||
|
{
|
||||||
|
throw std::string ("\"") + mdy + "\" is not a valid date.";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i + 1 < mdy.length () &&
|
||||||
|
(mdy[i + 0] == '1' || mdy[i + 0] == '2' || mdy[i + 0] == '3') &&
|
||||||
|
::isdigit (mdy[i + 1]))
|
||||||
|
{
|
||||||
|
day = ::atoi (mdy.substr (i, 2).c_str ());
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
day = ::atoi (mdy.substr (i, 1).c_str ());
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Double digit.
|
||||||
|
case 'y':
|
||||||
|
if (i + 1 >= mdy.length () ||
|
||||||
|
! ::isdigit (mdy[i + 0]) ||
|
||||||
|
! ::isdigit (mdy[i + 1]))
|
||||||
|
{
|
||||||
|
throw std::string ("\"") + mdy + "\" is not a valid date.";
|
||||||
|
}
|
||||||
|
|
||||||
|
year = ::atoi (mdy.substr (i, 2).c_str ()) + 2000;
|
||||||
|
i += 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'M':
|
||||||
|
if (i + 1 >= mdy.length () ||
|
||||||
|
! ::isdigit (mdy[i + 0]) ||
|
||||||
|
! ::isdigit (mdy[i + 1]))
|
||||||
|
{
|
||||||
|
throw std::string ("\"") + mdy + "\" is not a valid date.";
|
||||||
|
}
|
||||||
|
|
||||||
|
month = ::atoi (mdy.substr (i, 2).c_str ());
|
||||||
|
i += 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'D':
|
||||||
|
if (i + 1 >= mdy.length () ||
|
||||||
|
! ::isdigit (mdy[i + 0]) ||
|
||||||
|
! ::isdigit (mdy[i + 1]))
|
||||||
|
{
|
||||||
|
throw std::string ("\"") + mdy + "\" is not a valid date.";
|
||||||
|
}
|
||||||
|
|
||||||
|
day = ::atoi (mdy.substr (i, 2).c_str ());
|
||||||
|
i += 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Quadruple digit.
|
||||||
|
case 'Y':
|
||||||
|
if (i + 3 >= mdy.length () ||
|
||||||
|
! ::isdigit (mdy[i + 0]) ||
|
||||||
|
! ::isdigit (mdy[i + 1]) ||
|
||||||
|
! ::isdigit (mdy[i + 2]) ||
|
||||||
|
! ::isdigit (mdy[i + 3]))
|
||||||
|
{
|
||||||
|
throw std::string ("\"") + mdy + "\" is not a valid date.";
|
||||||
|
}
|
||||||
|
|
||||||
|
year = ::atoi (mdy.substr (i, 4).c_str ());
|
||||||
|
i += 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (i >= mdy.length () ||
|
||||||
|
mdy[i] != format[f])
|
||||||
|
{
|
||||||
|
throw std::string ("\"") + mdy + "\" is not a valid date.";
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!valid (month, day, year))
|
||||||
|
throw std::string ("\"") + mdy + "\" is not a valid date.";
|
||||||
|
|
||||||
|
// Duplicate Date::Date (const int, const int, const int);
|
||||||
|
struct tm t = {0};
|
||||||
|
t.tm_mday = day;
|
||||||
|
t.tm_mon = month - 1;
|
||||||
|
t.tm_year = year - 1900;
|
||||||
|
|
||||||
mT = mktime (&t);
|
mT = mktime (&t);
|
||||||
}
|
|
||||||
else
|
|
||||||
throw std::string ("\"") + mdy + "\" is not a valid date.";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -118,15 +223,6 @@ void Date::toMDY (int& m, int& d, int& y)
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
std::string Date::toString (const std::string& format /*= "m/d/Y"*/)
|
std::string Date::toString (const std::string& format /*= "m/d/Y"*/)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
int m, d, y;
|
|
||||||
toMDY (m, d, y);
|
|
||||||
|
|
||||||
char formatted [11];
|
|
||||||
sprintf (formatted, "%d/%d/%d", m, d, y);
|
|
||||||
return std::string (formatted);
|
|
||||||
*/
|
|
||||||
|
|
||||||
std::string formatted;
|
std::string formatted;
|
||||||
for (unsigned int i = 0; i < format.length (); ++i)
|
for (unsigned int i = 0; i < format.length (); ++i)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public:
|
|||||||
Date ();
|
Date ();
|
||||||
Date (time_t);
|
Date (time_t);
|
||||||
Date (const int, const int, const int);
|
Date (const int, const int, const int);
|
||||||
Date (const std::string&);
|
Date (const std::string&, const std::string format = "m/d/Y");
|
||||||
Date (const Date&);
|
Date (const Date&);
|
||||||
virtual ~Date ();
|
virtual ~Date ();
|
||||||
|
|
||||||
|
|||||||
14
src/T.cpp
14
src/T.cpp
@@ -275,20 +275,8 @@ const std::string T::compose () const
|
|||||||
int count = 0;
|
int count = 0;
|
||||||
foreach (i, mAttributes)
|
foreach (i, mAttributes)
|
||||||
{
|
{
|
||||||
std::string converted = i->second;
|
|
||||||
|
|
||||||
// Date attributes may need conversion to epoch.
|
|
||||||
if (i->first == "due" ||
|
|
||||||
i->first == "start" ||
|
|
||||||
i->first == "entry" ||
|
|
||||||
i->first == "end")
|
|
||||||
{
|
|
||||||
if (i->second.find ("/") != std::string::npos)
|
|
||||||
validDate (converted);
|
|
||||||
}
|
|
||||||
|
|
||||||
line += (count > 0 ? " " : "");
|
line += (count > 0 ? " " : "");
|
||||||
line += i->first + ":" + converted;
|
line += i->first + ":" + i->second;
|
||||||
|
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -659,6 +659,12 @@ void Table::suppressWS ()
|
|||||||
mSuppressWS = true;
|
mSuppressWS = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void Table::setDateFormat (const std::string& dateFormat)
|
||||||
|
{
|
||||||
|
mDateFormat = dateFormat;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
int Table::rowCount ()
|
int Table::rowCount ()
|
||||||
{
|
{
|
||||||
@@ -771,8 +777,8 @@ void Table::sort (std::vector <int>& order)
|
|||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Date dl ((std::string)*left);
|
Date dl ((std::string)*left, mDateFormat);
|
||||||
Date dr ((std::string)*right);
|
Date dr ((std::string)*right, mDateFormat);
|
||||||
if (dl > dr)
|
if (dl > dr)
|
||||||
SWAP
|
SWAP
|
||||||
}
|
}
|
||||||
@@ -789,8 +795,8 @@ void Table::sort (std::vector <int>& order)
|
|||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Date dl ((std::string)*left);
|
Date dl ((std::string)*left, mDateFormat);
|
||||||
Date dr ((std::string)*right);
|
Date dr ((std::string)*right, mDateFormat);
|
||||||
if (dl < dr)
|
if (dl < dr)
|
||||||
SWAP
|
SWAP
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ public:
|
|||||||
void setCellBg (int, int, Text::color);
|
void setCellBg (int, int, Text::color);
|
||||||
|
|
||||||
void suppressWS ();
|
void suppressWS ();
|
||||||
|
void setDateFormat (const std::string&);
|
||||||
|
|
||||||
int rowCount ();
|
int rowCount ();
|
||||||
int columnCount ();
|
int columnCount ();
|
||||||
@@ -128,6 +129,7 @@ private:
|
|||||||
|
|
||||||
// Misc...
|
// Misc...
|
||||||
bool mSuppressWS;
|
bool mSuppressWS;
|
||||||
|
std::string mDateFormat;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -185,29 +185,13 @@ static bool isCommand (const std::string& candidate)
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
bool validDate (std::string& date)
|
bool validDate (std::string& date, Config& conf)
|
||||||
{
|
{
|
||||||
size_t firstSlash = date.find ("/");
|
Date test (date, conf.get ("dateformat", "m/d/Y"));
|
||||||
size_t secondSlash = date.find ("/", firstSlash + 1);
|
|
||||||
if (firstSlash != std::string::npos &&
|
|
||||||
secondSlash != std::string::npos)
|
|
||||||
{
|
|
||||||
int m = ::atoi (date.substr (0, firstSlash ).c_str ());
|
|
||||||
int d = ::atoi (date.substr (firstSlash + 1, secondSlash - firstSlash).c_str ());
|
|
||||||
int y = ::atoi (date.substr (secondSlash + 1, std::string::npos ).c_str ());
|
|
||||||
if (!Date::valid (m, d, y))
|
|
||||||
throw std::string ("\"") + date + "\" is not a valid date.";
|
|
||||||
|
|
||||||
// Convert to epoch form.
|
char epoch[12];
|
||||||
Date dt (m, d, y);
|
sprintf (epoch, "%d", (int) test.toEpoch ());
|
||||||
time_t t;
|
date = epoch;
|
||||||
dt.toEpoch (t);
|
|
||||||
char converted[12];
|
|
||||||
sprintf (converted, "%u", (unsigned int) t);
|
|
||||||
date = converted;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
throw std::string ("Badly formed date - use the MM/DD/YYYY format");
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -227,7 +211,7 @@ static bool validPriority (std::string& input)
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
static bool validAttribute (std::string& name, std::string& value)
|
static bool validAttribute (std::string& name, std::string& value, Config& conf)
|
||||||
{
|
{
|
||||||
guess ("attribute", attributes, name);
|
guess ("attribute", attributes, name);
|
||||||
|
|
||||||
@@ -235,7 +219,7 @@ static bool validAttribute (std::string& name, std::string& value)
|
|||||||
guess ("color", colors, value);
|
guess ("color", colors, value);
|
||||||
|
|
||||||
else if (name == "due" && value != "")
|
else if (name == "due" && value != "")
|
||||||
validDate (value);
|
validDate (value, conf);
|
||||||
|
|
||||||
else if (name == "priority")
|
else if (name == "priority")
|
||||||
{
|
{
|
||||||
@@ -335,7 +319,8 @@ static bool validSubstitution (
|
|||||||
void parse (
|
void parse (
|
||||||
std::vector <std::string>& args,
|
std::vector <std::string>& args,
|
||||||
std::string& command,
|
std::string& command,
|
||||||
T& task)
|
T& task,
|
||||||
|
Config& conf)
|
||||||
{
|
{
|
||||||
command = "";
|
command = "";
|
||||||
|
|
||||||
@@ -369,7 +354,7 @@ void parse (
|
|||||||
std::string name = arg.substr (0, colon);
|
std::string name = arg.substr (0, colon);
|
||||||
std::string value = arg.substr (colon + 1, std::string::npos);
|
std::string value = arg.substr (colon + 1, std::string::npos);
|
||||||
|
|
||||||
if (validAttribute (name, value))
|
if (validAttribute (name, value, conf))
|
||||||
task.setAttribute (name, value);
|
task.setAttribute (name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -210,8 +210,9 @@ void autoColorize (T& task, Text::color& fg, Text::color& bg)
|
|||||||
{
|
{
|
||||||
if (it->first.substr (0, 14) == "color.keyword.")
|
if (it->first.substr (0, 14) == "color.keyword.")
|
||||||
{
|
{
|
||||||
std::string value = it->first.substr (14, std::string::npos);
|
std::string value = lowerCase (it->first.substr (14, std::string::npos));
|
||||||
if (task.getDescription ().find (value) != std::string::npos)
|
std::string desc = lowerCase (task.getDescription ());
|
||||||
|
if (desc.find (value) != std::string::npos)
|
||||||
{
|
{
|
||||||
fg = gsFg[it->first];
|
fg = gsFg[it->first];
|
||||||
bg = gsBg[it->first];
|
bg = gsBg[it->first];
|
||||||
|
|||||||
167
src/task.cpp
167
src/task.cpp
@@ -70,6 +70,7 @@ void usage (Config& conf)
|
|||||||
table.setColumnWidth (1, Table::minimum);
|
table.setColumnWidth (1, Table::minimum);
|
||||||
table.setColumnWidth (2, Table::flexible);
|
table.setColumnWidth (2, Table::flexible);
|
||||||
table.setTableWidth (width);
|
table.setTableWidth (width);
|
||||||
|
table.setDateFormat (conf.get ("dateformat", "m/d/Y"));
|
||||||
|
|
||||||
int row = table.addRow ();
|
int row = table.addRow ();
|
||||||
table.addCell (row, 0, "Usage:");
|
table.addCell (row, 0, "Usage:");
|
||||||
@@ -242,7 +243,7 @@ int main (int argc, char** argv)
|
|||||||
|
|
||||||
std::string command;
|
std::string command;
|
||||||
T task;
|
T task;
|
||||||
parse (args, command, task);
|
parse (args, command, task, conf);
|
||||||
|
|
||||||
if (command == "add") handleAdd (tdb, task, conf);
|
if (command == "add") handleAdd (tdb, task, conf);
|
||||||
else if (command == "projects") handleProjects (tdb, task, conf);
|
else if (command == "projects") handleProjects (tdb, task, conf);
|
||||||
@@ -326,6 +327,7 @@ void handleProjects (const TDB& tdb, T& task, Config& conf)
|
|||||||
table.setColumnUnderline (1);
|
table.setColumnUnderline (1);
|
||||||
|
|
||||||
table.setColumnJustification (1, Table::right);
|
table.setColumnJustification (1, Table::right);
|
||||||
|
table.setDateFormat (conf.get ("dateformat", "m/d/Y"));
|
||||||
|
|
||||||
foreach (i, unique)
|
foreach (i, unique)
|
||||||
{
|
{
|
||||||
@@ -407,6 +409,8 @@ void handleList (const TDB& tdb, T& task, Config& conf)
|
|||||||
|
|
||||||
initializeColorRules (conf);
|
initializeColorRules (conf);
|
||||||
|
|
||||||
|
bool showAge = conf.get ("showage", true);
|
||||||
|
|
||||||
// Create a table for output.
|
// Create a table for output.
|
||||||
Table table;
|
Table table;
|
||||||
table.setTableWidth (width);
|
table.setTableWidth (width);
|
||||||
@@ -415,7 +419,7 @@ void handleList (const TDB& tdb, T& task, Config& conf)
|
|||||||
table.addColumn ("Pri");
|
table.addColumn ("Pri");
|
||||||
table.addColumn ("Due");
|
table.addColumn ("Due");
|
||||||
table.addColumn ("Active");
|
table.addColumn ("Active");
|
||||||
table.addColumn ("Age");
|
if (showAge) table.addColumn ("Age");
|
||||||
table.addColumn ("Description");
|
table.addColumn ("Description");
|
||||||
|
|
||||||
table.setColumnUnderline (0);
|
table.setColumnUnderline (0);
|
||||||
@@ -424,27 +428,29 @@ void handleList (const TDB& tdb, T& task, Config& conf)
|
|||||||
table.setColumnUnderline (3);
|
table.setColumnUnderline (3);
|
||||||
table.setColumnUnderline (4);
|
table.setColumnUnderline (4);
|
||||||
table.setColumnUnderline (5);
|
table.setColumnUnderline (5);
|
||||||
table.setColumnUnderline (6);
|
if (showAge) table.setColumnUnderline (6);
|
||||||
|
|
||||||
table.setColumnWidth (0, Table::minimum);
|
table.setColumnWidth (0, Table::minimum);
|
||||||
table.setColumnWidth (1, Table::minimum);
|
table.setColumnWidth (1, Table::minimum);
|
||||||
table.setColumnWidth (2, Table::minimum);
|
table.setColumnWidth (2, Table::minimum);
|
||||||
table.setColumnWidth (3, Table::minimum);
|
table.setColumnWidth (3, Table::minimum);
|
||||||
table.setColumnWidth (4, Table::minimum);
|
table.setColumnWidth (4, Table::minimum);
|
||||||
table.setColumnWidth (5, Table::minimum);
|
if (showAge) table.setColumnWidth (5, Table::minimum);
|
||||||
table.setColumnWidth (6, Table::flexible);
|
table.setColumnWidth ((showAge ? 6 : 5), Table::flexible);
|
||||||
|
|
||||||
table.setColumnJustification (0, Table::right);
|
table.setColumnJustification (0, Table::right);
|
||||||
table.setColumnJustification (3, Table::right);
|
table.setColumnJustification (3, Table::right);
|
||||||
table.setColumnJustification (5, Table::right);
|
if (showAge) table.setColumnJustification (5, Table::right);
|
||||||
|
|
||||||
table.sortOn (3, Table::ascendingDate);
|
table.sortOn (3, Table::ascendingDate);
|
||||||
table.sortOn (2, Table::descendingPriority);
|
table.sortOn (2, Table::descendingPriority);
|
||||||
table.sortOn (1, Table::ascendingCharacter);
|
table.sortOn (1, Table::ascendingCharacter);
|
||||||
|
|
||||||
|
table.setDateFormat (conf.get ("dateformat", "m/d/Y"));
|
||||||
|
|
||||||
// Split any description specified into words.
|
// Split any description specified into words.
|
||||||
std::vector <std::string> descWords;
|
std::vector <std::string> descWords;
|
||||||
split (descWords, task.getDescription (), ' ');
|
split (descWords, lowerCase (task.getDescription ()), ' ');
|
||||||
|
|
||||||
// Get all the tags to match against.
|
// Get all the tags to match against.
|
||||||
std::vector <std::string> tagList;
|
std::vector <std::string> tagList;
|
||||||
@@ -460,9 +466,10 @@ void handleList (const TDB& tdb, T& task, Config& conf)
|
|||||||
T refTask (tasks[i]);
|
T refTask (tasks[i]);
|
||||||
|
|
||||||
// Apply description filter.
|
// Apply description filter.
|
||||||
|
std::string desc = lowerCase (refTask.getDescription ());
|
||||||
unsigned int matches = 0;
|
unsigned int matches = 0;
|
||||||
for (unsigned int w = 0; w < descWords.size (); ++w)
|
for (unsigned int w = 0; w < descWords.size (); ++w)
|
||||||
if (refTask.getDescription ().find (descWords[w]) != std::string::npos)
|
if (desc.find (descWords[w]) != std::string::npos)
|
||||||
++matches;
|
++matches;
|
||||||
|
|
||||||
if (matches == descWords.size ())
|
if (matches == descWords.size ())
|
||||||
@@ -470,8 +477,16 @@ void handleList (const TDB& tdb, T& task, Config& conf)
|
|||||||
// Apply attribute filter.
|
// Apply attribute filter.
|
||||||
matches = 0;
|
matches = 0;
|
||||||
foreach (a, attrList)
|
foreach (a, attrList)
|
||||||
if (a->second == refTask.getAttribute (a->first))
|
{
|
||||||
|
if (a->first == "project")
|
||||||
|
{
|
||||||
|
if (a->second.length () <= refTask.getAttribute (a->first).length ())
|
||||||
|
if (a->second == refTask.getAttribute (a->first).substr (0, a->second.length ()))
|
||||||
|
++matches;
|
||||||
|
}
|
||||||
|
else if (a->second == refTask.getAttribute (a->first))
|
||||||
++matches;
|
++matches;
|
||||||
|
}
|
||||||
|
|
||||||
if (matches == attrList.size ())
|
if (matches == attrList.size ())
|
||||||
{
|
{
|
||||||
@@ -488,7 +503,7 @@ void handleList (const TDB& tdb, T& task, Config& conf)
|
|||||||
bool overdue = false;
|
bool overdue = false;
|
||||||
Date now;
|
Date now;
|
||||||
std::string due = refTask.getAttribute ("due");
|
std::string due = refTask.getAttribute ("due");
|
||||||
if (due.length () && due.find ("/") == std::string::npos)
|
if (due.length ())
|
||||||
{
|
{
|
||||||
Date dt (::atoi (due.c_str ()));
|
Date dt (::atoi (due.c_str ()));
|
||||||
due = dt.toString (conf.get ("dateformat", "m/d/Y"));
|
due = dt.toString (conf.get ("dateformat", "m/d/Y"));
|
||||||
@@ -504,7 +519,7 @@ void handleList (const TDB& tdb, T& task, Config& conf)
|
|||||||
|
|
||||||
std::string age;
|
std::string age;
|
||||||
std::string created = refTask.getAttribute ("entry");
|
std::string created = refTask.getAttribute ("entry");
|
||||||
if (created.length () && created.find ("/") == std::string::npos)
|
if (created.length ())
|
||||||
{
|
{
|
||||||
Date dt (::atoi (created.c_str ()));
|
Date dt (::atoi (created.c_str ()));
|
||||||
formatTimeDeltaDays (age, (time_t) (now - dt));
|
formatTimeDeltaDays (age, (time_t) (now - dt));
|
||||||
@@ -517,8 +532,8 @@ void handleList (const TDB& tdb, T& task, Config& conf)
|
|||||||
table.addCell (row, 2, refTask.getAttribute ("priority"));
|
table.addCell (row, 2, refTask.getAttribute ("priority"));
|
||||||
table.addCell (row, 3, due);
|
table.addCell (row, 3, due);
|
||||||
table.addCell (row, 4, active);
|
table.addCell (row, 4, active);
|
||||||
table.addCell (row, 5, age);
|
if (showAge) table.addCell (row, 5, age);
|
||||||
table.addCell (row, 6, refTask.getDescription ());
|
table.addCell (row, (showAge ? 6 : 5), refTask.getDescription ());
|
||||||
|
|
||||||
if (conf.get ("color", true))
|
if (conf.get ("color", true))
|
||||||
{
|
{
|
||||||
@@ -581,6 +596,7 @@ void handleSmallList (const TDB& tdb, T& task, Config& conf)
|
|||||||
// Create a table for output.
|
// Create a table for output.
|
||||||
Table table;
|
Table table;
|
||||||
table.setTableWidth (width);
|
table.setTableWidth (width);
|
||||||
|
table.setDateFormat (conf.get ("dateformat", "m/d/Y"));
|
||||||
table.addColumn ("ID");
|
table.addColumn ("ID");
|
||||||
table.addColumn ("Project");
|
table.addColumn ("Project");
|
||||||
table.addColumn ("Pri");
|
table.addColumn ("Pri");
|
||||||
@@ -604,7 +620,7 @@ void handleSmallList (const TDB& tdb, T& task, Config& conf)
|
|||||||
|
|
||||||
// Split any description specified into words.
|
// Split any description specified into words.
|
||||||
std::vector <std::string> descWords;
|
std::vector <std::string> descWords;
|
||||||
split (descWords, task.getDescription (), ' ');
|
split (descWords, lowerCase (task.getDescription ()), ' ');
|
||||||
|
|
||||||
// Get all the tags to match against.
|
// Get all the tags to match against.
|
||||||
std::vector <std::string> tagList;
|
std::vector <std::string> tagList;
|
||||||
@@ -620,9 +636,10 @@ void handleSmallList (const TDB& tdb, T& task, Config& conf)
|
|||||||
T refTask (tasks[i]);
|
T refTask (tasks[i]);
|
||||||
|
|
||||||
// Apply description filter.
|
// Apply description filter.
|
||||||
|
std::string desc = lowerCase (refTask.getDescription ());
|
||||||
unsigned int matches = 0;
|
unsigned int matches = 0;
|
||||||
for (unsigned int w = 0; w < descWords.size (); ++w)
|
for (unsigned int w = 0; w < descWords.size (); ++w)
|
||||||
if (refTask.getDescription ().find (descWords[w]) != std::string::npos)
|
if (desc.find (descWords[w]) != std::string::npos)
|
||||||
++matches;
|
++matches;
|
||||||
|
|
||||||
if (matches == descWords.size ())
|
if (matches == descWords.size ())
|
||||||
@@ -630,8 +647,16 @@ void handleSmallList (const TDB& tdb, T& task, Config& conf)
|
|||||||
// Apply attribute filter.
|
// Apply attribute filter.
|
||||||
matches = 0;
|
matches = 0;
|
||||||
foreach (a, attrList)
|
foreach (a, attrList)
|
||||||
if (a->second == refTask.getAttribute (a->first))
|
{
|
||||||
|
if (a->first == "project")
|
||||||
|
{
|
||||||
|
if (a->second.length () <= refTask.getAttribute (a->first).length ())
|
||||||
|
if (a->second == refTask.getAttribute (a->first).substr (0, a->second.length ()))
|
||||||
|
++matches;
|
||||||
|
}
|
||||||
|
else if (a->second == refTask.getAttribute (a->first))
|
||||||
++matches;
|
++matches;
|
||||||
|
}
|
||||||
|
|
||||||
if (matches == attrList.size ())
|
if (matches == attrList.size ())
|
||||||
{
|
{
|
||||||
@@ -648,7 +673,7 @@ void handleSmallList (const TDB& tdb, T& task, Config& conf)
|
|||||||
bool overdue = false;
|
bool overdue = false;
|
||||||
Date now;
|
Date now;
|
||||||
std::string due = refTask.getAttribute ("due");
|
std::string due = refTask.getAttribute ("due");
|
||||||
if (due.length () && due.find ("/") == std::string::npos)
|
if (due.length ())
|
||||||
{
|
{
|
||||||
Date dt (::atoi (due.c_str ()));
|
Date dt (::atoi (due.c_str ()));
|
||||||
due = dt.toString (conf.get ("dateformat", "m/d/Y"));
|
due = dt.toString (conf.get ("dateformat", "m/d/Y"));
|
||||||
@@ -664,7 +689,7 @@ void handleSmallList (const TDB& tdb, T& task, Config& conf)
|
|||||||
|
|
||||||
std::string age;
|
std::string age;
|
||||||
std::string created = refTask.getAttribute ("entry");
|
std::string created = refTask.getAttribute ("entry");
|
||||||
if (created.length () && created.find ("/") == std::string::npos)
|
if (created.length ())
|
||||||
{
|
{
|
||||||
Date dt (::atoi (created.c_str ()));
|
Date dt (::atoi (created.c_str ()));
|
||||||
formatTimeDeltaDays (age, (time_t) (now - dt));
|
formatTimeDeltaDays (age, (time_t) (now - dt));
|
||||||
@@ -737,6 +762,7 @@ void handleCompleted (const TDB& tdb, T& task, Config& conf)
|
|||||||
// Create a table for output.
|
// Create a table for output.
|
||||||
Table table;
|
Table table;
|
||||||
table.setTableWidth (width);
|
table.setTableWidth (width);
|
||||||
|
table.setDateFormat (conf.get ("dateformat", "m/d/Y"));
|
||||||
table.addColumn ("Done");
|
table.addColumn ("Done");
|
||||||
table.addColumn ("Project");
|
table.addColumn ("Project");
|
||||||
table.addColumn ("Description");
|
table.addColumn ("Description");
|
||||||
@@ -757,7 +783,7 @@ void handleCompleted (const TDB& tdb, T& task, Config& conf)
|
|||||||
|
|
||||||
// Split any description specified into words.
|
// Split any description specified into words.
|
||||||
std::vector <std::string> descWords;
|
std::vector <std::string> descWords;
|
||||||
split (descWords, task.getDescription (), ' ');
|
split (descWords, lowerCase (task.getDescription ()), ' ');
|
||||||
|
|
||||||
// Get all the tags to match against.
|
// Get all the tags to match against.
|
||||||
std::vector <std::string> tagList;
|
std::vector <std::string> tagList;
|
||||||
@@ -773,9 +799,10 @@ void handleCompleted (const TDB& tdb, T& task, Config& conf)
|
|||||||
T refTask (tasks[i]);
|
T refTask (tasks[i]);
|
||||||
|
|
||||||
// Apply description filter.
|
// Apply description filter.
|
||||||
|
std::string desc = lowerCase (refTask.getDescription ());
|
||||||
unsigned int matches = 0;
|
unsigned int matches = 0;
|
||||||
for (unsigned int w = 0; w < descWords.size (); ++w)
|
for (unsigned int w = 0; w < descWords.size (); ++w)
|
||||||
if (refTask.getDescription ().find (descWords[w]) != std::string::npos)
|
if (desc.find (descWords[w]) != std::string::npos)
|
||||||
++matches;
|
++matches;
|
||||||
|
|
||||||
if (matches == descWords.size ())
|
if (matches == descWords.size ())
|
||||||
@@ -783,8 +810,16 @@ void handleCompleted (const TDB& tdb, T& task, Config& conf)
|
|||||||
// Apply attribute filter.
|
// Apply attribute filter.
|
||||||
matches = 0;
|
matches = 0;
|
||||||
foreach (a, attrList)
|
foreach (a, attrList)
|
||||||
if (a->second == refTask.getAttribute (a->first))
|
{
|
||||||
|
if (a->first == "project")
|
||||||
|
{
|
||||||
|
if (a->second.length () <= refTask.getAttribute (a->first).length ())
|
||||||
|
if (a->second == refTask.getAttribute (a->first).substr (0, a->second.length ()))
|
||||||
|
++matches;
|
||||||
|
}
|
||||||
|
else if (a->second == refTask.getAttribute (a->first))
|
||||||
++matches;
|
++matches;
|
||||||
|
}
|
||||||
|
|
||||||
if (matches == attrList.size ())
|
if (matches == attrList.size ())
|
||||||
{
|
{
|
||||||
@@ -852,6 +887,7 @@ void handleInfo (const TDB& tdb, T& task, Config& conf)
|
|||||||
|
|
||||||
Table table;
|
Table table;
|
||||||
table.setTableWidth (width);
|
table.setTableWidth (width);
|
||||||
|
table.setDateFormat (conf.get ("dateformat", "m/d/Y"));
|
||||||
|
|
||||||
table.addColumn ("Name");
|
table.addColumn ("Name");
|
||||||
table.addColumn ("Value");
|
table.addColumn ("Value");
|
||||||
@@ -916,10 +952,8 @@ void handleInfo (const TDB& tdb, T& task, Config& conf)
|
|||||||
due = dt.toString (conf.get ("dateformat", "m/d/Y"));
|
due = dt.toString (conf.get ("dateformat", "m/d/Y"));
|
||||||
table.addCell (row, 1, due);
|
table.addCell (row, 1, due);
|
||||||
|
|
||||||
if (due.length () && due.find ("/") == std::string::npos)
|
if (due.length ())
|
||||||
{
|
{
|
||||||
Date dt (::atoi (due.c_str ()));
|
|
||||||
|
|
||||||
overdue = (dt < now) ? true : false;
|
overdue = (dt < now) ? true : false;
|
||||||
now += 7 * 86400;
|
now += 7 * 86400;
|
||||||
imminent = dt < now ? true : false;
|
imminent = dt < now ? true : false;
|
||||||
@@ -976,7 +1010,7 @@ void handleInfo (const TDB& tdb, T& task, Config& conf)
|
|||||||
|
|
||||||
std::string age;
|
std::string age;
|
||||||
std::string created = refTask.getAttribute ("entry");
|
std::string created = refTask.getAttribute ("entry");
|
||||||
if (created.length () && created.find ("/") == std::string::npos)
|
if (created.length ())
|
||||||
{
|
{
|
||||||
Date dt (::atoi (created.c_str ()));
|
Date dt (::atoi (created.c_str ()));
|
||||||
formatTimeDeltaDays (age, (time_t) (now - dt));
|
formatTimeDeltaDays (age, (time_t) (now - dt));
|
||||||
@@ -1024,6 +1058,7 @@ void handleLongList (const TDB& tdb, T& task, Config& conf)
|
|||||||
// Create a table for output.
|
// Create a table for output.
|
||||||
Table table;
|
Table table;
|
||||||
table.setTableWidth (width);
|
table.setTableWidth (width);
|
||||||
|
table.setDateFormat (conf.get ("dateformat", "m/d/Y"));
|
||||||
table.addColumn ("ID");
|
table.addColumn ("ID");
|
||||||
table.addColumn ("Project");
|
table.addColumn ("Project");
|
||||||
table.addColumn ("Pri");
|
table.addColumn ("Pri");
|
||||||
@@ -1066,7 +1101,7 @@ void handleLongList (const TDB& tdb, T& task, Config& conf)
|
|||||||
|
|
||||||
// Split any description specified into words.
|
// Split any description specified into words.
|
||||||
std::vector <std::string> descWords;
|
std::vector <std::string> descWords;
|
||||||
split (descWords, task.getDescription (), ' ');
|
split (descWords, lowerCase (task.getDescription ()), ' ');
|
||||||
|
|
||||||
// Get all the tags to match against.
|
// Get all the tags to match against.
|
||||||
std::vector <std::string> tagList;
|
std::vector <std::string> tagList;
|
||||||
@@ -1082,9 +1117,10 @@ void handleLongList (const TDB& tdb, T& task, Config& conf)
|
|||||||
T refTask (tasks[i]);
|
T refTask (tasks[i]);
|
||||||
|
|
||||||
// Apply description filter.
|
// Apply description filter.
|
||||||
|
std::string desc = lowerCase (refTask.getDescription ());
|
||||||
unsigned int matches = 0;
|
unsigned int matches = 0;
|
||||||
for (unsigned int w = 0; w < descWords.size (); ++w)
|
for (unsigned int w = 0; w < descWords.size (); ++w)
|
||||||
if (refTask.getDescription ().find (descWords[w]) != std::string::npos)
|
if (desc.find (descWords[w]) != std::string::npos)
|
||||||
++matches;
|
++matches;
|
||||||
|
|
||||||
if (matches == descWords.size ())
|
if (matches == descWords.size ())
|
||||||
@@ -1092,8 +1128,16 @@ void handleLongList (const TDB& tdb, T& task, Config& conf)
|
|||||||
// Apply attribute filter.
|
// Apply attribute filter.
|
||||||
matches = 0;
|
matches = 0;
|
||||||
foreach (a, attrList)
|
foreach (a, attrList)
|
||||||
if (a->second == refTask.getAttribute (a->first))
|
{
|
||||||
|
if (a->first == "project")
|
||||||
|
{
|
||||||
|
if (a->second.length () <= refTask.getAttribute (a->first).length ())
|
||||||
|
if (a->second == refTask.getAttribute (a->first).substr (0, a->second.length ()))
|
||||||
|
++matches;
|
||||||
|
}
|
||||||
|
else if (a->second == refTask.getAttribute (a->first))
|
||||||
++matches;
|
++matches;
|
||||||
|
}
|
||||||
|
|
||||||
if (matches == attrList.size ())
|
if (matches == attrList.size ())
|
||||||
{
|
{
|
||||||
@@ -1108,14 +1152,14 @@ void handleLongList (const TDB& tdb, T& task, Config& conf)
|
|||||||
Date now;
|
Date now;
|
||||||
|
|
||||||
std::string started = refTask.getAttribute ("start");
|
std::string started = refTask.getAttribute ("start");
|
||||||
if (started.length () && started.find ("/") == std::string::npos)
|
if (started.length ())
|
||||||
{
|
{
|
||||||
Date dt (::atoi (started.c_str ()));
|
Date dt (::atoi (started.c_str ()));
|
||||||
started = dt.toString (conf.get ("dateformat", "m/d/Y"));
|
started = dt.toString (conf.get ("dateformat", "m/d/Y"));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string entered = refTask.getAttribute ("entry");
|
std::string entered = refTask.getAttribute ("entry");
|
||||||
if (entered.length () && entered.find ("/") == std::string::npos)
|
if (entered.length ())
|
||||||
{
|
{
|
||||||
Date dt (::atoi (entered.c_str ()));
|
Date dt (::atoi (entered.c_str ()));
|
||||||
entered = dt.toString (conf.get ("dateformat", "m/d/Y"));
|
entered = dt.toString (conf.get ("dateformat", "m/d/Y"));
|
||||||
@@ -1125,7 +1169,7 @@ void handleLongList (const TDB& tdb, T& task, Config& conf)
|
|||||||
bool imminent = false;
|
bool imminent = false;
|
||||||
bool overdue = false;
|
bool overdue = false;
|
||||||
std::string due = refTask.getAttribute ("due");
|
std::string due = refTask.getAttribute ("due");
|
||||||
if (due.length () && due.find ("/") == std::string::npos)
|
if (due.length ())
|
||||||
{
|
{
|
||||||
Date dt (::atoi (due.c_str ()));
|
Date dt (::atoi (due.c_str ()));
|
||||||
due = dt.toString (conf.get ("dateformat", "m/d/Y"));
|
due = dt.toString (conf.get ("dateformat", "m/d/Y"));
|
||||||
@@ -1137,7 +1181,7 @@ void handleLongList (const TDB& tdb, T& task, Config& conf)
|
|||||||
|
|
||||||
std::string age;
|
std::string age;
|
||||||
std::string created = refTask.getAttribute ("entry");
|
std::string created = refTask.getAttribute ("entry");
|
||||||
if (created.length () && created.find ("/") == std::string::npos)
|
if (created.length ())
|
||||||
{
|
{
|
||||||
Date dt (::atoi (created.c_str ()));
|
Date dt (::atoi (created.c_str ()));
|
||||||
formatTimeDeltaDays (age, (time_t) (now - dt));
|
formatTimeDeltaDays (age, (time_t) (now - dt));
|
||||||
@@ -1279,6 +1323,7 @@ void handleReportSummary (const TDB& tdb, T& task, Config& conf)
|
|||||||
table.setColumnJustification (3, Table::right);
|
table.setColumnJustification (3, Table::right);
|
||||||
|
|
||||||
table.sortOn (0, Table::ascendingCharacter);
|
table.sortOn (0, Table::ascendingCharacter);
|
||||||
|
table.setDateFormat (conf.get ("dateformat", "m/d/Y"));
|
||||||
|
|
||||||
int barWidth = 30;
|
int barWidth = 30;
|
||||||
foreach (i, allProjects)
|
foreach (i, allProjects)
|
||||||
@@ -1387,15 +1432,18 @@ void handleReportNext (const TDB& tdb, T& task, Config& conf)
|
|||||||
|
|
||||||
initializeColorRules (conf);
|
initializeColorRules (conf);
|
||||||
|
|
||||||
|
bool showAge = conf.get ("showage", true);
|
||||||
|
|
||||||
// Create a table for output.
|
// Create a table for output.
|
||||||
Table table;
|
Table table;
|
||||||
table.setTableWidth (width);
|
table.setTableWidth (width);
|
||||||
|
table.setDateFormat (conf.get ("dateformat", "m/d/Y"));
|
||||||
table.addColumn ("ID");
|
table.addColumn ("ID");
|
||||||
table.addColumn ("Project");
|
table.addColumn ("Project");
|
||||||
table.addColumn ("Pri");
|
table.addColumn ("Pri");
|
||||||
table.addColumn ("Due");
|
table.addColumn ("Due");
|
||||||
table.addColumn ("Active");
|
table.addColumn ("Active");
|
||||||
table.addColumn ("Age");
|
if (showAge) table.addColumn ("Age");
|
||||||
table.addColumn ("Description");
|
table.addColumn ("Description");
|
||||||
|
|
||||||
table.setColumnUnderline (0);
|
table.setColumnUnderline (0);
|
||||||
@@ -1404,19 +1452,19 @@ void handleReportNext (const TDB& tdb, T& task, Config& conf)
|
|||||||
table.setColumnUnderline (3);
|
table.setColumnUnderline (3);
|
||||||
table.setColumnUnderline (4);
|
table.setColumnUnderline (4);
|
||||||
table.setColumnUnderline (5);
|
table.setColumnUnderline (5);
|
||||||
table.setColumnUnderline (6);
|
if (showAge) table.setColumnUnderline (6);
|
||||||
|
|
||||||
table.setColumnWidth (0, Table::minimum);
|
table.setColumnWidth (0, Table::minimum);
|
||||||
table.setColumnWidth (1, Table::minimum);
|
table.setColumnWidth (1, Table::minimum);
|
||||||
table.setColumnWidth (2, Table::minimum);
|
table.setColumnWidth (2, Table::minimum);
|
||||||
table.setColumnWidth (3, Table::minimum);
|
table.setColumnWidth (3, Table::minimum);
|
||||||
table.setColumnWidth (4, Table::minimum);
|
table.setColumnWidth (4, Table::minimum);
|
||||||
table.setColumnWidth (5, Table::minimum);
|
if (showAge) table.setColumnWidth (5, Table::minimum);
|
||||||
table.setColumnWidth (6, Table::flexible);
|
table.setColumnWidth ((showAge ? 6 : 5), Table::flexible);
|
||||||
|
|
||||||
table.setColumnJustification (0, Table::right);
|
table.setColumnJustification (0, Table::right);
|
||||||
table.setColumnJustification (3, Table::right);
|
table.setColumnJustification (3, Table::right);
|
||||||
table.setColumnJustification (5, Table::right);
|
if (showAge) table.setColumnJustification (5, Table::right);
|
||||||
|
|
||||||
table.sortOn (3, Table::ascendingDate);
|
table.sortOn (3, Table::ascendingDate);
|
||||||
table.sortOn (2, Table::descendingPriority);
|
table.sortOn (2, Table::descendingPriority);
|
||||||
@@ -1424,7 +1472,7 @@ void handleReportNext (const TDB& tdb, T& task, Config& conf)
|
|||||||
|
|
||||||
// Split any description specified into words.
|
// Split any description specified into words.
|
||||||
std::vector <std::string> descWords;
|
std::vector <std::string> descWords;
|
||||||
split (descWords, task.getDescription (), ' ');
|
split (descWords, lowerCase (task.getDescription ()), ' ');
|
||||||
|
|
||||||
// Get all the tags to match against.
|
// Get all the tags to match against.
|
||||||
std::vector <std::string> tagList;
|
std::vector <std::string> tagList;
|
||||||
@@ -1440,9 +1488,10 @@ void handleReportNext (const TDB& tdb, T& task, Config& conf)
|
|||||||
T refTask (pending[*i]);
|
T refTask (pending[*i]);
|
||||||
|
|
||||||
// Apply description filter.
|
// Apply description filter.
|
||||||
|
std::string desc = lowerCase (refTask.getDescription ());
|
||||||
unsigned int matches = 0;
|
unsigned int matches = 0;
|
||||||
for (unsigned int w = 0; w < descWords.size (); ++w)
|
for (unsigned int w = 0; w < descWords.size (); ++w)
|
||||||
if (refTask.getDescription ().find (descWords[w]) != std::string::npos)
|
if (desc.find (descWords[w]) != std::string::npos)
|
||||||
++matches;
|
++matches;
|
||||||
|
|
||||||
if (matches == descWords.size ())
|
if (matches == descWords.size ())
|
||||||
@@ -1450,8 +1499,16 @@ void handleReportNext (const TDB& tdb, T& task, Config& conf)
|
|||||||
// Apply attribute filter.
|
// Apply attribute filter.
|
||||||
matches = 0;
|
matches = 0;
|
||||||
foreach (a, attrList)
|
foreach (a, attrList)
|
||||||
if (a->second == refTask.getAttribute (a->first))
|
{
|
||||||
|
if (a->first == "project")
|
||||||
|
{
|
||||||
|
if (a->second.length () <= refTask.getAttribute (a->first).length ())
|
||||||
|
if (a->second == refTask.getAttribute (a->first).substr (0, a->second.length ()))
|
||||||
|
++matches;
|
||||||
|
}
|
||||||
|
else if (a->second == refTask.getAttribute (a->first))
|
||||||
++matches;
|
++matches;
|
||||||
|
}
|
||||||
|
|
||||||
if (matches == attrList.size ())
|
if (matches == attrList.size ())
|
||||||
{
|
{
|
||||||
@@ -1468,7 +1525,7 @@ void handleReportNext (const TDB& tdb, T& task, Config& conf)
|
|||||||
bool overdue = false;
|
bool overdue = false;
|
||||||
Date now;
|
Date now;
|
||||||
std::string due = refTask.getAttribute ("due");
|
std::string due = refTask.getAttribute ("due");
|
||||||
if (due.length () && due.find ("/") == std::string::npos)
|
if (due.length ())
|
||||||
{
|
{
|
||||||
Date dt (::atoi (due.c_str ()));
|
Date dt (::atoi (due.c_str ()));
|
||||||
due = dt.toString (conf.get ("dateformat", "m/d/Y"));
|
due = dt.toString (conf.get ("dateformat", "m/d/Y"));
|
||||||
@@ -1484,7 +1541,7 @@ void handleReportNext (const TDB& tdb, T& task, Config& conf)
|
|||||||
|
|
||||||
std::string age;
|
std::string age;
|
||||||
std::string created = refTask.getAttribute ("entry");
|
std::string created = refTask.getAttribute ("entry");
|
||||||
if (created.length () && created.find ("/") == std::string::npos)
|
if (created.length ())
|
||||||
{
|
{
|
||||||
Date dt (::atoi (created.c_str ()));
|
Date dt (::atoi (created.c_str ()));
|
||||||
formatTimeDeltaDays (age, (time_t) (now - dt));
|
formatTimeDeltaDays (age, (time_t) (now - dt));
|
||||||
@@ -1497,8 +1554,8 @@ void handleReportNext (const TDB& tdb, T& task, Config& conf)
|
|||||||
table.addCell (row, 2, refTask.getAttribute ("priority"));
|
table.addCell (row, 2, refTask.getAttribute ("priority"));
|
||||||
table.addCell (row, 3, due);
|
table.addCell (row, 3, due);
|
||||||
table.addCell (row, 4, active);
|
table.addCell (row, 4, active);
|
||||||
table.addCell (row, 5, age);
|
if (showAge) table.addCell (row, 5, age);
|
||||||
table.addCell (row, 6, refTask.getDescription ());
|
table.addCell (row, (showAge ? 6 : 5), refTask.getDescription ());
|
||||||
|
|
||||||
if (conf.get ("color", true))
|
if (conf.get ("color", true))
|
||||||
{
|
{
|
||||||
@@ -1638,6 +1695,7 @@ void handleReportHistory (const TDB& tdb, T& task, Config& conf)
|
|||||||
|
|
||||||
// Now build the table.
|
// Now build the table.
|
||||||
Table table;
|
Table table;
|
||||||
|
table.setDateFormat (conf.get ("dateformat", "m/d/Y"));
|
||||||
table.addColumn ("Year");
|
table.addColumn ("Year");
|
||||||
table.addColumn ("Month");
|
table.addColumn ("Month");
|
||||||
table.addColumn ("Added");
|
table.addColumn ("Added");
|
||||||
@@ -1740,7 +1798,7 @@ void handleReportUsage (const TDB& tdb, T& task, Config& conf)
|
|||||||
{
|
{
|
||||||
T task;
|
T task;
|
||||||
std::string commandName;
|
std::string commandName;
|
||||||
parse (args, commandName, task);
|
parse (args, commandName, task, conf);
|
||||||
|
|
||||||
usage[commandName]++;
|
usage[commandName]++;
|
||||||
}
|
}
|
||||||
@@ -1759,6 +1817,7 @@ void handleReportUsage (const TDB& tdb, T& task, Config& conf)
|
|||||||
table.setColumnUnderline (1);
|
table.setColumnUnderline (1);
|
||||||
table.setColumnJustification (1, Table::right);
|
table.setColumnJustification (1, Table::right);
|
||||||
table.sortOn (1, Table::descendingNumeric);
|
table.sortOn (1, Table::descendingNumeric);
|
||||||
|
table.setDateFormat (conf.get ("dateformat", "m/d/Y"));
|
||||||
|
|
||||||
foreach (i, usage)
|
foreach (i, usage)
|
||||||
{
|
{
|
||||||
@@ -1788,6 +1847,7 @@ std::string renderMonth (
|
|||||||
Config& conf)
|
Config& conf)
|
||||||
{
|
{
|
||||||
Table table;
|
Table table;
|
||||||
|
table.setDateFormat (conf.get ("dateformat", "m/d/Y"));
|
||||||
table.addColumn (" ");
|
table.addColumn (" ");
|
||||||
table.addColumn ("Su");
|
table.addColumn ("Su");
|
||||||
table.addColumn ("Mo");
|
table.addColumn ("Mo");
|
||||||
@@ -1934,6 +1994,7 @@ void handleReportActive (const TDB& tdb, T& task, Config& conf)
|
|||||||
// Create a table for output.
|
// Create a table for output.
|
||||||
Table table;
|
Table table;
|
||||||
table.setTableWidth (width);
|
table.setTableWidth (width);
|
||||||
|
table.setDateFormat (conf.get ("dateformat", "m/d/Y"));
|
||||||
table.addColumn ("ID");
|
table.addColumn ("ID");
|
||||||
table.addColumn ("Project");
|
table.addColumn ("Project");
|
||||||
table.addColumn ("Pri");
|
table.addColumn ("Pri");
|
||||||
@@ -1959,10 +2020,6 @@ void handleReportActive (const TDB& tdb, T& task, Config& conf)
|
|||||||
table.sortOn (2, Table::descendingPriority);
|
table.sortOn (2, Table::descendingPriority);
|
||||||
table.sortOn (1, Table::ascendingCharacter);
|
table.sortOn (1, Table::ascendingCharacter);
|
||||||
|
|
||||||
// Split any description specified into words.
|
|
||||||
std::vector <std::string> descWords;
|
|
||||||
split (descWords, task.getDescription (), ' ');
|
|
||||||
|
|
||||||
// Get all the tags to match against.
|
// Get all the tags to match against.
|
||||||
std::vector <std::string> tagList;
|
std::vector <std::string> tagList;
|
||||||
task.getTags (tagList);
|
task.getTags (tagList);
|
||||||
@@ -1980,7 +2037,7 @@ void handleReportActive (const TDB& tdb, T& task, Config& conf)
|
|||||||
bool imminent = false;
|
bool imminent = false;
|
||||||
bool overdue = false;
|
bool overdue = false;
|
||||||
std::string due = refTask.getAttribute ("due");
|
std::string due = refTask.getAttribute ("due");
|
||||||
if (due.length () && due.find ("/") == std::string::npos)
|
if (due.length ())
|
||||||
{
|
{
|
||||||
Date dt (::atoi (due.c_str ()));
|
Date dt (::atoi (due.c_str ()));
|
||||||
due = dt.toString (conf.get ("dateformat", "m/d/Y"));
|
due = dt.toString (conf.get ("dateformat", "m/d/Y"));
|
||||||
@@ -2052,6 +2109,7 @@ void handleReportOverdue (const TDB& tdb, T& task, Config& conf)
|
|||||||
// Create a table for output.
|
// Create a table for output.
|
||||||
Table table;
|
Table table;
|
||||||
table.setTableWidth (width);
|
table.setTableWidth (width);
|
||||||
|
table.setDateFormat (conf.get ("dateformat", "m/d/Y"));
|
||||||
table.addColumn ("ID");
|
table.addColumn ("ID");
|
||||||
table.addColumn ("Project");
|
table.addColumn ("Project");
|
||||||
table.addColumn ("Pri");
|
table.addColumn ("Pri");
|
||||||
@@ -2077,10 +2135,6 @@ void handleReportOverdue (const TDB& tdb, T& task, Config& conf)
|
|||||||
table.sortOn (2, Table::descendingPriority);
|
table.sortOn (2, Table::descendingPriority);
|
||||||
table.sortOn (1, Table::ascendingCharacter);
|
table.sortOn (1, Table::ascendingCharacter);
|
||||||
|
|
||||||
// Split any description specified into words.
|
|
||||||
std::vector <std::string> descWords;
|
|
||||||
split (descWords, task.getDescription (), ' ');
|
|
||||||
|
|
||||||
// Get all the tags to match against.
|
// Get all the tags to match against.
|
||||||
std::vector <std::string> tagList;
|
std::vector <std::string> tagList;
|
||||||
task.getTags (tagList);
|
task.getTags (tagList);
|
||||||
@@ -2098,7 +2152,7 @@ void handleReportOverdue (const TDB& tdb, T& task, Config& conf)
|
|||||||
std::string due;
|
std::string due;
|
||||||
if ((due = refTask.getAttribute ("due")) != "")
|
if ((due = refTask.getAttribute ("due")) != "")
|
||||||
{
|
{
|
||||||
if (due.length () && due.find ("/") == std::string::npos)
|
if (due.length ())
|
||||||
{
|
{
|
||||||
Date dt (::atoi (due.c_str ()));
|
Date dt (::atoi (due.c_str ()));
|
||||||
due = dt.toString (conf.get ("dateformat", "m/d/Y"));
|
due = dt.toString (conf.get ("dateformat", "m/d/Y"));
|
||||||
@@ -2241,6 +2295,7 @@ void handleVersion (Config& conf)
|
|||||||
// Create a table for output.
|
// Create a table for output.
|
||||||
Table table;
|
Table table;
|
||||||
table.setTableWidth (width);
|
table.setTableWidth (width);
|
||||||
|
table.setDateFormat (conf.get ("dateformat", "m/d/Y"));
|
||||||
table.addColumn ("Config variable");
|
table.addColumn ("Config variable");
|
||||||
table.addColumn ("Value");
|
table.addColumn ("Value");
|
||||||
table.setColumnUnderline (0);
|
table.setColumnUnderline (0);
|
||||||
@@ -2264,7 +2319,7 @@ void handleVersion (Config& conf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Copyright (C) 2006 - 2008 P. Beckingham."
|
std::cout << "Copyright (C) 2006 - 2008, P. Beckingham."
|
||||||
<< std::endl
|
<< std::endl
|
||||||
<< PACKAGE
|
<< PACKAGE
|
||||||
<< " "
|
<< " "
|
||||||
|
|||||||
@@ -49,8 +49,8 @@ for (typeof (c) *foreach_p = & (c); \
|
|||||||
++i)
|
++i)
|
||||||
|
|
||||||
// parse.cpp
|
// parse.cpp
|
||||||
void parse (std::vector <std::string>&, std::string&, T&);
|
void parse (std::vector <std::string>&, std::string&, T&, Config&);
|
||||||
bool validDate (std::string&);
|
bool validDate (std::string&, Config&);
|
||||||
|
|
||||||
// task.cpp
|
// task.cpp
|
||||||
void handleAdd (const TDB&, T&, Config&);
|
void handleAdd (const TDB&, T&, Config&);
|
||||||
|
|||||||
1
src/tests/.gitignore
vendored
1
src/tests/.gitignore
vendored
@@ -1,5 +1,6 @@
|
|||||||
t.t
|
t.t
|
||||||
tdb.t
|
tdb.t
|
||||||
|
date.t
|
||||||
pending.data
|
pending.data
|
||||||
completed.data
|
completed.data
|
||||||
|
|
||||||
|
|||||||
28
src/tests/Makefile
Normal file
28
src/tests/Makefile
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
PROJECT = t.t tdb.t date.t
|
||||||
|
CFLAGS = -I. -I.. -Wall -pedantic -ggdb3 -fno-rtti
|
||||||
|
LFLAGS = -L/usr/local/lib
|
||||||
|
OBJECTS = ../TDB.o ../T.o ../parse.o ../text.o ../Date.o ../util.o ../Config.o
|
||||||
|
|
||||||
|
all: $(PROJECT)
|
||||||
|
|
||||||
|
install: $(PROJECT)
|
||||||
|
@echo unimplemented
|
||||||
|
|
||||||
|
test: $(PROJECT)
|
||||||
|
@echo unimplemented
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-rm *.o $(PROJECT)
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
g++ -c $(CFLAGS) $<
|
||||||
|
|
||||||
|
t.t: t.t.o $(OBJECTS) test.o
|
||||||
|
g++ t.t.o $(OBJECTS) test.o $(LFLAGS) -o t.t
|
||||||
|
|
||||||
|
tdb.t: tdb.t.o $(OBJECTS) test.o
|
||||||
|
g++ tdb.t.o $(OBJECTS) test.o $(LFLAGS) -o tdb.t
|
||||||
|
|
||||||
|
date.t: date.t.o $(OBJECTS) test.o
|
||||||
|
g++ date.t.o $(OBJECTS) test.o $(LFLAGS) -o date.t
|
||||||
|
|
||||||
@@ -9,78 +9,104 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
int main (int argc, char** argv)
|
int main (int argc, char** argv)
|
||||||
{
|
{
|
||||||
UnitTest t (46);
|
plan (63);
|
||||||
|
|
||||||
Date now;
|
Date now;
|
||||||
Date yesterday;
|
Date yesterday;
|
||||||
yesterday -= 1;
|
yesterday -= 1;
|
||||||
|
|
||||||
t.ok (yesterday <= now, "yesterday <= now");
|
ok (yesterday <= now, "yesterday <= now");
|
||||||
t.ok (yesterday < now, "yesterday < now");
|
ok (yesterday < now, "yesterday < now");
|
||||||
t.notok (yesterday == now, "!(yesterday == now)");
|
notok (yesterday == now, "!(yesterday == now)");
|
||||||
t.ok (yesterday != now, "yesterday != now");
|
ok (yesterday != now, "yesterday != now");
|
||||||
t.ok (now >= yesterday, "now >= yesterday");
|
ok (now >= yesterday, "now >= yesterday");
|
||||||
t.ok (now > yesterday, "now > yesterday");
|
ok (now > yesterday, "now > yesterday");
|
||||||
|
|
||||||
t.ok (Date::valid (2, 29, 2008), "valid: 2/29/2008");
|
ok (Date::valid (2, 29, 2008), "valid: 2/29/2008");
|
||||||
t.notok (Date::valid (2, 29, 2007), "invalid: 2/29/2007");
|
notok (Date::valid (2, 29, 2007), "invalid: 2/29/2007");
|
||||||
|
|
||||||
t.ok (Date::leapYear (2008), "2008 is a leap year");
|
ok (Date::leapYear (2008), "2008 is a leap year");
|
||||||
t.notok (Date::leapYear (2007), "2007 is not a leap year");
|
notok (Date::leapYear (2007), "2007 is not a leap year");
|
||||||
|
ok (Date::leapYear (2000), "2000 is a leap year");
|
||||||
|
ok (Date::leapYear (1900), "1900 is a leap year");
|
||||||
|
|
||||||
t.is (Date::daysInMonth (2, 2008), 29, "29 days in February 2008");
|
is (Date::daysInMonth (2, 2008), 29, "29 days in February 2008");
|
||||||
t.is (Date::daysInMonth (2, 2007), 28, "28 days in February 2007");
|
is (Date::daysInMonth (2, 2007), 28, "28 days in February 2007");
|
||||||
|
|
||||||
t.is (Date::monthName (1), "January", "1 = January");
|
is (Date::monthName (1), "January", "1 = January");
|
||||||
t.is (Date::monthName (2), "February", "2 = February");
|
is (Date::monthName (2), "February", "2 = February");
|
||||||
t.is (Date::monthName (3), "March", "3 = March");
|
is (Date::monthName (3), "March", "3 = March");
|
||||||
t.is (Date::monthName (4), "April", "4 = April");
|
is (Date::monthName (4), "April", "4 = April");
|
||||||
t.is (Date::monthName (5), "May", "5 = May");
|
is (Date::monthName (5), "May", "5 = May");
|
||||||
t.is (Date::monthName (6), "June", "6 = June");
|
is (Date::monthName (6), "June", "6 = June");
|
||||||
t.is (Date::monthName (7), "July", "7 = July");
|
is (Date::monthName (7), "July", "7 = July");
|
||||||
t.is (Date::monthName (8), "August", "8 = August");
|
is (Date::monthName (8), "August", "8 = August");
|
||||||
t.is (Date::monthName (9), "September", "9 = September");
|
is (Date::monthName (9), "September", "9 = September");
|
||||||
t.is (Date::monthName (10), "October", "10 = October");
|
is (Date::monthName (10), "October", "10 = October");
|
||||||
t.is (Date::monthName (11), "November", "11 = November");
|
is (Date::monthName (11), "November", "11 = November");
|
||||||
t.is (Date::monthName (12), "December", "12 = December");
|
is (Date::monthName (12), "December", "12 = December");
|
||||||
|
|
||||||
t.is (Date::dayName (0), "Sunday", "0 == Sunday");
|
is (Date::dayName (0), "Sunday", "0 == Sunday");
|
||||||
t.is (Date::dayName (1), "Monday", "1 == Monday");
|
is (Date::dayName (1), "Monday", "1 == Monday");
|
||||||
t.is (Date::dayName (2), "Tuesday", "2 == Tuesday");
|
is (Date::dayName (2), "Tuesday", "2 == Tuesday");
|
||||||
t.is (Date::dayName (3), "Wednesday", "3 == Wednesday");
|
is (Date::dayName (3), "Wednesday", "3 == Wednesday");
|
||||||
t.is (Date::dayName (4), "Thursday", "4 == Thursday");
|
is (Date::dayName (4), "Thursday", "4 == Thursday");
|
||||||
t.is (Date::dayName (5), "Friday", "5 == Friday");
|
is (Date::dayName (5), "Friday", "5 == Friday");
|
||||||
t.is (Date::dayName (6), "Saturday", "6 == Saturday");
|
is (Date::dayName (6), "Saturday", "6 == Saturday");
|
||||||
|
|
||||||
Date happyNewYear (1, 1, 2008);
|
Date happyNewYear (1, 1, 2008);
|
||||||
t.is (happyNewYear.dayOfWeek (), 2, "1/1/2008 == Tuesday");
|
is (happyNewYear.dayOfWeek (), 2, "1/1/2008 == Tuesday");
|
||||||
t.is (happyNewYear.month (), 1, "1/1/2008 == January");
|
is (happyNewYear.month (), 1, "1/1/2008 == January");
|
||||||
t.is (happyNewYear.day (), 1, "1/1/2008 == 1");
|
is (happyNewYear.day (), 1, "1/1/2008 == 1");
|
||||||
t.is (happyNewYear.year (), 2008, "1/1/2008 == 2008");
|
is (happyNewYear.year (), 2008, "1/1/2008 == 2008");
|
||||||
|
|
||||||
t.is (now - yesterday, 1, "today - yesterday == 1");
|
is (now - yesterday, 1, "today - yesterday == 1");
|
||||||
|
|
||||||
t.is (happyNewYear.toString (), "1/1/2008", "toString 1/1/2008");
|
is (happyNewYear.toString (), "1/1/2008", "toString 1/1/2008");
|
||||||
|
|
||||||
int m, d, y;
|
int m, d, y;
|
||||||
happyNewYear.toMDY (m, d, y);
|
happyNewYear.toMDY (m, d, y);
|
||||||
t.is (m, 1, "1/1/2008 == January");
|
is (m, 1, "1/1/2008 == January");
|
||||||
t.is (d, 1, "1/1/2008 == 1");
|
is (d, 1, "1/1/2008 == 1");
|
||||||
t.is (y, 2008, "1/1/2008 == 2008");
|
is (y, 2008, "1/1/2008 == 2008");
|
||||||
|
|
||||||
Date epoch (9, 8, 2001);
|
Date epoch (9, 8, 2001);
|
||||||
t.ok ((int)epoch.toEpoch () < 1000000000, "9/8/2001 < 1,000,000,000");
|
ok ((int)epoch.toEpoch () < 1000000000, "9/8/2001 < 1,000,000,000");
|
||||||
epoch += 86400;
|
epoch += 86400;
|
||||||
t.ok ((int)epoch.toEpoch () > 1000000000, "9/9/2001 > 1,000,000,000");
|
ok ((int)epoch.toEpoch () > 1000000000, "9/9/2001 > 1,000,000,000");
|
||||||
|
|
||||||
Date fromEpoch (epoch.toEpoch ());
|
Date fromEpoch (epoch.toEpoch ());
|
||||||
t.is (fromEpoch.toString (), epoch.toString (), "ctor (time_t)");
|
is (fromEpoch.toString (), epoch.toString (), "ctor (time_t)");
|
||||||
|
|
||||||
Date fromString ("1/1/2008");
|
Date fromString1 ("1/1/2008");
|
||||||
t.is (fromString.month (), 1, "ctor (std::string) -> m");
|
is (fromString1.month (), 1, "ctor (std::string) -> m");
|
||||||
t.is (fromString.day (), 1, "ctor (std::string) -> d");
|
is (fromString1.day (), 1, "ctor (std::string) -> d");
|
||||||
t.is (fromString.year (), 2008, "ctor (std::string) -> y");
|
is (fromString1.year (), 2008, "ctor (std::string) -> y");
|
||||||
|
|
||||||
|
Date fromString2 ("1/1/2008", "m/d/Y");
|
||||||
|
is (fromString2.month (), 1, "ctor (std::string) -> m");
|
||||||
|
is (fromString2.day (), 1, "ctor (std::string) -> d");
|
||||||
|
is (fromString2.year (), 2008, "ctor (std::string) -> y");
|
||||||
|
|
||||||
|
Date fromString3 ("20080101", "YMD");
|
||||||
|
is (fromString3.month (), 1, "ctor (std::string) -> m");
|
||||||
|
is (fromString3.day (), 1, "ctor (std::string) -> d");
|
||||||
|
is (fromString3.year (), 2008, "ctor (std::string) -> y");
|
||||||
|
|
||||||
|
Date fromString4 ("12/31/2007");
|
||||||
|
is (fromString4.month (), 12, "ctor (std::string) -> m");
|
||||||
|
is (fromString4.day (), 31, "ctor (std::string) -> d");
|
||||||
|
is (fromString4.year (), 2007, "ctor (std::string) -> y");
|
||||||
|
|
||||||
|
Date fromString5 ("12/31/2007", "m/d/Y");
|
||||||
|
is (fromString5.month (), 12, "ctor (std::string) -> m");
|
||||||
|
is (fromString5.day (), 31, "ctor (std::string) -> d");
|
||||||
|
is (fromString5.year (), 2007, "ctor (std::string) -> y");
|
||||||
|
|
||||||
|
Date fromString6 ("20071231", "YMD");
|
||||||
|
is (fromString6.month (), 12, "ctor (std::string) -> m");
|
||||||
|
is (fromString6.day (), 31, "ctor (std::string) -> d");
|
||||||
|
is (fromString6.year (), 2007, "ctor (std::string) -> y");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
91
task.html
91
task.html
@@ -1,7 +1,7 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
<!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">
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
<head>
|
<head>
|
||||||
<title>Task 1.1.0</title>
|
<title>Task 1.2.0</title>
|
||||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
body {
|
body {
|
||||||
@@ -167,10 +167,33 @@ a img { border: none; padding: 0; margin: 0; }
|
|||||||
<div class="content">
|
<div class="content">
|
||||||
<p>
|
<p>
|
||||||
Download the latest task source code
|
Download the latest task source code
|
||||||
<a href="http://www.beckingham.net/task-1.1.0.tar.gz">task-1.1.0.tar.gz</a>
|
<a href="http://www.beckingham.net/task-1.2.0.tar.gz">task-1.2.0.tar.gz</a>
|
||||||
(6/7/2008).
|
(6/13/2008).
|
||||||
|
</p>
|
||||||
|
|
||||||
New in version 1.1.0:
|
<p>
|
||||||
|
<h4>New in version 1.2.0</h4>
|
||||||
|
source: <a href="http://www.beckingham.net/task-1.2.0.tar.gz">task-1.2.0.tar.gz</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Subprojects supported - please see documentation below, or TUTORIAL
|
||||||
|
file
|
||||||
|
<li>"dateformat" configuration variable now properly used to parse as
|
||||||
|
well as render dates
|
||||||
|
<li>"task list x" now performs a caseless comparison between "x" and
|
||||||
|
the task description
|
||||||
|
<li>"showage" configuration variable determines whether the "Age" column
|
||||||
|
should appear on the "task list" and "task next" reports
|
||||||
|
<li>Improvements to the TUTORIAL file and this page
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<h4>New in version 1.1.0</h4>
|
||||||
|
source: <a href="http://www.beckingham.net/task-1.1.0.tar.gz">task-1.1.0.tar.gz</a>
|
||||||
|
<br />
|
||||||
|
Debian package: <a href="http://www.beckingham.net/task_1.1.0-1_i386.deb">task_1.1.0-1_i386.deb</a>
|
||||||
|
(Thanks to Richard Querin)
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
@@ -223,10 +246,10 @@ a img { border: none; padding: 0; margin: 0; }
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre><code>% ls
|
<pre><code>% ls
|
||||||
task-1.1.0.tar.gz
|
task-1.2.0.tar.gz
|
||||||
% gunzip task-1.1.0.tar.gz
|
% gunzip task-1.2.0.tar.gz
|
||||||
% tar xf task-1.1.0.tar
|
% tar xf task-1.2.0.tar
|
||||||
% cd task-1.1.0
|
% cd task-1.2.0
|
||||||
% ./configure
|
% ./configure
|
||||||
...
|
...
|
||||||
% make
|
% make
|
||||||
@@ -340,6 +363,52 @@ Permanently delete task? (y/n) y</code></pre>
|
|||||||
Wedding project tasks:
|
Wedding project tasks:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Subprojects are supported. If you have a project "Wedding", you can
|
||||||
|
specify that a task is a subproject "Transport" of "Wedding" by
|
||||||
|
assigning the project "Wedding.Transport". Let's do this:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre><code>% task 2 project:Wedding.Transport
|
||||||
|
% task ls
|
||||||
|
|
||||||
|
ID Project Pri Description
|
||||||
|
3 Family Send John a birthday card
|
||||||
|
2 Wedding.Transport Reserve a rental car
|
||||||
|
1 Wedding Book plane ticket</code></pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Task matches the leftmost part of the project when searching, so
|
||||||
|
projects may be abbreviated:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre><code>% task ls project:Wedding.Tra
|
||||||
|
|
||||||
|
ID Project Pri Description
|
||||||
|
2 Wedding.Transport Reserve a rental car</code></pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This way of matching projects can be used to see all tasks under
|
||||||
|
the "Wedding" project and all subprojects:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre><code>% task ls project:Wedding
|
||||||
|
|
||||||
|
ID Project Pri Description
|
||||||
|
2 Wedding.Transport Reserve a rental car
|
||||||
|
1 Wedding Book plane ticket</code></pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Let's reassign 2 back to the "Wedding" project:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre><code>% task 2 project:Wedding</code></pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Now that projects are assigned, we can look at just the
|
||||||
|
Wedding project tasks:
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre><code>% task ls project:Wedding
|
<pre><code>% task ls project:Wedding
|
||||||
|
|
||||||
ID Project Pri Description
|
ID Project Pri Description
|
||||||
@@ -978,6 +1047,12 @@ on_white on_bright_white</code></pre>
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</p>
|
</p>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>showage<dt>
|
||||||
|
<dd>
|
||||||
|
May be "yes" or "no". Determines whether the "Age"
|
||||||
|
column appears on the "list" and "next" reports.
|
||||||
<dd>
|
<dd>
|
||||||
|
|
||||||
<dt>color</dt>
|
<dt>color</dt>
|
||||||
|
|||||||
Reference in New Issue
Block a user