Compare commits
62 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8639e92606 | ||
|
|
6e1dbfb16e | ||
|
|
748300631a | ||
|
|
6d5309527c | ||
|
|
aafcba436e | ||
|
|
28ceeac796 | ||
|
|
ecdfb31553 | ||
|
|
8d920f9dc4 | ||
|
|
5f85550664 | ||
|
|
ee961daef6 | ||
|
|
ce42ae9622 | ||
|
|
47ffc0babc | ||
|
|
612a183776 | ||
|
|
396d85cd53 | ||
|
|
038f432752 | ||
|
|
ef886dff53 | ||
|
|
2cae1df42f | ||
|
|
82c0fea708 | ||
|
|
d6b30466c1 | ||
|
|
b0e18de1b6 | ||
|
|
b7e889339d | ||
|
|
2a5736b876 | ||
|
|
b176591261 | ||
|
|
c44baf913d | ||
|
|
0987171280 | ||
|
|
47c02965e9 | ||
|
|
ce561a6c43 | ||
|
|
b4b389c27e | ||
|
|
437c85da39 | ||
|
|
62115ea988 | ||
|
|
3ed1269753 | ||
|
|
a5ec1e4b27 | ||
|
|
a815492111 | ||
|
|
f3aa88cf83 | ||
|
|
f26a9c67be | ||
|
|
d837a25be7 | ||
|
|
78fae5195b | ||
|
|
e7304e86ce | ||
|
|
d7b95cb2e1 | ||
|
|
45ed7dcdaa | ||
|
|
d809b6dae7 | ||
|
|
a1cc4e5774 | ||
|
|
21c33f7030 | ||
|
|
2e32457032 | ||
|
|
e4ed873d60 | ||
|
|
e35dcd0e42 | ||
|
|
ec15dc9342 | ||
|
|
fb87039d8c | ||
|
|
e9a71b7db9 | ||
|
|
df215f228d | ||
|
|
4f8f044644 | ||
|
|
4380c7c712 | ||
|
|
4abc722eff | ||
|
|
11225eb599 | ||
|
|
e16bd057d8 | ||
|
|
29a152edb0 | ||
|
|
e99e6832f2 | ||
|
|
ff4e8dbef1 | ||
|
|
d265ac6c2d | ||
|
|
dc1760769f | ||
|
|
c6eb09cd63 | ||
|
|
ceffdca8a2 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -6,7 +6,7 @@ config.h.in
|
||||
config.status
|
||||
src/.deps
|
||||
src/Makefile
|
||||
src/task
|
||||
*/task
|
||||
stamp-h1
|
||||
Makefile
|
||||
configure
|
||||
|
||||
7
AUTHORS
7
AUTHORS
@@ -3,6 +3,8 @@ Principal Author:
|
||||
|
||||
Contributing Authors:
|
||||
Damian Glenny
|
||||
Andy Lester
|
||||
H. İbrahim Güngör
|
||||
|
||||
With thanks to:
|
||||
Eugene Kramer
|
||||
@@ -12,7 +14,8 @@ With thanks to:
|
||||
Thomas Engel
|
||||
Nishiishii
|
||||
galvanizd
|
||||
H. İbrahim Güngör
|
||||
Stas Antons
|
||||
Andy Lester
|
||||
Vincent Fleuranceau
|
||||
T. Charles Yun
|
||||
ArchiMark
|
||||
|
||||
|
||||
71
ChangeLog
71
ChangeLog
@@ -1,18 +1,61 @@
|
||||
Version numbers are of the form:
|
||||
|
||||
X.Y.Z
|
||||
|
||||
where the X represents a major version number, or architecture. The Y
|
||||
represents a feature release, and the Z represents a patch.
|
||||
|
||||
------ current release ---------------------------
|
||||
|
||||
1.4.1 (7/?/2008)
|
||||
1.5.0 (?)
|
||||
+ Removed deprecated TUTORIAL file.
|
||||
+ Removed "showage" configuration variable.
|
||||
+ "task stop" can now remove the start time from a started task.
|
||||
+ "task ghistory" now displays a differently aligned graph, allowing
|
||||
easier comparison by month of tasks added versus completed and deleted.
|
||||
+ "task version" command now reports unrecognized configuration variables,
|
||||
which may be spelling mistakes or deprecated variables.
|
||||
+ "configure --enable-debug" now supported to suppress compiler optimization
|
||||
to allow debugging.
|
||||
|
||||
------ old releases ------------------------------
|
||||
|
||||
1.4.3 (11/1/2008)
|
||||
+ Fixed misleading task count at bottom on "info" report.
|
||||
+ Added support for a shadow file that contains a plain text task report,
|
||||
with the "shadow.file" and "shadow.command" configuration variables
|
||||
The shadow file is automatically updated whenever the task database
|
||||
changes. Useful for integrating with "Samurize"
|
||||
+ Task now displays a message whenever a shadow file is updated, if the
|
||||
"shadow.notify" configuration variable is set "on"
|
||||
+ Bug: adding a task with a \n, \r or \f in it now fails properly
|
||||
+ Removed "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)
|
||||
+ "task undo" can now retract a "task done" command, provided no reports
|
||||
have been run (and therefore TDB::gc run)
|
||||
+ Task now correctly sorts on entire strings, instead of just the first
|
||||
character (thanks to Andy Lester)
|
||||
+ Task now uses dashes (-----) to column underlines when color is disabled
|
||||
(thanks to Vincent Fleuranceau)
|
||||
+ Task now allows mixed case attribute names (pri:, PRI:, Pri: ...) and
|
||||
commands (add, ADD, Add ...) (thanks to Vincent Fleuranceau)
|
||||
+ Task now supports a default project and priority for new tasks, via
|
||||
the new "default.project" and "default.priority" configuration variables
|
||||
(thanks to Vincent Fleuranceau)
|
||||
+ Task supports improved word-wrapping to the terminal width
|
||||
+ Task now supports "default.command" configuration variable (for example
|
||||
it could contain "list due:tomorrow") that is the command that is run
|
||||
whenever task is invoked with no arguments.
|
||||
+ Task supports modifying the existing description of a task, with the
|
||||
following syntax: task <id> "new description ...".
|
||||
+ Bug: Now properly supports relative dates in filters (task list due:eom,
|
||||
task list due:tomorrow, task list due:23rd ...)
|
||||
+ Bug: Source now properly includes <string.h> in order to build clean
|
||||
using gcc 4.3 (thanks to H. İbrahim Güngör)
|
||||
|
||||
1.4.1 (7/18/2008)
|
||||
+ Bug: Descriptions can not be altered with "task 123 New description"
|
||||
+ Tweak: For "task calendar" month names are now centered over the month
|
||||
+ Removed TUTORIAL file contents in favor of online version
|
||||
|
||||
------ old releases ------------------------------
|
||||
+ Provided Mac .pkg binary
|
||||
|
||||
1.4.0 (7/10/2008)
|
||||
+ New recurring tasks feature
|
||||
@@ -146,7 +189,7 @@ represents a feature release, and the Z represents a patch.
|
||||
+ Added more missing files.
|
||||
+ Added all source code.
|
||||
+ Generic OSS files added.
|
||||
+ Initial commit.
|
||||
+ Initial commit on Github.
|
||||
|
||||
0.9.3 (4/6/2008)
|
||||
+ Added "task completed" command.
|
||||
@@ -157,7 +200,7 @@ represents a feature release, and the Z represents a patch.
|
||||
+ "task" duplicated to "task_rel" for preparation of a fork.
|
||||
|
||||
0.9.1 (4/1/2008)
|
||||
+ Blank attributes read are longer be written out.
|
||||
+ Blank attributes read are no longer written out.
|
||||
+ Completed "task export" command.
|
||||
+ Added configuration values to "task version" command.
|
||||
+ Consolidated header files, removed unnecessary ones.
|
||||
@@ -185,10 +228,12 @@ represents a feature release, and the Z represents a patch.
|
||||
+ File locking
|
||||
+ retain deleted tasks
|
||||
+ "task info ID" report showing all metadata
|
||||
+ File format v2
|
||||
+ 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.]
|
||||
of the project. Seeded to two testers for feedback, suggestions. Development
|
||||
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"
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
SUBDIRS = src
|
||||
EXTRA_DIST = TUTORIAL DEVELOPERS
|
||||
EXTRA_DIST = DEVELOPERS
|
||||
|
||||
|
||||
3
NEWS
3
NEWS
@@ -1,4 +1,4 @@
|
||||
Welcome to Task 1.4.0.
|
||||
Welcome to Task 1.5.0.
|
||||
|
||||
Task has been built and tested on the following configurations:
|
||||
|
||||
@@ -7,6 +7,7 @@ Task has been built and tested on the following configurations:
|
||||
- Fedora Core 8
|
||||
- Fedora Core 9
|
||||
- Ubuntu 8 Hardy Heron
|
||||
- Ubuntu 9 Feisty Fawn
|
||||
- Solaris 10
|
||||
- Cygwin 1.5.25-14
|
||||
|
||||
|
||||
6
TUTORIAL
6
TUTORIAL
@@ -1,6 +0,0 @@
|
||||
|
||||
This TUTORIAL file has been deprecated. It is superceded by a richer and more
|
||||
extensive online version that can be found at:
|
||||
|
||||
http://www.beckingham.net/task.html
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
Some considerable time ago - longer than I had hoped - I demonstrated an
|
||||
alternate implementation of the todo script, called task, in the form of a
|
||||
YouTube movie:
|
||||
|
||||
http://www.youtube.com/watch?v=l68LCl6BYvs
|
||||
|
||||
A lot has happened since then, and the task program has been slowly improving
|
||||
thanks to feedback from some early testers, and continuous use by me. Today,
|
||||
I have uploaded a new movie:
|
||||
|
||||
http://www.youtube.com/watch?v=D2Kn4DMOVSw
|
||||
|
||||
This movie includes most of the changes and improvements to task, but behind
|
||||
the scenes are the biggest changes. There was a rewrite of the underlying
|
||||
storage mechanism yielding a clean API for the front end, and the code was
|
||||
reviewed for portability and converted to use GNU autoconf/automake.
|
||||
|
||||
Task has been released under GPL, and so far has been tested on:
|
||||
|
||||
Max OS X 10.4 (Tiger)
|
||||
Max OS X 10.5 (Leopard)
|
||||
Fedora 8
|
||||
Fedora 9
|
||||
Ubuntu 8 (Hardy Heron)
|
||||
Solaris 10
|
||||
|
||||
Task has been making me more organized and productive for some time now.
|
||||
Perhaps some of you might find it useful, and I welcome feedback of all kinds.
|
||||
|
||||
You can find the task source code at:
|
||||
|
||||
http://www.beckingham.net/task-1.0.0.tar.gz
|
||||
|
||||
Thank you.
|
||||
Paul Beckingham
|
||||
|
||||
281
binary/COPYING.txt
Normal file
281
binary/COPYING.txt
Normal file
@@ -0,0 +1,281 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
51
binary/README.txt
Normal file
51
binary/README.txt
Normal file
@@ -0,0 +1,51 @@
|
||||
Thank you for taking a look at task. Task is a GTD utility featuring:
|
||||
|
||||
- Robust C++ implementation
|
||||
- Tags
|
||||
- Colorful, tabular output
|
||||
- Reports, graphs
|
||||
- Lots of commands
|
||||
- Low-level API
|
||||
- Abbreviations for all commands, options
|
||||
- Multi-user file locking
|
||||
- Clean architecture allowing quick addition of new features
|
||||
- Recurring tasks
|
||||
|
||||
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.
|
||||
|
||||
You may want to watch the old task movie on YouTube:
|
||||
|
||||
http://www.youtube.com/watch?v=l68LCl6BYvs
|
||||
|
||||
or the new improved one:
|
||||
|
||||
http://www.youtube.com/watch?v=D2Kn4DMOVSw
|
||||
|
||||
Either will give you a fairly good idea of what task is capable of, and
|
||||
whether it fits in to your way of working. As a command line application,
|
||||
task is not for everyone and some of you may prefer to not proceed. The
|
||||
movie or online tutorial file are the quickest way for you to make that
|
||||
decision. The online tutorial can be found at:
|
||||
|
||||
http://www.beckingham.net/task.html
|
||||
|
||||
Task is based on ideas presented in the todo.sh script, found on:
|
||||
|
||||
http://todotxt.org
|
||||
|
||||
Task has many more features than todo.sh, but fundamentally, they are
|
||||
both working toward the same goals, which is to help you follow basic
|
||||
Getting Things Done (GTD) principles.
|
||||
|
||||
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!
|
||||
|
||||
I have found that task makes me more productive and organized.
|
||||
I hope task can do the same for you.
|
||||
|
||||
29
configure.ac
29
configure.ac
@@ -2,7 +2,30 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ(2.61)
|
||||
AC_INIT(task, 1.4.1, bugs@beckingham.net)
|
||||
AC_INIT(task, 1.5.0, bugs@beckingham.net)
|
||||
|
||||
|
||||
CFLAGS="${CFLAGS=}"
|
||||
CXXFLAGS="${CXXFLAGS=}"
|
||||
# this macro is used to get the arguments supplied
|
||||
# to the configure script (./configure --enable-debug)
|
||||
# Check if we have enable debug support.
|
||||
AC_MSG_CHECKING(whether to enable debugging)
|
||||
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)
|
||||
else
|
||||
CFLAGS="$CFLAGS -O3"
|
||||
CXXFLAGS="$CFLAGS -O3"
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
|
||||
AM_INIT_AUTOMAKE
|
||||
AC_CONFIG_SRCDIR([src/task.cpp])
|
||||
AC_CONFIG_HEADER([auto.h])
|
||||
@@ -12,6 +35,8 @@ AC_PROG_CXX
|
||||
AC_PROG_CC
|
||||
AC_LANG(C++)
|
||||
|
||||
AC_SUBST(CFLAGS)
|
||||
|
||||
# Checks for libraries.
|
||||
AC_CHECK_LIB(ncurses,initscr)
|
||||
AC_CHECK_LIB(ncurses,endwin)
|
||||
@@ -19,7 +44,7 @@ AC_CHECK_LIB(ncurses,endwin)
|
||||
# Checks for header files.
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS([stdlib.h sys/file.h sys/stat.h sys/time.h unistd.h])
|
||||
AC_CHECK_HEADERS([string vector map])
|
||||
AC_CHECK_HEADERS([sstream string vector map])
|
||||
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_HEADER_STDBOOL
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Task 1.4.1</title>
|
||||
<title>30-Second Tutorial</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<link rel="stylesheet" href="task.css" type="text/css" />
|
||||
</head>
|
||||
@@ -25,6 +25,7 @@
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="troubleshooting.html">Troubleshooting</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
|
||||
14
html/README
14
html/README
@@ -1,14 +0,0 @@
|
||||
Documentation Restructuring
|
||||
high level pages
|
||||
download
|
||||
previous verisons
|
||||
tutorial
|
||||
recurrence
|
||||
priorities
|
||||
subprojects
|
||||
tags
|
||||
|
||||
|
||||
need page banner
|
||||
need task link off beckinghma.net
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Task 1.4.1</title>
|
||||
<title>Advanced Usage</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<link rel="stylesheet" href="task.css" type="text/css" />
|
||||
</head>
|
||||
@@ -25,6 +25,7 @@
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="troubleshooting.html">Troubleshooting</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
@@ -43,6 +44,25 @@
|
||||
lists all these commands.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
However, if the following configuration variable is specified:
|
||||
</p>
|
||||
|
||||
<pre><code>default.command=list pri:H</code></pre>
|
||||
|
||||
<p>
|
||||
Then this command will be run whenever task is run without arguments.
|
||||
This means that your most common task command can be run simply
|
||||
with the command:
|
||||
</p>
|
||||
|
||||
<pre><code>% task
|
||||
[task list project:foo]
|
||||
|
||||
ID Project Pri Description
|
||||
1 foo H Design the thing
|
||||
2 foo Build the thing</code></pre>
|
||||
|
||||
<strong>% task projects</strong>
|
||||
<p>
|
||||
This report generates a list of all the different projects that you
|
||||
@@ -138,6 +158,11 @@ ID Project Pri Due Active Age Description
|
||||
"task start ..." command was run, as shown above.
|
||||
</p>
|
||||
|
||||
<strong>% task stop <id></strong>
|
||||
<p>
|
||||
Marks a task as inactive, by removing the start time.
|
||||
</p>
|
||||
|
||||
<strong>% task overdue</strong>
|
||||
<p>
|
||||
Simply lists all the task that have a due date that is past, in
|
||||
@@ -294,19 +319,6 @@ ID Project Pri Description
|
||||
This command displays all the colors that task supports.
|
||||
</p>
|
||||
|
||||
<strong>% task usage</strong>
|
||||
<p>
|
||||
If logging has been enabled by the "command.logging=on" directive
|
||||
in the .taskrc file, then task will record every command that is
|
||||
run. When this command is run, task will display a count of how
|
||||
many times each command was used.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This command is for the purpose of seeing whether command are
|
||||
actually used.
|
||||
</p>
|
||||
|
||||
<strong>% task version</strong>
|
||||
<p>
|
||||
This can be used to show the version number of task, and to display
|
||||
@@ -337,6 +349,14 @@ ID Project Pri Description
|
||||
% wtask list
|
||||
...</code></pre>
|
||||
|
||||
<strong>% task <id> "new description"</strong>
|
||||
<p>
|
||||
Not strictly a command, the replacement of the description can
|
||||
be achieved by quoting the entire description. The quotes are
|
||||
necessary in case one of the description words looks like a task
|
||||
command.
|
||||
</p>
|
||||
|
||||
<strong>% task <id> fg:... bg:...</strong>
|
||||
<p>
|
||||
Not strictly a command, the setting of the fg and bg (foreground
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Task 1.4.1</title>
|
||||
<title>Color Usage</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<link rel="stylesheet" href="task.css" type="text/css" />
|
||||
</head>
|
||||
@@ -25,6 +25,7 @@
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="troubleshooting.html">Troubleshooting</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
|
||||
108
html/config.html
108
html/config.html
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Task 1.4.1</title>
|
||||
<title>Task Configuration</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<link rel="stylesheet" href="task.css" type="text/css" />
|
||||
</head>
|
||||
@@ -25,6 +25,7 @@
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="troubleshooting.html">Troubleshooting</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
@@ -51,13 +52,6 @@
|
||||
/Users/paul/.task
|
||||
</dd>
|
||||
|
||||
<dt>command.logging</dt>
|
||||
<dd>
|
||||
May be "on" or "off", defaulting to "off". This determines
|
||||
whether task records commands. This is not generally useful,
|
||||
except while developing task.
|
||||
</dd>
|
||||
|
||||
<dt>confirmation</dt>
|
||||
<dd>
|
||||
May be "yes" or "no", and determines whether task will ask for
|
||||
@@ -177,12 +171,6 @@
|
||||
</p>
|
||||
</dd>
|
||||
|
||||
<dt>showage<dt>
|
||||
<dd>
|
||||
May be "yes" or "no". Determines whether the "Age"
|
||||
column appears on the "list" and "next" reports.
|
||||
<dd>
|
||||
|
||||
<dt>monthsperline</dt>
|
||||
<dd>
|
||||
Determines how many months the "task calendar" command
|
||||
@@ -210,6 +198,8 @@
|
||||
<dt>color</dt>
|
||||
<dd>
|
||||
May be "on" or "off". Determines whether task uses color.
|
||||
When "off", task will use dashes (-----) to underline column
|
||||
headings.
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
@@ -246,6 +236,96 @@
|
||||
<dd>
|
||||
Colors any task where the description contains X.
|
||||
</dd>
|
||||
|
||||
<dt>default.project</dt>
|
||||
<dd>
|
||||
Provides a default project name for the "task add ..." command.
|
||||
</dd>
|
||||
|
||||
<dt>default.priority</dt>
|
||||
<dd>
|
||||
Provides a default priority for the "task add ..." command.
|
||||
</dd>
|
||||
|
||||
<dt>default.command</dt>
|
||||
<dd>
|
||||
<p>
|
||||
Provides a default command that is run every time task is
|
||||
invoked with no arguments. For example, if set to:
|
||||
</p>
|
||||
|
||||
<pre><code>default.command=list project:foo</code></pre>
|
||||
|
||||
<p>
|
||||
Then task will run the "list project:foo" command if no
|
||||
command is specified. This means that by merely typing:
|
||||
</p>
|
||||
|
||||
<pre><code>% task
|
||||
[task list project:foo]
|
||||
|
||||
ID Project Pri Description
|
||||
1 foo H Design the thing
|
||||
2 foo Build the thing</code></pre>
|
||||
|
||||
<p>
|
||||
Note that the value of this variable is simply the command
|
||||
line that you would ordinarily type, but without the
|
||||
preceding "task" program name.
|
||||
</p>
|
||||
</dd>
|
||||
|
||||
<dt>shadow.file</dt>
|
||||
<dd>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This feature can be useful in maintaining a current file for
|
||||
use by the "Samurize" program.
|
||||
</p>
|
||||
</dd>
|
||||
|
||||
<dt>shadow.command</dt>
|
||||
<dd>
|
||||
<p>
|
||||
This is the command that is run to maintain the shadow file,
|
||||
determined by the shadow.file configuration variable. The
|
||||
format is identical to that of default.command - please see
|
||||
the documentation for default.command.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If this command is not specified, task will use the default.command
|
||||
value instead. If that is not specified, the command "list" is used.
|
||||
</p>
|
||||
</dd>
|
||||
|
||||
<dt>shadow.notify</dt>
|
||||
<dd>
|
||||
When this value is set to "on", task will display a message
|
||||
whenever the shadow file is updated by some task command.
|
||||
</dd>
|
||||
|
||||
<p>
|
||||
Note that the command:
|
||||
</p>
|
||||
|
||||
<pre><code>task version</code></pre>
|
||||
|
||||
<p>
|
||||
will display the configuration variables found in the .taskrc file,
|
||||
and will warn you of any variables that are not recognized.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Task 1.4.1</title>
|
||||
<title>Date Handling</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<link rel="stylesheet" href="task.css" type="text/css" />
|
||||
</head>
|
||||
@@ -25,6 +25,7 @@
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="troubleshooting.html">Troubleshooting</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
|
||||
133
html/filter.html
Normal file
133
html/filter.html
Normal file
@@ -0,0 +1,133 @@
|
||||
<!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 Filters</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 />
|
||||
<h2 class="title">Task Filters</h2>
|
||||
<div class="content">
|
||||
<p>
|
||||
A task filter is a means of reducing a task report to a
|
||||
subset that may consist of all tasks that have a specific
|
||||
project, priority, tag, or part of the description.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A task filter consists of additional command line options,
|
||||
that are specified in the same way as when a task is added.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
All task reports can make use of filters.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For example, the report:
|
||||
</p>
|
||||
|
||||
<code><pre>% task list</pre></code>
|
||||
|
||||
<p>
|
||||
Lists all tasks.
|
||||
</p>
|
||||
|
||||
<code><pre>% task list the</pre></code>
|
||||
|
||||
<p>
|
||||
Lists only tasks with "the" in the task description.
|
||||
</p>
|
||||
|
||||
<code><pre>% task list project:Home priority:H</pre></code>
|
||||
|
||||
<p>
|
||||
Lists only tasks with both the "Home" project and "H" priority.
|
||||
</p>
|
||||
|
||||
<code><pre>% task list +shopping</pre></code>
|
||||
|
||||
<p>
|
||||
Lists only tasks with the "shopping" tag.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<div class="content">
|
||||
<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>
|
||||
|
||||
188
html/links.html
Normal file
188
html/links.html
Normal file
@@ -0,0 +1,188 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Task on the Web</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<link rel="stylesheet" href="task.css" type="text/css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<div id="toolbar">
|
||||
<a href="task.html">Home</a>
|
||||
<a href="setup.html">Setup</a>
|
||||
<a href="30second.html">30-second Tutorial</a>
|
||||
<a href="simple.html">Simple</a>
|
||||
<a href="advanced.html">Advanced</a>
|
||||
<a href="shell.html">Shell</a>
|
||||
<a href="config.html">Configuration</a>
|
||||
<a href="color.html">Colors</a>
|
||||
<a href="usage.html">Usage</a>
|
||||
<a href="recur.html">Recurrence</a>
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="troubleshooting.html">Troubleshooting</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<h1 class="title">Task on the Web</h1>
|
||||
<p>
|
||||
Task links from around the web...
|
||||
</p>
|
||||
|
||||
<dt>
|
||||
November 2008, <a href="http://github.com/pbeckingham/task/tree/master/">Task repository on GitHub</a>
|
||||
</dt>
|
||||
<dd>
|
||||
For developers: the task git repository on github.com is now public.
|
||||
</dd>
|
||||
<br>
|
||||
|
||||
<dt>
|
||||
October 2008, <a href="http://blog.rfquerin.org/2008/10/07/using-task-and-dropbox-to-manage-your-to-do-list/">Using Task and Dropbox to manage your To-Do list</a>
|
||||
</dt>
|
||||
<dd>
|
||||
by Richard Querin. Richard discusses the ease of setting up task to
|
||||
use DropBox to share todo lists between work and home.
|
||||
</dd>
|
||||
<br>
|
||||
|
||||
<dt>
|
||||
September 2008, <a href="http://stasantons.blogspot.com/2008/09/task-program-visually-simple.html">Task visualization</a>
|
||||
</dt>
|
||||
<dd>
|
||||
by Stas Antons. Stas - a colleague of mine - presents a visualization
|
||||
of the simplicity of task.
|
||||
</dd>
|
||||
<br>
|
||||
|
||||
<dt>
|
||||
June 2008, <a href="http://blog.rfquerin.org/2008/06/17/building-debian-packages-for-task/">Building Debian Packages For Task</a>
|
||||
</dt>
|
||||
<dd>
|
||||
by Richard Querin. Richard has been providing Debian packages for the
|
||||
various task releases, and discusses how he got up to speed.
|
||||
</dd>
|
||||
<br>
|
||||
|
||||
<dt>
|
||||
June 2008, <a href="http://blog.rfquerin.org/2008/06/06/task-101-an-attempt-at-a-cygwin-build-how-to/">Task 1.0.1 - an attempt at a Cygwin Build How-To</a>
|
||||
</dt>
|
||||
<dd>
|
||||
by Richard Querin. Richard shows us how to build task using Cygwin, after
|
||||
a cry for help on the todo.txt mailing list.
|
||||
</dd>
|
||||
<br>
|
||||
|
||||
<dt>
|
||||
June 2008, <a href="http://www.youtube.com/watch?v=D2Kn4DMOVSw">The second task movie</a>
|
||||
</dt>
|
||||
<dd>
|
||||
This YouTube movie was made to illustrate some of the features of the task
|
||||
program, back when task 1.0.0 was released. While task has grown
|
||||
significantly since then, the commands shown are still valid. It will
|
||||
soon be time for a new movie!
|
||||
<p>
|
||||
|
||||
This movie has a voice-over that explains what is going on.
|
||||
<p>
|
||||
|
||||
For a higher-quality version, download the whole
|
||||
<a href="http://www.beckingham.net/todo2.mov">movie file (10MB)</a>.
|
||||
</dd>
|
||||
<br>
|
||||
|
||||
<dt>
|
||||
December 2006, <a href="http://www.youtube.com/watch?v=l68LCl6BYvs">The first task movie</a>
|
||||
</dt>
|
||||
<dd>
|
||||
This original YouTube task movie was made to illustrate the features of the
|
||||
then-unreleased task program. The idea was to get some feedback and see
|
||||
whether anyone was interested in a new implementation of todo.sh, that added
|
||||
features that are not easily possible with a shell implementation.
|
||||
<p>
|
||||
|
||||
This movie has no voice-over, and you may notice that it exactly duplicates
|
||||
the commands used in the original todo.sh movie (below). That is, until it
|
||||
deviates because of new task commands.
|
||||
</dd>
|
||||
<br>
|
||||
|
||||
<dt>
|
||||
June 2006, <a href="http://www.youtube.com/watch?v=daJ1Hs_y738">The original todo.sh movie</a>
|
||||
</dt>
|
||||
<dd>
|
||||
by Gina Trapani. This is the original YouTube todo.sh movie, made to
|
||||
illustrate the power and simplicity of the original todo.sh program.
|
||||
</dd>
|
||||
<br>
|
||||
|
||||
<dt>
|
||||
June 2006, <a href="http://todotxt.com/">Todo.sh, the inspiration for task</a>
|
||||
</dt>
|
||||
<dd>
|
||||
by Gina Trapani. The website that introduced me to the power and
|
||||
simplicity of the original todo.sh program. Contains useful links
|
||||
and resources - take a look!
|
||||
</dd>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<div class="content">
|
||||
<p>
|
||||
Copyright 2006-2008, P. Beckingham. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td align="right" valign="top" width="200px">
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<script type="text/javascript"><!--
|
||||
google_ad_client = "pub-9709799404235424";
|
||||
/* Task Main */
|
||||
google_ad_slot = "8660617875";
|
||||
google_ad_width = 120;
|
||||
google_ad_height = 600;
|
||||
//-->
|
||||
</script>
|
||||
<script type="text/javascript"
|
||||
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
|
||||
</script>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
|
||||
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
var pageTracker = _gat._getTracker("UA-4737637-1");
|
||||
pageTracker._initData();
|
||||
pageTracker._trackPageview();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Task 1.4.1</title>
|
||||
<title>Recurring Tasks</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<link rel="stylesheet" href="task.css" type="text/css" />
|
||||
</head>
|
||||
@@ -25,6 +25,7 @@
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="troubleshooting.html">Troubleshooting</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Task 1.4.1</title>
|
||||
<title>Task Setup</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<link rel="stylesheet" href="task.css" type="text/css" />
|
||||
</head>
|
||||
@@ -25,6 +25,7 @@
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="troubleshooting.html">Troubleshooting</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
|
||||
126
html/shadow.html
Normal file
126
html/shadow.html
Normal file
@@ -0,0 +1,126 @@
|
||||
<!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 Shadow Files</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 />
|
||||
<h2 class="title">Task Shadow Files</h2>
|
||||
<div class="content">
|
||||
<p>
|
||||
A shadow file is a text file containing a copy of a task
|
||||
report. It is automatically maintained by task whenever
|
||||
something changes in the task database.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This means there is always a current version of the task
|
||||
report kept in a text file. Products such as
|
||||
<a href="www.samurize.com">Samurize</a>,
|
||||
<a href="http://www.mulle-kybernetik.com/software/MkConsole/">MkConsole</a>,
|
||||
or
|
||||
<a href="http://projects.tynsoe.org/en/geektool/">GeekTool</a>
|
||||
can display this file on the computer desktop, so that it
|
||||
is readily visible.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To use a shadow file, edit your .taskrc configuration file,
|
||||
and add two entries as shown:
|
||||
</p>
|
||||
|
||||
<pre><code>shadow.file=/path/to/file
|
||||
shadow.command=list pri:H</code></pre>
|
||||
|
||||
<p>
|
||||
In this example the shadow file contains a report equivalent
|
||||
to running "task list pri:H".
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You can use any task command that generates a report, and of
|
||||
course, you can specify any file name, provided the directory
|
||||
it resides in already exists.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<div class="content">
|
||||
<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>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Task 1.4.1</title>
|
||||
<title>Interacting with the Shell</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<link rel="stylesheet" href="task.css" type="text/css" />
|
||||
</head>
|
||||
@@ -25,6 +25,7 @@
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="troubleshooting.html">Troubleshooting</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Task 1.4.1</title>
|
||||
<title>Simple Usage</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<link rel="stylesheet" href="task.css" type="text/css" />
|
||||
</head>
|
||||
@@ -25,6 +25,7 @@
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="troubleshooting.html">Troubleshooting</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Task 1.4.1</title>
|
||||
<title>Latest Release</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<link rel="stylesheet" href="task.css" type="text/css" />
|
||||
</head>
|
||||
@@ -25,6 +25,7 @@
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="troubleshooting.html">Troubleshooting</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
@@ -54,8 +55,8 @@
|
||||
<li><a href="date.html">Date Handling</a>
|
||||
<li><a href="troubleshooting.html">Troubleshooting</a>
|
||||
<li><a href="versions.html">Old Versions</a>
|
||||
|
||||
<li>Filters (coming soon)
|
||||
<li><a href="filter.html">Filters</a>
|
||||
<li><a href="shadow.html">Shadow Files</a>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
@@ -75,29 +76,34 @@
|
||||
<table>
|
||||
<tr>
|
||||
<td>Source:</td>
|
||||
<td><a href="http://www.beckingham.net/task-1.4.1.tar.gz">task-1.4.1.tar.gz</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mac OS X 10.5 (Leopard) Intel-only:</td>
|
||||
<td><a href="http://www.beckingham.net/task-1.4.1.pkg">task-1.4.1.pkg</a></td>
|
||||
<td><a href="http://www.beckingham.net/task-1.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 package:
|
||||
(Thanks to <a href="http://blog.rfquerin.org">Richard Querin</a>):
|
||||
</td>
|
||||
<td><a href="http://www.beckingham.net/task_1.4.1-1_i386.deb">task_1.4.1-1_i386.deb</a></td>
|
||||
<td><a href="http://www.beckingham.net/task_1.5.0-1_i386.deb">task_1.5.0-1_i386.deb</a></td>
|
||||
</tr>
|
||||
-->
|
||||
</table>
|
||||
|
||||
<h4>New in version 1.4.1 (7/18/2008)</h4>
|
||||
<h4>New in version 1.5.0 (?)</h4>
|
||||
<ul>
|
||||
<li>Fixed bug: Descriptions could not be altered with "task 123 New description"
|
||||
<li>Tweak: For "task calendar" month names are now centered over the month
|
||||
<li>Removed TUTORIAL file contents in favor of online version
|
||||
<li>New Mac Intel-only Leopard (10.5) binary package
|
||||
<li>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.
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
@@ -114,6 +120,7 @@
|
||||
<li>OS X 10.5 Leopard
|
||||
<li>Fedora Core 8
|
||||
<li>Fedora Core 9
|
||||
<li>Ubuntu 7 Feisty Fawn
|
||||
<li>Ubuntu 8 Hardy Heron
|
||||
<li>Solaris 10
|
||||
<li>Cygwin 1.5.25-14
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="troubleshooting.html">Troubleshooting</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
@@ -59,32 +60,6 @@
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<h2 class="title">How to get rid of the "Age" column</h2>
|
||||
<div class="content">
|
||||
<p>
|
||||
The "Age" column that shows up on several reports is proving
|
||||
to be unpopular. In task 1.2.0 and later, here is how to
|
||||
remove it from the reports - make sure you have the line:
|
||||
</p>
|
||||
|
||||
<code><pre>showage=no</pre></code>
|
||||
|
||||
<p>
|
||||
in your ~/.taskrc file.
|
||||
|
||||
Note that the "task long" report does not obey this setting
|
||||
in versions prior to 1.3.1.
|
||||
</p>
|
||||
|
||||
<p class="small">
|
||||
The "showage" setting is supported in task 1.2.0 or later.
|
||||
<br />
|
||||
The "task long" report supports this setting in versions 1.3.1
|
||||
or later.
|
||||
</p>
|
||||
<div>
|
||||
|
||||
<br />
|
||||
<h2 class="title">How do I build task under Cygwin?</h2>
|
||||
<div class="content">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Task 1.4.1</title>
|
||||
<title>Task Usage</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<link rel="stylesheet" href="task.css" type="text/css" />
|
||||
</head>
|
||||
@@ -25,6 +25,7 @@
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="troubleshooting.html">Troubleshooting</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
@@ -38,13 +39,15 @@
|
||||
task long [tags] [attrs] desc...
|
||||
task ls [tags] [attrs] desc...
|
||||
task completed [tags] [attrs] desc...
|
||||
task ID [tags] [attrs] [desc...]
|
||||
task ID [tags] [attrs] ["desc..."]
|
||||
task ID /from/to/
|
||||
task delete ID
|
||||
task undelete ID
|
||||
task info ID
|
||||
task start ID
|
||||
task stop ID
|
||||
task done ID
|
||||
task undo ID
|
||||
task projects
|
||||
task tags
|
||||
task summary
|
||||
@@ -57,7 +60,6 @@
|
||||
task oldest
|
||||
task newest
|
||||
task stats
|
||||
task usage
|
||||
task export
|
||||
task color
|
||||
task version
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
<a href="date.html">Date Handling</a>
|
||||
<a href="troubleshooting.html">Troubleshooting</a>
|
||||
<a href="versions.html">Old Versions</a>
|
||||
<a href="links.html">Task on the Web</a>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
@@ -35,11 +36,91 @@
|
||||
<br />
|
||||
|
||||
<div class="content">
|
||||
<p>
|
||||
<h4>New in version 1.4.3 (11/1/2008)</h4>
|
||||
<a href="http://www.beckingham.net/task-1.4.3.tar.gz">task-1.4.3.tar.gz</a>
|
||||
<br />
|
||||
Mac OS X 10.5 (Leopard) Intel-only:
|
||||
<a href="http://www.beckingham.net/task-1.4.3.pkg">task-1.4.3.pkg</a>
|
||||
<br />
|
||||
Debian package: <a href="http://www.beckingham.net/task_1.4.3-1_i386.deb">task_1.4.3-1_i386.deb</a>
|
||||
(Thanks to <a href="http://blog.rfquerin.org">Richard Querin</a>)
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Fixed misleading task count at bottom of "info" report.
|
||||
<li>Added support for a shadow file that contains a plain text task report,
|
||||
with the "shadow.file" and "shadow.command" configuration variables.
|
||||
The shadow file is automatically updated whenever the task database
|
||||
changes. Useful for integrating with "Samurize".
|
||||
<li>Task now displays a message whenever a shadow file is updated, if the
|
||||
"shadow.notify" configuration variable is set "on".
|
||||
<li>Fixed bug whereby adding a task with a \n, \r or \f did not fail properly.
|
||||
<li>Removed "task usage" command.
|
||||
<li>Added documentation for Shadow files.
|
||||
<li>Added documentation for task filters.
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<h4>New in version 1.4.2 (9/18/2008)</h4>
|
||||
<a href="http://www.beckingham.net/task-1.4.2.tar.gz">task-1.4.2.tar.gz</a>
|
||||
<br />
|
||||
Mac OS X 10.5 (Leopard) Intel-only:
|
||||
<a href="http://www.beckingham.net/task-1.4.2.pkg">task-1.4.2.pkg</a>
|
||||
<br />
|
||||
Debian package: <a href="http://www.beckingham.net/task_1.4.2-1_i386.deb">task_1.4.2-1_i386.deb</a>
|
||||
(Thanks to <a href="http://blog.rfquerin.org">Richard Querin</a>)
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>"task undo" can now retract a "task done" command, provided no
|
||||
reports have been run.
|
||||
<li>Task now correctly sorts on entire strings, instead of just the
|
||||
first character (thanks to Andy Lester).
|
||||
<li>Task now uses dashes (-----) to underline column headings when
|
||||
color is disabled (thanks to Vincent Fleuranceau).
|
||||
<li>Task now allows mixed case attribute names (pri:, PRI:, Pri: ...)
|
||||
and commands (add, ADD, Add ...) (thanks to Vincent Fleuranceau).
|
||||
<li>Task now supports a default project and priority for new tasks, via
|
||||
the new "default.project" and "default.priority" configuration variables
|
||||
(thanks to Vincent Fleuranceau).
|
||||
<li>Task supports improved word-wrapping to the terminal width.
|
||||
<li>Task now supports "default.command" configuration variable (for example
|
||||
it could contain "list due:tomorrow") which is the command that is run
|
||||
whenever task is invoked with no arguments.
|
||||
<li>Task supports modifying the existing description of a task, with the
|
||||
following syntax: task <id> "new description ...".
|
||||
<li>Fixed bug so that relative dates in filters (task list due:eom,
|
||||
task list due:tomorrow, task list due:23rd ...) are now properly
|
||||
supported.
|
||||
<li>Fixed bug so that source now properly includes <string.h> in
|
||||
order to build clean using gcc 4.3 (thanks to H. İbrahim Güngör)
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<h4>New in version 1.4.1 (7/18/2008)</h4>
|
||||
<a href="http://www.beckingham.net/task-1.4.1.tar.gz">task-1.4.1.tar.gz</a>
|
||||
<br />
|
||||
Mac OS X 10.5 (Leopard) Intel-only:
|
||||
<a href="http://www.beckingham.net/task-1.4.1.pkg">task-1.4.1.pkg</a>
|
||||
<br />
|
||||
Debian package: <a href="http://www.beckingham.net/task_1.4.1-1_i386.deb">task_1.4.1-1_i386.deb</a>
|
||||
(Thanks to <a href="http://blog.rfquerin.org">Richard Querin</a>)
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Fixed bug: Descriptions could not be altered with "task 123 New description"
|
||||
<li>Tweak: For "task calendar" month names are now centered over the month
|
||||
<li>Removed TUTORIAL file contents in favor of online version
|
||||
<li>New Mac Intel-only Leopard (10.5) binary package
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<h4>New in version 1.4.0 (7/10/2008)</h4>
|
||||
Source: <a href="http://www.beckingham.net/task-1.4.0.tar.gz">task-1.4.0.tar.gz</a>
|
||||
<br />
|
||||
Debian package: <a href="http://www.beckingham.net/task_1.4.1-1_i386.deb">task_1.4.1-1_i386.deb</a>
|
||||
Debian package: <a href="http://www.beckingham.net/task_1.4.0-1_i386.deb">task_1.4.0-1_i386.deb</a>
|
||||
(Thanks to <a href="http://blog.rfquerin.org">Richard Querin</a>)
|
||||
</p>
|
||||
|
||||
|
||||
70
ideas.txt
70
ideas.txt
@@ -1,70 +0,0 @@
|
||||
Real Parsing
|
||||
define grammar for command line
|
||||
implement flex/bison parser
|
||||
new grammar includes:
|
||||
- task delete <ID> [<ID> ...]
|
||||
- task done <ID> [<ID> ...]
|
||||
|
||||
User-Defined Reports
|
||||
report.large=id,uuid,project,priority,entry,start,due,active,tags,description
|
||||
report.long=id,project,priority,entry,start,due,tags,description
|
||||
report.list=id,project,priority,due,active,description
|
||||
report.ls=id,project,priority,description
|
||||
|
||||
Sorting is always: due+ priority- project+
|
||||
|
||||
ID UUID Project Priority Entry Start Due Active Tags Description
|
||||
|
||||
Test Suite
|
||||
- allow .taskrc override
|
||||
- debug=on to cause all cout to be csv
|
||||
- regression tests for every bug, command, feature
|
||||
|
||||
Recurrence
|
||||
+ new T::status recurring (stored as R)
|
||||
+ new user-specifiable attributes - recur:<duration> [until:<date>]
|
||||
+ duration:
|
||||
daily, day, 1d
|
||||
Nd
|
||||
weekly, 1w
|
||||
Nw
|
||||
biweekly
|
||||
monthly, 1m
|
||||
bimonthly
|
||||
Nm
|
||||
quarterly, 1q
|
||||
Nq
|
||||
biannual, biyearly
|
||||
annual, yearly, 1y
|
||||
Na, Ny
|
||||
+ recur: without due: => Error
|
||||
+ until: without recur: => Error
|
||||
+ New file format: supports status R, recur:, until:, base:, range:
|
||||
- on TDB.gc, adjust base: and compress range: for T::status == recurring
|
||||
- all recurring tasks are removed from lists by T::*pendingT, and a synthetic
|
||||
addendum is generated
|
||||
- when a recurring task is completed, range: is updated, and a synthetic
|
||||
task is added to completed.data that retains the attributes of the root
|
||||
|
||||
- Scenario:
|
||||
# Today = 6/22/2008
|
||||
% task add Friday due:6/15/2008 recur:weekly until 8/1/2008
|
||||
# task must generate a base and range
|
||||
# base:6/15/2008
|
||||
# range:-------
|
||||
# ^6/15
|
||||
# ^6/22
|
||||
# ^6/29
|
||||
# ^7/6
|
||||
# ^7/13
|
||||
# ^7/20
|
||||
# ^7/27
|
||||
% task ls
|
||||
1 Friday 6/15/2008 .lte. today (overdue)
|
||||
2 Friday 6/22/2008 .lte. today (due)
|
||||
3 Friday 6/29/2008 one recurrence
|
||||
4 Friday 7/6/2008 (not shown)
|
||||
5 Friday 7/13/2008 (not shown)
|
||||
6 Friday 7/20/2008 (not shown)
|
||||
7 Friday 7/27/2008 (not shown)
|
||||
|
||||
@@ -98,7 +98,7 @@ task history History shows general activity - how
|
||||
completed etc, by month
|
||||
|
||||
And that's it. There are more commands than this
|
||||
covered in the TUTORIAL file, but this should give
|
||||
covered in the online documentation, but this should give
|
||||
the basic idea.
|
||||
|
||||
Thank you for watching.
|
||||
|
||||
1
src/.gitignore
vendored
1
src/.gitignore
vendored
@@ -1,2 +1 @@
|
||||
./Makefile
|
||||
*.o
|
||||
|
||||
@@ -112,11 +112,9 @@ void Config::createDefault (const std::string& home)
|
||||
if ((out = fopen (rcFile.c_str (), "w")))
|
||||
{
|
||||
fprintf (out, "data.location=%s\n", dataDir.c_str ());
|
||||
fprintf (out, "command.logging=off\n");
|
||||
fprintf (out, "confirmation=yes\n");
|
||||
fprintf (out, "next=2\n");
|
||||
fprintf (out, "dateformat=m/d/Y\n");
|
||||
fprintf (out, "showage=yes\n");
|
||||
fprintf (out, "monthsperline=1\n");
|
||||
fprintf (out, "curses=on\n");
|
||||
fprintf (out, "color=on\n");
|
||||
@@ -131,6 +129,10 @@ void Config::createDefault (const std::string& home)
|
||||
fprintf (out, "#color.tag.bug=yellow\n");
|
||||
fprintf (out, "#color.project.home=on_green\n");
|
||||
fprintf (out, "#color.keyword.car=on_blue\n");
|
||||
fprintf (out, "#shadow.file=%s/shadow.txt\n", dataDir.c_str ());
|
||||
fprintf (out, "#shadow.command=list\n");
|
||||
fprintf (out, "#shadow.notify=on\n");
|
||||
fprintf (out, "#default.command=list\n");
|
||||
|
||||
fclose (out);
|
||||
|
||||
|
||||
21
src/Date.cpp
21
src/Date.cpp
@@ -543,22 +543,35 @@ bool Date::isRelativeDate (const std::string& input)
|
||||
else
|
||||
today += (dow - today.dayOfWeek ()) * 86400;
|
||||
|
||||
mT = today.mT;
|
||||
int m, d, y;
|
||||
today.toMDY (m, d, y);
|
||||
Date then (m, d, y);
|
||||
|
||||
mT = then.mT;
|
||||
return true;
|
||||
}
|
||||
else if (found == "today")
|
||||
{
|
||||
mT = today.mT;
|
||||
Date then (today.month (),
|
||||
today.day (),
|
||||
today.year ());
|
||||
mT = then.mT;
|
||||
return true;
|
||||
}
|
||||
else if (found == "tomorrow")
|
||||
{
|
||||
mT = today.mT + 86400;
|
||||
Date then (today.month (),
|
||||
today.day (),
|
||||
today.year ());
|
||||
mT = then.mT + 86400;
|
||||
return true;
|
||||
}
|
||||
else if (found == "yesterday")
|
||||
{
|
||||
mT = today.mT - 86400;
|
||||
Date then (today.month (),
|
||||
today.day (),
|
||||
today.year ());
|
||||
mT = then.mT - 86400;
|
||||
return true;
|
||||
}
|
||||
else if (found == "eom")
|
||||
|
||||
@@ -1,3 +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
|
||||
AM_CPPFLAGS = -Wall -pedantic -ggdb3 -fno-rtti
|
||||
|
||||
@@ -155,7 +155,6 @@ target_alias = @target_alias@
|
||||
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
|
||||
AM_CPPFLAGS = -Wall -pedantic -ggdb3 -fno-rtti
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
|
||||
89
src/TDB.cpp
89
src/TDB.cpp
@@ -37,7 +37,6 @@
|
||||
TDB::TDB ()
|
||||
: mPendingFile ("")
|
||||
, mCompletedFile ("")
|
||||
, mLogFile ("")
|
||||
, mId (1)
|
||||
{
|
||||
}
|
||||
@@ -54,7 +53,6 @@ void TDB::dataDirectory (const std::string& directory)
|
||||
{
|
||||
mPendingFile = directory + "/pending.data";
|
||||
mCompletedFile = directory + "/completed.data";
|
||||
mLogFile = directory + "/command.log";
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -237,7 +235,7 @@ bool TDB::completeT (const T& t)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool TDB::addT (const T& t) const
|
||||
bool TDB::addT (const T& t)
|
||||
{
|
||||
T task (t);
|
||||
std::vector <std::string> tags;
|
||||
@@ -256,7 +254,9 @@ bool TDB::addT (const T& t) const
|
||||
|
||||
if (task.getStatus () == T::pending ||
|
||||
task.getStatus () == T::recurring)
|
||||
{
|
||||
return writePending (task);
|
||||
}
|
||||
|
||||
return writeCompleted (task);
|
||||
}
|
||||
@@ -286,58 +286,6 @@ bool TDB::modifyT (const T& t)
|
||||
return overwritePending (pending);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool TDB::logRead (std::vector <std::string>& entries) const
|
||||
{
|
||||
entries.clear ();
|
||||
return readLockedFile (mLogFile, entries);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool TDB::logCommand (int argc, char** argv) const
|
||||
{
|
||||
// Get time info.
|
||||
time_t now;
|
||||
time (&now);
|
||||
struct tm* t = localtime (&now);
|
||||
|
||||
// Generate timestamp.
|
||||
char timestamp[20];
|
||||
sprintf (timestamp, "%04d-%02d-%02d %02d:%02d:%02d",
|
||||
t->tm_year + 1900,
|
||||
t->tm_mon + 1,
|
||||
t->tm_mday,
|
||||
t->tm_hour,
|
||||
t->tm_min,
|
||||
t->tm_sec);
|
||||
|
||||
std::string command = timestamp;
|
||||
command += " \"";
|
||||
for (int i = 0; i < argc; ++i)
|
||||
command += std::string (i ? " " : "") + argv[i];
|
||||
command += "\"\n";
|
||||
|
||||
if (! access (mLogFile.c_str (), F_OK | W_OK))
|
||||
{
|
||||
FILE* out;
|
||||
if ((out = fopen (mLogFile.c_str (), "a")))
|
||||
{
|
||||
#ifdef HAVE_FLOCK
|
||||
int retry = 0;
|
||||
while (flock (fileno (out), LOCK_EX) && ++retry <= 3)
|
||||
delay (0.25);
|
||||
#endif
|
||||
|
||||
fputs (command.c_str (), out);
|
||||
|
||||
fclose (out);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool TDB::lock (FILE* file) const
|
||||
{
|
||||
@@ -366,6 +314,7 @@ bool TDB::overwritePending (std::vector <T>& all)
|
||||
fputs (it->compose ().c_str (), out);
|
||||
|
||||
fclose (out);
|
||||
dbChanged ();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -373,7 +322,7 @@ bool TDB::overwritePending (std::vector <T>& all)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool TDB::writePending (const T& t) const
|
||||
bool TDB::writePending (const T& t)
|
||||
{
|
||||
// Write a single task to the pending file
|
||||
FILE* out;
|
||||
@@ -388,6 +337,7 @@ bool TDB::writePending (const T& t) const
|
||||
fputs (t.compose ().c_str (), out);
|
||||
|
||||
fclose (out);
|
||||
dbChanged ();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -395,7 +345,7 @@ bool TDB::writePending (const T& t) const
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool TDB::writeCompleted (const T& t) const
|
||||
bool TDB::writeCompleted (const T& t)
|
||||
{
|
||||
// Write a single task to the pending file
|
||||
FILE* out;
|
||||
@@ -410,6 +360,8 @@ bool TDB::writeCompleted (const T& t) const
|
||||
fputs (t.compose ().c_str (), out);
|
||||
|
||||
fclose (out);
|
||||
// Note: No call to dbChanged here because this call never occurs by itself.
|
||||
// It is always accompanied by an overwritePending call.
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -481,8 +433,11 @@ int TDB::gc ()
|
||||
}
|
||||
}
|
||||
|
||||
// Dump all clean tasks into pending.
|
||||
overwritePending (pending);
|
||||
// Dump all clean tasks into pending. But don't bother unless at least one
|
||||
// task was transferred.
|
||||
if (count)
|
||||
overwritePending (pending);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -493,4 +448,20 @@ int TDB::nextId ()
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TDB::onChange (void (*callback)())
|
||||
{
|
||||
if (callback)
|
||||
mOnChange.push_back (callback);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Iterate over callbacks.
|
||||
void TDB::dbChanged ()
|
||||
{
|
||||
foreach (i, mOnChange)
|
||||
if (*i)
|
||||
(**i) ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
12
src/TDB.h
12
src/TDB.h
@@ -45,25 +45,27 @@ public:
|
||||
bool allCompletedT (std::vector <T>&) const;
|
||||
bool deleteT (const T&);
|
||||
bool completeT (const T&);
|
||||
bool addT (const T&) const;
|
||||
bool addT (const T&);
|
||||
bool modifyT (const T&);
|
||||
bool logRead (std::vector <std::string>&) const;
|
||||
bool logCommand (int, char**) const;
|
||||
int gc ();
|
||||
int nextId ();
|
||||
|
||||
void onChange (void (*)());
|
||||
|
||||
private:
|
||||
bool lock (FILE*) const;
|
||||
bool overwritePending (std::vector <T>&);
|
||||
bool writePending (const T&) const;
|
||||
bool writeCompleted (const T&) const;
|
||||
bool writePending (const T&);
|
||||
bool writeCompleted (const T&);
|
||||
bool readLockedFile (const std::string&, std::vector <std::string>&) const;
|
||||
void dbChanged ();
|
||||
|
||||
private:
|
||||
std::string mPendingFile;
|
||||
std::string mCompletedFile;
|
||||
std::string mLogFile;
|
||||
int mId;
|
||||
std::vector <void (*)()> mOnChange;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
Table::Table ()
|
||||
: mRows (0)
|
||||
, mIntraPadding (1)
|
||||
, mDashedUnderline (false)
|
||||
, mTablePadding (0)
|
||||
, mTableWidth (0)
|
||||
, mSuppressWS (false)
|
||||
@@ -103,6 +104,12 @@ void Table::setTableWidth (int width)
|
||||
mTableWidth = width;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setTableDashedUnderline ()
|
||||
{
|
||||
mDashedUnderline = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int Table::addColumn (const std::string& col)
|
||||
{
|
||||
@@ -582,7 +589,57 @@ const std::string Table::formatHeader (
|
||||
fg, bg,
|
||||
Text::colorize (
|
||||
decoration, Text::nocolor,
|
||||
pad + preJust+ data + postJust + pad) + intraPad);
|
||||
pad + preJust + data + postJust + pad) + intraPad);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// data One Data to be rendered
|
||||
// width 8 Max data width for column/specified width
|
||||
// padding 1 Extra padding around data
|
||||
// intraPadding 0 Extra padding between columns only
|
||||
// justification right Alignment withing padding
|
||||
//
|
||||
// Returns:
|
||||
// "------- "
|
||||
// ------- data
|
||||
// ^ ^ padding
|
||||
// ^ intraPadding
|
||||
// ^^^^^^^^ width
|
||||
// ^ ^ fg/bg
|
||||
//
|
||||
const std::string Table::formatHeaderDashedUnderline (
|
||||
int col,
|
||||
int width,
|
||||
int padding)
|
||||
{
|
||||
assert (width > 0);
|
||||
|
||||
Text::color fg = getHeaderFg (col);
|
||||
Text::color bg = getHeaderBg (col);
|
||||
Text::color decoration = getHeaderUnderline (col);
|
||||
|
||||
std::string data = "";
|
||||
for (int i = 0; i < width; ++i)
|
||||
data += '-';
|
||||
|
||||
std::string pad = "";
|
||||
std::string intraPad = "";
|
||||
std::string attrOn = "";
|
||||
std::string attrOff = "";
|
||||
|
||||
for (int i = 0; i < padding; ++i)
|
||||
pad += " ";
|
||||
|
||||
// Place the value within the available space - justify.
|
||||
if (col < (signed) mColumns.size () - 1)
|
||||
for (int i = 0; i < getIntraPadding (); ++i)
|
||||
intraPad += " ";
|
||||
|
||||
return Text::colorize (
|
||||
fg, bg,
|
||||
Text::colorize (
|
||||
decoration, Text::nocolor,
|
||||
pad + data + pad) + intraPad);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -758,12 +815,12 @@ void Table::sort (std::vector <int>& order)
|
||||
break;
|
||||
|
||||
case ascendingCharacter:
|
||||
if ((char)*left > (char)*right)
|
||||
if ((std::string)*left > (std::string)*right)
|
||||
SWAP
|
||||
break;
|
||||
|
||||
case descendingCharacter:
|
||||
if ((char)*left < (char)*right)
|
||||
if ((std::string)*left < (std::string)*right)
|
||||
SWAP
|
||||
break;
|
||||
|
||||
@@ -861,13 +918,24 @@ const std::string Table::render ()
|
||||
|
||||
// Print column headers in column order.
|
||||
std::string output;
|
||||
std::string underline;
|
||||
for (size_t col = 0; col < mColumns.size (); ++col)
|
||||
{
|
||||
output += formatHeader (
|
||||
col,
|
||||
mCalculatedWidth[col],
|
||||
mColumnPadding[col]);
|
||||
|
||||
if (mDashedUnderline)
|
||||
underline += formatHeaderDashedUnderline (
|
||||
col,
|
||||
mCalculatedWidth[col],
|
||||
mColumnPadding[col]);
|
||||
}
|
||||
|
||||
output += "\n";
|
||||
if (underline.length ())
|
||||
output += underline + "\n";
|
||||
|
||||
// Determine row order, according to sort options.
|
||||
std::vector <int> order;
|
||||
|
||||
@@ -51,6 +51,7 @@ public:
|
||||
void setTablePadding (int);
|
||||
void setTableIntraPadding (int);
|
||||
void setTableWidth (int);
|
||||
void setTableDashedUnderline ();
|
||||
|
||||
int addColumn (const std::string&);
|
||||
void setColumnColor (int, Text::color, Text::color);
|
||||
@@ -98,6 +99,7 @@ private:
|
||||
just getJustification (const int, const int);
|
||||
just getHeaderJustification (const int);
|
||||
const std::string formatHeader (const int, const int, const int);
|
||||
const std::string formatHeaderDashedUnderline (const int, const int, const int);
|
||||
void formatCell (const int, const int, const int, const int, std::vector <std::string>&, std::string&);
|
||||
void optimize (std::string&);
|
||||
void sort (std::vector <int>&);
|
||||
@@ -110,6 +112,7 @@ private:
|
||||
std::map <std::string, std::string> mFg;
|
||||
std::map <std::string, std::string> mBg;
|
||||
std::map <std::string, std::string> mUnderline;
|
||||
bool mDashedUnderline;
|
||||
|
||||
// Padding...
|
||||
int mTablePadding;
|
||||
|
||||
412
src/command.cpp
412
src/command.cpp
@@ -26,6 +26,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
@@ -37,6 +38,7 @@
|
||||
#include "Config.h"
|
||||
#include "Date.h"
|
||||
#include "Table.h"
|
||||
#include "color.h"
|
||||
#include "TDB.h"
|
||||
#include "T.h"
|
||||
#include "task.h"
|
||||
@@ -46,7 +48,7 @@
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void handleAdd (const TDB& tdb, T& task, Config& conf)
|
||||
void handleAdd (TDB& tdb, T& task, Config& conf)
|
||||
{
|
||||
char entryTime[16];
|
||||
sprintf (entryTime, "%u", (unsigned int) time (NULL));
|
||||
@@ -66,16 +68,31 @@ void handleAdd (const TDB& tdb, T& task, Config& conf)
|
||||
task.setAttribute ("mask", "");
|
||||
}
|
||||
|
||||
// Override with default.project, if not specified.
|
||||
if (task.getAttribute ("project") == "")
|
||||
task.setAttribute ("project", conf.get ("default.project", ""));
|
||||
|
||||
// Override with default.priority, if not specified.
|
||||
if (task.getAttribute ("priority") == "")
|
||||
{
|
||||
std::string defaultPriority = conf.get ("default.priority", "");
|
||||
if (validPriority (defaultPriority))
|
||||
task.setAttribute ("priority", defaultPriority);
|
||||
}
|
||||
|
||||
// Disallow blank descriptions.
|
||||
if (task.getDescription () == "")
|
||||
throw std::string ("Cannot add a blank task.");
|
||||
throw std::string ("Cannot add a task that is blank, or contains <CR> or <LF> characters.");
|
||||
|
||||
if (!tdb.addT (task))
|
||||
throw std::string ("Could not create new task.");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void handleProjects (TDB& tdb, T& task, Config& conf)
|
||||
std::string handleProjects (TDB& tdb, T& task, Config& conf)
|
||||
{
|
||||
std::stringstream out;
|
||||
|
||||
// Get all the tasks, including deleted ones.
|
||||
std::vector <T> tasks;
|
||||
tdb.pendingT (tasks);
|
||||
@@ -112,21 +129,25 @@ void handleProjects (TDB& tdb, T& task, Config& conf)
|
||||
table.addCell (row, 1, i->second);
|
||||
}
|
||||
|
||||
std::cout << optionalBlankLine (conf)
|
||||
<< table.render ()
|
||||
<< optionalBlankLine (conf)
|
||||
<< unique.size ()
|
||||
<< (unique.size () == 1 ? " project" : " projects")
|
||||
<< std::endl;
|
||||
out << optionalBlankLine (conf)
|
||||
<< table.render ()
|
||||
<< optionalBlankLine (conf)
|
||||
<< unique.size ()
|
||||
<< (unique.size () == 1 ? " project" : " projects")
|
||||
<< std::endl;
|
||||
}
|
||||
else
|
||||
std::cout << "No projects."
|
||||
<< std::endl;
|
||||
out << "No projects."
|
||||
<< std::endl;
|
||||
|
||||
return out.str ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void handleTags (TDB& tdb, T& task, Config& conf)
|
||||
std::string handleTags (TDB& tdb, T& task, Config& conf)
|
||||
{
|
||||
std::stringstream out;
|
||||
|
||||
// Get all the tasks.
|
||||
std::vector <T> tasks;
|
||||
tdb.pendingT (tasks);
|
||||
@@ -151,20 +172,23 @@ void handleTags (TDB& tdb, T& task, Config& conf)
|
||||
std::cout << i->first << std::endl;
|
||||
|
||||
if (unique.size ())
|
||||
std::cout << optionalBlankLine (conf)
|
||||
<< unique.size ()
|
||||
<< (unique.size () == 1 ? " tag" : " tags")
|
||||
<< std::endl;
|
||||
out << optionalBlankLine (conf)
|
||||
<< unique.size ()
|
||||
<< (unique.size () == 1 ? " tag" : " tags")
|
||||
<< std::endl;
|
||||
else
|
||||
std::cout << "No tags."
|
||||
<< std::endl;
|
||||
out << "No tags."
|
||||
<< std::endl;
|
||||
|
||||
return out.str ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// If a task is deleted, but is still in the pending file, then it may be
|
||||
// undeleted simply by changing it's status.
|
||||
void handleUndelete (TDB& tdb, T& task, Config& conf)
|
||||
std::string handleUndelete (TDB& tdb, T& task, Config& conf)
|
||||
{
|
||||
std::stringstream out;
|
||||
std::vector <T> all;
|
||||
tdb.allPendingT (all);
|
||||
|
||||
@@ -178,8 +202,8 @@ void handleUndelete (TDB& tdb, T& task, Config& conf)
|
||||
{
|
||||
if (it->getAttribute ("recur") != "")
|
||||
{
|
||||
std::cout << "Task does not support 'undelete' for recurring tasks." << std::endl;
|
||||
return;
|
||||
out << "Task does not support 'undelete' for recurring tasks." << std::endl;
|
||||
return out.str ();
|
||||
}
|
||||
|
||||
T restored (*it);
|
||||
@@ -187,25 +211,73 @@ void handleUndelete (TDB& tdb, T& task, Config& conf)
|
||||
restored.removeAttribute ("end");
|
||||
tdb.modifyT (restored);
|
||||
|
||||
std::cout << "Task " << id << " successfully undeleted." << std::endl;
|
||||
return;
|
||||
out << "Task " << id << " successfully undeleted." << std::endl;
|
||||
return out.str ();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Task " << id << " is not deleted - therefore cannot undelete." << std::endl;
|
||||
return;
|
||||
out << "Task " << id << " is not deleted - therefore cannot undelete." << std::endl;
|
||||
return out.str ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Task " << id
|
||||
<< " not found - tasks can only be reliably undeleted if the undelete" << std::endl
|
||||
<< "command is run immediately after the errant delete command." << std::endl;
|
||||
out << "Task " << id
|
||||
<< " not found - tasks can only be reliably undeleted if the undelete" << std::endl
|
||||
<< "command is run immediately after the errant delete command." << std::endl;
|
||||
|
||||
return out.str ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void handleVersion (Config& conf)
|
||||
// If a task is done, but is still in the pending file, then it may be undone
|
||||
// simply by changing it's status.
|
||||
std::string handleUndo (TDB& tdb, T& task, Config& conf)
|
||||
{
|
||||
std::stringstream out;
|
||||
|
||||
std::vector <T> all;
|
||||
tdb.allPendingT (all);
|
||||
|
||||
int id = task.getId ();
|
||||
std::vector <T>::iterator it;
|
||||
for (it = all.begin (); it != all.end (); ++it)
|
||||
{
|
||||
if (it->getId () == id)
|
||||
{
|
||||
if (it->getStatus () == T::completed)
|
||||
{
|
||||
if (it->getAttribute ("recur") != "")
|
||||
return std::string ("Task does not support 'undo' for recurring tasks.\n");
|
||||
|
||||
T restored (*it);
|
||||
restored.setStatus (T::pending);
|
||||
restored.removeAttribute ("end");
|
||||
tdb.modifyT (restored);
|
||||
|
||||
out << "Task " << id << " successfully undone." << std::endl;
|
||||
return out.str ();
|
||||
}
|
||||
else
|
||||
{
|
||||
out << "Task " << id << " is not done - therefore cannot be undone." << std::endl;
|
||||
return out.str ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out << "Task " << id
|
||||
<< " not found - tasks can only be reliably undone if the undo" << std::endl
|
||||
<< "command is run immediately after the errant done command." << std::endl;
|
||||
|
||||
return out.str ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string handleVersion (Config& conf)
|
||||
{
|
||||
std::stringstream out;
|
||||
|
||||
// Determine window size, and set table accordingly.
|
||||
int width = conf.get ("defaultwidth", 80);
|
||||
#ifdef HAVE_LIBNCURSES
|
||||
@@ -217,6 +289,26 @@ void handleVersion (Config& conf)
|
||||
}
|
||||
#endif
|
||||
|
||||
// Create a table for the disclaimer.
|
||||
Table disclaimer;
|
||||
disclaimer.setTableWidth (width);
|
||||
disclaimer.addColumn (" ");
|
||||
disclaimer.setColumnWidth (0, Table::flexible);
|
||||
disclaimer.setColumnJustification (0, Table::left);
|
||||
disclaimer.addCell (disclaimer.addRow (), 0,
|
||||
"Task comes with ABSOLUTELY NO WARRANTY; for details read the COPYING file "
|
||||
"included. This is free software, and you are welcome to redistribute it "
|
||||
"under certain conditions; again, see the COPYING file for details.");
|
||||
|
||||
// Create a table for the URL.
|
||||
Table link;
|
||||
link.setTableWidth (width);
|
||||
link.addColumn (" ");
|
||||
link.setColumnWidth (0, Table::flexible);
|
||||
link.setColumnJustification (0, Table::left);
|
||||
link.addCell (link.addRow (), 0,
|
||||
"See http://www.beckingham.net/task.html for the latest releases and a full tutorial.");
|
||||
|
||||
// Create a table for output.
|
||||
Table table;
|
||||
table.setTableWidth (width);
|
||||
@@ -229,6 +321,8 @@ void handleVersion (Config& conf)
|
||||
table.setColumnUnderline (0);
|
||||
table.setColumnUnderline (1);
|
||||
}
|
||||
else
|
||||
table.setTableDashedUnderline ();
|
||||
|
||||
table.setColumnWidth (0, Table::minimum);
|
||||
table.setColumnWidth (1, Table::flexible);
|
||||
@@ -249,48 +343,79 @@ void handleVersion (Config& conf)
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Copyright (C) 2006 - 2008, P. Beckingham."
|
||||
<< std::endl
|
||||
<< PACKAGE
|
||||
<< " "
|
||||
<< VERSION
|
||||
<< std::endl
|
||||
<< std::endl
|
||||
<< "Task comes with ABSOLUTELY NO WARRANTY; for details read the COPYING file"
|
||||
<< std::endl
|
||||
<< "included. This is free software, and you are welcome to redistribute it"
|
||||
<< std::endl
|
||||
<< "under certain conditions; again, see the COPYING file for details."
|
||||
<< std::endl
|
||||
<< std::endl
|
||||
<< table.render ()
|
||||
<< std::endl
|
||||
<< "See http://www.beckingham.net/task.html for the latest releases and a full tutorial."
|
||||
<< std::endl
|
||||
<< std::endl;
|
||||
out << "Copyright (C) 2006 - 2008, P. Beckingham."
|
||||
<< std::endl
|
||||
<< (conf.get ("color", true) ? Text::colorize (Text::bold, Text::nocolor, PACKAGE) : PACKAGE)
|
||||
<< " "
|
||||
<< (conf.get ("color", true) ? Text::colorize (Text::bold, Text::nocolor, VERSION) : VERSION)
|
||||
<< std::endl
|
||||
<< disclaimer.render ()
|
||||
<< std::endl
|
||||
<< table.render ()
|
||||
<< link.render ()
|
||||
<< std::endl;
|
||||
|
||||
// Complain about configuration variables that are not recognized.
|
||||
// These are the regular configuration variables.
|
||||
std::string recognized =
|
||||
"blanklines color color.active color.due color.overdue color.pri.H "
|
||||
"color.pri.L color.pri.M color.pri.none color.tagged confirmation curses "
|
||||
"data.location dateformat default.command default.priority defaultwidth due "
|
||||
"monthsperline nag newest next oldest project shadow.command shadow.file "
|
||||
"shadow.notify";
|
||||
|
||||
std::vector <std::string> unrecognized;
|
||||
foreach (i, all)
|
||||
{
|
||||
if (recognized.find (*i) == std::string::npos)
|
||||
{
|
||||
// These are special configuration variables, because their name is
|
||||
// dynamic.
|
||||
if (i->find ("color.keyword.") == std::string::npos &&
|
||||
i->find ("color.project.") == std::string::npos &&
|
||||
i->find ("color.tag.") == std::string::npos &&
|
||||
i->find ("report.") == std::string::npos)
|
||||
{
|
||||
unrecognized.push_back (*i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (unrecognized.size ())
|
||||
{
|
||||
out << "Your .taskrc file contains these unrecognized variables:"
|
||||
<< std::endl;
|
||||
|
||||
foreach (i, unrecognized)
|
||||
out << " " << *i << std::endl;
|
||||
|
||||
out << std::endl;
|
||||
}
|
||||
|
||||
// Verify installation. This is mentioned in the documentation as the way to
|
||||
// ensure everything is properly installed.
|
||||
|
||||
if (all.size () == 0)
|
||||
std::cout << "Configuration error: .taskrc contains no entries"
|
||||
<< std::endl;
|
||||
out << "Configuration error: .taskrc contains no entries"
|
||||
<< std::endl;
|
||||
else
|
||||
{
|
||||
if (conf.get ("data.location") == "")
|
||||
std::cout << "Configuration error: data.location not specified in .taskrc "
|
||||
"file."
|
||||
<< std::endl;
|
||||
out << "Configuration error: data.location not specified in .taskrc "
|
||||
"file."
|
||||
<< std::endl;
|
||||
|
||||
if (access (expandPath (conf.get ("data.location")).c_str (), X_OK))
|
||||
std::cout << "Configuration error: data.location contains a directory name"
|
||||
" that doesn't exist, or is unreadable."
|
||||
<< std::endl;
|
||||
out << "Configuration error: data.location contains a directory name"
|
||||
" that doesn't exist, or is unreadable."
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
return out.str ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void handleDelete (TDB& tdb, T& task, Config& conf)
|
||||
std::string handleDelete (TDB& tdb, T& task, Config& conf)
|
||||
{
|
||||
if (conf.get ("confirmation") != "yes" || confirm ("Permanently delete task?"))
|
||||
{
|
||||
@@ -314,7 +439,7 @@ void handleDelete (TDB& tdb, T& task, Config& conf)
|
||||
sibling->getUUID () == parent)
|
||||
tdb.deleteT (*sibling);
|
||||
|
||||
return;
|
||||
return std::string ("");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -322,7 +447,7 @@ void handleDelete (TDB& tdb, T& task, Config& conf)
|
||||
t->setStatus (T::deleted);
|
||||
updateRecurrenceMask (tdb, all, *t);
|
||||
tdb.deleteT (*t);
|
||||
return;
|
||||
return std::string ("");
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -333,11 +458,13 @@ void handleDelete (TDB& tdb, T& task, Config& conf)
|
||||
}
|
||||
}
|
||||
else
|
||||
std::cout << "Task not deleted." << std::endl;
|
||||
return std::string ("Task not deleted.\n");
|
||||
|
||||
return std::string ("");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void handleStart (TDB& tdb, T& task, Config& conf)
|
||||
std::string handleStart (TDB& tdb, T& task, Config& conf)
|
||||
{
|
||||
std::vector <T> all;
|
||||
tdb.pendingT (all);
|
||||
@@ -359,14 +486,54 @@ void handleStart (TDB& tdb, T& task, Config& conf)
|
||||
tdb.modifyT (original);
|
||||
|
||||
nag (tdb, task, conf);
|
||||
return;
|
||||
return std::string ("");
|
||||
}
|
||||
else
|
||||
std::cout << "Task " << task.getId () << " already started." << std::endl;
|
||||
{
|
||||
std::stringstream out;
|
||||
out << "Task " << task.getId () << " already started." << std::endl;
|
||||
return out.str ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw std::string ("Task not found.");
|
||||
return std::string (""); // To satisfy gcc.
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string handleStop (TDB& tdb, T& task, Config& conf)
|
||||
{
|
||||
std::vector <T> all;
|
||||
tdb.pendingT (all);
|
||||
|
||||
std::vector <T>::iterator it;
|
||||
for (it = all.begin (); it != all.end (); ++it)
|
||||
{
|
||||
if (it->getId () == task.getId ())
|
||||
{
|
||||
T original (*it);
|
||||
|
||||
if (original.getAttribute ("start") != "")
|
||||
{
|
||||
original.removeAttribute ("start");
|
||||
original.setId (task.getId ());
|
||||
tdb.modifyT (original);
|
||||
|
||||
nag (tdb, task, conf);
|
||||
return std::string ("");
|
||||
}
|
||||
else
|
||||
{
|
||||
std::stringstream out;
|
||||
out << "Task " << task.getId () << " not started." << std::endl;
|
||||
return out.str ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw std::string ("Task not found.");
|
||||
return std::string (""); // To satisfy gcc.
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -405,6 +572,7 @@ void handleExport (TDB& tdb, T& task, Config& conf)
|
||||
if (out.good ())
|
||||
{
|
||||
out << "'id',"
|
||||
<< "'uuid',"
|
||||
<< "'status',"
|
||||
<< "'tags',"
|
||||
<< "'entry',"
|
||||
@@ -525,87 +693,91 @@ void handleModify (TDB& tdb, T& task, Config& conf)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void handleColor (Config& conf)
|
||||
std::string handleColor (Config& conf)
|
||||
{
|
||||
std::stringstream out;
|
||||
|
||||
if (conf.get ("color", true))
|
||||
{
|
||||
std::cout << optionalBlankLine (conf) << "Foreground" << std::endl
|
||||
<< " "
|
||||
<< Text::colorize (Text::bold, Text::nocolor, "bold") << " "
|
||||
<< Text::colorize (Text::underline, Text::nocolor, "underline") << " "
|
||||
<< Text::colorize (Text::bold_underline, Text::nocolor, "bold_underline") << std::endl
|
||||
out << optionalBlankLine (conf) << "Foreground" << std::endl
|
||||
<< " "
|
||||
<< Text::colorize (Text::bold, Text::nocolor, "bold") << " "
|
||||
<< Text::colorize (Text::underline, Text::nocolor, "underline") << " "
|
||||
<< Text::colorize (Text::bold_underline, Text::nocolor, "bold_underline") << std::endl
|
||||
|
||||
<< " " << Text::colorize (Text::black, Text::nocolor, "black") << " "
|
||||
<< Text::colorize (Text::bold_black, Text::nocolor, "bold_black") << " "
|
||||
<< Text::colorize (Text::underline_black, Text::nocolor, "underline_black") << " "
|
||||
<< Text::colorize (Text::bold_underline_black, Text::nocolor, "bold_underline_black") << std::endl
|
||||
<< " " << Text::colorize (Text::black, Text::nocolor, "black") << " "
|
||||
<< Text::colorize (Text::bold_black, Text::nocolor, "bold_black") << " "
|
||||
<< Text::colorize (Text::underline_black, Text::nocolor, "underline_black") << " "
|
||||
<< Text::colorize (Text::bold_underline_black, Text::nocolor, "bold_underline_black") << std::endl
|
||||
|
||||
<< " " << Text::colorize (Text::red, Text::nocolor, "red") << " "
|
||||
<< Text::colorize (Text::bold_red, Text::nocolor, "bold_red") << " "
|
||||
<< Text::colorize (Text::underline_red, Text::nocolor, "underline_red") << " "
|
||||
<< Text::colorize (Text::bold_underline_red, Text::nocolor, "bold_underline_red") << std::endl
|
||||
<< " " << Text::colorize (Text::red, Text::nocolor, "red") << " "
|
||||
<< Text::colorize (Text::bold_red, Text::nocolor, "bold_red") << " "
|
||||
<< Text::colorize (Text::underline_red, Text::nocolor, "underline_red") << " "
|
||||
<< Text::colorize (Text::bold_underline_red, Text::nocolor, "bold_underline_red") << std::endl
|
||||
|
||||
<< " " << Text::colorize (Text::green, Text::nocolor, "green") << " "
|
||||
<< Text::colorize (Text::bold_green, Text::nocolor, "bold_green") << " "
|
||||
<< Text::colorize (Text::underline_green, Text::nocolor, "underline_green") << " "
|
||||
<< Text::colorize (Text::bold_underline_green, Text::nocolor, "bold_underline_green") << std::endl
|
||||
<< " " << Text::colorize (Text::green, Text::nocolor, "green") << " "
|
||||
<< Text::colorize (Text::bold_green, Text::nocolor, "bold_green") << " "
|
||||
<< Text::colorize (Text::underline_green, Text::nocolor, "underline_green") << " "
|
||||
<< Text::colorize (Text::bold_underline_green, Text::nocolor, "bold_underline_green") << std::endl
|
||||
|
||||
<< " " << Text::colorize (Text::yellow, Text::nocolor, "yellow") << " "
|
||||
<< Text::colorize (Text::bold_yellow, Text::nocolor, "bold_yellow") << " "
|
||||
<< Text::colorize (Text::underline_yellow, Text::nocolor, "underline_yellow") << " "
|
||||
<< Text::colorize (Text::bold_underline_yellow, Text::nocolor, "bold_underline_yellow") << std::endl
|
||||
<< " " << Text::colorize (Text::yellow, Text::nocolor, "yellow") << " "
|
||||
<< Text::colorize (Text::bold_yellow, Text::nocolor, "bold_yellow") << " "
|
||||
<< Text::colorize (Text::underline_yellow, Text::nocolor, "underline_yellow") << " "
|
||||
<< Text::colorize (Text::bold_underline_yellow, Text::nocolor, "bold_underline_yellow") << std::endl
|
||||
|
||||
<< " " << Text::colorize (Text::blue, Text::nocolor, "blue") << " "
|
||||
<< Text::colorize (Text::bold_blue, Text::nocolor, "bold_blue") << " "
|
||||
<< Text::colorize (Text::underline_blue, Text::nocolor, "underline_blue") << " "
|
||||
<< Text::colorize (Text::bold_underline_blue, Text::nocolor, "bold_underline_blue") << std::endl
|
||||
<< " " << Text::colorize (Text::blue, Text::nocolor, "blue") << " "
|
||||
<< Text::colorize (Text::bold_blue, Text::nocolor, "bold_blue") << " "
|
||||
<< Text::colorize (Text::underline_blue, Text::nocolor, "underline_blue") << " "
|
||||
<< Text::colorize (Text::bold_underline_blue, Text::nocolor, "bold_underline_blue") << std::endl
|
||||
|
||||
<< " " << Text::colorize (Text::magenta, Text::nocolor, "magenta") << " "
|
||||
<< Text::colorize (Text::bold_magenta, Text::nocolor, "bold_magenta") << " "
|
||||
<< Text::colorize (Text::underline_magenta, Text::nocolor, "underline_magenta") << " "
|
||||
<< Text::colorize (Text::bold_underline_magenta, Text::nocolor, "bold_underline_magenta") << std::endl
|
||||
<< " " << Text::colorize (Text::magenta, Text::nocolor, "magenta") << " "
|
||||
<< Text::colorize (Text::bold_magenta, Text::nocolor, "bold_magenta") << " "
|
||||
<< Text::colorize (Text::underline_magenta, Text::nocolor, "underline_magenta") << " "
|
||||
<< Text::colorize (Text::bold_underline_magenta, Text::nocolor, "bold_underline_magenta") << std::endl
|
||||
|
||||
<< " " << Text::colorize (Text::cyan, Text::nocolor, "cyan") << " "
|
||||
<< Text::colorize (Text::bold_cyan, Text::nocolor, "bold_cyan") << " "
|
||||
<< Text::colorize (Text::underline_cyan, Text::nocolor, "underline_cyan") << " "
|
||||
<< Text::colorize (Text::bold_underline_cyan, Text::nocolor, "bold_underline_cyan") << std::endl
|
||||
<< " " << Text::colorize (Text::cyan, Text::nocolor, "cyan") << " "
|
||||
<< Text::colorize (Text::bold_cyan, Text::nocolor, "bold_cyan") << " "
|
||||
<< Text::colorize (Text::underline_cyan, Text::nocolor, "underline_cyan") << " "
|
||||
<< Text::colorize (Text::bold_underline_cyan, Text::nocolor, "bold_underline_cyan") << std::endl
|
||||
|
||||
<< " " << Text::colorize (Text::white, Text::nocolor, "white") << " "
|
||||
<< Text::colorize (Text::bold_white, Text::nocolor, "bold_white") << " "
|
||||
<< Text::colorize (Text::underline_white, Text::nocolor, "underline_white") << " "
|
||||
<< Text::colorize (Text::bold_underline_white, Text::nocolor, "bold_underline_white") << std::endl
|
||||
<< " " << Text::colorize (Text::white, Text::nocolor, "white") << " "
|
||||
<< Text::colorize (Text::bold_white, Text::nocolor, "bold_white") << " "
|
||||
<< Text::colorize (Text::underline_white, Text::nocolor, "underline_white") << " "
|
||||
<< Text::colorize (Text::bold_underline_white, Text::nocolor, "bold_underline_white") << std::endl
|
||||
|
||||
<< std::endl << "Background" << std::endl
|
||||
<< " " << Text::colorize (Text::nocolor, Text::on_black, "on_black") << " "
|
||||
<< Text::colorize (Text::nocolor, Text::on_bright_black, "on_bright_black") << std::endl
|
||||
<< std::endl << "Background" << std::endl
|
||||
<< " " << Text::colorize (Text::nocolor, Text::on_black, "on_black") << " "
|
||||
<< Text::colorize (Text::nocolor, Text::on_bright_black, "on_bright_black") << std::endl
|
||||
|
||||
<< " " << Text::colorize (Text::nocolor, Text::on_red, "on_red") << " "
|
||||
<< Text::colorize (Text::nocolor, Text::on_bright_red, "on_bright_red") << std::endl
|
||||
<< " " << Text::colorize (Text::nocolor, Text::on_red, "on_red") << " "
|
||||
<< Text::colorize (Text::nocolor, Text::on_bright_red, "on_bright_red") << std::endl
|
||||
|
||||
<< " " << Text::colorize (Text::nocolor, Text::on_green, "on_green") << " "
|
||||
<< Text::colorize (Text::nocolor, Text::on_bright_green, "on_bright_green") << std::endl
|
||||
<< " " << Text::colorize (Text::nocolor, Text::on_green, "on_green") << " "
|
||||
<< Text::colorize (Text::nocolor, Text::on_bright_green, "on_bright_green") << std::endl
|
||||
|
||||
<< " " << Text::colorize (Text::nocolor, Text::on_yellow, "on_yellow") << " "
|
||||
<< Text::colorize (Text::nocolor, Text::on_bright_yellow, "on_bright_yellow") << std::endl
|
||||
<< " " << Text::colorize (Text::nocolor, Text::on_yellow, "on_yellow") << " "
|
||||
<< Text::colorize (Text::nocolor, Text::on_bright_yellow, "on_bright_yellow") << std::endl
|
||||
|
||||
<< " " << Text::colorize (Text::nocolor, Text::on_blue, "on_blue") << " "
|
||||
<< Text::colorize (Text::nocolor, Text::on_bright_blue, "on_bright_blue") << std::endl
|
||||
<< " " << Text::colorize (Text::nocolor, Text::on_blue, "on_blue") << " "
|
||||
<< Text::colorize (Text::nocolor, Text::on_bright_blue, "on_bright_blue") << std::endl
|
||||
|
||||
<< " " << Text::colorize (Text::nocolor, Text::on_magenta, "on_magenta") << " "
|
||||
<< Text::colorize (Text::nocolor, Text::on_bright_magenta, "on_bright_magenta") << std::endl
|
||||
<< " " << Text::colorize (Text::nocolor, Text::on_magenta, "on_magenta") << " "
|
||||
<< Text::colorize (Text::nocolor, Text::on_bright_magenta, "on_bright_magenta") << std::endl
|
||||
|
||||
<< " " << Text::colorize (Text::nocolor, Text::on_cyan, "on_cyan") << " "
|
||||
<< Text::colorize (Text::nocolor, Text::on_bright_cyan, "on_bright_cyan") << std::endl
|
||||
<< " " << Text::colorize (Text::nocolor, Text::on_cyan, "on_cyan") << " "
|
||||
<< Text::colorize (Text::nocolor, Text::on_bright_cyan, "on_bright_cyan") << std::endl
|
||||
|
||||
<< " " << Text::colorize (Text::nocolor, Text::on_white, "on_white") << " "
|
||||
<< Text::colorize (Text::nocolor, Text::on_bright_white, "on_bright_white") << std::endl
|
||||
<< " " << Text::colorize (Text::nocolor, Text::on_white, "on_white") << " "
|
||||
<< Text::colorize (Text::nocolor, Text::on_bright_white, "on_bright_white") << std::endl
|
||||
|
||||
<< optionalBlankLine (conf);
|
||||
<< optionalBlankLine (conf);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Color is currently turned off in your .taskrc file." << std::endl;
|
||||
out << "Color is currently turned off in your .taskrc file." << std::endl;
|
||||
}
|
||||
|
||||
return out.str ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
103
src/parse.cpp
103
src/parse.cpp
@@ -35,6 +35,8 @@
|
||||
#include "T.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// NOTE: These are static arrays only because there is no initializer list for
|
||||
// std::vector.
|
||||
static const char* colors[] =
|
||||
{
|
||||
"bold",
|
||||
@@ -138,14 +140,18 @@ static const char* commands[] =
|
||||
"projects",
|
||||
"start",
|
||||
"stats",
|
||||
"stop",
|
||||
"summary",
|
||||
"tags",
|
||||
"undelete",
|
||||
"usage",
|
||||
"undo",
|
||||
"version",
|
||||
"",
|
||||
};
|
||||
|
||||
static std::vector <std::string> customReports;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void guess (const std::string& type, const char** list, std::string& candidate)
|
||||
{
|
||||
std::vector <std::string> options;
|
||||
@@ -179,6 +185,36 @@ void guess (const std::string& type, const char** list, std::string& candidate)
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void guess (const std::string& type, std::vector<std::string>& options, std::string& candidate)
|
||||
{
|
||||
std::vector <std::string> matches;
|
||||
autoComplete (candidate, options, matches);
|
||||
if (1 == matches.size ())
|
||||
candidate = matches[0];
|
||||
|
||||
else if (0 == matches.size ())
|
||||
// throw std::string ("Unrecognized ") + type + " '" + candidate + "'";
|
||||
candidate = "";
|
||||
|
||||
else
|
||||
{
|
||||
std::string error = "Ambiguous ";
|
||||
error += type;
|
||||
error += " '";
|
||||
error += candidate;
|
||||
error += "' - could be either of ";
|
||||
for (size_t i = 0; i < matches.size (); ++i)
|
||||
{
|
||||
if (i)
|
||||
error += ", ";
|
||||
error += matches[i];
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static bool isCommand (const std::string& candidate)
|
||||
{
|
||||
@@ -189,7 +225,11 @@ static bool isCommand (const std::string& candidate)
|
||||
std::vector <std::string> matches;
|
||||
autoComplete (candidate, options, matches);
|
||||
if (0 == matches.size ())
|
||||
return false;
|
||||
{
|
||||
autoComplete (candidate, customReports, matches);
|
||||
if (0 == matches.size ())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -207,7 +247,7 @@ bool validDate (std::string& date, Config& conf)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static bool validPriority (const std::string& input)
|
||||
bool validPriority (const std::string& input)
|
||||
{
|
||||
if (input != "H" &&
|
||||
input != "M" &&
|
||||
@@ -283,10 +323,12 @@ static bool validTag (const std::string& input)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static bool validDescription (const std::string& input)
|
||||
{
|
||||
if (input.length () > 0)
|
||||
return true;
|
||||
if (input.length () == 0) return false;
|
||||
if (input.find ("\r") != std::string::npos) return false;
|
||||
if (input.find ("\f") != std::string::npos) return false;
|
||||
if (input.find ("\n") != std::string::npos) return false;
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -295,7 +337,12 @@ static bool validCommand (std::string& input)
|
||||
std::string copy = input;
|
||||
guess ("command", commands, copy);
|
||||
if (copy == "")
|
||||
return false;
|
||||
{
|
||||
copy = input;
|
||||
guess ("command", customReports, copy);
|
||||
if (copy == "")
|
||||
return false;
|
||||
}
|
||||
|
||||
input = copy;
|
||||
return true;
|
||||
@@ -370,8 +417,8 @@ void parse (
|
||||
std::string to;
|
||||
|
||||
// An id is the first argument found that contains all digits.
|
||||
if (command != "add" && // "add" doesn't require an ID
|
||||
task.getId () == 0 &&
|
||||
if (lowerCase (command) != "add" && // "add" doesn't require an ID
|
||||
task.getId () == 0 &&
|
||||
validId (arg))
|
||||
task.setId (::atoi (arg.c_str ()));
|
||||
|
||||
@@ -388,7 +435,7 @@ void parse (
|
||||
// value.
|
||||
else if ((colon = arg.find (":")) != std::string::npos)
|
||||
{
|
||||
std::string name = arg.substr (0, colon);
|
||||
std::string name = lowerCase (arg.substr (0, colon));
|
||||
std::string value = arg.substr (colon + 1, std::string::npos);
|
||||
|
||||
if (validAttribute (name, value, conf))
|
||||
@@ -412,11 +459,11 @@ void parse (
|
||||
// Command.
|
||||
else if (command == "")
|
||||
{
|
||||
if (isCommand (arg) && validCommand (arg))
|
||||
command = arg;
|
||||
std::string l = lowerCase (arg);
|
||||
if (isCommand (l) && validCommand (l))
|
||||
command = l;
|
||||
else
|
||||
descCandidate += arg;
|
||||
// throw std::string ("'") + arg + "' is not a valid command.";
|
||||
}
|
||||
|
||||
// Anything else is just considered description.
|
||||
@@ -438,4 +485,34 @@ void parse (
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void loadCustomReports (Config& conf)
|
||||
{
|
||||
std::vector <std::string> all;
|
||||
conf.all (all);
|
||||
|
||||
foreach (i, all)
|
||||
{
|
||||
if (i->substr (0, 7) == "report.")
|
||||
{
|
||||
std::string report = i->substr (7, std::string::npos);
|
||||
unsigned int columns = report.find (".columns");
|
||||
if (columns != std::string::npos)
|
||||
{
|
||||
report = report.substr (0, columns);
|
||||
customReports.push_back (report);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool isCustomReport (const std::string& report)
|
||||
{
|
||||
foreach (i, customReports)
|
||||
if (*i == report)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
637
src/report.cpp
637
src/report.cpp
File diff suppressed because it is too large
Load Diff
244
src/task.cpp
244
src/task.cpp
@@ -29,6 +29,7 @@
|
||||
#include <fstream>
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <pwd.h>
|
||||
@@ -45,6 +46,11 @@
|
||||
#include <ncurses.h>
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Globals for exclusive use by callback function.
|
||||
static TDB* gTdb = NULL;
|
||||
static Config* gConf = NULL;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static void shortUsage (Config& conf)
|
||||
{
|
||||
@@ -119,12 +125,20 @@ static void shortUsage (Config& conf)
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task start ID");
|
||||
table.addCell (row, 2, "Marks specified task as started, starts the clock ticking");
|
||||
table.addCell (row, 2, "Marks specified task as started");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task stop ID");
|
||||
table.addCell (row, 2, "Removes the 'start' time from a task");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task done ID");
|
||||
table.addCell (row, 2, "Marks the specified task as completed");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task undo ID");
|
||||
table.addCell (row, 2, "Marks the specified done task as pending, provided a report has not yet been run");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task projects");
|
||||
table.addCell (row, 2, "Shows a list of all project names used, and how many tasks are in each");
|
||||
@@ -173,10 +187,6 @@ static void shortUsage (Config& conf)
|
||||
table.addCell (row, 1, "task stats");
|
||||
table.addCell (row, 2, "Shows task database statistics");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task usage");
|
||||
table.addCell (row, 2, "Shows task command usage frequency");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task export");
|
||||
table.addCell (row, 2, "Exports all tasks as a CSV file");
|
||||
@@ -279,6 +289,7 @@ 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.
|
||||
@@ -289,60 +300,37 @@ int main (int argc, char** argv)
|
||||
}
|
||||
|
||||
TDB tdb;
|
||||
tdb.dataDirectory (expandPath (conf.get ("data.location")));
|
||||
gTdb = &tdb;
|
||||
std::string dataLocation = expandPath (conf.get ("data.location"));
|
||||
tdb.dataDirectory (dataLocation);
|
||||
|
||||
// Log commands, if desired.
|
||||
if (conf.get ("command.logging") == "on")
|
||||
tdb.logCommand (argc, argv);
|
||||
// Set up TDB callback.
|
||||
std::string shadowFile = expandPath (conf.get ("shadow.file"));
|
||||
if (shadowFile != "")
|
||||
{
|
||||
if (shadowFile == dataLocation + "/pending.data")
|
||||
throw std::string ("Configuration variable 'shadow.file' is set to "
|
||||
"overwrite your pending tasks. Please change it.");
|
||||
|
||||
// Parse the command line.
|
||||
std::vector <std::string> args;
|
||||
for (int i = 1; i < argc; ++i)
|
||||
args.push_back (argv[i]);
|
||||
std::string command;
|
||||
T task;
|
||||
parse (args, command, task, conf);
|
||||
if (shadowFile == dataLocation + "/completed.data")
|
||||
throw std::string ("Configuration variable 'shadow.file' is set to "
|
||||
"overwrite your completed tasks. Please change it.");
|
||||
|
||||
if (command == "add") handleAdd (tdb, task, conf);
|
||||
else if (command == "projects") handleProjects (tdb, task, conf);
|
||||
else if (command == "tags") handleTags (tdb, task, conf);
|
||||
else if (command == "list") handleList (tdb, task, conf);
|
||||
else if (command == "info") handleInfo (tdb, task, conf);
|
||||
else if (command == "undelete") handleUndelete (tdb, task, conf);
|
||||
else if (command == "long") handleLongList (tdb, task, conf);
|
||||
else if (command == "ls") handleSmallList (tdb, task, conf);
|
||||
else if (command == "colors") handleColor ( conf);
|
||||
else if (command == "completed") handleCompleted (tdb, task, conf);
|
||||
else if (command == "delete") handleDelete (tdb, task, conf);
|
||||
else if (command == "start") handleStart (tdb, task, conf);
|
||||
else if (command == "done") handleDone (tdb, task, conf);
|
||||
else if (command == "export") handleExport (tdb, task, conf);
|
||||
else if (command == "version") handleVersion ( conf);
|
||||
else if (command == "summary") handleReportSummary (tdb, task, conf);
|
||||
else if (command == "next") handleReportNext (tdb, task, conf);
|
||||
else if (command == "history") handleReportHistory (tdb, task, conf);
|
||||
else if (command == "ghistory") handleReportGHistory (tdb, task, conf);
|
||||
else if (command == "calendar") handleReportCalendar (tdb, task, conf);
|
||||
else if (command == "active") handleReportActive (tdb, task, conf);
|
||||
else if (command == "overdue") handleReportOverdue (tdb, task, conf);
|
||||
else if (command == "oldest") handleReportOldest (tdb, task, conf);
|
||||
else if (command == "newest") handleReportNewest (tdb, task, conf);
|
||||
else if (command == "stats") handleReportStats (tdb, task, conf);
|
||||
else if (command == "usage") handleReportUsage (tdb, task, conf);
|
||||
else if (command == "" && task.getId ()) handleModify (tdb, task, conf);
|
||||
else if (command == "help") longUsage (conf);
|
||||
else shortUsage (conf);
|
||||
tdb.onChange (&onChangeCallback);
|
||||
}
|
||||
|
||||
std::cout << runTaskCommand (argc, argv, tdb, conf);
|
||||
}
|
||||
|
||||
catch (std::string& error)
|
||||
{
|
||||
std::cout << error << std::endl;
|
||||
std::cerr << error << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
catch (...)
|
||||
{
|
||||
std::cout << "Unknown error." << std::endl;
|
||||
std::cerr << "Unknown error." << std::endl;
|
||||
return -2;
|
||||
}
|
||||
|
||||
@@ -381,12 +369,18 @@ int getDueState (const std::string& due)
|
||||
if (due.length ())
|
||||
{
|
||||
Date dt (::atoi (due.c_str ()));
|
||||
Date now;
|
||||
|
||||
if (dt < now)
|
||||
// rightNow is the current date + time.
|
||||
Date rightNow;
|
||||
|
||||
// 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)
|
||||
return 2;
|
||||
|
||||
Date nextweek = now + 7 * 86400;
|
||||
Date nextweek = today + 7 * 86400;
|
||||
if (dt < nextweek)
|
||||
return 1;
|
||||
}
|
||||
@@ -534,7 +528,6 @@ Date getNextRecurrence (Date& current, std::string& period)
|
||||
while (! Date::valid (m, d, y))
|
||||
--d;
|
||||
|
||||
// std::cout << "# next " << current.toString () << " + " << period << " = " << m << "/" << d << "/" << y << std::endl;
|
||||
return Date (m, d, y);
|
||||
}
|
||||
|
||||
@@ -553,7 +546,6 @@ Date getNextRecurrence (Date& current, std::string& period)
|
||||
while (! Date::valid (m, d, y))
|
||||
--d;
|
||||
|
||||
// std::cout << "# next " << current.toString () << " + " << period << " = " << m << "/" << d << "/" << y << std::endl;
|
||||
return Date (m, d, y);
|
||||
}
|
||||
|
||||
@@ -569,7 +561,6 @@ Date getNextRecurrence (Date& current, std::string& period)
|
||||
while (! Date::valid (m, d, y))
|
||||
--d;
|
||||
|
||||
// std::cout << "# next " << current.toString () << " + " << period << " = " << m << "/" << d << "/" << y << std::endl;
|
||||
return Date (m, d, y);
|
||||
}
|
||||
|
||||
@@ -588,7 +579,6 @@ Date getNextRecurrence (Date& current, std::string& period)
|
||||
while (! Date::valid (m, d, y))
|
||||
--d;
|
||||
|
||||
// std::cout << "# next " << current.toString () << " + " << period << " = " << m << "/" << d << "/" << y << std::endl;
|
||||
return Date (m, d, y);
|
||||
}
|
||||
|
||||
@@ -604,7 +594,6 @@ Date getNextRecurrence (Date& current, std::string& period)
|
||||
while (! Date::valid (m, d, y))
|
||||
--d;
|
||||
|
||||
// std::cout << "# next " << current.toString () << " + " << period << " = " << m << "/" << d << "/" << y << std::endl;
|
||||
return Date (m, d, y);
|
||||
}
|
||||
|
||||
@@ -620,7 +609,6 @@ Date getNextRecurrence (Date& current, std::string& period)
|
||||
while (! Date::valid (m, d, y))
|
||||
--d;
|
||||
|
||||
// std::cout << "# next " << current.toString () << " + " << period << " = " << m << "/" << d << "/" << y << std::endl;
|
||||
return Date (m, d, y);
|
||||
}
|
||||
|
||||
@@ -629,7 +617,6 @@ Date getNextRecurrence (Date& current, std::string& period)
|
||||
{
|
||||
y += 2;
|
||||
|
||||
// std::cout << "# next " << current.toString () << " + " << period << " = " << m << "/" << d << "/" << y << std::endl;
|
||||
return Date (m, d, y);
|
||||
}
|
||||
|
||||
@@ -647,7 +634,6 @@ void updateRecurrenceMask (
|
||||
T& task)
|
||||
{
|
||||
std::string parent = task.getAttribute ("parent");
|
||||
// std::cout << "# updateRecurrenceMask of " << parent << std::endl;
|
||||
if (parent != "")
|
||||
{
|
||||
std::vector <T>::iterator it;
|
||||
@@ -655,11 +641,8 @@ void updateRecurrenceMask (
|
||||
{
|
||||
if (it->getUUID () == parent)
|
||||
{
|
||||
// std::cout << "# located parent task" << std::endl;
|
||||
unsigned int index = atoi (task.getAttribute ("imask").c_str ());
|
||||
// std::cout << "# child imask=" << index << std::endl;
|
||||
std::string mask = it->getAttribute ("mask");
|
||||
// std::cout << "# parent mask=" << mask << std::endl;
|
||||
if (mask.length () > index)
|
||||
{
|
||||
mask[index] = (task.getStatus () == T::pending) ? '-'
|
||||
@@ -667,15 +650,11 @@ void updateRecurrenceMask (
|
||||
: (task.getStatus () == T::deleted) ? 'X'
|
||||
: '?';
|
||||
|
||||
// std::cout << "# setting parent mask to=" << mask << std::endl;
|
||||
it->setAttribute ("mask", mask);
|
||||
// std::cout << "# tdb.modifyT (parent)" << std::endl;
|
||||
tdb.modifyT (*it);
|
||||
}
|
||||
else
|
||||
{
|
||||
// std::cout << "# mask of insufficient length" << std::endl;
|
||||
// std::cout << "# should never occur" << std::endl;
|
||||
std::string mask;
|
||||
for (unsigned int i = 0; i < index; ++i)
|
||||
mask += "?";
|
||||
@@ -693,3 +672,138 @@ void updateRecurrenceMask (
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Using gTdb and gConf, generate a report.
|
||||
void onChangeCallback ()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (gConf && gTdb)
|
||||
{
|
||||
// Determine if shadow file is enabled.
|
||||
std::string shadowFile = expandPath (gConf->get ("shadow.file"));
|
||||
if (shadowFile != "")
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
throw std::string ("No specified shadow file '") + shadowFile + "'.";
|
||||
|
||||
// Optionally display a notification that the shadow file was updated.
|
||||
if (gConf->get (std::string ("shadow.notify"), false))
|
||||
std::cout << "[Shadow file '" << shadowFile << "' updated]" << std::endl;
|
||||
}
|
||||
else
|
||||
throw std::string ("Internal error (TDB/Config).");
|
||||
}
|
||||
|
||||
catch (std::string& error)
|
||||
{
|
||||
std::cout << error << std::endl;
|
||||
}
|
||||
|
||||
catch (...)
|
||||
{
|
||||
std::cout << "Unknown error." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string runTaskCommand (
|
||||
int argc,
|
||||
char** argv,
|
||||
TDB& tdb,
|
||||
Config& conf,
|
||||
bool gc /* = true */)
|
||||
{
|
||||
std::vector <std::string> args;
|
||||
for (int i = 1; i < argc; ++i)
|
||||
args.push_back (argv[i]);
|
||||
|
||||
return runTaskCommand (args, tdb, conf, gc);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string runTaskCommand (
|
||||
std::vector <std::string>& args,
|
||||
TDB& tdb,
|
||||
Config& conf,
|
||||
bool gc /* = 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 != "")
|
||||
{
|
||||
// Stuff the command line.
|
||||
args.clear ();
|
||||
split (args, defaultCommand, ' ');
|
||||
std::cout << "[task " << defaultCommand << "]" << std::endl;
|
||||
}
|
||||
|
||||
loadCustomReports (conf);
|
||||
|
||||
std::string command;
|
||||
T task;
|
||||
parse (args, command, task, conf);
|
||||
|
||||
std::string out = "";
|
||||
|
||||
if (command == "" && task.getId ()) { handleModify (tdb, task, conf ); }
|
||||
else if (command == "add") { handleAdd (tdb, task, conf ); }
|
||||
else if (command == "done") { handleDone (tdb, task, conf ); }
|
||||
else if (command == "export") { handleExport (tdb, task, conf ); }
|
||||
else if (command == "projects") { out = handleProjects (tdb, task, conf ); }
|
||||
else if (command == "tags") { out = handleTags (tdb, task, conf ); }
|
||||
else if (command == "info") { out = handleInfo (tdb, task, conf ); }
|
||||
else if (command == "undelete") { out = handleUndelete (tdb, task, conf ); }
|
||||
else if (command == "delete") { out = handleDelete (tdb, task, conf ); }
|
||||
else if (command == "start") { out = handleStart (tdb, task, conf ); }
|
||||
else if (command == "stop") { out = handleStop (tdb, task, conf ); }
|
||||
else if (command == "undo") { out = handleUndo (tdb, task, conf ); }
|
||||
else if (command == "stats") { out = handleReportStats (tdb, task, conf ); }
|
||||
else if (command == "list") { if (gc) tdb.gc (); out = handleList (tdb, task, conf ); } // 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 ); }
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
57
src/task.h
57
src/task.h
@@ -55,7 +55,10 @@ for (typeof (c) *foreach_p = & (c); \
|
||||
|
||||
// parse.cpp
|
||||
void parse (std::vector <std::string>&, std::string&, T&, Config&);
|
||||
bool validPriority (const std::string&);
|
||||
bool validDate (std::string&, Config&);
|
||||
void loadCustomReports (Config&);
|
||||
bool isCustomReport (const std::string&);
|
||||
|
||||
// task.cpp
|
||||
void gatherNextTasks (const TDB&, T&, Config&, std::vector <T>&, std::vector <int>&);
|
||||
@@ -65,38 +68,44 @@ void handleRecurrence (TDB&, std::vector <T>&);
|
||||
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);
|
||||
|
||||
// command.cpp
|
||||
void handleAdd (const TDB&, T&, Config&);
|
||||
void handleProjects (TDB&, T&, Config&);
|
||||
void handleTags (TDB&, T&, Config&);
|
||||
void handleUndelete (TDB&, T&, Config&);
|
||||
void handleVersion (Config&);
|
||||
void handleAdd (TDB&, T&, Config&);
|
||||
void handleExport (TDB&, T&, Config&);
|
||||
void handleDelete (TDB&, T&, Config&);
|
||||
void handleStart (TDB&, T&, Config&);
|
||||
void handleDone (TDB&, T&, Config&);
|
||||
void handleModify (TDB&, T&, Config&);
|
||||
void handleColor (Config&);
|
||||
std::string handleProjects (TDB&, T&, Config&);
|
||||
std::string handleTags (TDB&, T&, Config&);
|
||||
std::string handleUndelete (TDB&, T&, Config&);
|
||||
std::string handleVersion (Config&);
|
||||
std::string handleDelete (TDB&, T&, Config&);
|
||||
std::string handleStart (TDB&, T&, Config&);
|
||||
std::string handleStop (TDB&, T&, Config&);
|
||||
std::string handleUndo (TDB&, T&, Config&);
|
||||
std::string handleColor (Config&);
|
||||
|
||||
// report.cpp
|
||||
void filter (std::vector<T>&, T&);
|
||||
void handleList (TDB&, T&, Config&);
|
||||
void handleInfo (TDB&, T&, Config&);
|
||||
void handleLongList (TDB&, T&, Config&);
|
||||
void handleSmallList (TDB&, T&, Config&);
|
||||
void handleCompleted (TDB&, T&, Config&);
|
||||
void handleReportSummary (TDB&, T&, Config&);
|
||||
void handleReportNext (TDB&, T&, Config&);
|
||||
void handleReportHistory (TDB&, T&, Config&);
|
||||
void handleReportGHistory (TDB&, T&, Config&);
|
||||
void handleReportUsage (const TDB&, T&, Config&);
|
||||
void handleReportCalendar (TDB&, T&, Config&);
|
||||
void handleReportActive (TDB&, T&, Config&);
|
||||
void handleReportOverdue (TDB&, T&, Config&);
|
||||
void handleReportStats (TDB&, T&, Config&);
|
||||
void handleReportOldest (TDB&, T&, Config&);
|
||||
void handleReportNewest (TDB&, T&, Config&);
|
||||
std::string handleList (TDB&, T&, Config&);
|
||||
std::string handleInfo (TDB&, T&, Config&);
|
||||
std::string handleLongList (TDB&, T&, Config&);
|
||||
std::string handleSmallList (TDB&, T&, Config&);
|
||||
std::string handleCompleted (TDB&, T&, Config&);
|
||||
std::string handleReportSummary (TDB&, T&, Config&);
|
||||
std::string handleReportNext (TDB&, T&, Config&);
|
||||
std::string handleReportHistory (TDB&, T&, Config&);
|
||||
std::string handleReportGHistory (TDB&, T&, Config&);
|
||||
std::string handleReportCalendar (TDB&, T&, Config&);
|
||||
std::string handleReportActive (TDB&, T&, Config&);
|
||||
std::string handleReportOverdue (TDB&, T&, Config&);
|
||||
std::string handleReportStats (TDB&, T&, Config&);
|
||||
std::string handleReportOldest (TDB&, T&, Config&);
|
||||
std::string handleReportNewest (TDB&, T&, Config&);
|
||||
|
||||
std::string handleCustomReport (TDB&, T&, Config&, const std::string&);
|
||||
|
||||
// util.cpp
|
||||
bool confirm (const std::string&);
|
||||
|
||||
15
src/tests/in
Executable file
15
src/tests/in
Executable file
@@ -0,0 +1,15 @@
|
||||
./task add monday due:monday
|
||||
./task add tuesday due:tuesday
|
||||
./task add wednesday due:wednesday
|
||||
./task add thursday due:thursday
|
||||
./task add friday due:friday
|
||||
./task add saturday due:saturday
|
||||
./task add sunday due:sunday
|
||||
./task add yesterday due:yesterday
|
||||
./task add today due:today
|
||||
./task add tomorrow due:tomorrow
|
||||
./task add eow due:eow
|
||||
./task add eom due:eom
|
||||
./task add eoy due:eoy
|
||||
./task add 21st due:21st
|
||||
|
||||
@@ -1 +1 @@
|
||||
<pkgref spec="1.12" uuid="C71026FD-E252-42CD-89C3-2F6F087AAF17"><config><identifier>com.beckingham.task141.task.pkg</identifier><version>1</version><description/><post-install type="none"/><requireAuthorization/><installFrom>/Users/paul/task.git/binary/task</installFrom><installTo mod="true" relocatable="true">/usr/local/bin</installTo><flags><followSymbolicLinks/></flags><packageStore type="internal"/><mod>parent</mod><mod>locationType</mod><mod>relocatable</mod><mod>installTo.path</mod><mod>installTo</mod></config><contents><file-list>01task-contents.xml</file-list><filter>/CVS$</filter><filter>/\.svn$</filter><filter>/\.cvsignore$</filter><filter>/\.cvspass$</filter><filter>/\.DS_Store$</filter></contents></pkgref>
|
||||
<pkgref spec="1.12" uuid="C71026FD-E252-42CD-89C3-2F6F087AAF17"><config><identifier>com.beckingham.task142.task.pkg</identifier><version/><description></description><post-install type="none"/><requireAuthorization/><installFrom>/Users/paul/task.git/binary/task</installFrom><installTo mod="true" relocatable="true">/usr/local/bin</installTo><flags><followSymbolicLinks/></flags><packageStore type="internal"></packageStore><mod>parent</mod><mod>locationType</mod><mod>relocatable</mod><mod>version</mod><mod>installTo.path</mod><mod>installTo</mod></config><contents><file-list>01task-contents.xml</file-list><filter>/CVS$</filter><filter>/\.svn$</filter><filter>/\.cvsignore$</filter><filter>/\.cvspass$</filter><filter>/\.DS_Store$</filter></contents></pkgref>
|
||||
@@ -1 +1 @@
|
||||
<pkmkdoc spec="1.12"><properties><title>Task 1.4.1</title><build>/Users/paul/task.git/binary/task-1.4.1.pkg</build><organization>com.beckingham</organization><userSees ui="easy"/><min-target os="3"/><domain system="true"/></properties><distribution><versions min-spec="1.000000"/><scripts></scripts></distribution><contents><choice title="task" id="choice0" starts_selected="true" starts_enabled="true" starts_hidden="false"><pkgref id="com.beckingham.task141.task.pkg"/><choice-reqs><requirement id="tosv" operator="ge" value="'10.5.0'" selected="no" enabled="no" hidden="unchanged" startSelected="unchanged" startEnabled="unchanged" startHidden="unchanged"/></choice-reqs></choice></contents><resources bg-scale="none" bg-align="topleft"><locale lang="en"><resource mod="true" type="license">/Users/paul/task.git/binary/COPYING.txt</resource><resource mod="true" type="readme">/Users/paul/task.git/binary/README.txt</resource></locale></resources><flags/><item type="file">01task.xml</item><mod>properties.title</mod><mod>properties.systemDomain</mod><mod>properties.anywhereDomain</mod></pkmkdoc>
|
||||
<pkmkdoc spec="1.12"><properties><title>Task 1.4.2</title><build>/Users/paul/Documents/task-1.4.2.pkg</build><organization>com.beckingham</organization><userSees ui="easy"/><min-target os="3"/><domain anywhere="true" system="true"/></properties><distribution><versions min-spec="1.000000"/><scripts></scripts></distribution><contents><choice title="task" id="choice0" starts_selected="true" starts_enabled="true" starts_hidden="false"><pkgref id="com.beckingham.task142.task.pkg"/><choice-reqs><requirement id="tosv" operator="ge" value="'10.5.0'" selected="no" enabled="no" hidden="unchanged" startSelected="unchanged" startEnabled="unchanged" startHidden="unchanged"/></choice-reqs></choice></contents><resources bg-scale="none" bg-align="topleft"><locale lang="en"><resource mod="true" type="license">/Users/paul/task.git/binary/COPYING.txt</resource><resource mod="true" type="readme">/Users/paul/task.git/binary/README.txt</resource></locale></resources><flags/><item type="file">01task.xml</item><mod>properties.title</mod><mod>properties.anywhereDomain</mod><mod>properties.systemDomain</mod></pkmkdoc>
|
||||
Reference in New Issue
Block a user