Compare commits
251 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f6b8b39d8b | ||
|
|
11ee827a0d | ||
|
|
89bbce8661 | ||
|
|
e1a7f61fb1 | ||
|
|
f310924675 | ||
|
|
2fd7f6d681 | ||
|
|
612b872ed4 | ||
|
|
f97955ded8 | ||
|
|
38907ac6d7 | ||
|
|
1da111ad6e | ||
|
|
c7d0b1c21b | ||
|
|
0c775f7998 | ||
|
|
c872e30ef5 | ||
|
|
2c826b6213 | ||
|
|
9d8777ec7d | ||
|
|
ee06280808 | ||
|
|
da8c3c1a16 | ||
|
|
4346f83f6e | ||
|
|
8b045156d0 | ||
|
|
c4e459e8d7 | ||
|
|
77475136b9 | ||
|
|
362b4a5bc9 | ||
|
|
ff14f0a28a | ||
|
|
a6637db232 | ||
|
|
95f07cf363 | ||
|
|
f9035eec70 | ||
|
|
cc5d44ee9d | ||
|
|
3f97bb0663 | ||
|
|
e268b7f71c | ||
|
|
753305a262 | ||
|
|
cec42bb2c4 | ||
|
|
de7f70ad3e | ||
|
|
046f511d66 | ||
|
|
e2e5b4884c | ||
|
|
05243c9e7a | ||
|
|
fd823871f0 | ||
|
|
4087a82402 | ||
|
|
e8da71498d | ||
|
|
4ab665b876 | ||
|
|
6762af8ffd | ||
|
|
407ef39c54 | ||
|
|
de4194479a | ||
|
|
08188fb811 | ||
|
|
cd89e10cfb | ||
|
|
1c736a319d | ||
|
|
72f84b3c3e | ||
|
|
e8443889bb | ||
|
|
e81fdd1975 | ||
|
|
f9c3103264 | ||
|
|
143666aca0 | ||
|
|
f7fc455b62 | ||
|
|
5814432366 | ||
|
|
90c721295a | ||
|
|
5cf33105a3 | ||
|
|
b23bad9a5b | ||
|
|
c61a295df7 | ||
|
|
aec64afc5c | ||
|
|
72ff15ea7a | ||
|
|
fea19e036a | ||
|
|
98391a0c24 | ||
|
|
2975b9244a | ||
|
|
c78be053cb | ||
|
|
708995093b | ||
|
|
7fea1f6a63 | ||
|
|
b67b27f5cd | ||
|
|
07819a1885 | ||
|
|
e03e1ec7b0 | ||
|
|
fb674a5626 | ||
|
|
410a63fe14 | ||
|
|
2cc625f631 | ||
|
|
51a78ab996 | ||
|
|
d7f9b2165c | ||
|
|
d135dc2337 | ||
|
|
57a11a74e1 | ||
|
|
f73281ee30 | ||
|
|
262e42d42b | ||
|
|
99174d66b6 | ||
|
|
a0838474c4 | ||
|
|
3235ac592f | ||
|
|
dcedbb3076 | ||
|
|
e84c5c4a3c | ||
|
|
c4ec5989fe | ||
|
|
a737b0e0c8 | ||
|
|
f2b7780d6b | ||
|
|
1b6faf57c9 | ||
|
|
76c66b8ab1 | ||
|
|
fe84ddcc98 | ||
|
|
0d832a6848 | ||
|
|
a77d4662f8 | ||
|
|
60915cefd4 | ||
|
|
f896d3f160 | ||
|
|
e23243e195 | ||
|
|
5b14fb63d8 | ||
|
|
081f8f5b3c | ||
|
|
06062a96eb | ||
|
|
2f18c512e0 | ||
|
|
7431f0cdd3 | ||
|
|
22f0b1d9fb | ||
|
|
b8187e24ae | ||
|
|
120593887b | ||
|
|
01e5e773eb | ||
|
|
e0fd39db7b | ||
|
|
a39261f82d | ||
|
|
a6b45af0a2 | ||
|
|
daea320564 | ||
|
|
1cbec205f1 | ||
|
|
579232b7ea | ||
|
|
cee8fda236 | ||
|
|
4dda1f0c27 | ||
|
|
0571412da0 | ||
|
|
b4f031e4a7 | ||
|
|
5b1d64960d | ||
|
|
a5fef2cc6b | ||
|
|
8ab3c1cc3c | ||
|
|
2700713c03 | ||
|
|
567bdd98a4 | ||
|
|
25425614b1 | ||
|
|
3b65051e9e | ||
|
|
5f4563af2f | ||
|
|
7e2bd166fa | ||
|
|
41b60f88d3 | ||
|
|
93ec320555 | ||
|
|
c1291dc587 | ||
|
|
57deb83b25 | ||
|
|
e4f5d6579c | ||
|
|
99dc72f26f | ||
|
|
406e648d58 | ||
|
|
db7b2dd9fe | ||
|
|
c31ec6b6a6 | ||
|
|
1a656f0f60 | ||
|
|
5ec0d569a9 | ||
|
|
3979c3283e | ||
|
|
ca795ea281 | ||
|
|
d10e9be500 | ||
|
|
f790df24c5 | ||
|
|
ca933d7f39 | ||
|
|
827bc6204b | ||
|
|
4537d5048e | ||
|
|
74ea5b4ef6 | ||
|
|
cc2220b406 | ||
|
|
7389ce617a | ||
|
|
165001acac | ||
|
|
3d3d788961 | ||
|
|
3c196230dd | ||
|
|
9a350a7dcd | ||
|
|
92579e5531 | ||
|
|
40a538a769 | ||
|
|
b6e4bc966f | ||
|
|
03815967d2 | ||
|
|
7049bf19d9 | ||
|
|
c69c3bb090 | ||
|
|
7238d1f1c9 | ||
|
|
9f82c55c5b | ||
|
|
87be68e2e8 | ||
|
|
7b1dec0d77 | ||
|
|
f8af5d999a | ||
|
|
8efd8620c8 | ||
|
|
e8a795befb | ||
|
|
b5690f00e2 | ||
|
|
65f74da7a4 | ||
|
|
429d0f3071 | ||
|
|
4baf30cf9c | ||
|
|
a3882160fa | ||
|
|
cd85a28e98 | ||
|
|
e33a918c24 | ||
|
|
df82fade2c | ||
|
|
2d2bd47075 | ||
|
|
bdd1b16ba0 | ||
|
|
5383943fa7 | ||
|
|
8ac3978222 | ||
|
|
c9a6d2a750 | ||
|
|
64cfc26ff3 | ||
|
|
7c87bbc19a | ||
|
|
4a524a220e | ||
|
|
2216eee678 | ||
|
|
28c97f181a | ||
|
|
0cfc9c720e | ||
|
|
05b5273136 | ||
|
|
c35a764019 | ||
|
|
8c95e82a63 | ||
|
|
79d644c257 | ||
|
|
2d07b08260 | ||
|
|
1f45e47e36 | ||
|
|
dac1942cad | ||
|
|
6d8cb5181f | ||
|
|
d174bb1143 | ||
|
|
dc946e175e | ||
|
|
9f278b1ffc | ||
|
|
6fade84535 | ||
|
|
0ff33d1c16 | ||
|
|
1999e38ba5 | ||
|
|
17de9fec9f | ||
|
|
751094cffb | ||
|
|
012e47267f | ||
|
|
bd5e91c31f | ||
|
|
9e7844796b | ||
|
|
209f7ffb00 | ||
|
|
28e997691f | ||
|
|
3f418c6fdc | ||
|
|
0362b41f3b | ||
|
|
4fa4c5f532 | ||
|
|
3088e1ebe1 | ||
|
|
6a7c66aa05 | ||
|
|
3b1d396e0a | ||
|
|
463c968cac | ||
|
|
41b8b207d4 | ||
|
|
9535121c1e | ||
|
|
9988ecec5e | ||
|
|
d573599a7e | ||
|
|
d831ab335a | ||
|
|
d7a9d06360 | ||
|
|
d69d658531 | ||
|
|
5c89c0f1be | ||
|
|
964d04322c | ||
|
|
8157c729d6 | ||
|
|
a1b7516cf8 | ||
|
|
1e70400143 | ||
|
|
6e956b45ad | ||
|
|
59a014d866 | ||
|
|
76c9d3565c | ||
|
|
8c484a333d | ||
|
|
0605161236 | ||
|
|
f9272773ac | ||
|
|
e2fca47a27 | ||
|
|
92ba36bdec | ||
|
|
72efddc066 | ||
|
|
bcf512e529 | ||
|
|
6d551357ff | ||
|
|
0219ed4fe3 | ||
|
|
cc7c1819ce | ||
|
|
1a4469d388 | ||
|
|
4e63d93005 | ||
|
|
481a0aa1eb | ||
|
|
6764a6a7ec | ||
|
|
dae268a836 | ||
|
|
096a4b9bdb | ||
|
|
e65a45ce17 | ||
|
|
01b3cb190c | ||
|
|
6faf1e44f5 | ||
|
|
2307dcab8a | ||
|
|
eba05513f7 | ||
|
|
2f7060ce56 | ||
|
|
c28c698bbf | ||
|
|
b55eaf8f16 | ||
|
|
3d4beaf41f | ||
|
|
50ccb67185 | ||
|
|
14d3abacf4 | ||
|
|
857f813a24 | ||
|
|
5498986e15 | ||
|
|
eb827603c3 | ||
|
|
b548342acc |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,4 +1,3 @@
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
auto.h*
|
||||
@@ -11,3 +10,5 @@ stamp-h1
|
||||
Makefile
|
||||
configure
|
||||
config.log
|
||||
www.xls
|
||||
*~
|
||||
|
||||
21
AUTHORS
21
AUTHORS
@@ -1,21 +1,36 @@
|
||||
Principal Author:
|
||||
Paul Beckingham, paul@beckingham.net
|
||||
Paul Beckingham
|
||||
|
||||
Contributing Authors:
|
||||
Damian Glenny
|
||||
Andy Lester
|
||||
H. İbrahim Güngör
|
||||
Stefan Dorn
|
||||
Michael Greb
|
||||
Benjamin Tegarden
|
||||
Chris Pride
|
||||
Richard Querin
|
||||
Federico Hernandez
|
||||
T. Charles Yun
|
||||
David J Patrick
|
||||
P.C. Shyamshankar
|
||||
Johan Friis
|
||||
Steven de Brouwer
|
||||
|
||||
With thanks to:
|
||||
Eugene Kramer
|
||||
Srijith K
|
||||
Richard Querin
|
||||
Bruce Israel
|
||||
Thomas Engel
|
||||
Nishiishii
|
||||
galvanizd
|
||||
Stas Antons
|
||||
Vincent Fleuranceau
|
||||
T. Charles Yun
|
||||
ArchiMark
|
||||
Carlos Yoder
|
||||
Russell Friesenhahn
|
||||
Paolo Marsi
|
||||
Eric Farris
|
||||
Bruce Dillahunty
|
||||
Askme Too
|
||||
|
||||
|
||||
375
ChangeLog
375
ChangeLog
@@ -1,7 +1,93 @@
|
||||
|
||||
------ current release ---------------------------
|
||||
|
||||
1.5.0 (?)
|
||||
1.7.0 (5/14/2009)
|
||||
+ Improved the errors when parsing a corrupt or unrecognized pending.data
|
||||
or completed.data file (thanks to T. Charles Yun).
|
||||
+ Added details to the "info" report about recurring tasks (thanks to T.
|
||||
Charles Yun).
|
||||
+ Now writes a sample "defaultwidth" configuration variable to the default
|
||||
.taskrc file (thanks to T. Charles Yun).
|
||||
+ Task allows commands that require an ID to now be given a sequence, which
|
||||
is a set of IDs. This allows commands like "task delete 1 2 5-10,12".
|
||||
+ Fixed bug in the ghistory report, which caused it to only show a new
|
||||
month if a task was added during that month.
|
||||
+ New command "duplicate" which allow existing task(s) to be duplicated,
|
||||
and also have modifications applied (thanks to David J Patrick).
|
||||
+ The "append", and "done" commands now allow modifications to be applied
|
||||
to the task(s) (thanks to David J Patrick).
|
||||
+ Improved word wrapping in various output.
|
||||
+ Fixed bug that added an extra line between header and graph in the
|
||||
ghistory report.
|
||||
+ Added simple 'taskprogram' mailing list subscribe form to the web site.
|
||||
+ For custom reports that define a "limit" to the number of rows of output
|
||||
such as "oldest" and "newest", task allows an override value. For
|
||||
example "task oldest 5" will display the 5 oldest tasks.
|
||||
+ Modified the "stats" report so that it has the same aesthetics as the
|
||||
other reports.
|
||||
+ New "timesheet" command displays tasks completed and started, per week,
|
||||
and can display multiple weeks.
|
||||
+ New tab completion script, task_completion.sh, for bash users, is installed
|
||||
to /usr/local/share/task (thanks to Federico Hernandez).
|
||||
+ Applied patch to allow task to build on Arch Linux (thanks to Johan Friis).
|
||||
+ Applied patch to fix a UUID bug on Solaris 8 (thanks to Steven de Brouwer).
|
||||
+ The task man page is now installed. Try "man task" (thanks to Federico
|
||||
Hernandez and P.C. Shyamshankar).
|
||||
+ Fixed bug that causes task to create a default .task directory, even if
|
||||
data.location specified otherwise (thanks to Federico Hernandez).
|
||||
+ New "edit" command that fires up a text editor (uses 'editor' configuration
|
||||
variable, $VISUAL or $EDITOR environment variable) and allows direct
|
||||
editing of all editable task details.
|
||||
|
||||
------ old releases ------------------------------
|
||||
|
||||
1.6.1 (4/24/2009) 1b6faf57c998617024d0348a87b941a5d2ab2249
|
||||
+ Fixed bug that caused new, first-time .taskrc files to be written without
|
||||
including the custom report labels (thanks to P.C. Shyamshankar).
|
||||
|
||||
1.6.0 (4/12/2009) 06062a96eb57d10dcd7fbe1edf968bb638a0b3a9
|
||||
+ Added support for new "append" command that adds more description text to
|
||||
an existing task.
|
||||
+ Added support for the "weekdays" recurrence, which means a task can recur
|
||||
five times a week, and not on weekends (thanks to Chris Pride).
|
||||
+ UTF8 text is now supported in task project names, tags and descriptions.
|
||||
+ Fixed bug that caused the y/n confirmation on task deletion to ignore the
|
||||
Enter key and fail to re-prompt (thanks to Bruce Dillahunty).
|
||||
+ When the "echo.command" configuration variable is set to "yes", it causes
|
||||
commands that modify tasks to display which task was affected (thanks to
|
||||
Bruce Dillahunty).
|
||||
+ A task can now be annotated with the command "task <id> annotate ...", and
|
||||
a timestamped annotation will appear in reports.
|
||||
+ A 'description_only' column is now available for use in custom reports,
|
||||
and it excludes annotations.
|
||||
+ A task can now be upgraded to a recurring task by adding a recurrence
|
||||
frequency, a due date, and an optional until date.
|
||||
+ When a recurring task is modified, all other instances of the recurring
|
||||
task are also modified.
|
||||
+ Custom reports now support user-specified column labels (thanks to T.
|
||||
Charles Yun).
|
||||
+ Task can now import tasks from a variety of data formats, including task
|
||||
export files from versions 1.4.3 and earlier, versions 1.5.0 and later,
|
||||
todo.sh 2.x, CSV, plain text and task command line. See online docs for
|
||||
full details.
|
||||
+ Export was including 'id' in the column header even though it was not
|
||||
included in the data.
|
||||
+ The task file format has changed slightly. Please back up your task
|
||||
data files before upgrading to 1.6.0.
|
||||
+ Added new column 'recurrence_indicator' that displays an 'R' if the task
|
||||
is a recurring task. This column can be added to any custom report.
|
||||
+ Added new column 'tag_indicator' that displays a '+' if the task
|
||||
has any tags. This column can be added to any custom report.
|
||||
+ Fixed bug where sometimes a task description was concatenated oddly if
|
||||
there was a colon somewhere in the description.
|
||||
+ Fixed bug that caused recurring annual tasks to exhibit a creeping due
|
||||
date, because of an assumption of 365 days per year, which failed to
|
||||
consider leap years (thanks to T. Charles Yun).
|
||||
+ Annotations can now be modified with the substitution commands /from/to/.
|
||||
+ Substitutions can now be made global with /from/to/g and all occurrences
|
||||
of "from" will be replaced with "to".
|
||||
|
||||
1.5.0 (3/15/2009) 87be68e2e83d7bb628be1e5679b16a49a26d3549
|
||||
+ Removed deprecated TUTORIAL file.
|
||||
+ Removed "showage" configuration variable.
|
||||
+ "task stop" can now remove the start time from a started task.
|
||||
@@ -11,146 +97,175 @@
|
||||
which may be spelling mistakes or deprecated variables.
|
||||
+ "configure --enable-debug" now supported to suppress compiler optimization
|
||||
to allow debugging.
|
||||
+ Allow lower case priorities, and automatically upper case them.
|
||||
+ Added support for "due" configuration variable which defines the number
|
||||
of days in the future when a task is considered due.
|
||||
+ Added support for custom reports, comprised of a set of column names and
|
||||
sort order, with optional filtering in the configuration file. This
|
||||
means user-defined reports can be written, and the reports currently
|
||||
in the configuration file can be renamed. Several of task's built in
|
||||
reports have been converted to user-defined reports.
|
||||
+ New online documentation for custom reports.
|
||||
+ New algorithm for determining when the "nag" message is displayed.
|
||||
+ Fixed bug where task hangs with a certain combination of recurring tasks
|
||||
and shadow files.
|
||||
+ Fixed bug with the task sort algorithm, which led to an unstable sequence
|
||||
when there were only a handful of tasks.
|
||||
+ Performance enhanced by eliminating unnecessary sorting.
|
||||
+ Task now has a large (and growing) test suite and bug regression tests
|
||||
to help ensure higher quality releases.
|
||||
+ Fixed bug that caused performance hit during table rendering.
|
||||
+ Fixed bug that concatenated a modified description without spaces.
|
||||
+ Added new column 'recur' that displays the recurrence period of any
|
||||
recurring tasks. This column can be added to any custom report.
|
||||
+ Added support for "color.recurring" configuration variable which
|
||||
specifies the color of recurring tasks.
|
||||
+ Added support for "locking" configuration variable that controls whether
|
||||
file locking is used.
|
||||
+ Task export feature now includes recurrence information, removes nested
|
||||
quotes, and limits output to pending tasks.
|
||||
+ Task no longer includes deleted tasks in the summary report (thanks to
|
||||
Benjamin Tegarden).
|
||||
+ Fixed bug that prevented the summary report from properly reporting
|
||||
recently completed tasks.
|
||||
|
||||
------ old releases ------------------------------
|
||||
|
||||
1.4.3 (11/1/2008)
|
||||
1.4.3 (11/1/2008) 8639e9260646c8c9224e0fc47e5d2443b46eecfc
|
||||
+ Fixed misleading task count at bottom on "info" report.
|
||||
+ Added support for a shadow file that contains a plain text task report,
|
||||
with the "shadow.file" and "shadow.command" configuration variables
|
||||
with the "shadow.file" and "shadow.command" configuration variables.
|
||||
The shadow file is automatically updated whenever the task database
|
||||
changes. Useful for integrating with "Samurize"
|
||||
changes. Useful for integrating with "Samurize".
|
||||
+ Task now displays a message whenever a shadow file is updated, if the
|
||||
"shadow.notify" configuration variable is set "on"
|
||||
+ Bug: adding a task with a \n, \r or \f in it now fails properly
|
||||
"shadow.notify" configuration variable is set "on".
|
||||
+ Bug: adding a task with a \n, \r or \f in it now fails properly.
|
||||
+ Removed "usage" command, and support for "command.logging" configuration
|
||||
variable.
|
||||
+ Added documentation for Shadow files.
|
||||
+ Added documentation for task filters.
|
||||
|
||||
1.4.2 (9/18/2008)
|
||||
1.4.2 (9/18/2008) e7304e86ce9bb80978c7055fd2a9e999619a6fb8
|
||||
+ "task undo" can now retract a "task done" command, provided no reports
|
||||
have been run (and therefore TDB::gc run)
|
||||
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)
|
||||
character (thanks to Andy Lester).
|
||||
+ Task now uses dashes (-----) to column underlines when color is disabled
|
||||
(thanks to Vincent Fleuranceau)
|
||||
(thanks to Vincent Fleuranceau).
|
||||
+ Task now allows mixed case attribute names (pri:, PRI:, Pri: ...) and
|
||||
commands (add, ADD, Add ...) (thanks to Vincent Fleuranceau)
|
||||
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
|
||||
(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 ...)
|
||||
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)
|
||||
using gcc 4.3 (thanks to H. İbrahim Güngör).
|
||||
|
||||
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
|
||||
+ Provided Mac .pkg binary
|
||||
1.4.1 (7/18/2008) e080c3168c6064628ab85b21bd859d9875a3a9a7
|
||||
+ 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.
|
||||
+ Provided Mac .pkg binary.
|
||||
|
||||
1.4.0 (7/10/2008)
|
||||
+ New recurring tasks feature
|
||||
1.4.0 (7/10/2008) 60b7d15a1d22e064acf0974c5d7eabbb57dd8071
|
||||
+ New recurring tasks feature.
|
||||
+ "task undelete" can now undelete erroneously deleted tasks, provided no
|
||||
reports have been run (and therefore TDB::gc run)
|
||||
+ Added averages to the "task history" report
|
||||
+ Added ability to override ~/.taskrc with rc:<file>
|
||||
+ Added bar chart history report "task ghistory"
|
||||
+ Added task filtering on all reports
|
||||
+ Automatically shuts off color, curses when output is not a tty
|
||||
+ Supports relative due: dates (tomorrow, wednesday, 23rd, eom ...)
|
||||
+ Supports the ~ character in .taskrc data.location
|
||||
reports have been run (and therefore TDB::gc run).
|
||||
+ Added averages to the "task history" report.
|
||||
+ Added ability to override ~/.taskrc with rc:<file>.
|
||||
+ Added bar chart history report "task ghistory".
|
||||
+ Added task filtering on all reports.
|
||||
+ Automatically shuts off color, curses when output is not a tty.
|
||||
+ Supports relative due: dates (tomorrow, wednesday, 23rd, eom ...).
|
||||
+ Supports the ~ character in .taskrc data.location.
|
||||
+ Allows colons on the description, provided what is to the left of the colon
|
||||
is not a standard attribute name
|
||||
+ Bug: Fixed where Esc[0m sequences were being emitted for no good reason
|
||||
+ Bug: Fixed underlined table headers when color is turned off
|
||||
+ Bug: Adding a blank priority resulted in an assigned garbage value
|
||||
+ Bug: Fixed parsing of date "07/08/2008" when using dateformat "m/d/Y"
|
||||
is not a standard attribute name.
|
||||
+ Bug: Fixed where Esc[0m sequences were being emitted for no good reason.
|
||||
+ Bug: Fixed underlined table headers when color is turned off.
|
||||
+ Bug: Adding a blank priority resulted in an assigned garbage value.
|
||||
+ Bug: Fixed parsing of date "07/08/2008" when using dateformat "m/d/Y".
|
||||
|
||||
1.3.1 (6/21/2008)
|
||||
1.3.1 (6/21/2008) 3a6de7d9402f2609a773a73b16eff97b14a32869
|
||||
+ New configuration variable, "defaultwidth" that determines the width
|
||||
of tables when ncurses support is not available
|
||||
of tables when ncurses support is not available.
|
||||
+ Bug: "showage" configuration variable should apply to all reports, not
|
||||
just the ones based on "list"
|
||||
just the ones based on "list".
|
||||
+ Bug: Fixed segmentation faults on Ubuntu when the "dateformat"
|
||||
configuration variables was missing. This was a code bug, and should
|
||||
have affected more platforms
|
||||
have affected more platforms.
|
||||
+ Bug: Task now will recreate a missing ~/.taskrc file, OR a missing
|
||||
~/.task directory
|
||||
~/.task directory.
|
||||
|
||||
1.3.0 (6/18/2008)
|
||||
1.3.0 (6/18/2008) 6673e408a223af98c38779c20b08524042c0edfa
|
||||
+ "task calendar" now displays multiple months per line, adjustable by the
|
||||
"monthsperline" configuration variable. Feature added by Damian Glenny
|
||||
+ "task export" can now filter tasks like the reports
|
||||
+ Factored out code to filter tasks
|
||||
"monthsperline" configuration variable. Feature added by Damian Glenny.
|
||||
+ "task export" can now filter tasks like the reports.
|
||||
+ Factored out code to filter tasks.
|
||||
+ Displays shorter message when a command is entered incorrectly, and the
|
||||
full usage for "task help"
|
||||
+ "task oldest" shows the oldest tasks
|
||||
+ "task newest" shows the newest tasks
|
||||
full usage for "task help".
|
||||
+ "task oldest" shows the oldest tasks.
|
||||
+ "task newest" shows the newest tasks.
|
||||
+ Bug: Segmentation fault when no "dateformat" configuration variable
|
||||
specified
|
||||
specified.
|
||||
+ Bug: Fixed bug whereby if you have more than one task with a due date, 7
|
||||
days gets added to the entry date of task 2..n
|
||||
+ Bug: Fixed bug whereby "1 wks" was being improperly pluralized
|
||||
days gets added to the entry date of task 2..n.
|
||||
+ Bug: Fixed bug whereby "1 wks" was being improperly pluralized.
|
||||
|
||||
1.2.0 (6/13/2008)
|
||||
1.2.0 (6/13/2008) c393d47cdfe7e197a31e94f4bb764474fa05ad8d
|
||||
+ Bug: "dateformat" configuration variable used to display dates, but
|
||||
not parse them
|
||||
not parse them.
|
||||
+ "task list x" now performs a caseless comparison between "x" and the
|
||||
description
|
||||
+ Task sub projects supported
|
||||
description.
|
||||
+ Task sub projects supported.
|
||||
+ "showage" confguration determines whether "Age" column appears on the
|
||||
"list" and "next" reports
|
||||
+ Improved TUTORIAL
|
||||
"list" and "next" reports.
|
||||
+ Improved TUTORIAL.
|
||||
|
||||
1.1.0 (6/7/2008)
|
||||
1.1.0 (6/7/2008) 73286e86628725b346db2a25fbcd4bd68efb9b3a
|
||||
+ "blanklines" configuration to stop displaying unnecessary white
|
||||
space and thus work better on small-screen devices
|
||||
+ "dateformat" configuration now determines how dates are formatted
|
||||
+ Better formatting of "task tags" output
|
||||
+ http://www.beckingham.net/task.html home page set up
|
||||
+ Added tags to the "task long" report
|
||||
space and thus work better on small-screen devices.
|
||||
+ "dateformat" configuration now determines how dates are formatted.
|
||||
+ Better formatting of "task tags" output.
|
||||
+ http://www.beckingham.net/task.html home page set up.
|
||||
+ Added tags to the "task long" report.
|
||||
|
||||
1.0.1 (6/4/2008)
|
||||
1.0.1 (6/4/2008) d216d401217027d93581808fc8944ab7d6b85fb0
|
||||
+ Bug: UUID generator not properly terminating string.
|
||||
+ Bug: srandom/srand not called prior to UUID generation.
|
||||
|
||||
1.0.0 (6/3/2008)
|
||||
+ New movie made, uploaded
|
||||
+ Bug: assertion fails on mobile for t v
|
||||
+ Bug: configure.ac does not properly determine ncurses availability
|
||||
+ Bug: Cannot seem to use the percent character in a task description
|
||||
+ Bug: New installation "task stats" reports newest task 12/31/1969
|
||||
+ Bug: New installation task projects displays header but no data - should short-circuit
|
||||
+ Bug: incorrect color specification in sample .taskrc file
|
||||
+ Bug: when run without arguments, task dumps core on Solaris 10
|
||||
+ "task calendar" now reports all months with due pending tasks
|
||||
+ Added rules for colorization by tag, project and keyword
|
||||
+ Added legend to "task calendar"
|
||||
1.0.0 (6/3/2008) f3de5c07118c597091a05c7d7fe8bdeae95474c1
|
||||
+ New movie made, uploaded.
|
||||
+ Bug: assertion fails on mobile for t v.
|
||||
+ Bug: configure.ac does not properly determine ncurses availability.
|
||||
+ Bug: Cannot seem to use the percent character in a task description.
|
||||
+ Bug: New installation "task stats" reports newest task 12/31/1969.
|
||||
+ Bug: New installation task projects displays header but no data - should short-circuit.
|
||||
+ Bug: incorrect color specification in sample .taskrc file.
|
||||
+ Bug: when run without arguments, task dumps core on Solaris 10.
|
||||
+ "task calendar" now reports all months with due pending tasks.
|
||||
+ Added rules for colorization by tag, project and keyword.
|
||||
+ Added legend to "task calendar".
|
||||
|
||||
0.9.9 (5/27/2008)
|
||||
0.9.9 (5/27/2008) 2ecf50032226c91b406f247417a063dc17c8e324
|
||||
+ Autoconf/automake behaving properly.
|
||||
+ Clean build on OS X 10.5.
|
||||
+ Clean build on Ubuntu 8.0.
|
||||
+ Clean build on Fedora Core 8.
|
||||
+ Clean build on Fedora Core 9.
|
||||
|
||||
0.9.8 (5/25/2008)
|
||||
0.9.8 (5/25/2008) 18fd59a1edb20e5c68d086a97fae5fa9f6bb348a
|
||||
+ Added "task color" command.
|
||||
+ Removed unnecessary files.
|
||||
+ Completed documentation.
|
||||
|
||||
0.9.7 (5/24/2008)
|
||||
+ Migrated old compiler flags into Makefile.am
|
||||
+ Added ncurses endwin function check to configure.ac
|
||||
0.9.7 (5/24/2008) 25dc4150947a3e612c8118838d04b3bbe68441f7
|
||||
+ Migrated old compiler flags into Makefile.am.
|
||||
+ Added ncurses endwin function check to configure.ac.
|
||||
+ Set up structure for AUTHORS file.
|
||||
+ Set up NEWS file, with pleas for feedback.
|
||||
+ Added welcome message to README.
|
||||
@@ -161,31 +276,31 @@
|
||||
+ Removed unnecessary SAMPLE_taskrc, and assorted references.
|
||||
+ Cleaned up ChangeLog.
|
||||
+ Minor mods to standard docs.
|
||||
+ Bumped version to 0.9.7
|
||||
+ Changed some autoconf details
|
||||
+ Corrected comment in T.cpp
|
||||
+ Bumped version to 0.9.7.
|
||||
+ Changed some autoconf details.
|
||||
+ Corrected comment in T.cpp.
|
||||
+ Made unit tests compile and run again.
|
||||
+ Removed tests from distibution.
|
||||
|
||||
0.9.6 (5/13/208)
|
||||
+ Corrected wrong include file in Table.cpp
|
||||
+ Corrected wrong include file in Table.cpp.
|
||||
+ Replaced color management code.
|
||||
+ Improved color rules code.
|
||||
|
||||
0.9.5 (5/12/2008)
|
||||
+ Replaced Table storage with Grid.
|
||||
+ Added Grid.cpp to configure.ac
|
||||
+ Added Makefile to src/.gitignore
|
||||
+ Added Grid.cpp to configure.ac.
|
||||
+ Added Makefile to src/.gitignore.
|
||||
+ Makefile should not be part of the repository.
|
||||
+ Added Grid.cpp
|
||||
+ Added Grid::Cell::operator==
|
||||
+ Added Grid.cpp.
|
||||
+ Added Grid::Cell::operator==.
|
||||
+ ChangeLog file begun.
|
||||
+ Bumped version to 0.9.5 for next release.
|
||||
|
||||
0.9.4 (4/26/2008)
|
||||
+ Integrated new Grid object into build - not yet integrated into Table.
|
||||
+ More .gitignore tweaks.
|
||||
+ Added .gitignore
|
||||
+ Added .gitignore.
|
||||
+ Added more missing files.
|
||||
+ Added all source code.
|
||||
+ Generic OSS files added.
|
||||
@@ -206,29 +321,29 @@
|
||||
+ Consolidated header files, removed unnecessary ones.
|
||||
|
||||
0.9.0 (3/23/2008)
|
||||
+ flat source directory
|
||||
+ autoconf complete
|
||||
+ "task next"
|
||||
+ "task stats"
|
||||
+ "task export"
|
||||
+ Rules-based colorization
|
||||
+ flat source directory.
|
||||
+ autoconf complete.
|
||||
+ "task next".
|
||||
+ "task stats".
|
||||
+ "task export".
|
||||
+ Rules-based colorization.
|
||||
|
||||
0.8.1 (1/28/2008) - 0.8.16 (3/13/2008)
|
||||
+ autoconf conversion (many builds)
|
||||
+ autoconf conversion (many builds).
|
||||
|
||||
0.8.0 Polish (1/25/2008)
|
||||
+ Code cleanup, reorganization
|
||||
+ "task overdue"
|
||||
+ Add "age" column to list and long
|
||||
+ Use 'conf' for build, version tracking
|
||||
+ Add "/from/to/" description editing
|
||||
+ Code cleanup, reorganization.
|
||||
+ "task overdue".
|
||||
+ Add "age" column to list and long.
|
||||
+ Use 'conf' for build, version tracking.
|
||||
+ Add "/from/to/" description editing.
|
||||
|
||||
0.7.0 Multi-user, File handling, atomicity (1/8/2008)
|
||||
+ Clean, publishable API reimplementation
|
||||
+ File locking
|
||||
+ retain deleted tasks
|
||||
+ "task info ID" report showing all metadata
|
||||
+ File format v2, including UUID
|
||||
+ Clean, publishable API reimplementation.
|
||||
+ File locking.
|
||||
+ retain deleted tasks.
|
||||
+ "task info ID" report showing all metadata.
|
||||
+ File format v2, including UUID.
|
||||
|
||||
[Development hiatus while planning for T, TDB API, new features and the future
|
||||
of the project. Seeded to two testers for feedback, suggestions. Development
|
||||
@@ -236,40 +351,40 @@ deliberately stopped to allow extended use of task, allowing command logging and
|
||||
regular usage to determine which features were needed or unnecessary.]
|
||||
|
||||
0.6.0 Reports (12/27/2006)
|
||||
+ "task history"
|
||||
+ "task summary"
|
||||
+ "task calendar"
|
||||
+ due support
|
||||
+ Table sorting
|
||||
+ "task history".
|
||||
+ "task summary".
|
||||
+ "task calendar".
|
||||
+ due support.
|
||||
+ Table sorting.
|
||||
|
||||
0.5.0 Multi-user support (12/10/2006)
|
||||
+ Command logging
|
||||
+ "task usage" report
|
||||
+ Command logging.
|
||||
+ "task usage" report.
|
||||
|
||||
0.4.0 Destructive / modification commands (12/3/2006)
|
||||
+ "task delete" complete
|
||||
+ "task id ..." complete
|
||||
+ "task list ..." synonym for "task find ..."
|
||||
+ "task delete" complete.
|
||||
+ "task id ..." complete.
|
||||
+ "task list ..." synonym for "task find ...".
|
||||
|
||||
0.3.0 Work in progress support (12/3/2006)
|
||||
+ "task start" complete
|
||||
+ "task done" complete
|
||||
+ completed.data support
|
||||
+ "task start" complete.
|
||||
+ "task done" complete.
|
||||
+ completed.data support.
|
||||
|
||||
0.2.0 Neutral commands (12/2/2006)
|
||||
+ "task find" complete
|
||||
+ "task projects" complete
|
||||
+ "task tags" complete
|
||||
+ "task find" complete.
|
||||
+ "task projects" complete.
|
||||
+ "task tags" complete.
|
||||
|
||||
0.1.0 Constructive commands (12/1/2006)
|
||||
+ "task add" complete
|
||||
+ completed.data support
|
||||
+ ~/.taskrc support
|
||||
+ "task add" complete.
|
||||
+ completed.data support.
|
||||
+ ~/.taskrc support.
|
||||
|
||||
0.0.1 Basic infrastructure (11/29/2006)
|
||||
+ Command line parsing
|
||||
+ API layer
|
||||
+ Usage
|
||||
+ Command line parsing.
|
||||
+ API layer.
|
||||
+ Usage.
|
||||
|
||||
------ start -----------------------------------
|
||||
|
||||
|
||||
@@ -18,5 +18,5 @@ included.
|
||||
color.cpp Color support functions.
|
||||
rules.cpp Auto-colorization rules.
|
||||
|
||||
Don't forget, please send bugs, patches to task@beckingham.net
|
||||
Please send bugs, patches to task@beckingham.net
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
SUBDIRS = src
|
||||
EXTRA_DIST = DEVELOPERS
|
||||
|
||||
EXTRA_DIST = task_completion.sh doc/man1/task.1 doc/man5/taskrc.5
|
||||
man1_MANS = doc/man1/task.1
|
||||
man5_MANS = doc/man5/taskrc.5
|
||||
otherdir = $(datadir)/doc/task-1.7.0
|
||||
other_DATA = AUTHORS ChangeLog COPYING INSTALL NEWS README task_completion.sh
|
||||
|
||||
734
Makefile.in
Normal file
734
Makefile.in
Normal file
@@ -0,0 +1,734 @@
|
||||
# Makefile.in generated by automake 1.10.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
VPATH = @srcdir@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
subdir = .
|
||||
DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
|
||||
$(srcdir)/Makefile.in $(srcdir)/auto.h.in \
|
||||
$(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \
|
||||
depcomp install-sh missing
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
|
||||
configure.lineno config.status.lineno
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = auto.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
SOURCES =
|
||||
DIST_SOURCES =
|
||||
RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
|
||||
html-recursive info-recursive install-data-recursive \
|
||||
install-dvi-recursive install-exec-recursive \
|
||||
install-html-recursive install-info-recursive \
|
||||
install-pdf-recursive install-ps-recursive install-recursive \
|
||||
installcheck-recursive installdirs-recursive pdf-recursive \
|
||||
ps-recursive uninstall-recursive
|
||||
man1dir = $(mandir)/man1
|
||||
am__installdirs = "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)" \
|
||||
"$(DESTDIR)$(otherdir)"
|
||||
man5dir = $(mandir)/man5
|
||||
NROFF = nroff
|
||||
MANS = $(man1_MANS) $(man5_MANS)
|
||||
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||
am__vpath_adj = case $$p in \
|
||||
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
*) f=$$p;; \
|
||||
esac;
|
||||
am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
|
||||
otherDATA_INSTALL = $(INSTALL_DATA)
|
||||
DATA = $(other_DATA)
|
||||
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
|
||||
distclean-recursive maintainer-clean-recursive
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DIST_SUBDIRS = $(SUBDIRS)
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
distdir = $(PACKAGE)-$(VERSION)
|
||||
top_distdir = $(distdir)
|
||||
am__remove_distdir = \
|
||||
{ test ! -d $(distdir) \
|
||||
|| { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
|
||||
&& rm -fr $(distdir); }; }
|
||||
DIST_ARCHIVES = $(distdir).tar.gz
|
||||
GZIP_ENV = --best
|
||||
distuninstallcheck_listfiles = find . -type f -print
|
||||
distcleancheck_listfiles = find . -type f -print
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXCPP = @CXXCPP@
|
||||
CXXDEPMODE = @CXXDEPMODE@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
GREP = @GREP@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
OBJEXT = @OBJEXT@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build_alias = @build_alias@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host_alias = @host_alias@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
SUBDIRS = src
|
||||
EXTRA_DIST = task_completion.sh doc/man1/task.1 doc/man5/taskrc.5
|
||||
man1_MANS = doc/man1/task.1
|
||||
man5_MANS = doc/man5/taskrc.5
|
||||
otherdir = $(datadir)/doc/task-1.7.0
|
||||
other_DATA = AUTHORS ChangeLog COPYING INSTALL NEWS README task_completion.sh
|
||||
all: auto.h
|
||||
$(MAKE) $(AM_MAKEFLAGS) all-recursive
|
||||
|
||||
.SUFFIXES:
|
||||
am--refresh:
|
||||
@:
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
echo ' cd $(srcdir) && $(AUTOMAKE) --gnu '; \
|
||||
cd $(srcdir) && $(AUTOMAKE) --gnu \
|
||||
&& exit 0; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \
|
||||
cd $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
echo ' $(SHELL) ./config.status'; \
|
||||
$(SHELL) ./config.status;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
$(SHELL) ./config.status --recheck
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(srcdir) && $(AUTOCONF)
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
|
||||
|
||||
auto.h: stamp-h1
|
||||
@if test ! -f $@; then \
|
||||
rm -f stamp-h1; \
|
||||
$(MAKE) $(AM_MAKEFLAGS) stamp-h1; \
|
||||
else :; fi
|
||||
|
||||
stamp-h1: $(srcdir)/auto.h.in $(top_builddir)/config.status
|
||||
@rm -f stamp-h1
|
||||
cd $(top_builddir) && $(SHELL) ./config.status auto.h
|
||||
$(srcdir)/auto.h.in: $(am__configure_deps)
|
||||
cd $(top_srcdir) && $(AUTOHEADER)
|
||||
rm -f stamp-h1
|
||||
touch $@
|
||||
|
||||
distclean-hdr:
|
||||
-rm -f auto.h stamp-h1
|
||||
install-man1: $(man1_MANS) $(man_MANS)
|
||||
@$(NORMAL_INSTALL)
|
||||
test -z "$(man1dir)" || $(MKDIR_P) "$(DESTDIR)$(man1dir)"
|
||||
@list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \
|
||||
l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
|
||||
for i in $$l2; do \
|
||||
case "$$i" in \
|
||||
*.1*) list="$$list $$i" ;; \
|
||||
esac; \
|
||||
done; \
|
||||
for i in $$list; do \
|
||||
if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
|
||||
else file=$$i; fi; \
|
||||
ext=`echo $$i | sed -e 's/^.*\\.//'`; \
|
||||
case "$$ext" in \
|
||||
1*) ;; \
|
||||
*) ext='1' ;; \
|
||||
esac; \
|
||||
inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
|
||||
inst=`echo $$inst | sed -e 's/^.*\///'`; \
|
||||
inst=`echo $$inst | sed '$(transform)'`.$$ext; \
|
||||
echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
|
||||
$(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst"; \
|
||||
done
|
||||
uninstall-man1:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \
|
||||
l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
|
||||
for i in $$l2; do \
|
||||
case "$$i" in \
|
||||
*.1*) list="$$list $$i" ;; \
|
||||
esac; \
|
||||
done; \
|
||||
for i in $$list; do \
|
||||
ext=`echo $$i | sed -e 's/^.*\\.//'`; \
|
||||
case "$$ext" in \
|
||||
1*) ;; \
|
||||
*) ext='1' ;; \
|
||||
esac; \
|
||||
inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
|
||||
inst=`echo $$inst | sed -e 's/^.*\///'`; \
|
||||
inst=`echo $$inst | sed '$(transform)'`.$$ext; \
|
||||
echo " rm -f '$(DESTDIR)$(man1dir)/$$inst'"; \
|
||||
rm -f "$(DESTDIR)$(man1dir)/$$inst"; \
|
||||
done
|
||||
install-man5: $(man5_MANS) $(man_MANS)
|
||||
@$(NORMAL_INSTALL)
|
||||
test -z "$(man5dir)" || $(MKDIR_P) "$(DESTDIR)$(man5dir)"
|
||||
@list='$(man5_MANS) $(dist_man5_MANS) $(nodist_man5_MANS)'; \
|
||||
l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
|
||||
for i in $$l2; do \
|
||||
case "$$i" in \
|
||||
*.5*) list="$$list $$i" ;; \
|
||||
esac; \
|
||||
done; \
|
||||
for i in $$list; do \
|
||||
if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
|
||||
else file=$$i; fi; \
|
||||
ext=`echo $$i | sed -e 's/^.*\\.//'`; \
|
||||
case "$$ext" in \
|
||||
5*) ;; \
|
||||
*) ext='5' ;; \
|
||||
esac; \
|
||||
inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
|
||||
inst=`echo $$inst | sed -e 's/^.*\///'`; \
|
||||
inst=`echo $$inst | sed '$(transform)'`.$$ext; \
|
||||
echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \
|
||||
$(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst"; \
|
||||
done
|
||||
uninstall-man5:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(man5_MANS) $(dist_man5_MANS) $(nodist_man5_MANS)'; \
|
||||
l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
|
||||
for i in $$l2; do \
|
||||
case "$$i" in \
|
||||
*.5*) list="$$list $$i" ;; \
|
||||
esac; \
|
||||
done; \
|
||||
for i in $$list; do \
|
||||
ext=`echo $$i | sed -e 's/^.*\\.//'`; \
|
||||
case "$$ext" in \
|
||||
5*) ;; \
|
||||
*) ext='5' ;; \
|
||||
esac; \
|
||||
inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
|
||||
inst=`echo $$inst | sed -e 's/^.*\///'`; \
|
||||
inst=`echo $$inst | sed '$(transform)'`.$$ext; \
|
||||
echo " rm -f '$(DESTDIR)$(man5dir)/$$inst'"; \
|
||||
rm -f "$(DESTDIR)$(man5dir)/$$inst"; \
|
||||
done
|
||||
install-otherDATA: $(other_DATA)
|
||||
@$(NORMAL_INSTALL)
|
||||
test -z "$(otherdir)" || $(MKDIR_P) "$(DESTDIR)$(otherdir)"
|
||||
@list='$(other_DATA)'; for p in $$list; do \
|
||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||
f=$(am__strip_dir) \
|
||||
echo " $(otherDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(otherdir)/$$f'"; \
|
||||
$(otherDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(otherdir)/$$f"; \
|
||||
done
|
||||
|
||||
uninstall-otherDATA:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(other_DATA)'; for p in $$list; do \
|
||||
f=$(am__strip_dir) \
|
||||
echo " rm -f '$(DESTDIR)$(otherdir)/$$f'"; \
|
||||
rm -f "$(DESTDIR)$(otherdir)/$$f"; \
|
||||
done
|
||||
|
||||
# This directory's subdirectories are mostly independent; you can cd
|
||||
# into them and run `make' without going through this Makefile.
|
||||
# To change the values of `make' variables: instead of editing Makefiles,
|
||||
# (1) if the variable is set in `config.status', edit `config.status'
|
||||
# (which will cause the Makefiles to be regenerated when you run `make');
|
||||
# (2) otherwise, pass the desired values on the `make' command line.
|
||||
$(RECURSIVE_TARGETS):
|
||||
@failcom='exit 1'; \
|
||||
for f in x $$MAKEFLAGS; do \
|
||||
case $$f in \
|
||||
*=* | --[!k]*);; \
|
||||
*k*) failcom='fail=yes';; \
|
||||
esac; \
|
||||
done; \
|
||||
dot_seen=no; \
|
||||
target=`echo $@ | sed s/-recursive//`; \
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
echo "Making $$target in $$subdir"; \
|
||||
if test "$$subdir" = "."; then \
|
||||
dot_seen=yes; \
|
||||
local_target="$$target-am"; \
|
||||
else \
|
||||
local_target="$$target"; \
|
||||
fi; \
|
||||
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|
||||
|| eval $$failcom; \
|
||||
done; \
|
||||
if test "$$dot_seen" = "no"; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
|
||||
fi; test -z "$$fail"
|
||||
|
||||
$(RECURSIVE_CLEAN_TARGETS):
|
||||
@failcom='exit 1'; \
|
||||
for f in x $$MAKEFLAGS; do \
|
||||
case $$f in \
|
||||
*=* | --[!k]*);; \
|
||||
*k*) failcom='fail=yes';; \
|
||||
esac; \
|
||||
done; \
|
||||
dot_seen=no; \
|
||||
case "$@" in \
|
||||
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
|
||||
*) list='$(SUBDIRS)' ;; \
|
||||
esac; \
|
||||
rev=''; for subdir in $$list; do \
|
||||
if test "$$subdir" = "."; then :; else \
|
||||
rev="$$subdir $$rev"; \
|
||||
fi; \
|
||||
done; \
|
||||
rev="$$rev ."; \
|
||||
target=`echo $@ | sed s/-recursive//`; \
|
||||
for subdir in $$rev; do \
|
||||
echo "Making $$target in $$subdir"; \
|
||||
if test "$$subdir" = "."; then \
|
||||
local_target="$$target-am"; \
|
||||
else \
|
||||
local_target="$$target"; \
|
||||
fi; \
|
||||
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|
||||
|| eval $$failcom; \
|
||||
done && test -z "$$fail"
|
||||
tags-recursive:
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
|
||||
done
|
||||
ctags-recursive:
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
|
||||
done
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
mkid -fID $$unique
|
||||
tags: TAGS
|
||||
|
||||
TAGS: tags-recursive $(HEADERS) $(SOURCES) auto.h.in $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
|
||||
include_option=--etags-include; \
|
||||
empty_fix=.; \
|
||||
else \
|
||||
include_option=--include; \
|
||||
empty_fix=; \
|
||||
fi; \
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
if test "$$subdir" = .; then :; else \
|
||||
test ! -f $$subdir/TAGS || \
|
||||
tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
|
||||
fi; \
|
||||
done; \
|
||||
list='$(SOURCES) $(HEADERS) auto.h.in $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$tags $$unique; \
|
||||
fi
|
||||
ctags: CTAGS
|
||||
CTAGS: ctags-recursive $(HEADERS) $(SOURCES) auto.h.in $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
list='$(SOURCES) $(HEADERS) auto.h.in $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$tags $$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& cd $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) $$here
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
$(am__remove_distdir)
|
||||
test -d $(distdir) || mkdir $(distdir)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
|
||||
fi; \
|
||||
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
|
||||
if test "$$subdir" = .; then :; else \
|
||||
test -d "$(distdir)/$$subdir" \
|
||||
|| $(MKDIR_P) "$(distdir)/$$subdir" \
|
||||
|| exit 1; \
|
||||
distdir=`$(am__cd) $(distdir) && pwd`; \
|
||||
top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
|
||||
(cd $$subdir && \
|
||||
$(MAKE) $(AM_MAKEFLAGS) \
|
||||
top_distdir="$$top_distdir" \
|
||||
distdir="$$distdir/$$subdir" \
|
||||
am__remove_distdir=: \
|
||||
am__skip_length_check=: \
|
||||
distdir) \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
-find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
|
||||
! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
|
||||
! -type d ! -perm -400 -exec chmod a+r {} \; -o \
|
||||
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|
||||
|| chmod -R a+r $(distdir)
|
||||
dist-gzip: distdir
|
||||
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
|
||||
$(am__remove_distdir)
|
||||
|
||||
dist-bzip2: distdir
|
||||
tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
|
||||
$(am__remove_distdir)
|
||||
|
||||
dist-lzma: distdir
|
||||
tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma
|
||||
$(am__remove_distdir)
|
||||
|
||||
dist-tarZ: distdir
|
||||
tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
|
||||
$(am__remove_distdir)
|
||||
|
||||
dist-shar: distdir
|
||||
shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
|
||||
$(am__remove_distdir)
|
||||
|
||||
dist-zip: distdir
|
||||
-rm -f $(distdir).zip
|
||||
zip -rq $(distdir).zip $(distdir)
|
||||
$(am__remove_distdir)
|
||||
|
||||
dist dist-all: distdir
|
||||
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
|
||||
$(am__remove_distdir)
|
||||
|
||||
# This target untars the dist file and tries a VPATH configuration. Then
|
||||
# it guarantees that the distribution is self-contained by making another
|
||||
# tarfile.
|
||||
distcheck: dist
|
||||
case '$(DIST_ARCHIVES)' in \
|
||||
*.tar.gz*) \
|
||||
GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
|
||||
*.tar.bz2*) \
|
||||
bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
|
||||
*.tar.lzma*) \
|
||||
unlzma -c $(distdir).tar.lzma | $(am__untar) ;;\
|
||||
*.tar.Z*) \
|
||||
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
|
||||
*.shar.gz*) \
|
||||
GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
|
||||
*.zip*) \
|
||||
unzip $(distdir).zip ;;\
|
||||
esac
|
||||
chmod -R a-w $(distdir); chmod a+w $(distdir)
|
||||
mkdir $(distdir)/_build
|
||||
mkdir $(distdir)/_inst
|
||||
chmod a-w $(distdir)
|
||||
dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
|
||||
&& dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
|
||||
&& cd $(distdir)/_build \
|
||||
&& ../configure --srcdir=.. --prefix="$$dc_install_base" \
|
||||
$(DISTCHECK_CONFIGURE_FLAGS) \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) check \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) install \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) uninstall \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
|
||||
distuninstallcheck \
|
||||
&& chmod -R a-w "$$dc_install_base" \
|
||||
&& ({ \
|
||||
(cd ../.. && umask 077 && mkdir "$$dc_destdir") \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
|
||||
distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
|
||||
} || { rm -rf "$$dc_destdir"; exit 1; }) \
|
||||
&& rm -rf "$$dc_destdir" \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) dist \
|
||||
&& rm -rf $(DIST_ARCHIVES) \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) distcleancheck
|
||||
$(am__remove_distdir)
|
||||
@(echo "$(distdir) archives ready for distribution: "; \
|
||||
list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
|
||||
sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
|
||||
distuninstallcheck:
|
||||
@cd $(distuninstallcheck_dir) \
|
||||
&& test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
|
||||
|| { echo "ERROR: files left after uninstall:" ; \
|
||||
if test -n "$(DESTDIR)"; then \
|
||||
echo " (check DESTDIR support)"; \
|
||||
fi ; \
|
||||
$(distuninstallcheck_listfiles) ; \
|
||||
exit 1; } >&2
|
||||
distcleancheck: distclean
|
||||
@if test '$(srcdir)' = . ; then \
|
||||
echo "ERROR: distcleancheck can only run from a VPATH build" ; \
|
||||
exit 1 ; \
|
||||
fi
|
||||
@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
|
||||
|| { echo "ERROR: files left in build directory after distclean:" ; \
|
||||
$(distcleancheck_listfiles) ; \
|
||||
exit 1; } >&2
|
||||
check-am: all-am
|
||||
check: check-recursive
|
||||
all-am: Makefile $(MANS) $(DATA) auto.h
|
||||
installdirs: installdirs-recursive
|
||||
installdirs-am:
|
||||
for dir in "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(otherdir)"; do \
|
||||
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||
done
|
||||
install: install-recursive
|
||||
install-exec: install-exec-recursive
|
||||
install-data: install-data-recursive
|
||||
uninstall: uninstall-recursive
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-recursive
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
`test -z '$(STRIP)' || \
|
||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-recursive
|
||||
|
||||
clean-am: clean-generic mostlyclean-am
|
||||
|
||||
distclean: distclean-recursive
|
||||
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-generic distclean-hdr distclean-tags
|
||||
|
||||
dvi: dvi-recursive
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-recursive
|
||||
|
||||
info: info-recursive
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am: install-man install-otherDATA
|
||||
|
||||
install-dvi: install-dvi-recursive
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-html: install-html-recursive
|
||||
|
||||
install-info: install-info-recursive
|
||||
|
||||
install-man: install-man1 install-man5
|
||||
|
||||
install-pdf: install-pdf-recursive
|
||||
|
||||
install-ps: install-ps-recursive
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-recursive
|
||||
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
|
||||
-rm -rf $(top_srcdir)/autom4te.cache
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-recursive
|
||||
|
||||
mostlyclean-am: mostlyclean-generic
|
||||
|
||||
pdf: pdf-recursive
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-recursive
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-man uninstall-otherDATA
|
||||
|
||||
uninstall-man: uninstall-man1 uninstall-man5
|
||||
|
||||
.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \
|
||||
install-strip
|
||||
|
||||
.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
|
||||
all all-am am--refresh check check-am clean clean-generic \
|
||||
ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \
|
||||
dist-lzma dist-shar dist-tarZ dist-zip distcheck distclean \
|
||||
distclean-generic distclean-hdr distclean-tags distcleancheck \
|
||||
distdir distuninstallcheck dvi dvi-am html html-am info \
|
||||
info-am install install-am install-data install-data-am \
|
||||
install-dvi install-dvi-am install-exec install-exec-am \
|
||||
install-html install-html-am install-info install-info-am \
|
||||
install-man install-man1 install-man5 install-otherDATA \
|
||||
install-pdf install-pdf-am install-ps install-ps-am \
|
||||
install-strip installcheck installcheck-am installdirs \
|
||||
installdirs-am maintainer-clean maintainer-clean-generic \
|
||||
mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \
|
||||
tags-recursive uninstall uninstall-am uninstall-man \
|
||||
uninstall-man1 uninstall-man5 uninstall-otherDATA
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
13
NEWS
13
NEWS
@@ -1,4 +1,4 @@
|
||||
Welcome to Task 1.5.0.
|
||||
Welcome to Task 1.7.0.
|
||||
|
||||
Task has been built and tested on the following configurations:
|
||||
|
||||
@@ -6,8 +6,13 @@ Task has been built and tested on the following configurations:
|
||||
- OS X 10.5 Leopard
|
||||
- Fedora Core 8
|
||||
- Fedora Core 9
|
||||
- Fedora Core 10
|
||||
- Ubuntu 7 Feisty Fawn
|
||||
- Ubuntu 8 Hardy Heron
|
||||
- Ubuntu 9 Feisty Fawn
|
||||
- Ubuntu 8.10 Intrepid Ibex
|
||||
- Ubuntu 9.04 Jaunty Jackalope
|
||||
- Arch Linux
|
||||
- Solaris 8
|
||||
- Solaris 10
|
||||
- Cygwin 1.5.25-14
|
||||
|
||||
@@ -28,5 +33,9 @@ order of increasing effort (to you) and usefulness (to me):
|
||||
will be applied and tested, and a new release will be made. You will be a
|
||||
hero.
|
||||
|
||||
- Another option involves using Github's issue tracker, which can be found
|
||||
at http://github.com/pbeckingham/task/issues which has the advantage that
|
||||
everyone gets to see and track the issue. You will still be a hero.
|
||||
|
||||
Thank you.
|
||||
|
||||
|
||||
8
README
8
README
@@ -14,7 +14,7 @@ Thank you for taking a look at task. Task is a GTD utility featuring:
|
||||
It is intended that features, mainly in the form of reports will be added
|
||||
frequently, with best practices and useful reports evolving from usage patterns.
|
||||
|
||||
Task is scope-limited to GTD functionality only.
|
||||
Task is scope-limited to GTD-like functionality only.
|
||||
|
||||
You may want to watch the old task movie on YouTube:
|
||||
|
||||
@@ -44,7 +44,11 @@ All feedback is welcome, in addition to any bug reports or patches to:
|
||||
|
||||
task@beckingham.net
|
||||
|
||||
Got an idea for an enhancement? Send a message!
|
||||
Or better yet, get involved in the discussion at
|
||||
|
||||
http://groups.google.com/group/taskprogram
|
||||
|
||||
Got an idea for an enhancement? Post a message!
|
||||
|
||||
I have found that task makes me more productive and organized.
|
||||
I hope task can do the same for you.
|
||||
|
||||
44
checklist.txt
Normal file
44
checklist.txt
Normal file
@@ -0,0 +1,44 @@
|
||||
Adding New Command Checklist
|
||||
----------------------------
|
||||
|
||||
- Create new handler in command.cpp or report.cpp.
|
||||
- Add prototype to task.h.
|
||||
- Add call to appropriate section in task.cpp.
|
||||
- Add usage info in task.cpp.
|
||||
- Add command name to list in parse.cpp.
|
||||
- Add unit tests in src/tests.
|
||||
- Add new configuration details to html/config.html.
|
||||
- Add command details to html/advanced.html.
|
||||
- Add description to ChangeLog, with attribution if the idea
|
||||
came from a single user, but not if it came from multiple
|
||||
users.
|
||||
- Add description to html/task.html.
|
||||
|
||||
|
||||
|
||||
Release Checklist
|
||||
-----------------
|
||||
|
||||
- Update "Upcoming Features" document on group
|
||||
- Ensure all unit tests pass on OS X
|
||||
- Ensure clean build on OS X
|
||||
- Make a source package (1)
|
||||
- Ensure clean build on latest Fedora Core from source package
|
||||
- Git clone and rebuild, ensure all unit tests pass
|
||||
- Ensure clean build on latest Ubuntu from source package
|
||||
- Git clone and rebuild, ensure all unit tests pass
|
||||
- Ensure clean build on Windows/Cygwin from source package
|
||||
- Git clone and rebuild, ensure all unit tests pass
|
||||
- Make a new source package (2)
|
||||
- Add actual release date to ChangeLog
|
||||
- Add actual release date to html/task.html
|
||||
- Merge version branch to master
|
||||
- Tag master
|
||||
- Make a new source package (3)
|
||||
- Send source package to package maintainer
|
||||
- Make OS X .pkg package
|
||||
- Wait for all packages
|
||||
- Upload all packages to website
|
||||
- Upload all docs to website
|
||||
- Send announcement to group
|
||||
|
||||
28
configure.ac
28
configure.ac
@@ -2,8 +2,7 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ(2.61)
|
||||
AC_INIT(task, 1.5.0, bugs@beckingham.net)
|
||||
|
||||
AC_INIT(task, 1.7.0, bugs@beckingham.net)
|
||||
|
||||
CFLAGS="${CFLAGS=}"
|
||||
CXXFLAGS="${CXXFLAGS=}"
|
||||
@@ -15,16 +14,23 @@ debug_default="yes"
|
||||
AC_ARG_ENABLE(debug, [ --enable-debug=[no/yes] turn on debugging
|
||||
[default=$debug_default]],, enable_debug=$debug_default)
|
||||
# Yes, shell scripts can be used
|
||||
if test "x$enable_debug" = "xyes"; then
|
||||
CFLAGS="$CFLAGS -Wall -pedantic -ggdb3 -DDEBUG"
|
||||
CXXFLAGS="$CFLAGS -Wall -pedantic -ggdb3 -DDEBUG"
|
||||
AC_MSG_RESULT(yes)
|
||||
if test "$enable_debug" = "yes"; then
|
||||
CXXFLAGS="$CFLAGS -Wall -pedantic -ggdb3 -DDEBUG"
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
CFLAGS="$CFLAGS -O3"
|
||||
CXXFLAGS="$CFLAGS -O3"
|
||||
AC_MSG_RESULT(no)
|
||||
CXXFLAGS="$CFLAGS -Wall -pedantic -O3"
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
# Check for OS.
|
||||
OS=`uname|sed -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'`
|
||||
if test "$OS" = "sunos"; then
|
||||
AC_MSG_NOTICE([OS Solaris detected])
|
||||
AC_DEFINE([SOLARIS], [], [Compiling on Solaris])
|
||||
else
|
||||
AC_MSG_NOTICE([OS Non-Solaris detected])
|
||||
AC_DEFINE([LINUX], [], [Compiling on Non-Solaris])
|
||||
fi
|
||||
|
||||
AM_INIT_AUTOMAKE
|
||||
AC_CONFIG_SRCDIR([src/task.cpp])
|
||||
@@ -39,7 +45,6 @@ AC_SUBST(CFLAGS)
|
||||
|
||||
# Checks for libraries.
|
||||
AC_CHECK_LIB(ncurses,initscr)
|
||||
AC_CHECK_LIB(ncurses,endwin)
|
||||
|
||||
# Checks for header files.
|
||||
AC_HEADER_STDC
|
||||
@@ -58,10 +63,11 @@ AC_STRUCT_TM
|
||||
AC_FUNC_MKTIME
|
||||
AC_FUNC_SELECT_ARGTYPES
|
||||
AC_CHECK_FUNCS([select])
|
||||
AC_CHECK_FUNC(flock, [AC_DEFINE([HAVE_FLOCK], [1], [Found flock])])
|
||||
#AC_CHECK_FUNC(flock, [AC_DEFINE([HAVE_FLOCK], [1], [Found flock])])
|
||||
AC_CHECK_FUNC(uuid_unparse_lower, [AC_DEFINE([HAVE_UUID], [1], [Found uuid_unparse_lower])])
|
||||
AC_CHECK_FUNC(random, [AC_DEFINE([HAVE_RANDOM], [1], [Found random])])
|
||||
AC_CHECK_FUNC(srandom, [AC_DEFINE([HAVE_SRANDOM], [1], [Found srandom])])
|
||||
|
||||
AC_CONFIG_FILES([Makefile src/Makefile])
|
||||
AC_OUTPUT
|
||||
|
||||
|
||||
382
doc/man1/task.1
Normal file
382
doc/man1/task.1
Normal file
@@ -0,0 +1,382 @@
|
||||
.TH task 1 2009-05-14 "Task 1.7.0" "User Manuals"
|
||||
|
||||
.SH NAME
|
||||
task \- A command line todo manager.
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B task [subcommand] [args]
|
||||
|
||||
.SH DESCRIPTION
|
||||
Task is a command line TODO list manager. It maintains a list of tasks that you
|
||||
want to do, allowing you to add/remove, and otherwise manipulate them. Task
|
||||
has a rich list of subcommands that allow you to do various things with it.
|
||||
|
||||
.SH SUBCOMMANDS
|
||||
|
||||
.TP
|
||||
.B add [tags] [attrs] description
|
||||
Adds a new task to the task list.
|
||||
|
||||
.TP
|
||||
.B append [tags] [attrs] description
|
||||
Appends more information to an existing
|
||||
task.
|
||||
|
||||
.TP
|
||||
.B annotate ID description
|
||||
Adds an annotation to an existing task.
|
||||
|
||||
.TP
|
||||
.B completed [tags] [attrs] description
|
||||
Provides a chronological listing of all completed tasks matching specified
|
||||
criteria.
|
||||
|
||||
.TP
|
||||
.B ID [tags] [attrs] [description]
|
||||
Modifies the existing task with provided information.
|
||||
|
||||
.TP
|
||||
.B ID /from/to/
|
||||
Performs one substitution on task description for fixing mistakes.
|
||||
|
||||
.TP
|
||||
.B ID /from/to/g
|
||||
Performs all substitutions on task description for fixing mistakes.
|
||||
|
||||
.TP
|
||||
.B duplicate ID [tags] [attrs] [description]
|
||||
Duplicates the specified task and allows modifications.
|
||||
|
||||
.TP
|
||||
.B delete ID
|
||||
Deletes the specified task from task list.
|
||||
|
||||
.TP
|
||||
.B undelete ID
|
||||
Undeletes the specified task, provided a report has not yet been run.
|
||||
|
||||
.TP
|
||||
.B info ID
|
||||
Shows all data and metadata for the specified task.
|
||||
|
||||
.TP
|
||||
.B start ID
|
||||
Marks the specified task as started.
|
||||
|
||||
.TP
|
||||
.B stop ID
|
||||
Removes the
|
||||
.I start
|
||||
time from the specified task.
|
||||
|
||||
.TP
|
||||
.B done ID [tags] [attrs] [description]
|
||||
Marks the specified task as done.
|
||||
|
||||
.TP
|
||||
.B undo ID
|
||||
Marks the specified task as pending, provided a report has not yet been run.
|
||||
|
||||
.TP
|
||||
.B projects
|
||||
Lists all project names used, and the number of tasks for each.
|
||||
|
||||
.TP
|
||||
.B tags
|
||||
Show a list of all tags used.
|
||||
|
||||
.TP
|
||||
.B summary
|
||||
Shows a report of task status by project.
|
||||
|
||||
.TP
|
||||
.B timesheet [weeks]
|
||||
Shows a weekly report of tasks completed and started.
|
||||
|
||||
.TP
|
||||
.B history
|
||||
Shows a report of task history by month.
|
||||
|
||||
.TP
|
||||
.B ghistory
|
||||
Shows a graphical report of task status by month.
|
||||
|
||||
.TP
|
||||
.B next
|
||||
Shows the most important pending tasks for each project.
|
||||
|
||||
.TP
|
||||
.B calendar
|
||||
Shows a monthly calendar with due tasks marked.
|
||||
|
||||
.TP
|
||||
.B active
|
||||
Shows all tasks that are started but not comleted.
|
||||
|
||||
.TP
|
||||
.B overdue
|
||||
Shows all incomplete tasks that are beyond their due date.
|
||||
|
||||
.TP
|
||||
.B stats
|
||||
Shows task database statistics.
|
||||
|
||||
.TP
|
||||
.B import \fIfile
|
||||
Imports tasks from a variety of formats.
|
||||
|
||||
.TP
|
||||
.B export \fIfile
|
||||
Exports all tasks as a CSV file.
|
||||
|
||||
.TP
|
||||
.B color
|
||||
Displays all possible colors.
|
||||
|
||||
.TP
|
||||
.B version
|
||||
Shows the task version number and current settings in the task configuration
|
||||
file.
|
||||
|
||||
.TP
|
||||
.B help
|
||||
Shows the long usage text.
|
||||
|
||||
.SH REPORT SUBCOMMANDS
|
||||
|
||||
A report is a listing of information from the task database. There are several
|
||||
built-in reports currently in task. The output and sort behaviour of these
|
||||
subcommands can be configured in the configuration file.
|
||||
|
||||
.TP
|
||||
.B ls [tags] [attrs] [description]
|
||||
Provides a minimal listing of tasks with specified criteria.
|
||||
|
||||
.TP
|
||||
.B list [tags] [attrs] [description]
|
||||
Provides a more detailed listing of tasks with specified criteria.
|
||||
|
||||
.TP
|
||||
.B long [tags] [attrs] [description]
|
||||
Provides the most detailed listing of tasks with specified criteria.
|
||||
|
||||
.TP
|
||||
.B newest [tags] [attrs] [description] | newest [limit]
|
||||
Shows the newest tasks with specified criteria.
|
||||
|
||||
.TP
|
||||
.B oldest [tags] [attrs] [description] | oldest [limit]
|
||||
Shows the oldest tasks with specified criteria
|
||||
|
||||
.SH ATTRIBUTES AND METADATA
|
||||
|
||||
.TP
|
||||
.B ID
|
||||
Tasks can be specified uniquely by IDs, which are simply the index of the
|
||||
task in a report. Be careful, as the IDs of tasks may change after a
|
||||
modification to the database. Always run a report to check you have the right
|
||||
ID for a task. IDs can be given to task as a sequence, for example,
|
||||
.br
|
||||
.B
|
||||
task del 1 2 5-10,12
|
||||
|
||||
.TP
|
||||
.B +tag|-tag
|
||||
Tags are arbitrary words associated with a task. Use + to add a tag and - to
|
||||
remove a tag from a task.
|
||||
|
||||
.TP
|
||||
.B project:<project-name>
|
||||
Specify the project to which a task is related to.
|
||||
|
||||
.TP
|
||||
.B priority:H|M|L|N
|
||||
Specify High, Medium, Low and No priority for a task.
|
||||
|
||||
.TP
|
||||
.B due:<due-date>
|
||||
Specify the due-date of a task.
|
||||
|
||||
.TP
|
||||
.B until:<end-date-of-recurrence>
|
||||
Specify the Recurrence end-date of a task.
|
||||
|
||||
.TP
|
||||
.B recur:<frequency>
|
||||
Specify the frequency of recurrence of a task.
|
||||
|
||||
.TP
|
||||
.B fg:<color-spec>
|
||||
Specify foreground color.
|
||||
|
||||
.TP
|
||||
.B bg:<color-spec>
|
||||
Specify background color.
|
||||
|
||||
.TP
|
||||
.B rc:<path>
|
||||
Specify alternate configuration file.
|
||||
|
||||
.SH SPECIFYING DATES AND FREQUENCIES
|
||||
|
||||
.SS DATES
|
||||
Task reads dates from the commandline and displays dates in the
|
||||
reports. The expected and desired date format is determined by the
|
||||
configuration variable
|
||||
.I dateformat
|
||||
in the task configuration file.
|
||||
|
||||
.RS
|
||||
.TP
|
||||
Exact specification
|
||||
task ... due:7/14/2008
|
||||
|
||||
.TP
|
||||
Relative wording
|
||||
task ... due:today
|
||||
.br
|
||||
task ... due:yesterday
|
||||
.br
|
||||
task ... due:tomorrow
|
||||
|
||||
.TP
|
||||
Day number with ordinal
|
||||
task ... due:23rd
|
||||
|
||||
.TP
|
||||
End of week (Friday), month and year
|
||||
task ... due:eow
|
||||
.br
|
||||
task ... due:eom
|
||||
.br
|
||||
task ... due:eoy
|
||||
|
||||
.TP
|
||||
Next occuring weekday
|
||||
task ... due:fri
|
||||
.RE
|
||||
|
||||
.SS FREQUENCIES
|
||||
Recurrence periods. Task supports several ways of specifying the
|
||||
.I frequency
|
||||
of recurring tasks.
|
||||
|
||||
.RS
|
||||
.TP
|
||||
daily, day, 1d, 2d, ...
|
||||
Every day or a number of days.
|
||||
|
||||
.TP
|
||||
weekdays
|
||||
Mondays, Tuesdays, Wednesdays, Thursdays, Fridays and skipping weekend days.
|
||||
|
||||
.TP
|
||||
weekly, 1w, 2w, ...
|
||||
Eery week or a number of weeks.
|
||||
|
||||
.TP
|
||||
biweekly, fortnight
|
||||
Every two weeks.
|
||||
|
||||
.TP
|
||||
quaterly, 1q, 2q, ...
|
||||
Every three months, a quarter, or a number of quaters.
|
||||
|
||||
.TP
|
||||
semiannual
|
||||
Every six months.
|
||||
|
||||
.TP
|
||||
annual, yearly, 1y, 2y, ...
|
||||
Every year or a number of years.
|
||||
|
||||
.TP
|
||||
biannual, biyearly, 2y
|
||||
Every two years.
|
||||
.RE
|
||||
|
||||
|
||||
.SH COMMAND ABBREVIATION
|
||||
All task commands may be abbreviated as long as a unique prefix is used. E.g.
|
||||
|
||||
.RS
|
||||
$ task li
|
||||
.RE
|
||||
|
||||
is an unambiguous abbreviation for
|
||||
|
||||
.RS
|
||||
$ task list
|
||||
.RE
|
||||
|
||||
but
|
||||
|
||||
.RS
|
||||
$ task l
|
||||
.RE
|
||||
|
||||
could be list, ls or long.
|
||||
|
||||
.SH EXAMPLES
|
||||
|
||||
A small section for examples e.g. some stuff from
|
||||
.br
|
||||
http://www.beckingham.net/30second.html
|
||||
.br
|
||||
http://www.beckingham.net/simple.html
|
||||
|
||||
.SH FILES
|
||||
|
||||
.TP
|
||||
~/.taskrc User configuration file.
|
||||
|
||||
.TP
|
||||
~/.task The default directory where task stores its data files. The location
|
||||
can be configured in the configuration file.
|
||||
|
||||
.TP
|
||||
~/.task/pending.data The file that contains the tasks that are not yet done.
|
||||
|
||||
.TP
|
||||
~/.task/completed.data The file that contains the completed "done" tasks.
|
||||
|
||||
.SH "CREDITS & COPYRIGHTS"
|
||||
task was written by P. Beckingham <task@beckingham.net>.
|
||||
.br
|
||||
Copyright (C) 2006 \- 2009 P. Beckingham
|
||||
|
||||
This manpage was originally written by P.C. Shyamshankar, and has been modified
|
||||
and supplemented by Federico Hernandez.
|
||||
|
||||
task is distributed under the GNU General Public License. See
|
||||
http://www.gnu.org/licenses/gpl-2.0.txt for more information.
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR taskrc (5)
|
||||
|
||||
For more information regarding task, the following may be referenced:
|
||||
|
||||
.TP
|
||||
<http://www.beckingham.net/task.html>
|
||||
The official site.
|
||||
|
||||
.TP
|
||||
<http://groups.google.com/group/taskprogram>
|
||||
The official mailing list.
|
||||
|
||||
.TP
|
||||
<http://github.com/pbeckingham/task/>
|
||||
The official code repository.
|
||||
|
||||
.SH REPORTING BUGS
|
||||
Bugs in task may be reported to the issue-tracker at
|
||||
|
||||
.RS
|
||||
<http://github.com/pbeckingham/task/issues>
|
||||
.RE
|
||||
|
||||
or to the mailing list at
|
||||
|
||||
.RS
|
||||
<http://groups.google.com/group/taskprogram>
|
||||
.RE
|
||||
411
doc/man5/taskrc.5
Normal file
411
doc/man5/taskrc.5
Normal file
@@ -0,0 +1,411 @@
|
||||
.TH taskrc 5 2009-05-14 "Task 1.7.0" "User Manuals"
|
||||
|
||||
.SH NAME
|
||||
taskrc \- Configuration file for the task(1) command
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B $HOME/.taskrc
|
||||
.B task rc:<directory-path>/.taskrc
|
||||
|
||||
.SH DESCRIPTION
|
||||
.B task
|
||||
obtains its configuration data from a file called
|
||||
.I .taskrc
|
||||
\&. This file is normally located in the user's home directory:
|
||||
|
||||
.RS
|
||||
$HOME/.taskrc
|
||||
.RE
|
||||
|
||||
The default location can be overriden using the
|
||||
.I rc:
|
||||
attribute when running task:
|
||||
|
||||
.RS
|
||||
$ task rc:<directory-path>/.taskrc
|
||||
.RE
|
||||
|
||||
If
|
||||
.B task
|
||||
is run without an existing configuration file it will ask if it should create a default, sample
|
||||
.I .taskrc
|
||||
file in the user's home directory.
|
||||
|
||||
The task configuration file consists of a series of "assignments" in each line. The "assignments" have the syntax:
|
||||
|
||||
.RS
|
||||
<name-of-configuration-variable>=<value-to-be-set>
|
||||
.RE
|
||||
|
||||
where:
|
||||
.RS
|
||||
.TP
|
||||
<name-of-configuration-variable>
|
||||
is one of the variables described below
|
||||
|
||||
.TP
|
||||
<value-to-be-set>
|
||||
is the value the variable is to be set to.
|
||||
.RE
|
||||
|
||||
and set a configuration variable to a certain value. The equal sign ("=") is used to separate the variable
|
||||
name from the value to be set.
|
||||
|
||||
The hash mark, or pounf sign ("#") is used as a "comment" character. It can be used to annotte the
|
||||
configuration file. It is placed at the beginning of a line and all text after the character to the
|
||||
end of the line is ignored.
|
||||
|
||||
.SH CONFIGURATION VARIABLES
|
||||
Valid variable names and their default values are:
|
||||
|
||||
.TP
|
||||
.B data.location=$HOME/.task
|
||||
This is a path to the directory containing all the task files. By default, it is set up to be ~/.task,
|
||||
for example: /Users/paul/.task
|
||||
|
||||
.TP
|
||||
.B confirmation=yes
|
||||
May be "yes" or "no", and determines whether task will ask for confirmation before deleting a task.
|
||||
|
||||
.TP
|
||||
.B echo.command=yes
|
||||
May be "yes" or "no", and causes task to display the ID and description of any task when you run the start, stop, do, undo, delete and undelete commands. The default value is "yes".
|
||||
|
||||
.TP
|
||||
.B next=2
|
||||
Is a number, defaulting to 2, which is the number of tasks for each project that are shown in the
|
||||
.B task next
|
||||
command.
|
||||
|
||||
.TP
|
||||
.B dateformat=m/d/Y
|
||||
This is a string of characters that define how task formats dates. The default value is: m/d/Y.
|
||||
The string should contain the characters
|
||||
|
||||
.RS
|
||||
m minimal-digit month, for example 1 or 12
|
||||
.br
|
||||
d minimal-digit day, for example 1 or 30
|
||||
.br
|
||||
y two-digit year, for example 09
|
||||
.br
|
||||
D two-digit day, for example 01 or 30
|
||||
.br
|
||||
M two-digit month, for example 01 or 12
|
||||
.br
|
||||
Y four-digit year, for example 2009
|
||||
.RE
|
||||
|
||||
The string may also contain other characters to act as spacers, or formatting. Examples for other
|
||||
variable values:
|
||||
|
||||
.RS
|
||||
.br
|
||||
d/m/Y would output 24/7/2009
|
||||
.br
|
||||
YMD would output 20090724
|
||||
.br
|
||||
m-d-y would output 07-24-09
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B monthsperline=99
|
||||
Determines how many months the "task calendar" command renders across the screen.
|
||||
Defaults to however many will fit. If more months that will fit are specified,
|
||||
task will only show as many that will fit.
|
||||
|
||||
.TP
|
||||
.B defaultwidth=80
|
||||
The width of tables used when ncurses support is not available. Defaults to 80.
|
||||
|
||||
.TP
|
||||
.B curses=on
|
||||
Determines whether task uses ncurses to establish the size of the window you are
|
||||
using, for text wrapping.
|
||||
|
||||
.TP
|
||||
.B due=7
|
||||
This is the number of days into the future that define when a task is considered due,
|
||||
and is colored accordingly. Defaults to 7.
|
||||
|
||||
.TP
|
||||
.B nag=You have higher priority tasks.
|
||||
This may be a string of text, or blank. It is used as a prompt when a task is completed
|
||||
that is not considered high priority. The "task next" command lists important tasks, and
|
||||
completing one of those does not generate this nagging. Default value is: You have higher
|
||||
priority tasks.
|
||||
|
||||
.TP
|
||||
.B locking=on
|
||||
Determines whether task uses file locking when accessing the pending.data and completed.data files.
|
||||
Default to "on". Solaris users who store the task data files on an NFS mount may need to set locking
|
||||
to "off". Note that setting this value to "off" is dangerous. It means that another program may write
|
||||
to the task.pending file when task is attempting to do the same.
|
||||
|
||||
.TP
|
||||
.B editor=vi
|
||||
Specifies which text editor you wish to use for when the
|
||||
.B task edit <ID>
|
||||
command is used. Task will first look for this configuration variable. If found, it is used.
|
||||
Otherwise task will look for the $VISUAL or $EDITOR environment variables, before it defaults
|
||||
to using "vi".
|
||||
|
||||
.TP
|
||||
.B color=on
|
||||
May be "on" or "off". Determines whether task uses color. When "off", task will
|
||||
use dashes (-----) to underline column headings.
|
||||
|
||||
Task has a number of coloration rules. They correspond to a particular attribute
|
||||
of a task, such as it being due, or being active, and specifies the automatic
|
||||
coloring of that task. A list of valid color, depending on your terminal, can be
|
||||
obtained by running the command
|
||||
|
||||
.RS
|
||||
.B task color
|
||||
.RE
|
||||
|
||||
.RS
|
||||
The coloration rules and their defaults are:
|
||||
.RE
|
||||
|
||||
.RS
|
||||
.RS
|
||||
.B color.overdue=bold_red
|
||||
.br
|
||||
.B color.due=bold_yellow
|
||||
.br
|
||||
.B color.pri.H=bold
|
||||
.br
|
||||
.B color.pri.M=on_yellow
|
||||
.br
|
||||
.B color.pri.L=on_green
|
||||
.br
|
||||
.B color.pri.none=white on_blue
|
||||
.br
|
||||
.B color.active=bold_cyan
|
||||
.br
|
||||
.B color.tagged=yellow
|
||||
.br
|
||||
.B color.recurring=on_red
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.RS
|
||||
The value for the coloration rules may be one optional foreground color and one optional
|
||||
color. For example, the value may be
|
||||
.RE
|
||||
|
||||
.RS
|
||||
.RS
|
||||
bold_red on_bright_yellow
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.RS
|
||||
Certain attributes like tags, projects and keywords can also have their own coloration rules.
|
||||
.RE
|
||||
|
||||
.RS
|
||||
.TP
|
||||
.B color.tag.X=yellow
|
||||
Colors any task that has the tag X.
|
||||
|
||||
.TP
|
||||
.B color.project.X=on_green
|
||||
Colors any task assigned to project X.
|
||||
|
||||
.TP
|
||||
.B color.keyword.X=on_blue
|
||||
Colors any task where the description contains X.
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B
|
||||
shadow.file=$HOME/.task/shadow.txt
|
||||
If specified, designates a file path that will be autoamtically written to by task,
|
||||
whenever the task database changes. In other words, it is automatically kept up to date.
|
||||
The shadow.command configuration variable is used to determine which report is written
|
||||
to the shadow file. There is no color used in the shadow file. This feature can be useful
|
||||
in maintaining a current file for use by programs like GeekTool, Conky or Samurize.
|
||||
|
||||
.TP
|
||||
.B
|
||||
shadow.command=list
|
||||
This is the command that is run to maintain the shadow file, determined by the
|
||||
.I shadow.file
|
||||
configuration variable. The format is identical to that of
|
||||
.I default.command
|
||||
\&. Please see the corresponding documentation for that command.
|
||||
|
||||
.TP
|
||||
.B
|
||||
shadow.notify=on
|
||||
When this value is set to "on", task will display a message whenever the shadow
|
||||
file is updated by some task command.
|
||||
|
||||
.TP
|
||||
.B
|
||||
default.project=foo
|
||||
Provides a default project name for the
|
||||
.I task add
|
||||
command.
|
||||
|
||||
.TP
|
||||
.B
|
||||
default.priority=M
|
||||
Provides a default priority for the
|
||||
.I task add
|
||||
command.
|
||||
|
||||
.TP
|
||||
.B
|
||||
default.command=list
|
||||
Provides a default command that is run every time task is invoked with no arguments.
|
||||
For example, if set to:
|
||||
|
||||
.RS
|
||||
.RS
|
||||
default.command=list project:foo
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.RS
|
||||
Then task will run the "list project:foo" command if no command is specified. This means that
|
||||
by merely typing
|
||||
.RE
|
||||
|
||||
.RS
|
||||
.RS
|
||||
$ task
|
||||
.br
|
||||
[task list project:foo]
|
||||
.br
|
||||
\&
|
||||
.br
|
||||
ID Project Pri Description
|
||||
1 foo H Design foo
|
||||
2 foo Build foo
|
||||
.RE
|
||||
.RE
|
||||
|
||||
The built in reports can be customized by using the following configuration variables.
|
||||
The output columns, their labels and the sort order can be set using the corresponding
|
||||
variables for each report.
|
||||
|
||||
.TP
|
||||
.B
|
||||
report.long.description
|
||||
Lists all task, all data, matching the specified criteria
|
||||
|
||||
.TP
|
||||
.B
|
||||
report.long.labels=ID,Project,Pri,Added,Started,Due,Recur,Age,Tags,Description
|
||||
.RE
|
||||
.B
|
||||
report.long.columns=id,project,priority,entry,start,due,recur,age,tags,description
|
||||
.B
|
||||
report.long.sort=due+,priority-,project+
|
||||
|
||||
.TP
|
||||
.B
|
||||
report.list.description
|
||||
Lists all tasks matching the specified criteria
|
||||
|
||||
.TP
|
||||
.B
|
||||
report.list.labels=ID,Project,Pri,Due,Active,Age,Description
|
||||
.RE
|
||||
.B
|
||||
report.list.columns=id,project,priority,due,active,age,description
|
||||
.B
|
||||
report.list.sort=due+,priority-,project+
|
||||
|
||||
|
||||
.TP
|
||||
.B
|
||||
report.ls.description
|
||||
Minimal listing of all tasks matching the specified criteria
|
||||
|
||||
.TP
|
||||
.B
|
||||
report.ls.labels=ID,Project,Pri,Description
|
||||
.RE
|
||||
.B
|
||||
report.ls.columns=id,project,priority,description
|
||||
.B
|
||||
report.ls.sort=priority-,project+
|
||||
|
||||
.TP
|
||||
.B
|
||||
report.newest.description
|
||||
Shows the newest tasks
|
||||
|
||||
.TP
|
||||
.B
|
||||
report.newest.labels=ID,Project,Pri,Due,Active,Age,Description
|
||||
.RE
|
||||
.B
|
||||
report.newest.columns=id,project,priority,due,active,age,description
|
||||
.B
|
||||
report.newest.sort=id-
|
||||
.B
|
||||
report.newest.limit=10
|
||||
|
||||
|
||||
.TP
|
||||
.B
|
||||
report.oldest.description
|
||||
Shows the oldest tasks
|
||||
|
||||
.TP
|
||||
.B
|
||||
report.oldest.labels=ID,Project,Pri,Due,Active,Age,Description
|
||||
.RE
|
||||
.B
|
||||
report.oldest.columns=id,project,priority,due,active,age,description
|
||||
.B
|
||||
report.oldest.sort=id+
|
||||
.B
|
||||
report.oldest.limit=10
|
||||
|
||||
|
||||
.SH "CREDITS & COPYRIGHTS"
|
||||
task was written by P. Beckingham <task@beckingham.net>.
|
||||
.br
|
||||
Copyright (C) 2006 \- 2009 P. Beckingham
|
||||
|
||||
This man page was originally written by Federico Hernandez. It is based on the task man page, which
|
||||
was originally written by P.C. Shyamshankar.
|
||||
|
||||
task is distributed under the GNU General Public License. See
|
||||
http://www.gnu.org/licenses/gpl-2.0.txt for more information.
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR task (1)
|
||||
|
||||
For more information regarding task, the following may be referenced:
|
||||
|
||||
.TP
|
||||
<http://www.beckingham.net/task.html>
|
||||
The official site.
|
||||
|
||||
.TP
|
||||
<http://groups.google.com/group/taskprogram>
|
||||
The official mailing list.
|
||||
|
||||
.TP
|
||||
<http://github.com/pbeckingham/task/>
|
||||
The official code repository.
|
||||
|
||||
.SH REPORTING BUGS
|
||||
Bugs in task may be reported to the issue-tracker at
|
||||
|
||||
.RS
|
||||
<http://github.com/pbeckingham/task/issues>
|
||||
.RE
|
||||
|
||||
or to the mailing list at
|
||||
|
||||
.RS
|
||||
<http://groups.google.com/group/taskprogram>
|
||||
.RE
|
||||
40
grammar.bnf
Normal file
40
grammar.bnf
Normal file
@@ -0,0 +1,40 @@
|
||||
|
||||
# This is a full BNF grammar for the task command line. It is intended that a
|
||||
# future release of task will incorporate a complete lexer/parser implementing
|
||||
# this grammar, which will allow for more sophisticated command lines, for
|
||||
# example:
|
||||
#
|
||||
# task delete 1 2 4-7
|
||||
# task add pri:H pro:X -- pro pri 1 ///
|
||||
#
|
||||
|
||||
command ::= simple_command
|
||||
| filter_command filter?
|
||||
| id_command
|
||||
| "export" file
|
||||
| <id>
|
||||
| <id> <substitution> ;
|
||||
|
||||
simple_command ::= "version" | "help" | "projects" | "tags" | "next" | "stats"
|
||||
| "color" ;
|
||||
|
||||
filter_command ::= "summary" | "history" | "calendar" | "active" | "overdue"
|
||||
| "oldest" | "newest" | "add" | "list" | "long" | "ls"
|
||||
| "completed" ;
|
||||
|
||||
id_command ::= "delete" | "undelete" | "info" | "start" | "end" | "done"
|
||||
| "undo" ;
|
||||
|
||||
filter ::= filter_part+ ;
|
||||
|
||||
filter_part ::= tag_add | tag_remove | attribute | word ;
|
||||
|
||||
tag_add ::= "+" word ;
|
||||
tag_remove ::= "-" word ;
|
||||
attribute ::= word ":" word ;
|
||||
word ::=
|
||||
file ::=
|
||||
id ::= digit+ ;
|
||||
digit ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
|
||||
substitution ::= "/" word+ "/" word* "/" "g"? ;
|
||||
|
||||
69
grammar.txt
69
grammar.txt
@@ -1,69 +0,0 @@
|
||||
|
||||
This is a full BNF grammar for the task command line. It is intended that a
|
||||
future release of task will incorporate a complete lexer/parser implementing
|
||||
this grammar.
|
||||
|
||||
|
||||
command:
|
||||
VERSION
|
||||
| HELP
|
||||
| PROJECTS
|
||||
| TAGS
|
||||
| SUMMARY
|
||||
| HISTORY
|
||||
| NEXT
|
||||
| CALENDAR
|
||||
| ACTIVE
|
||||
| OVERDUE
|
||||
| STATS
|
||||
| USAGE
|
||||
| OLDEST
|
||||
| NEWEST
|
||||
| EXPORT <file>
|
||||
| COLOR
|
||||
| DELETE <id>
|
||||
| UNDELETE <id>
|
||||
| INFO <id>
|
||||
| START <id>
|
||||
| DONE <id>
|
||||
| ADD [<tags>] [<attrs>] [<desc>]
|
||||
| LIST [<tags>] [<attrs>] [<desc>]
|
||||
| LONG [<tags>] [<attrs>] [<desc>]
|
||||
| LS [<tags>] [<attrs>] [<desc>]
|
||||
| COMPLETED [<tags>] [<attrs>] [<desc>]
|
||||
| <id> [<tags>] [<attrs>] [<desc>]
|
||||
| <id> <substitution>
|
||||
|
||||
id:
|
||||
\d+
|
||||
| \d{8}-\d{4}-\d{4}-\d{12}
|
||||
|
||||
tags:
|
||||
+<tag>
|
||||
| -<tag>
|
||||
|
||||
tag:
|
||||
\w+
|
||||
|
||||
attrs:
|
||||
<attr>
|
||||
| <attr> <attrs>
|
||||
|
||||
attr:
|
||||
<name>:<value>
|
||||
|
||||
name:
|
||||
\w+
|
||||
|
||||
value:
|
||||
.+
|
||||
|
||||
substitution:
|
||||
/ <pattern> / <pattern> /
|
||||
|
||||
pattern:
|
||||
.+
|
||||
|
||||
file:
|
||||
?
|
||||
|
||||
@@ -20,10 +20,9 @@
|
||||
<a href="shell.html">Shell</a>
|
||||
<a href="config.html">Configuration</a>
|
||||
<a href="color.html">Colors</a>
|
||||
<a href="usage.html">Usage</a>
|
||||
<a href="recur.html">Recurrence</a>
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="troubleshooting.html">Troubleshooting</a>
|
||||
<a href="faq.html">FAQ</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
@@ -80,7 +79,7 @@ No matches</code></pre>
|
||||
<br />
|
||||
<div class="content">
|
||||
<p>
|
||||
Copyright 2006-2008, P. Beckingham. All rights reserved.
|
||||
Copyright 2006-2009, P. Beckingham. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -20,10 +20,9 @@
|
||||
<a href="shell.html">Shell</a>
|
||||
<a href="config.html">Configuration</a>
|
||||
<a href="color.html">Colors</a>
|
||||
<a href="usage.html">Usage</a>
|
||||
<a href="recur.html">Recurrence</a>
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="troubleshooting.html">Troubleshooting</a>
|
||||
<a href="faq.html">FAQ</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
@@ -97,6 +96,37 @@ Car 2 2 wks 25% XXXXXXXXX</code></pre>
|
||||
indicating that percentage.
|
||||
</p>
|
||||
|
||||
<strong>% task <id> append ...</strong>
|
||||
<p>
|
||||
Appends the additional description to an existing task.
|
||||
</p>
|
||||
|
||||
<strong>% task annotate <id> additional note...</strong>
|
||||
<p>
|
||||
Allows an annotation to be attached to an existing task. Each
|
||||
annotation has a time stamp, and when displayed, the annotations
|
||||
are shown under the task description. For example:
|
||||
</p>
|
||||
|
||||
<pre><code>% task add Go to the supermarket
|
||||
% task annotate 1 need milk
|
||||
% task ls
|
||||
|
||||
ID Project Pri Due Active Age Description
|
||||
1 Go to the supermarket
|
||||
3/23/2009 need milk</code></pre>
|
||||
<p>
|
||||
The date of the annotation uses the "dateformat" configuration
|
||||
variable.
|
||||
</p>
|
||||
|
||||
<strong>% task duplicate 1 /foo/bar/g +tag priority:H</strong>
|
||||
<p>
|
||||
This duplicates task 1, then applies the modifications specified,
|
||||
which change all "foo" to "bar" in the description and annotations,
|
||||
adds the tag "tag", and sets the priority to "H".
|
||||
</p>
|
||||
|
||||
<strong>% task delete <id></strong>
|
||||
<p>
|
||||
There are two ways of getting rid of tasks - mark them as done, or
|
||||
@@ -120,6 +150,13 @@ Car 2 2 wks 25% XXXXXXXXX</code></pre>
|
||||
This is how a task is marked as done.
|
||||
</p>
|
||||
|
||||
<strong>% task undo <id></strong>
|
||||
<p>
|
||||
If a task was recently marked as done, and no report has been run, it
|
||||
may be possible to cancel the completed status of the task as though
|
||||
"task done ..." was never run.
|
||||
</p>
|
||||
|
||||
<strong>% task list ...</strong>
|
||||
<p>
|
||||
The list report will show the active status, and age of the task in
|
||||
@@ -188,6 +225,24 @@ Year Month Added Completed Deleted Net
|
||||
number decreased as more task were completed than added.
|
||||
</p>
|
||||
|
||||
<strong>% task ghistory</strong>
|
||||
<p>
|
||||
The ghistory report is a "graphical" version of the history
|
||||
report. It shows a colored bar graph and legend.
|
||||
</p>
|
||||
|
||||
<strong>% task timesheet 2</strong>
|
||||
<p>
|
||||
The timesheet report shows a list of tasks completed and started
|
||||
during a one-week period. In the example above, 2 weeks of tasks
|
||||
are shown.
|
||||
</p>
|
||||
<p>
|
||||
By default, the report starts on a Monday. To override this
|
||||
value, add an entry to your .taskrc file like this:
|
||||
<pre><code>weekstart=Sunday</code></pre>
|
||||
</p>
|
||||
|
||||
<strong>% task calendar</strong>
|
||||
<p>
|
||||
This report shows a calendar of the current month, with any task
|
||||
@@ -246,19 +301,27 @@ ID Project Pri Description
|
||||
12 Errand L Remember to deposit bonus check
|
||||
...</code></pre>
|
||||
|
||||
<strong>% task oldest</strong>
|
||||
<strong>% task oldest [limit]</strong>
|
||||
<p>
|
||||
Lists the oldest tasks. Shows 10 tasks by default, but can be
|
||||
set via the "oldest" configuration variable.
|
||||
Lists the oldest tasks. The number of tasks shown is set by
|
||||
the configuration variable:
|
||||
<pre><code>report.oldest.limit=10</code></pre>
|
||||
This value can be overridden at run time by specifying the
|
||||
number of tasks on the command line:
|
||||
<pre><code>task oldest 5</code></pre>
|
||||
</p>
|
||||
|
||||
<strong>% task newest</strong>
|
||||
<strong>% task newest [limit]</strong>
|
||||
<p>
|
||||
Lists the newest tasks. Shows 10 tasks by default, but can be
|
||||
set via the "newest" configuration variable.
|
||||
Lists the newest tasks. The number of tasks shown is set by
|
||||
the configuration variable:
|
||||
<pre><code>report.newest.limit=10</code></pre>
|
||||
This value can be overridden at run time by specifying the
|
||||
number of tasks on the command line:
|
||||
<pre><code>task newest 5</code></pre>
|
||||
</p>
|
||||
|
||||
<strong>% task /from/to/</strong>
|
||||
<strong>% task <id> /from/to/</strong>
|
||||
<p>
|
||||
If a task has been entered with a typo, it can be easily corrected
|
||||
by this command. For example:
|
||||
@@ -278,7 +341,20 @@ ID Project Pri Description
|
||||
...</code></pre>
|
||||
|
||||
<p>
|
||||
This command makes single corrections to a task description.
|
||||
This command makes a single correction to the first occurrence of
|
||||
"from" in a task description.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If a task is annotated, the annotation can also be modified using
|
||||
this command.
|
||||
</p>
|
||||
|
||||
<strong>% task <id> /from/to/g</strong>
|
||||
<p>
|
||||
The "g" modifier to the substitution command causes every occurrence
|
||||
of "from" to be replaced with "to", in both the description and any
|
||||
annotations.
|
||||
</p>
|
||||
|
||||
<strong>% task tags</strong>
|
||||
@@ -357,6 +433,22 @@ ID Project Pri Description
|
||||
command.
|
||||
</p>
|
||||
|
||||
<strong>% task <id> edit</strong>
|
||||
<p>
|
||||
This command allows you to use your text editor to edit all aspects
|
||||
of a task. The specified task will be written to a file, and your
|
||||
text editor will be invoked. If you modify the task in the text
|
||||
editor, task will update accordingly.
|
||||
</p>
|
||||
<p>
|
||||
Task will first check to see if you have defined a text editor
|
||||
in the 'editor' configuration variable. If not, task will
|
||||
check to see if you defined a text editor in the VISUAL
|
||||
environment variable. If not task will check to see if you
|
||||
defined a text editor in the EDITOR environment variable.
|
||||
If all those fail, task launches vi.
|
||||
</p>
|
||||
|
||||
<strong>% task <id> fg:... bg:...</strong>
|
||||
<p>
|
||||
Not strictly a command, the setting of the fg and bg (foreground
|
||||
@@ -398,7 +490,7 @@ on_white on_bright_white</code></pre>
|
||||
<br />
|
||||
<div class="content">
|
||||
<p>
|
||||
Copyright 2006-2008, P. Beckingham. All rights reserved.
|
||||
Copyright 2006-2009, P. Beckingham. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -20,10 +20,9 @@
|
||||
<a href="shell.html">Shell</a>
|
||||
<a href="config.html">Configuration</a>
|
||||
<a href="color.html">Colors</a>
|
||||
<a href="usage.html">Usage</a>
|
||||
<a href="recur.html">Recurrence</a>
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="troubleshooting.html">Troubleshooting</a>
|
||||
<a href="faq.html">FAQ</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
@@ -77,7 +76,7 @@ on_white on_bright_white</code></pre>
|
||||
<br />
|
||||
<div class="content">
|
||||
<p>
|
||||
Copyright 2006-2008, P. Beckingham. All rights reserved.
|
||||
Copyright 2006-2009, P. Beckingham. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -20,10 +20,9 @@
|
||||
<a href="shell.html">Shell</a>
|
||||
<a href="config.html">Configuration</a>
|
||||
<a href="color.html">Colors</a>
|
||||
<a href="usage.html">Usage</a>
|
||||
<a href="recur.html">Recurrence</a>
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="troubleshooting.html">Troubleshooting</a>
|
||||
<a href="faq.html">FAQ</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
@@ -58,6 +57,13 @@
|
||||
confirmation before deleting a task.
|
||||
</dd>
|
||||
|
||||
<dt>echo.command</dt>
|
||||
<dd>
|
||||
May be "yes" or "no", and causes task to display the ID and
|
||||
description of any task when you run the start, stop, do, undo,
|
||||
delete and undelete commands. The default value is "yes".
|
||||
</dd>
|
||||
|
||||
<dt>nag</dt>
|
||||
<dd>
|
||||
This may be a string of text, or blank. It is used as a prompt
|
||||
@@ -174,19 +180,27 @@
|
||||
<dt>monthsperline</dt>
|
||||
<dd>
|
||||
Determines how many months the "task calendar" command
|
||||
renders across the screen. Defaults to 1.
|
||||
renders across the screen. Defaults to however many will
|
||||
fit. If more months that will fit are specified, task will
|
||||
only show as many that will fit.
|
||||
</dd>
|
||||
|
||||
<dt>oldest</dt>
|
||||
<dt>weekstart</dt>
|
||||
<dd>
|
||||
Determines how many tasks the "task oldest" command displays.
|
||||
Defaults to 10.
|
||||
The day of the week that represents the first day of the week.
|
||||
Defaults to "Monday".
|
||||
</dd>
|
||||
|
||||
<dt>newest</dt>
|
||||
<dt>editor</dt>
|
||||
<dd>
|
||||
Determines how many tasks the "task newest" command displays.
|
||||
Defaults to 10.
|
||||
Specifies which text editor you wish to use for when the
|
||||
|
||||
<pre><code>task edit <ID></code></pre>
|
||||
|
||||
command is used. Task will first look for this configuration
|
||||
variable. If found, it is used. Otherwise task will look
|
||||
for the VISUAL or EDITOR environment variables, before it
|
||||
defaults to using 'vi'.
|
||||
</dd>
|
||||
|
||||
<dt>defaultwidth</dt>
|
||||
@@ -195,6 +209,14 @@
|
||||
Defaults to 80.
|
||||
</dd>
|
||||
|
||||
<dt>due</dt>
|
||||
<dd>
|
||||
|
||||
This is the number of days into the future that define when a
|
||||
task is considered due, and is colored accordingly.
|
||||
Defaults to 7.
|
||||
</dd>
|
||||
|
||||
<dt>color</dt>
|
||||
<dd>
|
||||
May be "on" or "off". Determines whether task uses color.
|
||||
@@ -210,7 +232,8 @@
|
||||
color.pri.L<br />
|
||||
color.pri.none<br />
|
||||
color.active<br />
|
||||
color.tagged
|
||||
color.tagged<br />
|
||||
color.recurring
|
||||
</dt>
|
||||
<dd>
|
||||
These are the coloration rules. They correspond to a particular
|
||||
@@ -316,6 +339,43 @@ ID Project Pri Description
|
||||
whenever the shadow file is updated by some task command.
|
||||
</dd>
|
||||
|
||||
<dt>locking</dt>
|
||||
<dd>
|
||||
<p>
|
||||
Determines whether task uses file locking when accessing the pending.data
|
||||
and completed.data files. Default to "on". Solaris users who store
|
||||
the task data files on an NFS mount may need to set locking to "off".
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Note that setting this value to "off" is dangerous. It means that
|
||||
another program may write to the task.pending file when task is
|
||||
attempting to do the same.
|
||||
</p>
|
||||
</dd>
|
||||
|
||||
<dt>import.synonym.id</dt>
|
||||
<dt>import.synonym.uuid</dt>
|
||||
<dt>import.synonym.status</dt>
|
||||
<dt>import.synonym.tags</dt>
|
||||
<dt>import.synonym.entry</dt>
|
||||
<dt>import.synonym.start</dt>
|
||||
<dt>import.synonym.due</dt>
|
||||
<dt>import.synonym.recur</dt>
|
||||
<dt>import.synonym.end</dt>
|
||||
<dt>import.synonym.project</dt>
|
||||
<dt>import.synonym.priority</dt>
|
||||
<dt>import.synonym.fg</dt>
|
||||
<dt>import.synonym.bg</dt>
|
||||
<dt>import.synonym.description</dt>
|
||||
<dd>
|
||||
If any of these configuration variables are found, they influence
|
||||
data import by specifying a single additional field name synonym.
|
||||
If a data import is failing because certain column names are not
|
||||
being recognized, then this is how the field mapping can be
|
||||
controlled.
|
||||
</dd>
|
||||
|
||||
<p>
|
||||
Note that the command:
|
||||
</p>
|
||||
@@ -326,13 +386,15 @@ ID Project Pri Description
|
||||
will display the configuration variables found in the .taskrc file,
|
||||
and will warn you of any variables that are not recognized.
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<div class="content">
|
||||
<p>
|
||||
Copyright 2006-2008, P. Beckingham. All rights reserved.
|
||||
Copyright 2006-2009, P. Beckingham. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
178
html/custom.html
Normal file
178
html/custom.html
Normal file
@@ -0,0 +1,178 @@
|
||||
<!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>Custom Reports</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<link rel="stylesheet" href="task.css" type="text/css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<div id="toolbar">
|
||||
<a href="task.html">Home</a>
|
||||
<a href="setup.html">Setup</a>
|
||||
<a href="30second.html">30-second Tutorial</a>
|
||||
<a href="simple.html">Simple</a>
|
||||
<a href="advanced.html">Advanced</a>
|
||||
<a href="shell.html">Shell</a>
|
||||
<a href="config.html">Configuration</a>
|
||||
<a href="color.html">Colors</a>
|
||||
<a href="recur.html">Recurrence</a>
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="faq.html">FAQ</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<h2 class="title">Custom Reports</h2>
|
||||
<div class="content">
|
||||
<p>
|
||||
Task allows you to customize reports, to a limited degree.
|
||||
The "list", "long", "ls", "oldest" and "newest" reports are
|
||||
all now custom reports, whereas in previous releases of task
|
||||
they were not mutable. This means they can be modified,
|
||||
renamed, or deleted.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
More importantly, you can define your own. Here are the
|
||||
three necessary items in the .taskrc file that define a new
|
||||
report:
|
||||
</p>
|
||||
|
||||
<code><pre>report.mine.description=Just the essentials
|
||||
report.mine.columns=id,project,priority,description
|
||||
report.mine.sort=priority-,project+</pre></code>
|
||||
|
||||
<p>
|
||||
This defines a report, called "mine", that has four columns:
|
||||
id, project, priority and description. It will be sorted on
|
||||
two columns: by descending priority then ascending project.
|
||||
The description that shows up in the task command usage page
|
||||
is "Just the essentials". Because this report is called
|
||||
"mine", it can be run with the command:
|
||||
</p>
|
||||
|
||||
<code><pre>% task mine</pre></code>
|
||||
|
||||
<p>
|
||||
An optional filter can also be specified like this:
|
||||
</p>
|
||||
|
||||
<code><pre>report.mine.filter=priority:H +bug</pre></code>
|
||||
|
||||
<p>
|
||||
This adds a filter so that only tasks with priority "H" and
|
||||
with the "bug" tag are included in the report. This filter
|
||||
definition is optional.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
An optional limit can also be specified, which limits the
|
||||
number of tasks shown in the report. If a limit is not
|
||||
specified, then the number of tasks is not limited.
|
||||
</p>
|
||||
|
||||
<code><pre>report.mine.limit=10</pre></code>
|
||||
|
||||
<p>
|
||||
Here is a list of all the possible columns that may be included
|
||||
in a report:
|
||||
</p>
|
||||
|
||||
<p>
|
||||
It is also possible to override the default columns names, if
|
||||
the following line is added to your .taskrc file:
|
||||
</p>
|
||||
|
||||
<pre><code>report.mine.labels=ID,Project,Priority,Description of task</code></pre>
|
||||
|
||||
<p>
|
||||
Note that there must be the same number of labels as there are
|
||||
columns to label, and they must appear in the same sequence.
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>id
|
||||
<li>uuid
|
||||
<li>project
|
||||
<li>priority
|
||||
<li>entry
|
||||
<li>start
|
||||
<li>due
|
||||
<li>age
|
||||
<li>active
|
||||
<li>tags
|
||||
<li>recur
|
||||
<li>description_only
|
||||
<li>description
|
||||
<li>tag_indicator
|
||||
<li>recurrence_indicator
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Custom reports will show up in the task command line usage.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<div class="content">
|
||||
<p>
|
||||
Copyright 2006-2009, P. Beckingham. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td align="right" valign="top" width="200px">
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<script type="text/javascript"><!--
|
||||
google_ad_client = "pub-9709799404235424";
|
||||
/* Task Main */
|
||||
google_ad_slot = "8660617875";
|
||||
google_ad_width = 120;
|
||||
google_ad_height = 600;
|
||||
//-->
|
||||
</script>
|
||||
<script type="text/javascript"
|
||||
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
|
||||
</script>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
|
||||
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
var pageTracker = _gat._getTracker("UA-4737637-1");
|
||||
pageTracker._initData();
|
||||
pageTracker._trackPageview();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -20,10 +20,9 @@
|
||||
<a href="shell.html">Shell</a>
|
||||
<a href="config.html">Configuration</a>
|
||||
<a href="color.html">Colors</a>
|
||||
<a href="usage.html">Usage</a>
|
||||
<a href="recur.html">Recurrence</a>
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="troubleshooting.html">Troubleshooting</a>
|
||||
<a href="faq.html">FAQ</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
@@ -110,7 +109,7 @@
|
||||
<br />
|
||||
<div class="content">
|
||||
<p>
|
||||
Copyright 2006-2008, P. Beckingham. All rights reserved.
|
||||
Copyright 2006-2009, P. Beckingham. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
239
html/faq.html
Normal file
239
html/faq.html
Normal file
@@ -0,0 +1,239 @@
|
||||
<!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>Frequently Asked Questions</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<link rel="stylesheet" href="task.css" type="text/css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<div id="toolbar">
|
||||
<a href="task.html">Home</a>
|
||||
<a href="setup.html">Setup</a>
|
||||
<a href="30second.html">30-second Tutorial</a>
|
||||
<a href="simple.html">Simple</a>
|
||||
<a href="advanced.html">Advanced</a>
|
||||
<a href="shell.html">Shell</a>
|
||||
<a href="config.html">Configuration</a>
|
||||
<a href="color.html">Colors</a>
|
||||
<a href="recur.html">Recurrence</a>
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="faq.html">FAQ</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<h2 class="title">Frequently Asked Questions</h2>
|
||||
<div class="content">
|
||||
<p>
|
||||
(Actually, that's a misnomer. These are really Repeatedly Asked
|
||||
Questions.)
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>
|
||||
Q: When I redirect the output of task to a file, I lose all
|
||||
the colors. How do I fix this?
|
||||
</b>
|
||||
<br />
|
||||
A: Task knows (or thinks it knows) when the output is not going
|
||||
directly to a terminal, and strips out all the color control
|
||||
characters. Prevent this with the following entry in your
|
||||
.taskrc file:
|
||||
<pre><code>_forcecolor=on</code></pre>
|
||||
</p>
|
||||
<hr>
|
||||
|
||||
<p>
|
||||
<b>
|
||||
Q: How do I backup my task data files? Where are they?
|
||||
</b>
|
||||
<br />
|
||||
A: Task writes all pending tasks to the file ~/.task/pending.data
|
||||
and all completed and deleted tasks to ~/.task/completed.data.
|
||||
They are text files, so they can just be copied to another
|
||||
location for safekeeping. Don't forget there is also the
|
||||
~/.taskrc file that contains your task configuration data.
|
||||
To be sure, and to future-proof your backup, consider backing
|
||||
up all the files in the ~/.task directory.
|
||||
</p>
|
||||
<hr>
|
||||
|
||||
<p>
|
||||
<b>
|
||||
Q: How can I separate my work tasks from my home tasks?
|
||||
Specifically, can I keep them completely separate?
|
||||
</b>
|
||||
<br />
|
||||
A: You can do this by creating an alternate .taskrc file,
|
||||
then using shell aliases. Here is are example Bash
|
||||
commands to achieve this:
|
||||
|
||||
<pre><code>% cp ~/.taskrc ~/.taskrc_home
|
||||
% (now edit .taskrc_home to change the value of data.location)
|
||||
% alias wtask="task"
|
||||
% alias htask="task rc:~/.taskrc_home"</code></pre>
|
||||
|
||||
This gives you two commands, 'wtask' and 'htask' that
|
||||
operate using two different sets of task data files.
|
||||
</p>
|
||||
<hr>
|
||||
|
||||
<p>
|
||||
<b>
|
||||
Q: Can I revert to a previous version of task? How?
|
||||
</b>
|
||||
<br />
|
||||
A: Yes, you can revert to a previous version of task,
|
||||
simply by downloading an
|
||||
<a href="versions.html">older version</a> and
|
||||
installing it. If you find a bug in task, then this
|
||||
may be the only way to work around the bug, until a
|
||||
new release is made.
|
||||
</p>
|
||||
<p>
|
||||
Note that it is possible that the task file format will
|
||||
change. For example, the format changed between versions
|
||||
1.5.0 and 1.6.0. Task will automatically upgrade the file
|
||||
but if you need to revert to a previous version of task,
|
||||
there is the file format to consider. This is yet another
|
||||
good reason to back up your task data files!
|
||||
</p>
|
||||
<hr>
|
||||
|
||||
<p>
|
||||
<b>
|
||||
Q: I'm using Ubuntu 9.04, and I want task to word-wrap
|
||||
descriptions. How do I do this?
|
||||
</b>
|
||||
<br />
|
||||
A: You need to install ncurses, by doing this:
|
||||
<code><pre>% sudo apt-get install libncurses5-dev</pre></code>
|
||||
Then you need to rebuild task from scratch, starting with
|
||||
<code><pre>% cd task-X.X.X
|
||||
% ./configure
|
||||
...</pre></code>
|
||||
The result should be a task program that knows the width
|
||||
of the terminal window, and wraps accordingly.
|
||||
</p>
|
||||
<hr>
|
||||
|
||||
<p>
|
||||
<b>
|
||||
Q: How do I build task under Cygwin?
|
||||
</b>
|
||||
<br />
|
||||
A: Task is built the same way everywhere. But under Cygwin, you'll
|
||||
need to make sure you have the following packages available
|
||||
first:
|
||||
|
||||
<ul>
|
||||
<li>gcc
|
||||
<li>make
|
||||
<li>libncurses-devel
|
||||
<li>libncurses8
|
||||
</ul>
|
||||
|
||||
The gcc and make packages allow you to compile the code, and
|
||||
are therefore required, but the ncurses packages are optional.
|
||||
Ncurses will allow task to determine the width of the window, and
|
||||
therefore use the whole width and wrap text accordingly, for a
|
||||
more aesthetically pleasing display.
|
||||
</p>
|
||||
<hr>
|
||||
|
||||
<p>
|
||||
<b>
|
||||
Q: Do colors work under Cygwin?
|
||||
</b>
|
||||
<br />
|
||||
A: They do, but only in a limited way. You can use regular
|
||||
foreground colors (black, red, green ...) and you can
|
||||
regular background colors (on_black, on_red, on_green ...),
|
||||
but underline and bold are not supported.
|
||||
<br />
|
||||
<br />
|
||||
If you run the command:
|
||||
<code><pre>% task colors</pre></code>
|
||||
Task will display all the colors it can use, and you will
|
||||
see which ones you can use.
|
||||
<br />
|
||||
<br />
|
||||
See the <a href="color.html">color</a> documentation for
|
||||
more details on which colors can be used.
|
||||
</p>
|
||||
<hr>
|
||||
|
||||
<!--
|
||||
<p>
|
||||
<b>
|
||||
Q:
|
||||
</b>
|
||||
<br />
|
||||
A:
|
||||
</p>
|
||||
<hr>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<div class="content">
|
||||
<p>
|
||||
Copyright 2006-2009, P. Beckingham. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td align="right" valign="top" width="200px">
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<script type="text/javascript"><!--
|
||||
google_ad_client = "pub-9709799404235424";
|
||||
/* Task Main */
|
||||
google_ad_slot = "8660617875";
|
||||
google_ad_width = 120;
|
||||
google_ad_height = 600;
|
||||
//-->
|
||||
</script>
|
||||
<script type="text/javascript"
|
||||
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
|
||||
</script>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
|
||||
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
var pageTracker = _gat._getTracker("UA-4737637-1");
|
||||
pageTracker._initData();
|
||||
pageTracker._trackPageview();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -20,10 +20,9 @@
|
||||
<a href="shell.html">Shell</a>
|
||||
<a href="config.html">Configuration</a>
|
||||
<a href="color.html">Colors</a>
|
||||
<a href="usage.html">Usage</a>
|
||||
<a href="recur.html">Recurrence</a>
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="troubleshooting.html">Troubleshooting</a>
|
||||
<a href="faq.html">FAQ</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
@@ -82,7 +81,7 @@
|
||||
<br />
|
||||
<div class="content">
|
||||
<p>
|
||||
Copyright 2006-2008, P. Beckingham. All rights reserved.
|
||||
Copyright 2006-2009, P. Beckingham. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
409
html/git.html
Normal file
409
html/git.html
Normal file
@@ -0,0 +1,409 @@
|
||||
<!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>git</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<link rel="stylesheet" href="task.css" type="text/css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<div id="toolbar">
|
||||
<a href="task.html">Home</a>
|
||||
<a href="setup.html">Setup</a>
|
||||
<a href="30second.html">30-second Tutorial</a>
|
||||
<a href="simple.html">Simple</a>
|
||||
<a href="advanced.html">Advanced</a>
|
||||
<a href="shell.html">Shell</a>
|
||||
<a href="config.html">Configuration</a>
|
||||
<a href="color.html">Colors</a>
|
||||
<a href="recur.html">Recurrence</a>
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="faq.html">FAQ</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<h2 class="title"><a name="simple">Using git</a></h2>
|
||||
<div class="content">
|
||||
<p>
|
||||
First you need to tell git who you are. These commands will
|
||||
write to ~/.gitconfig, and will be used to identify you when
|
||||
you commit changes. Plus, I like color.
|
||||
</p>
|
||||
|
||||
<pre><code>% git config --global user.name "John Doe"
|
||||
% git config --global user.email "john@doe.com"
|
||||
% git config --global color.ui=always</code></pre>
|
||||
|
||||
<p>
|
||||
Now we will clone the repository, which involves downloading
|
||||
about 2MB of files. Git repositories are very compact. We
|
||||
will clone the repository from github. This takes a minute or
|
||||
so.
|
||||
</p>
|
||||
|
||||
<pre><code>% cd
|
||||
% git clone git://github.com/pbeckingham/task.git task.git
|
||||
% cd task.git</code></pre>
|
||||
|
||||
<p>
|
||||
You just pulled the entire history of task changes since it
|
||||
was uploaded to github. That will be missing about a year and
|
||||
a half of prior changes, which were in Subversion. Let's
|
||||
build task:
|
||||
</p>
|
||||
|
||||
<pre><code>% autoreconf
|
||||
...
|
||||
% ./configure --prefix=/usr/local
|
||||
...
|
||||
% make
|
||||
...</code></pre>
|
||||
|
||||
<p>
|
||||
The task binary will be in the src directory. If you run:
|
||||
</p>
|
||||
|
||||
<pre><code>% sudo make install</code></pre>
|
||||
|
||||
<p>
|
||||
Then task will be copied to /usr/local/bin, according the
|
||||
--prefix argument used above. /usr/local is the default
|
||||
prefix, so that argument wasn't necessary, but illustrates
|
||||
it's use.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Meanwhile, you have just created a local copy of the
|
||||
repository. You can do anything to this copy except push to
|
||||
github. Only the repository owner can push to github, or
|
||||
additional users identified by the owner (with additional
|
||||
monthly github fee). In order to get your changes back to
|
||||
github, they have to go through the owner, either in the form
|
||||
of a patch via email, or by creating your own github account,
|
||||
pushing to you own task repository clone (github calls it a
|
||||
fork), then asking the owner to pull directly from your
|
||||
repository.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You only need to clone once, unless you feel like starting
|
||||
over, or creating additional clones. Ordinarily, you update
|
||||
your local copy by pulling changes from github with:
|
||||
</p>
|
||||
|
||||
<pre><code>% git pull</code></pre>
|
||||
|
||||
<p>
|
||||
Right now, nothing new should be pulled, because you just
|
||||
cloned. Sometimes you'll see changes that have either been
|
||||
made by the owner, or merged in from others, by the owner.
|
||||
Let's take a look at the commit history:
|
||||
</p>
|
||||
|
||||
<pre><code>% git log</code></pre>
|
||||
|
||||
<p>
|
||||
You see a whole series of commits. Each commit is a set of
|
||||
file changes that were made somewhere. Let's look at branches.
|
||||
Try this:
|
||||
</p>
|
||||
|
||||
<pre><code>% git branch
|
||||
* master</code></pre>
|
||||
|
||||
<p>
|
||||
This is telling you that you have only one branch, called
|
||||
master. The asterisk tells you that this is your current
|
||||
branch, which is redundant because you only have one. But
|
||||
there are other branches on github. See those with:
|
||||
</p>
|
||||
|
||||
<pre><code>% git branch -a
|
||||
* master
|
||||
remotes/origin/1.6.1
|
||||
remotes/origin/1.7.0
|
||||
remotes/origin/HEAD -> origin/master
|
||||
remotes/origin/master</code></pre>
|
||||
|
||||
<p>
|
||||
A remote is what git calls another repository. The origin
|
||||
remote is the repository that this clone originated from.
|
||||
This output tells you that there is a 1.6.1 branch on github,
|
||||
a 1.7.0 branch on github, and a master branch on github. It's
|
||||
not obvious, but your local master (the first one shown) is
|
||||
tracking remotes/origin/master, which means changes on the
|
||||
remote will get merged to the local tracking branch on pull.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The convention used by task is to create a new branch whenever
|
||||
work begins on a new version. When that version is released,
|
||||
the branch is merged to master, but retained. At time of
|
||||
writing, 1.6.1 is the currently released version of task, and
|
||||
so remotes/origin/1.6.1 and remotes/origin/master are
|
||||
currently identical, with all new development happening on the
|
||||
1.7.0 branch. When 1.7.0 is released, it will get merged to
|
||||
master, and the 1.6.1 branch will be deleted. Nothing will be
|
||||
lost, because 1.6.1 is already merged to master. Let's look
|
||||
at tags:
|
||||
</p>
|
||||
|
||||
<pre><code>% git tag</code></pre>
|
||||
...
|
||||
v1.4.3
|
||||
v1.5.0
|
||||
v1.6.0
|
||||
v1.6.1
|
||||
|
||||
<p>
|
||||
Those tags are just labels that represent the last commit for
|
||||
that version. You may notice that a change in the tag naming
|
||||
convention, that occurred when the owner realized that git
|
||||
will not allow a tag and a branch of the same name at the same
|
||||
time, so now there is a "v" in the tags.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Let's make a branch called 1.7.0 that tracks changes to
|
||||
remotes/origin/1.7.0. That means you can pull 1.7.0 changes
|
||||
from github into your local branch, to keep up to date.
|
||||
</p>
|
||||
|
||||
<pre><code>% git checkout -b 1.7.0 origin/1.7.0
|
||||
Branch 1.7.0 set up to track remote branch 1.7.0 from origin.
|
||||
Switched to a new branch '1.7.0'
|
||||
|
||||
% git branch -a
|
||||
* 1.7.0
|
||||
master
|
||||
remotes/origin/1.6.1
|
||||
remotes/origin/1.7.0
|
||||
remotes/origin/HEAD -> origin/master
|
||||
remotes/origin/master</code></pre>
|
||||
|
||||
<p>
|
||||
Now you can see that 1.7.0 is your current branch (*). That
|
||||
means you are looking at the 1.7.0 codebase. Let us now
|
||||
assume you intend to make a change, and submit the patch. We
|
||||
will add Solaris 8 as a supported OS. This will affect two
|
||||
files. First check status:
|
||||
</p>
|
||||
|
||||
<pre><code>% git status
|
||||
# On branch 1.7.0
|
||||
nothing to commit (working directory clean)</code></pre>
|
||||
|
||||
<p>
|
||||
No changes. That's what we expect. Now make the changes (any
|
||||
editor will suffice, but assume vi):
|
||||
</p>
|
||||
|
||||
<pre><code>% vi NEWS
|
||||
% vi html/task.html</code></pre>
|
||||
|
||||
<p>
|
||||
Now we expect to see changes. Status says:
|
||||
</p>
|
||||
|
||||
<pre><code>% git status
|
||||
# On branch 1.7.0
|
||||
# Changed but not updated:
|
||||
# (use "git add <file>..." to update what will be committed)
|
||||
# (use "git checkout -- <file>..." to discard changes in working directory)
|
||||
#
|
||||
# modified: NEWS
|
||||
# modified: html/task.html
|
||||
#
|
||||
no changes added to commit (use "git add" and/or "git commit -a")</code></pre>
|
||||
|
||||
<p>
|
||||
Git sees that those two files have changed, but as git states,
|
||||
they are not added to the commit. Git allows you to stage
|
||||
changes, then commit the staged changes - a two-step process
|
||||
that gives you complete control. Git also allows you to
|
||||
commit all changes and bypass the staging, but that's a
|
||||
shortcut that is risky, because you can inadvertently commit
|
||||
things you didn't want to. Let's see what git thinks changed:
|
||||
</p>
|
||||
|
||||
<pre><code>% git diff
|
||||
diff --git a/NEWS b/NEWS
|
||||
index 74adecd..30d4f8f 100644
|
||||
--- a/NEWS
|
||||
+++ b/NEWS
|
||||
@@ -12,6 +12,7 @@ Task has been built and tested on the following configurations:
|
||||
- Ubuntu 8.10 Intrepid Ibex
|
||||
- Ubuntu 9.04 Jaunty Jackalope
|
||||
- Arch Linux
|
||||
+ - Solaris 8
|
||||
- Solaris 10
|
||||
- Cygwin 1.5.25-14
|
||||
|
||||
diff --git a/html/task.html b/html/task.html
|
||||
index 66ee777..a2254f6 100644
|
||||
--- a/html/task.html
|
||||
+++ b/html/task.html
|
||||
@@ -193,6 +193,7 @@
|
||||
<li>Ubuntu 8.10 Intrepid Ibex
|
||||
<li>Ubuntu 9.04 Jaunty Jackalope
|
||||
<li>Arch Linux
|
||||
+ <li>Solaris 8
|
||||
<li>Solaris 10
|
||||
<li>Cygwin 1.5.25-14
|
||||
</ul></code></pre>
|
||||
|
||||
<p>
|
||||
Git has correctly spotted the changes. The "git diff" command
|
||||
always tells you the difference between the last commit and
|
||||
the current state. Now we will stage the two changes:
|
||||
</p>
|
||||
|
||||
<pre><code>% git add NEWS html/task.html
|
||||
% git diff</code></pre>
|
||||
|
||||
<p>
|
||||
No changes are reported. That's because if files are staged,
|
||||
then diff shows the difference between the staged files and
|
||||
the current state. We staged all changes, hence no diff. If
|
||||
we wanted to see the difference between the last commit and
|
||||
the staged files, try this:
|
||||
</p>
|
||||
|
||||
<pre><code>% git diff --cached
|
||||
(same as unstaged diff)</code></pre>
|
||||
|
||||
<p>
|
||||
Now the status shows that the files are staged:
|
||||
</p>
|
||||
|
||||
<pre><code>% git status
|
||||
# On branch 1.7.0
|
||||
# Changes to be committed:
|
||||
# (use "git reset HEAD <file>..." to unstage)
|
||||
#
|
||||
# modified: NEWS
|
||||
# modified: html/task.html
|
||||
#</code></pre>
|
||||
|
||||
<p>
|
||||
Now a commit command will commit the staged files:
|
||||
</p>
|
||||
|
||||
<pre><code>% git commit -m "Added Solaris 8 as a supported platform"
|
||||
[1.7.0 03308eb] Added Solaris 8 as a suported platform
|
||||
2 files changed, 2 insertions(+), 0 deletions(-)</code></pre>
|
||||
|
||||
<p>
|
||||
Now make a patch:
|
||||
</p>
|
||||
|
||||
<pre><code>% git format-patch HEAD^
|
||||
0001-Added-Solaris-8-as-a-supported-platform.patch</code></pre>
|
||||
|
||||
<p>
|
||||
HEAD is a label that means the current head of the branch, or
|
||||
in other words, what was last committed. HEAD^ means the
|
||||
commit before that. HEAD~2 is the one before that, HEAD~3
|
||||
etc. When we say create a patch of HEAD^, it means the same
|
||||
as:
|
||||
</p>
|
||||
|
||||
<pre><code>% git diff HEAD^</code></pre>
|
||||
|
||||
<p>
|
||||
Which means show the difference between the previous commit
|
||||
and the current commit, but the patch has extra identifying
|
||||
information in it. Take a look at that patch file. If you
|
||||
ran:
|
||||
</p>
|
||||
|
||||
<pre><code>% git format-patch HEAD~10</code></pre>
|
||||
|
||||
<p>
|
||||
Git will create 10 patch files, one for each commit. To get
|
||||
the patch applied to the repository, email it to the owner.
|
||||
The owner will then apply the patch with:
|
||||
</p>
|
||||
|
||||
<pre><code>owner> git apply 0001-Added-Solaris-8-as-a-supported-platform.patch</code></pre>
|
||||
|
||||
<p>
|
||||
Then push the changes with:
|
||||
</p>
|
||||
|
||||
<pre><code>owner> git push</code></pre>
|
||||
|
||||
<p>
|
||||
And that makes them available on github, which means in turn
|
||||
that the next time you run:
|
||||
</p>
|
||||
|
||||
<pre><code>% git pull</code></pre>
|
||||
|
||||
<p>
|
||||
Your changes will have come full circle.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<div class="content">
|
||||
<p>
|
||||
Copyright 2006-2009, P. Beckingham. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td align="right" valign="top" width="200px">
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<script type="text/javascript"><!--
|
||||
google_ad_client = "pub-9709799404235424";
|
||||
/* Task Main */
|
||||
google_ad_slot = "8660617875";
|
||||
google_ad_width = 120;
|
||||
google_ad_height = 600;
|
||||
//-->
|
||||
</script>
|
||||
<script type="text/javascript"
|
||||
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
|
||||
</script>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
|
||||
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
var pageTracker = _gat._getTracker("UA-4737637-1");
|
||||
pageTracker._initData();
|
||||
pageTracker._trackPageview();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
157
html/import.html
Normal file
157
html/import.html
Normal file
@@ -0,0 +1,157 @@
|
||||
<!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>Data Import</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<link rel="stylesheet" href="task.css" type="text/css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<div id="toolbar">
|
||||
<a href="task.html">Home</a>
|
||||
<a href="setup.html">Setup</a>
|
||||
<a href="30second.html">30-second Tutorial</a>
|
||||
<a href="simple.html">Simple</a>
|
||||
<a href="advanced.html">Advanced</a>
|
||||
<a href="shell.html">Shell</a>
|
||||
<a href="config.html">Configuration</a>
|
||||
<a href="color.html">Colors</a>
|
||||
<a href="recur.html">Recurrence</a>
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="faq.html">FAQ</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<h2 class="title">Data Import</h2>
|
||||
<div class="content">
|
||||
<p>
|
||||
Tasks can be imported from files with this command:
|
||||
|
||||
<pre><code>% task import file</code></pre>
|
||||
|
||||
A variety of different file types are recognized by task, namely:
|
||||
|
||||
<ul>
|
||||
<li>Tasks exported from task prior to version 1.5.0.
|
||||
<li>Tasks exported from task version 1.5.0 and later. The file
|
||||
format changed with 1.5.0.
|
||||
<li>todo.sh files.
|
||||
<li>CSV files with a variety of recognized column names.
|
||||
<li>Plain text files, with one task listed per line.
|
||||
<li>Task command line format.
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Task makes a good effort to determine which of these formats a
|
||||
file is. It does this by reading the file, and looking for
|
||||
familiar patterns. For example, the easiest files to recognize
|
||||
are those exported from task itself, because they all have a
|
||||
header line that comes in only three variations. Other formats
|
||||
are a little harder to identify, but they all have their own
|
||||
identifying characteristics.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The most complex import is when a CSV file is recognized.
|
||||
Task needs a field header line in order to map columns to task
|
||||
data items. For example, the if the following file is
|
||||
imported:
|
||||
</p>
|
||||
|
||||
<pre><code>number,status,task
|
||||
1,pending,task one
|
||||
2,pending,task two</code></pre>
|
||||
|
||||
<p>
|
||||
Task will map the "number" field to task's "id" field, etc,
|
||||
based on name. Task has a list of synonyms that it uses to
|
||||
map fields, but you can specify your own override with any of
|
||||
the following configuration variables:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>import.synonym.id
|
||||
<li>import.synonym.uuid
|
||||
<li>import.synonym.status
|
||||
<li>import.synonym.tags
|
||||
<li>import.synonym.entry
|
||||
<li>import.synonym.start
|
||||
<li>import.synonym.due
|
||||
<li>import.synonym.recur
|
||||
<li>import.synonym.end
|
||||
<li>import.synonym.project
|
||||
<li>import.synonym.priority
|
||||
<li>import.synonym.fg
|
||||
<li>import.synonym.bg
|
||||
<li>import.synonym.description
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Please note that it is wise to backup your task data files
|
||||
before an import.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<div class="content">
|
||||
<p>
|
||||
Copyright 2006-2009, P. Beckingham. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td align="right" valign="top" width="200px">
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<script type="text/javascript"><!--
|
||||
google_ad_client = "pub-9709799404235424";
|
||||
/* Task Main */
|
||||
google_ad_slot = "8660617875";
|
||||
google_ad_width = 120;
|
||||
google_ad_height = 600;
|
||||
//-->
|
||||
</script>
|
||||
<script type="text/javascript"
|
||||
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
|
||||
</script>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
|
||||
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
var pageTracker = _gat._getTracker("UA-4737637-1");
|
||||
pageTracker._initData();
|
||||
pageTracker._trackPageview();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -20,10 +20,9 @@
|
||||
<a href="shell.html">Shell</a>
|
||||
<a href="config.html">Configuration</a>
|
||||
<a href="color.html">Colors</a>
|
||||
<a href="usage.html">Usage</a>
|
||||
<a href="recur.html">Recurrence</a>
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="troubleshooting.html">Troubleshooting</a>
|
||||
<a href="faq.html">FAQ</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
@@ -37,6 +36,32 @@
|
||||
Task links from around the web...
|
||||
</p>
|
||||
|
||||
<dt>
|
||||
February 2009, <a href="http://lifehacker.com/5155450/todotxt-cli-manages-your-tasks-from-the-command-line">Todo.txt CLI Manages Your Tasks from the Command Line</a>
|
||||
</dt>
|
||||
<dd>
|
||||
Gina Trapani generously mentions task in an article about the newly updated, todo.sh 2.0.
|
||||
</dd>
|
||||
<br>
|
||||
|
||||
<dt>
|
||||
February, 2009, <a href="http://forum.worklifecreativity.net/index.php/topic,219.0.html">My command line based task management tools</a>
|
||||
</dt>
|
||||
<dd>
|
||||
Richard Querin talks about his task management tools.
|
||||
Richard generously provides the Debian packages for task.
|
||||
</dd>
|
||||
<br>
|
||||
|
||||
<dt>
|
||||
February, 2009, <a href="http://wiki.archlinux.org/index.php/Common_Apps">Common Apps</a>
|
||||
</dt>
|
||||
<dd>
|
||||
<a href="http://wiki.archlinux.org">Archlinux.org</a> mentions task on a page which is
|
||||
a point of reference for people looking for software to fill a particular need.
|
||||
</dd>
|
||||
<br>
|
||||
|
||||
<dt>
|
||||
November 2008, <a href="http://github.com/pbeckingham/task/tree/master/">Task repository on GitHub</a>
|
||||
</dt>
|
||||
@@ -137,7 +162,7 @@
|
||||
<br />
|
||||
<div class="content">
|
||||
<p>
|
||||
Copyright 2006-2008, P. Beckingham. All rights reserved.
|
||||
Copyright 2006-2009, P. Beckingham. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -20,10 +20,9 @@
|
||||
<a href="shell.html">Shell</a>
|
||||
<a href="config.html">Configuration</a>
|
||||
<a href="color.html">Colors</a>
|
||||
<a href="usage.html">Usage</a>
|
||||
<a href="recur.html">Recurrence</a>
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="troubleshooting.html">Troubleshooting</a>
|
||||
<a href="faq.html">FAQ</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
@@ -52,7 +51,7 @@
|
||||
generated on a regular basis. Consider the example:
|
||||
</p>
|
||||
|
||||
<pre><code>% task Pay rent due:7/1/2008 recur:monthly</code></pre>
|
||||
<pre><code>% task add Pay rent due:7/1/2008 recur:monthly</code></pre>
|
||||
|
||||
<p>
|
||||
If today's date is 7/10, for example, then that due date is in the past, and
|
||||
@@ -81,7 +80,7 @@ ID Project Pri Due Active Age Description
|
||||
Thursdays instead:
|
||||
</p>
|
||||
|
||||
<pre><code>% task TPS report due:thursday recur:weekly until:8/31/2008</code></pre>
|
||||
<pre><code>% task add TPS report due:thursday recur:weekly until:8/31/2008</code></pre>
|
||||
|
||||
<p>
|
||||
This create a weekly recurring task that expires on 8/31/2008. What this means
|
||||
@@ -101,6 +100,13 @@ Permanently delete task? (y/n) y
|
||||
This is a recurring task. Do you want to delete all pending
|
||||
recurrences of this same task? (y/n) y</code></pre>
|
||||
|
||||
<h4>Modification</h4>
|
||||
<p>
|
||||
When a recurring task is modified, all the other recurring task instances will
|
||||
be modified. For example, if you raise the priority of one of the recurring
|
||||
task instances, all will be modified.
|
||||
</p>
|
||||
|
||||
<h4>Recurrence Periods</h4>
|
||||
<p>
|
||||
In the above examples, the recurrence period was specified as "monthly" and
|
||||
@@ -116,6 +122,13 @@ recurrences of this same task? (y/n) y</code></pre>
|
||||
<td class="table_d">daily, day, 1d, 2d ...</td>
|
||||
<td class="table_d">Every day, or a number of days</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="table_d">weekdays</td>
|
||||
<td class="table_d">
|
||||
Monday, Tuesday, Wednesday, Thursday and Friday,
|
||||
skipping weekend days
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="table_d">weekly, 1w, 2w ...</td>
|
||||
<td class="table_d">Every week, or a number of weeks</td>
|
||||
@@ -155,7 +168,7 @@ recurrences of this same task? (y/n) y</code></pre>
|
||||
<br />
|
||||
<div class="content">
|
||||
<p>
|
||||
Copyright 2006-2008, P. Beckingham. All rights reserved.
|
||||
Copyright 2006-2009, P. Beckingham. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
154
html/sequence.html
Normal file
154
html/sequence.html
Normal file
@@ -0,0 +1,154 @@
|
||||
<!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 Usage</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<link rel="stylesheet" href="task.css" type="text/css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<div id="toolbar">
|
||||
<a href="task.html">Home</a>
|
||||
<a href="setup.html">Setup</a>
|
||||
<a href="30second.html">30-second Tutorial</a>
|
||||
<a href="simple.html">Simple</a>
|
||||
<a href="advanced.html">Advanced</a>
|
||||
<a href="shell.html">Shell</a>
|
||||
<a href="config.html">Configuration</a>
|
||||
<a href="color.html">Colors</a>
|
||||
<a href="recur.html">Recurrence</a>
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="faq.html">FAQ</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<h1 class="title">ID Sequences</h1>
|
||||
<div class="content">
|
||||
<p>
|
||||
Some task commands require an ID to be specified. For example:
|
||||
</p>
|
||||
|
||||
<pre><code>% task 3 done</code></pre>
|
||||
|
||||
<p>
|
||||
This marks a single task as done. But if you wanted to mark
|
||||
several tasks as done, you could use:
|
||||
</p>
|
||||
|
||||
<pre><code>% task 3,4,5 done</code></pre>
|
||||
|
||||
<p>
|
||||
Which would mark tasks 3, 4 and 5 as all done. In this example,
|
||||
the three IDs are consecutive, which means you could also have
|
||||
entered:
|
||||
</p>
|
||||
|
||||
<pre><code>% task 3-5 done</code></pre>
|
||||
|
||||
<p>
|
||||
Or in a more complex example:
|
||||
</p>
|
||||
|
||||
<pre><code>% task 1,3-5,12 23-25 done</code></pre>
|
||||
|
||||
<p>
|
||||
This would mark tasks 1, 3, 4, 5, 12, 23, 24 and 25 as done.
|
||||
Note that this example uses two sequences, separated by a space.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You must be careful though. Task tries very carefully to do
|
||||
the right thing when it interprets the command line, but must
|
||||
still impose some rules so that it can unambiguously read the
|
||||
command. If you use one or more sequences, then they must
|
||||
appear on the command line adjacent to each other. If they
|
||||
are separated by something else, then task assumes the second
|
||||
and subsequent set is not a sequence. Here is an example
|
||||
of this:
|
||||
</p>
|
||||
|
||||
<pre><code>% task 3 Order part number 4-123</code></pre>
|
||||
|
||||
<p>
|
||||
Clearly the 4-123 is a part number, and not a sequence.
|
||||
Task is being asked to modify the description of task 3 to be
|
||||
"Order part number 4-123". Note that the ID is separated
|
||||
from the part number by something other than a sequence.
|
||||
Here is a bad example that task will misinterpret:
|
||||
</p>
|
||||
|
||||
<pre><code>% task 3 4-123 is back-ordered, try again next week</code></pre>
|
||||
|
||||
<p>
|
||||
The intent here is that task 3 have its description modified to be
|
||||
"40123 is back-ordered, try again next week", but will be
|
||||
misinterpreted as tasks 3, 4, 5, 6 ... 123 will all be modified
|
||||
to have the description "is back-ordered, try again next week".
|
||||
The solution is to quote the whole description:
|
||||
</p>
|
||||
|
||||
<pre><code>% task 3 "4-123 is back-ordered, try again next week"</code></pre>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<div class="content">
|
||||
<p>
|
||||
Copyright 2006-2009, P. Beckingham. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td align="right" valign="top" width="200px">
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<script type="text/javascript"><!--
|
||||
google_ad_client = "pub-9709799404235424";
|
||||
/* Task Main */
|
||||
google_ad_slot = "8660617875";
|
||||
google_ad_width = 120;
|
||||
google_ad_height = 600;
|
||||
//-->
|
||||
</script>
|
||||
<script type="text/javascript"
|
||||
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
|
||||
</script>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
|
||||
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
var pageTracker = _gat._getTracker("UA-4737637-1");
|
||||
pageTracker._initData();
|
||||
pageTracker._trackPageview();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -20,10 +20,9 @@
|
||||
<a href="shell.html">Shell</a>
|
||||
<a href="config.html">Configuration</a>
|
||||
<a href="color.html">Colors</a>
|
||||
<a href="usage.html">Usage</a>
|
||||
<a href="recur.html">Recurrence</a>
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="troubleshooting.html">Troubleshooting</a>
|
||||
<a href="faq.html">FAQ</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
@@ -40,10 +39,10 @@
|
||||
</p>
|
||||
|
||||
<pre><code>% ls
|
||||
task-1.4.1.tar.gz
|
||||
% gunzip task-1.4.1.tar.gz
|
||||
% tar xf task-1.4.1.tar
|
||||
% cd task-1.4.1
|
||||
task-1.6.0.tar.gz
|
||||
% gunzip task-1.6.0.tar.gz
|
||||
% tar xf task-1.6.0.tar
|
||||
% cd task-1.6.0
|
||||
% ./configure
|
||||
...
|
||||
% make
|
||||
@@ -90,7 +89,7 @@ Done.
|
||||
<br />
|
||||
<div class="content">
|
||||
<p>
|
||||
Copyright 2006-2008, P. Beckingham. All rights reserved.
|
||||
Copyright 2006-2009, P. Beckingham. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -20,10 +20,9 @@
|
||||
<a href="shell.html">Shell</a>
|
||||
<a href="config.html">Configuration</a>
|
||||
<a href="color.html">Colors</a>
|
||||
<a href="usage.html">Usage</a>
|
||||
<a href="recur.html">Recurrence</a>
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="troubleshooting.html">Troubleshooting</a>
|
||||
<a href="faq.html">FAQ</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
@@ -43,7 +42,7 @@
|
||||
<p>
|
||||
This means there is always a current version of the task
|
||||
report kept in a text file. Products such as
|
||||
<a href="www.samurize.com">Samurize</a>,
|
||||
<a href="http://www.samurize.com">Samurize</a>,
|
||||
<a href="http://www.mulle-kybernetik.com/software/MkConsole/">MkConsole</a>,
|
||||
or
|
||||
<a href="http://projects.tynsoe.org/en/geektool/">GeekTool</a>
|
||||
@@ -53,15 +52,18 @@
|
||||
|
||||
<p>
|
||||
To use a shadow file, edit your .taskrc configuration file,
|
||||
and add two entries as shown:
|
||||
and add three entries as shown:
|
||||
</p>
|
||||
|
||||
<pre><code>shadow.file=/path/to/file
|
||||
shadow.command=list pri:H</code></pre>
|
||||
shadow.command=list pri:H
|
||||
shadow.notify=on</code></pre>
|
||||
|
||||
<p>
|
||||
In this example the shadow file contains a report equivalent
|
||||
to running "task list pri:H".
|
||||
to running "task list pri:H". Note that the third entry
|
||||
causes a message to be displayed whenever task updates the
|
||||
shadow file. It is optional.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -75,7 +77,7 @@ shadow.command=list pri:H</code></pre>
|
||||
<br />
|
||||
<div class="content">
|
||||
<p>
|
||||
Copyright 2006-2008, P. Beckingham. All rights reserved.
|
||||
Copyright 2006-2009, P. Beckingham. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -20,10 +20,9 @@
|
||||
<a href="shell.html">Shell</a>
|
||||
<a href="config.html">Configuration</a>
|
||||
<a href="color.html">Colors</a>
|
||||
<a href="usage.html">Usage</a>
|
||||
<a href="recur.html">Recurrence</a>
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="troubleshooting.html">Troubleshooting</a>
|
||||
<a href="faq.html">FAQ</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
@@ -80,7 +79,7 @@
|
||||
<br />
|
||||
<div class="content">
|
||||
<p>
|
||||
Copyright 2006-2008, P. Beckingham. All rights reserved.
|
||||
Copyright 2006-2009, P. Beckingham. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -20,10 +20,9 @@
|
||||
<a href="shell.html">Shell</a>
|
||||
<a href="config.html">Configuration</a>
|
||||
<a href="color.html">Colors</a>
|
||||
<a href="usage.html">Usage</a>
|
||||
<a href="recur.html">Recurrence</a>
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="troubleshooting.html">Troubleshooting</a>
|
||||
<a href="faq.html">FAQ</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
@@ -305,7 +304,7 @@ ID Project Pri Due Active Age Description
|
||||
<br />
|
||||
<div class="content">
|
||||
<p>
|
||||
Copyright 2006-2008, P. Beckingham. All rights reserved.
|
||||
Copyright 2006-2009, P. Beckingham. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -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 Usage</title>
|
||||
<title>Tab Completion</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<link rel="stylesheet" href="task.css" type="text/css" />
|
||||
</head>
|
||||
@@ -20,10 +20,9 @@
|
||||
<a href="shell.html">Shell</a>
|
||||
<a href="config.html">Configuration</a>
|
||||
<a href="color.html">Colors</a>
|
||||
<a href="usage.html">Usage</a>
|
||||
<a href="recur.html">Recurrence</a>
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="troubleshooting.html">Troubleshooting</a>
|
||||
<a href="faq.html">FAQ</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
@@ -32,68 +31,32 @@
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<h2 class="title"><a name="usage">Command Usage<a></h2>
|
||||
<h2 class="title"><a name="simple">Tab Completion</a></h2>
|
||||
<div class="content">
|
||||
<pre><code>task add [tags] [attrs] desc...
|
||||
task list [tags] [attrs] desc...
|
||||
task long [tags] [attrs] desc...
|
||||
task ls [tags] [attrs] desc...
|
||||
task completed [tags] [attrs] desc...
|
||||
task ID [tags] [attrs] ["desc..."]
|
||||
task ID /from/to/
|
||||
task delete ID
|
||||
task undelete ID
|
||||
task info ID
|
||||
task start ID
|
||||
task stop ID
|
||||
task done ID
|
||||
task undo ID
|
||||
task projects
|
||||
task tags
|
||||
task summary
|
||||
task history
|
||||
task ghistory
|
||||
task next
|
||||
task calendar
|
||||
task active
|
||||
task overdue
|
||||
task oldest
|
||||
task newest
|
||||
task stats
|
||||
task export
|
||||
task color
|
||||
task version
|
||||
<p>
|
||||
There is a Bash tab completion script distributed with task,
|
||||
called task_completion.sh.
|
||||
</p>
|
||||
|
||||
ID is the numeric identifier displayed by the 'task list' command
|
||||
<p>
|
||||
To install it, copy it to your
|
||||
|
||||
Tags are arbitrary words, any quantity:
|
||||
+tag The + means add the tag
|
||||
-tag The - means remove the tag
|
||||
<code>/etc/bash_completion.d</code>
|
||||
|
||||
Attributes are:
|
||||
project: Project name
|
||||
priority: Priority
|
||||
due: Due date
|
||||
fg: Foreground color
|
||||
bg: Background color
|
||||
directory (in case you want to have it available system-wide)
|
||||
and then
|
||||
|
||||
Any command or attribute name may be abbreviated if still unique:
|
||||
task list project:Home
|
||||
task li pro:Home
|
||||
<pre><code>source /etc/bash_completion</code></pre>
|
||||
|
||||
Some task descriptions need to be escaped because of the shell:
|
||||
task add "quoted ' quote"
|
||||
task add escaped \' quote
|
||||
|
||||
Many characters have special meaning to the shell, including:
|
||||
$ ! ' " ( ) ; \ ` * ? { } [ ] < > | & % # ~</code></pre>
|
||||
<div>
|
||||
or source it from your home directory's bashrc files.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<div class="content">
|
||||
<p>
|
||||
Copyright 2006-2008, P. Beckingham. All rights reserved.
|
||||
Copyright 2006-2009, P. Beckingham. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
146
html/task.html
146
html/task.html
@@ -20,10 +20,9 @@
|
||||
<a href="shell.html">Shell</a>
|
||||
<a href="config.html">Configuration</a>
|
||||
<a href="color.html">Colors</a>
|
||||
<a href="usage.html">Usage</a>
|
||||
<a href="recur.html">Recurrence</a>
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="troubleshooting.html">Troubleshooting</a>
|
||||
<a href="faq.html">FAQ</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
@@ -50,13 +49,17 @@
|
||||
<li><a href="shell.html">Interacting with the Shell</a>
|
||||
<li><a href="config.html">Configuring Task</a>
|
||||
<li><a href="color.html">Color</a>
|
||||
<li><a href="usage.html">Task Command Usage</a>
|
||||
<li><a href="recur.html">Recurring Tasks</a>
|
||||
<li><a href="date.html">Date Handling</a>
|
||||
<li><a href="troubleshooting.html">Troubleshooting</a>
|
||||
<li><a href="versions.html">Old Versions</a>
|
||||
<li><a href="filter.html">Filters</a>
|
||||
<li><a href="shadow.html">Shadow Files</a>
|
||||
<li><a href="custom.html">Custom Reports</a>
|
||||
<li><a href="import.html">Data Import</a>
|
||||
<li><a href="faq.html">Frequently Asked Questions</a>
|
||||
<li><a href="sequence.html">ID Sequences</a>
|
||||
<li><a href="tab_completion.html">Tab Completion</a>
|
||||
<li><a href="git.html">How to use git and contribute to task</a>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
@@ -69,41 +72,113 @@
|
||||
which illustrates many of task's features.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For the latest news, discussion of proposed task features, and
|
||||
somewhere to voice your opinions, join us at
|
||||
<a href="http://groups.google.com/group/taskprogram">http://groups.google.com/group/taskprogram</a>.
|
||||
|
||||
<table border=0 style="background-color: #fff; padding: 5px;" cellspacing=0>
|
||||
<tr>
|
||||
<td>
|
||||
<img src="http://groups.google.com/groups/img/3nb/groups_bar.gif"
|
||||
height=26 width=132 alt="Google Groups">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding-left: 5px">
|
||||
<b>Subscribe to taskprogram</b>
|
||||
</td>
|
||||
</tr>
|
||||
<form action="http://groups.google.com/group/taskprogram/boxsubscribe">
|
||||
<tr>
|
||||
<td style="padding-left: 5px;">
|
||||
Email:
|
||||
<input type=text name=email>
|
||||
<input type=submit name="sub" value="Subscribe">
|
||||
</td>
|
||||
</tr>
|
||||
</form>
|
||||
<tr>
|
||||
<td align=right>
|
||||
<a href="http://groups.google.com/group/taskprogram">Visit this group</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</p>
|
||||
|
||||
<br />
|
||||
<h2 class="title">Get the Latest Release</h2>
|
||||
<h2 class="title">Get the Latest Stable Release</h2>
|
||||
|
||||
<div class="content">
|
||||
<table>
|
||||
<tr>
|
||||
<td>Source:</td>
|
||||
<td><a href="http://www.beckingham.net/task-1.5.0.tar.gz">task-1.5.0.tar.gz</a></td>
|
||||
<td><a href="http://www.beckingham.net/task-1.7.0.tar.gz">task-1.7.0.tar.gz</a></td>
|
||||
</tr>
|
||||
<!--
|
||||
<tr>
|
||||
<td>Mac OS X 10.5 (Leopard) Intel-only:</td>
|
||||
<td><a href="http://www.beckingham.net/task-1.5.0.pkg">task-1.5.0.pkg</a></td>
|
||||
<td><a href="http://www.beckingham.net/task-1.7.0.pkg">task-1.7.0.pkg</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Debian package:
|
||||
(Thanks to <a href="http://blog.rfquerin.org">Richard Querin</a>):
|
||||
Debian:
|
||||
(Thanks to <a href="http://blog.rfquerin.org">Richard Querin</a>):
|
||||
</td>
|
||||
<td><a href="http://www.beckingham.net/task_1.5.0-1_i386.deb">task_1.5.0-1_i386.deb</a></td>
|
||||
<td><a href="http://www.beckingham.net/task_1.7.0-1_i386.deb">task_1.7.0-1_i386.deb</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Red Hat:
|
||||
(Thanks to <a href="http://www.ultrafredde.com">Federico Hernandez</a>):
|
||||
</td>
|
||||
<td><a href="http://www.beckingham.net/task-1.7.0-1.FC10.i386.rpm">task-1.7.0-1.FC10.i386.rpm</a></td>
|
||||
</tr>
|
||||
-->
|
||||
<tr>
|
||||
<td>Git - get the whole source and history:</td>
|
||||
<td><a href="http://github.com/pbeckingham/task">http://github.com/pbeckingham/task</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h4>New in version 1.5.0 (?)</h4>
|
||||
<h4>New in version 1.7.0 (5/14/2009)</h4>
|
||||
<ul>
|
||||
<li>Removed deprecated TUTORIAL file.
|
||||
<li>Removed support for the "showage" configuration variable.
|
||||
<li>"task stop" can remove the start time from a started task.
|
||||
<li>"task ghistory" now displays a differently aligned graph, allowing
|
||||
easier comparison by month of tasks added versus completed and deleted.
|
||||
<li>"task version" command now reports unrecognized configuration variables,
|
||||
which may be spelling mistakes or deprecated variables.
|
||||
<li>"configure --enable-debug" now supported to suppress compiler optimization
|
||||
to allow debugging.
|
||||
<li>Improved the errors when parsing a corrupt or unrecognized pending.data
|
||||
or completed.data file (thanks to T. Charles Yun).
|
||||
<li>Added details to the "info" report about recurring tasks (thanks to T.
|
||||
Charles Yun).
|
||||
<li>Now writes a sample "defaultwidth" configuration variable to the default
|
||||
.taskrc file (thanks to T. Charles Yun).
|
||||
<li>Task allows commands that require an ID to now be given a sequence, which
|
||||
is a set of IDs. This allows commands like "task delete 1 2 5-10,12".
|
||||
<li>Fixed bug in the ghistory report, which caused it to only show a new
|
||||
month if a task was added during that month.
|
||||
<li>New command "duplicate" which allows an existing task to be duplicated,
|
||||
and also have modifications applied (thanks to David J Patrick).
|
||||
<li>The "append", and "done" commands now allow modifications to be applied
|
||||
to the task(s) (thanks to David J Patrick).
|
||||
<li>Improved word wrapping in various output.
|
||||
<li>Fixed bug that added an extra line between header and graph in the
|
||||
ghistory report.
|
||||
<li>Added simple 'taskprogram' mailing list subscribe form to the web site.
|
||||
<li>For custom reports that define a "limit" to the number of rows of output
|
||||
such as "oldest" and "newest", task allows an override value. For
|
||||
example "task oldest 5" will display the 5 oldest tasks.
|
||||
<li>Modified the "stats" report so that it has the same aesthetics as the
|
||||
other reports.
|
||||
<li>New "timesheet" command displays tasks completed and started, per week,
|
||||
and can display multiple weeks.
|
||||
<li>New tab completion script, task_completion.sh, for bash users, is installed
|
||||
to /usr/local/share/task (thanks to Federico Hernandez).
|
||||
<li>Applied patch to allow task to build on Arch Linux (thanks to Johan Friis).
|
||||
<li>Applied patch to fix a UUID bug on Solaris 8 (thanks to Steven de Brouwer).
|
||||
<li>The task man page is now installed. Try "man task" (thanks to Federico
|
||||
Hernandez and P.C. Shyamshankar).
|
||||
<li>Fixed bug that causes task to create a default .task directory, even if
|
||||
data.location specified otherwise (thanks to Federico Hernandez).
|
||||
<li>New "edit" command that fires up a text editor (uses 'editor' configuration
|
||||
variable, $VISUAL or $EDITOR environment variable) and allows direct
|
||||
editing of all editable task details.
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
@@ -115,16 +190,23 @@
|
||||
Task has been built from source and tested in the following environments:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>OS X 10.4 Tiger
|
||||
<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
|
||||
</ul>
|
||||
<p>
|
||||
<ul>
|
||||
<li>OS X 10.4 Tiger
|
||||
<li>OS X 10.5 Leopard
|
||||
<li>Fedora Core 8
|
||||
<li>Fedora Core 9
|
||||
<li>Fedora Core 10
|
||||
<li>Ubuntu 7 Feisty Fawn
|
||||
<li>Ubuntu 8 Hardy Heron
|
||||
<li>Ubuntu 8.10 Intrepid Ibex
|
||||
<li>Ubuntu 9.04 Jaunty Jackalope
|
||||
<li>Arch Linux
|
||||
<li>Solaris 8
|
||||
<li>Solaris 10
|
||||
<li>Cygwin 1.5.25-14
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If you have difficulties building task, have found a bug, have a
|
||||
@@ -133,7 +215,7 @@
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Take a look at the <a href="troubleshooting.html">troubleshooting guide</a>
|
||||
Take a look at the <a href="faq.html">FAQ</a>
|
||||
for tips and workarounds to problems.
|
||||
</p>
|
||||
|
||||
@@ -143,7 +225,7 @@
|
||||
<br />
|
||||
<div class="content">
|
||||
<p>
|
||||
Copyright 2006-2008, P. Beckingham. All rights reserved.
|
||||
Copyright 2006-2009, P. Beckingham. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,138 +0,0 @@
|
||||
<!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 Troubleshooting Guide</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<link rel="stylesheet" href="task.css" type="text/css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<div id="toolbar">
|
||||
<a href="task.html">Home</a>
|
||||
<a href="setup.html">Setup</a>
|
||||
<a href="30second.html">30-second Tutorial</a>
|
||||
<a href="simple.html">Simple</a>
|
||||
<a href="advanced.html">Advanced</a>
|
||||
<a href="shell.html">Shell</a>
|
||||
<a href="config.html">Configuration</a>
|
||||
<a href="color.html">Colors</a>
|
||||
<a href="usage.html">Usage</a>
|
||||
<a href="recur.html">Recurrence</a>
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="troubleshooting.html">Troubleshooting</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<h1 class="title">Task Troubleshooting Guide</h1>
|
||||
<p>
|
||||
Here you will find tips and suggestions for making task behave
|
||||
properly, and bug workarounds.
|
||||
</p>
|
||||
|
||||
<br />
|
||||
<h2 class="title">Segmentation Fault for certain commands</h2>
|
||||
<div class="content">
|
||||
<p>
|
||||
Upgrading task to version 1.1.0, 1.2.0 and 1.3.0 can cause
|
||||
segmentation faults. This is mostly occurring for Ubuntu users,
|
||||
although there is no reason for it to be limited to Ubuntu.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Task 1.3.1 fixes this bug, but there is a workaround for users
|
||||
of earlier versions. Add the following line to your ~/.taskrc
|
||||
file:
|
||||
</p>
|
||||
|
||||
<code><pre>dateformat=m/d/Y</pre></code>
|
||||
|
||||
<p class="small">
|
||||
The "dateformat" setting is supported in task 1.1.0 and later.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<h2 class="title">How do I build task under Cygwin?</h2>
|
||||
<div class="content">
|
||||
<p>
|
||||
Task is built the same way everywhere. But under Cygwin, you'll
|
||||
need to make sure you have the following packages available
|
||||
first:
|
||||
|
||||
<ul>
|
||||
<li>gcc
|
||||
<li>make
|
||||
<li>libncurses-devel
|
||||
<li>libncurses8
|
||||
</ul>
|
||||
|
||||
The gcc and make packages allow you to compile the code, and
|
||||
are therefore required, but the ncurses packages are optional.
|
||||
Ncurses will allow task to determine the width of the window, and
|
||||
therefore use the whole width and wrap text accordingly, for a
|
||||
more aesthetically pleasing display.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<div class="content">
|
||||
<p>
|
||||
Copyright 2006-2008, P. Beckingham. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td align="right" valign="top" width="200px">
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<script type="text/javascript"><!--
|
||||
google_ad_client = "pub-9709799404235424";
|
||||
/* Task Main */
|
||||
google_ad_slot = "8660617875";
|
||||
google_ad_width = 120;
|
||||
google_ad_height = 600;
|
||||
//-->
|
||||
</script>
|
||||
<script type="text/javascript"
|
||||
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
|
||||
</script>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
|
||||
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
var pageTracker = _gat._getTracker("UA-4737637-1");
|
||||
pageTracker._initData();
|
||||
pageTracker._trackPageview();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -20,10 +20,9 @@
|
||||
<a href="shell.html">Shell</a>
|
||||
<a href="config.html">Configuration</a>
|
||||
<a href="color.html">Colors</a>
|
||||
<a href="usage.html">Usage</a>
|
||||
<a href="recur.html">Recurrence</a>
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="troubleshooting.html">Troubleshooting</a>
|
||||
<a href="faq.html">FAQ</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
@@ -36,6 +35,192 @@
|
||||
<br />
|
||||
|
||||
<div class="content">
|
||||
<h4>New in version 1.6.1 (4/24/2009)</h4>
|
||||
<p>
|
||||
<table>
|
||||
<tr>
|
||||
<td>Source:</td>
|
||||
<td><a href="http://www.beckingham.net/task-1.6.1.tar.gz">task-1.6.1.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.6.1.pkg">task-1.6.1.pkg</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Debian:
|
||||
(Thanks to <a href="http://blog.rfquerin.org">Richard Querin</a>):
|
||||
</td>
|
||||
<td><a href="http://www.beckingham.net/task_1.6.1-1_i386.deb">task_1.6.1-1_i386.deb</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Red Hat:
|
||||
(Thanks to <a href="http://www.ultrafredde.com">Federico Hernandez</a>):
|
||||
</td>
|
||||
<td><a href="http://www.beckingham.net/task-1.6.1-1.FC10.i386.rpm">task-1.6.1-1.FC10.i386.rpm</a></td>
|
||||
</tr>
|
||||
-->
|
||||
<tr>
|
||||
<td>Git - get the whole source and history:</td>
|
||||
<td><a href="http://github.com/pbeckingham/task">http://github.com/pbeckingham/task</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<ul>
|
||||
<li>Fixed bug that caused new, first-time .taskrc files to be written without
|
||||
including the custom report labels (thanks to P.C. Shyamshankar).
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h4>New in version 1.6.0 (4/13/2009)</h4>
|
||||
<p>
|
||||
<table>
|
||||
<tr>
|
||||
<td>Source:</td>
|
||||
<td><a href="http://www.beckingham.net/task-1.6.0.tar.gz">task-1.6.0.tar.gz</a></td>
|
||||
</tr>
|
||||
<!--
|
||||
<tr>
|
||||
<td>Mac OS X 10.5 (Leopard) Intel-only:</td>
|
||||
<td><a href="http://www.beckingham.net/task-1.6.0.pkg">task-1.6.0.pkg</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Debian:
|
||||
(Thanks to <a href="http://blog.rfquerin.org">Richard Querin</a>):
|
||||
</td>
|
||||
<td><a href="http://www.beckingham.net/task_1.6.0-1_i386.deb">task_1.6.0-1_i386.deb</a></td>
|
||||
</tr>
|
||||
-->
|
||||
<tr>
|
||||
<td>
|
||||
Red Hat:
|
||||
(Thanks to <a href="http://www.ultrafredde.com">Federico Hernandez</a>):
|
||||
</td>
|
||||
<td><a href="http://www.beckingham.net/task-1.6.0-1.FC10.i386.rpm">task-1.6.0-1.FC10.i386.rpm</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Git - get the whole source and history:</td>
|
||||
<td><a href="http://github.com/pbeckingham/task">http://github.com/pbeckingham/task</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<ul>
|
||||
<li>Added support for new "append" command that adds more description text to
|
||||
an existing task.
|
||||
<li>Added support for the "weekdays" recurrence, which means a task can recur
|
||||
five times a week, and not on weekends (thanks to Chris Pride).
|
||||
<li>UTF8 text is now supported in task project names, tags and descriptions.
|
||||
<li>Fixed bug that caused the y/n confirmation on task deletion to ignore the
|
||||
Enter key and fail to re-prompt (thanks to Bruce Dillahunty).
|
||||
<li>When the "echo.command" configuration variable is set to "yes", it causes
|
||||
commands that modify tasks to display which task was affected (thanks to
|
||||
Bruce Dillahunty).
|
||||
<li>A task can now be annotated with the command "task <id> annotate ...", and
|
||||
a timestamped annotation will appear in reports.
|
||||
<li>A 'description_only' column is now available for use in custom reports,
|
||||
and it excludes annotations.
|
||||
<li>A task can now be upgraded to a recurring task by adding a recurrence
|
||||
frequency, a due date, and an optional until date.
|
||||
<li>When a recurring task is modified, all other instances of the recurring
|
||||
task are also modified.
|
||||
<li>Custom reports now support user-specified column labels (thanks to T.
|
||||
Charles Yun).
|
||||
<li>Task can now import tasks from a variety of data formats, including task
|
||||
export files from versions 1.4.3 and earlier, versions 1.5.0 and later,
|
||||
todo.sh 2.x, CSV, plain text and task command line. See online docs for
|
||||
full details.
|
||||
<li>Export was including 'id' in the column header even though it was not
|
||||
included in the data.
|
||||
<li>The task file format has changed slightly. Please back up your task
|
||||
data files before upgrading to 1.6.0.
|
||||
<li>Added new column 'recurrence_indicator' that displays an 'R' if the task
|
||||
is a recurring task. This column can be added to any custom report.
|
||||
<li>Added new column 'tag_indicator' that displays a '+' if the task
|
||||
has any tags. This column can be added to any custom report.
|
||||
<li>Fixed bug where sometimes a task description was concatenated oddly if
|
||||
there was a colon somewhere in the description.
|
||||
<li>Fixed bug that caused recurring annual tasks to exhibit a creeping due
|
||||
date, because of an assumption of 365 days per year, which failed to
|
||||
consider leap years (thanks to T. Charles Yun).
|
||||
<li>Annotations can now be modified with the substitution commands /from/to/.
|
||||
<li>Substitutions can now be made global with /from/to/g and all occurrences
|
||||
of "from" will be replaced with "to".
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<h4>New in version 1.5.0 (3/15/2009)</h4>
|
||||
<table>
|
||||
<tr>
|
||||
<td>Source:</td>
|
||||
<td><a href="http://www.beckingham.net/task-1.5.0.tar.gz">task-1.5.0.tar.gz</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mac OS X 10.5 (Leopard) Intel-only:</td>
|
||||
<td><a href="http://www.beckingham.net/task-1.5.0.pkg">task-1.5.0.pkg</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Debian:
|
||||
(Thanks to <a href="http://blog.rfquerin.org">Richard Querin</a>):
|
||||
</td>
|
||||
<td><a href="http://www.beckingham.net/task_1.5.0-1_i386.deb">task_1.5.0-1_i386.deb</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Red Hat:
|
||||
(Thanks to <a href="http://www.ultrafredde.com">Federico Hernandez</a>):
|
||||
</td>
|
||||
<td><a href="http://www.beckingham.net/task-1.5.0-1.i386.rpm">task-1.5.0-1.i386.rpm</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<ul>
|
||||
<li>Removed deprecated TUTORIAL file.
|
||||
<li>Removed support for the "showage" configuration variable.
|
||||
<li>"task stop" can remove the start time from a started task.
|
||||
<li>"task ghistory" now displays a differently aligned graph, allowing
|
||||
easier comparison by month of tasks added versus completed and deleted.
|
||||
<li>"task version" command now reports unrecognized configuration variables,
|
||||
which may be spelling mistakes or deprecated variables.
|
||||
<li>"configure --enable-debug" now supported to suppress compiler optimization
|
||||
to allow debugging.
|
||||
<li>Allow lower case priorities, and automatically upper case them.
|
||||
<li>Added support for "due" configuration variable which defines the number
|
||||
of days in the future when a task is considered due.
|
||||
<li>Added support for custom reports, comprised of a set of column names and
|
||||
sort order, with optional filtering in the configuration file. This
|
||||
means user-defined reports can be written, and the reports currently
|
||||
in the configuration file can be renamed. Several of task's built in
|
||||
reports have been converted to user-defined reports.
|
||||
<li>New online documentation for custom reports.
|
||||
<li>New algorithm for determining when the "nag" message is displayed.
|
||||
<li>Fixed bug where task hangs with a certain combination of recurring tasks
|
||||
and shadow files.
|
||||
<li>Fixed bug with the task sort algorithm, which led to an unstable sequence
|
||||
when there were only a handful of tasks.
|
||||
<li>Performance enhanced by eliminating unnecessary sorting.
|
||||
<li>Task now has a large (and growing) test suite and bug regression tests
|
||||
to help ensure higher quality releases.
|
||||
<li>Fixed bug that caused large performance hit during table rendering.
|
||||
<li>Fixed bug that concatenated a modified description without spaces.
|
||||
<li>Added new column 'recur' that displays the recurrence period of any
|
||||
recurring tasks. This column can be added to any custom report.
|
||||
<li>Added support for "color.recurring" configuration variable which
|
||||
specifies the color of recurring tasks.
|
||||
<li>Added support for "locking" configuration variable that controls whether
|
||||
file locking is used.
|
||||
<li>Task export feature now includes recurrence information, removes nested
|
||||
quotes, and limits output to pending tasks.
|
||||
<li>Task no longer includes deleted tasks in the summary report (thanks to
|
||||
Benjamin Tegarden).
|
||||
<li>Fixed bug that prevented the summary report from properly reporting
|
||||
recently completed tasks.
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<h4>New in version 1.4.3 (11/1/2008)</h4>
|
||||
<a href="http://www.beckingham.net/task-1.4.3.tar.gz">task-1.4.3.tar.gz</a>
|
||||
@@ -47,6 +232,7 @@
|
||||
(Thanks to <a href="http://blog.rfquerin.org">Richard Querin</a>)
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<ul>
|
||||
<li>Fixed misleading task count at bottom of "info" report.
|
||||
<li>Added support for a shadow file that contains a plain text task report,
|
||||
@@ -250,7 +436,7 @@
|
||||
<br />
|
||||
<div class="content">
|
||||
<p>
|
||||
Copyright 2006-2008, P. Beckingham. All rights reserved.
|
||||
Copyright 2006-2009, P. Beckingham. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
92
script.txt
92
script.txt
@@ -1,105 +1,109 @@
|
||||
Hello, and welcome to this quick demo of the task program.
|
||||
Hello, and welcome to this quick demo of the task program.
|
||||
|
||||
task add do laundry Let's add some tasks
|
||||
I need to do laundry
|
||||
task add do laundry Let's add some tasks
|
||||
I need to do laundry
|
||||
|
||||
task add project:garage order dumpster Oh yeah, the dumpster
|
||||
task add project:garage order dumpster Oh yeah, I need to order the dumpster
|
||||
|
||||
task add +phone tell mom i loveher Must call Mom (that "phone" there is a tag - they are
|
||||
useful for searching, categorizing)
|
||||
task add +phone tell mom i loveher Must call Mom (that "phone" there is a tag - they can
|
||||
be useful for searching and categorizing)
|
||||
task add +phone pro:garage schedule
|
||||
goodwill pickup
|
||||
|
||||
task ad +email pro:garage ask Tom if Notice I can abbreviating commands
|
||||
task ad +email pro:garage ask Tom if Notice I can abbreviate commands
|
||||
he wants that old bkie
|
||||
|
||||
task ls Let's see what we've got
|
||||
I spelled bike wrong
|
||||
task ls Let's see what we've got
|
||||
Oh, I spelled bike wrong
|
||||
|
||||
task 5 /bkie/bike/
|
||||
task ls That's better
|
||||
task ls That's better
|
||||
|
||||
task 1 pro:home Let's assign projects
|
||||
task 1 pro:home Let's assign projects
|
||||
task 3 pro:home tell mom I love her
|
||||
task ls pro:garage
|
||||
|
||||
task long pro:garage Let's see all the columns
|
||||
task long pro:garage Let's see all the columns
|
||||
|
||||
task list pro:garage There are different ways to list
|
||||
task list pro:garage There are different ways to list
|
||||
|
||||
task lis +phone By tag
|
||||
task li pro:garage +phone By project and tag
|
||||
task l mom By word
|
||||
task lis +phone By tag
|
||||
task li pro:garage +phone By project and tag
|
||||
task l mom By word
|
||||
|
||||
task 1 priority:H Priorities can be High, Medium or Low
|
||||
task 1 priority:H Priorities can be High, Medium or Low
|
||||
task pri:H 3
|
||||
task 1 pri:M
|
||||
task li The list is sorted by priority.
|
||||
task li The list is sorted by priority.
|
||||
|
||||
task 2 pri:L
|
||||
task li
|
||||
|
||||
task done 3 Suppose task 3 is done
|
||||
task li ...and it's gone
|
||||
task done 3 Suppose task 3 is done
|
||||
task li ...and it's gone
|
||||
|
||||
task 2 +phone +mistake Lets add tags
|
||||
task 2 +phone +mistake Lets add tags
|
||||
|
||||
# Oops!
|
||||
task 2 -mistake or remove tags
|
||||
task 2 -mistake or remove tags
|
||||
|
||||
task tags or look at all the tags
|
||||
task tags or look at all the tags
|
||||
|
||||
task info 2 or all the details
|
||||
task info 2 or all the details
|
||||
|
||||
task projects or all the projects
|
||||
task projects or all the projects
|
||||
|
||||
task 3 fg:bold Let's make it colorful
|
||||
task 3 fg:bold Let's make it colorful
|
||||
task 4 fg:bold_green
|
||||
task li
|
||||
task 3 fg:bold_underline_white
|
||||
task li
|
||||
|
||||
task 4 bg:on_bright_red fg:bold_yellow
|
||||
task li Oh that's just nasty - let's get rid of that.
|
||||
task li Oh that's just nasty - let's get rid of that.
|
||||
task 4 bg:
|
||||
task li
|
||||
task 4 fg:
|
||||
task 3 fg:
|
||||
|
||||
task colors There are many combinations to choose from
|
||||
task colors There are many combinations to choose from
|
||||
|
||||
(Slashes!!!)
|
||||
task 1 due:6/8/2008 Let's add a due date
|
||||
task 1 due:6/8/2008 Let's add a due date
|
||||
date
|
||||
|
||||
task li
|
||||
task calendar Notice the due task is in yellow, today is marked cyan
|
||||
task calendar Notice the due task is in yellow, today is marked cyan
|
||||
|
||||
task 1 due:5/20/2008 This is now an overdue task
|
||||
task li and it shows up red
|
||||
task 1 due:5/20/2008 This is now an overdue task
|
||||
task li and it shows up red
|
||||
task overdue
|
||||
task cal
|
||||
|
||||
task export file.csv You can export the tasks to a spreadsheet
|
||||
task export file.csv You can export the tasks to a spreadsheet
|
||||
cat file.csv
|
||||
|
||||
task start 1 Started tasks can be used as reminders
|
||||
of what you are supposed to be doing
|
||||
task start 1 Started tasks can be used as reminders
|
||||
of what you are supposed to be doing
|
||||
|
||||
task active They show up as active
|
||||
task done 1 Let's clear out a couple
|
||||
task active They show up as active
|
||||
task done 1 Let's clear out a couple
|
||||
task li
|
||||
task done 3
|
||||
task active
|
||||
|
||||
task summary Summary shows progress on all projects
|
||||
task summary Summary shows progress on all projects
|
||||
|
||||
task history History shows general activity - how many added,
|
||||
completed etc, by month
|
||||
task history History shows general activity - how many added,
|
||||
completed etc, by month
|
||||
|
||||
And that's it. There are more commands than this
|
||||
covered in the online documentation, but this should give
|
||||
the basic idea.
|
||||
task ghistory This report shows a histogram of tasks that were
|
||||
added (in red), completed (in green) and deleted
|
||||
(in yellow), all by month.
|
||||
|
||||
Thank you for watching.
|
||||
And that's it. There are more commands than this
|
||||
covered in the online documentation, but this should give
|
||||
the basic idea.
|
||||
|
||||
Thank you for watching.
|
||||
|
||||
|
||||
110
src/Config.cpp
110
src/Config.cpp
@@ -1,7 +1,7 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2008, Paul Beckingham.
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -36,8 +36,40 @@
|
||||
#include "Config.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// These are default (but overridable) reports. These entries are necessary
|
||||
// because these three reports were converted from hard-coded reports to custom
|
||||
// reports, and therefore need these config file entries. However, users are
|
||||
// already used to seeing these five reports, but do not have these entries.
|
||||
// The choice was a) make users edit their .taskrc files, b) write a .taskrc
|
||||
// upgrade program to make the change, or c) this.
|
||||
Config::Config ()
|
||||
{
|
||||
(*this)["report.long.description"] = "Lists all task, all data, matching the specified criteria";
|
||||
(*this)["report.long.columns"] = "id,project,priority,entry,start,due,recur,age,tags,description";
|
||||
(*this)["report.long.labels"] = "ID,Project,Pri,Added,Started,Due,Recur,Age,Tags,Description";
|
||||
(*this)["report.long.sort"] = "due+,priority-,project+";
|
||||
|
||||
(*this)["report.list.description"] = "Lists all tasks matching the specified criteria";
|
||||
(*this)["report.list.columns"] = "id,project,priority,due,active,age,description";
|
||||
(*this)["report.list.labels"] = "ID,Project,Pri,Due,Active,Age,Description";
|
||||
(*this)["report.list.sort"] = "due+,priority-,project+";
|
||||
|
||||
(*this)["report.ls.description"] = "Minimal listing of all tasks matching the specified criteria";
|
||||
(*this)["report.ls.columns"] = "id,project,priority,description";
|
||||
(*this)["report.ls.labels"] = "ID,Project,Pri,Description";
|
||||
(*this)["report.ls.sort"] = "priority-,project+";
|
||||
|
||||
(*this)["report.newest.description"] = "Shows the newest tasks";
|
||||
(*this)["report.newest.columns"] = "id,project,priority,due,active,age,description";
|
||||
(*this)["report.newest.labels"] = "ID,Project,Pri,Due,Active,Age,Description";
|
||||
(*this)["report.newest.sort"] = "id-";
|
||||
(*this)["report.newest.limit"] = "10";
|
||||
|
||||
(*this)["report.oldest.description"] = "Shows the oldest tasks";
|
||||
(*this)["report.oldest.columns"] = "id,project,priority,due,active,age,description";
|
||||
(*this)["report.oldest.labels"] = "ID,Project,Pri,Due,Active,Age,Description";
|
||||
(*this)["report.oldest.sort"] = "id+";
|
||||
(*this)["report.oldest.limit"] = "10";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -47,9 +79,9 @@ Config::Config (const std::string& file)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Read the Configuration filee and populate the *this map. The file format
|
||||
// is simply lines with name=value pairs. Whitespace between name, = and value
|
||||
// is not tolerated, but blank lines and comments starting with # are allowed.
|
||||
// Read the Configuration file and populate the *this map. The file format is
|
||||
// simply lines with name=value pairs. Whitespace between name, = and value is
|
||||
// not tolerated, but blank lines and comments starting with # are allowed.
|
||||
bool Config::load (const std::string& file)
|
||||
{
|
||||
std::ifstream in;
|
||||
@@ -113,26 +145,71 @@ void Config::createDefault (const std::string& home)
|
||||
{
|
||||
fprintf (out, "data.location=%s\n", dataDir.c_str ());
|
||||
fprintf (out, "confirmation=yes\n");
|
||||
fprintf (out, "echo.command=yes\n");
|
||||
fprintf (out, "next=2\n");
|
||||
fprintf (out, "dateformat=m/d/Y\n");
|
||||
fprintf (out, "monthsperline=1\n");
|
||||
fprintf (out, "#monthsperline=2\n");
|
||||
fprintf (out, "#defaultwidth=80\n");
|
||||
fprintf (out, "curses=on\n");
|
||||
fprintf (out, "color=on\n");
|
||||
fprintf (out, "due=7\n");
|
||||
fprintf (out, "nag=You have higher priority tasks.\n");
|
||||
fprintf (out, "locking=on\n");
|
||||
fprintf (out, "#editor=vi\n");
|
||||
|
||||
fprintf (out, "color.overdue=bold_red\n");
|
||||
fprintf (out, "#color.due=on_bright_yellow\n");
|
||||
fprintf (out, "#color.pri.H=on_red\n");
|
||||
fprintf (out, "color.due=bold_yellow\n");
|
||||
fprintf (out, "color.pri.H=bold\n");
|
||||
fprintf (out, "#color.pri.M=on_yellow\n");
|
||||
fprintf (out, "#color.pri.L=on_green\n");
|
||||
fprintf (out, "#color.pri.none=white on_blue\n");
|
||||
fprintf (out, "color.active=bold_cyan\n");
|
||||
fprintf (out, "color.tagged=yellow\n");
|
||||
fprintf (out, "#color.tag.bug=yellow\n");
|
||||
fprintf (out, "#color.project.home=on_green\n");
|
||||
fprintf (out, "#color.project.garden=on_green\n");
|
||||
fprintf (out, "#color.keyword.car=on_blue\n");
|
||||
fprintf (out, "#color.recurring=on_red\n");
|
||||
fprintf (out, "#shadow.file=%s/shadow.txt\n", dataDir.c_str ());
|
||||
fprintf (out, "#shadow.command=list\n");
|
||||
fprintf (out, "#shadow.notify=on\n");
|
||||
fprintf (out, "#default.command=list\n");
|
||||
fprintf (out, "#default.project=foo\n");
|
||||
fprintf (out, "#default.priority=M\n");
|
||||
fprintf (out, "default.command=list\n");
|
||||
|
||||
// Custom reports.
|
||||
fprintf (out, "# Fields: id,uuid,project,priority,entry,start,due,recur,age,active,tags,description\n");
|
||||
fprintf (out, "# description_only\n");
|
||||
fprintf (out, "# Description: This report is ...\n");
|
||||
fprintf (out, "# Sort: due+,priority-,project+\n");
|
||||
fprintf (out, "# Filter: pro:x pri:H +bug\n");
|
||||
fprintf (out, "# Limit: 10\n");
|
||||
|
||||
fprintf (out, "report.long.description=Lists all task, all data, matching the specified criteria\n");
|
||||
fprintf (out, "report.long.labels=ID,Project,Pri,Added,Started,Due,Recur,Age,Tags,Description\n");
|
||||
fprintf (out, "report.long.columns=id,project,priority,entry,start,due,recur,age,tags,description\n");
|
||||
fprintf (out, "report.long.sort=due+,priority-,project+\n");
|
||||
|
||||
fprintf (out, "report.list.description=Lists all tasks matching the specified criteria\n");
|
||||
fprintf (out, "report.list.labels=ID,Project,Pri,Due,Active,Age,Description\n");
|
||||
fprintf (out, "report.list.columns=id,project,priority,due,active,age,description\n");
|
||||
fprintf (out, "report.list.sort=due+,priority-,project+\n");
|
||||
|
||||
fprintf (out, "report.ls.description=Minimal listing of all tasks matching the specified criteria\n");
|
||||
fprintf (out, "report.ls.labels=ID,Project,Pri,Description\n");
|
||||
fprintf (out, "report.ls.columns=id,project,priority,description\n");
|
||||
fprintf (out, "report.ls.sort=priority-,project+\n");
|
||||
|
||||
fprintf (out, "report.newest.description=Shows the newest tasks\n");
|
||||
fprintf (out, "report.newest.labels=ID,Project,Pri,Due,Active,Age,Description\n");
|
||||
fprintf (out, "report.newest.columns=id,project,priority,due,active,age,description\n");
|
||||
fprintf (out, "report.newest.sort=id-\n");
|
||||
fprintf (out, "report.newest.limit=10\n");
|
||||
|
||||
fprintf (out, "report.oldest.description=Shows the oldest tasks\n");
|
||||
fprintf (out, "report.oldest.labels=ID,Project,Pri,Due,Active,Age,Description\n");
|
||||
fprintf (out, "report.oldest.columns=id,project,priority,due,active,age,description\n");
|
||||
fprintf (out, "report.oldest.sort=id+\n");
|
||||
fprintf (out, "report.oldest.limit=10\n");
|
||||
|
||||
fclose (out);
|
||||
|
||||
@@ -143,6 +220,9 @@ void Config::createDefault (const std::string& home)
|
||||
|
||||
this->load (rcFile);
|
||||
|
||||
// Get the data.location value from the (potentially newly created) .taskrc
|
||||
// file.
|
||||
dataDir = this->get ("data.location", dataDir);
|
||||
if (-1 == access (dataDir.c_str (), F_OK))
|
||||
mkdir (dataDir.c_str (), S_IRWXU);
|
||||
}
|
||||
@@ -191,11 +271,13 @@ bool Config::get (const std::string& key, bool default_value)
|
||||
{
|
||||
std::string value = lowerCase ((*this)[key]);
|
||||
|
||||
if (value == "t" ||
|
||||
value == "true" ||
|
||||
value == "1" ||
|
||||
value == "yes" ||
|
||||
value == "on")
|
||||
if (value == "t" ||
|
||||
value == "true" ||
|
||||
value == "1" ||
|
||||
value == "yes" ||
|
||||
value == "on" ||
|
||||
value == "enable" ||
|
||||
value == "enabled")
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2008, Paul Beckingham.
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2008, Paul Beckingham.
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2008, Paul Beckingham.
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -27,6 +27,7 @@
|
||||
#ifndef INCLUDED_DATE
|
||||
#define INCLUDED_DATE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
class Date;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2008, Paul Beckingham.
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -60,6 +60,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <iostream>
|
||||
#include <stdlib.h>
|
||||
#include <Grid.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -325,7 +326,7 @@ Grid::Cell::operator int () const
|
||||
case CELL_INT: return mInt;
|
||||
case CELL_FLOAT: return (int) mFloat;
|
||||
case CELL_DOUBLE: return (int) mDouble;
|
||||
case CELL_STRING: return mString.length ();
|
||||
case CELL_STRING: return ::atoi (mString.c_str ());
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -340,7 +341,7 @@ Grid::Cell::operator float () const
|
||||
case CELL_INT: return (float) mInt;
|
||||
case CELL_FLOAT: return mFloat;
|
||||
case CELL_DOUBLE: return (float) mDouble;
|
||||
case CELL_STRING: return (float) mString.length ();
|
||||
case CELL_STRING: return (float) ::atof (mString.c_str ());
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
@@ -355,7 +356,7 @@ Grid::Cell::operator double () const
|
||||
case CELL_INT: return (double) mInt;
|
||||
case CELL_FLOAT: return (double) mFloat;
|
||||
case CELL_DOUBLE: return mDouble;
|
||||
case CELL_STRING: return (double) mString.length ();
|
||||
case CELL_STRING: return (double) ::atof (mString.c_str ());
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2008, Paul Beckingham.
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -27,6 +27,7 @@
|
||||
#ifndef INCLUDED_GRID
|
||||
#define INCLUDED_GRID
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
bin_PROGRAMS = task
|
||||
task_SOURCES = Config.cpp Date.cpp T.cpp TDB.cpp Table.cpp Grid.cpp color.cpp parse.cpp task.cpp command.cpp report.cpp util.cpp text.cpp rules.cpp Config.h Date.h T.h TDB.h Table.h Grid.h color.h task.h
|
||||
task_SOURCES = Config.cpp Date.cpp T.cpp TDB.cpp Table.cpp Grid.cpp Timer.cpp color.cpp parse.cpp task.cpp command.cpp edit.cpp report.cpp util.cpp text.cpp rules.cpp import.cpp Config.h Date.h T.h TDB.h Table.h Grid.h Timer.h color.h task.h
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Makefile.in generated by automake 1.10 from Makefile.am.
|
||||
# Makefile.in generated by automake 1.10.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
@@ -44,12 +44,13 @@ am__installdirs = "$(DESTDIR)$(bindir)"
|
||||
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
|
||||
PROGRAMS = $(bin_PROGRAMS)
|
||||
am_task_OBJECTS = Config.$(OBJEXT) Date.$(OBJEXT) T.$(OBJEXT) \
|
||||
TDB.$(OBJEXT) Table.$(OBJEXT) Grid.$(OBJEXT) color.$(OBJEXT) \
|
||||
parse.$(OBJEXT) task.$(OBJEXT) command.$(OBJEXT) \
|
||||
report.$(OBJEXT) util.$(OBJEXT) text.$(OBJEXT) rules.$(OBJEXT)
|
||||
TDB.$(OBJEXT) Table.$(OBJEXT) Grid.$(OBJEXT) Timer.$(OBJEXT) \
|
||||
color.$(OBJEXT) parse.$(OBJEXT) task.$(OBJEXT) \
|
||||
command.$(OBJEXT) edit.$(OBJEXT) report.$(OBJEXT) \
|
||||
util.$(OBJEXT) text.$(OBJEXT) rules.$(OBJEXT) import.$(OBJEXT)
|
||||
task_OBJECTS = $(am_task_OBJECTS)
|
||||
task_LDADD = $(LDADD)
|
||||
DEFAULT_INCLUDES = -I. -I$(top_builddir)@am__isrc@
|
||||
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
|
||||
@@ -152,9 +153,10 @@ sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
task_SOURCES = Config.cpp Date.cpp T.cpp TDB.cpp Table.cpp Grid.cpp color.cpp parse.cpp task.cpp command.cpp report.cpp util.cpp text.cpp rules.cpp Config.h Date.h T.h TDB.h Table.h Grid.h color.h task.h
|
||||
task_SOURCES = Config.cpp Date.cpp T.cpp TDB.cpp Table.cpp Grid.cpp Timer.cpp color.cpp parse.cpp task.cpp command.cpp edit.cpp report.cpp util.cpp text.cpp rules.cpp import.cpp Config.h Date.h T.h TDB.h Table.h Grid.h Timer.h color.h task.h
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
@@ -227,8 +229,11 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/T.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TDB.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Table.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Timer.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/color.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/command.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/edit.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/import.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/report.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rules.Po@am__quote@
|
||||
@@ -255,8 +260,8 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
$(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
mkid -fID $$unique
|
||||
tags: TAGS
|
||||
|
||||
@@ -268,8 +273,8 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
@@ -279,13 +284,12 @@ ctags: CTAGS
|
||||
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$tags $$unique
|
||||
|
||||
270
src/T.cpp
270
src/T.cpp
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2008, Paul Beckingham.
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -25,6 +25,7 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include "task.h"
|
||||
#include "T.h"
|
||||
@@ -36,9 +37,14 @@ T::T ()
|
||||
mUUID = uuid ();
|
||||
mStatus = pending;
|
||||
mId = 0;
|
||||
mSequence.clear ();
|
||||
mTags.clear ();
|
||||
mAttributes.clear ();
|
||||
mDescription = "";
|
||||
mFrom = "";
|
||||
mTo = "";
|
||||
mGlobal = false;
|
||||
mAnnotations.clear ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -54,10 +60,12 @@ T::T (const T& other)
|
||||
mStatus = other.mStatus;
|
||||
mUUID = other.mUUID;
|
||||
mId = other.mId;
|
||||
mSequence = other.mSequence;
|
||||
mDescription = other.mDescription;
|
||||
mTags = other.mTags;
|
||||
mRemoveTags = other.mRemoveTags;
|
||||
mAttributes = other.mAttributes;
|
||||
mAnnotations = other.mAnnotations;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -68,10 +76,12 @@ T& T::operator= (const T& other)
|
||||
mStatus = other.mStatus;
|
||||
mUUID = other.mUUID;
|
||||
mId = other.mId;
|
||||
mSequence = other.mSequence;
|
||||
mDescription = other.mDescription;
|
||||
mTags = other.mTags;
|
||||
mRemoveTags = other.mRemoveTags;
|
||||
mAttributes = other.mAttributes;
|
||||
mAnnotations = other.mAnnotations;
|
||||
}
|
||||
|
||||
return *this;
|
||||
@@ -109,6 +119,12 @@ void T::addRemoveTag (const std::string& tag)
|
||||
mRemoveTags.push_back (tag);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int T::getTagCount () const
|
||||
{
|
||||
return mTags.size ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void T::getTags (std::vector<std::string>& all) const
|
||||
{
|
||||
@@ -230,21 +246,61 @@ void T::removeAttribute (const std::string& name)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void T::getSubstitution (std::string& from, std::string& to) const
|
||||
void T::getSubstitution (
|
||||
std::string& from,
|
||||
std::string& to,
|
||||
bool& global) const
|
||||
{
|
||||
from = mFrom;
|
||||
to = mTo;
|
||||
from = mFrom;
|
||||
to = mTo;
|
||||
global = mGlobal;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void T::setSubstitution (const std::string& from, const std::string& to)
|
||||
void T::setSubstitution (
|
||||
const std::string& from,
|
||||
const std::string& to,
|
||||
bool global)
|
||||
{
|
||||
mFrom = from;
|
||||
mTo = to;
|
||||
mFrom = from;
|
||||
mTo = to;
|
||||
mGlobal = global;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// uuid status [tags] [attributes] description
|
||||
void T::getAnnotations (std::map <time_t, std::string>& all) const
|
||||
{
|
||||
all = mAnnotations;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void T::setAnnotations (const std::map <time_t, std::string>& all)
|
||||
{
|
||||
mAnnotations = all;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void T::addAnnotation (const std::string& description)
|
||||
{
|
||||
std::string sanitized = description;
|
||||
std::replace (sanitized.begin (), sanitized.end (), '"', '\'');
|
||||
std::replace (sanitized.begin (), sanitized.end (), '[', '(');
|
||||
std::replace (sanitized.begin (), sanitized.end (), ']', ')');
|
||||
mAnnotations[time (NULL)] = sanitized;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool T::sequenceContains (int id) const
|
||||
{
|
||||
foreach (seq, mSequence)
|
||||
if (*seq == id)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// uuid status [tags] [attributes] [annotations] description
|
||||
//
|
||||
// uuid \x{8}-\x{4}-\x{4}-\x{4}-\x{12}
|
||||
// status - + X r
|
||||
@@ -282,10 +338,26 @@ const std::string T::compose () const
|
||||
++count;
|
||||
}
|
||||
|
||||
line += "] ";
|
||||
line += "] [";
|
||||
|
||||
// Annotations
|
||||
std::stringstream annotation;
|
||||
bool first = true;
|
||||
foreach (note, mAnnotations)
|
||||
{
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
annotation << " ";
|
||||
|
||||
annotation << note->first << ":\"" << note->second << "\"";
|
||||
}
|
||||
line += annotation.str () + "] ";
|
||||
|
||||
// Description
|
||||
line += mDescription;
|
||||
|
||||
// EOL
|
||||
line += "\n";
|
||||
|
||||
if (line.length () > T_LINE_MAX)
|
||||
@@ -328,6 +400,11 @@ const std::string T::composeCSV ()
|
||||
line += value;
|
||||
line += ",";
|
||||
|
||||
value = mAttributes["recur"];
|
||||
if (value != "")
|
||||
line += value;
|
||||
line += ",";
|
||||
|
||||
value = mAttributes["end"];
|
||||
if (value != "")
|
||||
line += value;
|
||||
@@ -353,7 +430,11 @@ const std::string T::composeCSV ()
|
||||
line += "'" + value + "'";
|
||||
line += ",";
|
||||
|
||||
line += "'" + mDescription + "'\n";
|
||||
// Convert single quotes to double quotes, because single quotes are used to
|
||||
// delimit the values that need it.
|
||||
std::string clean = mDescription;
|
||||
std::replace (clean.begin (), clean.end (), '\'', '"');
|
||||
line += "'" + clean + "'\n";
|
||||
|
||||
return line;
|
||||
}
|
||||
@@ -412,10 +493,12 @@ void T::parse (const std::string& line)
|
||||
}
|
||||
else
|
||||
throw std::string ("Line too short");
|
||||
|
||||
mAnnotations.clear ();
|
||||
}
|
||||
break;
|
||||
|
||||
// File format version 2, from 2008.1.1
|
||||
// File format version 2, from 2008.1.1 - 2009.3.23
|
||||
case 2:
|
||||
{
|
||||
if (line.length () > 46) // ^.{36} . \[\] \[\] \n
|
||||
@@ -437,24 +520,24 @@ void T::parse (const std::string& line)
|
||||
if (openAttrBracket != std::string::npos &&
|
||||
closeAttrBracket != std::string::npos)
|
||||
{
|
||||
std::string tags = line.substr (
|
||||
openTagBracket + 1, closeTagBracket - openTagBracket - 1);
|
||||
std::vector <std::string> rawTags;
|
||||
split (mTags, tags, ' ');
|
||||
std::string tags = line.substr (
|
||||
openTagBracket + 1, closeTagBracket - openTagBracket - 1);
|
||||
std::vector <std::string> rawTags;
|
||||
split (mTags, tags, ' ');
|
||||
|
||||
std::string attributes = line.substr (
|
||||
openAttrBracket + 1, closeAttrBracket - openAttrBracket - 1);
|
||||
std::vector <std::string> pairs;
|
||||
split (pairs, attributes, ' ');
|
||||
for (size_t i = 0; i < pairs.size (); ++i)
|
||||
{
|
||||
std::vector <std::string> pair;
|
||||
split (pair, pairs[i], ':');
|
||||
if (pair.size () == 2)
|
||||
mAttributes[pair[0]] = pair[1];
|
||||
}
|
||||
std::string attributes = line.substr (
|
||||
openAttrBracket + 1, closeAttrBracket - openAttrBracket - 1);
|
||||
std::vector <std::string> pairs;
|
||||
split (pairs, attributes, ' ');
|
||||
for (size_t i = 0; i < pairs.size (); ++i)
|
||||
{
|
||||
std::vector <std::string> pair;
|
||||
split (pair, pairs[i], ':');
|
||||
if (pair.size () == 2)
|
||||
mAttributes[pair[0]] = pair[1];
|
||||
}
|
||||
|
||||
mDescription = line.substr (closeAttrBracket + 2, std::string::npos);
|
||||
mDescription = line.substr (closeAttrBracket + 2, std::string::npos);
|
||||
}
|
||||
else
|
||||
throw std::string ("Missing attribute brackets");
|
||||
@@ -464,11 +547,112 @@ void T::parse (const std::string& line)
|
||||
}
|
||||
else
|
||||
throw std::string ("Line too short");
|
||||
|
||||
mAnnotations.clear ();
|
||||
}
|
||||
break;
|
||||
|
||||
// File format version 3, from 2009.3.23
|
||||
case 3:
|
||||
{
|
||||
if (line.length () > 49) // ^.{36} . \[\] \[\] \[\] \n
|
||||
{
|
||||
mUUID = line.substr (0, 36);
|
||||
|
||||
mStatus = line[37] == '+' ? completed
|
||||
: line[37] == 'X' ? deleted
|
||||
: line[37] == 'r' ? recurring
|
||||
: pending;
|
||||
|
||||
size_t openTagBracket = line.find ("[");
|
||||
size_t closeTagBracket = line.find ("]", openTagBracket);
|
||||
if (openTagBracket != std::string::npos &&
|
||||
closeTagBracket != std::string::npos)
|
||||
{
|
||||
size_t openAttrBracket = line.find ("[", closeTagBracket);
|
||||
size_t closeAttrBracket = line.find ("]", openAttrBracket);
|
||||
if (openAttrBracket != std::string::npos &&
|
||||
closeAttrBracket != std::string::npos)
|
||||
{
|
||||
size_t openAnnoBracket = line.find ("[", closeAttrBracket);
|
||||
size_t closeAnnoBracket = line.find ("]", openAnnoBracket);
|
||||
if (openAnnoBracket != std::string::npos &&
|
||||
closeAnnoBracket != std::string::npos)
|
||||
{
|
||||
std::string tags = line.substr (
|
||||
openTagBracket + 1, closeTagBracket - openTagBracket - 1);
|
||||
std::vector <std::string> rawTags;
|
||||
split (mTags, tags, ' ');
|
||||
|
||||
std::string attributes = line.substr (
|
||||
openAttrBracket + 1, closeAttrBracket - openAttrBracket - 1);
|
||||
std::vector <std::string> pairs;
|
||||
split (pairs, attributes, ' ');
|
||||
|
||||
for (size_t i = 0; i < pairs.size (); ++i)
|
||||
{
|
||||
std::vector <std::string> pair;
|
||||
split (pair, pairs[i], ':');
|
||||
if (pair.size () == 2)
|
||||
mAttributes[pair[0]] = pair[1];
|
||||
}
|
||||
|
||||
// Extract and split the annotations, which are of the form:
|
||||
// 1234:"..." 5678:"..."
|
||||
std::string annotations = line.substr (
|
||||
openAnnoBracket + 1, closeAnnoBracket - openAnnoBracket - 1);
|
||||
pairs.clear ();
|
||||
|
||||
std::string::size_type start = 0;
|
||||
std::string::size_type end = 0;
|
||||
do
|
||||
{
|
||||
end = annotations.find ('"', start);
|
||||
if (end != std::string::npos)
|
||||
{
|
||||
end = annotations.find ('"', end + 1);
|
||||
|
||||
if (start != std::string::npos &&
|
||||
end != std::string::npos)
|
||||
{
|
||||
pairs.push_back (annotations.substr (start, end - start + 1));
|
||||
start = end + 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (start != std::string::npos &&
|
||||
end != std::string::npos);
|
||||
|
||||
for (size_t i = 0; i < pairs.size (); ++i)
|
||||
{
|
||||
std::string pair = pairs[i];
|
||||
std::string::size_type colon = pair.find (":");
|
||||
if (colon != std::string::npos)
|
||||
{
|
||||
std::string name = pair.substr (0, colon);
|
||||
std::string value = pair.substr (colon + 2, pair.length () - colon - 3);
|
||||
mAnnotations[::atoi (name.c_str ())] = value;
|
||||
}
|
||||
}
|
||||
|
||||
mDescription = line.substr (closeAnnoBracket + 2, std::string::npos);
|
||||
}
|
||||
else
|
||||
throw std::string ("Missing annotation brackets.");
|
||||
}
|
||||
else
|
||||
throw std::string ("Missing attribute brackets.");
|
||||
}
|
||||
else
|
||||
throw std::string ("Missing tag brackets.");
|
||||
}
|
||||
else
|
||||
throw std::string ("Line too short.");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw std::string ();
|
||||
throw std::string ("Unrecognized task file format.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -503,16 +687,31 @@ int T::determineVersion (const std::string& line)
|
||||
line[23] == '-' &&
|
||||
line[36] == ' ' &&
|
||||
(line[37] == '-' || line[37] == '+' || line[37] == 'X' || line[37] == 'r'))
|
||||
return 2;
|
||||
{
|
||||
// Version 3 looks like:
|
||||
//
|
||||
// uuid status [tags] [attributes] [annotations] description\n
|
||||
//
|
||||
// Scan for the number of [] pairs.
|
||||
std::string::size_type tagAtts = line.find ("] [", 0);
|
||||
std::string::size_type attsAnno = line.find ("] [", tagAtts + 1);
|
||||
std::string::size_type annoDesc = line.find ("] ", attsAnno + 1);
|
||||
if (tagAtts != std::string::npos &&
|
||||
attsAnno != std::string::npos &&
|
||||
annoDesc != std::string::npos)
|
||||
return 3;
|
||||
else
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Version 3?
|
||||
// Version 4?
|
||||
//
|
||||
// Fortunately, with the hindsight that will come with version 3, the
|
||||
// identifying characteristics of 1 and 2 may be modified such that if 3 has
|
||||
// a UUID followed by a status, then there is still a way to differentiate
|
||||
// between 2 and 3.
|
||||
// Fortunately, with the hindsight that will come with version 4, the
|
||||
// identifying characteristics of 1, 2 and 3 may be modified such that if 4
|
||||
// has a UUID followed by a status, then there is still a way to differentiate
|
||||
// between 2, 3 and 4.
|
||||
//
|
||||
// The danger is that a version 2 binary reads and misinterprets a version 3
|
||||
// The danger is that a version 3 binary reads and misinterprets a version 4
|
||||
// file. This is why it is a good idea to rely on an explicit version
|
||||
// declaration rather than chance positioning.
|
||||
|
||||
@@ -525,6 +724,7 @@ int T::determineVersion (const std::string& line)
|
||||
bool T::validate () const
|
||||
{
|
||||
// TODO Verify until > due
|
||||
// TODO Verify entry < until, due, start, end
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
21
src/T.h
21
src/T.h
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2008, Paul Beckingham.
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -49,22 +49,26 @@ public:
|
||||
void setUUID (const std::string& uuid) { mUUID = uuid; }
|
||||
|
||||
int getId () const { return mId; }
|
||||
void setId (int id) { mId = id; }
|
||||
void setId (int id) { mId = id; mSequence.push_back (id); }
|
||||
std::vector <int> getAllIds () const { return mSequence; }
|
||||
void addId (int id) { if (mId == 0) mId = id; mSequence.push_back (id); }
|
||||
|
||||
status getStatus () const { return mStatus; }
|
||||
void setStatus (status s) { mStatus = s; }
|
||||
|
||||
const std::string getDescription () const { return mDescription; }
|
||||
void setDescription (const std::string& description) { mDescription = description; }
|
||||
int getAnnotationCount () const { return mAnnotations.size (); }
|
||||
|
||||
void getSubstitution (std::string&, std::string&) const;
|
||||
void setSubstitution (const std::string&, const std::string&);
|
||||
void getSubstitution (std::string&, std::string&, bool&) const;
|
||||
void setSubstitution (const std::string&, const std::string&, bool);
|
||||
|
||||
bool hasTag (const std::string&) const;
|
||||
|
||||
void getRemoveTags (std::vector<std::string>&); // SPECIAL
|
||||
void addRemoveTag (const std::string&); // SPECIAL
|
||||
|
||||
int getTagCount () const;
|
||||
void getTags (std::vector<std::string>&) const;
|
||||
void addTag (const std::string&);
|
||||
void addTags (const std::vector <std::string>&);
|
||||
@@ -77,6 +81,11 @@ public:
|
||||
void removeAttribute (const std::string&);
|
||||
void removeAttributes ();
|
||||
|
||||
void getAnnotations (std::map <time_t, std::string>&) const;
|
||||
void setAnnotations (const std::map <time_t, std::string>&);
|
||||
void addAnnotation (const std::string&);
|
||||
bool sequenceContains (int) const;
|
||||
|
||||
const std::string compose () const;
|
||||
const std::string composeCSV ();
|
||||
void parse (const std::string&);
|
||||
@@ -89,13 +98,15 @@ private:
|
||||
status mStatus;
|
||||
std::string mUUID;
|
||||
int mId;
|
||||
std::vector <int> mSequence;
|
||||
std::string mDescription;
|
||||
std::vector<std::string> mTags;
|
||||
std::vector<std::string> mRemoveTags;
|
||||
std::map<std::string, std::string> mAttributes;
|
||||
|
||||
std::string mFrom;
|
||||
std::string mTo;
|
||||
bool mGlobal;
|
||||
std::map <time_t, std::string> mAnnotations;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
189
src/TDB.cpp
189
src/TDB.cpp
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2008, Paul Beckingham.
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -26,6 +26,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <sys/file.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
@@ -38,6 +39,7 @@ TDB::TDB ()
|
||||
: mPendingFile ("")
|
||||
, mCompletedFile ("")
|
||||
, mId (1)
|
||||
, mNoLock (false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -103,13 +105,27 @@ bool TDB::pendingT (std::vector <T>& all)
|
||||
{
|
||||
mId = 1;
|
||||
|
||||
int line = 1;
|
||||
std::vector <std::string>::iterator it;
|
||||
for (it = lines.begin (); it != lines.end (); ++it)
|
||||
{
|
||||
T t (*it);
|
||||
t.setId (mId++);
|
||||
if (t.getStatus () == T::pending)
|
||||
all.push_back (t);
|
||||
try
|
||||
{
|
||||
T t (*it);
|
||||
t.setId (mId++);
|
||||
if (t.getStatus () == T::pending)
|
||||
all.push_back (t);
|
||||
}
|
||||
|
||||
catch (std::string& e)
|
||||
{
|
||||
std::stringstream more;
|
||||
more << " Line " << line << ", in " << "pending.data";
|
||||
|
||||
throw e + more.str ();
|
||||
}
|
||||
|
||||
++line;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -129,12 +145,26 @@ bool TDB::allPendingT (std::vector <T>& all)
|
||||
{
|
||||
mId = 1;
|
||||
|
||||
int line = 1;
|
||||
std::vector <std::string>::iterator it;
|
||||
for (it = lines.begin (); it != lines.end (); ++it)
|
||||
{
|
||||
T t (*it);
|
||||
t.setId (mId++);
|
||||
all.push_back (t);
|
||||
try
|
||||
{
|
||||
T t (*it);
|
||||
t.setId (mId++);
|
||||
all.push_back (t);
|
||||
}
|
||||
|
||||
catch (std::string& e)
|
||||
{
|
||||
std::stringstream more;
|
||||
more << " Line " << line << ", in " << "pending.data";
|
||||
|
||||
throw e + more.str ();
|
||||
}
|
||||
|
||||
++line;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -151,12 +181,26 @@ bool TDB::completedT (std::vector <T>& all) const
|
||||
std::vector <std::string> lines;
|
||||
if (readLockedFile (mCompletedFile, lines))
|
||||
{
|
||||
int line = 1;
|
||||
std::vector <std::string>::iterator it;
|
||||
for (it = lines.begin (); it != lines.end (); ++it)
|
||||
{
|
||||
T t (*it);
|
||||
if (t.getStatus () != T::deleted)
|
||||
all.push_back (t);
|
||||
try
|
||||
{
|
||||
T t (*it);
|
||||
if (t.getStatus () != T::deleted)
|
||||
all.push_back (t);
|
||||
}
|
||||
|
||||
catch (std::string& e)
|
||||
{
|
||||
std::stringstream more;
|
||||
more << " Line " << line << ", in " << "pending.data";
|
||||
|
||||
throw e + more.str ();
|
||||
}
|
||||
|
||||
++line;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -173,11 +217,25 @@ bool TDB::allCompletedT (std::vector <T>& all) const
|
||||
std::vector <std::string> lines;
|
||||
if (readLockedFile (mCompletedFile, lines))
|
||||
{
|
||||
int line = 1;
|
||||
std::vector <std::string>::iterator it;
|
||||
for (it = lines.begin (); it != lines.end (); ++it)
|
||||
{
|
||||
T t (*it);
|
||||
all.push_back (t);
|
||||
try
|
||||
{
|
||||
T t (*it);
|
||||
all.push_back (t);
|
||||
}
|
||||
|
||||
catch (std::string& e)
|
||||
{
|
||||
std::stringstream more;
|
||||
more << " Line " << line << ", in " << "pending.data";
|
||||
|
||||
throw e + more.str ();
|
||||
}
|
||||
|
||||
++line;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -186,54 +244,6 @@ bool TDB::allCompletedT (std::vector <T>& all) const
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool TDB::deleteT (const T& t)
|
||||
{
|
||||
T task (t);
|
||||
|
||||
std::vector <T> all;
|
||||
allPendingT (all);
|
||||
|
||||
std::vector <T>::iterator it;
|
||||
for (it = all.begin (); it != all.end (); ++it)
|
||||
if (task.getId () == it->getId ())
|
||||
{
|
||||
it->setStatus (T::deleted);
|
||||
|
||||
char endTime[16];
|
||||
sprintf (endTime, "%u", (unsigned int) time (NULL));
|
||||
it->setAttribute ("end", endTime);
|
||||
|
||||
return overwritePending (all);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool TDB::completeT (const T& t)
|
||||
{
|
||||
T task (t);
|
||||
|
||||
std::vector <T> all;
|
||||
allPendingT (all);
|
||||
|
||||
std::vector <T>::iterator it;
|
||||
for (it = all.begin (); it != all.end (); ++it)
|
||||
if (task.getId () == it->getId ())
|
||||
{
|
||||
it->setStatus (T::completed);
|
||||
|
||||
char endTime[16];
|
||||
sprintf (endTime, "%u", (unsigned int) time (NULL));
|
||||
it->setAttribute ("end", endTime);
|
||||
|
||||
return overwritePending (all);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool TDB::addT (const T& t)
|
||||
{
|
||||
@@ -289,11 +299,10 @@ bool TDB::modifyT (const T& t)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool TDB::lock (FILE* file) const
|
||||
{
|
||||
#ifdef HAVE_FLOCK
|
||||
if (mNoLock)
|
||||
return true;
|
||||
|
||||
return flock (fileno (file), LOCK_EX) ? false : true;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -303,18 +312,16 @@ bool TDB::overwritePending (std::vector <T>& all)
|
||||
FILE* out;
|
||||
if ((out = fopen (mPendingFile.c_str (), "w")))
|
||||
{
|
||||
#ifdef HAVE_FLOCK
|
||||
int retry = 0;
|
||||
while (flock (fileno (out), LOCK_EX) && ++retry <= 3)
|
||||
delay (0.25);
|
||||
#endif
|
||||
if (!mNoLock)
|
||||
while (flock (fileno (out), LOCK_EX) && ++retry <= 3)
|
||||
delay (0.1);
|
||||
|
||||
std::vector <T>::iterator it;
|
||||
for (it = all.begin (); it != all.end (); ++it)
|
||||
fputs (it->compose ().c_str (), out);
|
||||
|
||||
fclose (out);
|
||||
dbChanged ();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -328,16 +335,14 @@ bool TDB::writePending (const T& t)
|
||||
FILE* out;
|
||||
if ((out = fopen (mPendingFile.c_str (), "a")))
|
||||
{
|
||||
#ifdef HAVE_FLOCK
|
||||
int retry = 0;
|
||||
while (flock (fileno (out), LOCK_EX) && ++retry <= 3)
|
||||
delay (0.25);
|
||||
#endif
|
||||
if (!mNoLock)
|
||||
while (flock (fileno (out), LOCK_EX) && ++retry <= 3)
|
||||
delay (0.1);
|
||||
|
||||
fputs (t.compose ().c_str (), out);
|
||||
|
||||
fclose (out);
|
||||
dbChanged ();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -351,17 +356,14 @@ bool TDB::writeCompleted (const T& t)
|
||||
FILE* out;
|
||||
if ((out = fopen (mCompletedFile.c_str (), "a")))
|
||||
{
|
||||
#ifdef HAVE_FLOCK
|
||||
int retry = 0;
|
||||
while (flock (fileno (out), LOCK_EX) && ++retry <= 3)
|
||||
delay (0.25);
|
||||
#endif
|
||||
if (!mNoLock)
|
||||
while (flock (fileno (out), LOCK_EX) && ++retry <= 3)
|
||||
delay (0.1);
|
||||
|
||||
fputs (t.compose ().c_str (), out);
|
||||
|
||||
fclose (out);
|
||||
// Note: No call to dbChanged here because this call never occurs by itself.
|
||||
// It is always accompanied by an overwritePending call.
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -380,11 +382,10 @@ bool TDB::readLockedFile (
|
||||
FILE* in;
|
||||
if ((in = fopen (file.c_str (), "r")))
|
||||
{
|
||||
#ifdef HAVE_FLOCK
|
||||
int retry = 0;
|
||||
while (flock (fileno (in), LOCK_EX) && ++retry <= 3)
|
||||
delay (0.25);
|
||||
#endif
|
||||
if (!mNoLock)
|
||||
while (flock (fileno (in), LOCK_EX) && ++retry <= 3)
|
||||
delay (0.1);
|
||||
|
||||
char line[T_LINE_MAX];
|
||||
while (fgets (line, T_LINE_MAX, in))
|
||||
@@ -406,6 +407,8 @@ bool TDB::readLockedFile (
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Scans the pending tasks for any that are completed or deleted, and if so,
|
||||
// moves them to the completed.data file. Returns a count of tasks moved.
|
||||
int TDB::gc ()
|
||||
{
|
||||
int count = 0;
|
||||
@@ -423,7 +426,9 @@ int TDB::gc ()
|
||||
// Some tasks stay in the pending file.
|
||||
if (it->getStatus () == T::pending ||
|
||||
it->getStatus () == T::recurring)
|
||||
{
|
||||
pending.push_back (*it);
|
||||
}
|
||||
|
||||
// Others are transferred to the completed file.
|
||||
else
|
||||
@@ -448,19 +453,9 @@ int TDB::nextId ()
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TDB::onChange (void (*callback)())
|
||||
void TDB::noLock ()
|
||||
{
|
||||
if (callback)
|
||||
mOnChange.push_back (callback);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Iterate over callbacks.
|
||||
void TDB::dbChanged ()
|
||||
{
|
||||
foreach (i, mOnChange)
|
||||
if (*i)
|
||||
(**i) ();
|
||||
mNoLock = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
10
src/TDB.h
10
src/TDB.h
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2008, Paul Beckingham.
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -43,15 +43,12 @@ public:
|
||||
bool allPendingT (std::vector <T>&);
|
||||
bool completedT (std::vector <T>&) const;
|
||||
bool allCompletedT (std::vector <T>&) const;
|
||||
bool deleteT (const T&);
|
||||
bool completeT (const T&);
|
||||
bool addT (const T&);
|
||||
bool modifyT (const T&);
|
||||
bool logRead (std::vector <std::string>&) const;
|
||||
int gc ();
|
||||
int nextId ();
|
||||
|
||||
void onChange (void (*)());
|
||||
void noLock ();
|
||||
|
||||
private:
|
||||
bool lock (FILE*) const;
|
||||
@@ -59,13 +56,12 @@ private:
|
||||
bool writePending (const T&);
|
||||
bool writeCompleted (const T&);
|
||||
bool readLockedFile (const std::string&, std::vector <std::string>&) const;
|
||||
void dbChanged ();
|
||||
|
||||
private:
|
||||
std::string mPendingFile;
|
||||
std::string mCompletedFile;
|
||||
int mId;
|
||||
std::vector <void (*)()> mOnChange;
|
||||
bool mNoLock;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
215
src/Table.cpp
215
src/Table.cpp
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2008, Paul Beckingham.
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -227,7 +227,7 @@ void Table::setRowBg (const int row, const Text::color c)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::addCell (const int row, const int col, const std::string& data)
|
||||
{
|
||||
int length = 0;
|
||||
unsigned int length = 0;
|
||||
|
||||
if (mSuppressWS)
|
||||
{
|
||||
@@ -238,7 +238,19 @@ void Table::addCell (const int row, const int col, const std::string& data)
|
||||
data2 = data;
|
||||
|
||||
clean (data2);
|
||||
length = data2.length ();
|
||||
// For multi-line cells, find the longest line.
|
||||
if (data2.find ("\n") != std::string::npos)
|
||||
{
|
||||
length = 0;
|
||||
std::vector <std::string> lines;
|
||||
split (lines, data2, "\n");
|
||||
for (unsigned int i = 0; i < lines.size (); ++i)
|
||||
if (lines[i].length () > length)
|
||||
length = lines[i].length ();
|
||||
}
|
||||
else
|
||||
length = data2.length ();
|
||||
|
||||
mData.add (row, col, data2);
|
||||
}
|
||||
else
|
||||
@@ -248,11 +260,22 @@ void Table::addCell (const int row, const int col, const std::string& data)
|
||||
else
|
||||
mData.add (row, col, data);
|
||||
|
||||
length = data.length ();
|
||||
// For multi-line cells, find the longest line.
|
||||
if (data.find ("\n") != std::string::npos)
|
||||
{
|
||||
length = 0;
|
||||
std::vector <std::string> lines;
|
||||
split (lines, data, "\n");
|
||||
for (unsigned int i = 0; i < lines.size (); ++i)
|
||||
if (lines[i].length () > length)
|
||||
length = lines[i].length ();
|
||||
}
|
||||
else
|
||||
length = data.length ();
|
||||
}
|
||||
|
||||
// Automatically maintain max width.
|
||||
mMaxDataWidth[col] = max (mMaxDataWidth[col], length);
|
||||
mMaxDataWidth[col] = max (mMaxDataWidth[col], (int)length);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -508,9 +531,7 @@ void Table::calculateColumnWidths ()
|
||||
}
|
||||
else
|
||||
{
|
||||
// std::cout << "# insufficient room, considering only flexible columns." << std::endl;
|
||||
|
||||
// The fallback position is to assume no width was specificed, and just
|
||||
// The fallback position is to assume no width was specified, and just
|
||||
// calculate widths accordingly.
|
||||
mTableWidth = 0;
|
||||
calculateColumnWidths ();
|
||||
@@ -736,34 +757,105 @@ int Table::columnCount ()
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Removes extraneous output characters, such as:
|
||||
// - spaces followed by a newline is collapsed to just a newline, if there is
|
||||
// no Bg color.
|
||||
// - removal of redundant color codes:
|
||||
// ^[[31mName^[[0m ^[[31mValue^[[0m -> ^[[31mName Value^[[0m
|
||||
//
|
||||
// This method is a work in progress.
|
||||
void Table::optimize (std::string& output)
|
||||
void Table::optimize (std::string& output) const
|
||||
{
|
||||
/*
|
||||
int start = output.length ();
|
||||
*/
|
||||
|
||||
// \s\n -> \n
|
||||
size_t i = 0;
|
||||
while ((i = output.find (" \n")) != std::string::npos)
|
||||
{
|
||||
output = output.substr (0, i) +
|
||||
output.substr (i + 1, std::string::npos);
|
||||
}
|
||||
// int start = output.length ();
|
||||
|
||||
/*
|
||||
std::cout << int ((100 * (start - output.length ()) / start))
|
||||
<< "%" << std::endl;
|
||||
Well, how about that!
|
||||
|
||||
The benchmark.t unit test adds a 1000 tasks, fiddles with some of them, then
|
||||
runs a series of reports. The results are timed, and look like this:
|
||||
|
||||
1000 tasks added in 3 seconds
|
||||
600 tasks altered in 32 seconds
|
||||
'task ls' in 26 seconds
|
||||
'task list' in 17 seconds
|
||||
'task list pri:H' in 19 seconds
|
||||
'task list +tag' in 0 seconds
|
||||
'task list project_A' in 0 seconds
|
||||
'task long' in 29 seconds
|
||||
'task completed' in 2 seconds
|
||||
'task history' in 0 seconds
|
||||
'task ghistory' in 0 seconds
|
||||
|
||||
This performance is terrible. To identify the worst offender, Various Timer
|
||||
objects were added in Table::render, assuming that table sorting is the major
|
||||
bottleneck. But no, it is Table::optimize that is the problem. After
|
||||
commenting out this method, the results are now:
|
||||
|
||||
1000 tasks added in 3 seconds
|
||||
600 tasks altered in 29 seconds
|
||||
'task ls' in 0 seconds
|
||||
'task list' in 0 seconds
|
||||
'task list pri:H' in 1 seconds
|
||||
'task list +tag' in 0 seconds
|
||||
'task list project_A' in 0 seconds
|
||||
'task long' in 0 seconds
|
||||
'task completed' in 0 seconds
|
||||
'task history' in 0 seconds
|
||||
'task ghistory' in 0 seconds
|
||||
|
||||
Much better.
|
||||
*/
|
||||
|
||||
char patterns[5][16] =
|
||||
{
|
||||
" \n",
|
||||
" \n",
|
||||
" \n",
|
||||
" \n",
|
||||
};
|
||||
|
||||
std::string::size_type trailing;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
do
|
||||
{
|
||||
trailing = output.find (patterns[i]);
|
||||
if (trailing != std::string::npos)
|
||||
output.replace (trailing, strlen (patterns[i]), "\n");
|
||||
}
|
||||
while (trailing != std::string::npos);
|
||||
}
|
||||
|
||||
// std::cout << int ((100 * (start - output.length ()) / start))
|
||||
// << "%" << std::endl;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Combsort11, with O(n log n) average, O(n log n) worst case performance.
|
||||
//
|
||||
// function combsort11(array input)
|
||||
// gap := input.size
|
||||
//
|
||||
// loop until gap <= 1 and swaps = 0
|
||||
// if gap > 1
|
||||
// gap := gap / 1.3
|
||||
// if gap = 10 or gap = 9
|
||||
// gap := 11
|
||||
// end if
|
||||
// end if
|
||||
//
|
||||
// i := 0
|
||||
// swaps := 0
|
||||
//
|
||||
// loop until i + gap >= input.size
|
||||
// if input[i] > input[i+gap]
|
||||
// swap(input[i], input[i+gap])
|
||||
// swaps := 1
|
||||
// end if
|
||||
// i := i + 1
|
||||
// end loop
|
||||
//
|
||||
// end loop
|
||||
// end function
|
||||
|
||||
#define SWAP \
|
||||
{ \
|
||||
int temp = order[r]; \
|
||||
@@ -776,7 +868,7 @@ void Table::sort (std::vector <int>& order)
|
||||
int gap = order.size ();
|
||||
int swaps = 1;
|
||||
|
||||
while (gap > 1 || swaps != 0)
|
||||
while (gap > 1 || swaps > 0)
|
||||
{
|
||||
if (gap > 1)
|
||||
{
|
||||
@@ -797,10 +889,28 @@ void Table::sort (std::vector <int>& order)
|
||||
|
||||
Grid::Cell* left = mData.byRow (order[r], mSortColumns[c]);
|
||||
Grid::Cell* right = mData.byRow (order[r + gap], mSortColumns[c]);
|
||||
if (left == NULL && right != NULL)
|
||||
SWAP
|
||||
|
||||
if (left && right && *left != *right)
|
||||
// Data takes precedence over missing data.
|
||||
if (left == NULL && right != NULL)
|
||||
{
|
||||
SWAP
|
||||
break;
|
||||
}
|
||||
|
||||
// No data - try comparing the next column.
|
||||
else if (left == NULL && right == NULL)
|
||||
{
|
||||
keepScanning = true;
|
||||
}
|
||||
|
||||
// Identical data - try comparing the next column.
|
||||
else if (left && right && *left == *right)
|
||||
{
|
||||
keepScanning = true;
|
||||
}
|
||||
|
||||
// Differing data - do a proper comparison.
|
||||
else if (left && right && *left != *right)
|
||||
{
|
||||
switch (mSortOrder[mSortColumns[c]])
|
||||
{
|
||||
@@ -861,24 +971,38 @@ void Table::sort (std::vector <int>& order)
|
||||
break;
|
||||
|
||||
case ascendingPriority:
|
||||
if (((std::string)*left == "" && (std::string)*right != "") ||
|
||||
((std::string)*left == "M" && (std::string)*right == "L") ||
|
||||
((std::string)*left == "H" && ((std::string)*right == "L" || (std::string)*right == "M")))
|
||||
if (((std::string)*left == "" && (std::string)*right != "") ||
|
||||
((std::string)*left == "M" && (std::string)*right == "L") ||
|
||||
((std::string)*left == "H" && ((std::string)*right == "L" || (std::string)*right == "M")))
|
||||
SWAP
|
||||
break;
|
||||
|
||||
case descendingPriority:
|
||||
if (((std::string)*left == "" && (std::string)*right != "") ||
|
||||
if (((std::string)*left == "" && (std::string)*right != "") ||
|
||||
((std::string)*left == "L" && ((std::string)*right == "M" || (std::string)*right == "H")) ||
|
||||
((std::string)*left == "M" && (std::string)*right == "H"))
|
||||
((std::string)*left == "M" && (std::string)*right == "H"))
|
||||
SWAP
|
||||
break;
|
||||
|
||||
case ascendingPeriod:
|
||||
if ((std::string)*left == "" && (std::string)*right != "")
|
||||
break;
|
||||
else if ((std::string)*left != "" && (std::string)*right == "")
|
||||
SWAP
|
||||
else if (convertDuration ((std::string)*left) > convertDuration ((std::string)*right))
|
||||
SWAP
|
||||
break;
|
||||
|
||||
case descendingPeriod:
|
||||
if ((std::string)*left != "" && (std::string)*right == "")
|
||||
break;
|
||||
else if ((std::string)*left == "" && (std::string)*right != "")
|
||||
SWAP
|
||||
else if (convertDuration ((std::string)*left) < convertDuration ((std::string)*right))
|
||||
SWAP
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
keepScanning = true;
|
||||
}
|
||||
|
||||
++r;
|
||||
@@ -912,7 +1036,7 @@ void Table::clean (std::string& value)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const std::string Table::render ()
|
||||
const std::string Table::render (int maximum /* = 0 */)
|
||||
{
|
||||
calculateColumnWidths ();
|
||||
|
||||
@@ -946,8 +1070,14 @@ const std::string Table::render ()
|
||||
if (mSortColumns.size ())
|
||||
sort (order);
|
||||
|
||||
// If a non-zero maximum is specified, then it limits the number of rows of
|
||||
// the table that are rendered.
|
||||
int limit = mRows;
|
||||
if (maximum != 0)
|
||||
limit = min (maximum, mRows);
|
||||
|
||||
// Print all rows.
|
||||
for (int row = 0; row < mRows; ++row)
|
||||
for (int row = 0; row < limit; ++row)
|
||||
{
|
||||
std::vector <std::vector <std::string> > columns;
|
||||
std::vector <std::string> blanks;
|
||||
@@ -981,14 +1111,19 @@ const std::string Table::render ()
|
||||
else
|
||||
output += blanks[col];
|
||||
|
||||
// Trim right.
|
||||
output.erase (output.find_last_not_of (" ") + 1);
|
||||
output += "\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Trim right.
|
||||
output.erase (output.find_last_not_of (" ") + 1);
|
||||
output += "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Eliminate redundant color codes.
|
||||
optimize (output);
|
||||
return output;
|
||||
}
|
||||
|
||||
19
src/Table.h
19
src/Table.h
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2008, Paul Beckingham.
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -37,9 +37,16 @@ class Table
|
||||
{
|
||||
public:
|
||||
enum just {left, center, right};
|
||||
enum order {ascendingNumeric, ascendingCharacter, ascendingPriority,
|
||||
ascendingDate, descendingNumeric, descendingCharacter,
|
||||
descendingPriority, descendingDate};
|
||||
enum order {ascendingNumeric,
|
||||
ascendingCharacter,
|
||||
ascendingPriority,
|
||||
ascendingDate,
|
||||
ascendingPeriod,
|
||||
descendingNumeric,
|
||||
descendingCharacter,
|
||||
descendingPriority,
|
||||
descendingDate,
|
||||
descendingPeriod};
|
||||
enum sizing {minimum = -1, flexible = 0};
|
||||
|
||||
Table ();
|
||||
@@ -84,7 +91,7 @@ public:
|
||||
|
||||
int rowCount ();
|
||||
int columnCount ();
|
||||
const std::string render ();
|
||||
const std::string render (int maximum = 0);
|
||||
|
||||
private:
|
||||
std::string getCell (const int, const int);
|
||||
@@ -101,9 +108,9 @@ private:
|
||||
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>&);
|
||||
void clean (std::string&);
|
||||
void optimize (std::string&) const;
|
||||
|
||||
private:
|
||||
std::vector <std::string> mColumns;
|
||||
|
||||
56
src/Timer.cpp
Normal file
56
src/Timer.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free Software
|
||||
// Foundation; either version 2 of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
// details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program; if not, write to the
|
||||
//
|
||||
// Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor,
|
||||
// Boston, MA
|
||||
// 02110-1301
|
||||
// USA
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <Timer.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Timer starts when the object is constructed.
|
||||
Timer::Timer (const std::string& description)
|
||||
: mDescription (description)
|
||||
{
|
||||
::gettimeofday (&mStart, NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Timer stops when the object is desctructed.
|
||||
Timer::~Timer ()
|
||||
{
|
||||
struct timeval end;
|
||||
::gettimeofday (&end, NULL);
|
||||
|
||||
std::cout << "Timer "
|
||||
<< mDescription
|
||||
<< " "
|
||||
<< std::setprecision (6)
|
||||
<< ((end.tv_sec - mStart.tv_sec) +
|
||||
((end.tv_usec - mStart.tv_usec ) / 1000000.0))
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
46
src/Timer.h
Normal file
46
src/Timer.h
Normal file
@@ -0,0 +1,46 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free Software
|
||||
// Foundation; either version 2 of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
// details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program; if not, write to the
|
||||
//
|
||||
// Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor,
|
||||
// Boston, MA
|
||||
// 02110-1301
|
||||
// USA
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef INCLUDED_TIMER
|
||||
#define INCLUDED_TIMER
|
||||
|
||||
#include <string>
|
||||
#include <sys/time.h>
|
||||
|
||||
class Timer
|
||||
{
|
||||
public:
|
||||
Timer (const std::string&);
|
||||
~Timer ();
|
||||
|
||||
private:
|
||||
std::string mDescription;
|
||||
struct timeval mStart;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2008, Paul Beckingham.
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2008, Paul Beckingham.
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
|
||||
854
src/command.cpp
854
src/command.cpp
File diff suppressed because it is too large
Load Diff
588
src/edit.cpp
Normal file
588
src/edit.cpp
Normal file
@@ -0,0 +1,588 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free Software
|
||||
// Foundation; either version 2 of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
// details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program; if not, write to the
|
||||
//
|
||||
// Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor,
|
||||
// Boston, MA
|
||||
// 02110-1301
|
||||
// USA
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include "task.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static std::string findValue (
|
||||
const std::string& text,
|
||||
const std::string& name)
|
||||
{
|
||||
std::string::size_type found = text.find (name);
|
||||
if (found != std::string::npos)
|
||||
{
|
||||
std::string::size_type eol = text.find ("\n", found);
|
||||
if (eol != std::string::npos)
|
||||
{
|
||||
std::string value = text.substr (
|
||||
found + name.length (),
|
||||
eol - (found + name.length ()));
|
||||
|
||||
return trim (value, "\t ");
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static std::string findDate (
|
||||
Config& conf,
|
||||
const std::string& text,
|
||||
const std::string& name)
|
||||
{
|
||||
std::string::size_type found = text.find (name);
|
||||
if (found != std::string::npos)
|
||||
{
|
||||
std::string::size_type eol = text.find ("\n", found);
|
||||
if (eol != std::string::npos)
|
||||
{
|
||||
std::string value = trim (text.substr (
|
||||
found + name.length (),
|
||||
eol - (found + name.length ())), "\t ");
|
||||
|
||||
if (value != "")
|
||||
{
|
||||
Date dt (value, conf.get ("dateformat", "m/d/Y"));
|
||||
char epoch [16];
|
||||
sprintf (epoch, "%d", (int)dt.toEpoch ());
|
||||
return std::string (epoch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static std::string formatStatus (T& task)
|
||||
{
|
||||
switch (task.getStatus ())
|
||||
{
|
||||
case T::pending: return "Pending"; break;
|
||||
case T::completed: return "Completed"; break;
|
||||
case T::deleted: return "Deleted"; break;
|
||||
case T::recurring: return "Recurring"; break;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static std::string formatDate (
|
||||
Config& conf,
|
||||
T& task,
|
||||
const std::string& attribute)
|
||||
{
|
||||
std::string value = task.getAttribute (attribute);
|
||||
if (value.length ())
|
||||
{
|
||||
Date dt (::atoi (value.c_str ()));
|
||||
value = dt.toString (conf.get ("dateformat", "m/d/Y"));
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static std::string formatTask (Config& conf, T task)
|
||||
{
|
||||
std::stringstream before;
|
||||
before << "# The 'task edit <id>' command allows you to modify all aspects of a task" << std::endl
|
||||
<< "# using a text editor. What is shown below is a representation of the" << std::endl
|
||||
<< "# task in all it's detail. Modify what you wish, and if you save and" << std::endl
|
||||
<< "# quit your editor, task will read this file and try to make sense of" << std::endl
|
||||
<< "# what changed, and apply those changes. If you quit your editor without" << std::endl
|
||||
<< "# saving or making any modifications, task will do nothing." << std::endl
|
||||
<< "#" << std::endl
|
||||
<< "# Lines that begin with # represent data you cannot change, like ID." << std::endl
|
||||
<< "# If you get too 'creative' with your editing, task will dump you back " << std::endl
|
||||
<< "# into the editor to try again." << std::endl
|
||||
<< "#" << std::endl
|
||||
<< "# Should you find yourself in an endless Groundhog Day loop, editing and" << std::endl
|
||||
<< "# editing the same file, just quit the editor without making any changes." << std::endl
|
||||
<< "# Task will notice this and stop the editing." << std::endl
|
||||
<< "#" << std::endl
|
||||
<< "# Name Editable details" << std::endl
|
||||
<< "# ----------------- ----------------------------------------------------" << std::endl
|
||||
<< "# ID: " << task.getId () << std::endl
|
||||
<< "# UUID: " << task.getUUID () << std::endl
|
||||
<< "# Status: " << formatStatus (task) << std::endl
|
||||
<< "# Mask: " << task.getAttribute ("mask") << std::endl
|
||||
<< "# iMask: " << task.getAttribute ("imask") << std::endl
|
||||
<< " Project: " << task.getAttribute ("project") << std::endl
|
||||
<< " Priority: " << task.getAttribute ("priority") << std::endl;
|
||||
|
||||
std::vector <std::string> tags;
|
||||
task.getTags (tags);
|
||||
std::string allTags;
|
||||
join (allTags, " ", tags);
|
||||
before << "# Separate the tags with spaces, like this: tag1 tag2" << std::endl
|
||||
<< " Tags: " << allTags << std::endl
|
||||
<< "# The description field is allowed to wrap and use multiple lines. Task" << std::endl
|
||||
<< "# will combine them." << std::endl
|
||||
<< " Description: " << task.getDescription () << std::endl
|
||||
<< " Created: " << formatDate (conf, task, "entry") << std::endl
|
||||
<< " Started: " << formatDate (conf, task, "start") << std::endl
|
||||
<< " Ended: " << formatDate (conf, task, "end") << std::endl
|
||||
<< " Due: " << formatDate (conf, task, "due") << std::endl
|
||||
<< " Until: " << formatDate (conf, task, "until") << std::endl
|
||||
<< " Recur: " << task.getAttribute ("recur") << std::endl
|
||||
<< " Parent: " << task.getAttribute ("parent") << std::endl
|
||||
<< " Foreground color: " << task.getAttribute ("fg") << std::endl
|
||||
<< " Background color: " << task.getAttribute ("bg") << std::endl
|
||||
<< "# Annotations look like this: <date> <text>, and there can be any number" << std::endl
|
||||
<< "# of them." << std::endl;
|
||||
|
||||
std::map <time_t, std::string> annotations;
|
||||
task.getAnnotations (annotations);
|
||||
foreach (anno, annotations)
|
||||
{
|
||||
Date dt (anno->first);
|
||||
before << " Annotation: " << dt.toString (conf.get ("dateformat", "m/d/Y"))
|
||||
<< " " << anno->second << std::endl;
|
||||
}
|
||||
|
||||
before << " Annotation: " << std::endl
|
||||
<< " Annotation: " << std::endl
|
||||
<< "# End" << std::endl;
|
||||
return before.str ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static void parseTask (Config& conf, T& task, const std::string& after)
|
||||
{
|
||||
// project
|
||||
std::string value = findValue (after, "Project:");
|
||||
if (task.getAttribute ("project") != value)
|
||||
{
|
||||
if (value != "")
|
||||
{
|
||||
std::cout << "Project modified." << std::endl;
|
||||
task.setAttribute ("project", value);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Project deleted." << std::endl;
|
||||
task.removeAttribute ("project");
|
||||
}
|
||||
}
|
||||
|
||||
// priority
|
||||
value = findValue (after, "Priority:");
|
||||
if (task.getAttribute ("priority") != value)
|
||||
{
|
||||
if (value != "")
|
||||
{
|
||||
if (validPriority (value))
|
||||
{
|
||||
std::cout << "Priority modified." << std::endl;
|
||||
task.setAttribute ("priority", value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Priority deleted." << std::endl;
|
||||
task.removeAttribute ("priority");
|
||||
}
|
||||
}
|
||||
|
||||
// tags
|
||||
value = findValue (after, "Tags:");
|
||||
std::vector <std::string> tags;
|
||||
split (tags, value, ' ');
|
||||
task.removeTags ();
|
||||
task.addTags (tags);
|
||||
|
||||
// description.
|
||||
value = findValue (after, "Description: ");
|
||||
if (task.getDescription () != value)
|
||||
{
|
||||
if (value != "")
|
||||
{
|
||||
std::cout << "Description modified." << std::endl;
|
||||
task.setDescription (value);
|
||||
}
|
||||
else
|
||||
throw std::string ("Cannot remove description.");
|
||||
}
|
||||
|
||||
// entry
|
||||
value = findDate (conf, after, "Created:");
|
||||
if (value != "")
|
||||
{
|
||||
Date edited (::atoi (value.c_str ()));
|
||||
|
||||
Date original (::atoi (task.getAttribute ("entry").c_str ()));
|
||||
if (!original.sameDay (edited))
|
||||
{
|
||||
std::cout << "Creation date modified." << std::endl;
|
||||
task.setAttribute ("entry", value);
|
||||
}
|
||||
}
|
||||
else
|
||||
throw std::string ("Cannot remove creation date");
|
||||
|
||||
// start
|
||||
value = findDate (conf, after, "Started:");
|
||||
if (value != "")
|
||||
{
|
||||
Date edited (::atoi (value.c_str ()));
|
||||
|
||||
if (task.getAttribute ("start") != "")
|
||||
{
|
||||
Date original (::atoi (task.getAttribute ("start").c_str ()));
|
||||
if (!original.sameDay (edited))
|
||||
{
|
||||
std::cout << "Start date modified." << std::endl;
|
||||
task.setAttribute ("start", value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Start date modified." << std::endl;
|
||||
task.setAttribute ("start", value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (task.getAttribute ("start") != "")
|
||||
{
|
||||
std::cout << "Start date removed." << std::endl;
|
||||
task.removeAttribute ("start");
|
||||
}
|
||||
}
|
||||
|
||||
// end
|
||||
value = findDate (conf, after, "Ended:");
|
||||
if (value != "")
|
||||
{
|
||||
Date edited (::atoi (value.c_str ()));
|
||||
|
||||
if (task.getAttribute ("end") != "")
|
||||
{
|
||||
Date original (::atoi (task.getAttribute ("end").c_str ()));
|
||||
if (!original.sameDay (edited))
|
||||
{
|
||||
std::cout << "Done date modified." << std::endl;
|
||||
task.setAttribute ("end", value);
|
||||
}
|
||||
}
|
||||
else if (task.getStatus () != T::deleted)
|
||||
throw std::string ("Cannot set a done date on a pending task.");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (task.getAttribute ("end") != "")
|
||||
{
|
||||
std::cout << "Done date removed." << std::endl;
|
||||
task.setStatus (T::pending);
|
||||
task.removeAttribute ("end");
|
||||
}
|
||||
}
|
||||
|
||||
// due
|
||||
value = findDate (conf, after, "Due:");
|
||||
if (value != "")
|
||||
{
|
||||
Date edited (::atoi (value.c_str ()));
|
||||
|
||||
if (task.getAttribute ("due") != "")
|
||||
{
|
||||
Date original (::atoi (task.getAttribute ("due").c_str ()));
|
||||
if (!original.sameDay (edited))
|
||||
{
|
||||
std::cout << "Due date modified." << std::endl;
|
||||
task.setAttribute ("due", value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Due date modified." << std::endl;
|
||||
task.setAttribute ("due", value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (task.getAttribute ("due") != "")
|
||||
{
|
||||
if (task.getStatus () == T::recurring ||
|
||||
task.getAttribute ("parent") != "")
|
||||
{
|
||||
std::cout << "Cannot remove a due date from a recurring task." << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Due date removed." << std::endl;
|
||||
task.removeAttribute ("due");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// until
|
||||
value = findDate (conf, after, "Until:");
|
||||
if (value != "")
|
||||
{
|
||||
Date edited (::atoi (value.c_str ()));
|
||||
|
||||
if (task.getAttribute ("until") != "")
|
||||
{
|
||||
Date original (::atoi (task.getAttribute ("until").c_str ()));
|
||||
if (!original.sameDay (edited))
|
||||
{
|
||||
std::cout << "Until date modified." << std::endl;
|
||||
task.setAttribute ("until", value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Until date modified." << std::endl;
|
||||
task.setAttribute ("until", value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (task.getAttribute ("until") != "")
|
||||
{
|
||||
std::cout << "Until date removed." << std::endl;
|
||||
task.removeAttribute ("until");
|
||||
}
|
||||
}
|
||||
|
||||
// recur
|
||||
value = findValue (after, "Recur:");
|
||||
if (value != task.getAttribute ("recur"))
|
||||
{
|
||||
if (value != "")
|
||||
{
|
||||
if (validDuration (value))
|
||||
{
|
||||
std::cout << "Recurrence modified." << std::endl;
|
||||
if (task.getAttribute ("due") != "")
|
||||
{
|
||||
task.setAttribute ("recur", value);
|
||||
task.setStatus (T::recurring);
|
||||
}
|
||||
else
|
||||
throw std::string ("A recurring task must have a due date.");
|
||||
}
|
||||
else
|
||||
throw std::string ("Not a valid recurrence duration.");
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Recurrence removed." << std::endl;
|
||||
task.setStatus (T::pending);
|
||||
task.removeAttribute ("recur");
|
||||
task.removeAttribute ("until");
|
||||
task.removeAttribute ("mask");
|
||||
task.removeAttribute ("imask");
|
||||
}
|
||||
}
|
||||
|
||||
// parent
|
||||
value = findValue (after, "Parent:");
|
||||
if (value != task.getAttribute ("parent"))
|
||||
{
|
||||
if (value != "")
|
||||
{
|
||||
std::cout << "Parent UUID modified." << std::endl;
|
||||
task.setAttribute ("parent", value);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Parent UUID removed." << std::endl;
|
||||
task.removeAttribute ("parent");
|
||||
}
|
||||
}
|
||||
|
||||
// fg
|
||||
value = findValue (after, "Foreground color:");
|
||||
if (value != task.getAttribute ("fg"))
|
||||
{
|
||||
if (value != "")
|
||||
{
|
||||
std::cout << "Foreground color modified." << std::endl;
|
||||
task.setAttribute ("fg", value);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Foreground color removed." << std::endl;
|
||||
task.removeAttribute ("fg");
|
||||
}
|
||||
}
|
||||
|
||||
// bg
|
||||
value = findValue (after, "Background color:");
|
||||
if (value != task.getAttribute ("bg"))
|
||||
{
|
||||
if (value != "")
|
||||
{
|
||||
std::cout << "Background color modified." << std::endl;
|
||||
task.setAttribute ("bg", value);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Background color removed." << std::endl;
|
||||
task.removeAttribute ("bg");
|
||||
}
|
||||
}
|
||||
|
||||
// Annotations
|
||||
std::map <time_t, std::string> annotations;
|
||||
std::string::size_type found = 0;
|
||||
while ((found = after.find ("Annotation:", found)) != std::string::npos)
|
||||
{
|
||||
found += 11;
|
||||
|
||||
std::string::size_type eol = after.find ("\n", found);
|
||||
if (eol != std::string::npos)
|
||||
{
|
||||
std::string value = trim (after.substr (
|
||||
found,
|
||||
eol - found), "\t ");
|
||||
|
||||
std::string::size_type gap = value.find (" ");
|
||||
if (gap != std::string::npos)
|
||||
{
|
||||
Date when (value.substr (0, gap));
|
||||
std::string text = trim (value.substr (gap, std::string::npos), "\t ");
|
||||
annotations[when.toEpoch ()] = text;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task.setAnnotations (annotations);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Introducing the Silver Bullet. This feature is the catch-all fixative for
|
||||
// various other ills. This is like opening up the hood and going in with a
|
||||
// wrench. To be used sparingly.
|
||||
std::string handleEdit (TDB& tdb, T& task, Config& conf)
|
||||
{
|
||||
std::stringstream out;
|
||||
std::vector <T> all;
|
||||
tdb.allPendingT (all);
|
||||
|
||||
filterSequence (all, task);
|
||||
foreach (seq, all)
|
||||
{
|
||||
// Check for file permissions.
|
||||
std::string dataLocation = expandPath (conf.get ("data.location"));
|
||||
if (access (dataLocation.c_str (), X_OK))
|
||||
throw std::string ("Your data.location directory is not writable.");
|
||||
|
||||
// Create a temp file name in data.location.
|
||||
std::stringstream pattern;
|
||||
pattern << dataLocation << "/task." << seq->getId () << ".XXXXXX";
|
||||
char cpattern [PATH_MAX];
|
||||
strcpy (cpattern, pattern.str ().c_str ());
|
||||
mkstemp (cpattern);
|
||||
char* file = cpattern;
|
||||
|
||||
// Format the contents, T -> text, write to a file.
|
||||
std::string before = formatTask (conf, *seq);
|
||||
spit (file, before);
|
||||
|
||||
// Determine correct editor: .taskrc:editor > $VISUAL > $EDITOR > vi
|
||||
std::string editor = conf.get ("editor", "");
|
||||
char* peditor = getenv ("VISUAL");
|
||||
if (editor == "" && peditor) editor = std::string (peditor);
|
||||
peditor = getenv ("EDITOR");
|
||||
if (editor == "" && peditor) editor = std::string (peditor);
|
||||
if (editor == "") editor = "vi";
|
||||
|
||||
// Complete the command line.
|
||||
editor += " ";
|
||||
editor += file;
|
||||
|
||||
ARE_THESE_REALLY_HARMFUL:
|
||||
// Launch the editor.
|
||||
std::cout << "Launching '" << editor << "' now..." << std::endl;
|
||||
system (editor.c_str ());
|
||||
std::cout << "Editing complete." << std::endl;
|
||||
|
||||
// Slurp file.
|
||||
std::string after;
|
||||
slurp (file, after, false);
|
||||
|
||||
// TODO Remove this debugging code.
|
||||
//spit ("./before", before);
|
||||
//spit ("./after", after);
|
||||
|
||||
// Update seq based on what can be parsed back out of the file, but only
|
||||
// if changes were made.
|
||||
if (before != after)
|
||||
{
|
||||
std::cout << "Edits were detected." << std::endl;
|
||||
std::string problem = "";
|
||||
bool oops = false;
|
||||
|
||||
try
|
||||
{
|
||||
parseTask (conf, *seq, after);
|
||||
tdb.modifyT (*seq);
|
||||
}
|
||||
|
||||
catch (std::string& e)
|
||||
{
|
||||
problem = e;
|
||||
oops = true;
|
||||
}
|
||||
|
||||
if (oops)
|
||||
{
|
||||
std::cout << "Error: " << problem << std::endl;
|
||||
|
||||
// Preserve the edits.
|
||||
before = after;
|
||||
spit (file, before);
|
||||
|
||||
if (confirm ("Task couldn't handle your edits. Would you like to try again?"))
|
||||
goto ARE_THESE_REALLY_HARMFUL;
|
||||
}
|
||||
}
|
||||
else
|
||||
std::cout << "No edits were detected." << std::endl;
|
||||
|
||||
// Cleanup.
|
||||
unlink (file);
|
||||
}
|
||||
|
||||
return out.str ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
1203
src/import.cpp
Normal file
1203
src/import.cpp
Normal file
File diff suppressed because it is too large
Load Diff
175
src/parse.cpp
175
src/parse.cpp
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2008, Paul Beckingham.
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -116,26 +116,27 @@ static const char* attributes[] =
|
||||
"",
|
||||
};
|
||||
|
||||
// Alphabetical please.
|
||||
static const char* commands[] =
|
||||
{
|
||||
"active",
|
||||
"add",
|
||||
"append",
|
||||
"annotate",
|
||||
"calendar",
|
||||
"colors",
|
||||
"completed",
|
||||
"delete",
|
||||
"done",
|
||||
"duplicate",
|
||||
"edit",
|
||||
"export",
|
||||
"help",
|
||||
"history",
|
||||
"ghistory",
|
||||
"import",
|
||||
"info",
|
||||
"list",
|
||||
"long",
|
||||
"ls",
|
||||
"newest",
|
||||
"next",
|
||||
"oldest",
|
||||
"overdue",
|
||||
"projects",
|
||||
"start",
|
||||
@@ -143,6 +144,7 @@ static const char* commands[] =
|
||||
"stop",
|
||||
"summary",
|
||||
"tags",
|
||||
"timesheet",
|
||||
"undelete",
|
||||
"undo",
|
||||
"version",
|
||||
@@ -164,7 +166,6 @@ void guess (const std::string& type, const char** list, std::string& candidate)
|
||||
candidate = matches[0];
|
||||
|
||||
else if (0 == matches.size ())
|
||||
// throw std::string ("Unrecognized ") + type + " '" + candidate + "'";
|
||||
candidate = "";
|
||||
|
||||
else
|
||||
@@ -194,7 +195,6 @@ void guess (const std::string& type, std::vector<std::string>& options, std::str
|
||||
candidate = matches[0];
|
||||
|
||||
else if (0 == matches.size ())
|
||||
// throw std::string ("Unrecognized ") + type + " '" + candidate + "'";
|
||||
candidate = "";
|
||||
|
||||
else
|
||||
@@ -239,7 +239,7 @@ bool validDate (std::string& date, Config& conf)
|
||||
{
|
||||
Date test (date, conf.get ("dateformat", "m/d/Y"));
|
||||
|
||||
char epoch[12];
|
||||
char epoch[16];
|
||||
sprintf (epoch, "%d", (int) test.toEpoch ());
|
||||
date = epoch;
|
||||
|
||||
@@ -303,6 +303,9 @@ static bool validAttribute (
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static bool validId (const std::string& input)
|
||||
{
|
||||
if (input.length () == 0)
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < input.length (); ++i)
|
||||
if (!::isdigit (input[i]))
|
||||
return false;
|
||||
@@ -310,6 +313,58 @@ static bool validId (const std::string& input)
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 1,2-4,6
|
||||
static bool validSequence (
|
||||
const std::string& input,
|
||||
std::vector <int>& ids)
|
||||
{
|
||||
std::vector <std::string> ranges;
|
||||
split (ranges, input, ',');
|
||||
|
||||
std::vector <std::string>::iterator it;
|
||||
for (it = ranges.begin (); it != ranges.end (); ++it)
|
||||
{
|
||||
std::vector <std::string> range;
|
||||
split (range, *it, '-');
|
||||
|
||||
switch (range.size ())
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
if (! validId (range[0]))
|
||||
return false;
|
||||
|
||||
int id = ::atoi (range[0].c_str ());
|
||||
ids.push_back (id);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
if (! validId (range[0]) ||
|
||||
! validId (range[1]))
|
||||
return false;
|
||||
|
||||
int low = ::atoi (range[0].c_str ());
|
||||
int high = ::atoi (range[1].c_str ());
|
||||
if (low >= high)
|
||||
return false;
|
||||
|
||||
for (int i = low; i <= high; ++i)
|
||||
ids.push_back (i);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ids.size () ? true : false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static bool validTag (const std::string& input)
|
||||
{
|
||||
@@ -352,7 +407,8 @@ static bool validCommand (std::string& input)
|
||||
static bool validSubstitution (
|
||||
std::string& input,
|
||||
std::string& from,
|
||||
std::string& to)
|
||||
std::string& to,
|
||||
bool& global)
|
||||
{
|
||||
size_t first = input.find ('/');
|
||||
if (first != std::string::npos)
|
||||
@@ -366,10 +422,17 @@ static bool validSubstitution (
|
||||
if (first == 0 &&
|
||||
first < second &&
|
||||
second < third &&
|
||||
third == input.length () - 1)
|
||||
(third == input.length () - 1 ||
|
||||
third == input.length () - 2))
|
||||
{
|
||||
from = input.substr (first + 1, second - first - 1);
|
||||
to = input.substr (second + 1, third - second - 1);
|
||||
|
||||
global = false;
|
||||
if (third == input.length () - 2 &&
|
||||
input.find ('g', third + 1) != std::string::npos)
|
||||
global = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -386,15 +449,23 @@ bool validDuration (std::string& input)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Token Distinguishing characteristic
|
||||
// ------- -----------------------------
|
||||
// command first positional
|
||||
// id \d+
|
||||
// description default, accumulate
|
||||
// substitution /\w+/\w*/
|
||||
// tags [-+]\w+
|
||||
// attributes \w+:.+
|
||||
// Token EBNF
|
||||
// ------- ----------------------------------
|
||||
// command first non-id recognized argument
|
||||
//
|
||||
// substitution ::= "/" from "/" to "/g"
|
||||
// | "/" from "/" to "/" ;
|
||||
//
|
||||
// tags ::= "+" word
|
||||
// | "-" word ;
|
||||
//
|
||||
// attributes ::= word ":" value
|
||||
// | word ":"
|
||||
//
|
||||
// sequence ::= \d+ "," sequence
|
||||
// | \d+ "-" \d+ ;
|
||||
//
|
||||
// description (whatever isn't one of the above)
|
||||
void parse (
|
||||
std::vector <std::string>& args,
|
||||
std::string& command,
|
||||
@@ -403,6 +474,9 @@ void parse (
|
||||
{
|
||||
command = "";
|
||||
|
||||
bool foundSequence = false;
|
||||
bool foundSomethingAfterSequence = false;
|
||||
|
||||
std::string descCandidate = "";
|
||||
for (size_t i = 0; i < args.size (); ++i)
|
||||
{
|
||||
@@ -415,16 +489,25 @@ void parse (
|
||||
size_t colon; // Pointer to colon in argument.
|
||||
std::string from;
|
||||
std::string to;
|
||||
bool global;
|
||||
std::vector <int> sequence;
|
||||
|
||||
// An id is the first argument found that contains all digits.
|
||||
if (lowerCase (command) != "add" && // "add" doesn't require an ID
|
||||
task.getId () == 0 &&
|
||||
validId (arg))
|
||||
task.setId (::atoi (arg.c_str ()));
|
||||
if (lowerCase (command) != "add" && // "add" doesn't require an ID
|
||||
validSequence (arg, sequence) &&
|
||||
! foundSomethingAfterSequence)
|
||||
{
|
||||
foundSequence = true;
|
||||
foreach (id, sequence)
|
||||
task.addId (*id);
|
||||
}
|
||||
|
||||
// Tags begin with + or - and contain arbitrary text.
|
||||
else if (validTag (arg))
|
||||
{
|
||||
if (foundSequence)
|
||||
foundSomethingAfterSequence = true;
|
||||
|
||||
if (arg[0] == '+')
|
||||
task.addTag (arg.substr (1, std::string::npos));
|
||||
else if (arg[0] == '-')
|
||||
@@ -435,6 +518,9 @@ void parse (
|
||||
// value.
|
||||
else if ((colon = arg.find (":")) != std::string::npos)
|
||||
{
|
||||
if (foundSequence)
|
||||
foundSomethingAfterSequence = true;
|
||||
|
||||
std::string name = lowerCase (arg.substr (0, colon));
|
||||
std::string value = arg.substr (colon + 1, std::string::npos);
|
||||
|
||||
@@ -447,39 +533,52 @@ void parse (
|
||||
// If it is not a valid attribute, then allow the argument as part of
|
||||
// the description.
|
||||
else
|
||||
{
|
||||
if (descCandidate.length ())
|
||||
descCandidate += " ";
|
||||
descCandidate += arg;
|
||||
}
|
||||
}
|
||||
|
||||
// Substitution of description text.
|
||||
else if (validSubstitution (arg, from, to))
|
||||
else if (validSubstitution (arg, from, to, global))
|
||||
{
|
||||
task.setSubstitution (from, to);
|
||||
if (foundSequence)
|
||||
foundSomethingAfterSequence = true;
|
||||
|
||||
task.setSubstitution (from, to, global);
|
||||
}
|
||||
|
||||
// Command.
|
||||
else if (command == "")
|
||||
{
|
||||
if (foundSequence)
|
||||
foundSomethingAfterSequence = true;
|
||||
|
||||
std::string l = lowerCase (arg);
|
||||
if (isCommand (l) && validCommand (l))
|
||||
command = l;
|
||||
else
|
||||
{
|
||||
if (descCandidate.length ())
|
||||
descCandidate += " ";
|
||||
descCandidate += arg;
|
||||
}
|
||||
}
|
||||
|
||||
// Anything else is just considered description.
|
||||
else
|
||||
descCandidate += std::string (arg) + " ";
|
||||
{
|
||||
if (foundSequence)
|
||||
foundSomethingAfterSequence = true;
|
||||
|
||||
if (descCandidate.length ())
|
||||
descCandidate += " ";
|
||||
descCandidate += arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (task.getAttribute ("recur") != "" &&
|
||||
task.getAttribute ("due") == "")
|
||||
throw std::string ("You cannot specify a recurring task without a due date.");
|
||||
|
||||
if (task.getAttribute ("until") != "" &&
|
||||
task.getAttribute ("recur") == "")
|
||||
throw std::string ("You cannot specify an until date for a non-recurring task.");
|
||||
|
||||
if (validDescription (descCandidate))
|
||||
task.setDescription (descCandidate);
|
||||
}
|
||||
@@ -495,7 +594,7 @@ void loadCustomReports (Config& conf)
|
||||
if (i->substr (0, 7) == "report.")
|
||||
{
|
||||
std::string report = i->substr (7, std::string::npos);
|
||||
unsigned int columns = report.find (".columns");
|
||||
std::string::size_type columns = report.find (".columns");
|
||||
if (columns != std::string::npos)
|
||||
{
|
||||
report = report.substr (0, columns);
|
||||
@@ -515,4 +614,10 @@ bool isCustomReport (const std::string& report)
|
||||
return false;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void allCustomReports (std::vector <std::string>& all)
|
||||
{
|
||||
all = customReports;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
2043
src/report.cpp
2043
src/report.cpp
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2008, Paul Beckingham.
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -80,10 +80,14 @@ void initializeColorRules (Config& conf)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void autoColorize (T& task, Text::color& fg, Text::color& bg)
|
||||
void autoColorize (
|
||||
T& task,
|
||||
Text::color& fg,
|
||||
Text::color& bg,
|
||||
Config& conf)
|
||||
{
|
||||
// Note: fg, bg already contain colors specifically assigned via command.
|
||||
// Note: These rules form a hierarchy - the last rule is king.
|
||||
// Note: These rules form a hierarchy - the last rule is King.
|
||||
|
||||
// Colorization of the tagged.
|
||||
if (gsFg["color.tagged"] != Text::nocolor ||
|
||||
@@ -153,29 +157,6 @@ void autoColorize (T& task, Text::color& fg, Text::color& bg)
|
||||
}
|
||||
}
|
||||
|
||||
// Colorization of the due and overdue.
|
||||
std::string due = task.getAttribute ("due");
|
||||
if (due != "")
|
||||
{
|
||||
Date dueDate (::atoi (due.c_str ()));
|
||||
Date now;
|
||||
Date then (now + 7 * 86400);
|
||||
|
||||
// Overdue
|
||||
if (dueDate < now)
|
||||
{
|
||||
fg = gsFg["color.overdue"];
|
||||
bg = gsBg["color.overdue"];
|
||||
}
|
||||
|
||||
// Imminent
|
||||
else if (dueDate < then)
|
||||
{
|
||||
fg = gsFg["color.due"];
|
||||
bg = gsBg["color.due"];
|
||||
}
|
||||
}
|
||||
|
||||
// Colorization by tag value.
|
||||
std::map <std::string, Text::color>::iterator it;
|
||||
for (it = gsFg.begin (); it != gsFg.end (); ++it)
|
||||
@@ -219,6 +200,40 @@ void autoColorize (T& task, Text::color& fg, Text::color& bg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Colorization of the due and overdue.
|
||||
std::string due = task.getAttribute ("due");
|
||||
if (due != "")
|
||||
{
|
||||
Date dueDate (::atoi (due.c_str ()));
|
||||
Date now;
|
||||
Date then (now + conf.get ("due", 7) * 86400);
|
||||
|
||||
// Overdue
|
||||
if (dueDate < now)
|
||||
{
|
||||
fg = gsFg["color.overdue"];
|
||||
bg = gsBg["color.overdue"];
|
||||
}
|
||||
|
||||
// Imminent
|
||||
else if (dueDate < then)
|
||||
{
|
||||
fg = gsFg["color.due"];
|
||||
bg = gsBg["color.due"];
|
||||
}
|
||||
}
|
||||
|
||||
// Colorization of the recurring.
|
||||
if (gsFg["color.recurring"] != Text::nocolor ||
|
||||
gsBg["color.recurring"] != Text::nocolor)
|
||||
{
|
||||
if (task.getAttribute ("recur") != "")
|
||||
{
|
||||
fg = gsFg["color.recurring"];
|
||||
bg = gsBg["color.recurring"];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
425
src/task.cpp
425
src/task.cpp
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2008, Paul Beckingham.
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -47,15 +48,11 @@
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Globals for exclusive use by callback function.
|
||||
static TDB* gTdb = NULL;
|
||||
static Config* gConf = NULL;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static void shortUsage (Config& conf)
|
||||
static std::string shortUsage (Config& conf)
|
||||
{
|
||||
std::stringstream out;
|
||||
Table table;
|
||||
int width = conf.get ("defaultwidth", 80);
|
||||
int width = conf.get ("defaultwidth", (int) 80);
|
||||
#ifdef HAVE_LIBNCURSES
|
||||
if (conf.get ("curses", true))
|
||||
{
|
||||
@@ -88,16 +85,12 @@ static void shortUsage (Config& conf)
|
||||
table.addCell (row, 2, "Adds a new task");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task list [tags] [attrs] desc...");
|
||||
table.addCell (row, 2, "Lists all tasks matching the specified criteria");
|
||||
table.addCell (row, 1, "task append [tags] [attrs] desc...");
|
||||
table.addCell (row, 2, "Appends more description to an existing task");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task long [tags] [attrs] desc...");
|
||||
table.addCell (row, 2, "Lists all task, all data, matching the specified criteria");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task ls [tags] [attrs] desc...");
|
||||
table.addCell (row, 2, "Minimal listing of all tasks matching the specified criteria");
|
||||
table.addCell (row, 1, "task annotate ID desc...");
|
||||
table.addCell (row, 2, "Adds an annotation to an existing task");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task completed [tags] [attrs] desc...");
|
||||
@@ -109,7 +102,19 @@ static void shortUsage (Config& conf)
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task ID /from/to/");
|
||||
table.addCell (row, 2, "Perform the substitution on the desc, for fixing mistakes");
|
||||
table.addCell (row, 2, "Performs one substitution on the task description, for fixing mistakes");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task ID /from/to/g");
|
||||
table.addCell (row, 2, "Performs all substitutions on the task description, for fixing mistakes");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task edit ID");
|
||||
table.addCell (row, 2, "Launches an editor to let you modify all aspects of a task directly, therefore it is to be used carefully");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task duplicate ID [tags] [attrs] [desc...]");
|
||||
table.addCell (row, 2, "Duplicates the specified task, and allows modifications");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task delete ID");
|
||||
@@ -132,7 +137,7 @@ static void shortUsage (Config& conf)
|
||||
table.addCell (row, 2, "Removes the 'start' time from a task");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task done ID");
|
||||
table.addCell (row, 1, "task done ID [tags] [attrs] [desc...]");
|
||||
table.addCell (row, 2, "Marks the specified task as completed");
|
||||
|
||||
row = table.addRow ();
|
||||
@@ -151,6 +156,10 @@ static void shortUsage (Config& conf)
|
||||
table.addCell (row, 1, "task summary");
|
||||
table.addCell (row, 2, "Shows a report of task status by project");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task timesheet [weeks]");
|
||||
table.addCell (row, 2, "Shows a weekly report of tasks completed and started");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task history");
|
||||
table.addCell (row, 2, "Shows a report of task history, by month");
|
||||
@@ -175,18 +184,14 @@ static void shortUsage (Config& conf)
|
||||
table.addCell (row, 1, "task overdue");
|
||||
table.addCell (row, 2, "Shows all incomplete tasks that are beyond their due date");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task oldest");
|
||||
table.addCell (row, 2, "Shows the oldest tasks");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task newest");
|
||||
table.addCell (row, 2, "Shows the newest tasks");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task stats");
|
||||
table.addCell (row, 2, "Shows task database statistics");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task import");
|
||||
table.addCell (row, 2, "Imports tasks from a variety of formats");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task export");
|
||||
table.addCell (row, 2, "Exports all tasks as a CSV file");
|
||||
@@ -203,46 +208,72 @@ static void shortUsage (Config& conf)
|
||||
table.addCell (row, 1, "task help");
|
||||
table.addCell (row, 2, "Shows the long usage text");
|
||||
|
||||
std::cout << table.render ()
|
||||
<< std::endl
|
||||
<< "See http://www.beckingham.net/task.html for the latest releases and a full tutorial."
|
||||
<< std::endl
|
||||
<< std::endl;
|
||||
// Add custom reports here...
|
||||
std::vector <std::string> all;
|
||||
allCustomReports (all);
|
||||
foreach (report, all)
|
||||
{
|
||||
std::string command = std::string ("task ") + *report + std::string (" [tags] [attrs] desc...");
|
||||
std::string description = conf.get (
|
||||
std::string ("report.") + *report + ".description", std::string ("(missing description)"));
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, command);
|
||||
table.addCell (row, 2, description);
|
||||
}
|
||||
|
||||
out << table.render ()
|
||||
<< std::endl
|
||||
<< "See http://www.beckingham.net/task.html for the latest releases and a "
|
||||
<< "full tutorial. New releases containing fixes and enhancements are "
|
||||
<< "made frequently. Join in the discussion of task, present and future, "
|
||||
<< "at http://groups.google.com/group/taskprogram"
|
||||
<< std::endl
|
||||
<< std::endl;
|
||||
|
||||
return out.str ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static void longUsage (Config& conf)
|
||||
static std::string longUsage (Config& conf)
|
||||
{
|
||||
shortUsage (conf);
|
||||
std::stringstream out;
|
||||
out << shortUsage (conf)
|
||||
<< "ID is the numeric identifier displayed by the 'task list' command. "
|
||||
<< "You can specify multiple IDs for task commands, and multiple tasks "
|
||||
<< "will be affected. To specify multiple IDs make sure you use one "
|
||||
<< "of these forms:" << "\n"
|
||||
<< " task delete 1,2,3" << "\n"
|
||||
<< " task info 1-3" << "\n"
|
||||
<< " task pri:H 1,2-5,19" << "\n"
|
||||
<< "\n"
|
||||
<< "Tags are arbitrary words, any quantity:" << "\n"
|
||||
<< " +tag The + means add the tag" << "\n"
|
||||
<< " -tag The - means remove the tag" << "\n"
|
||||
<< "\n"
|
||||
<< "Attributes are:" << "\n"
|
||||
<< " project: Project name" << "\n"
|
||||
<< " priority: Priority" << "\n"
|
||||
<< " due: Due date" << "\n"
|
||||
<< " recur: Recurrence frequency" << "\n"
|
||||
<< " until: Recurrence end date" << "\n"
|
||||
<< " fg: Foreground color" << "\n"
|
||||
<< " bg: Background color" << "\n"
|
||||
<< " rc: Alternate .taskrc file" << "\n"
|
||||
<< "\n"
|
||||
<< "Any command or attribute name may be abbreviated if still unique:" << "\n"
|
||||
<< " task list project:Home" << "\n"
|
||||
<< " task li pro:Home" << "\n"
|
||||
<< "\n"
|
||||
<< "Some task descriptions need to be escaped because of the shell:" << "\n"
|
||||
<< " task add \"quoted ' quote\"" << "\n"
|
||||
<< " task add escaped \\' quote" << "\n"
|
||||
<< "\n"
|
||||
<< "Many characters have special meaning to the shell, including:" << "\n"
|
||||
<< " $ ! ' \" ( ) ; \\ ` * ? { } [ ] < > | & % # ~" << "\n"
|
||||
<< std::endl;
|
||||
|
||||
std::cout
|
||||
<< "ID is the numeric identifier displayed by the 'task list' command" << "\n"
|
||||
<< "\n"
|
||||
<< "Tags are arbitrary words, any quantity:" << "\n"
|
||||
<< " +tag The + means add the tag" << "\n"
|
||||
<< " -tag The - means remove the tag" << "\n"
|
||||
<< "\n"
|
||||
<< "Attributes are:" << "\n"
|
||||
<< " project: Project name" << "\n"
|
||||
<< " priority: Priority" << "\n"
|
||||
<< " due: Due date" << "\n"
|
||||
<< " recur: Recurrence frequency" << "\n"
|
||||
<< " until: Recurrence end date" << "\n"
|
||||
<< " fg: Foreground color" << "\n"
|
||||
<< " bg: Background color" << "\n"
|
||||
<< " rc: Alternate .taskrc file" << "\n"
|
||||
<< "\n"
|
||||
<< "Any command or attribute name may be abbreviated if still unique:" << "\n"
|
||||
<< " task list project:Home" << "\n"
|
||||
<< " task li pro:Home" << "\n"
|
||||
<< "\n"
|
||||
<< "Some task descriptions need to be escaped because of the shell:" << "\n"
|
||||
<< " task add \"quoted ' quote\"" << "\n"
|
||||
<< " task add escaped \\' quote" << "\n"
|
||||
<< "\n"
|
||||
<< "Many characters have special meaning to the shell, including:" << "\n"
|
||||
<< " $ ! ' \" ( ) ; \\ ` * ? { } [ ] < > | & % # ~" << "\n"
|
||||
<< std::endl;
|
||||
return out.str ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -274,9 +305,6 @@ void loadConfFile (int argc, char** argv, Config& conf)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
// TODO Find out what this is, and either promote it to live code, or remove it.
|
||||
// std::set_terminate (__gnu_cxx::__verbose_terminate_handler);
|
||||
|
||||
// Set up randomness.
|
||||
#ifdef HAVE_SRANDOM
|
||||
srandom (time (NULL));
|
||||
@@ -289,22 +317,26 @@ int main (int argc, char** argv)
|
||||
// Load the config file from the home directory. If the file cannot be
|
||||
// found, offer to create a sample one.
|
||||
Config conf;
|
||||
gConf = &conf;
|
||||
loadConfFile (argc, argv, conf);
|
||||
|
||||
// When redirecting output to a file, do not use color, curses.
|
||||
if (!isatty (fileno (stdout)))
|
||||
{
|
||||
conf.set ("curses", "off");
|
||||
conf.set ("color", "off");
|
||||
|
||||
if (! conf.get (std::string ("_forcecolor"), false))
|
||||
conf.set ("color", "off");
|
||||
}
|
||||
|
||||
TDB tdb;
|
||||
gTdb = &tdb;
|
||||
std::string dataLocation = expandPath (conf.get ("data.location"));
|
||||
tdb.dataDirectory (dataLocation);
|
||||
|
||||
// Set up TDB callback.
|
||||
// Allow user override of file locking. Solaris/NFS machines may want this.
|
||||
if (! conf.get ("locking", true))
|
||||
tdb.noLock ();
|
||||
|
||||
// Check for silly shadow file settings.
|
||||
std::string shadowFile = expandPath (conf.get ("shadow.file"));
|
||||
if (shadowFile != "")
|
||||
{
|
||||
@@ -315,8 +347,6 @@ int main (int argc, char** argv)
|
||||
if (shadowFile == dataLocation + "/completed.data")
|
||||
throw std::string ("Configuration variable 'shadow.file' is set to "
|
||||
"overwrite your completed tasks. Please change it.");
|
||||
|
||||
tdb.onChange (&onChangeCallback);
|
||||
}
|
||||
|
||||
std::cout << runTaskCommand (argc, argv, tdb, conf);
|
||||
@@ -324,7 +354,7 @@ int main (int argc, char** argv)
|
||||
|
||||
catch (std::string& error)
|
||||
{
|
||||
std::cerr << error << std::endl;
|
||||
std::cout << error << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -343,18 +373,56 @@ void nag (TDB& tdb, T& task, Config& conf)
|
||||
std::string nagMessage = conf.get ("nag", std::string (""));
|
||||
if (nagMessage != "")
|
||||
{
|
||||
// Load all pending.
|
||||
// Load all pending tasks.
|
||||
std::vector <T> pending;
|
||||
tdb.allPendingT (pending);
|
||||
|
||||
// Restrict to matching subset.
|
||||
std::vector <int> matching;
|
||||
gatherNextTasks (tdb, task, conf, pending, matching);
|
||||
// Counters.
|
||||
int overdue = 0;
|
||||
int high = 0;
|
||||
int medium = 0;
|
||||
int low = 0;
|
||||
bool isOverdue = false;
|
||||
char pri = ' ';
|
||||
|
||||
foreach (i, matching)
|
||||
if (pending[*i].getId () == task.getId ())
|
||||
return;
|
||||
// Scan all pending tasks.
|
||||
foreach (t, pending)
|
||||
{
|
||||
if (t->getId () == task.getId ())
|
||||
{
|
||||
if (getDueState (t->getAttribute ("due")) == 2)
|
||||
isOverdue = true;
|
||||
|
||||
std::string priority = t->getAttribute ("priority");
|
||||
if (priority.length ())
|
||||
pri = priority[0];
|
||||
}
|
||||
else if (t->getStatus () == T::pending)
|
||||
{
|
||||
if (getDueState (t->getAttribute ("due")) == 2)
|
||||
overdue++;
|
||||
|
||||
std::string priority = t->getAttribute ("priority");
|
||||
if (priority.length ())
|
||||
{
|
||||
switch (priority[0])
|
||||
{
|
||||
case 'H': high++; break;
|
||||
case 'M': medium++; break;
|
||||
case 'L': low++; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// General form is "if there are no more deserving tasks", suppress the nag.
|
||||
if (isOverdue ) return;
|
||||
if (pri == 'H' && !overdue ) return;
|
||||
if (pri == 'M' && !overdue && !high ) return;
|
||||
if (pri == 'L' && !overdue && !high && !medium ) return;
|
||||
if (pri == ' ' && !overdue && !high && !medium && !low) return;
|
||||
|
||||
// All the excuses are made, all that remains is to nag the user.
|
||||
std::cout << nagMessage << std::endl;
|
||||
}
|
||||
}
|
||||
@@ -372,15 +440,12 @@ int getDueState (const std::string& due)
|
||||
|
||||
// rightNow is the current date + time.
|
||||
Date rightNow;
|
||||
Date midnight (rightNow.month (), rightNow.day (), rightNow.year ());
|
||||
|
||||
// By performing this conversion, today is set up as the same date, but
|
||||
// midnight.
|
||||
Date today (rightNow.month (), rightNow.day (), rightNow.year ());
|
||||
|
||||
if (dt < today)
|
||||
if (dt < midnight)
|
||||
return 2;
|
||||
|
||||
Date nextweek = today + 7 * 86400;
|
||||
Date nextweek = midnight + 7 * 86400;
|
||||
if (dt < nextweek)
|
||||
return 1;
|
||||
}
|
||||
@@ -410,7 +475,13 @@ void handleRecurrence (TDB& tdb, std::vector <T>& tasks)
|
||||
<< " ("
|
||||
<< trim (t->getDescription ())
|
||||
<< ") is past its 'until' date, and has be deleted" << std::endl;
|
||||
tdb.deleteT (*t);
|
||||
|
||||
// Determine the end date.
|
||||
char endTime[16];
|
||||
sprintf (endTime, "%u", (unsigned int) time (NULL));
|
||||
t->setAttribute ("end", endTime);
|
||||
t->setStatus (T::deleted);
|
||||
tdb.modifyT (*t);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -531,6 +602,18 @@ Date getNextRecurrence (Date& current, std::string& period)
|
||||
return Date (m, d, y);
|
||||
}
|
||||
|
||||
if (period == "weekdays")
|
||||
{
|
||||
int dow = current.dayOfWeek ();
|
||||
int days;
|
||||
|
||||
if (dow == 5) days = 3;
|
||||
else if (dow == 6) days = 2;
|
||||
else days = 1;
|
||||
|
||||
return current + (days * 86400);
|
||||
}
|
||||
|
||||
if (isdigit (period[0]) && period[period.length () - 1] == 'm')
|
||||
{
|
||||
std::string numeric = period.substr (0, period.length () - 1);
|
||||
@@ -620,6 +703,19 @@ Date getNextRecurrence (Date& current, std::string& period)
|
||||
return Date (m, d, y);
|
||||
}
|
||||
|
||||
else if (period == "annual" ||
|
||||
period == "yearly")
|
||||
{
|
||||
y += 1;
|
||||
|
||||
// If the due data just happens to be 2/29 in a leap year, then simply
|
||||
// incrementing y is going to create an invalid date.
|
||||
if (m == 2 && d == 29)
|
||||
d = 28;
|
||||
|
||||
return Date (m, d, y);
|
||||
}
|
||||
|
||||
// If the period is an 'easy' one, add it to current, and we're done.
|
||||
int days = convertDuration (period);
|
||||
return current + (days * 86400);
|
||||
@@ -672,61 +768,53 @@ void updateRecurrenceMask (
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Using gTdb and gConf, generate a report.
|
||||
void onChangeCallback ()
|
||||
void updateShadowFile (TDB& tdb, Config& conf)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (gConf && gTdb)
|
||||
// Determine if shadow file is enabled.
|
||||
std::string shadowFile = expandPath (conf.get ("shadow.file"));
|
||||
if (shadowFile != "")
|
||||
{
|
||||
// Determine if shadow file is enabled.
|
||||
std::string shadowFile = expandPath (gConf->get ("shadow.file"));
|
||||
if (shadowFile != "")
|
||||
std::string oldCurses = conf.get ("curses");
|
||||
std::string oldColor = conf.get ("color");
|
||||
conf.set ("curses", "off");
|
||||
conf.set ("color", "off");
|
||||
|
||||
// Run report. Use shadow.command, using default.command as a fallback
|
||||
// with "list" as a default.
|
||||
std::string command = conf.get ("shadow.command",
|
||||
conf.get ("default.command", "list"));
|
||||
std::vector <std::string> args;
|
||||
split (args, command, ' ');
|
||||
std::string result = runTaskCommand (args, tdb, conf);
|
||||
|
||||
std::ofstream out (shadowFile.c_str ());
|
||||
if (out.good ())
|
||||
{
|
||||
std::string oldCurses = gConf->get ("curses");
|
||||
std::string oldColor = gConf->get ("color");
|
||||
gConf->set ("curses", "off");
|
||||
gConf->set ("color", "off");
|
||||
|
||||
// Run report. Use shadow.command, using default.command as a fallback
|
||||
// with "list" as a default.
|
||||
std::string command = gConf->get ("shadow.command",
|
||||
gConf->get ("default.command", "list"));
|
||||
std::vector <std::string> args;
|
||||
split (args, command, ' ');
|
||||
std::string result = runTaskCommand (args, *gTdb, *gConf);
|
||||
|
||||
std::ofstream out (shadowFile.c_str ());
|
||||
if (out.good ())
|
||||
{
|
||||
out << result;
|
||||
out.close ();
|
||||
}
|
||||
else
|
||||
throw std::string ("Could not write file '") + shadowFile + "'";
|
||||
|
||||
gConf->set ("curses", oldCurses);
|
||||
gConf->set ("color", oldColor);
|
||||
out << result;
|
||||
out.close ();
|
||||
}
|
||||
else
|
||||
throw std::string ("No specified shadow file '") + shadowFile + "'.";
|
||||
throw std::string ("Could not write file '") + shadowFile + "'";
|
||||
|
||||
// Optionally display a notification that the shadow file was updated.
|
||||
if (gConf->get (std::string ("shadow.notify"), false))
|
||||
std::cout << "[Shadow file '" << shadowFile << "' updated]" << std::endl;
|
||||
conf.set ("curses", oldCurses);
|
||||
conf.set ("color", oldColor);
|
||||
}
|
||||
else
|
||||
throw std::string ("Internal error (TDB/Config).");
|
||||
|
||||
// Optionally display a notification that the shadow file was updated.
|
||||
if (conf.get (std::string ("shadow.notify"), false))
|
||||
std::cout << "[Shadow file '" << shadowFile << "' updated]" << std::endl;
|
||||
}
|
||||
|
||||
catch (std::string& error)
|
||||
{
|
||||
std::cout << error << std::endl;
|
||||
std::cerr << error << std::endl;
|
||||
}
|
||||
|
||||
catch (...)
|
||||
{
|
||||
std::cout << "Unknown error." << std::endl;
|
||||
std::cerr << "Unknown error." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -736,13 +824,14 @@ std::string runTaskCommand (
|
||||
char** argv,
|
||||
TDB& tdb,
|
||||
Config& conf,
|
||||
bool gc /* = true */)
|
||||
bool gc /* = true */,
|
||||
bool shadow /* = true */)
|
||||
{
|
||||
std::vector <std::string> args;
|
||||
for (int i = 1; i < argc; ++i)
|
||||
args.push_back (argv[i]);
|
||||
|
||||
return runTaskCommand (args, tdb, conf, gc);
|
||||
return runTaskCommand (args, tdb, conf, gc, shadow);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -750,12 +839,15 @@ std::string runTaskCommand (
|
||||
std::vector <std::string>& args,
|
||||
TDB& tdb,
|
||||
Config& conf,
|
||||
bool gc /* = false */)
|
||||
bool gc /* = false */,
|
||||
bool shadow /* = false */)
|
||||
{
|
||||
// If argc == 1 and the default.command configuration variable is set,
|
||||
// then use that, otherwise stick with argc/argv.
|
||||
std::string defaultCommand = conf.get ("default.command");
|
||||
if (args.size () == 0 && defaultCommand != "")
|
||||
if ((args.size () == 0 ||
|
||||
(args.size () == 1 && args[0].substr (0, 3) == "rc:")) &&
|
||||
defaultCommand != "")
|
||||
{
|
||||
// Stuff the command line.
|
||||
args.clear ();
|
||||
@@ -769,39 +861,54 @@ std::string runTaskCommand (
|
||||
T task;
|
||||
parse (args, command, task, conf);
|
||||
|
||||
std::string out = "";
|
||||
bool gcMod = false; // Change occurred by way of gc.
|
||||
bool cmdMod = false; // Change occurred by way of command type.
|
||||
std::string out;
|
||||
|
||||
if (command == "" && task.getId ()) { handleModify (tdb, task, conf ); }
|
||||
else if (command == "add") { handleAdd (tdb, task, conf ); }
|
||||
else if (command == "done") { handleDone (tdb, task, conf ); }
|
||||
else if (command == "export") { handleExport (tdb, task, conf ); }
|
||||
else if (command == "projects") { out = handleProjects (tdb, task, conf ); }
|
||||
else if (command == "tags") { out = handleTags (tdb, task, conf ); }
|
||||
else if (command == "info") { out = handleInfo (tdb, task, conf ); }
|
||||
else if (command == "undelete") { out = handleUndelete (tdb, task, conf ); }
|
||||
else if (command == "delete") { out = handleDelete (tdb, task, conf ); }
|
||||
else if (command == "start") { out = handleStart (tdb, task, conf ); }
|
||||
else if (command == "stop") { out = handleStop (tdb, task, conf ); }
|
||||
else if (command == "undo") { out = handleUndo (tdb, task, conf ); }
|
||||
else if (command == "stats") { out = handleReportStats (tdb, task, conf ); }
|
||||
else if (command == "list") { if (gc) tdb.gc (); out = handleList (tdb, task, conf ); } // TODO replace with Custom
|
||||
else if (command == "long") { if (gc) tdb.gc (); out = handleLongList (tdb, task, conf ); } // TODO replace with Custom
|
||||
else if (command == "ls") { if (gc) tdb.gc (); out = handleSmallList (tdb, task, conf ); } // TODO replace with Custom
|
||||
else if (command == "completed") { if (gc) tdb.gc (); out = handleCompleted (tdb, task, conf ); } // TODO replace with Custom
|
||||
else if (command == "summary") { if (gc) tdb.gc (); out = handleReportSummary (tdb, task, conf ); }
|
||||
else if (command == "next") { if (gc) tdb.gc (); out = handleReportNext (tdb, task, conf ); } // TODO replace with Custom
|
||||
else if (command == "history") { if (gc) tdb.gc (); out = handleReportHistory (tdb, task, conf ); }
|
||||
else if (command == "ghistory") { if (gc) tdb.gc (); out = handleReportGHistory (tdb, task, conf ); }
|
||||
else if (command == "calendar") { if (gc) tdb.gc (); out = handleReportCalendar (tdb, task, conf ); }
|
||||
else if (command == "active") { if (gc) tdb.gc (); out = handleReportActive (tdb, task, conf ); } // TODO replace with Custom
|
||||
else if (command == "overdue") { if (gc) tdb.gc (); out = handleReportOverdue (tdb, task, conf ); } // TODO replace with Custom
|
||||
else if (command == "oldest") { if (gc) tdb.gc (); out = handleReportOldest (tdb, task, conf ); } // TODO replace with Custom
|
||||
else if (command == "newest") { if (gc) tdb.gc (); out = handleReportNewest (tdb, task, conf ); } // TODO replace with Custom
|
||||
else if (command == "colors") { out = handleColor ( conf ); }
|
||||
else if (command == "version") { out = handleVersion ( conf ); }
|
||||
else if (command == "help") { longUsage ( conf ); }
|
||||
else if (isCustomReport (command)) { if (gc) tdb.gc (); out = handleCustomReport (tdb, task, conf, command); } // New Custom reports
|
||||
else { shortUsage ( conf ); }
|
||||
// Read-only commands with no side effects.
|
||||
if (command == "export") { out = handleExport (tdb, task, conf); }
|
||||
else if (command == "projects") { out = handleProjects (tdb, task, conf); }
|
||||
else if (command == "tags") { out = handleTags (tdb, task, conf); }
|
||||
else if (command == "info") { out = handleInfo (tdb, task, conf); }
|
||||
else if (command == "stats") { out = handleReportStats (tdb, task, conf); }
|
||||
else if (command == "history") { out = handleReportHistory (tdb, task, conf); }
|
||||
else if (command == "ghistory") { out = handleReportGHistory (tdb, task, conf); }
|
||||
else if (command == "calendar") { out = handleReportCalendar (tdb, task, conf); }
|
||||
else if (command == "summary") { out = handleReportSummary (tdb, task, conf); }
|
||||
else if (command == "timesheet") { out = handleReportTimesheet (tdb, task, conf); }
|
||||
else if (command == "colors") { out = handleColor ( conf); }
|
||||
else if (command == "version") { out = handleVersion ( conf); }
|
||||
else if (command == "help") { out = longUsage ( conf); }
|
||||
|
||||
// Commands that cause updates.
|
||||
else if (command == "" && task.getId ()) { cmdMod = true; out = handleModify (tdb, task, conf); }
|
||||
else if (command == "add") { cmdMod = true; out = handleAdd (tdb, task, conf); }
|
||||
else if (command == "append") { cmdMod = true; out = handleAppend (tdb, task, conf); }
|
||||
else if (command == "annotate") { cmdMod = true; out = handleAnnotate (tdb, task, conf); }
|
||||
else if (command == "done") { cmdMod = true; out = handleDone (tdb, task, conf); }
|
||||
else if (command == "undelete") { cmdMod = true; out = handleUndelete (tdb, task, conf); }
|
||||
else if (command == "delete") { cmdMod = true; out = handleDelete (tdb, task, conf); }
|
||||
else if (command == "start") { cmdMod = true; out = handleStart (tdb, task, conf); }
|
||||
else if (command == "stop") { cmdMod = true; out = handleStop (tdb, task, conf); }
|
||||
else if (command == "undo") { cmdMod = true; out = handleUndo (tdb, task, conf); }
|
||||
else if (command == "import") { cmdMod = true; out = handleImport (tdb, task, conf); }
|
||||
else if (command == "duplicate") { cmdMod = true; out = handleDuplicate (tdb, task, conf); }
|
||||
else if (command == "edit") { cmdMod = true; out = handleEdit (tdb, task, conf); }
|
||||
|
||||
// Command that display IDs and therefore need TDB::gc first.
|
||||
else if (command == "completed") { if (gc) gcMod = tdb.gc (); out = handleCompleted (tdb, task, conf); }
|
||||
else if (command == "next") { if (gc) gcMod = tdb.gc (); out = handleReportNext (tdb, task, conf); }
|
||||
else if (command == "active") { if (gc) gcMod = tdb.gc (); out = handleReportActive (tdb, task, conf); }
|
||||
else if (command == "overdue") { if (gc) gcMod = tdb.gc (); out = handleReportOverdue (tdb, task, conf); }
|
||||
else if (isCustomReport (command)) { if (gc) gcMod = tdb.gc (); out = handleCustomReport (tdb, task, conf, command); }
|
||||
|
||||
// If the command is not recognized, display usage.
|
||||
else { out = shortUsage (conf); }
|
||||
|
||||
// Only update the shadow file if such an update was not suppressed (shadow),
|
||||
// and if an actual change occurred (gcMod || cmdMod).
|
||||
if (shadow && (gcMod || cmdMod))
|
||||
updateShadowFile (tdb, conf);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
110
src/task.h
110
src/task.h
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2008, Paul Beckingham.
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -57,8 +57,10 @@ for (typeof (c) *foreach_p = & (c); \
|
||||
void parse (std::vector <std::string>&, std::string&, T&, Config&);
|
||||
bool validPriority (const std::string&);
|
||||
bool validDate (std::string&, Config&);
|
||||
bool validDuration (std::string&);
|
||||
void loadCustomReports (Config&);
|
||||
bool isCustomReport (const std::string&);
|
||||
void allCustomReports (std::vector <std::string>&);
|
||||
|
||||
// task.cpp
|
||||
void gatherNextTasks (const TDB&, T&, Config&, std::vector <T>&, std::vector <int>&);
|
||||
@@ -69,14 +71,15 @@ bool generateDueDates (T&, std::vector <Date>&);
|
||||
Date getNextRecurrence (Date&, std::string&);
|
||||
void updateRecurrenceMask (TDB&, std::vector <T>&, T&);
|
||||
void onChangeCallback ();
|
||||
std::string runTaskCommand (int, char**, TDB&, Config&, bool gc = true);
|
||||
std::string runTaskCommand (std::vector <std::string>&, TDB&, Config&, bool gc = false);
|
||||
std::string runTaskCommand (int, char**, TDB&, Config&, bool gc = true, bool shadow = true);
|
||||
std::string runTaskCommand (std::vector <std::string>&, TDB&, Config&, bool gc = false, bool shadow = false);
|
||||
|
||||
// command.cpp
|
||||
void handleAdd (TDB&, T&, Config&);
|
||||
void handleExport (TDB&, T&, Config&);
|
||||
void handleDone (TDB&, T&, Config&);
|
||||
void handleModify (TDB&, T&, Config&);
|
||||
std::string handleAdd (TDB&, T&, Config&);
|
||||
std::string handleAppend (TDB&, T&, Config&);
|
||||
std::string handleExport (TDB&, T&, Config&);
|
||||
std::string handleDone (TDB&, T&, Config&);
|
||||
std::string handleModify (TDB&, T&, Config&);
|
||||
std::string handleProjects (TDB&, T&, Config&);
|
||||
std::string handleTags (TDB&, T&, Config&);
|
||||
std::string handleUndelete (TDB&, T&, Config&);
|
||||
@@ -86,13 +89,22 @@ std::string handleStart (TDB&, T&, Config&);
|
||||
std::string handleStop (TDB&, T&, Config&);
|
||||
std::string handleUndo (TDB&, T&, Config&);
|
||||
std::string handleColor (Config&);
|
||||
std::string handleAnnotate (TDB&, T&, Config&);
|
||||
std::string handleDuplicate (TDB&, T&, Config&);
|
||||
T findT (int, const std::vector <T>&);
|
||||
int deltaAppend (T&, T&);
|
||||
int deltaDescription (T&, T&);
|
||||
int deltaTags (T&, T&);
|
||||
int deltaAttributes (T&, T&);
|
||||
int deltaSubstitutions (T&, T&);
|
||||
|
||||
// edit.cpp
|
||||
std::string handleEdit (TDB&, T&, Config&);
|
||||
|
||||
// report.cpp
|
||||
void filterSequence (std::vector<T>&, T&);
|
||||
void filter (std::vector<T>&, T&);
|
||||
std::string handleList (TDB&, T&, Config&);
|
||||
std::string handleInfo (TDB&, T&, Config&);
|
||||
std::string handleLongList (TDB&, T&, Config&);
|
||||
std::string handleSmallList (TDB&, T&, Config&);
|
||||
std::string handleCompleted (TDB&, T&, Config&);
|
||||
std::string handleReportSummary (TDB&, T&, Config&);
|
||||
std::string handleReportNext (TDB&, T&, Config&);
|
||||
@@ -102,18 +114,18 @@ std::string handleReportCalendar (TDB&, T&, Config&);
|
||||
std::string handleReportActive (TDB&, T&, Config&);
|
||||
std::string handleReportOverdue (TDB&, T&, Config&);
|
||||
std::string handleReportStats (TDB&, T&, Config&);
|
||||
std::string handleReportOldest (TDB&, T&, Config&);
|
||||
std::string handleReportNewest (TDB&, T&, Config&);
|
||||
std::string handleReportTimesheet (TDB&, T&, Config&);
|
||||
|
||||
std::string handleCustomReport (TDB&, T&, Config&, const std::string&);
|
||||
void validReportColumns (const std::vector <std::string>&);
|
||||
void validSortColumns (const std::vector <std::string>&, const std::vector <std::string>&);
|
||||
|
||||
// util.cpp
|
||||
bool confirm (const std::string&);
|
||||
// text.cpp
|
||||
void wrapText (std::vector <std::string>&, const std::string&, const int);
|
||||
std::string trimLeft (const std::string& in, const std::string& t = " ");
|
||||
std::string trimRight (const std::string& in, const std::string& t = " ");
|
||||
std::string trim (const std::string& in, const std::string& t = " ");
|
||||
void extractParagraphs (const std::string&, std::vector<std::string>&);
|
||||
std::string unquoteText (const std::string&);
|
||||
void extractLine (std::string&, std::string&, int);
|
||||
void split (std::vector<std::string>&, const std::string&, const char);
|
||||
void split (std::vector<std::string>&, const std::string&, const std::string&);
|
||||
@@ -121,17 +133,77 @@ void join (std::string&, const std::string&, const std::vector<std::string>&);
|
||||
std::string commify (const std::string&);
|
||||
std::string lowerCase (const std::string&);
|
||||
std::string upperCase (const std::string&);
|
||||
const char* optionalBlankLine (Config&);
|
||||
|
||||
// util.cpp
|
||||
bool confirm (const std::string&);
|
||||
void delay (float);
|
||||
int autoComplete (const std::string&, const std::vector<std::string>&, std::vector<std::string>&);
|
||||
void formatTimeDeltaDays (std::string&, time_t);
|
||||
std::string formatSeconds (time_t);
|
||||
int autoComplete (const std::string&, const std::vector<std::string>&, std::vector<std::string>&);
|
||||
const std::string uuid ();
|
||||
const char* optionalBlankLine (Config&);
|
||||
int convertDuration (std::string&);
|
||||
int convertDuration (const std::string&);
|
||||
std::string expandPath (const std::string&);
|
||||
|
||||
#ifdef SOLARIS
|
||||
#define LOCK_SH 1
|
||||
#define LOCK_EX 2
|
||||
#define LOCK_NB 4
|
||||
#define LOCK_UN 8
|
||||
|
||||
int flock (int, int);
|
||||
#endif
|
||||
|
||||
bool slurp (const std::string&, std::vector <std::string>&, bool trimLines = false);
|
||||
bool slurp (const std::string&, std::string&, bool trimLines = false);
|
||||
void spit (const std::string&, const std::string&);
|
||||
|
||||
// rules.cpp
|
||||
void initializeColorRules (Config&);
|
||||
void autoColorize (T&, Text::color&, Text::color&);
|
||||
void autoColorize (T&, Text::color&, Text::color&, Config&);
|
||||
|
||||
// import.cpp
|
||||
std::string handleImport (TDB&, T&, Config&);
|
||||
|
||||
// list template
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <class T> void listDiff (
|
||||
const T& left, const T& right, T& leftOnly, T& rightOnly)
|
||||
{
|
||||
leftOnly.clear ();
|
||||
rightOnly.clear ();
|
||||
|
||||
for (unsigned int l = 0; l < left.size (); ++l)
|
||||
{
|
||||
bool found = false;
|
||||
for (unsigned int r = 0; r < right.size (); ++r)
|
||||
{
|
||||
if (left[l] == right[r])
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
leftOnly.push_back (left[l]);
|
||||
}
|
||||
|
||||
for (unsigned int r = 0; r < right.size (); ++r)
|
||||
{
|
||||
bool found = false;
|
||||
for (unsigned int l = 0; l < left.size (); ++l)
|
||||
{
|
||||
if (left[l] == right[r])
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
rightOnly.push_back (right[r]);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
7
src/tests/.gitignore
vendored
7
src/tests/.gitignore
vendored
@@ -1,7 +1,8 @@
|
||||
t.t
|
||||
t.benchmark.t
|
||||
tdb.t
|
||||
date.t
|
||||
duration.t
|
||||
pending.data
|
||||
completed.data
|
||||
|
||||
text.t
|
||||
autocomplete.t
|
||||
parse.t
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
PROJECT = t.t tdb.t date.t duration.t
|
||||
PROJECT = t.t tdb.t date.t duration.t t.benchmark.t text.t autocomplete.t \
|
||||
parse.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
|
||||
@@ -29,3 +30,15 @@ date.t: date.t.o $(OBJECTS) test.o
|
||||
duration.t: duration.t.o $(OBJECTS) test.o
|
||||
g++ duration.t.o $(OBJECTS) test.o $(LFLAGS) -o duration.t
|
||||
|
||||
t.benchmark.t: t.benchmark.t.o $(OBJECTS) test.o
|
||||
g++ t.benchmark.t.o $(OBJECTS) test.o $(LFLAGS) -o t.benchmark.t
|
||||
|
||||
text.t: text.t.o $(OBJECTS) test.o
|
||||
g++ text.t.o $(OBJECTS) test.o $(LFLAGS) -o text.t
|
||||
|
||||
autocomplete.t: autocomplete.t.o $(OBJECTS) test.o
|
||||
g++ autocomplete.t.o $(OBJECTS) test.o $(LFLAGS) -o autocomplete.t
|
||||
|
||||
parse.t: parse.t.o $(OBJECTS) test.o
|
||||
g++ parse.t.o $(OBJECTS) test.o $(LFLAGS) -o parse.t
|
||||
|
||||
|
||||
99
src/tests/abbreviation.t
Executable file
99
src/tests/abbreviation.t
Executable file
@@ -0,0 +1,99 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 22;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'abbrev.rc')
|
||||
{
|
||||
print $fh "data.location=.\n";
|
||||
close $fh;
|
||||
ok (-r 'abbrev.rc', 'Created abbrev.rc');
|
||||
}
|
||||
|
||||
# Test the priority attribute abbrevations.
|
||||
qx{../task rc:abbrev.rc add priority:H with};
|
||||
qx{../task rc:abbrev.rc add without};
|
||||
|
||||
my $output = qx{../task rc:abbrev.rc list priority:H};
|
||||
like ($output, qr/\bwith\b/, 'priority:H with');
|
||||
unlike ($output, qr/\bwithout\b/, 'priority:H without');
|
||||
|
||||
$output = qx{../task rc:abbrev.rc list priorit:H};
|
||||
like ($output, qr/\bwith\b/, 'priorit:H with');
|
||||
unlike ($output, qr/\bwithout\b/, 'priorit:H without');
|
||||
|
||||
$output = qx{../task rc:abbrev.rc list priori:H};
|
||||
like ($output, qr/\bwith\b/, 'priori:H with');
|
||||
unlike ($output, qr/\bwithout\b/, 'priori:H without');
|
||||
|
||||
$output = qx{../task rc:abbrev.rc list prior:H};
|
||||
like ($output, qr/\bwith\b/, 'prior:H with');
|
||||
unlike ($output, qr/\bwithout\b/, 'prior:H without');
|
||||
|
||||
$output = qx{../task rc:abbrev.rc list prio:H};
|
||||
like ($output, qr/\bwith\b/, 'prio:H with');
|
||||
unlike ($output, qr/\bwithout\b/, 'prio:H without');
|
||||
|
||||
$output = qx{../task rc:abbrev.rc list pri:H};
|
||||
like ($output, qr/\bwith\b/, 'pri:H with');
|
||||
unlike ($output, qr/\bwithout\b/, 'pri:H without');
|
||||
|
||||
# Test the version command abbreviations.
|
||||
$output = qx{../task rc:abbrev.rc version};
|
||||
like ($output, qr/ABSOLUTELY NO WARRANTY/, 'version');
|
||||
|
||||
$output = qx{../task rc:abbrev.rc versio};
|
||||
like ($output, qr/ABSOLUTELY NO WARRANTY/, 'versio');
|
||||
|
||||
$output = qx{../task rc:abbrev.rc versi};
|
||||
like ($output, qr/ABSOLUTELY NO WARRANTY/, 'versi');
|
||||
|
||||
$output = qx{../task rc:abbrev.rc vers};
|
||||
like ($output, qr/ABSOLUTELY NO WARRANTY/, 'vers');
|
||||
|
||||
$output = qx{../task rc:abbrev.rc ver};
|
||||
like ($output, qr/ABSOLUTELY NO WARRANTY/, 'ver');
|
||||
|
||||
$output = qx{../task rc:abbrev.rc ve};
|
||||
like ($output, qr/ABSOLUTELY NO WARRANTY/, 've');
|
||||
|
||||
$output = qx{../task rc:abbrev.rc v};
|
||||
like ($output, qr/ABSOLUTELY NO WARRANTY/, 'v');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'abbrev.rc';
|
||||
ok (!-r 'abbrev.rc', 'Removed abbrev.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
72
src/tests/add.t
Executable file
72
src/tests/add.t
Executable file
@@ -0,0 +1,72 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 14;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'add.rc')
|
||||
{
|
||||
print $fh "data.location=.\n";
|
||||
close $fh;
|
||||
ok (-r 'add.rc', 'Created add.rc');
|
||||
}
|
||||
|
||||
# Test the add command.
|
||||
my $output = qx{../task rc:add.rc add This is a test; ../task rc:add.rc info 1};
|
||||
like ($output, qr/ID\s+1\n/, 'add ID');
|
||||
like ($output, qr/Description\s+This is a test\n/, 'add ID');
|
||||
like ($output, qr/Status\s+Pending\n/, 'add Pending');
|
||||
like ($output, qr/UUID\s+[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}\n/, 'add UUID');
|
||||
|
||||
# Test the /// modifier.
|
||||
$output = qx{../task rc:add.rc 1 /test/TEST/; ../task rc:add.rc 1 "/is //"; ../task rc:add.rc info 1};
|
||||
like ($output, qr/ID\s+1\n/, 'add ID');
|
||||
like ($output, qr/Status\s+Pending\n/, 'add Pending');
|
||||
like ($output, qr/Description\s+This a TEST\n/, 'add ID');
|
||||
|
||||
# Test delete.
|
||||
$output = qx{../task rc:add.rc delete 1; ../task rc:add.rc info 1};
|
||||
like ($output, qr/ID\s+1\n/, 'add ID');
|
||||
like ($output, qr/Status\s+Deleted\n/, 'add Deleted');
|
||||
|
||||
# Test undelete.
|
||||
$output = qx{../task rc:add.rc undelete 1; ../task rc:add.rc info 1};
|
||||
like ($output, qr/ID\s+1\n/, 'add ID');
|
||||
like ($output, qr/Status\s+Pending\n/, 'add Pending');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'add.rc';
|
||||
ok (!-r 'add.rc', 'Removed add.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
74
src/tests/annotate.t
Executable file
74
src/tests/annotate.t
Executable file
@@ -0,0 +1,74 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 8;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'annotate.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"report.r.description=r\n",
|
||||
"report.r.columns=id,description\n",
|
||||
"report.r.sort=id+\n";
|
||||
close $fh;
|
||||
ok (-r 'annotate.rc', 'Created annotate.rc');
|
||||
}
|
||||
|
||||
# Add two tasks, annotate one twice.
|
||||
qx{../task rc:annotate.rc add one};
|
||||
qx{../task rc:annotate.rc add two};
|
||||
qx{../task rc:annotate.rc annotate 1 foo};
|
||||
sleep 2;
|
||||
qx{../task rc:annotate.rc annotate 1 bar};
|
||||
my $output = qx{../task rc:annotate.rc r};
|
||||
|
||||
# ID Description
|
||||
# -- -------------------------------
|
||||
# 1 one
|
||||
# 3/24/2009 foo
|
||||
# 3/24/2009 bar
|
||||
# 2 two
|
||||
#
|
||||
# 2 tasks
|
||||
like ($output, qr/1 one/, 'task 1');
|
||||
like ($output, qr/2 two/, 'task 2');
|
||||
like ($output, qr/one.+\d{1,2}\/\d{1,2}\/\d{4} foo/ms, 'first annotation');
|
||||
like ($output, qr/foo.+\d{1,2}\/\d{1,2}\/\d{4} bar/ms, 'second annotation');
|
||||
like ($output, qr/2 tasks/, 'count');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'annotate.rc';
|
||||
ok (!-r 'annotate.rc', 'Removed annotate.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
55
src/tests/append.t
Executable file
55
src/tests/append.t
Executable file
@@ -0,0 +1,55 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 4;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'append.rc')
|
||||
{
|
||||
print $fh "data.location=.\n";
|
||||
close $fh;
|
||||
ok (-r 'append.rc', 'Created append.rc');
|
||||
}
|
||||
|
||||
# Add a task, then append more decsription.
|
||||
qx{../task rc:append.rc add foo};
|
||||
qx{../task rc:append.rc 1 append bar};
|
||||
my $output = qx{../task rc:append.rc info 1};
|
||||
like ($output, qr/Description\s+foo\sbar\n/, 'append worked');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'append.rc';
|
||||
ok (!-r 'append.rc', 'Removed append.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
63
src/tests/autocomplete.t.cpp
Normal file
63
src/tests/autocomplete.t.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free Software
|
||||
// Foundation; either version 2 of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
// details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program; if not, write to the
|
||||
//
|
||||
// Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor,
|
||||
// Boston, MA
|
||||
// 02110-1301
|
||||
// USA
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#include <iostream>
|
||||
#include <test.h>
|
||||
#include <../task.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
UnitTest t (8);
|
||||
|
||||
std::vector <std::string> options;
|
||||
options.push_back ("abc");
|
||||
options.push_back ("abcd");
|
||||
options.push_back ("abcde");
|
||||
options.push_back ("bcdef");
|
||||
options.push_back ("cdefg");
|
||||
|
||||
std::vector <std::string> matches;
|
||||
int result = autoComplete ("", options, matches);
|
||||
t.is (result, 0, "no match on empty string");
|
||||
|
||||
result = autoComplete ("x", options, matches);
|
||||
t.is (result, 0, "no match on wrong string");
|
||||
|
||||
result = autoComplete ("abcd", options, matches);
|
||||
t.is (result, 1, "exact match on 'abcd'");
|
||||
t.is (matches[0], "abcd", "exact match on 'abcd'");
|
||||
|
||||
result = autoComplete ("ab", options, matches);
|
||||
t.is (result, 3, "partial match on 'ab'");
|
||||
t.is (matches[0], "abc", "partial match on 'abc'");
|
||||
t.is (matches[1], "abcd", "partial match on 'abcd'");
|
||||
t.is (matches[2], "abcde", "partial match on 'abcde'");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
57
src/tests/basic.t
Executable file
57
src/tests/basic.t
Executable file
@@ -0,0 +1,57 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 7;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'basic.rc')
|
||||
{
|
||||
print $fh "data.location=.\n";
|
||||
close $fh;
|
||||
ok (-r 'basic.rc', 'Created basic.rc');
|
||||
}
|
||||
|
||||
# Test the usage command.
|
||||
my $output = qx{../task rc:basic.rc};
|
||||
like ($output, qr/Usage: task/, 'usage');
|
||||
like ($output, qr/http:\/\/www\.beckingham\.net\/task\.html/, 'usage - url');
|
||||
|
||||
# Test the version command.
|
||||
$output = qx{../task rc:basic.rc version};
|
||||
like ($output, qr/task \d+\.\d+\.\d+/, 'version - task version number');
|
||||
like ($output, qr/ABSOLUTELY NO WARRANTY/, 'version - warranty');
|
||||
like ($output, qr/http:\/\/www\.beckingham\.net\/task\.html/, 'version - url');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'basic.rc';
|
||||
ok (!-r 'basic.rc', 'Removed basic.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
103
src/tests/benchmark.t
Executable file
103
src/tests/benchmark.t
Executable file
@@ -0,0 +1,103 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 4;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'bench.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"_forcecolor=1\n";
|
||||
close $fh;
|
||||
ok (-r 'bench.rc', 'Created bench.rc');
|
||||
}
|
||||
|
||||
# Do lots of things. Time it all.
|
||||
|
||||
my @tags = qw(t_one t_two t_three t_four t_five t_six t_seven t_eight);
|
||||
my @projects = qw(p_one p_two p_three p_foud p_five p_six p_seven p_eight);
|
||||
my @priorities = qw(H M L);
|
||||
my $description = 'This is a medium-sized description with no special characters';
|
||||
|
||||
# Start the clock.
|
||||
my $start = time ();
|
||||
my $cursor = $start;
|
||||
diag ("start=$start");
|
||||
|
||||
# Make a mess.
|
||||
for my $i (1 .. 1000)
|
||||
{
|
||||
my $project = $projects[rand % 8];
|
||||
my $priority = $priorities[rand % 3];
|
||||
my $tag = $tags[rand % 8];
|
||||
|
||||
qx{../task rc:bench.rc add project:$project priority:$priority +$tag $i $description};
|
||||
}
|
||||
diag ("1000 tasks added in " . (time () - $cursor) . " seconds");
|
||||
$cursor = time ();
|
||||
|
||||
qx{../task rc:bench.rc /with/WITH/} for 1 .. 200;
|
||||
qx{../task rc:bench.rc done $_} for 201 .. 400;
|
||||
qx{../task rc:bench.rc start $_} for 401 .. 600;
|
||||
diag ("600 tasks altered in " . (time () - $cursor) . " seconds");
|
||||
$cursor = time ();
|
||||
|
||||
# Report it all. Note that all Timer information is displayed.
|
||||
|
||||
for (1 .. 100)
|
||||
{
|
||||
diag (grep {/^Timer /} qx{../task rc:bench.rc ls});
|
||||
diag (grep {/^Timer /} qx{../task rc:bench.rc list});
|
||||
diag (grep {/^Timer /} qx{../task rc:bench.rc list priority:H});
|
||||
diag (grep {/^Timer /} qx{../task rc:bench.rc list +tag});
|
||||
diag (grep {/^Timer /} qx{../task rc:bench.rc list project_A});
|
||||
diag (grep {/^Timer /} qx{../task rc:bench.rc long});
|
||||
diag (grep {/^Timer /} qx{../task rc:bench.rc completed});
|
||||
diag (grep {/^Timer /} qx{../task rc:bench.rc history});
|
||||
diag (grep {/^Timer /} qx{../task rc:bench.rc ghistory});
|
||||
}
|
||||
|
||||
# Stop the clock.
|
||||
my $stop = time ();
|
||||
diag ("stop=$stop");
|
||||
diag ("total=" . ($stop - $start));
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'completed.data';
|
||||
ok (!-r 'completed.data', 'Removed completed.data');
|
||||
|
||||
unlink 'bench.rc';
|
||||
ok (!-r 'bench.rc', 'Removed bench.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
40
src/tests/benchmark.txt
Normal file
40
src/tests/benchmark.txt
Normal file
@@ -0,0 +1,40 @@
|
||||
3/8/2009
|
||||
Before:
|
||||
Table::render
|
||||
26.1792
|
||||
16.67
|
||||
18.9697
|
||||
28.6328
|
||||
1.86553
|
||||
0.00044
|
||||
0.000319
|
||||
---------
|
||||
92.317989
|
||||
|
||||
After Table::optimize removed:
|
||||
Table::render
|
||||
0.146177
|
||||
0.145928
|
||||
0.184444
|
||||
0.014784
|
||||
0.000512
|
||||
0.000267
|
||||
---------
|
||||
0.492112
|
||||
|
||||
Speedup:
|
||||
92.317989 / 0.492112 = 187.6
|
||||
|
||||
3/8/2009
|
||||
New benchmark:
|
||||
1..4
|
||||
ok 1 - Created bench.rc
|
||||
# start=1236565862
|
||||
# 1000 tasks added in 3 seconds
|
||||
# 600 tasks altered in 28 seconds
|
||||
# stop=1236566048
|
||||
# total=186
|
||||
ok 2 - Removed pending.data
|
||||
ok 3 - Removed completed.data
|
||||
ok 4 - Removed bench.rc
|
||||
|
||||
79
src/tests/bug.annual.t
Executable file
79
src/tests/bug.annual.t
Executable file
@@ -0,0 +1,79 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 13;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'annual.rc')
|
||||
{
|
||||
print $fh "data.location=.\n";
|
||||
close $fh;
|
||||
ok (-r 'annual.rc', 'Created annual.rc');
|
||||
}
|
||||
|
||||
# If a task is added with a due date ten years ago, with an annual recurrence,
|
||||
# then the synthetic tasks in between then and now have a due date that creeps.
|
||||
#
|
||||
# ID Project Pri Due Active Age Description
|
||||
# -- ------- --- ---------- ------ --- -----------
|
||||
# 2 1/1/2000 - foo
|
||||
# 3 12/31/2000 - foo
|
||||
# 4 12/31/2001 - foo
|
||||
# 5 12/31/2002 - foo
|
||||
# 6 12/31/2003 - foo
|
||||
# 7 12/30/2004 - foo
|
||||
# 8 12/30/2005 - foo
|
||||
# 9 12/30/2006 - foo
|
||||
# 10 12/30/2007 - foo
|
||||
# 11 12/29/2008 - foo
|
||||
# 12 12/29/2009 - foo
|
||||
|
||||
qx{../task rc:annual.rc add foo due:1/1/2000 recur:annual until:1/1/2009};
|
||||
my $output = qx{../task rc:annual.rc list};
|
||||
like ($output, qr/2\s+1\/1\/2000\s+- foo/, 'synthetic 1 no creep');
|
||||
like ($output, qr/3\s+1\/1\/2001\s+- foo/, 'synthetic 2 no creep');
|
||||
like ($output, qr/4\s+1\/1\/2002\s+- foo/, 'synthetic 3 no creep');
|
||||
like ($output, qr/5\s+1\/1\/2003\s+- foo/, 'synthetic 4 no creep');
|
||||
like ($output, qr/6\s+1\/1\/2004\s+- foo/, 'synthetic 5 no creep');
|
||||
like ($output, qr/7\s+1\/1\/2005\s+- foo/, 'synthetic 6 no creep');
|
||||
like ($output, qr/8\s+1\/1\/2006\s+- foo/, 'synthetic 7 no creep');
|
||||
like ($output, qr/9\s+1\/1\/2007\s+- foo/, 'synthetic 8 no creep');
|
||||
like ($output, qr/10\s+1\/1\/2008\s+- foo/, 'synthetic 9 no creep');
|
||||
like ($output, qr/11\s+1\/1\/2009\s+- foo/, 'synthetic 10 no creep');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'annual.rc';
|
||||
ok (!-r 'annual.rc', 'Removed annual.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
77
src/tests/bug.concat.t
Executable file
77
src/tests/bug.concat.t
Executable file
@@ -0,0 +1,77 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 6;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'bug_concat.rc')
|
||||
{
|
||||
print $fh "data.location=.\n";
|
||||
close $fh;
|
||||
ok (-r 'bug_concat.rc', 'Created bug_concat.rc');
|
||||
}
|
||||
|
||||
# When a task is modified like this:
|
||||
#
|
||||
# % task 1 This is a new description
|
||||
#
|
||||
# The arguments are concatenated thus:
|
||||
#
|
||||
# Thisisanewdescription
|
||||
|
||||
qx{../task rc:bug_concat.rc add This is the original text};
|
||||
my $output = qx{../task rc:bug_concat.rc info 1};
|
||||
like ($output, qr/Description\s+This is the original text\n/, 'original correct');
|
||||
|
||||
qx{../task rc:bug_concat.rc 1 This is the modified text};
|
||||
$output = qx{../task rc:bug_concat.rc info 1};
|
||||
like ($output, qr/Description\s+This is the modified text\n/, 'modified correct');
|
||||
|
||||
# When a task is added like this:
|
||||
#
|
||||
# % task add aaa bbb:ccc ddd
|
||||
#
|
||||
# The description is concatenated thus:
|
||||
#
|
||||
# aaabbb:ccc ddd
|
||||
|
||||
qx{../task rc:bug_concat.rc add aaa bbb:ccc ddd};
|
||||
$output = qx{../task rc:bug_concat.rc info 2};
|
||||
like ($output, qr/Description\s+aaa bbb:ccc ddd\n/, 'properly concatenated');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'bug_concat.rc';
|
||||
ok (!-r 'bug_concat.rc', 'Removed bug_concat.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
83
src/tests/bug.hang.t
Executable file
83
src/tests/bug.hang.t
Executable file
@@ -0,0 +1,83 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 5;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'hang.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"shadow.file=shadow.txt\n",
|
||||
"shadow.command=list\n";
|
||||
close $fh;
|
||||
ok (-r 'hang.rc', 'Created hang.rc');
|
||||
}
|
||||
|
||||
=pod
|
||||
I found a bug in the current version of task. Using recur and a shadow file will
|
||||
lead to an infinite loop. To reproduce it, define a shadow file in the .taskrc,
|
||||
set a command for it that rebuilds the database, e.g. "list", and then add a
|
||||
task with a recurrence set, e.g. "task add due:today recur:1d infinite loop".
|
||||
Task will then loop forever and add the same recurring task until it runs out of
|
||||
memory. So I checked the source and I believe I found the cause.
|
||||
handleRecurrence() in task.cpp will modify the mask, but writes it only after it
|
||||
has added all new tasks. Adding the task will, however, invoke onChangeCallback,
|
||||
which starts the same process all over again.
|
||||
=cut
|
||||
|
||||
eval
|
||||
{
|
||||
$SIG{'ALRM'} = sub {die "alarm\n"};
|
||||
alarm 10;
|
||||
my $output = qx{../task rc:hang.rc list;
|
||||
../task rc:hang.rc add due:today recur:1d infinite loop;
|
||||
../task rc:hang.rc info 1};
|
||||
alarm 0;
|
||||
|
||||
like ($output, qr/^Description\s+infinite loop\n/m, 'no hang');
|
||||
};
|
||||
|
||||
if ($@ eq "alarm\n")
|
||||
{
|
||||
fail ('task hang on add or recurring task, with shadow file, for 10s');
|
||||
}
|
||||
|
||||
# Cleanup.
|
||||
unlink 'shadow.txt';
|
||||
ok (!-r 'shadow.txt', 'Removed shadow.txt');
|
||||
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'hang.rc';
|
||||
ok (!-r 'hang.rc', 'Removed hang.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
164
src/tests/bug.period.t
Executable file
164
src/tests/bug.period.t
Executable file
@@ -0,0 +1,164 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 41;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'period.rc')
|
||||
{
|
||||
print $fh "data.location=.\n";
|
||||
close $fh;
|
||||
ok (-r 'period.rc', 'Created period.rc');
|
||||
}
|
||||
|
||||
=pod
|
||||
http://github.com/pbeckingham/task/blob/857f813a24f7ce15fea9f2c28aadad84cb5c8847/src/task.cpp
|
||||
619 // If the period is an 'easy' one, add it to current, and we're done.
|
||||
620 int days = convertDuration (period);
|
||||
|
||||
Date getNextRecurrence (Date& current, std::string& period)
|
||||
|
||||
starting at line 509 special cases several possibilities for period, '\d\s?m'
|
||||
'monthly', 'quarterly', 'semiannual', 'bimonthly', 'biannual', 'biyearly'.
|
||||
Everything else falls through with period being passed to convertDuration.
|
||||
convertDuration doesn't know about 'daily' though so it seems to be returning 0.
|
||||
|
||||
Confirmed:
|
||||
getNextRecurrence convertDuration
|
||||
----------------- ---------------
|
||||
daily
|
||||
day
|
||||
weekly
|
||||
sennight
|
||||
biweekly
|
||||
fortnight
|
||||
monthly monthly
|
||||
quarterly quarterly
|
||||
semiannual semiannual
|
||||
bimonthly bimonthly
|
||||
biannual biannual
|
||||
biyearly biyearly
|
||||
annual
|
||||
yearly
|
||||
*m *m
|
||||
*q *q
|
||||
*d
|
||||
*w
|
||||
*y
|
||||
=cut
|
||||
|
||||
my $output = qx{../task rc:period.rc add daily due:tomorrow recur:daily};
|
||||
like ($output, qr/^$/, 'recur:daily');
|
||||
|
||||
$output = qx{../task rc:period.rc add day due:tomorrow recur:day};
|
||||
like ($output, qr/^$/, 'recur:day');
|
||||
|
||||
$output = qx{../task rc:period.rc add weekly due:tomorrow recur:weekly};
|
||||
like ($output, qr/^$/, 'recur:weekly');
|
||||
|
||||
$output = qx{../task rc:period.rc add sennight due:tomorrow recur:sennight};
|
||||
like ($output, qr/^$/, 'recur:sennight');
|
||||
|
||||
$output = qx{../task rc:period.rc add biweekly due:tomorrow recur:biweekly};
|
||||
like ($output, qr/^$/, 'recur:biweekly');
|
||||
|
||||
$output = qx{../task rc:period.rc add fortnight due:tomorrow recur:fortnight};
|
||||
like ($output, qr/^$/, 'recur:fortnight');
|
||||
|
||||
$output = qx{../task rc:period.rc add monthly due:tomorrow recur:monthly};
|
||||
like ($output, qr/^$/, 'recur:monthly');
|
||||
|
||||
$output = qx{../task rc:period.rc add quarterly due:tomorrow recur:quarterly};
|
||||
like ($output, qr/^$/, 'recur:quarterly');
|
||||
|
||||
$output = qx{../task rc:period.rc add semiannual due:tomorrow recur:semiannual};
|
||||
like ($output, qr/^$/, 'recur:semiannual');
|
||||
|
||||
$output = qx{../task rc:period.rc add bimonthly due:tomorrow recur:bimonthly};
|
||||
like ($output, qr/^$/, 'recur:bimonthly');
|
||||
|
||||
$output = qx{../task rc:period.rc add biannual due:tomorrow recur:biannual};
|
||||
like ($output, qr/^$/, 'recur:biannual');
|
||||
|
||||
$output = qx{../task rc:period.rc add biyearly due:tomorrow recur:biyearly};
|
||||
like ($output, qr/^$/, 'recur:biyearly');
|
||||
|
||||
$output = qx{../task rc:period.rc add annual due:tomorrow recur:annual};
|
||||
like ($output, qr/^$/, 'recur:annual');
|
||||
|
||||
$output = qx{../task rc:period.rc add yearly due:tomorrow recur:yearly};
|
||||
like ($output, qr/^$/, 'recur:yearly');
|
||||
|
||||
$output = qx{../task rc:period.rc add 2d due:tomorrow recur:2d};
|
||||
like ($output, qr/^$/, 'recur:2m');
|
||||
|
||||
$output = qx{../task rc:period.rc add 2w due:tomorrow recur:2w};
|
||||
like ($output, qr/^$/, 'recur:2q');
|
||||
|
||||
$output = qx{../task rc:period.rc add 2m due:tomorrow recur:2m};
|
||||
like ($output, qr/^$/, 'recur:2d');
|
||||
|
||||
$output = qx{../task rc:period.rc add 2q due:tomorrow recur:2q};
|
||||
like ($output, qr/^$/, 'recur:2w');
|
||||
|
||||
$output = qx{../task rc:period.rc add 2y due:tomorrow recur:2y};
|
||||
like ($output, qr/^$/, 'recur:2y');
|
||||
|
||||
# Verify that the recurring task instances get created. One of each.
|
||||
$output = qx{../task rc:period.rc list};
|
||||
like ($output, qr/\bdaily\b/, 'verify daily');
|
||||
like ($output, qr/\bday\b/, 'verify day');
|
||||
like ($output, qr/\bweekly\b/, 'verify weekly');
|
||||
like ($output, qr/\bsennight\b/, 'verify sennight');
|
||||
like ($output, qr/\bbiweekly\b/, 'verify biweekly');
|
||||
like ($output, qr/\bfortnight\b/, 'verify fortnight');
|
||||
like ($output, qr/\bmonthly\b/, 'verify monthly');
|
||||
like ($output, qr/\bquarterly\b/, 'verify quarterly');
|
||||
like ($output, qr/\bsemiannual\b/, 'verify semiannual');
|
||||
like ($output, qr/\bbimonthly\b/, 'verify bimonthly');
|
||||
like ($output, qr/\bbiannual\b/, 'verify biannual');
|
||||
like ($output, qr/\bbiyearly\b/, 'verify biyearly');
|
||||
like ($output, qr/\bannual\b/, 'verify annual');
|
||||
like ($output, qr/\byearly\b/, 'verify yearly');
|
||||
like ($output, qr/\b2d\b/, 'verify 2d');
|
||||
like ($output, qr/\b2w\b/, 'verify 2w');
|
||||
like ($output, qr/\b2m\b/, 'verify 2m');
|
||||
like ($output, qr/\b2q\b/, 'verify 2q');
|
||||
like ($output, qr/\b2y\b/, 'verify 2y');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'period.rc';
|
||||
ok (!-r 'period.rc', 'Removed period.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
61
src/tests/bug.sort.t
Executable file
61
src/tests/bug.sort.t
Executable file
@@ -0,0 +1,61 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 5;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'bug_sort.rc')
|
||||
{
|
||||
print $fh "data.location=.\n";
|
||||
close $fh;
|
||||
ok (-r 'bug_sort.rc', 'Created bug_sort.rc');
|
||||
}
|
||||
|
||||
my $setup = "../task rc:bug_sort.rc add one;"
|
||||
. "../task rc:bug_sort.rc add two;"
|
||||
. "../task rc:bug_sort.rc add three recur:daily due:eom;";
|
||||
qx{$setup};
|
||||
|
||||
my $output = qx{../task rc:bug_sort.rc list};
|
||||
like ($output, qr/three.*(?:one.*two|two.*one)/msi, 'list did not hang');
|
||||
|
||||
qx{../task rc:bug_sort.rc 1 priority:H};
|
||||
$output = qx{../task rc:bug_sort.rc list};
|
||||
like ($output, qr/three.*one.*two/msi, 'list did not hang after pri:H on 1');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'bug_sort.rc';
|
||||
ok (!-r 'bug_sort.rc', 'Removed bug_sort.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
67
src/tests/bug.summary.t
Executable file
67
src/tests/bug.summary.t
Executable file
@@ -0,0 +1,67 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 6;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'summary.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"confirmation=no\n";
|
||||
close $fh;
|
||||
ok (-r 'summary.rc', 'Created summary.rc');
|
||||
}
|
||||
|
||||
# Add three tasks. Do 1, delete 1, leave 1 pending. Summary should depict a
|
||||
# 50% completion.
|
||||
qx{../task rc:summary.rc add project:A one};
|
||||
qx{../task rc:summary.rc add project:A two};
|
||||
qx{../task rc:summary.rc add project:A three};
|
||||
qx{../task rc:summary.rc do 1};
|
||||
qx{../task rc:summary.rc delete 2};
|
||||
my $output = qx{../task rc:summary.rc summary};
|
||||
like ($output, qr/A\s+1\s+-\s+50%/, 'summary correctly shows 50% before report');
|
||||
|
||||
qx{../task rc:summary.rc list};
|
||||
$output = qx{../task rc:summary.rc summary};
|
||||
like ($output, qr/A\s+1\s+-\s+50%/, 'summary correctly shows 50% after report');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'completed.data';
|
||||
ok (!-r 'completed.data', 'Removed completed.data');
|
||||
|
||||
unlink 'summary.rc';
|
||||
ok (!-r 'summary.rc', 'Removed summary.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
60
src/tests/color.active.t
Executable file
60
src/tests/color.active.t
Executable file
@@ -0,0 +1,60 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 5;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'color.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"color.active=red\n",
|
||||
"_forcecolor=1\n";
|
||||
close $fh;
|
||||
ok (-r 'color.rc', 'Created color.rc');
|
||||
}
|
||||
|
||||
# Test the add command.
|
||||
qx{../task rc:color.rc add nothing};
|
||||
qx{../task rc:color.rc add red};
|
||||
qx{../task rc:color.rc start 2};
|
||||
my $output = qx{../task rc:color.rc list};
|
||||
|
||||
like ($output, qr/ (?!<\033\[\d\dm) .* nothing .* (?!>\033\[0m) /x, 'none');
|
||||
like ($output, qr/ \033\[31m .* red .* \033\[0m /x, 'color.active');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'color.rc';
|
||||
ok (!-r 'color.rc', 'Removed color.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
58
src/tests/color.disable.t
Executable file
58
src/tests/color.disable.t
Executable file
@@ -0,0 +1,58 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 6;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'color.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"color.pri.H=red\n";
|
||||
close $fh;
|
||||
ok (-r 'color.rc', 'Created color.rc');
|
||||
}
|
||||
|
||||
# Test the add command.
|
||||
qx{../task rc:color.rc add priority:H red};
|
||||
my $output = qx{../task rc:color.rc list};
|
||||
|
||||
like ($output, qr/red/, 'color.disable - found red');
|
||||
unlike ($output, qr/\033\[31m/, 'color.disable - no color red');
|
||||
unlike ($output, qr/\033\[0m/, 'color.disable - no color reset');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'color.rc';
|
||||
ok (!-r 'color.rc', 'Removed color.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
59
src/tests/color.due.t
Executable file
59
src/tests/color.due.t
Executable file
@@ -0,0 +1,59 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 5;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'color.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"color.due=red\n",
|
||||
"_forcecolor=1\n";
|
||||
close $fh;
|
||||
ok (-r 'color.rc', 'Created color.rc');
|
||||
}
|
||||
|
||||
# Test the add command.
|
||||
qx{../task rc:color.rc add due:eoy nothing};
|
||||
qx{../task rc:color.rc add due:tomorrow red};
|
||||
my $output = qx{../task rc:color.rc list};
|
||||
|
||||
like ($output, qr/ (?!<\033\[\d\dm) \d{1,2}\/\d{1,2}\/\d{4} (?!>\033\[0m) .* nothing /x, 'none');
|
||||
like ($output, qr/ \033\[31m .* red .* \033\[0m/x, 'color.due');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'color.rc';
|
||||
ok (!-r 'color.rc', 'Removed color.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
62
src/tests/color.keyword.t
Executable file
62
src/tests/color.keyword.t
Executable file
@@ -0,0 +1,62 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 6;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'color.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"color.keyword.red=red\n",
|
||||
"color.keyword.green=green\n",
|
||||
"_forcecolor=1\n";
|
||||
close $fh;
|
||||
ok (-r 'color.rc', 'Created color.rc');
|
||||
}
|
||||
|
||||
# Test the add command.
|
||||
qx{../task rc:color.rc add nothing};
|
||||
qx{../task rc:color.rc add red};
|
||||
qx{../task rc:color.rc add green};
|
||||
my $output = qx{../task rc:color.rc list};
|
||||
|
||||
like ($output, qr/ (?!<\033\[\d\dm) .* nothing .* (?!>\033\[0m) /x, 'none');
|
||||
like ($output, qr/ \033\[31m .* red .* \033\[0m /x, 'color.keyword.red');
|
||||
like ($output, qr/ \033\[32m .* green .* \033\[0m /x, 'color.keyword.green');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'color.rc';
|
||||
ok (!-r 'color.rc', 'Removed color.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
59
src/tests/color.overdue.t
Executable file
59
src/tests/color.overdue.t
Executable file
@@ -0,0 +1,59 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 5;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'color.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"color.overdue=red\n",
|
||||
"_forcecolor=1\n";
|
||||
close $fh;
|
||||
ok (-r 'color.rc', 'Created color.rc');
|
||||
}
|
||||
|
||||
# Test the add command.
|
||||
qx{../task rc:color.rc add due:tomorrow nothing};
|
||||
qx{../task rc:color.rc add due:yesterday red};
|
||||
my $output = qx{../task rc:color.rc list};
|
||||
|
||||
like ($output, qr/ (?!<\033\[\d\dm) \d{1,2}\/\d{1,2}\/\d{4} (?!>\033\[0m) .* nothing /x, 'none');
|
||||
like ($output, qr/ \033\[31m .* red .* \033\[0m/x, 'color.overdue');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'color.rc';
|
||||
ok (!-r 'color.rc', 'Removed color.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
66
src/tests/color.pri.t
Executable file
66
src/tests/color.pri.t
Executable file
@@ -0,0 +1,66 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 7;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'color.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"color.pri.H=red\n",
|
||||
"color.pri.M=green\n",
|
||||
"color.pri.L=blue\n",
|
||||
"color.pri.none=yellow\n",
|
||||
"_forcecolor=1\n";
|
||||
close $fh;
|
||||
ok (-r 'color.rc', 'Created color.rc');
|
||||
}
|
||||
|
||||
# Test the add command.
|
||||
qx{../task rc:color.rc add priority:H red};
|
||||
qx{../task rc:color.rc add priority:M green};
|
||||
qx{../task rc:color.rc add priority:L blue};
|
||||
qx{../task rc:color.rc add yellow};
|
||||
my $output = qx{../task rc:color.rc list};
|
||||
|
||||
like ($output, qr/ \033\[31m .* red .* \033\[0m /x, 'color.pri.H');
|
||||
like ($output, qr/ \033\[32m .* green .* \033\[0m /x, 'color.pri.M');
|
||||
like ($output, qr/ \033\[34m .* blue .* \033\[0m /x, 'color.pri.L');
|
||||
like ($output, qr/ \033\[33m .* yellow .* \033\[0m /x, 'color.pri.none');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'color.rc';
|
||||
ok (!-r 'color.rc', 'Removed color.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
59
src/tests/color.project.t
Executable file
59
src/tests/color.project.t
Executable file
@@ -0,0 +1,59 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 5;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'color.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"color.project.x=red\n",
|
||||
"_forcecolor=1\n";
|
||||
close $fh;
|
||||
ok (-r 'color.rc', 'Created color.rc');
|
||||
}
|
||||
|
||||
# Test the add command.
|
||||
qx{../task rc:color.rc add nothing};
|
||||
qx{../task rc:color.rc add project:x red};
|
||||
my $output = qx{../task rc:color.rc list};
|
||||
|
||||
like ($output, qr/ (?!<\033\[\d\dm) .* nothing .* (?!>\033\[0m) /x, 'none');
|
||||
like ($output, qr/ \033\[31m .* red .* \033\[0m /x, 'color.project.red');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'color.rc';
|
||||
ok (!-r 'color.rc', 'Removed color.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
59
src/tests/color.recurring.t
Executable file
59
src/tests/color.recurring.t
Executable file
@@ -0,0 +1,59 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 5;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'color.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"color.recurring=red\n",
|
||||
"_forcecolor=1\n";
|
||||
close $fh;
|
||||
ok (-r 'color.rc', 'Created color.rc');
|
||||
}
|
||||
|
||||
# Test the add command.
|
||||
qx{../task rc:color.rc add nothing};
|
||||
qx{../task rc:color.rc add due:tomorrow recur:1w red};
|
||||
my $output = qx{../task rc:color.rc list};
|
||||
|
||||
like ($output, qr/ (?!<\033\[\d\dm) .* nothing .* (?!>\033\[0m) /x, 'none');
|
||||
like ($output, qr/ \033\[31m .* red .* \033\[0m /x, 'color.recurring');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'color.rc';
|
||||
ok (!-r 'color.rc', 'Removed color.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
62
src/tests/color.tag.t
Executable file
62
src/tests/color.tag.t
Executable file
@@ -0,0 +1,62 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 6;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'color.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"color.tag.red=red\n",
|
||||
"color.tag.green=green\n",
|
||||
"_forcecolor=1\n";
|
||||
close $fh;
|
||||
ok (-r 'color.rc', 'Created color.rc');
|
||||
}
|
||||
|
||||
# Test the add command.
|
||||
qx{../task rc:color.rc add nothing};
|
||||
qx{../task rc:color.rc add +red red};
|
||||
qx{../task rc:color.rc add +green green};
|
||||
my $output = qx{../task rc:color.rc list};
|
||||
|
||||
like ($output, qr/ (?!<\033\[\d\dm) .* nothing .* (?!>\033\[0m) /x, 'none');
|
||||
like ($output, qr/ \033\[31m .* red .* \033\[0m /x, 'color.tag.red');
|
||||
like ($output, qr/ \033\[32m .* green .* \033\[0m /x, 'color.tag.green');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'color.rc';
|
||||
ok (!-r 'color.rc', 'Removed color.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
59
src/tests/color.tagged.t
Executable file
59
src/tests/color.tagged.t
Executable file
@@ -0,0 +1,59 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 5;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'color.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"color.tagged=red\n",
|
||||
"_forcecolor=1\n";
|
||||
close $fh;
|
||||
ok (-r 'color.rc', 'Created color.rc');
|
||||
}
|
||||
|
||||
# Test the add command.
|
||||
qx{../task rc:color.rc add nothing};
|
||||
qx{../task rc:color.rc add +tag red};
|
||||
my $output = qx{../task rc:color.rc list};
|
||||
|
||||
like ($output, qr/ (?!<\033\[\d\dm) .* nothing .* (?!>\033\[0m) /x, 'none');
|
||||
like ($output, qr/ \033\[31m .* red .* \033\[0m /x, 'color.tagged');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'color.rc';
|
||||
ok (!-r 'color.rc', 'Removed color.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
64
src/tests/completed.t
Executable file
64
src/tests/completed.t
Executable file
@@ -0,0 +1,64 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 6;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'completed.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"confirmation=no\n";
|
||||
close $fh;
|
||||
ok (-r 'completed.rc', 'Created completed.rc');
|
||||
}
|
||||
|
||||
# Add two tasks, mark 1 as done, the other as deleted.
|
||||
qx{../task rc:completed.rc add one};
|
||||
qx{../task rc:completed.rc add two};
|
||||
qx{../task rc:completed.rc 1 done};
|
||||
qx{../task rc:completed.rc 2 delete};
|
||||
|
||||
# Generate completed report.
|
||||
my $output = qx{../task rc:completed.rc completed};
|
||||
like ($output, qr/one/, 'one -> completed');
|
||||
unlike ($output, qr/two/, 'two -> deleted');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'completed.data';
|
||||
ok (!-r 'completed.data', 'Removed completed.data');
|
||||
|
||||
unlink 'completed.rc';
|
||||
ok (!-r 'completed.rc', 'Removed completed.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
57
src/tests/config.obsolete.t
Executable file
57
src/tests/config.obsolete.t
Executable file
@@ -0,0 +1,57 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 5;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'obsolete.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"foo=1\n";
|
||||
close $fh;
|
||||
ok (-r 'obsolete.rc', 'Created obsolete.rc');
|
||||
}
|
||||
|
||||
# Test the add command.
|
||||
my $output = qx{../task rc:obsolete.rc version};
|
||||
|
||||
like ($output, qr/Your .taskrc file contains these unrecognized variables:\n/,
|
||||
'unsupported configuration variable');
|
||||
like ($output, qr/ foo\n/, 'unsupported configuration variable');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'obsolete.rc';
|
||||
ok (!-r 'obsolete.rc', 'Removed obsolete.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
109
src/tests/confirmation.t
Executable file
109
src/tests/confirmation.t
Executable file
@@ -0,0 +1,109 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 26;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'confirm.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"confirmation=yes\n";
|
||||
close $fh;
|
||||
ok (-r 'confirm.rc', 'Created confirm.rc');
|
||||
}
|
||||
|
||||
# Create the response file.
|
||||
if (open my $fh, '>', 'response.txt')
|
||||
{
|
||||
print $fh "\n\nn\n";
|
||||
close $fh;
|
||||
ok (-r 'response.txt', 'Created response.txt');
|
||||
}
|
||||
|
||||
qx{../task rc:confirm.rc add foo} for 1 .. 10;
|
||||
|
||||
# Test the various forms of "yes".
|
||||
my $output = qx{echo "yes" | ../task rc:confirm.rc del 1};
|
||||
like ($output, qr/Permanently delete task 1 'foo'\? \(y\/n\)/, 'confirmation - yes works');
|
||||
unlike ($output, qr/Task not deleted\./, 'confirmation - yes works');
|
||||
|
||||
$output = qx{echo "ye" | ../task rc:confirm.rc del 2};
|
||||
like ($output, qr/Permanently delete task 2 'foo'\? \(y\/n\)/, 'confirmation - ye works');
|
||||
unlike ($output, qr/Task not deleted\./, 'confirmation - ye works');
|
||||
|
||||
$output = qx{echo "y" | ../task rc:confirm.rc del 3};
|
||||
like ($output, qr/Permanently delete task 3 'foo'\? \(y\/n\)/, 'confirmation - y works');
|
||||
unlike ($output, qr/Task not deleted\./, 'confirmation - y works');
|
||||
|
||||
$output = qx{echo "YES" | ../task rc:confirm.rc del 4};
|
||||
like ($output, qr/Permanently delete task 4 'foo'\? \(y\/n\)/, 'confirmation - YES works');
|
||||
unlike ($output, qr/Task not deleted\./, 'confirmation - YES works');
|
||||
|
||||
$output = qx{echo "YE" | ../task rc:confirm.rc del 5};
|
||||
like ($output, qr/Permanently delete task 5 'foo'\? \(y\/n\)/, 'confirmation - YE works');
|
||||
unlike ($output, qr/Task not deleted\./, 'confirmation - YE works');
|
||||
|
||||
$output = qx{echo "Y" | ../task rc:confirm.rc del 6};
|
||||
like ($output, qr/Permanently delete task 6 'foo'\? \(y\/n\)/, 'confirmation - Y works');
|
||||
unlike ($output, qr/Task not deleted\./, 'confirmation - Y works');
|
||||
|
||||
# Test the various forms of "no".
|
||||
$output = qx{echo "no" | ../task rc:confirm.rc del 7};
|
||||
like ($output, qr/Permanently delete task 7 'foo'\? \(y\/n\)/, 'confirmation - no works');
|
||||
like ($output, qr/Task not deleted\./, 'confirmation - no works');
|
||||
|
||||
$output = qx{echo "n" | ../task rc:confirm.rc del 7};
|
||||
like ($output, qr/Permanently delete task 7 'foo'\? \(y\/n\)/, 'confirmation - n works');
|
||||
like ($output, qr/Task not deleted\./, 'confirmation - n works');
|
||||
|
||||
$output = qx{echo "NO" | ../task rc:confirm.rc del 7};
|
||||
like ($output, qr/Permanently delete task 7 'foo'\? \(y\/n\)/, 'confirmation - NO works');
|
||||
like ($output, qr/Task not deleted\./, 'confirmation - NO works');
|
||||
|
||||
$output = qx{echo "N" | ../task rc:confirm.rc del 7};
|
||||
like ($output, qr/Permanently delete task 7 'foo'\? \(y\/n\)/, 'confirmation - N works');
|
||||
like ($output, qr/Task not deleted\./, 'confirmation - N works');
|
||||
|
||||
# Test newlines.
|
||||
$output = qx{cat response.txt | ../task rc:confirm.rc del 7};
|
||||
like ($output, qr/(Permanently delete task 7 'foo'\? \(y\/n\)) \1 \1/, 'confirmation - \n re-prompt works');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'response.txt';
|
||||
ok (!-r 'response.txt', 'Removed response.txt');
|
||||
|
||||
unlink 'confirm.rc';
|
||||
ok (!-r 'confirm.rc', 'Removed confirm.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
57
src/tests/custom.columns.t
Executable file
57
src/tests/custom.columns.t
Executable file
@@ -0,0 +1,57 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 4;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'custom.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"report.foo.description=DESC\n",
|
||||
"report.foo.columns=id,foo,description\n",
|
||||
"report.foo.sort=id+\n",
|
||||
"report.foo.filter=project:A\n";
|
||||
close $fh;
|
||||
ok (-r 'custom.rc', 'Created custom.rc');
|
||||
}
|
||||
|
||||
# Generate the usage screen, and locate the custom report on it.
|
||||
my $output = qx{../task rc:custom.rc foo 2>&1};
|
||||
like ($output, qr/Unrecognized column name: foo\n/, 'custom report spotted invalid column');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'custom.rc';
|
||||
ok (!-r 'custom.rc', 'Removed custom.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
61
src/tests/custom.recur_ind.t
Executable file
61
src/tests/custom.recur_ind.t
Executable file
@@ -0,0 +1,61 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 6;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'custom.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"report.foo.description=DESC\n",
|
||||
"report.foo.columns=id,recurrence_indicator\n",
|
||||
"report.foo.labels=ID,R\n",
|
||||
"report.foo.sort=id+\n";
|
||||
close $fh;
|
||||
ok (-r 'custom.rc', 'Created custom.rc');
|
||||
}
|
||||
|
||||
# Generate the usage screen, and locate the custom report on it.
|
||||
qx{../task rc:custom.rc add foo due:tomorrow recur:weekly};
|
||||
qx{../task rc:custom.rc add bar};
|
||||
my $output = qx{../task rc:custom.rc foo 2>&1};
|
||||
like ($output, qr/ID R/, 'Recurrence indicator heading');
|
||||
like ($output, qr/3\s+R/, 'Recurrence indicator t1');
|
||||
unlike ($output, qr/2\s+R/, 'No recurrence indicator t2');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'custom.rc';
|
||||
ok (!-r 'custom.rc', 'Removed custom.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
63
src/tests/custom.t
Executable file
63
src/tests/custom.t
Executable file
@@ -0,0 +1,63 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 6;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'custom.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"report.foo.description=DESC\n",
|
||||
"report.foo.columns=id,description\n",
|
||||
"report.foo.sort=id+\n",
|
||||
"report.foo.filter=project:A\n";
|
||||
close $fh;
|
||||
ok (-r 'custom.rc', 'Created custom.rc');
|
||||
}
|
||||
|
||||
# Generate the usage screen, and locate the custom report on it.
|
||||
my $output = qx{../task rc:custom.rc usage};
|
||||
like ($output, qr/task foo \[tags\] \[attrs\] desc\.\.\.\s+DESC\n/m, 'report.foo');
|
||||
|
||||
qx{../task rc:custom.rc add project:A one};
|
||||
qx{../task rc:custom.rc add two};
|
||||
$output = qx{../task rc:custom.rc foo};
|
||||
like ($output, qr/one/, 'custom filter included');
|
||||
unlike ($output, qr/two/, 'custom filter excluded');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'custom.rc';
|
||||
ok (!-r 'custom.rc', 'Removed custom.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
61
src/tests/custom.tag_ind.t
Executable file
61
src/tests/custom.tag_ind.t
Executable file
@@ -0,0 +1,61 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 6;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'custom.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"report.foo.description=DESC\n",
|
||||
"report.foo.columns=id,tag_indicator\n",
|
||||
"report.foo.labels=ID,T\n",
|
||||
"report.foo.sort=id+\n";
|
||||
close $fh;
|
||||
ok (-r 'custom.rc', 'Created custom.rc');
|
||||
}
|
||||
|
||||
# Generate the usage screen, and locate the custom report on it.
|
||||
qx{../task rc:custom.rc add foo +tag};
|
||||
qx{../task rc:custom.rc add bar};
|
||||
my $output = qx{../task rc:custom.rc foo 2>&1};
|
||||
like ($output, qr/ID T/, 'Tag indicator heading');
|
||||
like ($output, qr/1\s+\+/, 'Tag indicator t1');
|
||||
unlike ($output, qr/2\s+\+/, 'No tag indicator t2');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'custom.rc';
|
||||
ok (!-r 'custom.rc', 'Removed custom.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
@@ -1,5 +1,27 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright 2005 - 2008, Paul Beckingham. All rights reserved.
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free Software
|
||||
// Foundation; either version 2 of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
// details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program; if not, write to the
|
||||
//
|
||||
// Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor,
|
||||
// Boston, MA
|
||||
// 02110-1301
|
||||
// USA
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#include <iostream>
|
||||
@@ -9,7 +31,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
plan (100);
|
||||
UnitTest t (100);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -17,207 +39,207 @@ int main (int argc, char** argv)
|
||||
Date yesterday;
|
||||
yesterday -= 1;
|
||||
|
||||
ok (yesterday <= now, "yesterday <= now");
|
||||
ok (yesterday < now, "yesterday < now");
|
||||
notok (yesterday == now, "!(yesterday == now)");
|
||||
ok (yesterday != now, "yesterday != now");
|
||||
ok (now >= yesterday, "now >= yesterday");
|
||||
ok (now > yesterday, "now > yesterday");
|
||||
t.ok (yesterday <= now, "yesterday <= now");
|
||||
t.ok (yesterday < now, "yesterday < now");
|
||||
t.notok (yesterday == now, "!(yesterday == now)");
|
||||
t.ok (yesterday != now, "yesterday != now");
|
||||
t.ok (now >= yesterday, "now >= yesterday");
|
||||
t.ok (now > yesterday, "now > yesterday");
|
||||
|
||||
// Loose comparisons.
|
||||
Date left ("7/4/2008");
|
||||
Date comp1 ("7/4/2008");
|
||||
ok (left.sameDay (comp1), "7/4/2008 is on the same day as 7/4/2008");
|
||||
ok (left.sameMonth (comp1), "7/4/2008 is in the same month as 7/4/2008");
|
||||
ok (left.sameYear (comp1), "7/4/2008 is in the same year as 7/4/2008");
|
||||
t.ok (left.sameDay (comp1), "7/4/2008 is on the same day as 7/4/2008");
|
||||
t.ok (left.sameMonth (comp1), "7/4/2008 is in the same month as 7/4/2008");
|
||||
t.ok (left.sameYear (comp1), "7/4/2008 is in the same year as 7/4/2008");
|
||||
|
||||
Date comp2 ("7/5/2008");
|
||||
notok (left.sameDay (comp2), "7/4/2008 is not on the same day as 7/5/2008");
|
||||
ok (left.sameMonth (comp2), "7/4/2008 is in the same month as 7/5/2008");
|
||||
ok (left.sameYear (comp2), "7/4/2008 is in the same year as 7/5/2008");
|
||||
t.notok (left.sameDay (comp2), "7/4/2008 is not on the same day as 7/5/2008");
|
||||
t.ok (left.sameMonth (comp2), "7/4/2008 is in the same month as 7/5/2008");
|
||||
t.ok (left.sameYear (comp2), "7/4/2008 is in the same year as 7/5/2008");
|
||||
|
||||
Date comp3 ("8/4/2008");
|
||||
notok (left.sameDay (comp3), "7/4/2008 is not on the same day as 8/4/2008");
|
||||
notok (left.sameMonth (comp3), "7/4/2008 is not in the same month as 8/4/2008");
|
||||
ok (left.sameYear (comp3), "7/4/2008 is in the same year as 8/4/2008");
|
||||
t.notok (left.sameDay (comp3), "7/4/2008 is not on the same day as 8/4/2008");
|
||||
t.notok (left.sameMonth (comp3), "7/4/2008 is not in the same month as 8/4/2008");
|
||||
t.ok (left.sameYear (comp3), "7/4/2008 is in the same year as 8/4/2008");
|
||||
|
||||
Date comp4 ("7/4/2009");
|
||||
notok (left.sameDay (comp4), "7/4/2008 is not on the same day as 7/4/2009");
|
||||
notok (left.sameMonth (comp4), "7/4/2008 is not in the same month as 7/4/2009");
|
||||
notok (left.sameYear (comp4), "7/4/2008 is not in the same year as 7/4/2009");
|
||||
t.notok (left.sameDay (comp4), "7/4/2008 is not on the same day as 7/4/2009");
|
||||
t.notok (left.sameMonth (comp4), "7/4/2008 is not in the same month as 7/4/2009");
|
||||
t.notok (left.sameYear (comp4), "7/4/2008 is not in the same year as 7/4/2009");
|
||||
|
||||
// Validity.
|
||||
ok (Date::valid (2, 29, 2008), "valid: 2/29/2008");
|
||||
notok (Date::valid (2, 29, 2007), "invalid: 2/29/2007");
|
||||
t.ok (Date::valid (2, 29, 2008), "valid: 2/29/2008");
|
||||
t.notok (Date::valid (2, 29, 2007), "invalid: 2/29/2007");
|
||||
|
||||
// Leap year.
|
||||
ok (Date::leapYear (2008), "2008 is 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.ok (Date::leapYear (2008), "2008 is a leap year");
|
||||
t.notok (Date::leapYear (2007), "2007 is not a leap year");
|
||||
t.ok (Date::leapYear (2000), "2000 is a leap year");
|
||||
t.ok (Date::leapYear (1900), "1900 is a leap year");
|
||||
|
||||
// Days in month.
|
||||
is (Date::daysInMonth (2, 2008), 29, "29 days in February 2008");
|
||||
is (Date::daysInMonth (2, 2007), 28, "28 days in February 2007");
|
||||
t.is (Date::daysInMonth (2, 2008), 29, "29 days in February 2008");
|
||||
t.is (Date::daysInMonth (2, 2007), 28, "28 days in February 2007");
|
||||
|
||||
// Names.
|
||||
is (Date::monthName (1), "January", "1 = January");
|
||||
is (Date::monthName (2), "February", "2 = February");
|
||||
is (Date::monthName (3), "March", "3 = March");
|
||||
is (Date::monthName (4), "April", "4 = April");
|
||||
is (Date::monthName (5), "May", "5 = May");
|
||||
is (Date::monthName (6), "June", "6 = June");
|
||||
is (Date::monthName (7), "July", "7 = July");
|
||||
is (Date::monthName (8), "August", "8 = August");
|
||||
is (Date::monthName (9), "September", "9 = September");
|
||||
is (Date::monthName (10), "October", "10 = October");
|
||||
is (Date::monthName (11), "November", "11 = November");
|
||||
is (Date::monthName (12), "December", "12 = December");
|
||||
t.is (Date::monthName (1), "January", "1 = January");
|
||||
t.is (Date::monthName (2), "February", "2 = February");
|
||||
t.is (Date::monthName (3), "March", "3 = March");
|
||||
t.is (Date::monthName (4), "April", "4 = April");
|
||||
t.is (Date::monthName (5), "May", "5 = May");
|
||||
t.is (Date::monthName (6), "June", "6 = June");
|
||||
t.is (Date::monthName (7), "July", "7 = July");
|
||||
t.is (Date::monthName (8), "August", "8 = August");
|
||||
t.is (Date::monthName (9), "September", "9 = September");
|
||||
t.is (Date::monthName (10), "October", "10 = October");
|
||||
t.is (Date::monthName (11), "November", "11 = November");
|
||||
t.is (Date::monthName (12), "December", "12 = December");
|
||||
|
||||
is (Date::dayName (0), "Sunday", "0 == Sunday");
|
||||
is (Date::dayName (1), "Monday", "1 == Monday");
|
||||
is (Date::dayName (2), "Tuesday", "2 == Tuesday");
|
||||
is (Date::dayName (3), "Wednesday", "3 == Wednesday");
|
||||
is (Date::dayName (4), "Thursday", "4 == Thursday");
|
||||
is (Date::dayName (5), "Friday", "5 == Friday");
|
||||
is (Date::dayName (6), "Saturday", "6 == Saturday");
|
||||
t.is (Date::dayName (0), "Sunday", "0 == Sunday");
|
||||
t.is (Date::dayName (1), "Monday", "1 == Monday");
|
||||
t.is (Date::dayName (2), "Tuesday", "2 == Tuesday");
|
||||
t.is (Date::dayName (3), "Wednesday", "3 == Wednesday");
|
||||
t.is (Date::dayName (4), "Thursday", "4 == Thursday");
|
||||
t.is (Date::dayName (5), "Friday", "5 == Friday");
|
||||
t.is (Date::dayName (6), "Saturday", "6 == Saturday");
|
||||
|
||||
is (Date::dayOfWeek ("SUNDAY"), 0, "SUNDAY == 0");
|
||||
is (Date::dayOfWeek ("sunday"), 0, "sunday == 0");
|
||||
is (Date::dayOfWeek ("Sunday"), 0, "Sunday == 0");
|
||||
is (Date::dayOfWeek ("Monday"), 1, "Monday == 1");
|
||||
is (Date::dayOfWeek ("Tuesday"), 2, "Tuesday == 2");
|
||||
is (Date::dayOfWeek ("Wednesday"), 3, "Wednesday == 3");
|
||||
is (Date::dayOfWeek ("Thursday"), 4, "Thursday == 4");
|
||||
is (Date::dayOfWeek ("Friday"), 5, "Friday == 5");
|
||||
is (Date::dayOfWeek ("Saturday"), 6, "Saturday == 6");
|
||||
t.is (Date::dayOfWeek ("SUNDAY"), 0, "SUNDAY == 0");
|
||||
t.is (Date::dayOfWeek ("sunday"), 0, "sunday == 0");
|
||||
t.is (Date::dayOfWeek ("Sunday"), 0, "Sunday == 0");
|
||||
t.is (Date::dayOfWeek ("Monday"), 1, "Monday == 1");
|
||||
t.is (Date::dayOfWeek ("Tuesday"), 2, "Tuesday == 2");
|
||||
t.is (Date::dayOfWeek ("Wednesday"), 3, "Wednesday == 3");
|
||||
t.is (Date::dayOfWeek ("Thursday"), 4, "Thursday == 4");
|
||||
t.is (Date::dayOfWeek ("Friday"), 5, "Friday == 5");
|
||||
t.is (Date::dayOfWeek ("Saturday"), 6, "Saturday == 6");
|
||||
|
||||
Date happyNewYear (1, 1, 2008);
|
||||
is (happyNewYear.dayOfWeek (), 2, "1/1/2008 == Tuesday");
|
||||
is (happyNewYear.month (), 1, "1/1/2008 == January");
|
||||
is (happyNewYear.day (), 1, "1/1/2008 == 1");
|
||||
is (happyNewYear.year (), 2008, "1/1/2008 == 2008");
|
||||
t.is (happyNewYear.dayOfWeek (), 2, "1/1/2008 == Tuesday");
|
||||
t.is (happyNewYear.month (), 1, "1/1/2008 == January");
|
||||
t.is (happyNewYear.day (), 1, "1/1/2008 == 1");
|
||||
t.is (happyNewYear.year (), 2008, "1/1/2008 == 2008");
|
||||
|
||||
is (now - yesterday, 1, "today - yesterday == 1");
|
||||
t.is (now - yesterday, 1, "today - yesterday == 1");
|
||||
|
||||
is (happyNewYear.toString (), "1/1/2008", "toString 1/1/2008");
|
||||
t.is (happyNewYear.toString (), "1/1/2008", "toString 1/1/2008");
|
||||
|
||||
int m, d, y;
|
||||
happyNewYear.toMDY (m, d, y);
|
||||
is (m, 1, "1/1/2008 == January");
|
||||
is (d, 1, "1/1/2008 == 1");
|
||||
is (y, 2008, "1/1/2008 == 2008");
|
||||
t.is (m, 1, "1/1/2008 == January");
|
||||
t.is (d, 1, "1/1/2008 == 1");
|
||||
t.is (y, 2008, "1/1/2008 == 2008");
|
||||
|
||||
Date epoch (9, 8, 2001);
|
||||
ok ((int)epoch.toEpoch () < 1000000000, "9/8/2001 < 1,000,000,000");
|
||||
t.ok ((int)epoch.toEpoch () < 1000000000, "9/8/2001 < 1,000,000,000");
|
||||
epoch += 86400;
|
||||
ok ((int)epoch.toEpoch () > 1000000000, "9/9/2001 > 1,000,000,000");
|
||||
t.ok ((int)epoch.toEpoch () > 1000000000, "9/9/2001 > 1,000,000,000");
|
||||
|
||||
Date fromEpoch (epoch.toEpoch ());
|
||||
is (fromEpoch.toString (), epoch.toString (), "ctor (time_t)");
|
||||
t.is (fromEpoch.toString (), epoch.toString (), "ctor (time_t)");
|
||||
|
||||
// Date parsing.
|
||||
Date fromString1 ("1/1/2008");
|
||||
is (fromString1.month (), 1, "ctor (std::string) -> m");
|
||||
is (fromString1.day (), 1, "ctor (std::string) -> d");
|
||||
is (fromString1.year (), 2008, "ctor (std::string) -> y");
|
||||
t.is (fromString1.month (), 1, "ctor (std::string) -> m");
|
||||
t.is (fromString1.day (), 1, "ctor (std::string) -> d");
|
||||
t.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");
|
||||
t.is (fromString2.month (), 1, "ctor (std::string) -> m");
|
||||
t.is (fromString2.day (), 1, "ctor (std::string) -> d");
|
||||
t.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");
|
||||
t.is (fromString3.month (), 1, "ctor (std::string) -> m");
|
||||
t.is (fromString3.day (), 1, "ctor (std::string) -> d");
|
||||
t.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");
|
||||
t.is (fromString4.month (), 12, "ctor (std::string) -> m");
|
||||
t.is (fromString4.day (), 31, "ctor (std::string) -> d");
|
||||
t.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");
|
||||
t.is (fromString5.month (), 12, "ctor (std::string) -> m");
|
||||
t.is (fromString5.day (), 31, "ctor (std::string) -> d");
|
||||
t.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");
|
||||
t.is (fromString6.month (), 12, "ctor (std::string) -> m");
|
||||
t.is (fromString6.day (), 31, "ctor (std::string) -> d");
|
||||
t.is (fromString6.year (), 2007, "ctor (std::string) -> y");
|
||||
|
||||
Date fromString7 ("01/01/2008", "m/d/Y");
|
||||
is (fromString7.month (), 1, "ctor (std::string) -> m");
|
||||
is (fromString7.day (), 1, "ctor (std::string) -> d");
|
||||
is (fromString7.year (), 2008, "ctor (std::string) -> y");
|
||||
t.is (fromString7.month (), 1, "ctor (std::string) -> m");
|
||||
t.is (fromString7.day (), 1, "ctor (std::string) -> d");
|
||||
t.is (fromString7.year (), 2008, "ctor (std::string) -> y");
|
||||
|
||||
// Relative dates.
|
||||
Date r1 ("today");
|
||||
ok (r1.sameDay (now), "today = now");
|
||||
t.ok (r1.sameDay (now), "today = now");
|
||||
|
||||
Date r2 ("tomorrow");
|
||||
ok (r2.sameDay (now + 86400), "tomorrow = now + 1d");
|
||||
t.ok (r2.sameDay (now + 86400), "tomorrow = now + 1d");
|
||||
|
||||
Date r3 ("yesterday");
|
||||
ok (r3.sameDay (now - 86400), "yesterday = now - 1d");
|
||||
t.ok (r3.sameDay (now - 86400), "yesterday = now - 1d");
|
||||
|
||||
Date r4 ("sunday");
|
||||
if (now.dayOfWeek () >= 0)
|
||||
ok (r4.sameDay (now + (0 - now.dayOfWeek () + 7) * 86400), "next sunday");
|
||||
t.ok (r4.sameDay (now + (0 - now.dayOfWeek () + 7) * 86400), "next sunday");
|
||||
else
|
||||
ok (r4.sameDay (now + (0 - now.dayOfWeek ()) * 86400), "next sunday");;
|
||||
t.ok (r4.sameDay (now + (0 - now.dayOfWeek ()) * 86400), "next sunday");;
|
||||
|
||||
Date r5 ("monday");
|
||||
if (now.dayOfWeek () >= 1)
|
||||
ok (r5.sameDay (now + (1 - now.dayOfWeek () + 7) * 86400), "next monday");
|
||||
t.ok (r5.sameDay (now + (1 - now.dayOfWeek () + 7) * 86400), "next monday");
|
||||
else
|
||||
ok (r5.sameDay (now + (1 - now.dayOfWeek ()) * 86400), "next monday");;
|
||||
t.ok (r5.sameDay (now + (1 - now.dayOfWeek ()) * 86400), "next monday");;
|
||||
|
||||
Date r6 ("tuesday");
|
||||
if (now.dayOfWeek () >= 2)
|
||||
ok (r6.sameDay (now + (2 - now.dayOfWeek () + 7) * 86400), "next tuesday");
|
||||
t.ok (r6.sameDay (now + (2 - now.dayOfWeek () + 7) * 86400), "next tuesday");
|
||||
else
|
||||
ok (r6.sameDay (now + (2 - now.dayOfWeek ()) * 86400), "next tuesday");;
|
||||
t.ok (r6.sameDay (now + (2 - now.dayOfWeek ()) * 86400), "next tuesday");;
|
||||
|
||||
Date r7 ("wednesday");
|
||||
if (now.dayOfWeek () >= 3)
|
||||
ok (r7.sameDay (now + (3 - now.dayOfWeek () + 7) * 86400), "next wednesday");
|
||||
t.ok (r7.sameDay (now + (3 - now.dayOfWeek () + 7) * 86400), "next wednesday");
|
||||
else
|
||||
ok (r7.sameDay (now + (3 - now.dayOfWeek ()) * 86400), "next wednesday");;
|
||||
t.ok (r7.sameDay (now + (3 - now.dayOfWeek ()) * 86400), "next wednesday");;
|
||||
|
||||
Date r8 ("thursday");
|
||||
if (now.dayOfWeek () >= 4)
|
||||
ok (r8.sameDay (now + (4 - now.dayOfWeek () + 7) * 86400), "next thursday");
|
||||
t.ok (r8.sameDay (now + (4 - now.dayOfWeek () + 7) * 86400), "next thursday");
|
||||
else
|
||||
ok (r8.sameDay (now + (4 - now.dayOfWeek ()) * 86400), "next thursday");;
|
||||
t.ok (r8.sameDay (now + (4 - now.dayOfWeek ()) * 86400), "next thursday");;
|
||||
|
||||
Date r9 ("friday");
|
||||
if (now.dayOfWeek () >= 5)
|
||||
ok (r9.sameDay (now + (5 - now.dayOfWeek () + 7) * 86400), "next friday");
|
||||
t.ok (r9.sameDay (now + (5 - now.dayOfWeek () + 7) * 86400), "next friday");
|
||||
else
|
||||
ok (r9.sameDay (now + (5 - now.dayOfWeek ()) * 86400), "next friday");;
|
||||
t.ok (r9.sameDay (now + (5 - now.dayOfWeek ()) * 86400), "next friday");;
|
||||
|
||||
Date r10 ("saturday");
|
||||
if (now.dayOfWeek () >= 6)
|
||||
ok (r10.sameDay (now + (6 - now.dayOfWeek () + 7) * 86400), "next saturday");
|
||||
t.ok (r10.sameDay (now + (6 - now.dayOfWeek () + 7) * 86400), "next saturday");
|
||||
else
|
||||
ok (r10.sameDay (now + (6 - now.dayOfWeek ()) * 86400), "next saturday");;
|
||||
t.ok (r10.sameDay (now + (6 - now.dayOfWeek ()) * 86400), "next saturday");;
|
||||
|
||||
Date r11 ("eow");
|
||||
ok (r11 < now + (8 * 86400), "eow < 7 days away");
|
||||
t.ok (r11 < now + (8 * 86400), "eow < 7 days away");
|
||||
|
||||
Date r12 ("eom");
|
||||
ok (r12.sameMonth (now), "eom in same month as now");
|
||||
t.ok (r12.sameMonth (now), "eom in same month as now");
|
||||
|
||||
Date r13 ("eoy");
|
||||
ok (r13.sameYear (now), "eoy in same year as now");
|
||||
t.ok (r13.sameYear (now), "eoy in same year as now");
|
||||
}
|
||||
|
||||
catch (std::string& e)
|
||||
{
|
||||
fail ("Exception thrown.");
|
||||
diag (e);
|
||||
t.fail ("Exception thrown.");
|
||||
t.diag (e);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
72
src/tests/dateformat.t
Executable file
72
src/tests/dateformat.t
Executable file
@@ -0,0 +1,72 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 8;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'date1.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"dateformat=YMD\n";
|
||||
close $fh;
|
||||
ok (-r 'date1.rc', 'Created date1.rc');
|
||||
}
|
||||
|
||||
if (open my $fh, '>', 'date2.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"dateformat=m/d/y\n";
|
||||
close $fh;
|
||||
ok (-r 'date2.rc', 'Created date2.rc');
|
||||
}
|
||||
|
||||
qx{../task rc:date1.rc add foo due:20091231};
|
||||
my $output = qx{../task rc:date1.rc info 1};
|
||||
like ($output, qr/\b20091231\b/, 'date format YMD parsed');
|
||||
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
qx{../task rc:date2.rc add foo due:12/1/09};
|
||||
$output = qx{../task rc:date2.rc info 1};
|
||||
like ($output, qr/\b12\/1\/09\b/, 'date format m/d/y parsed');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'date1.rc';
|
||||
ok (!-r 'date1.rc', 'Removed date1.rc');
|
||||
|
||||
unlink 'date2.rc';
|
||||
ok (!-r 'date2.rc', 'Removed date2.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
83
src/tests/default.t
Executable file
83
src/tests/default.t
Executable file
@@ -0,0 +1,83 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 16;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'default.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"default.command=list\n",
|
||||
"default.project=PROJECT\n",
|
||||
"default.priority=M\n";
|
||||
close $fh;
|
||||
ok (-r 'default.rc', 'Created default.rc');
|
||||
}
|
||||
|
||||
# Set up a default command, project and priority.
|
||||
qx{../task rc:default.rc add all defaults};
|
||||
my $output = qx{../task rc:default.rc list};
|
||||
like ($output, qr/ all defaults/, 'task added');
|
||||
like ($output, qr/ PROJECT /, 'default project added');
|
||||
like ($output, qr/ M /, 'default priority added');
|
||||
unlink 'pending.data';
|
||||
|
||||
qx{../task rc:default.rc add project:specific priority:L all specified};
|
||||
$output = qx{../task rc:default.rc list};
|
||||
like ($output, qr/ all specified/, 'task added');
|
||||
like ($output, qr/ specific /, 'project specified');
|
||||
like ($output, qr/ L /, 'priority specified');
|
||||
unlink 'pending.data';
|
||||
|
||||
qx{../task rc:default.rc add project:specific project specified};
|
||||
$output = qx{../task rc:default.rc list};
|
||||
like ($output, qr/ project specified/, 'task added');
|
||||
like ($output, qr/ specific /, 'project specified');
|
||||
like ($output, qr/ M /, 'default priority added');
|
||||
unlink 'pending.data';
|
||||
|
||||
qx{../task rc:default.rc add priority:L priority specified};
|
||||
$output = qx{../task rc:default.rc list};
|
||||
like ($output, qr/ priority specified/, 'task added');
|
||||
like ($output, qr/ PROJECT /, 'default project added');
|
||||
like ($output, qr/ L /, 'priority specified');
|
||||
|
||||
$output = qx{../task rc:default.rc};
|
||||
like ($output, qr/1 PROJECT L .+ priority specified/, 'default command worked');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'default.rc';
|
||||
ok (!-r 'default.rc', 'Removed default.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
78
src/tests/delete.t
Executable file
78
src/tests/delete.t
Executable file
@@ -0,0 +1,78 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 16;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'undelete.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"echo.command=no\n";
|
||||
close $fh;
|
||||
ok (-r 'undelete.rc', 'Created undelete.rc');
|
||||
}
|
||||
|
||||
# Add a task, delete it, undelete it.
|
||||
my $output = qx{../task rc:undelete.rc add one; ../task rc:undelete.rc info 1};
|
||||
ok (-r 'pending.data', 'pending.data created');
|
||||
like ($output, qr/Status\s+Pending\n/, 'Pending');
|
||||
|
||||
$output = qx{../task rc:undelete.rc delete 1; ../task rc:undelete.rc info 1};
|
||||
like ($output, qr/Status\s+Deleted\n/, 'Deleted');
|
||||
ok (! -r 'completed.data', 'completed.data not created');
|
||||
|
||||
$output = qx{../task rc:undelete.rc undelete 1; ../task rc:undelete.rc info 1};
|
||||
like ($output, qr/Status\s+Pending\n/, 'Pending');
|
||||
ok (! -r 'completed.data', 'completed.data not created');
|
||||
|
||||
$output = qx{../task rc:undelete.rc delete 1; ../task rc:undelete.rc list};
|
||||
like ($output, qr/^No matches/, 'No matches');
|
||||
ok (-r 'completed.data', 'completed.data created');
|
||||
|
||||
$output = qx{../task rc:undelete.rc undelete 1};
|
||||
like ($output, qr/Task 1 not found/, 'Task 1 not found');
|
||||
|
||||
$output = qx{../task rc:undelete.rc info 1};
|
||||
like ($output, qr/No matches./, 'no matches');
|
||||
|
||||
# Cleanup.
|
||||
ok (-r 'pending.data', 'Need to remove pending.data');
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
ok (-r 'completed.data', 'Need to remove completed.data');
|
||||
unlink 'completed.data';
|
||||
ok (!-r 'completed.data', 'Removed completed.data');
|
||||
|
||||
unlink 'undelete.rc';
|
||||
ok (!-r 'undelete.rc', 'Removed undelete.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
67
src/tests/due.t
Executable file
67
src/tests/due.t
Executable file
@@ -0,0 +1,67 @@
|
||||
#! /usr/bin/perl
|
||||
################################################################################
|
||||
## task - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006 - 2009, Paul Beckingham.
|
||||
## All rights reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it under
|
||||
## the terms of the GNU General Public License as published by the Free Software
|
||||
## Foundation; either version 2 of the License, or (at your option) any later
|
||||
## version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along with
|
||||
## this program; if not, write to the
|
||||
##
|
||||
## Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor,
|
||||
## Boston, MA
|
||||
## 02110-1301
|
||||
## USA
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 5;
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'due.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"due=4\n",
|
||||
"color=on\n",
|
||||
"color.due=red\n",
|
||||
"_forcecolor=on\n",
|
||||
"dateformat=m/d/Y\n";
|
||||
close $fh;
|
||||
ok (-r 'due.rc', 'Created due.rc');
|
||||
}
|
||||
|
||||
# Add a task that is almost due, and one that is just due.
|
||||
my ($d, $m, $y) = (localtime (time + 3 * 86_400))[3..5];
|
||||
my $just = sprintf ("%d/%d/%d", $m + 1, $d, $y + 1900);
|
||||
|
||||
($d, $m, $y) = (localtime (time + 5 * 86_400))[3..5];
|
||||
my $almost = sprintf ("%d/%d/%d", $m + 1, $d, $y + 1900);
|
||||
|
||||
qx{../task rc:due.rc add one due:$just};
|
||||
qx{../task rc:due.rc add two due:$almost};
|
||||
my $output = qx{../task rc:due.rc list};
|
||||
like ($output, qr/\[31m.+$just.+\[0m/, 'one marked due');
|
||||
like ($output, qr/\s+$almost\s+/, 'two not marked due');
|
||||
|
||||
# Cleanup.
|
||||
unlink 'pending.data';
|
||||
ok (!-r 'pending.data', 'Removed pending.data');
|
||||
|
||||
unlink 'due.rc';
|
||||
ok (!-r 'due.rc', 'Removed due.rc');
|
||||
|
||||
exit 0;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user