Compare commits

...

193 Commits

Author SHA1 Message Date
Paul Beckingham
06062a96eb Documentation Update - version 2009-04-12 23:41:05 -04:00
Paul Beckingham
7431f0cdd3 Bug Fix - use " not ' for annotation quoting
- Annotations were using ' to quote text, sanitizing ' -> " inside
  the text.  It would be better to quote with " and sanitize " -> '
  because ' is more common in the text (e.g. "Doesn't work") than ".
2009-04-12 22:53:20 -04:00
Paul Beckingham
22f0b1d9fb Documentation Update
- Added the global modifier of the substitution command to the
  command line grammar file.
2009-04-12 22:35:26 -04:00
Paul Beckingham
b8187e24ae Enhancement - file import
- Added support for configuration variables that override field
  mapping.
- Updated documentation.
2009-04-12 20:29:37 -04:00
Paul Beckingham
120593887b Code Cleanup - unit test warning
- Cleaned up Perl warning in unit test.
2009-04-12 02:17:12 -04:00
Paul Beckingham
01e5e773eb Enhancement - stats report
- Rearranged sequence of stats report to make more sense, with
  counts first and statistics (derived data) last.
2009-04-12 02:10:05 -04:00
Paul Beckingham
e0fd39db7b Enhancement - substitutions /from/to/g
- Added support for the "g" modifier to the substitution command,
  that replace every occurrence of "from" with "to", in the task
  description and any annotations.
2009-04-12 02:01:08 -04:00
Paul Beckingham
a39261f82d Unit tests - substitution
- Added unit tests to ensure that substitution works on the task
  description and annotations.
2009-04-12 01:03:52 -04:00
Paul Beckingham
a6b45af0a2 Enhancement - annotation substitution
- Annotations are now modifiable using the /from/to/ modification
  command.
2009-04-12 00:56:58 -04:00
Paul Beckingham
daea320564 Bug Fix - annual recurrence due-date creep
- Fixed bug where annual recurring tasks exhibit due-date creep
  (thanks to T. Charles Yun).
2009-04-12 00:05:21 -04:00
Paul Beckingham
1cbec205f1 Bug Fix - concatenation of colons in description
- When a task description contained a colon, the two words preceding
  the colon were concatenated.  For example, "aa bb:cc dd" gets
  concatenated to "aabb:cc dd".
- Added unit to test to prevent regression.
- Updated documentation.
2009-04-11 23:02:48 -04:00
Paul Beckingham
579232b7ea Documentation Update
- Cygwin doesn't support all color combinations, which include bold,
  underline and bright background colors.  Added a troubleshooting
  item that describes this problem, and suggests running "task colors"
  to determine just which colors are supported.
2009-04-11 22:39:37 -04:00
Paul Beckingham
cee8fda236 Documentation Update
- added Federico Hernandez to the AUTHORS file for his contribution of
  Red Hat RPM packages.
- Added RPM download links.
2009-04-11 22:18:12 -04:00
Paul Beckingham
4dda1f0c27 Documentation Update
- Added Ubuntu Jaunty Jackalope 9.04 (beta) to the list of supported
  platforms.
2009-04-05 12:26:11 -04:00
Paul Beckingham
0571412da0 Documentation Update
- Added Ubuntu 9.04 (Jaunty Jackalope) to the list of supported systems
  (thanks to Federico Hernandez).
2009-03-30 19:51:13 -04:00
Paul Beckingham
b4f031e4a7 New report columns
- Added support for tag_indicator column.
- Added support for recurrence_indicator column.
2009-03-30 00:29:28 -04:00
Paul Beckingham
5b1d64960d Documentation Update
- Added faq question/answer.
- Clarified file format upgrade via backup warning.
2009-03-29 23:50:00 -04:00
Paul Beckingham
a5fef2cc6b Autoconf
- Removed double check for ncurses, causing the library to be listed
  twice on the link line.
2009-03-29 22:17:14 -04:00
Paul Beckingham
8ab3c1cc3c Bug Fix
- Fixed bug whereby if no columns labels were specified, it was
  considered a column count mismatch.
- Fixed unit tests to use m/d/Y not M/D/Y dateformat.
2009-03-29 21:27:48 -04:00
Paul Beckingham
2700713c03 Merge branch 'import' into 1.6.0
Conflicts:
	ChangeLog
	html/task.html
2009-03-29 18:51:27 -04:00
Paul Beckingham
567bdd98a4 Code Cleanup
- Removed temporary file import samples
2009-03-29 17:43:21 -04:00
Paul Beckingham
25425614b1 File Import
- Implemented all remaining import functionality.
2009-03-29 17:42:11 -04:00
Paul Beckingham
3b65051e9e Unit Tests - labels
- Added unit tests to verify that custom report labels are properly used.
2009-03-29 15:41:09 -04:00
Paul Beckingham
5f4563af2f File Import
- Implemented import from task 1.4.3, 1.5.0, 1.6.0, plain text,
  todo.sh and task command line files.
- Implemented unit tests to cover the above.
2009-03-29 15:34:35 -04:00
Paul Beckingham
7e2bd166fa Code Cleanup
- Guaranteed the correct Config::get call via cast.  There is some
  doubt as to the correct call being made otherwise.  This is not a
  very likely fix, but does eliminate one possibility.
2009-03-29 11:08:32 -04:00
Paul Beckingham
41b60f88d3 Custom Report Labels
- Added the ability to override the labels of custom reports (thanks
  to T. Charles Yun).
2009-03-27 23:51:20 -04:00
Paul Beckingham
93ec320555 Updated FAQ 2009-03-27 22:32:40 -04:00
Paul Beckingham
c1291dc587 Updated Documentation
- Added description of import process.
2009-03-27 22:02:13 -04:00
Paul Beckingham
57deb83b25 Documentation Update
- Added a faq.html file, although it is not so much a set of frequently
  asked questions, but of repeatedly asked questions.  Questions from
  the mail bag, if they apply to a general audience might be shown
  here.
2009-03-27 21:25:34 -04:00
Paul Beckingham
e4f5d6579c File Import
- Updated documentation.
- Added another recognized format - task command line.
2009-03-26 00:52:51 -04:00
Paul Beckingham
99dc72f26f File Import
- Added format identifier code for task 1.4.3, task 1.5.0, todo.sh
  2.0 and CSV.
- Implemented import for type text.
- Implemented util.cpp:slurp function.
- Gathered sample input files for import testing, and later, unit
  tests.
2009-03-26 00:41:15 -04:00
Paul Beckingham
406e648d58 Code Cleanup
- The new 'echo.command' configuration variable was incorrectly
  flagged as obsolete by report.cpp:handleVersion.
2009-03-25 17:49:22 -04:00
Paul Beckingham
db7b2dd9fe File Import
- Implemented scaffolding for new import command.
2009-03-25 02:05:50 -04:00
Paul Beckingham
c31ec6b6a6 Unit Tests - all file formats
- Added unit tests to verify correct parsing of file formats 1, 2
  and 3.
2009-03-25 01:29:59 -04:00
Paul Beckingham
1a656f0f60 Recurring Tasks - upgrades and bug fixes
- Improved (fixed) logical consistency checks that prevent the
  addition of a recurrence frequency without a due date.
- Improved (fixed) logical consistency checks that prevent the
  addition of an until date with a recurrence frequency.
- When a recurring task is modified, all sibling instances, as well
  as the parent task now get modified.
- When a recurring task is appended, all sibling instances, as well
  as the parent task now get modified.
- Updated documentation.
- It is now possible to upgrade a regular task to a recurring task,
  which is triggered by the "recur" attribute.
2009-03-25 01:08:13 -04:00
Paul Beckingham
5ec0d569a9 Enhancement - annotations
- Added annotated description to the active, overdue and next reports.
2009-03-24 23:15:55 -04:00
Paul Beckingham
3979c3283e Enhancement - annotations
- Added support for "annotate" command to annotate existing tasks.
- Bumped file format to version 3, due to the annotations.
- Added unit tests to verify that annotations work.
- Changed 'description' column everywhere to include annotations.
- Added 'description_only' column to exclude the annotations.
- Fixed bug in Table.cpp that calculated the width of multi-line
  columns by using the cell length, instead of the length of the
  longest individual line.
- Updated documentation with new feature.
- Updated documentation with new column.
- Enhanced t.t unit tests to cover format 43
2009-03-24 01:57:12 -04:00
Paul Beckingham
ca795ea281 Bug Fix - confirmation was broken
- Fixed inverted condition that broke confirmation.
2009-03-23 21:55:02 -04:00
Paul Beckingham
d10e9be500 Bug fix - assumed "yes" value, instead of Bool
- Fixed bug where only a value of "yes" would enable confirmation,
  instead of any Boolean true value.
2009-03-22 23:50:42 -04:00
Paul Beckingham
f790df24c5 Enhancement - added echo of id, description
- Added an echo of the ID and description of the task for the start,
  stop, do, undo, delete and undelete commands.  Thanks to Bruce
  Dillahunty.
- Updated documentation.
- Added "echo.command=no" to delete.t, undo.t because the default
  value is "yes", which breaks tests.
- Fixed syntax errors in utf8.t
- Corrected expected number of tests in recur.t
2009-03-22 23:34:17 -04:00
Paul Beckingham
ca933d7f39 Unit Tests - duration
- Corrected unit tests that were mistakenly using 'week' instead of
  'weekly'.
2009-03-20 20:02:59 -04:00
Paul Beckingham
827bc6204b Unit Tests - autocomplete
- Implemented unit test to verify the functionality of the
  util.cpp:autoComplete function.
2009-03-20 20:01:44 -04:00
Paul Beckingham
4537d5048e Unit Tests - confirmation
- Implemented unit tests to very that "confirmation=yes" works.
- Implemented unit tests to very that \n causes a re-prompt.
- Updated docs with regard to this fix, thanks to Bruce Dillahunty.
2009-03-20 18:12:11 -04:00
Paul Beckingham
74ea5b4ef6 Bug Fix - confirmation not processing newline
- Fixed bug where util.cpp:confirm was eating newlines, and not
  rewriting the prompt.  Consequently, after confirm asked the
  question, and the user hit <Enter>, nothing was displayed but
  the newline.  Now uses std::getline.
2009-03-20 16:56:25 -04:00
Paul Beckingham
cc2220b406 Unit Tests - text
- Added unit tests to verify correct functioning of the text utility
  code.
2009-03-19 20:48:02 -04:00
Paul Beckingham
7389ce617a i18n - utf8 support
- Added more unit tests to verify that utf8 projects and tags are
  supported.
2009-03-19 19:46:41 -04:00
Paul Beckingham
165001acac i18n - unit tests
- Added more utf8.t unit tests.
- Removed text.cpp:extractParagraphs, which is not used.
2009-03-19 19:14:01 -04:00
Paul Beckingham
3d3d788961 Recurring Tasks - new "weekdays" frequency
- Added support for "weekdays" as a recurrence frequency, which skips
  Saturday and Sunday, but is otherwise a daily recurrence.  Thanks
  to Chris Pride.
2009-03-18 23:29:25 -04:00
Paul Beckingham
3c196230dd Autoconf
- Added the "-Wall and -pedantic" compiler flags for the non-debug
  build.  The should have been there anyway.
2009-03-18 22:54:59 -04:00
Paul Beckingham
9a350a7dcd Documentation Update
- Updated docs that referenced 1.4.1, failed to include new 1.5.0
  and 1.6.0 commands.
2009-03-17 23:54:56 -04:00
Paul Beckingham
92579e5531 Unit Test - oldest/newest
- Added unit tests to verify oldest and newest reports both work when
  less than 10 tasks are added, and have the correct sort order.
2009-03-17 23:36:00 -04:00
Paul Beckingham
40a538a769 Unit Tests - utf8.t
- Implemented unit tests (more of a demo) that add a bunch of UTF-8
  encoded tasks, as a starting point to updating task to be aware of
  encodings, Unicode etc.
2009-03-17 22:45:53 -04:00
Paul Beckingham
b6e4bc966f Merge branch 'master' of git@github.com:pbeckingham/task into 1.6.0 2009-03-16 22:27:40 -04:00
Paul Beckingham
03815967d2 Documentation Update - task.html
- Added reference to github to allow direct download, clone, fork etc.
2009-03-16 22:26:27 -04:00
Andy Lester
7049bf19d9 Ignore backup files, too
Signed-off-by: Paul Beckingham <paul@beckingham.net>
2009-03-17 10:19:07 +08:00
Paul Beckingham
c69c3bb090 New Command - append
- New "append" command concatenates additional text onto an existing
  task description.
- Added unit tests to append command.
2009-03-16 08:29:09 -04:00
Paul Beckingham
7238d1f1c9 Began 1.6.0 Development 2009-03-16 08:27:24 -04:00
Paul Beckingham
9f82c55c5b Merge branch '1.5.0'
Conflicts:
	html/task.html
2009-03-15 22:26:50 -04:00
Paul Beckingham
87be68e2e8 Bug Fix
- Shebang in tests/run_all was backwards.
2009-03-15 22:12:18 -04:00
Paul Beckingham
7b1dec0d77 Bug Fix - abbreviation.t
- abbreviation.t contains unit tests that fail to specify an alternate
  rc file (rc:abbrev.rc), and so instead rely on ~/.taskrc.  For a new
  installation, there is no .taskrc, so task offers to create one.
  When done in the context of a unit test, task hangs waiting for input.
2009-03-15 19:15:35 -04:00
Paul Beckingham
f8af5d999a Unit Tests - run_all
- Added script to run all unit tests and capture output.
2009-03-15 17:38:54 -04:00
Paul Beckingham
8efd8620c8 Portability - Ubuntu 8.10
- When creating a new .taskrc file, no newlines were included at EOL.
  This needs a 1.5.1 regression test.
2009-03-15 17:21:54 -04:00
Paul Beckingham
e8a795befb Unit Tests - due, export
- due.t was incorrectly reporting the number of tests it intended to
  run.
- export.t was not updated when the export command was updated to include
  recurrence information.
2009-03-15 17:01:22 -04:00
Paul Beckingham
b5690f00e2 Portabiliy - Fedora 9, Ubuntu 8
- The custom report limit "report.x.limit" was being used to limit the
  rendered rows in the table.  Instead, there should be something like
  min (limit, actual_rows) used, in Table.cpp.
  The symptom was duplicate tasks in a "task oldest" report, when there
  were less than 10 tasks.
2009-03-15 16:39:41 -04:00
Paul Beckingham
65f74da7a4 Portability - Fedora 9
- Using size_t as a result for std::string::find causes a silent error,
  reported only on Ubuntu 8.  size_t is not large enough.  The proper
  result type is std::string::size_type.  This fixes a problem with
  the command "task old" responding with "Ambiguous commane 'old' -
  could be one of oldest, oldest.description, oldest.limit, oldest.sort".
2009-03-15 16:26:20 -04:00
Paul Beckingham
429d0f3071 Portability - Fedora 9
- Compiler pointed out an expression (a || b && c) that clearly needs
  parentheses around (a || b).  Gcc on other OSes don't mention this.
2009-03-15 16:14:16 -04:00
Paul Beckingham
4baf30cf9c Portability - Ubuntu 8
- Changed unsigned int to size_t for std::string::npos comparison.
- Removed validBuiltinCommand function that is not used.
2009-03-15 16:13:02 -04:00
Paul Beckingham
a3882160fa Documentation Update
- Updated docs to reflect the 1.5.0 release date.
2009-03-15 15:12:16 -04:00
Paul Beckingham
cd85a28e98 Unit Tests - due, overdue
- Unit tests to verify that the "overdue" report is properly
  displaying tasks.
- Unit tests to verify that "due" can be defined.
2009-03-15 15:04:52 -04:00
Paul Beckingham
e33a918c24 Bug Fix - summary report
- Fixed bug in summary report where recently completed (and therefore
  not yet in the completed.data file) tasks were not included in the
  report.
2009-03-15 11:37:05 -04:00
Paul Beckingham
df82fade2c Unit Tests - bug.summry, custom.columns, next
- Added unit tests to verify that the next report returns the correct
  tasks.
- Added unit test to verify that unrecognized columns in a custom
  report are flagged.
- Added unit tests to verify that only pending and completed tasks
  are included in the summary report.
2009-03-15 11:31:27 -04:00
Paul Beckingham
2d2bd47075 Bug Fix - summary report included deleted tasks
- Applied patch from Benjamin Tegarden to exclude deleted tasks from
  the summary report.
2009-03-14 13:47:48 -04:00
Paul Beckingham
bdd1b16ba0 Documentation Update
- Updated docs to reflect recent changes.
2009-03-14 13:38:39 -04:00
Paul Beckingham
5383943fa7 Enhanced export command
- Now sanitizes output by replacing ' with " in descriptions.
- Added 'recur' attribute to exported output.
- Removed recurring, deleted and complete tasks from the export.
2009-03-14 13:36:32 -04:00
Paul Beckingham
8ac3978222 Unit Tests - dateformat, shadow
- Improved dateformat.t tests to cover all acceptable date format
  characters.
- Unit tests for shadow file update notification.
- Unit tests for shadow file updates under certain circumstances.
- Unit tests for shadow file no updates under other circumstances.
2009-03-14 12:54:11 -04:00
Paul Beckingham
c9a6d2a750 Improved GC and Shadow File Handling
- Every command now returns an output string, or at least has an
  opportunity to do so.
- TDB::gc is only performed a) when allowed, and b) when the command
  will display line numbers.
- updateShadowFile is only performed when a) shadow updates are allowed,
  and either b) when a command is guaranteed to have modified a task or
  c) when TDB:gc has already made changes.
2009-03-14 12:05:32 -04:00
Paul Beckingham
64cfc26ff3 Enhanced Stats Report
- now reports number of unique tags (given filtering)
- now reports number of unique projects (given filtering)
2009-03-14 12:04:25 -04:00
Paul Beckingham
7c87bbc19a Unit Tests - dateformat
- Unit tests determine whether the dateformat configuration variable
  determines how dates are parsed, and how dates are rendered.
2009-03-14 12:02:33 -04:00
Paul Beckingham
4a524a220e Bug Fix - default command, default unit test
- Task runs the default command when no arguments are provided, but
  when an "rc:..." argument is provided, it does not run the default
  command.
- Implemented unit tests to verify the functioning of default commands,
  default project and default priority.
2009-03-14 00:21:42 -04:00
Paul Beckingham
2216eee678 Help Consistency
- Added note about frequent releases to the shortUsage output, so it
  is now consistent with that of "version".
2009-03-13 13:12:34 -04:00
Paul Beckingham
28c97f181a Grammar
- Changed wording of the help output.
2009-03-13 10:35:17 -04:00
Paul Beckingham
0cfc9c720e Compile Bug - missing <stdlib.h>
- Added stdlib.h to Grid.cpp, thanks to Benjamin Tegardin.
2009-03-13 09:06:23 -04:00
Paul Beckingham
05b5273136 Unit Tests - oldest
- Implemented unit tests to verify that the "oldest" report does
  indeed show the oldest 10 tasks.
- Implemented unit tests to verify that the "newest" report does
  indeed show the newest 10 tasks.
2009-03-12 22:56:22 -04:00
Paul Beckingham
c35a764019 Custom Reports - oldest, newest
- Added support for the "report.X.limit" configuration variable, to
  restrict the number of rows a report generates.
- Added support for Table::render (limit) to limit the number of rows
  that are rendered.
- Removed "oldest" and "newest" report code.
- Added "oldest" and "newest" custom report details to Config.cpp
- Updated various documentation.
2009-03-12 22:34:45 -04:00
Paul Beckingham
8c95e82a63 Unit Tests - start/stop/acive
- Added unit tests to test the start and stop commands via the active
  report.
2009-03-10 23:06:02 -04:00
Paul Beckingham
79d644c257 Unit Tests - custom
- Added unit tests to verify correct functioning of custom report
  filters.
2009-03-10 22:30:15 -04:00
Paul Beckingham
2d07b08260 Custom Reports - usage
- Added defined custom reports to the usage text.  This includes the
  new "report.X.description" configuration variable.
2009-03-10 22:21:23 -04:00
Paul Beckingham
1f45e47e36 Bug Fix - history/ghistory triggered only by add
- Fixed bug whereby if a new month rolls around, and no task is added,
  no row of data is shown in the history or ghistory reports, even
  though tasks may have been completed or deleted ni the new month.
2009-03-10 16:37:35 -04:00
Paul Beckingham
dac1942cad Bug Fix - calendar
- Task now displays as many calendars will fit across the window,
  unless a lower value is specified in the "monthsperline" configuration
  variable.
- Task now obeys the "color" configuration variable when determining
  whether to add a legend to the calendar output.
2009-03-10 16:12:59 -04:00
Paul Beckingham
6d8cb5181f Bug Fix - unit test tdb.t
- Fixed two failing unit tests in tdb.t.cpp, which were both due to
  incorrect test logic, rather than a TDB bug.
2009-03-10 15:40:48 -04:00
Paul Beckingham
d174bb1143 Bug Workaround - locking
- Added support for the "locking" configuration variable that disables
  file locking.  This can be helpful to folks who use task on Solaris,
  and store their task data files on an NFS mount.
2009-03-10 15:21:29 -04:00
Paul Beckingham
dc946e175e Unit Tests - completed, delete
- Added unit tests to verify that the completed.data file is not
  created until the first report is run after the task is marked
  as done.
- Added unit tests to verify that delete/undelete work as expected.
2009-03-10 14:32:32 -04:00
Paul Beckingham
9f278b1ffc Unit Tests - export
- Added unit tests to export tasks and compare.
2009-03-10 00:22:23 -04:00
Paul Beckingham
6fade84535 Unit Tests - color.*, abbreviation
- Added unit tests for all auto coloration configuration settings.
- Tweaked colorization rule precedence to allow color.due to override
  the built-in coloration of due tasks.
2009-03-10 00:08:40 -04:00
Paul Beckingham
0ff33d1c16 Version command changes
- Added color.recurring to the list of valid config values.
- Added message to "version" command hinting that folks should look
  periodically for updated versions of task.  Task does not "call home"
  and check for updates (and never will), and so it is easy to not
  realize that there may be newer versions of task with bug fixes and
  new features.
2009-03-09 23:02:01 -04:00
Paul Beckingham
1999e38ba5 Colorization - color.recurring
- Added support for "color.recurring" configuration variable to
  colorize recurring tasks.
- Updated docs.
2009-03-09 22:12:49 -04:00
Paul Beckingham
17de9fec9f New Column - recur
- Added new column 'recur' for use in custom reports.
- Implemented Table::ascendingPeriod, Table::descendingPeriod allowing
  sorting on the recur column.
- Added unit tests to both use the new column and test the sorting.
- Code cleanup.
2009-03-09 22:01:08 -04:00
Paul Beckingham
751094cffb Documentation Update
- Added recent bug fix details.
2009-03-09 03:09:43 -04:00
Paul Beckingham
012e47267f Bug Fix - concatenated description on modify
- When a task was modified, the new description was concatenated
  without spaces.
2009-03-09 03:06:41 -04:00
Paul Beckingham
bd5e91c31f Merge branch '1.5.0' of git@github.com:pbeckingham/task into 1.5.0 2009-03-09 02:54:10 -04:00
Paul Beckingham
9e7844796b Updated Documentation
- Added 'beta' download section to main web page.
2009-03-09 02:53:44 -04:00
Paul Beckingham
209f7ffb00 Updated Documentation
- Added new platforms to NEWS file.
2009-03-09 02:52:36 -04:00
Paul Beckingham
28e997691f Unit Tests - repair
- Added auto right trim to all table rows, which is a much more
  efficient way of doing what Table::optimize was doing.
- Table::optimize is now a nop.
2009-03-08 22:56:47 -04:00
Paul Beckingham
3f418c6fdc Performance
- Made Table::optimize a public method.
- Table::optimize called only from handleReportGHistory, where it's
  needed.
- Retaining benchmark.txt, to allow further improvements.
2009-03-08 21:29:55 -04:00
Paul Beckingham
0362b41f3b Performance
- Added Timer class to display high resolution timing information.
- Found terrible bug in Table::optimize that was taking up 99.7%,
  on average, of the Table::rendering time, including sorting.  This
  fix naturally causes a 187-fold speedup of rendering.
- Changed report.cpp in handleCustomReport to only load pending tasks,
  instead of all pending tasks.  Subtle, but important difference.
2009-03-08 20:49:33 -04:00
Paul Beckingham
4fa4c5f532 Unit Tests - t.benchmark.t
- Added benchmark to measure time taken to parse 1,000,000 T records.
2009-03-08 17:59:27 -04:00
Paul Beckingham
3088e1ebe1 Unit Tests - abbreviation, filter, benchmark
- Added tests for attribute abbreviation.
- Added tests for filter permutation testing.
- Added benchmark for ongoing performance measurement.
- Mentioned test suite in docs.  Why not?
2009-03-07 02:06:13 -05:00
Paul Beckingham
6a7c66aa05 Unit Tests - color.disable color.pri config.obsolete
- Added unit tests to cover automatic colorization by priority.
- Added unit tests to cover automatic disabling of color when !isatty.
- Added unit tests to cover display of unsupported configuration
  variable in the 'version' report.
- Added support the '_forcecolor' configuration variable to allow the
  possibility of unit tests that test color support, yet redirect
  output to a file.  This configuration variable will not be
  documented.
2009-03-07 00:14:58 -05:00
Paul Beckingham
3b1d396e0a Acknowledgement
- Michael Greb acknowledged for his help in reporting several bugs in
  sufficient detail, and narrowing down the cause.
2009-03-06 21:59:25 -05:00
Paul Beckingham
463c968cac Unit Tests - undo.t
- Added unit tests for the undo command, which verify that a task may
  only be undone if a TDB::gc has not occurred.
2009-03-06 00:39:28 -05:00
Paul Beckingham
41b8b207d4 Documentation Update
- Added examples to the grammar file.
- Added recent change to ChangeLog, html/task.html.
2009-03-05 10:13:10 -05:00
Paul Beckingham
9535121c1e Performance
- Removed the unnecessary sort in the 'completed' report.  The tasks
  are already sorted.
2009-03-05 10:08:25 -05:00
Paul Beckingham
9988ecec5e Portability
- Modified util.cpp to allow clean compilation on Solaris.
2009-03-04 09:37:00 -05:00
Paul Beckingham
d573599a7e Unit Tests - subproject
- Implemented unit test to verify that the project and subproject
  filtering is working properly.
2009-03-04 00:04:09 -05:00
Paul Beckingham
d831ab335a Report Column Header
- Added "Number" to the ghistory graph title.
2009-03-03 23:13:31 -05:00
Paul Beckingham
d7a9d06360 Unit Tests - add, bug_hang, bug_period, bug_sort, nag, tag
- Implemented unit tests to verify tag manipulation
- Implemented unit tests to verify nag functionality
- Implemented unit tests to verify bug fix for hang on shadow write
- Implemented unit tests to verify bug fix for unsupported recurrence periods
- Implemented unit tests to verify bug fix for hang on sort
- Corrected typo in add.t
2009-03-03 21:19:07 -05:00
Paul Beckingham
d69d658531 Unit Tests - tag
- Added unit tests to test the +tag and -tag task modification
  feature.
2009-03-03 17:15:40 -05:00
Paul Beckingham
5c89c0f1be Documentation Update
- Modified ChangeLog and task.html to reflect new bug fixes.
2009-03-03 00:53:32 -05:00
Paul Beckingham
964d04322c Bug Fix - nag
- Implemented new nag algorithm, and debugged why it then broke.
2009-03-03 00:46:02 -05:00
Paul Beckingham
8157c729d6 Unit Tests - bug_sort
- Added a unit test to cover the bug whereby certain combinations
  of adding tasks causes Table::sort to loop indefinitely.
2009-03-03 00:08:06 -05:00
Paul Beckingham
a1b7516cf8 Sort Algorithm Fix
- The sort algorithm (Combsort11) was broken because it didn't
  consider all the possible variations of present/missing, same/
  different combinations of data, when performing a compare.  This
  led to an unstable sort, which is an infinite loop in Combsort11.
2009-03-02 23:49:13 -05:00
Paul Beckingham
1e70400143 Shadow File Rewrite
- No longer writes shadow files based on TDB onChange trigger.
- Addressed bug whereby adding a recurring task trigger a shadow
  file rewrite, which in turn performs trigger another rewrite...
2009-03-02 23:47:41 -05:00
Paul Beckingham
6e956b45ad Code Cleanup
- Fixed typo in unit test
2009-03-02 00:44:28 -05:00
Paul Beckingham
59a014d866 Unit Tests - nag
- Added unit tests to exercise the nag option.
2009-03-01 23:52:28 -05:00
Paul Beckingham
76c9d3565c Documentation Update
- Added paragraph tags.  Don't know why, but the rendering was odd.
2009-02-24 22:27:51 -05:00
Paul Beckingham
8c484a333d Documentation Update
- Added folks to AUTHORS file.
- Added Fedora Core 10, Ubuntu 8.10 Intrepid Ibex to compatibility
  list.
2009-02-23 22:59:17 -05:00
Paul Beckingham
0605161236 Updated OS Compatibility List
- Fedora Core 10
- Ubuntu 8.10 Intrepid Ibex
2009-02-23 10:38:01 -05:00
Paul Beckingham
f9272773ac Credit
- Added Carlos Yoder to AUTHORS, for his contribution.
- Added Russell Friesenhahn to AUTHORS, for his contribution.
2009-02-21 17:24:07 -05:00
Paul Beckingham
e2fca47a27 Typo
- Added missing "http://" to "www.samurize.com", at the suggestion
  of Carlos Yoder.
2009-02-20 21:08:39 -05:00
Paul Beckingham
92ba36bdec Unit Tests - add, delete, info, ///
- Began set of high-level integration tests, in Perl.
2009-02-16 23:12:04 -05:00
Paul Beckingham
72efddc066 Sample .taskrc - update
- Added default config variables for new reports.
- Removed README.1.5.0.
- Removed messages configure.ac
2009-02-16 21:35:26 -05:00
Paul Beckingham
bcf512e529 Nag Rewrite
- Now uses a better escalating scale of "importance".
2009-02-16 21:09:00 -05:00
Paul Beckingham
6d551357ff Packaging
- Began modification of script.txt in preparation for next movie!
- Added README.1.5.0 warning to configure.ac.  Do you think people
  will see it?  And then read the file?  I may need to provide an
  automated solution.
2009-02-15 23:44:58 -05:00
Paul Beckingham
0219ed4fe3 Packaging
- Added README.1.5.0 detailing the new custom report configuration
  variables that must be added.
- Added README.1.5.0 to the distribution.
- Added new custom.html documentation.
- Added warning to task.html about the README.1.5.0 changes.
2009-02-15 23:26:15 -05:00
Paul Beckingham
cc7c1819ce Sample .taskrc - update
- Added recent .taskrc file changes to the default file that is created
  when task is run the first time.
2009-02-15 22:45:50 -05:00
Paul Beckingham
1a4469d388 Error handling
- Validates specified columns in custom reports against list of good
  column names.
- Validates list of sort columns in custom reports against list of
  specified column names.
- Minor fix to grammar file.
2009-02-15 22:33:18 -05:00
Paul Beckingham
4e63d93005 Documentation Update
- Added commit ids to ChangeLog
- Added tags to respective commit ids
2009-02-15 16:54:59 -05:00
Paul Beckingham
481a0aa1eb Custom Reports - old reports removed 2009-02-15 15:13:24 -05:00
Paul Beckingham
6764a6a7ec Custom Reports - basic implementation
- Custom reports can be defined and run.
- Custom columns included.
- Custom filter applied.
- Custom sorting applied.
2009-02-15 14:54:54 -05:00
Paul Beckingham
dae268a836 Merge branch '1.5.0' of git@github.com:pbeckingham/task into 1.5.0 2009-02-14 23:18:05 -05:00
Paul Beckingham
096a4b9bdb Bug Fix - split
- Fixed bug in split functions, which was causing empty strings to be
  split into a single element list consisting of one empty string.
  The symptom was that all tasks without tags appeared to have one
  zero-length tag and the task was colored according to color.tagged.
2009-02-14 23:17:35 -05:00
Paul Beckingham
e65a45ce17 Bug Fix
- Fixed bug in split functions, which was causing empty strings to be
  split into a single element list consisting of one empty string.
  The symptom was that all tasks without tags appeared to have one
  zero-length tag and the task was colored according to color.tagged.
2009-02-14 23:13:31 -05:00
Paul Beckingham
01b3cb190c Configuration Variable - due
- Added support for the "due" configuration variable that defines
  how many days into the future when a task is considered due.
2009-02-14 20:19:47 -05:00
Paul Beckingham
6faf1e44f5 Bug Fix - lower case priorities
- Changed a call to isupper to islower.  This was preventing the
  internal modification to upper case.
- Updated ChangeLog accordingly.
2009-02-14 20:04:34 -05:00
Paul Beckingham
2307dcab8a Copyright Update
- bumped the year, on the source copyright notices.
2009-02-14 17:50:38 -05:00
Paul Beckingham
eba05513f7 Unit Tests
- Converted unit tests to use a UnitTest object, with more methods and
  and exit summary.
- Removed "fail" tests in tdb.t.cpp, because it artificially reduces
  the number of passing tests - the comments in the code suffice.
2009-02-14 17:05:50 -05:00
Paul Beckingham
2f7060ce56 Unit Tests
- Fixed long-broken unit tests that were expecting wrong values.
2009-01-31 12:08:03 -05:00
Paul Beckingham
c28c698bbf Cleanup
- Converted grammar.bnf to the EBNF used by Parser.
2009-01-28 12:09:24 -05:00
Paul Beckingham
b55eaf8f16 Cleanup
- renamed grammar.txt to grammar.bnf
2009-01-28 11:51:29 -05:00
Paul Beckingham
3d4beaf41f - Enhanced split algorithm to be non-destrutive, and therefore faster
- Added autoconf testing to detect Solaris
- Added Solaris-specific flock implementation
2008-12-14 15:18:33 -05:00
Paul Beckingham
50ccb67185 - Added builtin command detection
- Now allows override of due/overdue coloration
2008-12-14 11:09:15 -05:00
Paul Beckingham
14d3abacf4 - Beginning to fill out processing of the generalized custom report. 2008-11-19 00:33:43 -05:00
Paul Beckingham
857f813a24 - Added the 1.4.3 debian package from Richard Querin. 2008-11-11 08:54:55 -05:00
Paul Beckingham
8639e92606 - Updated release date for 1.4.3. 2008-11-11 08:53:59 -05:00
Paul Beckingham
5498986e15 - Fixed typo. 2008-11-11 00:27:14 -05:00
Paul Beckingham
eb827603c3 - Final tidying up of 1.4.3 loose ends. 2008-11-11 00:10:14 -05:00
Paul Beckingham
6e1dbfb16e - Now handles the configuration variable recognition of the
new custom report variables.
2008-11-10 09:53:49 -05:00
Paul Beckingham
748300631a - Now parses the command line and can distinguish regular commands, as well as
custom reports.
2008-11-09 22:46:12 -05:00
Paul Beckingham
6d5309527c - Enabled "configure --enable-debug" to suppress optimization, therefore
allowing debugging without the debugger showing the unoptimized source
  while stepping through optimized code.
2008-11-09 01:42:30 -05:00
Paul Beckingham
aafcba436e - Clarified old statements in ChangeLog.
- Removed now obsolete ideas.txt file.
2008-11-09 00:17:45 -05:00
Paul Beckingham
28ceeac796 - Beginnings of the "task list pri:!H" inverse filtering capability.
Doesn't work, and is commented out for now.  Need a better approach
  because of the priority attribute validation of "!H" failing, and the
  Unix shell interpreting "!", thus requiring an escape, which makes the
  command ("task list pri:\!H") ugly.
2008-11-08 23:48:19 -05:00
Paul Beckingham
ecdfb31553 - "task version" command now reports unrecognized configuration variables,
which may be spelling mistakes or deprecated variables.
2008-11-08 23:32:29 -05:00
Paul Beckingham
8d920f9dc4 - Updated documentation to reflect removal of the "showage" configuration variable. 2008-11-08 22:45:27 -05:00
Paul Beckingham
5f85550664 - Removed support for the "showage" configuration variable. 2008-11-08 22:43:40 -05:00
Paul Beckingham
b548342acc - Modified docs to include "shadow.notify". 2008-11-02 23:21:41 -05:00
Paul Beckingham
ee961daef6 Merge branch 'master' into 1.5.0
Conflicts:
	ChangeLog
	NEWS
	configure.ac
	html/task.html
	src/task.cpp
	src/task.h
2008-11-02 22:29:38 -05:00
Paul Beckingham
ce42ae9622 Merge branch '1.4.3' of git@github.com:pbeckingham/task into 1.4.3
Conflicts:
	ChangeLog
	html/task.html
	src/task.cpp
2008-11-02 21:50:55 -05:00
Paul Beckingham
47ffc0babc - Deleted old test file. 2008-11-02 21:43:10 -05:00
Paul Beckingham
612a183776 - Major documentation update
- New filter page
- New shadow file page
2008-11-02 21:23:34 -05:00
Paul Beckingham
396d85cd53 - Removed "usage" command. 2008-11-01 16:48:28 -04:00
Paul Beckingham
038f432752 - ChangeLog update 2008-11-01 16:38:55 -04:00
Paul Beckingham
ef886dff53 Merge branch '1.4.3' 2008-11-01 16:32:08 -04:00
Paul Beckingham
2cae1df42f - Merged 1.4.3 to master 2008-11-01 16:31:30 -04:00
Paul Beckingham
82c0fea708 - Remove debugging code. 2008-11-01 16:14:15 -04:00
Paul Beckingham
d6b30466c1 - "task ghistory" now displays a differently aligned graph, allowing
easier comparison by month of tasks added versus completed and deleted.
2008-11-01 15:44:25 -04:00
Paul Beckingham
b0e18de1b6 - Fixed bug where the onChangeCallback was being called twice for "task list" after "task do xx". 2008-10-25 02:09:31 -04:00
Paul Beckingham
b7e889339d - Added support for shadow.notify to indicate when the shadow file is updated
- Fixed description validation bug that allowed \n, \r and \f in a description, then rendered the pending.data file unparseable
2008-10-25 02:03:21 -04:00
Paul Beckingham
2a5736b876 - TDB::gc now only calls overwritePending when something changed.
- Removed TDB::gc calls from report.cpp.
- Made TDB::gc calls from task.cpp whenever necessary.
- Disabled TDB::gc calls when running a report for the sake of the shadow file.
- Shadow file overwrite now implemented using ostream, instead of cout.rdbuf trickery, for the well-being of cygwin.
2008-10-24 23:15:52 -04:00
Paul Beckingham
b176591261 - Converted reports/command to return strings 2008-10-23 00:44:21 -04:00
Paul Beckingham
c44baf913d Merge branch '1.5.0' of git@github.com:pbeckingham/task into 1.5.0
Conflicts:
	html/task.html
	src/task.cpp
2008-10-19 11:50:14 -04:00
Paul Beckingham
0987171280 - Added support for "task stop <id>" command, that removes the start time from a task.
- Updated documentation accordingly.
2008-10-19 11:47:03 -04:00
Paul Beckingham
47c02965e9 Merge branch '1.4.3' into 1.5.0
Conflicts:
	NEWS
	TUTORIAL
	configure.ac
	html/advanced.html
	html/task.html
	html/versions.html
	src/task.cpp
2008-10-18 18:19:47 -04:00
Paul Beckingham
ce561a6c43 - Instrumented version for shadow file testing. 2008-10-15 10:16:46 -04:00
Paul Beckingham
b4b389c27e - Added checks to ensure that a shadow.file value doesn't collide with either the pending.data or completed.data files. 2008-10-09 21:24:12 -04:00
Paul Beckingham
437c85da39 Merge branch '1.4.3' into 1.5.0
Conflicts:
	NEWS
	TUTORIAL
	configure.ac
	html/advanced.html
	html/task.html
	html/versions.html
	src/task.cpp
2008-10-09 21:03:29 -04:00
Paul Beckingham
62115ea988 - Removed version number from HTML titles.
- New filter.html doc.
- New shadow.html doc.
2008-10-09 18:43:13 -04:00
Paul Beckingham
3ed1269753 - Added support for plain text shadow files. 2008-10-09 18:24:35 -04:00
Paul Beckingham
a5ec1e4b27 - Added support for shadow file, shadow file command
- Added support for TDB::onChange callback
2008-10-09 17:19:57 -04:00
Paul Beckingham
a815492111 - New links page referring to task links on the web. 2008-09-26 22:30:42 -04:00
Paul Beckingham
f3aa88cf83 Merge branch 'master' into 1.5.0 2008-09-26 22:27:03 -04:00
Paul Beckingham
f26a9c67be - Built 1.4.2 and packaged it as a Mac OS X Leopard Intel binary
- Modified incorrect Debian packages in versions.html
- Added Debian and Mac packages to task.html
2008-09-26 22:25:38 -04:00
Paul Beckingham
d837a25be7 - Removed support for the "command.logging" configuration variable and
the "task usage" command.
2008-09-20 20:46:20 -04:00
Paul Beckingham
78fae5195b - Converted 1.4.2 references to 1.5.0. 2008-09-20 20:24:58 -04:00
136 changed files with 11822 additions and 2518 deletions

5
.gitignore vendored
View File

@@ -1,4 +1,3 @@
Makefile.in
aclocal.m4
autom4te.cache
auto.h*
@@ -6,8 +5,10 @@ config.h.in
config.status
src/.deps
src/Makefile
src/task
*/task
stamp-h1
Makefile
configure
config.log
www.xls
*~

14
AUTHORS
View File

@@ -5,11 +5,16 @@ Contributing Authors:
Damian Glenny
Andy Lester
H. İbrahim Güngör
Stefan Dorn
Michael Greb
Benjamin Tegarden
Chris Pride
Richard Querin
Federico Hernandez
With thanks to:
Eugene Kramer
Srijith K
Richard Querin
Bruce Israel
Thomas Engel
Nishiishii
@@ -17,4 +22,11 @@ With thanks to:
Stas Antons
Vincent Fleuranceau
T. Charles Yun
ArchiMark
Carlos Yoder
Russell Friesenhahn
Paolo Marsi
Eric Farris
Bruce Dillahunty
Askme Too

360
ChangeLog
View File

@@ -1,137 +1,229 @@
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.2 (9/18/2008)
1.6.0 (4/12/2009)
+ Added support for new "append" command that adds more description text to
an existing task.
+ Added support for the "weekdays" recurrence, which means a task can recur
five times a week, and not on weekends (thanks to Chris Pride).
+ UTF8 text is now supported in task project names, tags and descriptions.
+ Fixed bug that caused the y/n confirmation on task deletion to ignore the
Enter key and fail to re-prompt (thanks to Bruce Dillahunty).
+ When the "echo.command" configuration variable is set to "yes", it causes
commands that modify tasks to display which task was affected (thanks to
Bruce Dillahunty).
+ A task can now be annotated with the command "task <id> annotate ...", and
a timestamped annotation will appear in reports.
+ A 'description_only' column is now available for use in custom reports,
and it excludes annotations.
+ A task can now be upgraded to a recurring task by adding a recurrence
frequency, a due date, and an optional until date.
+ When a recurring task is modified, all other instances of the recurring
task are also modified.
+ Custom reports now support user-specified column labels (thanks to T.
Charles Yun).
+ Task can now import tasks from a variety of data formats, including task
export files from versions 1.4.3 and earlier, versions 1.5.0 and later,
todo.sh 2.x, CSV, plain text and task command line. See online docs for
full details.
+ Export was including 'id' in the column header even though it was not
included in the data.
+ The task file format has changed slightly. Please back up your task
data files before upgrading to 1.6.0.
+ Added new column 'recurrence_indicator' that displays an 'R' if the task
is a recurring task. This column can be added to any custom report.
+ Added new column 'tag_indicator' that displays a '+' if the task
has any tags. This column can be added to any custom report.
+ Fixed bug where sometimes a task description was concatenated oddly if
there was a colon somewhere in the description.
+ Fixed bug that caused recurring annual tasks to exhibit a creeping due
date, because of an assumption of 365 days per year, which failed to
consider leap years (thanks to T. Charles Yun).
+ Annotations can now be modified with the substitution commands /from/to/.
+ Substitutions can now be made global with /from/to/g and all occurrences
of "from" will be replaced with "to".
------ old releases ------------------------------
1.5.0 (3/15/2009)
+ 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.
+ Allow lower case priorities, and automatically upper case them.
+ Added support for "due" configuration variable which defines the number
of days in the future when a task is considered due.
+ Added support for custom reports, comprised of a set of column names and
sort order, with optional filtering in the configuration file. This
means user-defined reports can be written, and the reports currently
in the configuration file can be renamed. Several of task's built in
reports have been converted to user-defined reports.
+ New online documentation for custom reports.
+ New algorithm for determining when the "nag" message is displayed.
+ Fixed bug where task hangs with a certain combination of recurring tasks
and shadow files.
+ Fixed bug with the task sort algorithm, which led to an unstable sequence
when there were only a handful of tasks.
+ Performance enhanced by eliminating unnecessary sorting.
+ Task now has a large (and growing) test suite and bug regression tests
to help ensure higher quality releases.
+ Fixed bug that caused performance hit during table rendering.
+ Fixed bug that concatenated a modified description without spaces.
+ Added new column 'recur' that displays the recurrence period of any
recurring tasks. This column can be added to any custom report.
+ Added support for "color.recurring" configuration variable which
specifies the color of recurring tasks.
+ Added support for "locking" configuration variable that controls whether
file locking is used.
+ Task export feature now includes recurrence information, removes nested
quotes, and limits output to pending tasks.
+ Task no longer includes deleted tasks in the summary report (thanks to
Benjamin Tegarden).
+ Fixed bug that prevented the summary report from properly reporting
recently completed tasks.
1.4.3 (11/1/2008) 8639e9260646c8c9224e0fc47e5d2443b46eecfc
+ Fixed misleading task count at bottom on "info" report.
+ Added support for a shadow file that contains a plain text task report,
with the "shadow.file" and "shadow.command" configuration variables.
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) e7304e86ce9bb80978c7055fd2a9e999619a6fb8
+ "task undo" can now retract a "task done" command, provided no reports
have been run (and therefore TDB::gc run)
have been run (and therefore TDB::gc run).
+ Task now correctly sorts on entire strings, instead of just the first
character (thanks to Andy Lester)
character (thanks to Andy Lester).
+ Task now uses dashes (-----) to column underlines when color is disabled
(thanks to Vincent Fleuranceau)
(thanks to Vincent Fleuranceau).
+ Task now allows mixed case attribute names (pri:, PRI:, Pri: ...) and
commands (add, ADD, Add ...) (thanks to Vincent Fleuranceau)
commands (add, ADD, Add ...) (thanks to Vincent Fleuranceau).
+ Task now supports a default project and priority for new tasks, via
the new "default.project" and "default.priority" configuration variables
(thanks to Vincent Fleuranceau)
+ Task supports improved word-wrapping to the terminal width
(thanks to Vincent Fleuranceau).
+ Task supports improved word-wrapping to the terminal width.
+ Task now supports "default.command" configuration variable (for example
it could contain "list due:tomorrow") that is the command that is run
whenever task is invoked with no arguments.
+ Task supports modifying the existing description of a task, with the
following syntax: task <id> "new description ...".
+ Bug: Now properly supports relative dates in filters (task list due:eom,
task list due:tomorrow, task list due:23rd ...)
task list due:tomorrow, task list due:23rd ...).
+ Bug: Source now properly includes <string.h> in order to build clean
using gcc 4.3 (thanks to H. İbrahim Güngör)
using gcc 4.3 (thanks to H. İbrahim Güngör).
------ old releases ------------------------------
1.4.1 (7/18/2008) e080c3168c6064628ab85b21bd859d9875a3a9a7
+ Bug: Descriptions can not be altered with "task 123 New description".
+ Tweak: For "task calendar" month names are now centered over the month.
+ Removed TUTORIAL file contents in favor of online version.
+ Provided Mac .pkg binary.
1.4.1 (7/18/2008)
+ Bug: Descriptions can not be altered with "task 123 New description"
+ Tweak: For "task calendar" month names are now centered over the month
+ Removed TUTORIAL file contents in favor of online version
+ Provided Mac .pkg binary
1.4.0 (7/10/2008)
+ New recurring tasks feature
1.4.0 (7/10/2008) 60b7d15a1d22e064acf0974c5d7eabbb57dd8071
+ New recurring tasks feature.
+ "task undelete" can now undelete erroneously deleted tasks, provided no
reports have been run (and therefore TDB::gc run)
+ Added averages to the "task history" report
+ Added ability to override ~/.taskrc with rc:<file>
+ Added bar chart history report "task ghistory"
+ Added task filtering on all reports
+ Automatically shuts off color, curses when output is not a tty
+ Supports relative due: dates (tomorrow, wednesday, 23rd, eom ...)
+ Supports the ~ character in .taskrc data.location
reports have been run (and therefore TDB::gc run).
+ Added averages to the "task history" report.
+ Added ability to override ~/.taskrc with rc:<file>.
+ Added bar chart history report "task ghistory".
+ Added task filtering on all reports.
+ Automatically shuts off color, curses when output is not a tty.
+ Supports relative due: dates (tomorrow, wednesday, 23rd, eom ...).
+ Supports the ~ character in .taskrc data.location.
+ Allows colons on the description, provided what is to the left of the colon
is not a standard attribute name
+ Bug: Fixed where Esc[0m sequences were being emitted for no good reason
+ Bug: Fixed underlined table headers when color is turned off
+ Bug: Adding a blank priority resulted in an assigned garbage value
+ Bug: Fixed parsing of date "07/08/2008" when using dateformat "m/d/Y"
is not a standard attribute name.
+ Bug: Fixed where Esc[0m sequences were being emitted for no good reason.
+ Bug: Fixed underlined table headers when color is turned off.
+ Bug: Adding a blank priority resulted in an assigned garbage value.
+ Bug: Fixed parsing of date "07/08/2008" when using dateformat "m/d/Y".
1.3.1 (6/21/2008)
1.3.1 (6/21/2008) 3a6de7d9402f2609a773a73b16eff97b14a32869
+ New configuration variable, "defaultwidth" that determines the width
of tables when ncurses support is not available
of tables when ncurses support is not available.
+ Bug: "showage" configuration variable should apply to all reports, not
just the ones based on "list"
just the ones based on "list".
+ Bug: Fixed segmentation faults on Ubuntu when the "dateformat"
configuration variables was missing. This was a code bug, and should
have affected more platforms
have affected more platforms.
+ Bug: Task now will recreate a missing ~/.taskrc file, OR a missing
~/.task directory
~/.task directory.
1.3.0 (6/18/2008)
1.3.0 (6/18/2008) 6673e408a223af98c38779c20b08524042c0edfa
+ "task calendar" now displays multiple months per line, adjustable by the
"monthsperline" configuration variable. Feature added by Damian Glenny
+ "task export" can now filter tasks like the reports
+ Factored out code to filter tasks
"monthsperline" configuration variable. Feature added by Damian Glenny.
+ "task export" can now filter tasks like the reports.
+ Factored out code to filter tasks.
+ Displays shorter message when a command is entered incorrectly, and the
full usage for "task help"
+ "task oldest" shows the oldest tasks
+ "task newest" shows the newest tasks
full usage for "task help".
+ "task oldest" shows the oldest tasks.
+ "task newest" shows the newest tasks.
+ Bug: Segmentation fault when no "dateformat" configuration variable
specified
specified.
+ Bug: Fixed bug whereby if you have more than one task with a due date, 7
days gets added to the entry date of task 2..n
+ Bug: Fixed bug whereby "1 wks" was being improperly pluralized
days gets added to the entry date of task 2..n.
+ Bug: Fixed bug whereby "1 wks" was being improperly pluralized.
1.2.0 (6/13/2008)
1.2.0 (6/13/2008) c393d47cdfe7e197a31e94f4bb764474fa05ad8d
+ Bug: "dateformat" configuration variable used to display dates, but
not parse them
not parse them.
+ "task list x" now performs a caseless comparison between "x" and the
description
+ Task sub projects supported
description.
+ Task sub projects supported.
+ "showage" confguration determines whether "Age" column appears on the
"list" and "next" reports
+ Improved TUTORIAL
"list" and "next" reports.
+ Improved TUTORIAL.
1.1.0 (6/7/2008)
1.1.0 (6/7/2008) 73286e86628725b346db2a25fbcd4bd68efb9b3a
+ "blanklines" configuration to stop displaying unnecessary white
space and thus work better on small-screen devices
+ "dateformat" configuration now determines how dates are formatted
+ Better formatting of "task tags" output
+ http://www.beckingham.net/task.html home page set up
+ Added tags to the "task long" report
space and thus work better on small-screen devices.
+ "dateformat" configuration now determines how dates are formatted.
+ Better formatting of "task tags" output.
+ http://www.beckingham.net/task.html home page set up.
+ Added tags to the "task long" report.
1.0.1 (6/4/2008)
1.0.1 (6/4/2008) d216d401217027d93581808fc8944ab7d6b85fb0
+ Bug: UUID generator not properly terminating string.
+ Bug: srandom/srand not called prior to UUID generation.
1.0.0 (6/3/2008)
+ New movie made, uploaded
+ Bug: assertion fails on mobile for t v
+ Bug: configure.ac does not properly determine ncurses availability
+ Bug: Cannot seem to use the percent character in a task description
+ Bug: New installation "task stats" reports newest task 12/31/1969
+ Bug: New installation task projects displays header but no data - should short-circuit
+ Bug: incorrect color specification in sample .taskrc file
+ Bug: when run without arguments, task dumps core on Solaris 10
+ "task calendar" now reports all months with due pending tasks
+ Added rules for colorization by tag, project and keyword
+ Added legend to "task calendar"
1.0.0 (6/3/2008) f3de5c07118c597091a05c7d7fe8bdeae95474c1
+ New movie made, uploaded.
+ Bug: assertion fails on mobile for t v.
+ Bug: configure.ac does not properly determine ncurses availability.
+ Bug: Cannot seem to use the percent character in a task description.
+ Bug: New installation "task stats" reports newest task 12/31/1969.
+ Bug: New installation task projects displays header but no data - should short-circuit.
+ Bug: incorrect color specification in sample .taskrc file.
+ Bug: when run without arguments, task dumps core on Solaris 10.
+ "task calendar" now reports all months with due pending tasks.
+ Added rules for colorization by tag, project and keyword.
+ Added legend to "task calendar".
0.9.9 (5/27/2008)
0.9.9 (5/27/2008) 2ecf50032226c91b406f247417a063dc17c8e324
+ Autoconf/automake behaving properly.
+ Clean build on OS X 10.5.
+ Clean build on Ubuntu 8.0.
+ Clean build on Fedora Core 8.
+ Clean build on Fedora Core 9.
0.9.8 (5/25/2008)
0.9.8 (5/25/2008) 18fd59a1edb20e5c68d086a97fae5fa9f6bb348a
+ Added "task color" command.
+ Removed unnecessary files.
+ Completed documentation.
0.9.7 (5/24/2008)
+ Migrated old compiler flags into Makefile.am
+ Added ncurses endwin function check to configure.ac
0.9.7 (5/24/2008) 25dc4150947a3e612c8118838d04b3bbe68441f7
+ Migrated old compiler flags into Makefile.am.
+ Added ncurses endwin function check to configure.ac.
+ Set up structure for AUTHORS file.
+ Set up NEWS file, with pleas for feedback.
+ Added welcome message to README.
@@ -142,35 +234,35 @@ represents a feature release, and the Z represents a patch.
+ Removed unnecessary SAMPLE_taskrc, and assorted references.
+ Cleaned up ChangeLog.
+ Minor mods to standard docs.
+ Bumped version to 0.9.7
+ Changed some autoconf details
+ Corrected comment in T.cpp
+ Bumped version to 0.9.7.
+ Changed some autoconf details.
+ Corrected comment in T.cpp.
+ Made unit tests compile and run again.
+ Removed tests from distibution.
0.9.6 (5/13/208)
+ Corrected wrong include file in Table.cpp
+ Corrected wrong include file in Table.cpp.
+ Replaced color management code.
+ Improved color rules code.
0.9.5 (5/12/2008)
+ Replaced Table storage with Grid.
+ Added Grid.cpp to configure.ac
+ Added Makefile to src/.gitignore
+ Added Grid.cpp to configure.ac.
+ Added Makefile to src/.gitignore.
+ Makefile should not be part of the repository.
+ Added Grid.cpp
+ Added Grid::Cell::operator==
+ Added Grid.cpp.
+ Added Grid::Cell::operator==.
+ ChangeLog file begun.
+ Bumped version to 0.9.5 for next release.
0.9.4 (4/26/2008)
+ Integrated new Grid object into build - not yet integrated into Table.
+ More .gitignore tweaks.
+ Added .gitignore
+ Added .gitignore.
+ Added more missing files.
+ Added all source code.
+ Generic OSS files added.
+ Initial commit.
+ Initial commit on Github.
0.9.3 (4/6/2008)
+ Added "task completed" command.
@@ -181,74 +273,76 @@ 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.
0.9.0 (3/23/2008)
+ flat source directory
+ autoconf complete
+ "task next"
+ "task stats"
+ "task export"
+ Rules-based colorization
+ flat source directory.
+ autoconf complete.
+ "task next".
+ "task stats".
+ "task export".
+ Rules-based colorization.
0.8.1 (1/28/2008) - 0.8.16 (3/13/2008)
+ autoconf conversion (many builds)
+ autoconf conversion (many builds).
0.8.0 Polish (1/25/2008)
+ Code cleanup, reorganization
+ "task overdue"
+ Add "age" column to list and long
+ Use 'conf' for build, version tracking
+ Add "/from/to/" description editing
+ Code cleanup, reorganization.
+ "task overdue".
+ Add "age" column to list and long.
+ Use 'conf' for build, version tracking.
+ Add "/from/to/" description editing.
0.7.0 Multi-user, File handling, atomicity (1/8/2008)
+ Clean, publishable API reimplementation
+ File locking
+ retain deleted tasks
+ "task info ID" report showing all metadata
+ File format v2
+ Clean, publishable API reimplementation.
+ File locking.
+ retain deleted tasks.
+ "task info ID" report showing all metadata.
+ File format v2, including UUID.
[Development hiatus while planning for T, TDB API, new features and the future
of the project. Seeded to two testers for feedback, suggestions.]
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"
+ "task summary"
+ "task calendar"
+ due support
+ Table sorting
+ "task history".
+ "task summary".
+ "task calendar".
+ due support.
+ Table sorting.
0.5.0 Multi-user support (12/10/2006)
+ Command logging
+ "task usage" report
+ Command logging.
+ "task usage" report.
0.4.0 Destructive / modification commands (12/3/2006)
+ "task delete" complete
+ "task id ..." complete
+ "task list ..." synonym for "task find ..."
+ "task delete" complete.
+ "task id ..." complete.
+ "task list ..." synonym for "task find ...".
0.3.0 Work in progress support (12/3/2006)
+ "task start" complete
+ "task done" complete
+ completed.data support
+ "task start" complete.
+ "task done" complete.
+ completed.data support.
0.2.0 Neutral commands (12/2/2006)
+ "task find" complete
+ "task projects" complete
+ "task tags" complete
+ "task find" complete.
+ "task projects" complete.
+ "task tags" complete.
0.1.0 Constructive commands (12/1/2006)
+ "task add" complete
+ completed.data support
+ ~/.taskrc support
+ "task add" complete.
+ completed.data support.
+ ~/.taskrc support.
0.0.1 Basic infrastructure (11/29/2006)
+ Command line parsing
+ API layer
+ Usage
+ Command line parsing.
+ API layer.
+ Usage.
------ start -----------------------------------

View File

@@ -1,3 +1,3 @@
SUBDIRS = src
EXTRA_DIST = TUTORIAL DEVELOPERS
EXTRA_DIST = DEVELOPERS

595
Makefile.in Normal file
View File

@@ -0,0 +1,595 @@
# Makefile.in generated by automake 1.10 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
subdir = .
DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in $(srcdir)/auto.h.in \
$(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \
depcomp install-sh missing
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
configure.lineno config.status.lineno
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = auto.h
CONFIG_CLEAN_FILES =
SOURCES =
DIST_SOURCES =
RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
html-recursive info-recursive install-data-recursive \
install-dvi-recursive install-exec-recursive \
install-html-recursive install-info-recursive \
install-pdf-recursive install-ps-recursive install-recursive \
installcheck-recursive installdirs-recursive pdf-recursive \
ps-recursive uninstall-recursive
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
ETAGS = etags
CTAGS = ctags
DIST_SUBDIRS = $(SUBDIRS)
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
am__remove_distdir = \
{ test ! -d $(distdir) \
|| { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
&& rm -fr $(distdir); }; }
DIST_ARCHIVES = $(distdir).tar.gz
GZIP_ENV = --best
distuninstallcheck_listfiles = find . -type f -print
distcleancheck_listfiles = find . -type f -print
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build_alias = @build_alias@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host_alias = @host_alias@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
SUBDIRS = src
EXTRA_DIST = DEVELOPERS
all: auto.h
$(MAKE) $(AM_MAKEFLAGS) all-recursive
.SUFFIXES:
am--refresh:
@:
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
echo ' cd $(srcdir) && $(AUTOMAKE) --gnu '; \
cd $(srcdir) && $(AUTOMAKE) --gnu \
&& exit 0; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
echo ' $(SHELL) ./config.status'; \
$(SHELL) ./config.status;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
$(SHELL) ./config.status --recheck
$(top_srcdir)/configure: $(am__configure_deps)
cd $(srcdir) && $(AUTOCONF)
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
auto.h: stamp-h1
@if test ! -f $@; then \
rm -f stamp-h1; \
$(MAKE) $(AM_MAKEFLAGS) stamp-h1; \
else :; fi
stamp-h1: $(srcdir)/auto.h.in $(top_builddir)/config.status
@rm -f stamp-h1
cd $(top_builddir) && $(SHELL) ./config.status auto.h
$(srcdir)/auto.h.in: $(am__configure_deps)
cd $(top_srcdir) && $(AUTOHEADER)
rm -f stamp-h1
touch $@
distclean-hdr:
-rm -f auto.h stamp-h1
# This directory's subdirectories are mostly independent; you can cd
# into them and run `make' without going through this Makefile.
# To change the values of `make' variables: instead of editing Makefiles,
# (1) if the variable is set in `config.status', edit `config.status'
# (which will cause the Makefiles to be regenerated when you run `make');
# (2) otherwise, pass the desired values on the `make' command line.
$(RECURSIVE_TARGETS):
@failcom='exit 1'; \
for f in x $$MAKEFLAGS; do \
case $$f in \
*=* | --[!k]*);; \
*k*) failcom='fail=yes';; \
esac; \
done; \
dot_seen=no; \
target=`echo $@ | sed s/-recursive//`; \
list='$(SUBDIRS)'; for subdir in $$list; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
dot_seen=yes; \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| eval $$failcom; \
done; \
if test "$$dot_seen" = "no"; then \
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
fi; test -z "$$fail"
$(RECURSIVE_CLEAN_TARGETS):
@failcom='exit 1'; \
for f in x $$MAKEFLAGS; do \
case $$f in \
*=* | --[!k]*);; \
*k*) failcom='fail=yes';; \
esac; \
done; \
dot_seen=no; \
case "$@" in \
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
*) list='$(SUBDIRS)' ;; \
esac; \
rev=''; for subdir in $$list; do \
if test "$$subdir" = "."; then :; else \
rev="$$subdir $$rev"; \
fi; \
done; \
rev="$$rev ."; \
target=`echo $@ | sed s/-recursive//`; \
for subdir in $$rev; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| eval $$failcom; \
done && test -z "$$fail"
tags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
done
ctags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
done
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: tags-recursive $(HEADERS) $(SOURCES) auto.h.in $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
include_option=--etags-include; \
empty_fix=.; \
else \
include_option=--include; \
empty_fix=; \
fi; \
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test ! -f $$subdir/TAGS || \
tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
fi; \
done; \
list='$(SOURCES) $(HEADERS) auto.h.in $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique; \
fi
ctags: CTAGS
CTAGS: ctags-recursive $(HEADERS) $(SOURCES) auto.h.in $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) auto.h.in $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
$(am__remove_distdir)
test -d $(distdir) || mkdir $(distdir)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test -d "$(distdir)/$$subdir" \
|| $(MKDIR_P) "$(distdir)/$$subdir" \
|| exit 1; \
distdir=`$(am__cd) $(distdir) && pwd`; \
top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
(cd $$subdir && \
$(MAKE) $(AM_MAKEFLAGS) \
top_distdir="$$top_distdir" \
distdir="$$distdir/$$subdir" \
am__remove_distdir=: \
am__skip_length_check=: \
distdir) \
|| exit 1; \
fi; \
done
-find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
! -type d ! -perm -400 -exec chmod a+r {} \; -o \
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|| chmod -R a+r $(distdir)
dist-gzip: distdir
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
$(am__remove_distdir)
dist-bzip2: distdir
tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
$(am__remove_distdir)
dist-tarZ: distdir
tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
$(am__remove_distdir)
dist-shar: distdir
shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
$(am__remove_distdir)
dist-zip: distdir
-rm -f $(distdir).zip
zip -rq $(distdir).zip $(distdir)
$(am__remove_distdir)
dist dist-all: distdir
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
$(am__remove_distdir)
# This target untars the dist file and tries a VPATH configuration. Then
# it guarantees that the distribution is self-contained by making another
# tarfile.
distcheck: dist
case '$(DIST_ARCHIVES)' in \
*.tar.gz*) \
GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
*.tar.bz2*) \
bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
*.tar.Z*) \
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
*.shar.gz*) \
GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
*.zip*) \
unzip $(distdir).zip ;;\
esac
chmod -R a-w $(distdir); chmod a+w $(distdir)
mkdir $(distdir)/_build
mkdir $(distdir)/_inst
chmod a-w $(distdir)
dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
&& dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
&& cd $(distdir)/_build \
&& ../configure --srcdir=.. --prefix="$$dc_install_base" \
$(DISTCHECK_CONFIGURE_FLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
&& $(MAKE) $(AM_MAKEFLAGS) check \
&& $(MAKE) $(AM_MAKEFLAGS) install \
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
&& $(MAKE) $(AM_MAKEFLAGS) uninstall \
&& $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
distuninstallcheck \
&& chmod -R a-w "$$dc_install_base" \
&& ({ \
(cd ../.. && umask 077 && mkdir "$$dc_destdir") \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
} || { rm -rf "$$dc_destdir"; exit 1; }) \
&& rm -rf "$$dc_destdir" \
&& $(MAKE) $(AM_MAKEFLAGS) dist \
&& rm -rf $(DIST_ARCHIVES) \
&& $(MAKE) $(AM_MAKEFLAGS) distcleancheck
$(am__remove_distdir)
@(echo "$(distdir) archives ready for distribution: "; \
list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
distuninstallcheck:
@cd $(distuninstallcheck_dir) \
&& test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
|| { echo "ERROR: files left after uninstall:" ; \
if test -n "$(DESTDIR)"; then \
echo " (check DESTDIR support)"; \
fi ; \
$(distuninstallcheck_listfiles) ; \
exit 1; } >&2
distcleancheck: distclean
@if test '$(srcdir)' = . ; then \
echo "ERROR: distcleancheck can only run from a VPATH build" ; \
exit 1 ; \
fi
@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
|| { echo "ERROR: files left in build directory after distclean:" ; \
$(distcleancheck_listfiles) ; \
exit 1; } >&2
check-am: all-am
check: check-recursive
all-am: Makefile auto.h
installdirs: installdirs-recursive
installdirs-am:
install: install-recursive
install-exec: install-exec-recursive
install-data: install-data-recursive
uninstall: uninstall-recursive
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-recursive
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-recursive
clean-am: clean-generic mostlyclean-am
distclean: distclean-recursive
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -f Makefile
distclean-am: clean-am distclean-generic distclean-hdr distclean-tags
dvi: dvi-recursive
dvi-am:
html: html-recursive
info: info-recursive
info-am:
install-data-am:
install-dvi: install-dvi-recursive
install-exec-am:
install-html: install-html-recursive
install-info: install-info-recursive
install-man:
install-pdf: install-pdf-recursive
install-ps: install-ps-recursive
installcheck-am:
maintainer-clean: maintainer-clean-recursive
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf $(top_srcdir)/autom4te.cache
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-recursive
mostlyclean-am: mostlyclean-generic
pdf: pdf-recursive
pdf-am:
ps: ps-recursive
ps-am:
uninstall-am:
.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \
install-strip
.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
all all-am am--refresh check check-am clean clean-generic \
ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \
dist-shar dist-tarZ dist-zip distcheck distclean \
distclean-generic distclean-hdr distclean-tags distcleancheck \
distdir distuninstallcheck dvi dvi-am html html-am info \
info-am install install-am install-data install-data-am \
install-dvi install-dvi-am install-exec install-exec-am \
install-html install-html-am install-info install-info-am \
install-man install-pdf install-pdf-am install-ps \
install-ps-am install-strip installcheck installcheck-am \
installdirs installdirs-am maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
pdf-am ps ps-am tags tags-recursive uninstall uninstall-am
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

7
NEWS
View File

@@ -1,4 +1,4 @@
Welcome to Task 1.4.0.
Welcome to Task 1.6.0.
Task has been built and tested on the following configurations:
@@ -6,8 +6,11 @@ Task has been built and tested on the following configurations:
- OS X 10.5 Leopard
- Fedora Core 8
- Fedora Core 9
- Fedora Core 10
- Ubuntu 7 Feisty Fawn
- Ubuntu 8 Hardy Heron
- Ubuntu 9 Feisty Fawn
- Ubuntu 8.10 Intrepid Ibex
- Ubuntu 9.04 Jaunty Jackalope (beta)
- Solaris 10
- Cygwin 1.5.25-14

View File

@@ -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

View File

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

281
binary/COPYING.txt Normal file
View 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
View 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.

View File

@@ -2,7 +2,36 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.61)
AC_INIT(task, 1.4.2, bugs@beckingham.net)
AC_INIT(task, 1.6.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 "$enable_debug" = "yes"; then
CXXFLAGS="$CFLAGS -Wall -pedantic -ggdb3 -DDEBUG"
AC_MSG_RESULT(yes)
else
CXXFLAGS="$CFLAGS -Wall -pedantic -O3"
AC_MSG_RESULT(no)
fi
# Check for OS.
OS=`uname|sed -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'`
if test "$OS" = "sunos"; then
AC_MSG_NOTICE([OS Solaris detected])
AC_DEFINE([SOLARIS], [], [Compiling on Solaris])
else
AC_MSG_NOTICE([OS Non-Solaris detected])
AC_DEFINE([LINUX], [], [Compiling on Non-Solaris])
fi
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([src/task.cpp])
AC_CONFIG_HEADER([auto.h])
@@ -12,14 +41,15 @@ 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)
# 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
@@ -33,10 +63,11 @@ AC_STRUCT_TM
AC_FUNC_MKTIME
AC_FUNC_SELECT_ARGTYPES
AC_CHECK_FUNCS([select])
AC_CHECK_FUNC(flock, [AC_DEFINE([HAVE_FLOCK], [1], [Found flock])])
#AC_CHECK_FUNC(flock, [AC_DEFINE([HAVE_FLOCK], [1], [Found flock])])
AC_CHECK_FUNC(uuid_unparse_lower, [AC_DEFINE([HAVE_UUID], [1], [Found uuid_unparse_lower])])
AC_CHECK_FUNC(random, [AC_DEFINE([HAVE_RANDOM], [1], [Found random])])
AC_CHECK_FUNC(srandom, [AC_DEFINE([HAVE_SRANDOM], [1], [Found srandom])])
AC_CONFIG_FILES([Makefile src/Makefile])
AC_OUTPUT

40
grammar.bnf Normal file
View File

@@ -0,0 +1,40 @@
# This is a full BNF grammar for the task command line. It is intended that a
# future release of task will incorporate a complete lexer/parser implementing
# this grammar, which will allow for more sophisticated command lines, for
# example:
#
# task delete 1 2 4-7
# task add pri:H pro:X -- pro pri 1 ///
#
command ::= simple_command
| filter_command filter?
| id_command
| "export" file
| <id>
| <id> <substitution> ;
simple_command ::= "version" | "help" | "projects" | "tags" | "next" | "stats"
| "color" ;
filter_command ::= "summary" | "history" | "calendar" | "active" | "overdue"
| "oldest" | "newest" | "add" | "list" | "long" | "ls"
| "completed" ;
id_command ::= "delete" | "undelete" | "info" | "start" | "end" | "done"
| "undo" ;
filter ::= filter_part+ ;
filter_part ::= tag_add | tag_remove | attribute | word ;
tag_add ::= "+" word ;
tag_remove ::= "-" word ;
attribute ::= word ":" word ;
word ::=
file ::=
id ::= digit+ ;
digit ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
substitution ::= "/" word+ "/" word* "/" "g"? ;

View File

@@ -1,69 +0,0 @@
This is a full BNF grammar for the task command line. It is intended that a
future release of task will incorporate a complete lexer/parser implementing
this grammar.
command:
VERSION
| HELP
| PROJECTS
| TAGS
| SUMMARY
| HISTORY
| NEXT
| CALENDAR
| ACTIVE
| OVERDUE
| STATS
| USAGE
| OLDEST
| NEWEST
| EXPORT <file>
| COLOR
| DELETE <id>
| UNDELETE <id>
| INFO <id>
| START <id>
| DONE <id>
| ADD [<tags>] [<attrs>] [<desc>]
| LIST [<tags>] [<attrs>] [<desc>]
| LONG [<tags>] [<attrs>] [<desc>]
| LS [<tags>] [<attrs>] [<desc>]
| COMPLETED [<tags>] [<attrs>] [<desc>]
| <id> [<tags>] [<attrs>] [<desc>]
| <id> <substitution>
id:
\d+
| \d{8}-\d{4}-\d{4}-\d{12}
tags:
+<tag>
| -<tag>
tag:
\w+
attrs:
<attr>
| <attr> <attrs>
attr:
<name>:<value>
name:
\w+
value:
.+
substitution:
/ <pattern> / <pattern> /
pattern:
.+
file:
?

View File

@@ -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">
@@ -79,7 +80,7 @@ No matches</code></pre>
<br />
<div class="content">
<p>
Copyright 2006-2008, P. Beckingham. All rights reserved.
Copyright 2006-2009, P. Beckingham. All rights reserved.
</p>
</div>

View File

@@ -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

View File

@@ -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">
@@ -96,6 +97,30 @@ Car 2 2 wks 25% XXXXXXXXX</code></pre>
indicating that percentage.
</p>
<strong>% task &lt;id&gt; append ...</strong>
<p>
Appends the additional description to an existing task.
</p>
<strong>% task annotate &lt;id&gt; additional note...</strong>
<p>
Allows an annotation to be attached to an existing task. Each
annotation has a time stamp, and when displayed, the annotations
are shown under the task description. For example:
</p>
<pre><code>% task add Go to the supermarket
% task annotate 1 need milk
% task ls
ID Project Pri Due Active Age Description
1 Go to the supermarket
3/23/2009 need milk</code></pre>
<p>
The date of the annotation uses the "dateformat" configuration
variable.
</p>
<strong>% task delete &lt;id&gt;</strong>
<p>
There are two ways of getting rid of tasks - mark them as done, or
@@ -119,6 +144,13 @@ Car 2 2 wks 25% XXXXXXXXX</code></pre>
This is how a task is marked as done.
</p>
<strong>% task undo &lt;id&gt;</strong>
<p>
If a task was recently marked as done, and no report has been run, it
may be possible to cancel the completed status of the task as though
"task done ..." was never run.
</p>
<strong>% task list ...</strong>
<p>
The list report will show the active status, and age of the task in
@@ -157,6 +189,11 @@ ID Project Pri Due Active Age Description
"task start ..." command was run, as shown above.
</p>
<strong>% task stop &lt;id&gt;</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
@@ -252,7 +289,7 @@ ID Project Pri Description
set via the "newest" configuration variable.
</p>
<strong>% task /from/to/</strong>
<strong>% task &lt;id&gt; /from/to/</strong>
<p>
If a task has been entered with a typo, it can be easily corrected
by this command. For example:
@@ -272,7 +309,20 @@ ID Project Pri Description
...</code></pre>
<p>
This command makes single corrections to a task description.
This command makes a single correction to the first occurrence of
"from" in a task description.
</p>
<p>
If a task is annotated, the annotation can also be modified using
this command.
</p>
<strong>% task &lt;id&gt; /from/to/g</strong>
<p>
The "g" modifier to the substitution command causes every occurrence
of "from" to be replaced with "to", in both the description and any
annotations.
</p>
<strong>% task tags</strong>
@@ -313,19 +363,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
@@ -405,7 +442,7 @@ on_white on_bright_white</code></pre>
<br />
<div class="content">
<p>
Copyright 2006-2008, P. Beckingham. All rights reserved.
Copyright 2006-2009, P. Beckingham. All rights reserved.
</p>
</div>

View File

@@ -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">
@@ -76,7 +77,7 @@ on_white on_bright_white</code></pre>
<br />
<div class="content">
<p>
Copyright 2006-2008, P. Beckingham. All rights reserved.
Copyright 2006-2009, P. Beckingham. All rights reserved.
</p>
</div>

View File

@@ -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,19 +52,19 @@
/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
confirmation before deleting a task.
</dd>
<dt>echo.command</dt>
<dd>
May be "yes" or "no", and causes task to display the ID and
description of any task when you run the start, stop, do, undo,
delete and undelete commands. The default value is "yes".
</dd>
<dt>nag</dt>
<dd>
This may be a string of text, or blank. It is used as a prompt
@@ -177,28 +178,12 @@
</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
renders across the screen. Defaults to 1.
</dd>
<dt>oldest</dt>
<dd>
Determines how many tasks the "task oldest" command displays.
Defaults to 10.
</dd>
<dt>newest</dt>
<dd>
Determines how many tasks the "task newest" command displays.
Defaults to 10.
renders across the screen. Defaults to however many will
fit. If more months that will fit are specified, task will
only show as many that will fit.
</dd>
<dt>defaultwidth</dt>
@@ -207,6 +192,14 @@
Defaults to 80.
</dd>
<dt>due</dt>
<dd>
This is the number of days into the future that define when a
task is considered due, and is colored accordingly.
Defaults to 7.
</dd>
<dt>color</dt>
<dd>
May be "on" or "off". Determines whether task uses color.
@@ -222,7 +215,8 @@
color.pri.L<br />
color.pri.none<br />
color.active<br />
color.tagged
color.tagged<br />
color.recurring
</dt>
<dd>
These are the coloration rules. They correspond to a particular
@@ -286,13 +280,104 @@ ID Project Pri Description
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>
<dt>locking</dt>
<dd>
<p>
Determines whether task uses file locking when accessing the pending.data
and completed.data files. Default to "on". Solaris users who store
the task data files on an NFS mount may need to set locking to "off".
</p>
<p>
Note that setting this value to "off" is dangerous. It means that
another program may write to the task.pending file when task is
attempting to do the same.
</p>
</dd>
<dt>import.synonym.id</dt>
<dt>import.synonym.uuid</dt>
<dt>import.synonym.status</dt>
<dt>import.synonym.tags</dt>
<dt>import.synonym.entry</dt>
<dt>import.synonym.start</dt>
<dt>import.synonym.due</dt>
<dt>import.synonym.recur</dt>
<dt>import.synonym.end</dt>
<dt>import.synonym.project</dt>
<dt>import.synonym.priority</dt>
<dt>import.synonym.fg</dt>
<dt>import.synonym.bg</dt>
<dt>import.synonym.description</dt>
<dd>
If any of these configuration variables are found, they influence
data import by specifying a single additional field name synonym.
If a data import is failing because certain column names are not
being recognized, then this is how the field mapping can be
controlled.
</dd>
<p>
Note that the command:
</p>
<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 />
<br />
<div class="content">
<p>
Copyright 2006-2008, P. Beckingham. All rights reserved.
Copyright 2006-2009, P. Beckingham. All rights reserved.
</p>
</div>

179
html/custom.html Normal file
View File

@@ -0,0 +1,179 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Custom Reports</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="task.css" type="text/css" />
</head>
<body>
<div id="container">
<table>
<tr>
<td>
<div id="toolbar">
<a href="task.html">Home</a>
<a href="setup.html">Setup</a>
<a href="30second.html">30-second Tutorial</a>
<a href="simple.html">Simple</a>
<a href="advanced.html">Advanced</a>
<a href="shell.html">Shell</a>
<a href="config.html">Configuration</a>
<a href="color.html">Colors</a>
<a href="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">Custom Reports</h2>
<div class="content">
<p>
Task allows you to customize reports, to a limited degree.
The "list", "long", "ls", "oldest" and "newest" reports are
all now custom reports, whereas in previous releases of task
they were not mutable. This means they can be modified,
renamed, or deleted.
</p>
<p>
More importantly, you can define your own. Here are the
three necessary items in the .taskrc file that define a new
report:
</p>
<code><pre>report.mine.description=Just the essentials
report.mine.columns=id,project,priority,description
report.mine.sort=priority-,project+</pre></code>
<p>
This defines a report, called "mine", that has four columns:
id, project, priority and description. It will be sorted on
two columns: by descending priority then ascending project.
The description that shows up in the task command usage page
is "Just the essentials". Because this report is called
"mine", it can be run with the command:
</p>
<code><pre>% task mine</pre></code>
<p>
An optional filter can also be specified like this:
</p>
<code><pre>report.mine.filter=priority:H +bug</pre></code>
<p>
This adds a filter so that only tasks with priority "H" and
with the "bug" tag are included in the report. This filter
definition is optional.
</p>
<p>
An optional limit can also be specified, which limits the
number of tasks shown in the report. If a limit is not
specified, then the number of tasks is not limited.
</p>
<code><pre>report.mine.limit=10</pre></code>
<p>
Here is a list of all the possible columns that may be included
in a report:
</p>
<p>
It is also possible to override the default columns names, if
the following line is added to your .taskrc file:
</p>
<pre><code>report.mine.labels=ID,Project,Priority,Description of task</code></pre>
<p>
Note that there must be the same number of labels as there are
columns to label, and they must appear in the same sequence.
</p>
<ul>
<li>id
<li>uuid
<li>project
<li>priority
<li>entry
<li>start
<li>due
<li>age
<li>active
<li>tags
<li>recur
<li>description_only
<li>description
<li>tag_indicator
<li>recurrence_indicator
</ul>
<p>
Custom reports will show up in the task command line usage.
</p>
</div>
<br />
<br />
<div class="content">
<p>
Copyright 2006-2009, P. Beckingham. All rights reserved.
</p>
</div>
</div>
</td>
<td align="right" valign="top" width="200px">
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<script type="text/javascript"><!--
google_ad_client = "pub-9709799404235424";
/* Task Main */
google_ad_slot = "8660617875";
google_ad_width = 120;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</td>
</tr>
</table>
</div>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
var pageTracker = _gat._getTracker("UA-4737637-1");
pageTracker._initData();
pageTracker._trackPageview();
</script>
</body>
</html>

View File

@@ -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">
@@ -109,7 +110,7 @@
<br />
<div class="content">
<p>
Copyright 2006-2008, P. Beckingham. All rights reserved.
Copyright 2006-2009, P. Beckingham. All rights reserved.
</p>
</div>

175
html/faq.html Normal file
View File

@@ -0,0 +1,175 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Frequently Asked Questions</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="task.css" type="text/css" />
</head>
<body>
<div id="container">
<table>
<tr>
<td>
<div id="toolbar">
<a href="task.html">Home</a>
<a href="setup.html">Setup</a>
<a href="30second.html">30-second Tutorial</a>
<a href="simple.html">Simple</a>
<a href="advanced.html">Advanced</a>
<a href="shell.html">Shell</a>
<a href="config.html">Configuration</a>
<a href="color.html">Colors</a>
<a href="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">Frequently Asked Questions</h2>
<div class="content">
<p>
(Actually, that's a misnomer. These are really Repeatedly Asked
Questions.)
</p>
<p>
<b>
Q: When I redirect the output of task to a file, I lose all
the colors. How do I fix this?
</b>
<br />
A: Task knows (or thinks it knows) when the output is not going
directly to a terminal, and strips out all the color control
characters. Prevent this with the following entry in your
.taskrc file:
<pre><code>_forcecolor=on</code></pre>
</p>
<hr>
<p>
<b>
Q: How do I backup my task data files? Where are they?
</b>
<br />
A: Task writes all pending tasks to the file ~/.task/pending.data
and all completed and deleted tasks to ~/.task/completed.data.
They are text files, so they can just be copied to another
location for safekeeping. Don't forget there is also the
~/.taskrc file that contains your task configuration data.
</p>
<hr>
<p>
<b>
Q: How can I separate my work tasks from my home tasks?
Specifically, can I keep them completely separate?
</b>
<br />
A: You can do this by creating an alternate .taskrc file,
then using shell aliases. Here is are example Bash
commands to achieve this:
<pre><code>% cp ~/.taskrc ~/.taskrc_home
% (now edit .taskrc_home to change the value of data.location)
% alias wtask="task"
% alias htask="task rc:~/.taskrc_home"</code></pre>
This gives you two commands, 'wtask' and 'htask' that
operate using two different sets of task data files.
</p>
<hr>
<p>
<b>
Q: Can I revert to a previous version of task? How?
</b>
<br />
A: Yes, you can revert to a previous version of task,
simply by downloading an
<a href="versions.html">older version</a> and
installing it. If you find a bug in task, then this
may be the only way to work around the bug, until a
new release is made.
</p>
<p>
Note that it is possible that the task file format will
change. For example, the format changed between versions
1.5.0 and 1.6.0. Task will automatically upgrade the file
but if you need to revert to a previous version of task,
there is the file format to consider. This is yet another
good reason to back up your task data files!
</p>
<hr>
<!--
<p>
<b>
Q:
</b>
<br />
A:
</p>
<hr>
-->
</div>
<br />
<br />
<div class="content">
<p>
Copyright 2006-2009, P. Beckingham. All rights reserved.
</p>
</div>
</div>
</td>
<td align="right" valign="top" width="200px">
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<script type="text/javascript"><!--
google_ad_client = "pub-9709799404235424";
/* Task Main */
google_ad_slot = "8660617875";
google_ad_width = 120;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</td>
</tr>
</table>
</div>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
var pageTracker = _gat._getTracker("UA-4737637-1");
pageTracker._initData();
pageTracker._trackPageview();
</script>
</body>
</html>

133
html/filter.html Normal file
View 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-2009, P. Beckingham. All rights reserved.
</p>
</div>
</div>
</td>
<td align="right" valign="top" width="200px">
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<script type="text/javascript"><!--
google_ad_client = "pub-9709799404235424";
/* Task Main */
google_ad_slot = "8660617875";
google_ad_width = 120;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</td>
</tr>
</table>
</div>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
var pageTracker = _gat._getTracker("UA-4737637-1");
pageTracker._initData();
pageTracker._trackPageview();
</script>
</body>
</html>

158
html/import.html Normal file
View File

@@ -0,0 +1,158 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Data Import</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="task.css" type="text/css" />
</head>
<body>
<div id="container">
<table>
<tr>
<td>
<div id="toolbar">
<a href="task.html">Home</a>
<a href="setup.html">Setup</a>
<a href="30second.html">30-second Tutorial</a>
<a href="simple.html">Simple</a>
<a href="advanced.html">Advanced</a>
<a href="shell.html">Shell</a>
<a href="config.html">Configuration</a>
<a href="color.html">Colors</a>
<a href="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">Data Import</h2>
<div class="content">
<p>
Tasks can be imported from files with this command:
<pre><code>% task import file</code></pre>
A variety of different file types are recognized by task, namely:
<ul>
<li>Tasks exported from task prior to version 1.5.0.
<li>Tasks exported from task version 1.5.0 and later. The file
format changed with 1.5.0.
<li>todo.sh files.
<li>CSV files with a variety of recognized column names.
<li>Plain text files, with one task listed per line.
<li>Task command line format.
</ul>
</p>
<p>
Task makes a good effort to determine which of these formats a
file is. It does this by reading the file, and looking for
familiar patterns. For example, the easiest files to recognize
are those exported from task itself, because they all have a
header line that comes in only three variations. Other formats
are a little harder to identify, but they all have their own
identifying characteristics.
</p>
<p>
The most complex import is when a CSV file is recognized.
Task needs a field header line in order to map columns to task
data items. For example, the if the following file is
imported:
</p>
<pre><code>number,status,task
1,pending,task one
2,pending,task two</code></pre>
<p>
Task will map the "number" field to task's "id" field, etc,
based on name. Task has a list of synonyms that it uses to
map fields, but you can specify your own override with any of
the following configuration variables:
</p>
<ul>
<li>import.synonym.id
<li>import.synonym.uuid
<li>import.synonym.status
<li>import.synonym.tags
<li>import.synonym.entry
<li>import.synonym.start
<li>import.synonym.due
<li>import.synonym.recur
<li>import.synonym.end
<li>import.synonym.project
<li>import.synonym.priority
<li>import.synonym.fg
<li>import.synonym.bg
<li>import.synonym.description
</ul>
<p>
Please note that it is wise to backup your task data files
before an import.
</p>
</div>
<br />
<br />
<div class="content">
<p>
Copyright 2006-2009, P. Beckingham. All rights reserved.
</p>
</div>
</div>
</td>
<td align="right" valign="top" width="200px">
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<script type="text/javascript"><!--
google_ad_client = "pub-9709799404235424";
/* Task Main */
google_ad_slot = "8660617875";
google_ad_width = 120;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</td>
</tr>
</table>
</div>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
var pageTracker = _gat._getTracker("UA-4737637-1");
pageTracker._initData();
pageTracker._trackPageview();
</script>
</body>
</html>

214
html/links.html Normal file
View File

@@ -0,0 +1,214 @@
<!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>
February 2009, <a href="http://lifehacker.com/5155450/todotxt-cli-manages-your-tasks-from-the-command-line">Todo.txt CLI Manages Your Tasks from the Command Line</a>
</dt>
<dd>
Gina Trapani generously mentions task in an article about the newly updated, todo.sh 2.0.
</dd>
<br>
<dt>
February, 2009, <a href="http://forum.worklifecreativity.net/index.php/topic,219.0.html">My command line based task management tools</a>
</dt>
<dd>
Richard Querin talks about his task management tools.
Richard generously provides the Debian packages for task.
</dd>
<br>
<dt>
February, 2009, <a href="http://wiki.archlinux.org/index.php/Common_Apps">Common Apps</a>
</dt>
<dd>
<a href="http://wiki.archlinux.org">Archlinux.org</a> mentions task on a page which is
a point of reference for people looking for software to fill a particular need.
</dd>
<br>
<dt>
November 2008, <a href="http://github.com/pbeckingham/task/tree/master/">Task repository on GitHub</a>
</dt>
<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-2009, P. Beckingham. All rights reserved.
</p>
</div>
</div>
</td>
<td align="right" valign="top" width="200px">
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<script type="text/javascript"><!--
google_ad_client = "pub-9709799404235424";
/* Task Main */
google_ad_slot = "8660617875";
google_ad_width = 120;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</td>
</tr>
</table>
</div>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
var pageTracker = _gat._getTracker("UA-4737637-1");
pageTracker._initData();
pageTracker._trackPageview();
</script>
</body>
</html>

View File

@@ -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">
@@ -100,6 +101,13 @@ Permanently delete task? (y/n) y
This is a recurring task. Do you want to delete all pending
recurrences of this same task? (y/n) y</code></pre>
<h4>Modification</h4>
<p>
When a recurring task is modified, all the other recurring task instances will
be modified. For example, if you raise the priority of one of the recurring
task instances, all will be modified.
</p>
<h4>Recurrence Periods</h4>
<p>
In the above examples, the recurrence period was specified as "monthly" and
@@ -115,6 +123,13 @@ recurrences of this same task? (y/n) y</code></pre>
<td class="table_d">daily, day, 1d, 2d ...</td>
<td class="table_d">Every day, or a number of days</td>
</tr>
<tr>
<td class="table_d">weekdays</td>
<td class="table_d">
Monday, Tuesday, Wednesday, Thursday and Friday,
skipping weekend days
</td>
</tr>
<tr>
<td class="table_d">weekly, 1w, 2w ...</td>
<td class="table_d">Every week, or a number of weeks</td>
@@ -154,7 +169,7 @@ recurrences of this same task? (y/n) y</code></pre>
<br />
<div class="content">
<p>
Copyright 2006-2008, P. Beckingham. All rights reserved.
Copyright 2006-2009, P. Beckingham. All rights reserved.
</p>
</div>

View File

@@ -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">
@@ -39,10 +40,10 @@
</p>
<pre><code>% ls
task-1.4.1.tar.gz
% gunzip task-1.4.1.tar.gz
% tar xf task-1.4.1.tar
% cd task-1.4.1
task-1.6.0.tar.gz
% gunzip task-1.6.0.tar.gz
% tar xf task-1.6.0.tar
% cd task-1.6.0
% ./configure
...
% make
@@ -89,7 +90,7 @@ Done.
<br />
<div class="content">
<p>
Copyright 2006-2008, P. Beckingham. All rights reserved.
Copyright 2006-2009, P. Beckingham. All rights reserved.
</p>
</div>

129
html/shadow.html Normal file
View File

@@ -0,0 +1,129 @@
<!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="http://www.samurize.com">Samurize</a>,
<a href="http://www.mulle-kybernetik.com/software/MkConsole/">MkConsole</a>,
or
<a href="http://projects.tynsoe.org/en/geektool/">GeekTool</a>
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 three entries as shown:
</p>
<pre><code>shadow.file=/path/to/file
shadow.command=list pri:H
shadow.notify=on</code></pre>
<p>
In this example the shadow file contains a report equivalent
to running "task list pri:H". Note that the third entry
causes a message to be displayed whenever task updates the
shadow file. It is optional.
</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-2009, P. Beckingham. All rights reserved.
</p>
</div>
</div>
</td>
<td align="right" valign="top" width="200px">
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<script type="text/javascript"><!--
google_ad_client = "pub-9709799404235424";
/* Task Main */
google_ad_slot = "8660617875";
google_ad_width = 120;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</td>
</tr>
</table>
</div>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
var pageTracker = _gat._getTracker("UA-4737637-1");
pageTracker._initData();
pageTracker._trackPageview();
</script>
</body>
</html>

View File

@@ -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">
@@ -79,7 +80,7 @@
<br />
<div class="content">
<p>
Copyright 2006-2008, P. Beckingham. All rights reserved.
Copyright 2006-2009, P. Beckingham. All rights reserved.
</p>
</div>

View File

@@ -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">
@@ -304,7 +305,7 @@ ID Project Pri Due Active Age Description
<br />
<div class="content">
<p>
Copyright 2006-2008, P. Beckingham. All rights reserved.
Copyright 2006-2009, P. Beckingham. All rights reserved.
</p>
</div>

View File

@@ -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.2</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,11 @@
<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>
<li><a href="custom.html">Custom Reports</a>
<li><a href="import.html">Data Import</a>
<li><a href="faq.html">Frequently Asked Questions</a>
</ul>
<p>
@@ -69,76 +73,129 @@
</p>
<br />
<h2 class="title">Get the Latest Release</h2>
<h2 class="title">Get the Latest Stable Release</h2>
<div class="content">
<table>
<tr>
<td>Source:</td>
<td><a href="http://www.beckingham.net/task-1.4.2.tar.gz">task-1.4.2.tar.gz</a></td>
<td><a href="http://www.beckingham.net/task-1.6.0.tar.gz">task-1.6.0.tar.gz</a></td>
</tr>
<!--
<tr>
<td>Mac OS X 10.5 (Leopard) Intel-only:</td>
<td><a href="http://www.beckingham.net/task-1.4.2.pkg">task-1.4.2.pkg</a></td>
<td><a href="http://www.beckingham.net/task-1.6.0.pkg">task-1.6.0.pkg</a></td>
</tr>
-->
<!--
<tr>
<td>
Debian package:
(Thanks to <a href="http://blog.rfquerin.org">Richard Querin</a>):
Debian:
(Thanks to <a href="http://blog.rfquerin.org">Richard&nbsp;Querin</a>):
</td>
<td><a href="http://www.beckingham.net/task_1.4.2-1_i386.deb">task_1.4.2-1_i386.deb</a></td>
<td><a href="http://www.beckingham.net/task_1.6.0-1_i386.deb">task_1.6.0-1_i386.deb</a></td>
</tr>
<tr>
<td>
Red Hat:
(Thanks to <a href="http://www.ultrafredde.com">Federico&nbsp;Hernandez</a>):
</td>
<td><a href="http://www.beckingham.net/task-1.6.0-1.i386.rpm">task-1.6.0-1.i386.rpm</a></td>
</tr>
<tr>
<td>Git - get the whole source and history:</td>
<td><a href="http://github.com/pbeckingham/task">http://github.com/pbeckingham/task</a></td>
</tr>
-->
</table>
<h4>New in version 1.4.2 (9/18/2008)</h4>
<h4>New in version 1.6.0 (?)</h4>
<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 &lt;id&gt; "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 &lt;string.h&gt; in
order to build clean using gcc 4.3 (thanks to H. İbrahim Güngör)
<li>Added support for new "append" command that adds more description text to
an existing task.
<li>Added support for the "weekdays" recurrence, which means a task can recur
five times a week, and not on weekends (thanks to Chris Pride).
<li>UTF8 text is now supported in task project names, tags and descriptions.
<li>Fixed bug that caused the y/n confirmation on task deletion to ignore the
Enter key and fail to re-prompt (thanks to Bruce Dillahunty).
<li>When the "echo.command" configuration variable is set to "yes", it causes
commands that modify tasks to display which task was affected (thanks to
Bruce Dillahunty).
<li>A task can now be annotated with the command "task <id> annotate ...", and
a timestamped annotation will appear in reports.
<li>A 'description_only' column is now available for use in custom reports,
and it excludes annotations.
<li>A task can now be upgraded to a recurring task by adding a recurrence
frequency, a due date, and an optional until date.
<li>When a recurring task is modified, all other instances of the recurring
task are also modified.
<li>Custom reports now support user-specified column labels (thanks to T.
Charles Yun).
<li>Task can now import tasks from a variety of data formats, including task
export files from versions 1.4.3 and earlier, versions 1.5.0 and later,
todo.sh 2.x, CSV, plain text and task command line. See online docs for
full details.
<li>Export was including 'id' in the column header even though it was not
included in the data.
<li>The task file format has changed slightly. Please back up your task
data files before upgrading to 1.6.0.
<li>Added new column 'recurrence_indicator' that displays an 'R' if the task
is a recurring task. This column can be added to any custom report.
<li>Added new column 'tag_indicator' that displays a '+' if the task
has any tags. This column can be added to any custom report.
<li>Fixed bug where sometimes a task description was concatenated oddly if
there was a colon somewhere in the description.
<li>Fixed bug that caused recurring annual tasks to exhibit a creeping due
date, because of an assumption of 365 days per year, which failed to
consider leap years (thanks to T. Charles Yun).
<li>Annotations can now be modified with the substitution commands /from/to/.
<li>Substitutions can now be made global with /from/to/g and all occurrences
of "from" will be replaced with "to".
</ul>
<p>
(Find out <a href="versions.html">what was new in prior versions</a>)
</p>
<!--
<h2>Task 1.6.0 Beta</h2>
<p>
The next version of task is in beta. This means it is approaching the
end of the current development and testing cycle, and feedback from
a wider audience is needed to find the last bugs. If you would like
to help test the next release of task, download the beta source below
and install in the usual manner.
</p>
<p>
Please note that beta software may contain significant bugs. If you
use this beta release, you should first backup your existing task
data files.
</p>
<p>
Refer to the ChangeLog file for details regarding the various fixes
and enhancements.
</p>
<table>
<tr>
<td>Source:</td>
<td><a href="http://www.beckingham.net/task-1.6.0beta.tar.gz">task-1.6.0beta.tar.gz</a></td>
</tr>
</table>
-->
<h2>Troubleshooting</h2>
<p>
Task has been built from source and tested in the following environments:
</p>
<ul>
<li>OS X 10.4 Tiger
<li>OS X 10.5 Leopard
<li>Fedora Core 8
<li>Fedora Core 9
<li>Ubuntu 7 Feisty Fawn
<li>Ubuntu 8 Hardy Heron
<li>Solaris 10
<li>Cygwin 1.5.25-14
</ul>
<p>
<ul>
<li>OS X 10.4 Tiger
<li>OS X 10.5 Leopard
<li>Fedora Core 8
<li>Fedora Core 9
<li>Fedora Core 10
<li>Ubuntu 7 Feisty Fawn
<li>Ubuntu 8 Hardy Heron
<li>Ubuntu 8.10 Intrepid Ibex
<li>Solaris 10
<li>Cygwin 1.5.25-14
</ul>
</p>
<p>
If you have difficulties building task, have found a bug, have a
@@ -157,7 +214,7 @@
<br />
<div class="content">
<p>
Copyright 2006-2008, P. Beckingham. All rights reserved.
Copyright 2006-2009, P. Beckingham. All rights reserved.
</p>
</div>

View File

@@ -25,6 +25,7 @@
<a href="date.html">Date Handling</a>
<a href="troubleshooting.html">Troubleshooting</a>
<a href="versions.html">Old Versions</a>
<a href="links.html">Task on the Web</a>
</div>
<div id="content">
@@ -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">
@@ -108,11 +83,29 @@
</p>
</div>
<br />
<h2 class="title">Do colors work under Cygwin?</h2>
<div class="content">
<p>
They do, but only in a limited way. You can use regular
foreground colors (black, red, green ...) and you can
regular background colors (on_black, on_red, on_green ...),
but underline and bold are not supported.
</p>
<p>
If you run the command:
<code><pre>% task colors</pre></code>
Task will display all the colors it can use, and you will
see which ones you can use.
</p>
</div>
<br />
<br />
<div class="content">
<p>
Copyright 2006-2008, P. Beckingham. All rights reserved.
Copyright 2006-2009, P. Beckingham. All rights reserved.
</p>
</div>

View File

@@ -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">
@@ -33,18 +34,20 @@
<br />
<h2 class="title"><a name="usage">Command Usage<a></h2>
<div class="content">
<pre><code>task add [tags] [attrs] desc...
task list [tags] [attrs] desc...
task long [tags] [attrs] desc...
task ls [tags] [attrs] desc...
<pre><code>Usage: task
task add [tags] [attrs] desc...
task append [tags] [attrs] desc...
task annotate ID 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
@@ -54,13 +57,18 @@
task calendar
task active
task overdue
task oldest
task newest
task stats
task usage
task export
task color
task version
task help
task list [tags] [attrs] desc...
task long [tags] [attrs] desc...
task ls [tags] [attrs] desc...
task newest [tags] [attrs] desc...
task oldest [tags] [attrs] desc...
See http://www.beckingham.net/task.html for the latest releases and a full tutorial.
ID is the numeric identifier displayed by the 'task list' command
@@ -72,8 +80,11 @@ Attributes are:
project: Project name
priority: Priority
due: Due date
recur: Recurrence frequency
until: Recurrence end date
fg: Foreground color
bg: Background color
rc: Alternate .taskrc file
Any command or attribute name may be abbreviated if still unique:
task list project:Home
@@ -84,14 +95,14 @@ Some task descriptions need to be escaped because of the shell:
task add escaped \' quote
Many characters have special meaning to the shell, including:
$ ! ' " ( ) ; \ ` * ? { } [ ] < > | &amp; % # ~</code></pre>
$ ! ' " ( ) ; \ ` * ? { } [ ] < > | & % # ~</code></pre>
<div>
<br />
<br />
<div class="content">
<p>
Copyright 2006-2008, P. Beckingham. All rights reserved.
Copyright 2006-2009, P. Beckingham. All rights reserved.
</p>
</div>

View File

@@ -25,6 +25,7 @@
<a href="date.html">Date Handling</a>
<a href="troubleshooting.html">Troubleshooting</a>
<a href="versions.html">Old Versions</a>
<a href="links.html">Task on the Web</a>
</div>
<div id="content">
@@ -35,12 +36,149 @@
<br />
<div class="content">
<p>
<h4>New in version 1.5.0 (3/15/2009)</h4>
<table>
<tr>
<td>Source:</td>
<td><a href="http://www.beckingham.net/task-1.5.0.tar.gz">task-1.5.0.tar.gz</a></td>
</tr>
<tr>
<td>Mac OS X 10.5 (Leopard) Intel-only:</td>
<td><a href="http://www.beckingham.net/task-1.5.0.pkg">task-1.5.0.pkg</a></td>
</tr>
<tr>
<td>
Debian:
(Thanks to <a href="http://blog.rfquerin.org">Richard&nbsp;Querin</a>):
</td>
<td><a href="http://www.beckingham.net/task_1.5.0-1_i386.deb">task_1.5.0-1_i386.deb</a></td>
</tr>
<tr>
<td>
Red Hat:
(Thanks to <a href="http://www.ultrafredde.com">Federico&nbsp;Hernandez</a>):
</td>
<td><a href="http://www.beckingham.net/task-1.5.0-1.i386.rpm">task-1.5.0-1.i386.rpm</a></td>
</tr>
</table>
<ul>
<li>Removed deprecated TUTORIAL file.
<li>Removed support for the "showage" configuration variable.
<li>"task stop" can remove the start time from a started task.
<li>"task ghistory" now displays a differently aligned graph, allowing
easier comparison by month of tasks added versus completed and deleted.
<li>"task version" command now reports unrecognized configuration variables,
which may be spelling mistakes or deprecated variables.
<li>"configure --enable-debug" now supported to suppress compiler optimization
to allow debugging.
<li>Allow lower case priorities, and automatically upper case them.
<li>Added support for "due" configuration variable which defines the number
of days in the future when a task is considered due.
<li>Added support for custom reports, comprised of a set of column names and
sort order, with optional filtering in the configuration file. This
means user-defined reports can be written, and the reports currently
in the configuration file can be renamed. Several of task's built in
reports have been converted to user-defined reports.
<li>New online documentation for custom reports.
<li>New algorithm for determining when the "nag" message is displayed.
<li>Fixed bug where task hangs with a certain combination of recurring tasks
and shadow files.
<li>Fixed bug with the task sort algorithm, which led to an unstable sequence
when there were only a handful of tasks.
<li>Performance enhanced by eliminating unnecessary sorting.
<li>Task now has a large (and growing) test suite and bug regression tests
to help ensure higher quality releases.
<li>Fixed bug that caused large performance hit during table rendering.
<li>Fixed bug that concatenated a modified description without spaces.
<li>Added new column 'recur' that displays the recurrence period of any
recurring tasks. This column can be added to any custom report.
<li>Added support for "color.recurring" configuration variable which
specifies the color of recurring tasks.
<li>Added support for "locking" configuration variable that controls whether
file locking is used.
<li>Task export feature now includes recurrence information, removes nested
quotes, and limits output to pending tasks.
<li>Task no longer includes deleted tasks in the summary report (thanks to
Benjamin Tegarden).
<li>Fixed bug that prevented the summary report from properly reporting
recently completed tasks.
</ul>
</p>
<p>
<h4>New in version 1.4.3 (11/1/2008)</h4>
<a href="http://www.beckingham.net/task-1.4.3.tar.gz">task-1.4.3.tar.gz</a>
<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>
<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 &lt;id&gt; "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 &lt;string.h&gt; 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>
@@ -54,7 +192,7 @@
<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>
@@ -184,7 +322,7 @@
<br />
<div class="content">
<p>
Copyright 2006-2008, P. Beckingham. All rights reserved.
Copyright 2006-2009, P. Beckingham. All rights reserved.
</p>
</div>
</div>

View File

@@ -1,22 +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

View File

@@ -1,105 +1,109 @@
Hello, and welcome to this quick demo of the task program.
Hello, and welcome to this quick demo of the task program.
task add do laundry Let's add some tasks
I need to do laundry
task add do laundry Let's add some tasks
I need to do laundry
task add project:garage order dumpster Oh yeah, the dumpster
task add project:garage order dumpster Oh yeah, I need to order the dumpster
task add +phone tell mom i loveher Must call Mom (that "phone" there is a tag - they are
useful for searching, categorizing)
task add +phone tell mom i loveher Must call Mom (that "phone" there is a tag - they can
be useful for searching and categorizing)
task add +phone pro:garage schedule
goodwill pickup
task ad +email pro:garage ask Tom if Notice I can abbreviating commands
task ad +email pro:garage ask Tom if Notice I can abbreviate commands
he wants that old bkie
task ls Let's see what we've got
I spelled bike wrong
task ls Let's see what we've got
Oh, I spelled bike wrong
task 5 /bkie/bike/
task ls That's better
task ls That's better
task 1 pro:home Let's assign projects
task 1 pro:home Let's assign projects
task 3 pro:home tell mom I love her
task ls pro:garage
task long pro:garage Let's see all the columns
task long pro:garage Let's see all the columns
task list pro:garage There are different ways to list
task list pro:garage There are different ways to list
task lis +phone By tag
task li pro:garage +phone By project and tag
task l mom By word
task lis +phone By tag
task li pro:garage +phone By project and tag
task l mom By word
task 1 priority:H Priorities can be High, Medium or Low
task 1 priority:H Priorities can be High, Medium or Low
task pri:H 3
task 1 pri:M
task li The list is sorted by priority.
task li The list is sorted by priority.
task 2 pri:L
task li
task done 3 Suppose task 3 is done
task li ...and it's gone
task done 3 Suppose task 3 is done
task li ...and it's gone
task 2 +phone +mistake Lets add tags
task 2 +phone +mistake Lets add tags
# Oops!
task 2 -mistake or remove tags
task 2 -mistake or remove tags
task tags or look at all the tags
task tags or look at all the tags
task info 2 or all the details
task info 2 or all the details
task projects or all the projects
task projects or all the projects
task 3 fg:bold Let's make it colorful
task 3 fg:bold Let's make it colorful
task 4 fg:bold_green
task li
task 3 fg:bold_underline_white
task li
task 4 bg:on_bright_red fg:bold_yellow
task li Oh that's just nasty - let's get rid of that.
task li Oh that's just nasty - let's get rid of that.
task 4 bg:
task li
task 4 fg:
task 3 fg:
task colors There are many combinations to choose from
task colors There are many combinations to choose from
(Slashes!!!)
task 1 due:6/8/2008 Let's add a due date
task 1 due:6/8/2008 Let's add a due date
date
task li
task calendar Notice the due task is in yellow, today is marked cyan
task calendar Notice the due task is in yellow, today is marked cyan
task 1 due:5/20/2008 This is now an overdue task
task li and it shows up red
task 1 due:5/20/2008 This is now an overdue task
task li and it shows up red
task overdue
task cal
task export file.csv You can export the tasks to a spreadsheet
task export file.csv You can export the tasks to a spreadsheet
cat file.csv
task start 1 Started tasks can be used as reminders
of what you are supposed to be doing
task start 1 Started tasks can be used as reminders
of what you are supposed to be doing
task active They show up as active
task done 1 Let's clear out a couple
task active They show up as active
task done 1 Let's clear out a couple
task li
task done 3
task active
task summary Summary shows progress on all projects
task summary Summary shows progress on all projects
task history History shows general activity - how many added,
completed etc, by month
task history History shows general activity - how many added,
completed etc, by month
And that's it. There are more commands than this
covered in the TUTORIAL file, but this should give
the basic idea.
task ghistory This report shows a histogram of tasks that were
added (in red), completed (in green) and deleted
(in yellow), all by month.
Thank you for watching.
And that's it. There are more commands than this
covered in the online documentation, but this should give
the basic idea.
Thank you for watching.

1
src/.gitignore vendored
View File

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

View File

@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2008, Paul Beckingham.
// Copyright 2006 - 2009, Paul Beckingham.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
@@ -36,8 +36,40 @@
#include "Config.h"
////////////////////////////////////////////////////////////////////////////////
// These are default (but overridable) reports. These entries are necessary
// because these three reports were converted from hard-coded reports to custom
// reports, and therefore need these config file entries. However, users are
// already used to seeing these five reports, but do not have these entries.
// The choice was a) make users edit their .taskrc files, b) write a .taskrc
// upgrade program to make the change, or c) this.
Config::Config ()
{
(*this)["report.long.description"] = "Lists all task, all data, matching the specified criteria";
(*this)["report.long.columns"] = "id,project,priority,entry,start,due,recur,age,tags,description";
(*this)["report.long.labels"] = "ID,Project,Pri,Added,Started,Due,Recur,Age,Tags,Description";
(*this)["report.long.sort"] = "due+,priority-,project+";
(*this)["report.list.description"] = "Lists all tasks matching the specified criteria";
(*this)["report.list.columns"] = "id,project,priority,due,active,age,description";
(*this)["report.list.labels"] = "ID,Project,Pri,Due,Active,Age,Description";
(*this)["report.list.sort"] = "due+,priority-,project+";
(*this)["report.ls.description"] = "Minimal listing of all tasks matching the specified criteria";
(*this)["report.ls.columns"] = "id,project,priority,description";
(*this)["report.ls.labels"] = "ID,Project,Pri,Description";
(*this)["report.ls.sort"] = "priority-,project+";
(*this)["report.newest.description"] = "Shows the newest tasks";
(*this)["report.newest.columns"] = "id,project,priority,due,active,age,description";
(*this)["report.newest.labels"] = "ID,Project,Pri,Due,Active,Age,Description";
(*this)["report.newest.sort"] = "id-";
(*this)["report.newest.limit"] = "10";
(*this)["report.oldest.description"] = "Shows the oldest tasks";
(*this)["report.oldest.columns"] = "id,project,priority,due,active,age,description";
(*this)["report.oldest.labels"] = "ID,Project,Pri,Due,Active,Age,Description";
(*this)["report.oldest.sort"] = "id+";
(*this)["report.oldest.limit"] = "10";
}
////////////////////////////////////////////////////////////////////////////////
@@ -47,9 +79,9 @@ Config::Config (const std::string& file)
}
////////////////////////////////////////////////////////////////////////////////
// Read the Configuration filee and populate the *this map. The file format
// is simply lines with name=value pairs. Whitespace between name, = and value
// is not tolerated, but blank lines and comments starting with # are allowed.
// Read the Configuration file and populate the *this map. The file format is
// simply lines with name=value pairs. Whitespace between name, = and value is
// not tolerated, but blank lines and comments starting with # are allowed.
bool Config::load (const std::string& file)
{
std::ifstream in;
@@ -112,25 +144,65 @@ 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, "echo.command=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, "#monthsperline=2\n");
fprintf (out, "curses=on\n");
fprintf (out, "color=on\n");
fprintf (out, "due=7\n");
fprintf (out, "nag=You have higher priority tasks.\n");
fprintf (out, "locking=on\n");
fprintf (out, "color.overdue=bold_red\n");
fprintf (out, "#color.due=on_bright_yellow\n");
fprintf (out, "#color.pri.H=on_red\n");
fprintf (out, "color.due=bold_yellow\n");
fprintf (out, "color.pri.H=bold\n");
fprintf (out, "#color.pri.M=on_yellow\n");
fprintf (out, "#color.pri.L=on_green\n");
fprintf (out, "#color.pri.none=white on_blue\n");
fprintf (out, "color.active=bold_cyan\n");
fprintf (out, "color.tagged=yellow\n");
fprintf (out, "#color.tag.bug=yellow\n");
fprintf (out, "#color.project.home=on_green\n");
fprintf (out, "#color.project.garden=on_green\n");
fprintf (out, "#color.keyword.car=on_blue\n");
fprintf (out, "#color.recurring=on_red\n");
fprintf (out, "#shadow.file=%s/shadow.txt\n", dataDir.c_str ());
fprintf (out, "#shadow.command=list\n");
fprintf (out, "#shadow.notify=on\n");
fprintf (out, "#default.project=foo\n");
fprintf (out, "#default.priority=M\n");
fprintf (out, "default.command=list\n");
// Custom reports.
fprintf (out, "# Fields: id,uuid,project,priority,entry,start,due,recur,age,active,tags,description\n");
fprintf (out, "# description_only\n");
fprintf (out, "# Description: This report is ...\n");
fprintf (out, "# Sort: due+,priority-,project+\n");
fprintf (out, "# Filter: pro:x pri:H +bug\n");
fprintf (out, "# Limit: 10\n");
fprintf (out, "report.long.description=Lists all task, all data, matching the specified criteria\n");
fprintf (out, "report.long.columns=id,project,priority,entry,start,due,recur,age,tags,description\n");
fprintf (out, "report.long.sort=due+,priority-,project+\n");
fprintf (out, "report.list.description=Lists all tasks matching the specified criteria\n");
fprintf (out, "report.list.columns=id,project,priority,due,active,age,description\n");
fprintf (out, "report.list.sort=due+,priority-,project+\n");
fprintf (out, "report.ls.description=Minimal listing of all tasks matching the specified criteria\n");
fprintf (out, "report.ls.columns=id,project,priority,description\n");
fprintf (out, "report.ls.sort=priority-,project+\n");
fprintf (out, "report.newest.description=Shows the newest tasks\n");
fprintf (out, "report.newest.columns=id,project,priority,due,active,age,description\n");
fprintf (out, "report.newest.sort=id-\n");
fprintf (out, "report.newest.limit=10\n");
fprintf (out, "report.oldest.description=Shows the oldest tasks\n");
fprintf (out, "report.oldest.columns=id,project,priority,due,active,age,description\n");
fprintf (out, "report.oldest.sort=id+\n");
fprintf (out, "report.oldest.limit=10\n");
fclose (out);
@@ -189,11 +261,13 @@ bool Config::get (const std::string& key, bool default_value)
{
std::string value = lowerCase ((*this)[key]);
if (value == "t" ||
value == "true" ||
value == "1" ||
value == "yes" ||
value == "on")
if (value == "t" ||
value == "true" ||
value == "1" ||
value == "yes" ||
value == "on" ||
value == "enable" ||
value == "enabled")
return true;
return false;

View File

@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2008, Paul Beckingham.
// Copyright 2006 - 2009, Paul Beckingham.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under

View File

@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2008, Paul Beckingham.
// Copyright 2006 - 2009, Paul Beckingham.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under

View File

@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2008, Paul Beckingham.
// Copyright 2006 - 2009, Paul Beckingham.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under

View File

@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2008, Paul Beckingham.
// Copyright 2006 - 2009, Paul Beckingham.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
@@ -60,6 +60,7 @@
////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <stdlib.h>
#include <Grid.h>
////////////////////////////////////////////////////////////////////////////////
@@ -325,7 +326,7 @@ Grid::Cell::operator int () const
case CELL_INT: return mInt;
case CELL_FLOAT: return (int) mFloat;
case CELL_DOUBLE: return (int) mDouble;
case CELL_STRING: return mString.length ();
case CELL_STRING: return ::atoi (mString.c_str ());
}
return 0;
@@ -340,7 +341,7 @@ Grid::Cell::operator float () const
case CELL_INT: return (float) mInt;
case CELL_FLOAT: return mFloat;
case CELL_DOUBLE: return (float) mDouble;
case CELL_STRING: return (float) mString.length ();
case CELL_STRING: return (float) ::atof (mString.c_str ());
}
return 0.0;
@@ -355,7 +356,7 @@ Grid::Cell::operator double () const
case CELL_INT: return (double) mInt;
case CELL_FLOAT: return (double) mFloat;
case CELL_DOUBLE: return mDouble;
case CELL_STRING: return (double) mString.length ();
case CELL_STRING: return (double) ::atof (mString.c_str ());
}
return 0.0;

View File

@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2008, Paul Beckingham.
// Copyright 2006 - 2009, Paul Beckingham.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under

View File

@@ -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
task_SOURCES = Config.cpp Date.cpp T.cpp TDB.cpp Table.cpp Grid.cpp Timer.cpp color.cpp parse.cpp task.cpp command.cpp report.cpp util.cpp text.cpp rules.cpp import.cpp Config.h Date.h T.h TDB.h Table.h Grid.h Timer.h color.h task.h

View File

@@ -44,9 +44,10 @@ am__installdirs = "$(DESTDIR)$(bindir)"
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
PROGRAMS = $(bin_PROGRAMS)
am_task_OBJECTS = Config.$(OBJEXT) Date.$(OBJEXT) T.$(OBJEXT) \
TDB.$(OBJEXT) Table.$(OBJEXT) Grid.$(OBJEXT) color.$(OBJEXT) \
parse.$(OBJEXT) task.$(OBJEXT) command.$(OBJEXT) \
report.$(OBJEXT) util.$(OBJEXT) text.$(OBJEXT) rules.$(OBJEXT)
TDB.$(OBJEXT) Table.$(OBJEXT) Grid.$(OBJEXT) Timer.$(OBJEXT) \
color.$(OBJEXT) parse.$(OBJEXT) task.$(OBJEXT) \
command.$(OBJEXT) report.$(OBJEXT) util.$(OBJEXT) \
text.$(OBJEXT) rules.$(OBJEXT) import.$(OBJEXT)
task_OBJECTS = $(am_task_OBJECTS)
task_LDADD = $(LDADD)
DEFAULT_INCLUDES = -I. -I$(top_builddir)@am__isrc@
@@ -154,8 +155,7 @@ sysconfdir = @sysconfdir@
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
task_SOURCES = Config.cpp Date.cpp T.cpp TDB.cpp Table.cpp Grid.cpp Timer.cpp color.cpp parse.cpp task.cpp command.cpp report.cpp util.cpp text.cpp rules.cpp import.cpp Config.h Date.h T.h TDB.h Table.h Grid.h Timer.h color.h task.h
all: all-am
.SUFFIXES:
@@ -228,8 +228,10 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/T.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TDB.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Table.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Timer.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/color.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/command.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/import.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/report.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rules.Po@am__quote@

254
src/T.cpp
View File

@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2008, Paul Beckingham.
// Copyright 2006 - 2009, Paul Beckingham.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
@@ -25,6 +25,7 @@
//
////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <sstream>
#include <algorithm>
#include "task.h"
#include "T.h"
@@ -39,6 +40,10 @@ T::T ()
mTags.clear ();
mAttributes.clear ();
mDescription = "";
mFrom = "";
mTo = "";
mGlobal = false;
mAnnotations.clear ();
}
////////////////////////////////////////////////////////////////////////////////
@@ -58,6 +63,7 @@ T::T (const T& other)
mTags = other.mTags;
mRemoveTags = other.mRemoveTags;
mAttributes = other.mAttributes;
mAnnotations = other.mAnnotations;
}
////////////////////////////////////////////////////////////////////////////////
@@ -72,6 +78,7 @@ T& T::operator= (const T& other)
mTags = other.mTags;
mRemoveTags = other.mRemoveTags;
mAttributes = other.mAttributes;
mAnnotations = other.mAnnotations;
}
return *this;
@@ -109,6 +116,12 @@ void T::addRemoveTag (const std::string& tag)
mRemoveTags.push_back (tag);
}
////////////////////////////////////////////////////////////////////////////////
int T::getTagCount () const
{
return mTags.size ();
}
////////////////////////////////////////////////////////////////////////////////
void T::getTags (std::vector<std::string>& all) const
{
@@ -230,21 +243,51 @@ void T::removeAttribute (const std::string& name)
}
////////////////////////////////////////////////////////////////////////////////
void T::getSubstitution (std::string& from, std::string& to) const
void T::getSubstitution (
std::string& from,
std::string& to,
bool& global) const
{
from = mFrom;
to = mTo;
from = mFrom;
to = mTo;
global = mGlobal;
}
////////////////////////////////////////////////////////////////////////////////
void T::setSubstitution (const std::string& from, const std::string& to)
void T::setSubstitution (
const std::string& from,
const std::string& to,
bool global)
{
mFrom = from;
mTo = to;
mFrom = from;
mTo = to;
mGlobal = global;
}
////////////////////////////////////////////////////////////////////////////////
// uuid status [tags] [attributes] description
void T::getAnnotations (std::map <time_t, std::string>& all) const
{
all = mAnnotations;
}
////////////////////////////////////////////////////////////////////////////////
void T::setAnnotations (const std::map <time_t, std::string>& all)
{
mAnnotations = all;
}
////////////////////////////////////////////////////////////////////////////////
void T::addAnnotation (const std::string& description)
{
std::string sanitized = description;
std::replace (sanitized.begin (), sanitized.end (), '"', '\'');
std::replace (sanitized.begin (), sanitized.end (), '[', '(');
std::replace (sanitized.begin (), sanitized.end (), ']', ')');
mAnnotations[time (NULL)] = sanitized;
}
////////////////////////////////////////////////////////////////////////////////
// uuid status [tags] [attributes] [annotations] description
//
// uuid \x{8}-\x{4}-\x{4}-\x{4}-\x{12}
// status - + X r
@@ -282,10 +325,26 @@ const std::string T::compose () const
++count;
}
line += "] ";
line += "] [";
// Annotations
std::stringstream annotation;
bool first = true;
foreach (note, mAnnotations)
{
if (first)
first = false;
else
annotation << " ";
annotation << note->first << ":\"" << note->second << "\"";
}
line += annotation.str () + "] ";
// Description
line += mDescription;
// EOL
line += "\n";
if (line.length () > T_LINE_MAX)
@@ -328,6 +387,11 @@ const std::string T::composeCSV ()
line += value;
line += ",";
value = mAttributes["recur"];
if (value != "")
line += value;
line += ",";
value = mAttributes["end"];
if (value != "")
line += value;
@@ -353,7 +417,11 @@ const std::string T::composeCSV ()
line += "'" + value + "'";
line += ",";
line += "'" + mDescription + "'\n";
// Convert single quotes to double quotes, because single quotes are used to
// delimit the values that need it.
std::string clean = mDescription;
std::replace (clean.begin (), clean.end (), '\'', '"');
line += "'" + clean + "'\n";
return line;
}
@@ -412,10 +480,12 @@ void T::parse (const std::string& line)
}
else
throw std::string ("Line too short");
mAnnotations.clear ();
}
break;
// File format version 2, from 2008.1.1
// File format version 2, from 2008.1.1 - 2009.3.23
case 2:
{
if (line.length () > 46) // ^.{36} . \[\] \[\] \n
@@ -437,24 +507,122 @@ void T::parse (const std::string& line)
if (openAttrBracket != std::string::npos &&
closeAttrBracket != std::string::npos)
{
std::string tags = line.substr (
openTagBracket + 1, closeTagBracket - openTagBracket - 1);
std::vector <std::string> rawTags;
split (mTags, tags, ' ');
std::string tags = line.substr (
openTagBracket + 1, closeTagBracket - openTagBracket - 1);
std::vector <std::string> rawTags;
split (mTags, tags, ' ');
std::string attributes = line.substr (
openAttrBracket + 1, closeAttrBracket - openAttrBracket - 1);
std::vector <std::string> pairs;
split (pairs, attributes, ' ');
for (size_t i = 0; i < pairs.size (); ++i)
{
std::vector <std::string> pair;
split (pair, pairs[i], ':');
if (pair.size () == 2)
mAttributes[pair[0]] = pair[1];
}
std::string attributes = line.substr (
openAttrBracket + 1, closeAttrBracket - openAttrBracket - 1);
std::vector <std::string> pairs;
split (pairs, attributes, ' ');
for (size_t i = 0; i < pairs.size (); ++i)
{
std::vector <std::string> pair;
split (pair, pairs[i], ':');
if (pair.size () == 2)
mAttributes[pair[0]] = pair[1];
}
mDescription = line.substr (closeAttrBracket + 2, std::string::npos);
mDescription = line.substr (closeAttrBracket + 2, std::string::npos);
}
else
throw std::string ("Missing attribute brackets");
}
else
throw std::string ("Missing tag brackets");
}
else
throw std::string ("Line too short");
mAnnotations.clear ();
}
break;
// File format version 3, from 2009.3.23
case 3:
{
if (line.length () > 49) // ^.{36} . \[\] \[\] \[\] \n
{
mUUID = line.substr (0, 36);
mStatus = line[37] == '+' ? completed
: line[37] == 'X' ? deleted
: line[37] == 'r' ? recurring
: pending;
size_t openTagBracket = line.find ("[");
size_t closeTagBracket = line.find ("]", openTagBracket);
if (openTagBracket != std::string::npos &&
closeTagBracket != std::string::npos)
{
size_t openAttrBracket = line.find ("[", closeTagBracket);
size_t closeAttrBracket = line.find ("]", openAttrBracket);
if (openAttrBracket != std::string::npos &&
closeAttrBracket != std::string::npos)
{
size_t openAnnoBracket = line.find ("[", closeAttrBracket);
size_t closeAnnoBracket = line.find ("]", openAnnoBracket);
if (openAnnoBracket != std::string::npos &&
closeAnnoBracket != std::string::npos)
{
std::string tags = line.substr (
openTagBracket + 1, closeTagBracket - openTagBracket - 1);
std::vector <std::string> rawTags;
split (mTags, tags, ' ');
std::string attributes = line.substr (
openAttrBracket + 1, closeAttrBracket - openAttrBracket - 1);
std::vector <std::string> pairs;
split (pairs, attributes, ' ');
for (size_t i = 0; i < pairs.size (); ++i)
{
std::vector <std::string> pair;
split (pair, pairs[i], ':');
if (pair.size () == 2)
mAttributes[pair[0]] = pair[1];
}
// Extract and split the annotations, which are of the form:
// 1234:"..." 5678:"..."
std::string annotations = line.substr (
openAnnoBracket + 1, closeAnnoBracket - openAnnoBracket - 1);
pairs.clear ();
std::string::size_type start = 0;
std::string::size_type end = 0;
do
{
end = annotations.find ('"', start);
if (end != std::string::npos)
{
end = annotations.find ('"', end + 1);
if (start != std::string::npos &&
end != std::string::npos)
{
pairs.push_back (annotations.substr (start, end - start + 1));
start = end + 2;
}
}
}
while (start != std::string::npos &&
end != std::string::npos);
for (size_t i = 0; i < pairs.size (); ++i)
{
std::string pair = pairs[i];
std::string::size_type colon = pair.find (":");
if (colon != std::string::npos)
{
std::string name = pair.substr (0, colon);
std::string value = pair.substr (colon + 2, pair.length () - colon - 3);
mAnnotations[::atoi (name.c_str ())] = value;
}
}
mDescription = line.substr (closeAnnoBracket + 2, std::string::npos);
}
}
else
throw std::string ("Missing attribute brackets");
@@ -468,7 +636,7 @@ void T::parse (const std::string& line)
break;
default:
throw std::string ();
throw std::string ("Unrecognized task file format.");
break;
}
}
@@ -503,16 +671,31 @@ int T::determineVersion (const std::string& line)
line[23] == '-' &&
line[36] == ' ' &&
(line[37] == '-' || line[37] == '+' || line[37] == 'X' || line[37] == 'r'))
return 2;
{
// Version 3 looks like:
//
// uuid status [tags] [attributes] [annotations] description\n
//
// Scan for the number of [] pairs.
std::string::size_type tagAtts = line.find ("] [", 0);
std::string::size_type attsAnno = line.find ("] [", tagAtts + 1);
std::string::size_type annoDesc = line.find ("] ", attsAnno + 1);
if (tagAtts != std::string::npos &&
attsAnno != std::string::npos &&
annoDesc != std::string::npos)
return 3;
else
return 2;
}
// Version 3?
// Version 4?
//
// Fortunately, with the hindsight that will come with version 3, the
// identifying characteristics of 1 and 2 may be modified such that if 3 has
// a UUID followed by a status, then there is still a way to differentiate
// between 2 and 3.
// Fortunately, with the hindsight that will come with version 4, the
// identifying characteristics of 1, 2 and 3 may be modified such that if 4
// has a UUID followed by a status, then there is still a way to differentiate
// between 2, 3 and 4.
//
// The danger is that a version 2 binary reads and misinterprets a version 3
// The danger is that a version 3 binary reads and misinterprets a version 4
// file. This is why it is a good idea to rely on an explicit version
// declaration rather than chance positioning.
@@ -525,6 +708,7 @@ int T::determineVersion (const std::string& line)
bool T::validate () const
{
// TODO Verify until > due
// TODO Verify entry < until, due, start, end
return true;
}

15
src/T.h
View File

@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2008, Paul Beckingham.
// Copyright 2006 - 2009, Paul Beckingham.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
@@ -56,15 +56,17 @@ public:
const std::string getDescription () const { return mDescription; }
void setDescription (const std::string& description) { mDescription = description; }
int getAnnotationCount () const { return mAnnotations.size (); }
void getSubstitution (std::string&, std::string&) const;
void setSubstitution (const std::string&, const std::string&);
void getSubstitution (std::string&, std::string&, bool&) const;
void setSubstitution (const std::string&, const std::string&, bool);
bool hasTag (const std::string&) const;
void getRemoveTags (std::vector<std::string>&); // SPECIAL
void addRemoveTag (const std::string&); // SPECIAL
int getTagCount () const;
void getTags (std::vector<std::string>&) const;
void addTag (const std::string&);
void addTags (const std::vector <std::string>&);
@@ -77,6 +79,10 @@ public:
void removeAttribute (const std::string&);
void removeAttributes ();
void getAnnotations (std::map <time_t, std::string>&) const;
void setAnnotations (const std::map <time_t, std::string>&);
void addAnnotation (const std::string&);
const std::string compose () const;
const std::string composeCSV ();
void parse (const std::string&);
@@ -93,9 +99,10 @@ private:
std::vector<std::string> mTags;
std::vector<std::string> mRemoveTags;
std::map<std::string, std::string> mAttributes;
std::string mFrom;
std::string mTo;
bool mGlobal;
std::map <time_t, std::string> mAnnotations;
};
#endif

View File

@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2008, Paul Beckingham.
// Copyright 2006 - 2009, Paul Beckingham.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
@@ -37,8 +37,8 @@
TDB::TDB ()
: mPendingFile ("")
, mCompletedFile ("")
, mLogFile ("")
, mId (1)
, mNoLock (false)
{
}
@@ -54,7 +54,6 @@ void TDB::dataDirectory (const std::string& directory)
{
mPendingFile = directory + "/pending.data";
mCompletedFile = directory + "/completed.data";
mLogFile = directory + "/command.log";
}
else
{
@@ -237,7 +236,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 +255,9 @@ bool TDB::addT (const T& t) const
if (task.getStatus () == T::pending ||
task.getStatus () == T::recurring)
{
return writePending (task);
}
return writeCompleted (task);
}
@@ -286,66 +287,13 @@ 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
{
#ifdef HAVE_FLOCK
if (mNoLock)
return true;
return flock (fileno (file), LOCK_EX) ? false : true;
#else
return true;
#endif
}
////////////////////////////////////////////////////////////////////////////////
@@ -355,11 +303,10 @@ bool TDB::overwritePending (std::vector <T>& all)
FILE* out;
if ((out = fopen (mPendingFile.c_str (), "w")))
{
#ifdef HAVE_FLOCK
int retry = 0;
while (flock (fileno (out), LOCK_EX) && ++retry <= 3)
delay (0.25);
#endif
if (!mNoLock)
while (flock (fileno (out), LOCK_EX) && ++retry <= 3)
delay (0.1);
std::vector <T>::iterator it;
for (it = all.begin (); it != all.end (); ++it)
@@ -373,17 +320,16 @@ 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;
if ((out = fopen (mPendingFile.c_str (), "a")))
{
#ifdef HAVE_FLOCK
int retry = 0;
while (flock (fileno (out), LOCK_EX) && ++retry <= 3)
delay (0.25);
#endif
if (!mNoLock)
while (flock (fileno (out), LOCK_EX) && ++retry <= 3)
delay (0.1);
fputs (t.compose ().c_str (), out);
@@ -395,17 +341,16 @@ 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;
if ((out = fopen (mCompletedFile.c_str (), "a")))
{
#ifdef HAVE_FLOCK
int retry = 0;
while (flock (fileno (out), LOCK_EX) && ++retry <= 3)
delay (0.25);
#endif
if (!mNoLock)
while (flock (fileno (out), LOCK_EX) && ++retry <= 3)
delay (0.1);
fputs (t.compose ().c_str (), out);
@@ -428,11 +373,10 @@ bool TDB::readLockedFile (
FILE* in;
if ((in = fopen (file.c_str (), "r")))
{
#ifdef HAVE_FLOCK
int retry = 0;
while (flock (fileno (in), LOCK_EX) && ++retry <= 3)
delay (0.25);
#endif
if (!mNoLock)
while (flock (fileno (in), LOCK_EX) && ++retry <= 3)
delay (0.1);
char line[T_LINE_MAX];
while (fgets (line, T_LINE_MAX, in))
@@ -454,6 +398,8 @@ bool TDB::readLockedFile (
}
////////////////////////////////////////////////////////////////////////////////
// Scans the pending tasks for any that are completed or deleted, and if so,
// moves them to the completed.data file. Returns a count of tasks moved.
int TDB::gc ()
{
int count = 0;
@@ -471,7 +417,9 @@ int TDB::gc ()
// Some tasks stay in the pending file.
if (it->getStatus () == T::pending ||
it->getStatus () == T::recurring)
{
pending.push_back (*it);
}
// Others are transferred to the completed file.
else
@@ -481,8 +429,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 +444,10 @@ int TDB::nextId ()
}
////////////////////////////////////////////////////////////////////////////////
void TDB::noLock ()
{
mNoLock = true;
}
////////////////////////////////////////////////////////////////////////////////

View File

@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2008, Paul Beckingham.
// Copyright 2006 - 2009, Paul Beckingham.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
@@ -45,25 +45,26 @@ 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 noLock ();
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;
private:
std::string mPendingFile;
std::string mCompletedFile;
std::string mLogFile;
int mId;
bool mNoLock;
};
#endif

View File

@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2008, Paul Beckingham.
// Copyright 2006 - 2009, Paul Beckingham.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
@@ -227,7 +227,7 @@ void Table::setRowBg (const int row, const Text::color c)
////////////////////////////////////////////////////////////////////////////////
void Table::addCell (const int row, const int col, const std::string& data)
{
int length = 0;
unsigned int length = 0;
if (mSuppressWS)
{
@@ -238,7 +238,19 @@ void Table::addCell (const int row, const int col, const std::string& data)
data2 = data;
clean (data2);
length = data2.length ();
// For multi-line cells, find the longest line.
if (data2.find ("\n") != std::string::npos)
{
length = 0;
std::vector <std::string> lines;
split (lines, data2, "\n");
for (unsigned int i = 0; i < lines.size (); ++i)
if (lines[i].length () > length)
length = lines[i].length ();
}
else
length = data2.length ();
mData.add (row, col, data2);
}
else
@@ -248,11 +260,22 @@ void Table::addCell (const int row, const int col, const std::string& data)
else
mData.add (row, col, data);
length = data.length ();
// For multi-line cells, find the longest line.
if (data.find ("\n") != std::string::npos)
{
length = 0;
std::vector <std::string> lines;
split (lines, data, "\n");
for (unsigned int i = 0; i < lines.size (); ++i)
if (lines[i].length () > length)
length = lines[i].length ();
}
else
length = data.length ();
}
// Automatically maintain max width.
mMaxDataWidth[col] = max (mMaxDataWidth[col], length);
mMaxDataWidth[col] = max (mMaxDataWidth[col], (int)length);
}
////////////////////////////////////////////////////////////////////////////////
@@ -508,9 +531,7 @@ void Table::calculateColumnWidths ()
}
else
{
// std::cout << "# insufficient room, considering only flexible columns." << std::endl;
// The fallback position is to assume no width was specificed, and just
// The fallback position is to assume no width was specified, and just
// calculate widths accordingly.
mTableWidth = 0;
calculateColumnWidths ();
@@ -736,34 +757,84 @@ int Table::columnCount ()
////////////////////////////////////////////////////////////////////////////////
// Removes extraneous output characters, such as:
// - spaces followed by a newline is collapsed to just a newline, if there is
// no Bg color.
// - removal of redundant color codes:
// ^[[31mName^[[0m ^[[31mValue^[[0m -> ^[[31mName Value^[[0m
//
// This method is a work in progress.
void Table::optimize (std::string& output)
void Table::optimize (std::string& output) const
{
/*
int start = output.length ();
*/
// \s\n -> \n
size_t i = 0;
while ((i = output.find (" \n")) != std::string::npos)
{
output = output.substr (0, i) +
output.substr (i + 1, std::string::npos);
}
// int start = output.length ();
/*
std::cout << int ((100 * (start - output.length ()) / start))
<< "%" << std::endl;
Well, how about that!
The benchmark.t unit test adds a 1000 tasks, fiddles with some of them, then
runs a series of reports. The results are timed, and look like this:
1000 tasks added in 3 seconds
600 tasks altered in 32 seconds
'task ls' in 26 seconds
'task list' in 17 seconds
'task list pri:H' in 19 seconds
'task list +tag' in 0 seconds
'task list project_A' in 0 seconds
'task long' in 29 seconds
'task completed' in 2 seconds
'task history' in 0 seconds
'task ghistory' in 0 seconds
This performance is terrible. To identify the worst offender, Various Timer
objects were added in Table::render, assuming that table sorting is the major
bottleneck. But no, it is Table::optimize that is the problem. After
commenting out this method, the results are now:
1000 tasks added in 3 seconds
600 tasks altered in 29 seconds
'task ls' in 0 seconds
'task list' in 0 seconds
'task list pri:H' in 1 seconds
'task list +tag' in 0 seconds
'task list project_A' in 0 seconds
'task long' in 0 seconds
'task completed' in 0 seconds
'task history' in 0 seconds
'task ghistory' in 0 seconds
Much better.
*/
// std::cout << int ((100 * (start - output.length ()) / start))
// << "%" << std::endl;
}
////////////////////////////////////////////////////////////////////////////////
// Combsort11, with O(n log n) average, O(n log n) worst case performance.
//
// function combsort11(array input)
// gap := input.size
//
// loop until gap <= 1 and swaps = 0
// if gap > 1
// gap := gap / 1.3
// if gap = 10 or gap = 9
// gap := 11
// end if
// end if
//
// i := 0
// swaps := 0
//
// loop until i + gap >= input.size
// if input[i] > input[i+gap]
// swap(input[i], input[i+gap])
// swaps := 1
// end if
// i := i + 1
// end loop
//
// end loop
// end function
#define SWAP \
{ \
int temp = order[r]; \
@@ -776,7 +847,7 @@ void Table::sort (std::vector <int>& order)
int gap = order.size ();
int swaps = 1;
while (gap > 1 || swaps != 0)
while (gap > 1 || swaps > 0)
{
if (gap > 1)
{
@@ -797,10 +868,28 @@ void Table::sort (std::vector <int>& order)
Grid::Cell* left = mData.byRow (order[r], mSortColumns[c]);
Grid::Cell* right = mData.byRow (order[r + gap], mSortColumns[c]);
if (left == NULL && right != NULL)
SWAP
if (left && right && *left != *right)
// Data takes precedence over missing data.
if (left == NULL && right != NULL)
{
SWAP
break;
}
// No data - try comparing the next column.
else if (left == NULL && right == NULL)
{
keepScanning = true;
}
// Identical data - try comparing the next column.
else if (left && right && *left == *right)
{
keepScanning = true;
}
// Differing data - do a proper comparison.
else if (left && right && *left != *right)
{
switch (mSortOrder[mSortColumns[c]])
{
@@ -861,24 +950,38 @@ void Table::sort (std::vector <int>& order)
break;
case ascendingPriority:
if (((std::string)*left == "" && (std::string)*right != "") ||
((std::string)*left == "M" && (std::string)*right == "L") ||
((std::string)*left == "H" && ((std::string)*right == "L" || (std::string)*right == "M")))
if (((std::string)*left == "" && (std::string)*right != "") ||
((std::string)*left == "M" && (std::string)*right == "L") ||
((std::string)*left == "H" && ((std::string)*right == "L" || (std::string)*right == "M")))
SWAP
break;
case descendingPriority:
if (((std::string)*left == "" && (std::string)*right != "") ||
if (((std::string)*left == "" && (std::string)*right != "") ||
((std::string)*left == "L" && ((std::string)*right == "M" || (std::string)*right == "H")) ||
((std::string)*left == "M" && (std::string)*right == "H"))
((std::string)*left == "M" && (std::string)*right == "H"))
SWAP
break;
case ascendingPeriod:
if ((std::string)*left == "" && (std::string)*right != "")
break;
else if ((std::string)*left != "" && (std::string)*right == "")
SWAP
else if (convertDuration ((std::string)*left) > convertDuration ((std::string)*right))
SWAP
break;
case descendingPeriod:
if ((std::string)*left != "" && (std::string)*right == "")
break;
else if ((std::string)*left == "" && (std::string)*right != "")
SWAP
else if (convertDuration ((std::string)*left) < convertDuration ((std::string)*right))
SWAP
break;
}
break;
}
else
keepScanning = true;
}
++r;
@@ -912,7 +1015,7 @@ void Table::clean (std::string& value)
}
////////////////////////////////////////////////////////////////////////////////
const std::string Table::render ()
const std::string Table::render (int maximum /* = 0 */)
{
calculateColumnWidths ();
@@ -946,8 +1049,14 @@ const std::string Table::render ()
if (mSortColumns.size ())
sort (order);
// If a non-zero maximum is specified, then it limits the number of rows of
// the table that are rendered.
int limit = mRows;
if (maximum != 0)
limit = min (maximum, mRows);
// Print all rows.
for (int row = 0; row < mRows; ++row)
for (int row = 0; row < limit; ++row)
{
std::vector <std::vector <std::string> > columns;
std::vector <std::string> blanks;
@@ -981,15 +1090,19 @@ const std::string Table::render ()
else
output += blanks[col];
// Trim right.
output.erase (output.find_last_not_of (" ") + 1);
output += "\n";
}
}
else
{
// Trim right.
output.erase (output.find_last_not_of (" ") + 1);
output += "\n";
}
}
// Eliminate redundant color codes.
optimize (output);
return output;
}

View File

@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2008, Paul Beckingham.
// Copyright 2006 - 2009, Paul Beckingham.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
@@ -37,9 +37,16 @@ class Table
{
public:
enum just {left, center, right};
enum order {ascendingNumeric, ascendingCharacter, ascendingPriority,
ascendingDate, descendingNumeric, descendingCharacter,
descendingPriority, descendingDate};
enum order {ascendingNumeric,
ascendingCharacter,
ascendingPriority,
ascendingDate,
ascendingPeriod,
descendingNumeric,
descendingCharacter,
descendingPriority,
descendingDate,
descendingPeriod};
enum sizing {minimum = -1, flexible = 0};
Table ();
@@ -84,7 +91,7 @@ public:
int rowCount ();
int columnCount ();
const std::string render ();
const std::string render (int maximum = 0);
private:
std::string getCell (const int, const int);
@@ -101,9 +108,9 @@ private:
const std::string formatHeader (const int, const int, const int);
const std::string formatHeaderDashedUnderline (const int, const int, const int);
void formatCell (const int, const int, const int, const int, std::vector <std::string>&, std::string&);
void optimize (std::string&);
void sort (std::vector <int>&);
void clean (std::string&);
void optimize (std::string&) const;
private:
std::vector <std::string> mColumns;

56
src/Timer.cpp Normal file
View File

@@ -0,0 +1,56 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2009, Paul Beckingham.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <iomanip>
#include <Timer.h>
////////////////////////////////////////////////////////////////////////////////
// Timer starts when the object is constructed.
Timer::Timer (const std::string& description)
: mDescription (description)
{
::gettimeofday (&mStart, NULL);
}
////////////////////////////////////////////////////////////////////////////////
// Timer stops when the object is desctructed.
Timer::~Timer ()
{
struct timeval end;
::gettimeofday (&end, NULL);
std::cout << "Timer "
<< mDescription
<< " "
<< std::setprecision (6)
<< ((end.tv_sec - mStart.tv_sec) +
((end.tv_usec - mStart.tv_usec ) / 1000000.0))
<< std::endl;
}
////////////////////////////////////////////////////////////////////////////////

46
src/Timer.h Normal file
View File

@@ -0,0 +1,46 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2009, Paul Beckingham.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_TIMER
#define INCLUDED_TIMER
#include <string>
#include <sys/time.h>
class Timer
{
public:
Timer (const std::string&);
~Timer ();
private:
std::string mDescription;
struct timeval mStart;
};
#endif
////////////////////////////////////////////////////////////////////////////////

View File

@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2008, Paul Beckingham.
// Copyright 2006 - 2009, Paul Beckingham.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under

View File

@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2008, Paul Beckingham.
// Copyright 2006 - 2009, Paul Beckingham.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under

File diff suppressed because it is too large Load Diff

1203
src/import.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2008, Paul Beckingham.
// Copyright 2006 - 2009, Paul Beckingham.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
@@ -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",
@@ -118,6 +120,8 @@ static const char* commands[] =
{
"active",
"add",
"append",
"annotate",
"calendar",
"colors",
"completed",
@@ -127,26 +131,25 @@ static const char* commands[] =
"help",
"history",
"ghistory",
"import",
"info",
"list",
"long",
"ls",
"newest",
"next",
"oldest",
"overdue",
"projects",
"start",
"stats",
"stop",
"summary",
"tags",
"undelete",
"undo",
"usage",
"version",
"",
};
static std::vector <std::string> customReports;
////////////////////////////////////////////////////////////////////////////////
void guess (const std::string& type, const char** list, std::string& candidate)
{
std::vector <std::string> options;
@@ -159,7 +162,35 @@ void guess (const std::string& type, const char** list, std::string& candidate)
candidate = matches[0];
else if (0 == matches.size ())
// throw std::string ("Unrecognized ") + type + " '" + candidate + "'";
candidate = "";
else
{
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;
}
}
////////////////////////////////////////////////////////////////////////////////
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 ())
candidate = "";
else
@@ -190,7 +221,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;
}
@@ -200,7 +235,7 @@ bool validDate (std::string& date, Config& conf)
{
Date test (date, conf.get ("dateformat", "m/d/Y"));
char epoch[12];
char epoch[16];
sprintf (epoch, "%d", (int) test.toEpoch ());
date = epoch;
@@ -284,10 +319,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;
}
////////////////////////////////////////////////////////////////////////////////
@@ -296,7 +333,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;
@@ -306,7 +348,8 @@ static bool validCommand (std::string& input)
static bool validSubstitution (
std::string& input,
std::string& from,
std::string& to)
std::string& to,
bool& global)
{
size_t first = input.find ('/');
if (first != std::string::npos)
@@ -320,10 +363,17 @@ static bool validSubstitution (
if (first == 0 &&
first < second &&
second < third &&
third == input.length () - 1)
(third == input.length () - 1 ||
third == input.length () - 2))
{
from = input.substr (first + 1, second - first - 1);
to = input.substr (second + 1, third - second - 1);
global = false;
if (third == input.length () - 2 &&
input.find ('g', third + 1) != std::string::npos)
global = true;
return true;
}
}
@@ -369,6 +419,7 @@ void parse (
size_t colon; // Pointer to colon in argument.
std::string from;
std::string to;
bool global;
// An id is the first argument found that contains all digits.
if (lowerCase (command) != "add" && // "add" doesn't require an ID
@@ -401,13 +452,17 @@ void parse (
// If it is not a valid attribute, then allow the argument as part of
// the description.
else
{
if (descCandidate.length ())
descCandidate += " ";
descCandidate += arg;
}
}
// Substitution of description text.
else if (validSubstitution (arg, from, to))
else if (validSubstitution (arg, from, to, global))
{
task.setSubstitution (from, to);
task.setSubstitution (from, to, global);
}
// Command.
@@ -417,26 +472,62 @@ void parse (
if (isCommand (l) && validCommand (l))
command = l;
else
{
if (descCandidate.length ())
descCandidate += " ";
descCandidate += arg;
}
}
// Anything else is just considered description.
else
descCandidate += std::string (arg) + " ";
{
if (descCandidate.length ())
descCandidate += " ";
descCandidate += arg;
}
}
}
if (task.getAttribute ("recur") != "" &&
task.getAttribute ("due") == "")
throw std::string ("You cannot specify a recurring task without a due date.");
if (task.getAttribute ("until") != "" &&
task.getAttribute ("recur") == "")
throw std::string ("You cannot specify an until date for a non-recurring task.");
if (validDescription (descCandidate))
task.setDescription (descCandidate);
}
////////////////////////////////////////////////////////////////////////////////
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);
std::string::size_type 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;
}
////////////////////////////////////////////////////////////////////////////////
void allCustomReports (std::vector <std::string>& all)
{
all = customReports;
}
////////////////////////////////////////////////////////////////////////////////

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2008, Paul Beckingham.
// Copyright 2006 - 2009, Paul Beckingham.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
@@ -80,10 +80,14 @@ void initializeColorRules (Config& conf)
}
////////////////////////////////////////////////////////////////////////////////
void autoColorize (T& task, Text::color& fg, Text::color& bg)
void autoColorize (
T& task,
Text::color& fg,
Text::color& bg,
Config& conf)
{
// Note: fg, bg already contain colors specifically assigned via command.
// Note: These rules form a hierarchy - the last rule is king.
// Note: These rules form a hierarchy - the last rule is King.
// Colorization of the tagged.
if (gsFg["color.tagged"] != Text::nocolor ||
@@ -153,29 +157,6 @@ void autoColorize (T& task, Text::color& fg, Text::color& bg)
}
}
// Colorization of the due and overdue.
std::string due = task.getAttribute ("due");
if (due != "")
{
Date dueDate (::atoi (due.c_str ()));
Date now;
Date then (now + 7 * 86400);
// Overdue
if (dueDate < now)
{
fg = gsFg["color.overdue"];
bg = gsBg["color.overdue"];
}
// Imminent
else if (dueDate < then)
{
fg = gsFg["color.due"];
bg = gsBg["color.due"];
}
}
// Colorization by tag value.
std::map <std::string, Text::color>::iterator it;
for (it = gsFg.begin (); it != gsFg.end (); ++it)
@@ -219,6 +200,40 @@ void autoColorize (T& task, Text::color& fg, Text::color& bg)
}
}
}
// Colorization of the due and overdue.
std::string due = task.getAttribute ("due");
if (due != "")
{
Date dueDate (::atoi (due.c_str ()));
Date now;
Date then (now + conf.get ("due", 7) * 86400);
// Overdue
if (dueDate < now)
{
fg = gsFg["color.overdue"];
bg = gsBg["color.overdue"];
}
// Imminent
else if (dueDate < then)
{
fg = gsFg["color.due"];
bg = gsBg["color.due"];
}
}
// Colorization of the recurring.
if (gsFg["color.recurring"] != Text::nocolor ||
gsBg["color.recurring"] != Text::nocolor)
{
if (task.getAttribute ("recur") != "")
{
fg = gsFg["color.recurring"];
bg = gsBg["color.recurring"];
}
}
}
////////////////////////////////////////////////////////////////////////////////

View File

@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2008, Paul Beckingham.
// Copyright 2006 - 2009, Paul Beckingham.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
@@ -27,6 +27,7 @@
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
@@ -47,10 +48,11 @@
#endif
////////////////////////////////////////////////////////////////////////////////
static void shortUsage (Config& conf)
static std::string shortUsage (Config& conf)
{
std::stringstream out;
Table table;
int width = conf.get ("defaultwidth", 80);
int width = conf.get ("defaultwidth", (int) 80);
#ifdef HAVE_LIBNCURSES
if (conf.get ("curses", true))
{
@@ -83,16 +85,12 @@ static void shortUsage (Config& conf)
table.addCell (row, 2, "Adds a new task");
row = table.addRow ();
table.addCell (row, 1, "task list [tags] [attrs] desc...");
table.addCell (row, 2, "Lists all tasks matching the specified criteria");
table.addCell (row, 1, "task append [tags] [attrs] desc...");
table.addCell (row, 2, "Appends more description to an existing task");
row = table.addRow ();
table.addCell (row, 1, "task long [tags] [attrs] desc...");
table.addCell (row, 2, "Lists all task, all data, matching the specified criteria");
row = table.addRow ();
table.addCell (row, 1, "task ls [tags] [attrs] desc...");
table.addCell (row, 2, "Minimal listing of all tasks matching the specified criteria");
table.addCell (row, 1, "task annotate ID desc...");
table.addCell (row, 2, "Adds an annotation to an existing task");
row = table.addRow ();
table.addCell (row, 1, "task completed [tags] [attrs] desc...");
@@ -120,7 +118,11 @@ 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");
@@ -166,21 +168,13 @@ static void shortUsage (Config& conf)
table.addCell (row, 1, "task overdue");
table.addCell (row, 2, "Shows all incomplete tasks that are beyond their due date");
row = table.addRow ();
table.addCell (row, 1, "task oldest");
table.addCell (row, 2, "Shows the oldest tasks");
row = table.addRow ();
table.addCell (row, 1, "task newest");
table.addCell (row, 2, "Shows the newest tasks");
row = table.addRow ();
table.addCell (row, 1, "task stats");
table.addCell (row, 2, "Shows task database statistics");
row = table.addRow ();
table.addCell (row, 1, "task usage");
table.addCell (row, 2, "Shows task command usage frequency");
table.addCell (row, 1, "task import");
table.addCell (row, 2, "Imports tasks from a variety of formats");
row = table.addRow ();
table.addCell (row, 1, "task export");
@@ -198,46 +192,65 @@ static void shortUsage (Config& conf)
table.addCell (row, 1, "task help");
table.addCell (row, 2, "Shows the long usage text");
std::cout << table.render ()
<< std::endl
<< "See http://www.beckingham.net/task.html for the latest releases and a full tutorial."
<< std::endl
<< std::endl;
// Add custom reports here...
std::vector <std::string> all;
allCustomReports (all);
foreach (report, all)
{
std::string command = std::string ("task ") + *report + std::string (" [tags] [attrs] desc...");
std::string description = conf.get (
std::string ("report.") + *report + ".description", std::string ("(missing description)"));
row = table.addRow ();
table.addCell (row, 1, command);
table.addCell (row, 2, description);
}
out << table.render ()
<< std::endl
<< "See http://www.beckingham.net/task.html for the latest releases and a "
<< "full tutorial. New releases containing fixes and enhancements are "
<< "made frequently."
<< std::endl
<< std::endl;
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
static void longUsage (Config& conf)
static std::string longUsage (Config& conf)
{
shortUsage (conf);
std::stringstream out;
out << shortUsage (conf)
<< "ID is the numeric identifier displayed by the 'task list' command." << "\n"
<< "\n"
<< "Tags are arbitrary words, any quantity:" << "\n"
<< " +tag The + means add the tag" << "\n"
<< " -tag The - means remove the tag" << "\n"
<< "\n"
<< "Attributes are:" << "\n"
<< " project: Project name" << "\n"
<< " priority: Priority" << "\n"
<< " due: Due date" << "\n"
<< " recur: Recurrence frequency" << "\n"
<< " until: Recurrence end date" << "\n"
<< " fg: Foreground color" << "\n"
<< " bg: Background color" << "\n"
<< " rc: Alternate .taskrc file" << "\n"
<< "\n"
<< "Any command or attribute name may be abbreviated if still unique:" << "\n"
<< " task list project:Home" << "\n"
<< " task li pro:Home" << "\n"
<< "\n"
<< "Some task descriptions need to be escaped because of the shell:" << "\n"
<< " task add \"quoted ' quote\"" << "\n"
<< " task add escaped \\' quote" << "\n"
<< "\n"
<< "Many characters have special meaning to the shell, including:" << "\n"
<< " $ ! ' \" ( ) ; \\ ` * ? { } [ ] < > | & % # ~" << "\n"
<< std::endl;
std::cout
<< "ID is the numeric identifier displayed by the 'task list' command" << "\n"
<< "\n"
<< "Tags are arbitrary words, any quantity:" << "\n"
<< " +tag The + means add the tag" << "\n"
<< " -tag The - means remove the tag" << "\n"
<< "\n"
<< "Attributes are:" << "\n"
<< " project: Project name" << "\n"
<< " priority: Priority" << "\n"
<< " due: Due date" << "\n"
<< " recur: Recurrence frequency" << "\n"
<< " until: Recurrence end date" << "\n"
<< " fg: Foreground color" << "\n"
<< " bg: Background color" << "\n"
<< " rc: Alternate .taskrc file" << "\n"
<< "\n"
<< "Any command or attribute name may be abbreviated if still unique:" << "\n"
<< " task list project:Home" << "\n"
<< " task li pro:Home" << "\n"
<< "\n"
<< "Some task descriptions need to be escaped because of the shell:" << "\n"
<< " task add \"quoted ' quote\"" << "\n"
<< " task add escaped \\' quote" << "\n"
<< "\n"
<< "Many characters have special meaning to the shell, including:" << "\n"
<< " $ ! ' \" ( ) ; \\ ` * ? { } [ ] < > | & % # ~" << "\n"
<< std::endl;
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
@@ -269,9 +282,6 @@ void loadConfFile (int argc, char** argv, Config& conf)
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{
// TODO Find out what this is, and either promote it to live code, or remove it.
// std::set_terminate (__gnu_cxx::__verbose_terminate_handler);
// Set up randomness.
#ifdef HAVE_SRANDOM
srandom (time (NULL));
@@ -290,78 +300,44 @@ int main (int argc, char** argv)
if (!isatty (fileno (stdout)))
{
conf.set ("curses", "off");
conf.set ("color", "off");
if (! conf.get (std::string ("_forcecolor"), false))
conf.set ("color", "off");
}
TDB tdb;
tdb.dataDirectory (expandPath (conf.get ("data.location")));
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);
// Allow user override of file locking. Solaris/NFS machines may want this.
if (! conf.get ("locking", true))
tdb.noLock ();
// If argc == 1 and the default.command configuration variable is set,
// then use that, otherwise stick with argc/argv.
std::vector <std::string> args;
std::string defaultCommand = conf.get ("default.command");
if (argc == 1 && defaultCommand != "")
// Check for silly shadow file settings.
std::string shadowFile = expandPath (conf.get ("shadow.file"));
if (shadowFile != "")
{
// Stuff the command line.
split (args, defaultCommand, ' ');
std::cout << "[task " << defaultCommand << "]" << std::endl;
}
else
{
// Parse the command line.
for (int i = 1; i < argc; ++i)
args.push_back (argv[i]);
if (shadowFile == dataLocation + "/pending.data")
throw std::string ("Configuration variable 'shadow.file' is set to "
"overwrite your pending tasks. Please change it.");
if (shadowFile == dataLocation + "/completed.data")
throw std::string ("Configuration variable 'shadow.file' is set to "
"overwrite your completed tasks. Please change it.");
}
std::string command;
T task;
parse (args, command, task, conf);
if (command == "add") handleAdd (tdb, task, conf);
else if (command == "projects") handleProjects (tdb, task, conf);
else if (command == "tags") handleTags (tdb, task, conf);
else if (command == "list") handleList (tdb, task, conf);
else if (command == "info") handleInfo (tdb, task, conf);
else if (command == "undelete") handleUndelete (tdb, task, conf);
else if (command == "long") handleLongList (tdb, task, conf);
else if (command == "ls") handleSmallList (tdb, task, conf);
else if (command == "colors") handleColor ( conf);
else if (command == "completed") handleCompleted (tdb, task, conf);
else if (command == "delete") handleDelete (tdb, task, conf);
else if (command == "start") handleStart (tdb, task, conf);
else if (command == "done") handleDone (tdb, task, conf);
else if (command == "undo") handleUndo (tdb, task, conf);
else if (command == "export") handleExport (tdb, task, conf);
else if (command == "version") handleVersion ( conf);
else if (command == "summary") handleReportSummary (tdb, task, conf);
else if (command == "next") handleReportNext (tdb, task, conf);
else if (command == "history") handleReportHistory (tdb, task, conf);
else if (command == "ghistory") handleReportGHistory (tdb, task, conf);
else if (command == "calendar") handleReportCalendar (tdb, task, conf);
else if (command == "active") handleReportActive (tdb, task, conf);
else if (command == "overdue") handleReportOverdue (tdb, task, conf);
else if (command == "oldest") handleReportOldest (tdb, task, conf);
else if (command == "newest") handleReportNewest (tdb, task, conf);
else if (command == "stats") handleReportStats (tdb, task, conf);
else if (command == "usage") handleReportUsage (tdb, task, conf);
else if (command == "" && task.getId ()) handleModify (tdb, task, conf);
else if (command == "help") longUsage (conf);
else shortUsage (conf);
std::cout << runTaskCommand (argc, argv, tdb, conf);
}
catch (std::string& error)
{
std::cout << error << std::endl;
std::cerr << error << std::endl;
return -1;
}
catch (...)
{
std::cout << "Unknown error." << std::endl;
std::cerr << "Unknown error." << std::endl;
return -2;
}
@@ -374,18 +350,56 @@ void nag (TDB& tdb, T& task, Config& conf)
std::string nagMessage = conf.get ("nag", std::string (""));
if (nagMessage != "")
{
// Load all pending.
// Load all pending tasks.
std::vector <T> pending;
tdb.allPendingT (pending);
// Restrict to matching subset.
std::vector <int> matching;
gatherNextTasks (tdb, task, conf, pending, matching);
// Counters.
int overdue = 0;
int high = 0;
int medium = 0;
int low = 0;
bool isOverdue = false;
char pri = ' ';
foreach (i, matching)
if (pending[*i].getId () == task.getId ())
return;
// Scan all pending tasks.
foreach (t, pending)
{
if (t->getId () == task.getId ())
{
if (getDueState (t->getAttribute ("due")) == 2)
isOverdue = true;
std::string priority = t->getAttribute ("priority");
if (priority.length ())
pri = priority[0];
}
else if (t->getStatus () == T::pending)
{
if (getDueState (t->getAttribute ("due")) == 2)
overdue++;
std::string priority = t->getAttribute ("priority");
if (priority.length ())
{
switch (priority[0])
{
case 'H': high++; break;
case 'M': medium++; break;
case 'L': low++; break;
}
}
}
}
// General form is "if there are no more deserving tasks", suppress the nag.
if (isOverdue ) return;
if (pri == 'H' && !overdue ) return;
if (pri == 'M' && !overdue && !high ) return;
if (pri == 'L' && !overdue && !high && !medium ) return;
if (pri == ' ' && !overdue && !high && !medium && !low) return;
// All the excuses are made, all that remains is to nag the user.
std::cout << nagMessage << std::endl;
}
}
@@ -400,12 +414,15 @@ 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;
Date midnight (rightNow.month (), rightNow.day (), rightNow.year ());
if (dt < midnight)
return 2;
Date nextweek = now + 7 * 86400;
Date nextweek = midnight + 7 * 86400;
if (dt < nextweek)
return 1;
}
@@ -553,10 +570,21 @@ 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);
}
if (period == "weekdays")
{
int dow = current.dayOfWeek ();
int days;
if (dow == 5) days = 3;
else if (dow == 6) days = 2;
else days = 1;
return current + (days * 86400);
}
if (isdigit (period[0]) && period[period.length () - 1] == 'm')
{
std::string numeric = period.substr (0, period.length () - 1);
@@ -572,7 +600,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 +615,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);
}
@@ -607,7 +633,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);
}
@@ -623,7 +648,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);
}
@@ -639,7 +663,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);
}
@@ -648,7 +671,19 @@ 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);
}
else if (period == "annual" ||
period == "yearly")
{
y += 1;
// If the due data just happens to be 2/29 in a leap year, then simply
// incrementing y is going to create an invalid date.
if (m == 2 && d == 29)
d = 28;
return Date (m, d, y);
}
@@ -666,7 +701,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;
@@ -674,11 +708,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) ? '-'
@@ -686,15 +717,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 += "?";
@@ -712,3 +739,146 @@ void updateRecurrenceMask (
}
////////////////////////////////////////////////////////////////////////////////
void updateShadowFile (TDB& tdb, Config& conf)
{
try
{
// Determine if shadow file is enabled.
std::string shadowFile = expandPath (conf.get ("shadow.file"));
if (shadowFile != "")
{
std::string oldCurses = conf.get ("curses");
std::string oldColor = conf.get ("color");
conf.set ("curses", "off");
conf.set ("color", "off");
// Run report. Use shadow.command, using default.command as a fallback
// with "list" as a default.
std::string command = conf.get ("shadow.command",
conf.get ("default.command", "list"));
std::vector <std::string> args;
split (args, command, ' ');
std::string result = runTaskCommand (args, tdb, conf);
std::ofstream out (shadowFile.c_str ());
if (out.good ())
{
out << result;
out.close ();
}
else
throw std::string ("Could not write file '") + shadowFile + "'";
conf.set ("curses", oldCurses);
conf.set ("color", oldColor);
}
// Optionally display a notification that the shadow file was updated.
if (conf.get (std::string ("shadow.notify"), false))
std::cout << "[Shadow file '" << shadowFile << "' updated]" << std::endl;
}
catch (std::string& error)
{
std::cerr << error << std::endl;
}
catch (...)
{
std::cerr << "Unknown error." << std::endl;
}
}
////////////////////////////////////////////////////////////////////////////////
std::string runTaskCommand (
int argc,
char** argv,
TDB& tdb,
Config& conf,
bool gc /* = true */,
bool shadow /* = true */)
{
std::vector <std::string> args;
for (int i = 1; i < argc; ++i)
args.push_back (argv[i]);
return runTaskCommand (args, tdb, conf, gc, shadow);
}
////////////////////////////////////////////////////////////////////////////////
std::string runTaskCommand (
std::vector <std::string>& args,
TDB& tdb,
Config& conf,
bool gc /* = false */,
bool shadow /* = false */)
{
// If argc == 1 and the default.command configuration variable is set,
// then use that, otherwise stick with argc/argv.
std::string defaultCommand = conf.get ("default.command");
if ((args.size () == 0 ||
(args.size () == 1 && args[0].substr (0, 3) == "rc:")) &&
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);
bool gcMod = false; // Change occurred by way of gc.
bool cmdMod = false; // Change occurred by way of command type.
std::string out;
// Read-only commands with no side effects.
if (command == "export") { out = handleExport (tdb, task, conf); }
else if (command == "projects") { out = handleProjects (tdb, task, conf); }
else if (command == "tags") { out = handleTags (tdb, task, conf); }
else if (command == "info") { out = handleInfo (tdb, task, conf); }
else if (command == "stats") { out = handleReportStats (tdb, task, conf); }
else if (command == "history") { out = handleReportHistory (tdb, task, conf); }
else if (command == "ghistory") { out = handleReportGHistory (tdb, task, conf); }
else if (command == "calendar") { out = handleReportCalendar (tdb, task, conf); }
else if (command == "summary") { out = handleReportSummary (tdb, task, conf); }
else if (command == "colors") { out = handleColor ( conf); }
else if (command == "version") { out = handleVersion ( conf); }
else if (command == "help") { out = longUsage ( conf); }
// Commands that cause updates.
else if (command == "" && task.getId ()) { cmdMod = true; out = handleModify (tdb, task, conf); }
else if (command == "add") { cmdMod = true; out = handleAdd (tdb, task, conf); }
else if (command == "append") { cmdMod = true; out = handleAppend (tdb, task, conf); }
else if (command == "annotate") { cmdMod = true; out = handleAnnotate (tdb, task, conf); }
else if (command == "done") { cmdMod = true; out = handleDone (tdb, task, conf); }
else if (command == "undelete") { cmdMod = true; out = handleUndelete (tdb, task, conf); }
else if (command == "delete") { cmdMod = true; out = handleDelete (tdb, task, conf); }
else if (command == "start") { cmdMod = true; out = handleStart (tdb, task, conf); }
else if (command == "stop") { cmdMod = true; out = handleStop (tdb, task, conf); }
else if (command == "undo") { cmdMod = true; out = handleUndo (tdb, task, conf); }
else if (command == "import") { cmdMod = true; out = handleImport (tdb, task, conf); }
// Command that display IDs and therefore need TDB::gc first.
else if (command == "completed") { if (gc) gcMod = tdb.gc (); out = handleCompleted (tdb, task, conf); }
else if (command == "next") { if (gc) gcMod = tdb.gc (); out = handleReportNext (tdb, task, conf); }
else if (command == "active") { if (gc) gcMod = tdb.gc (); out = handleReportActive (tdb, task, conf); }
else if (command == "overdue") { if (gc) gcMod = tdb.gc (); out = handleReportOverdue (tdb, task, conf); }
else if (isCustomReport (command)) { if (gc) gcMod = tdb.gc (); out = handleCustomReport (tdb, task, conf, command); }
// If the command is not recognized, display usage.
else { out = shortUsage (conf); }
// Only update the shadow file if such an update was not suppressed (shadow),
// and if an actual change occurred (gcMod || cmdMod).
if (shadow && (gcMod || cmdMod))
updateShadowFile (tdb, conf);
return out;
}
////////////////////////////////////////////////////////////////////////////////

View File

@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2008, Paul Beckingham.
// Copyright 2006 - 2009, Paul Beckingham.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
@@ -57,6 +57,9 @@ for (typeof (c) *foreach_p = & (c); \
void parse (std::vector <std::string>&, std::string&, T&, Config&);
bool validPriority (const std::string&);
bool validDate (std::string&, Config&);
void loadCustomReports (Config&);
bool isCustomReport (const std::string&);
void allCustomReports (std::vector <std::string>&);
// task.cpp
void gatherNextTasks (const TDB&, T&, Config&, std::vector <T>&, std::vector <int>&);
@@ -66,47 +69,51 @@ 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, bool shadow = true);
std::string runTaskCommand (std::vector <std::string>&, TDB&, Config&, bool gc = false, bool shadow = 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 handleExport (TDB&, T&, Config&);
void handleDelete (TDB&, T&, Config&);
void handleStart (TDB&, T&, Config&);
void handleDone (TDB&, T&, Config&);
void handleUndo (TDB&, T&, Config&);
void handleModify (TDB&, T&, Config&);
void handleColor (Config&);
std::string handleAdd (TDB&, T&, Config&);
std::string handleAppend (TDB&, T&, Config&);
std::string handleExport (TDB&, T&, Config&);
std::string handleDone (TDB&, T&, Config&);
std::string handleModify (TDB&, T&, Config&);
std::string handleProjects (TDB&, T&, Config&);
std::string handleTags (TDB&, T&, Config&);
std::string handleUndelete (TDB&, T&, Config&);
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&);
std::string handleAnnotate (TDB&, T&, Config&);
T findT (int, const std::vector <T>&);
// 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 handleInfo (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&);
// util.cpp
bool confirm (const std::string&);
std::string handleCustomReport (TDB&, T&, Config&, const std::string&);
void validReportColumns (const std::vector <std::string>&);
void validSortColumns (const std::vector <std::string>&, const std::vector <std::string>&);
// text.cpp
void wrapText (std::vector <std::string>&, const std::string&, const int);
std::string trimLeft (const std::string& in, const std::string& t = " ");
std::string trimRight (const std::string& in, const std::string& t = " ");
std::string trim (const std::string& in, const std::string& t = " ");
void extractParagraphs (const std::string&, std::vector<std::string>&);
std::string unquoteText (const std::string&);
void extractLine (std::string&, std::string&, int);
void split (std::vector<std::string>&, const std::string&, const char);
void split (std::vector<std::string>&, const std::string&, const std::string&);
@@ -114,17 +121,34 @@ void join (std::string&, const std::string&, const std::vector<std::string>&);
std::string commify (const std::string&);
std::string lowerCase (const std::string&);
std::string upperCase (const std::string&);
const char* optionalBlankLine (Config&);
// util.cpp
bool confirm (const std::string&);
void delay (float);
int autoComplete (const std::string&, const std::vector<std::string>&, std::vector<std::string>&);
void formatTimeDeltaDays (std::string&, time_t);
std::string formatSeconds (time_t);
int autoComplete (const std::string&, const std::vector<std::string>&, std::vector<std::string>&);
const std::string uuid ();
const char* optionalBlankLine (Config&);
int convertDuration (std::string&);
int convertDuration (const std::string&);
std::string expandPath (const std::string&);
#ifdef SOLARIS
#define LOCK_SH 1
#define LOCK_EX 2
#define LOCK_NB 4
#define LOCK_UN 8
int flock (int, int);
#endif
bool slurp (const std::string&, std::vector <std::string>&, bool trimLines = false);
// rules.cpp
void initializeColorRules (Config&);
void autoColorize (T&, Text::color&, Text::color&);
void autoColorize (T&, Text::color&, Text::color&, Config&);
// import.cpp
std::string handleImport (TDB&, T&, Config&);
////////////////////////////////////////////////////////////////////////////////

View File

@@ -1,7 +1,7 @@
t.t
t.benchmark.t
tdb.t
date.t
duration.t
pending.data
completed.data
text.t
autocomplete.t

View File

@@ -1,4 +1,4 @@
PROJECT = t.t tdb.t date.t duration.t
PROJECT = t.t tdb.t date.t duration.t t.benchmark.t text.t autocomplete.t
CFLAGS = -I. -I.. -Wall -pedantic -ggdb3 -fno-rtti
LFLAGS = -L/usr/local/lib
OBJECTS = ../TDB.o ../T.o ../parse.o ../text.o ../Date.o ../util.o ../Config.o
@@ -29,3 +29,12 @@ date.t: date.t.o $(OBJECTS) test.o
duration.t: duration.t.o $(OBJECTS) test.o
g++ duration.t.o $(OBJECTS) test.o $(LFLAGS) -o duration.t
t.benchmark.t: t.benchmark.t.o $(OBJECTS) test.o
g++ t.benchmark.t.o $(OBJECTS) test.o $(LFLAGS) -o t.benchmark.t
text.t: text.t.o $(OBJECTS) test.o
g++ text.t.o $(OBJECTS) test.o $(LFLAGS) -o text.t
autocomplete.t: autocomplete.t.o $(OBJECTS) test.o
g++ autocomplete.t.o $(OBJECTS) test.o $(LFLAGS) -o autocomplete.t

99
src/tests/abbreviation.t Executable file
View File

@@ -0,0 +1,99 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 22;
# Create the rc file.
if (open my $fh, '>', 'abbrev.rc')
{
print $fh "data.location=.\n";
close $fh;
ok (-r 'abbrev.rc', 'Created abbrev.rc');
}
# Test the priority attribute abbrevations.
qx{../task rc:abbrev.rc add priority:H with};
qx{../task rc:abbrev.rc add without};
my $output = qx{../task rc:abbrev.rc list priority:H};
like ($output, qr/\bwith\b/, 'priority:H with');
unlike ($output, qr/\bwithout\b/, 'priority:H without');
$output = qx{../task rc:abbrev.rc list priorit:H};
like ($output, qr/\bwith\b/, 'priorit:H with');
unlike ($output, qr/\bwithout\b/, 'priorit:H without');
$output = qx{../task rc:abbrev.rc list priori:H};
like ($output, qr/\bwith\b/, 'priori:H with');
unlike ($output, qr/\bwithout\b/, 'priori:H without');
$output = qx{../task rc:abbrev.rc list prior:H};
like ($output, qr/\bwith\b/, 'prior:H with');
unlike ($output, qr/\bwithout\b/, 'prior:H without');
$output = qx{../task rc:abbrev.rc list prio:H};
like ($output, qr/\bwith\b/, 'prio:H with');
unlike ($output, qr/\bwithout\b/, 'prio:H without');
$output = qx{../task rc:abbrev.rc list pri:H};
like ($output, qr/\bwith\b/, 'pri:H with');
unlike ($output, qr/\bwithout\b/, 'pri:H without');
# Test the version command abbreviations.
$output = qx{../task rc:abbrev.rc version};
like ($output, qr/ABSOLUTELY NO WARRANTY/, 'version');
$output = qx{../task rc:abbrev.rc versio};
like ($output, qr/ABSOLUTELY NO WARRANTY/, 'versio');
$output = qx{../task rc:abbrev.rc versi};
like ($output, qr/ABSOLUTELY NO WARRANTY/, 'versi');
$output = qx{../task rc:abbrev.rc vers};
like ($output, qr/ABSOLUTELY NO WARRANTY/, 'vers');
$output = qx{../task rc:abbrev.rc ver};
like ($output, qr/ABSOLUTELY NO WARRANTY/, 'ver');
$output = qx{../task rc:abbrev.rc ve};
like ($output, qr/ABSOLUTELY NO WARRANTY/, 've');
$output = qx{../task rc:abbrev.rc v};
like ($output, qr/ABSOLUTELY NO WARRANTY/, 'v');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'abbrev.rc';
ok (!-r 'abbrev.rc', 'Removed abbrev.rc');
exit 0;

72
src/tests/add.t Executable file
View File

@@ -0,0 +1,72 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 14;
# Create the rc file.
if (open my $fh, '>', 'add.rc')
{
print $fh "data.location=.\n";
close $fh;
ok (-r 'add.rc', 'Created add.rc');
}
# Test the add command.
my $output = qx{../task rc:add.rc add This is a test; ../task rc:add.rc info 1};
like ($output, qr/ID\s+1\n/, 'add ID');
like ($output, qr/Description\s+This is a test\n/, 'add ID');
like ($output, qr/Status\s+Pending\n/, 'add Pending');
like ($output, qr/UUID\s+[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}\n/, 'add UUID');
# Test the /// modifier.
$output = qx{../task rc:add.rc 1 /test/TEST/; ../task rc:add.rc 1 "/is //"; ../task rc:add.rc info 1};
like ($output, qr/ID\s+1\n/, 'add ID');
like ($output, qr/Status\s+Pending\n/, 'add Pending');
like ($output, qr/Description\s+This a TEST\n/, 'add ID');
# Test delete.
$output = qx{../task rc:add.rc delete 1; ../task rc:add.rc info 1};
like ($output, qr/ID\s+1\n/, 'add ID');
like ($output, qr/Status\s+Deleted\n/, 'add Deleted');
# Test undelete.
$output = qx{../task rc:add.rc undelete 1; ../task rc:add.rc info 1};
like ($output, qr/ID\s+1\n/, 'add ID');
like ($output, qr/Status\s+Pending\n/, 'add Pending');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'add.rc';
ok (!-r 'add.rc', 'Removed add.rc');
exit 0;

74
src/tests/annotate.t Executable file
View File

@@ -0,0 +1,74 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 8;
# Create the rc file.
if (open my $fh, '>', 'annotate.rc')
{
print $fh "data.location=.\n",
"report.r.description=r\n",
"report.r.columns=id,description\n",
"report.r.sort=id+\n";
close $fh;
ok (-r 'annotate.rc', 'Created annotate.rc');
}
# Add two tasks, annotate one twice.
qx{../task rc:annotate.rc add one};
qx{../task rc:annotate.rc add two};
qx{../task rc:annotate.rc annotate 1 foo};
sleep 2;
qx{../task rc:annotate.rc annotate 1 bar};
my $output = qx{../task rc:annotate.rc r};
# ID Description
# -- -------------------------------
# 1 one
# 3/24/2009 foo
# 3/24/2009 bar
# 2 two
#
# 2 tasks
like ($output, qr/1 one/, 'task 1');
like ($output, qr/2 two/, 'task 2');
like ($output, qr/one.+\d{1,2}\/\d{1,2}\/\d{4} foo/ms, 'first annotation');
like ($output, qr/foo.+\d{1,2}\/\d{1,2}\/\d{4} bar/ms, 'second annotation');
like ($output, qr/2 tasks/, 'count');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'annotate.rc';
ok (!-r 'annotate.rc', 'Removed annotate.rc');
exit 0;

55
src/tests/append.t Executable file
View File

@@ -0,0 +1,55 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 4;
# Create the rc file.
if (open my $fh, '>', 'append.rc')
{
print $fh "data.location=.\n";
close $fh;
ok (-r 'append.rc', 'Created append.rc');
}
# Add a task, then append more decsription.
qx{../task rc:append.rc add foo};
qx{../task rc:append.rc 1 append bar};
my $output = qx{../task rc:append.rc info 1};
like ($output, qr/Description\s+foo\sbar\n/, 'append worked');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'append.rc';
ok (!-r 'append.rc', 'Removed append.rc');
exit 0;

View File

@@ -0,0 +1,63 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2009, Paul Beckingham.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <test.h>
#include <../task.h>
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{
UnitTest t (8);
std::vector <std::string> options;
options.push_back ("abc");
options.push_back ("abcd");
options.push_back ("abcde");
options.push_back ("bcdef");
options.push_back ("cdefg");
std::vector <std::string> matches;
int result = autoComplete ("", options, matches);
t.is (result, 0, "no match on empty string");
result = autoComplete ("x", options, matches);
t.is (result, 0, "no match on wrong string");
result = autoComplete ("abcd", options, matches);
t.is (result, 1, "exact match on 'abcd'");
t.is (matches[0], "abcd", "exact match on 'abcd'");
result = autoComplete ("ab", options, matches);
t.is (result, 3, "partial match on 'ab'");
t.is (matches[0], "abc", "partial match on 'abc'");
t.is (matches[1], "abcd", "partial match on 'abcd'");
t.is (matches[2], "abcde", "partial match on 'abcde'");
return 0;
}
////////////////////////////////////////////////////////////////////////////////

57
src/tests/basic.t Executable file
View File

@@ -0,0 +1,57 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 7;
# Create the rc file.
if (open my $fh, '>', 'basic.rc')
{
print $fh "data.location=.\n";
close $fh;
ok (-r 'basic.rc', 'Created basic.rc');
}
# Test the usage command.
my $output = qx{../task rc:basic.rc};
like ($output, qr/Usage: task/, 'usage');
like ($output, qr/http:\/\/www\.beckingham\.net\/task\.html/, 'usage - url');
# Test the version command.
$output = qx{../task rc:basic.rc version};
like ($output, qr/task \d+\.\d+\.\d+/, 'version - task version number');
like ($output, qr/ABSOLUTELY NO WARRANTY/, 'version - warranty');
like ($output, qr/http:\/\/www\.beckingham\.net\/task\.html/, 'version - url');
# Cleanup.
unlink 'basic.rc';
ok (!-r 'basic.rc', 'Removed basic.rc');
exit 0;

103
src/tests/benchmark.t Executable file
View File

@@ -0,0 +1,103 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 4;
# Create the rc file.
if (open my $fh, '>', 'bench.rc')
{
print $fh "data.location=.\n",
"_forcecolor=1\n";
close $fh;
ok (-r 'bench.rc', 'Created bench.rc');
}
# Do lots of things. Time it all.
my @tags = qw(t_one t_two t_three t_four t_five t_six t_seven t_eight);
my @projects = qw(p_one p_two p_three p_foud p_five p_six p_seven p_eight);
my @priorities = qw(H M L);
my $description = 'This is a medium-sized description with no special characters';
# Start the clock.
my $start = time ();
my $cursor = $start;
diag ("start=$start");
# Make a mess.
for my $i (1 .. 1000)
{
my $project = $projects[rand % 8];
my $priority = $priorities[rand % 3];
my $tag = $tags[rand % 8];
qx{../task rc:bench.rc add project:$project priority:$priority +$tag $i $description};
}
diag ("1000 tasks added in " . (time () - $cursor) . " seconds");
$cursor = time ();
qx{../task rc:bench.rc /with/WITH/} for 1 .. 200;
qx{../task rc:bench.rc done $_} for 201 .. 400;
qx{../task rc:bench.rc start $_} for 401 .. 600;
diag ("600 tasks altered in " . (time () - $cursor) . " seconds");
$cursor = time ();
# Report it all. Note that all Timer information is displayed.
for (1 .. 100)
{
diag (grep {/^Timer /} qx{../task rc:bench.rc ls});
diag (grep {/^Timer /} qx{../task rc:bench.rc list});
diag (grep {/^Timer /} qx{../task rc:bench.rc list priority:H});
diag (grep {/^Timer /} qx{../task rc:bench.rc list +tag});
diag (grep {/^Timer /} qx{../task rc:bench.rc list project_A});
diag (grep {/^Timer /} qx{../task rc:bench.rc long});
diag (grep {/^Timer /} qx{../task rc:bench.rc completed});
diag (grep {/^Timer /} qx{../task rc:bench.rc history});
diag (grep {/^Timer /} qx{../task rc:bench.rc ghistory});
}
# Stop the clock.
my $stop = time ();
diag ("stop=$stop");
diag ("total=" . ($stop - $start));
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'completed.data';
ok (!-r 'completed.data', 'Removed completed.data');
unlink 'bench.rc';
ok (!-r 'bench.rc', 'Removed bench.rc');
exit 0;

40
src/tests/benchmark.txt Normal file
View File

@@ -0,0 +1,40 @@
3/8/2009
Before:
Table::render
26.1792
16.67
18.9697
28.6328
1.86553
0.00044
0.000319
---------
92.317989
After Table::optimize removed:
Table::render
0.146177
0.145928
0.184444
0.014784
0.000512
0.000267
---------
0.492112
Speedup:
92.317989 / 0.492112 = 187.6
3/8/2009
New benchmark:
1..4
ok 1 - Created bench.rc
# start=1236565862
# 1000 tasks added in 3 seconds
# 600 tasks altered in 28 seconds
# stop=1236566048
# total=186
ok 2 - Removed pending.data
ok 3 - Removed completed.data
ok 4 - Removed bench.rc

79
src/tests/bug.annual.t Executable file
View File

@@ -0,0 +1,79 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 14;
# Create the rc file.
if (open my $fh, '>', 'annual.rc')
{
print $fh "data.location=.\n";
close $fh;
ok (-r 'annual.rc', 'Created annual.rc');
}
# If a task is added with a due date ten years ago, with an annual recurrence,
# then the synthetic tasks in between then and now have a due date that creeps.
#
# ID Project Pri Due Active Age Description
# -- ------- --- ---------- ------ --- -----------
# 2 1/1/2000 - foo
# 3 12/31/2000 - foo
# 4 12/31/2001 - foo
# 5 12/31/2002 - foo
# 6 12/31/2003 - foo
# 7 12/30/2004 - foo
# 8 12/30/2005 - foo
# 9 12/30/2006 - foo
# 10 12/30/2007 - foo
# 11 12/29/2008 - foo
# 12 12/29/2009 - foo
qx{../task rc:annual.rc add foo due:1/1/2000 recur:annual until:1/1/2009};
my $output = qx{../task rc:annual.rc list};
like ($output, qr/2\s+1\/1\/2000\s+- foo/, 'synthetic 1 no creep');
like ($output, qr/3\s+1\/1\/2001\s+- foo/, 'synthetic 2 no creep');
like ($output, qr/4\s+1\/1\/2002\s+- foo/, 'synthetic 3 no creep');
like ($output, qr/5\s+1\/1\/2003\s+- foo/, 'synthetic 4 no creep');
like ($output, qr/6\s+1\/1\/2004\s+- foo/, 'synthetic 5 no creep');
like ($output, qr/7\s+1\/1\/2005\s+- foo/, 'synthetic 6 no creep');
like ($output, qr/8\s+1\/1\/2006\s+- foo/, 'synthetic 7 no creep');
like ($output, qr/9\s+1\/1\/2007\s+- foo/, 'synthetic 8 no creep');
like ($output, qr/10\s+1\/1\/2008\s+- foo/, 'synthetic 9 no creep');
like ($output, qr/11\s+1\/1\/2009\s+- foo/, 'synthetic 10 no creep');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'annual.rc';
ok (!-r 'annual.rc', 'Removed annual.rc');
exit 0;

77
src/tests/bug.concat.t Executable file
View File

@@ -0,0 +1,77 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 6;
# Create the rc file.
if (open my $fh, '>', 'bug_concat.rc')
{
print $fh "data.location=.\n";
close $fh;
ok (-r 'bug_concat.rc', 'Created bug_concat.rc');
}
# When a task is modified like this:
#
# % task 1 This is a new description
#
# The arguments are concatenated thus:
#
# Thisisanewdescription
qx{../task rc:bug_concat.rc add This is the original text};
my $output = qx{../task rc:bug_concat.rc info 1};
like ($output, qr/Description\s+This is the original text\n/, 'original correct');
qx{../task rc:bug_concat.rc 1 This is the modified text};
$output = qx{../task rc:bug_concat.rc info 1};
like ($output, qr/Description\s+This is the modified text\n/, 'modified correct');
# When a task is added like this:
#
# % task add aaa bbb:ccc ddd
#
# The description is concatenated thus:
#
# aaabbb:ccc ddd
qx{../task rc:bug_concat.rc add aaa bbb:ccc ddd};
$output = qx{../task rc:bug_concat.rc info 2};
like ($output, qr/Description\s+aaa bbb:ccc ddd\n/, 'properly concatenated');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'bug_concat.rc';
ok (!-r 'bug_concat.rc', 'Removed bug_concat.rc');
exit 0;

83
src/tests/bug.hang.t Executable file
View File

@@ -0,0 +1,83 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 5;
# Create the rc file.
if (open my $fh, '>', 'hang.rc')
{
print $fh "data.location=.\n",
"shadow.file=shadow.txt\n",
"shadow.command=list\n";
close $fh;
ok (-r 'hang.rc', 'Created hang.rc');
}
=pod
I found a bug in the current version of task. Using recur and a shadow file will
lead to an infinite loop. To reproduce it, define a shadow file in the .taskrc,
set a command for it that rebuilds the database, e.g. "list", and then add a
task with a recurrence set, e.g. "task add due:today recur:1d infinite loop".
Task will then loop forever and add the same recurring task until it runs out of
memory. So I checked the source and I believe I found the cause.
handleRecurrence() in task.cpp will modify the mask, but writes it only after it
has added all new tasks. Adding the task will, however, invoke onChangeCallback,
which starts the same process all over again.
=cut
eval
{
$SIG{'ALRM'} = sub {die "alarm\n"};
alarm 10;
my $output = qx{../task rc:hang.rc list;
../task rc:hang.rc add due:today recur:1d infinite loop;
../task rc:hang.rc info 1};
alarm 0;
like ($output, qr/^Description\s+infinite loop\n/m, 'no hang');
};
if ($@ eq "alarm\n")
{
fail ('task hang on add or recurring task, with shadow file, for 10s');
}
# Cleanup.
unlink 'shadow.txt';
ok (!-r 'shadow.txt', 'Removed shadow.txt');
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'hang.rc';
ok (!-r 'hang.rc', 'Removed hang.rc');
exit 0;

164
src/tests/bug.period.t Executable file
View File

@@ -0,0 +1,164 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 41;
# Create the rc file.
if (open my $fh, '>', 'period.rc')
{
print $fh "data.location=.\n";
close $fh;
ok (-r 'period.rc', 'Created period.rc');
}
=pod
http://github.com/pbeckingham/task/blob/857f813a24f7ce15fea9f2c28aadad84cb5c8847/src/task.cpp
619 // If the period is an 'easy' one, add it to current, and we're done.
620 int days = convertDuration (period);
Date getNextRecurrence (Date& current, std::string& period)
starting at line 509 special cases several possibilities for period, '\d\s?m'
'monthly', 'quarterly', 'semiannual', 'bimonthly', 'biannual', 'biyearly'.
Everything else falls through with period being passed to convertDuration.
convertDuration doesn't know about 'daily' though so it seems to be returning 0.
Confirmed:
getNextRecurrence convertDuration
----------------- ---------------
daily
day
weekly
sennight
biweekly
fortnight
monthly monthly
quarterly quarterly
semiannual semiannual
bimonthly bimonthly
biannual biannual
biyearly biyearly
annual
yearly
*m *m
*q *q
*d
*w
*y
=cut
my $output = qx{../task rc:period.rc add daily due:tomorrow recur:daily};
like ($output, qr/^$/, 'recur:daily');
$output = qx{../task rc:period.rc add day due:tomorrow recur:day};
like ($output, qr/^$/, 'recur:day');
$output = qx{../task rc:period.rc add weekly due:tomorrow recur:weekly};
like ($output, qr/^$/, 'recur:weekly');
$output = qx{../task rc:period.rc add sennight due:tomorrow recur:sennight};
like ($output, qr/^$/, 'recur:sennight');
$output = qx{../task rc:period.rc add biweekly due:tomorrow recur:biweekly};
like ($output, qr/^$/, 'recur:biweekly');
$output = qx{../task rc:period.rc add fortnight due:tomorrow recur:fortnight};
like ($output, qr/^$/, 'recur:fortnight');
$output = qx{../task rc:period.rc add monthly due:tomorrow recur:monthly};
like ($output, qr/^$/, 'recur:monthly');
$output = qx{../task rc:period.rc add quarterly due:tomorrow recur:quarterly};
like ($output, qr/^$/, 'recur:quarterly');
$output = qx{../task rc:period.rc add semiannual due:tomorrow recur:semiannual};
like ($output, qr/^$/, 'recur:semiannual');
$output = qx{../task rc:period.rc add bimonthly due:tomorrow recur:bimonthly};
like ($output, qr/^$/, 'recur:bimonthly');
$output = qx{../task rc:period.rc add biannual due:tomorrow recur:biannual};
like ($output, qr/^$/, 'recur:biannual');
$output = qx{../task rc:period.rc add biyearly due:tomorrow recur:biyearly};
like ($output, qr/^$/, 'recur:biyearly');
$output = qx{../task rc:period.rc add annual due:tomorrow recur:annual};
like ($output, qr/^$/, 'recur:annual');
$output = qx{../task rc:period.rc add yearly due:tomorrow recur:yearly};
like ($output, qr/^$/, 'recur:yearly');
$output = qx{../task rc:period.rc add 2d due:tomorrow recur:2d};
like ($output, qr/^$/, 'recur:2m');
$output = qx{../task rc:period.rc add 2w due:tomorrow recur:2w};
like ($output, qr/^$/, 'recur:2q');
$output = qx{../task rc:period.rc add 2m due:tomorrow recur:2m};
like ($output, qr/^$/, 'recur:2d');
$output = qx{../task rc:period.rc add 2q due:tomorrow recur:2q};
like ($output, qr/^$/, 'recur:2w');
$output = qx{../task rc:period.rc add 2y due:tomorrow recur:2y};
like ($output, qr/^$/, 'recur:2y');
# Verify that the recurring task instances get created. One of each.
$output = qx{../task rc:period.rc list};
like ($output, qr/\bdaily\b/, 'verify daily');
like ($output, qr/\bday\b/, 'verify day');
like ($output, qr/\bweekly\b/, 'verify weekly');
like ($output, qr/\bsennight\b/, 'verify sennight');
like ($output, qr/\bbiweekly\b/, 'verify biweekly');
like ($output, qr/\bfortnight\b/, 'verify fortnight');
like ($output, qr/\bmonthly\b/, 'verify monthly');
like ($output, qr/\bquarterly\b/, 'verify quarterly');
like ($output, qr/\bsemiannual\b/, 'verify semiannual');
like ($output, qr/\bbimonthly\b/, 'verify bimonthly');
like ($output, qr/\bbiannual\b/, 'verify biannual');
like ($output, qr/\bbiyearly\b/, 'verify biyearly');
like ($output, qr/\bannual\b/, 'verify annual');
like ($output, qr/\byearly\b/, 'verify yearly');
like ($output, qr/\b2d\b/, 'verify 2d');
like ($output, qr/\b2w\b/, 'verify 2w');
like ($output, qr/\b2m\b/, 'verify 2m');
like ($output, qr/\b2q\b/, 'verify 2q');
like ($output, qr/\b2y\b/, 'verify 2y');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'period.rc';
ok (!-r 'period.rc', 'Removed period.rc');
exit 0;

61
src/tests/bug.sort.t Executable file
View File

@@ -0,0 +1,61 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 5;
# Create the rc file.
if (open my $fh, '>', 'bug_sort.rc')
{
print $fh "data.location=.\n";
close $fh;
ok (-r 'bug_sort.rc', 'Created bug_sort.rc');
}
my $setup = "../task rc:bug_sort.rc add one;"
. "../task rc:bug_sort.rc add two;"
. "../task rc:bug_sort.rc add three recur:daily due:eom;";
qx{$setup};
my $output = qx{../task rc:bug_sort.rc list};
like ($output, qr/three.*(?:one.*two|two.*one)/msi, 'list did not hang');
qx{../task rc:bug_sort.rc 1 priority:H};
$output = qx{../task rc:bug_sort.rc list};
like ($output, qr/three.*one.*two/msi, 'list did not hang after pri:H on 1');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'bug_sort.rc';
ok (!-r 'bug_sort.rc', 'Removed bug_sort.rc');
exit 0;

67
src/tests/bug.summary.t Executable file
View File

@@ -0,0 +1,67 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 6;
# Create the rc file.
if (open my $fh, '>', 'summary.rc')
{
print $fh "data.location=.\n",
"confirmation=no\n";
close $fh;
ok (-r 'summary.rc', 'Created summary.rc');
}
# Add three tasks. Do 1, delete 1, leave 1 pending. Summary should depict a
# 50% completion.
qx{../task rc:summary.rc add project:A one};
qx{../task rc:summary.rc add project:A two};
qx{../task rc:summary.rc add project:A three};
qx{../task rc:summary.rc do 1};
qx{../task rc:summary.rc delete 2};
my $output = qx{../task rc:summary.rc summary};
like ($output, qr/A\s+1\s+-\s+50%/, 'summary correctly shows 50% before report');
qx{../task rc:summary.rc list};
$output = qx{../task rc:summary.rc summary};
like ($output, qr/A\s+1\s+-\s+50%/, 'summary correctly shows 50% after report');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'completed.data';
ok (!-r 'completed.data', 'Removed completed.data');
unlink 'summary.rc';
ok (!-r 'summary.rc', 'Removed summary.rc');
exit 0;

60
src/tests/color.active.t Executable file
View File

@@ -0,0 +1,60 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 5;
# Create the rc file.
if (open my $fh, '>', 'color.rc')
{
print $fh "data.location=.\n",
"color.active=red\n",
"_forcecolor=1\n";
close $fh;
ok (-r 'color.rc', 'Created color.rc');
}
# Test the add command.
qx{../task rc:color.rc add nothing};
qx{../task rc:color.rc add red};
qx{../task rc:color.rc start 2};
my $output = qx{../task rc:color.rc list};
like ($output, qr/ (?!<\033\[\d\dm) .* nothing .* (?!>\033\[0m) /x, 'none');
like ($output, qr/ \033\[31m .* red .* \033\[0m /x, 'color.active');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'color.rc';
ok (!-r 'color.rc', 'Removed color.rc');
exit 0;

58
src/tests/color.disable.t Executable file
View File

@@ -0,0 +1,58 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 6;
# Create the rc file.
if (open my $fh, '>', 'color.rc')
{
print $fh "data.location=.\n",
"color.pri.H=red\n";
close $fh;
ok (-r 'color.rc', 'Created color.rc');
}
# Test the add command.
qx{../task rc:color.rc add priority:H red};
my $output = qx{../task rc:color.rc list};
like ($output, qr/red/, 'color.disable - found red');
unlike ($output, qr/\033\[31m/, 'color.disable - no color red');
unlike ($output, qr/\033\[0m/, 'color.disable - no color reset');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'color.rc';
ok (!-r 'color.rc', 'Removed color.rc');
exit 0;

59
src/tests/color.due.t Executable file
View File

@@ -0,0 +1,59 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 5;
# Create the rc file.
if (open my $fh, '>', 'color.rc')
{
print $fh "data.location=.\n",
"color.due=red\n",
"_forcecolor=1\n";
close $fh;
ok (-r 'color.rc', 'Created color.rc');
}
# Test the add command.
qx{../task rc:color.rc add due:eoy nothing};
qx{../task rc:color.rc add due:tomorrow red};
my $output = qx{../task rc:color.rc list};
like ($output, qr/ (?!<\033\[\d\dm) \d{1,2}\/\d{1,2}\/\d{4} (?!>\033\[0m) .* nothing /x, 'none');
like ($output, qr/ \033\[31m .* red .* \033\[0m/x, 'color.due');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'color.rc';
ok (!-r 'color.rc', 'Removed color.rc');
exit 0;

62
src/tests/color.keyword.t Executable file
View File

@@ -0,0 +1,62 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 6;
# Create the rc file.
if (open my $fh, '>', 'color.rc')
{
print $fh "data.location=.\n",
"color.keyword.red=red\n",
"color.keyword.green=green\n",
"_forcecolor=1\n";
close $fh;
ok (-r 'color.rc', 'Created color.rc');
}
# Test the add command.
qx{../task rc:color.rc add nothing};
qx{../task rc:color.rc add red};
qx{../task rc:color.rc add green};
my $output = qx{../task rc:color.rc list};
like ($output, qr/ (?!<\033\[\d\dm) .* nothing .* (?!>\033\[0m) /x, 'none');
like ($output, qr/ \033\[31m .* red .* \033\[0m /x, 'color.keyword.red');
like ($output, qr/ \033\[32m .* green .* \033\[0m /x, 'color.keyword.green');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'color.rc';
ok (!-r 'color.rc', 'Removed color.rc');
exit 0;

59
src/tests/color.overdue.t Executable file
View File

@@ -0,0 +1,59 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 5;
# Create the rc file.
if (open my $fh, '>', 'color.rc')
{
print $fh "data.location=.\n",
"color.overdue=red\n",
"_forcecolor=1\n";
close $fh;
ok (-r 'color.rc', 'Created color.rc');
}
# Test the add command.
qx{../task rc:color.rc add due:tomorrow nothing};
qx{../task rc:color.rc add due:yesterday red};
my $output = qx{../task rc:color.rc list};
like ($output, qr/ (?!<\033\[\d\dm) \d{1,2}\/\d{1,2}\/\d{4} (?!>\033\[0m) .* nothing /x, 'none');
like ($output, qr/ \033\[31m .* red .* \033\[0m/x, 'color.overdue');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'color.rc';
ok (!-r 'color.rc', 'Removed color.rc');
exit 0;

66
src/tests/color.pri.t Executable file
View File

@@ -0,0 +1,66 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 7;
# Create the rc file.
if (open my $fh, '>', 'color.rc')
{
print $fh "data.location=.\n",
"color.pri.H=red\n",
"color.pri.M=green\n",
"color.pri.L=blue\n",
"color.pri.none=yellow\n",
"_forcecolor=1\n";
close $fh;
ok (-r 'color.rc', 'Created color.rc');
}
# Test the add command.
qx{../task rc:color.rc add priority:H red};
qx{../task rc:color.rc add priority:M green};
qx{../task rc:color.rc add priority:L blue};
qx{../task rc:color.rc add yellow};
my $output = qx{../task rc:color.rc list};
like ($output, qr/ \033\[31m .* red .* \033\[0m /x, 'color.pri.H');
like ($output, qr/ \033\[32m .* green .* \033\[0m /x, 'color.pri.M');
like ($output, qr/ \033\[34m .* blue .* \033\[0m /x, 'color.pri.L');
like ($output, qr/ \033\[33m .* yellow .* \033\[0m /x, 'color.pri.none');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'color.rc';
ok (!-r 'color.rc', 'Removed color.rc');
exit 0;

59
src/tests/color.project.t Executable file
View File

@@ -0,0 +1,59 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 5;
# Create the rc file.
if (open my $fh, '>', 'color.rc')
{
print $fh "data.location=.\n",
"color.project.x=red\n",
"_forcecolor=1\n";
close $fh;
ok (-r 'color.rc', 'Created color.rc');
}
# Test the add command.
qx{../task rc:color.rc add nothing};
qx{../task rc:color.rc add project:x red};
my $output = qx{../task rc:color.rc list};
like ($output, qr/ (?!<\033\[\d\dm) .* nothing .* (?!>\033\[0m) /x, 'none');
like ($output, qr/ \033\[31m .* red .* \033\[0m /x, 'color.project.red');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'color.rc';
ok (!-r 'color.rc', 'Removed color.rc');
exit 0;

59
src/tests/color.recurring.t Executable file
View File

@@ -0,0 +1,59 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 5;
# Create the rc file.
if (open my $fh, '>', 'color.rc')
{
print $fh "data.location=.\n",
"color.recurring=red\n",
"_forcecolor=1\n";
close $fh;
ok (-r 'color.rc', 'Created color.rc');
}
# Test the add command.
qx{../task rc:color.rc add nothing};
qx{../task rc:color.rc add due:tomorrow recur:1w red};
my $output = qx{../task rc:color.rc list};
like ($output, qr/ (?!<\033\[\d\dm) .* nothing .* (?!>\033\[0m) /x, 'none');
like ($output, qr/ \033\[31m .* red .* \033\[0m /x, 'color.recurring');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'color.rc';
ok (!-r 'color.rc', 'Removed color.rc');
exit 0;

62
src/tests/color.tag.t Executable file
View File

@@ -0,0 +1,62 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 6;
# Create the rc file.
if (open my $fh, '>', 'color.rc')
{
print $fh "data.location=.\n",
"color.tag.red=red\n",
"color.tag.green=green\n",
"_forcecolor=1\n";
close $fh;
ok (-r 'color.rc', 'Created color.rc');
}
# Test the add command.
qx{../task rc:color.rc add nothing};
qx{../task rc:color.rc add +red red};
qx{../task rc:color.rc add +green green};
my $output = qx{../task rc:color.rc list};
like ($output, qr/ (?!<\033\[\d\dm) .* nothing .* (?!>\033\[0m) /x, 'none');
like ($output, qr/ \033\[31m .* red .* \033\[0m /x, 'color.tag.red');
like ($output, qr/ \033\[32m .* green .* \033\[0m /x, 'color.tag.green');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'color.rc';
ok (!-r 'color.rc', 'Removed color.rc');
exit 0;

59
src/tests/color.tagged.t Executable file
View File

@@ -0,0 +1,59 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 5;
# Create the rc file.
if (open my $fh, '>', 'color.rc')
{
print $fh "data.location=.\n",
"color.tagged=red\n",
"_forcecolor=1\n";
close $fh;
ok (-r 'color.rc', 'Created color.rc');
}
# Test the add command.
qx{../task rc:color.rc add nothing};
qx{../task rc:color.rc add +tag red};
my $output = qx{../task rc:color.rc list};
like ($output, qr/ (?!<\033\[\d\dm) .* nothing .* (?!>\033\[0m) /x, 'none');
like ($output, qr/ \033\[31m .* red .* \033\[0m /x, 'color.tagged');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'color.rc';
ok (!-r 'color.rc', 'Removed color.rc');
exit 0;

64
src/tests/completed.t Executable file
View File

@@ -0,0 +1,64 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 6;
# Create the rc file.
if (open my $fh, '>', 'completed.rc')
{
print $fh "data.location=.\n",
"confirmation=no\n";
close $fh;
ok (-r 'completed.rc', 'Created completed.rc');
}
# Add two tasks, mark 1 as done, the other as deleted.
qx{../task rc:completed.rc add one};
qx{../task rc:completed.rc add two};
qx{../task rc:completed.rc 1 done};
qx{../task rc:completed.rc 2 delete};
# Generate completed report.
my $output = qx{../task rc:completed.rc completed};
like ($output, qr/one/, 'one -> completed');
unlike ($output, qr/two/, 'two -> deleted');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'completed.data';
ok (!-r 'completed.data', 'Removed completed.data');
unlink 'completed.rc';
ok (!-r 'completed.rc', 'Removed completed.rc');
exit 0;

57
src/tests/config.obsolete.t Executable file
View File

@@ -0,0 +1,57 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 5;
# Create the rc file.
if (open my $fh, '>', 'obsolete.rc')
{
print $fh "data.location=.\n",
"foo=1\n";
close $fh;
ok (-r 'obsolete.rc', 'Created obsolete.rc');
}
# Test the add command.
my $output = qx{../task rc:obsolete.rc version};
like ($output, qr/Your .taskrc file contains these unrecognized variables:\n/,
'unsupported configuration variable');
like ($output, qr/ foo\n/, 'unsupported configuration variable');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'obsolete.rc';
ok (!-r 'obsolete.rc', 'Removed obsolete.rc');
exit 0;

109
src/tests/confirmation.t Executable file
View File

@@ -0,0 +1,109 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 26;
# Create the rc file.
if (open my $fh, '>', 'confirm.rc')
{
print $fh "data.location=.\n",
"confirmation=yes\n";
close $fh;
ok (-r 'confirm.rc', 'Created confirm.rc');
}
# Create the response file.
if (open my $fh, '>', 'response.txt')
{
print $fh "\n\nn\n";
close $fh;
ok (-r 'response.txt', 'Created response.txt');
}
qx{../task rc:confirm.rc add foo} for 1 .. 10;
# Test the various forms of "yes".
my $output = qx{echo "yes" | ../task rc:confirm.rc del 1};
like ($output, qr/Permanently delete task\? \(y\/n\)/, 'confirmation - yes works');
unlike ($output, qr/Task not deleted\./, 'confirmation - yes works');
$output = qx{echo "ye" | ../task rc:confirm.rc del 2};
like ($output, qr/Permanently delete task\? \(y\/n\)/, 'confirmation - ye works');
unlike ($output, qr/Task not deleted\./, 'confirmation - ye works');
$output = qx{echo "y" | ../task rc:confirm.rc del 3};
like ($output, qr/Permanently delete task\? \(y\/n\)/, 'confirmation - y works');
unlike ($output, qr/Task not deleted\./, 'confirmation - y works');
$output = qx{echo "YES" | ../task rc:confirm.rc del 4};
like ($output, qr/Permanently delete task\? \(y\/n\)/, 'confirmation - YES works');
unlike ($output, qr/Task not deleted\./, 'confirmation - YES works');
$output = qx{echo "YE" | ../task rc:confirm.rc del 5};
like ($output, qr/Permanently delete task\? \(y\/n\)/, 'confirmation - YE works');
unlike ($output, qr/Task not deleted\./, 'confirmation - YE works');
$output = qx{echo "Y" | ../task rc:confirm.rc del 6};
like ($output, qr/Permanently delete task\? \(y\/n\)/, 'confirmation - Y works');
unlike ($output, qr/Task not deleted\./, 'confirmation - Y works');
# Test the various forms of "no".
$output = qx{echo "no" | ../task rc:confirm.rc del 7};
like ($output, qr/Permanently delete task\? \(y\/n\)/, 'confirmation - no works');
like ($output, qr/Task not deleted\./, 'confirmation - no works');
$output = qx{echo "n" | ../task rc:confirm.rc del 7};
like ($output, qr/Permanently delete task\? \(y\/n\)/, 'confirmation - n works');
like ($output, qr/Task not deleted\./, 'confirmation - n works');
$output = qx{echo "NO" | ../task rc:confirm.rc del 7};
like ($output, qr/Permanently delete task\? \(y\/n\)/, 'confirmation - NO works');
like ($output, qr/Task not deleted\./, 'confirmation - NO works');
$output = qx{echo "N" | ../task rc:confirm.rc del 7};
like ($output, qr/Permanently delete task\? \(y\/n\)/, 'confirmation - N works');
like ($output, qr/Task not deleted\./, 'confirmation - N works');
# Test newlines.
$output = qx{cat response.txt | ../task rc:confirm.rc del 7};
like ($output, qr/(Permanently delete task\? \(y\/n\)) \1 \1/, 'confirmation - \n re-prompt works');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'response.txt';
ok (!-r 'response.txt', 'Removed response.txt');
unlink 'confirm.rc';
ok (!-r 'confirm.rc', 'Removed confirm.rc');
exit 0;

57
src/tests/custom.columns.t Executable file
View File

@@ -0,0 +1,57 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 4;
# Create the rc file.
if (open my $fh, '>', 'custom.rc')
{
print $fh "data.location=.\n",
"report.foo.description=DESC\n",
"report.foo.columns=id,foo,description\n",
"report.foo.sort=id+\n",
"report.foo.filter=project:A\n";
close $fh;
ok (-r 'custom.rc', 'Created custom.rc');
}
# Generate the usage screen, and locate the custom report on it.
my $output = qx{../task rc:custom.rc foo 2>&1};
like ($output, qr/Unrecognized column name: foo\n/, 'custom report spotted invalid column');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'custom.rc';
ok (!-r 'custom.rc', 'Removed custom.rc');
exit 0;

61
src/tests/custom.recur_ind.t Executable file
View File

@@ -0,0 +1,61 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 6;
# Create the rc file.
if (open my $fh, '>', 'custom.rc')
{
print $fh "data.location=.\n",
"report.foo.description=DESC\n",
"report.foo.columns=id,recurrence_indicator\n",
"report.foo.labels=ID,R\n",
"report.foo.sort=id+\n";
close $fh;
ok (-r 'custom.rc', 'Created custom.rc');
}
# Generate the usage screen, and locate the custom report on it.
qx{../task rc:custom.rc add foo due:tomorrow recur:weekly};
qx{../task rc:custom.rc add bar};
my $output = qx{../task rc:custom.rc foo 2>&1};
like ($output, qr/ID R/, 'Recurrence indicator heading');
like ($output, qr/3\s+R/, 'Recurrence indicator t1');
unlike ($output, qr/2\s+R/, 'No recurrence indicator t2');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'custom.rc';
ok (!-r 'custom.rc', 'Removed custom.rc');
exit 0;

63
src/tests/custom.t Executable file
View File

@@ -0,0 +1,63 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 6;
# Create the rc file.
if (open my $fh, '>', 'custom.rc')
{
print $fh "data.location=.\n",
"report.foo.description=DESC\n",
"report.foo.columns=id,description\n",
"report.foo.sort=id+\n",
"report.foo.filter=project:A\n";
close $fh;
ok (-r 'custom.rc', 'Created custom.rc');
}
# Generate the usage screen, and locate the custom report on it.
my $output = qx{../task rc:custom.rc usage};
like ($output, qr/task foo \[tags\] \[attrs\] desc\.\.\.\s+DESC\n/m, 'report.foo');
qx{../task rc:custom.rc add project:A one};
qx{../task rc:custom.rc add two};
$output = qx{../task rc:custom.rc foo};
like ($output, qr/one/, 'custom filter included');
unlike ($output, qr/two/, 'custom filter excluded');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'custom.rc';
ok (!-r 'custom.rc', 'Removed custom.rc');
exit 0;

61
src/tests/custom.tag_ind.t Executable file
View File

@@ -0,0 +1,61 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 6;
# Create the rc file.
if (open my $fh, '>', 'custom.rc')
{
print $fh "data.location=.\n",
"report.foo.description=DESC\n",
"report.foo.columns=id,tag_indicator\n",
"report.foo.labels=ID,T\n",
"report.foo.sort=id+\n";
close $fh;
ok (-r 'custom.rc', 'Created custom.rc');
}
# Generate the usage screen, and locate the custom report on it.
qx{../task rc:custom.rc add foo +tag};
qx{../task rc:custom.rc add bar};
my $output = qx{../task rc:custom.rc foo 2>&1};
like ($output, qr/ID T/, 'Tag indicator heading');
like ($output, qr/1\s+\+/, 'Tag indicator t1');
unlike ($output, qr/2\s+\+/, 'No tag indicator t2');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'custom.rc';
ok (!-r 'custom.rc', 'Removed custom.rc');
exit 0;

View File

@@ -1,5 +1,27 @@
////////////////////////////////////////////////////////////////////////////////
// Copyright 2005 - 2008, Paul Beckingham. All rights reserved.
// task - a command line task list manager.
//
// Copyright 2006 - 2009, Paul Beckingham.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#include <iostream>
@@ -9,7 +31,7 @@
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{
plan (100);
UnitTest t (100);
try
{
@@ -17,207 +39,207 @@ int main (int argc, char** argv)
Date yesterday;
yesterday -= 1;
ok (yesterday <= now, "yesterday <= now");
ok (yesterday < now, "yesterday < now");
notok (yesterday == now, "!(yesterday == now)");
ok (yesterday != now, "yesterday != now");
ok (now >= yesterday, "now >= yesterday");
ok (now > yesterday, "now > yesterday");
t.ok (yesterday <= now, "yesterday <= now");
t.ok (yesterday < now, "yesterday < now");
t.notok (yesterday == now, "!(yesterday == now)");
t.ok (yesterday != now, "yesterday != now");
t.ok (now >= yesterday, "now >= yesterday");
t.ok (now > yesterday, "now > yesterday");
// Loose comparisons.
Date left ("7/4/2008");
Date comp1 ("7/4/2008");
ok (left.sameDay (comp1), "7/4/2008 is on the same day as 7/4/2008");
ok (left.sameMonth (comp1), "7/4/2008 is in the same month as 7/4/2008");
ok (left.sameYear (comp1), "7/4/2008 is in the same year as 7/4/2008");
t.ok (left.sameDay (comp1), "7/4/2008 is on the same day as 7/4/2008");
t.ok (left.sameMonth (comp1), "7/4/2008 is in the same month as 7/4/2008");
t.ok (left.sameYear (comp1), "7/4/2008 is in the same year as 7/4/2008");
Date comp2 ("7/5/2008");
notok (left.sameDay (comp2), "7/4/2008 is not on the same day as 7/5/2008");
ok (left.sameMonth (comp2), "7/4/2008 is in the same month as 7/5/2008");
ok (left.sameYear (comp2), "7/4/2008 is in the same year as 7/5/2008");
t.notok (left.sameDay (comp2), "7/4/2008 is not on the same day as 7/5/2008");
t.ok (left.sameMonth (comp2), "7/4/2008 is in the same month as 7/5/2008");
t.ok (left.sameYear (comp2), "7/4/2008 is in the same year as 7/5/2008");
Date comp3 ("8/4/2008");
notok (left.sameDay (comp3), "7/4/2008 is not on the same day as 8/4/2008");
notok (left.sameMonth (comp3), "7/4/2008 is not in the same month as 8/4/2008");
ok (left.sameYear (comp3), "7/4/2008 is in the same year as 8/4/2008");
t.notok (left.sameDay (comp3), "7/4/2008 is not on the same day as 8/4/2008");
t.notok (left.sameMonth (comp3), "7/4/2008 is not in the same month as 8/4/2008");
t.ok (left.sameYear (comp3), "7/4/2008 is in the same year as 8/4/2008");
Date comp4 ("7/4/2009");
notok (left.sameDay (comp4), "7/4/2008 is not on the same day as 7/4/2009");
notok (left.sameMonth (comp4), "7/4/2008 is not in the same month as 7/4/2009");
notok (left.sameYear (comp4), "7/4/2008 is not in the same year as 7/4/2009");
t.notok (left.sameDay (comp4), "7/4/2008 is not on the same day as 7/4/2009");
t.notok (left.sameMonth (comp4), "7/4/2008 is not in the same month as 7/4/2009");
t.notok (left.sameYear (comp4), "7/4/2008 is not in the same year as 7/4/2009");
// Validity.
ok (Date::valid (2, 29, 2008), "valid: 2/29/2008");
notok (Date::valid (2, 29, 2007), "invalid: 2/29/2007");
t.ok (Date::valid (2, 29, 2008), "valid: 2/29/2008");
t.notok (Date::valid (2, 29, 2007), "invalid: 2/29/2007");
// Leap year.
ok (Date::leapYear (2008), "2008 is a leap year");
notok (Date::leapYear (2007), "2007 is not a leap year");
ok (Date::leapYear (2000), "2000 is a leap year");
ok (Date::leapYear (1900), "1900 is a leap year");
t.ok (Date::leapYear (2008), "2008 is a leap year");
t.notok (Date::leapYear (2007), "2007 is not a leap year");
t.ok (Date::leapYear (2000), "2000 is a leap year");
t.ok (Date::leapYear (1900), "1900 is a leap year");
// Days in month.
is (Date::daysInMonth (2, 2008), 29, "29 days in February 2008");
is (Date::daysInMonth (2, 2007), 28, "28 days in February 2007");
t.is (Date::daysInMonth (2, 2008), 29, "29 days in February 2008");
t.is (Date::daysInMonth (2, 2007), 28, "28 days in February 2007");
// Names.
is (Date::monthName (1), "January", "1 = January");
is (Date::monthName (2), "February", "2 = February");
is (Date::monthName (3), "March", "3 = March");
is (Date::monthName (4), "April", "4 = April");
is (Date::monthName (5), "May", "5 = May");
is (Date::monthName (6), "June", "6 = June");
is (Date::monthName (7), "July", "7 = July");
is (Date::monthName (8), "August", "8 = August");
is (Date::monthName (9), "September", "9 = September");
is (Date::monthName (10), "October", "10 = October");
is (Date::monthName (11), "November", "11 = November");
is (Date::monthName (12), "December", "12 = December");
t.is (Date::monthName (1), "January", "1 = January");
t.is (Date::monthName (2), "February", "2 = February");
t.is (Date::monthName (3), "March", "3 = March");
t.is (Date::monthName (4), "April", "4 = April");
t.is (Date::monthName (5), "May", "5 = May");
t.is (Date::monthName (6), "June", "6 = June");
t.is (Date::monthName (7), "July", "7 = July");
t.is (Date::monthName (8), "August", "8 = August");
t.is (Date::monthName (9), "September", "9 = September");
t.is (Date::monthName (10), "October", "10 = October");
t.is (Date::monthName (11), "November", "11 = November");
t.is (Date::monthName (12), "December", "12 = December");
is (Date::dayName (0), "Sunday", "0 == Sunday");
is (Date::dayName (1), "Monday", "1 == Monday");
is (Date::dayName (2), "Tuesday", "2 == Tuesday");
is (Date::dayName (3), "Wednesday", "3 == Wednesday");
is (Date::dayName (4), "Thursday", "4 == Thursday");
is (Date::dayName (5), "Friday", "5 == Friday");
is (Date::dayName (6), "Saturday", "6 == Saturday");
t.is (Date::dayName (0), "Sunday", "0 == Sunday");
t.is (Date::dayName (1), "Monday", "1 == Monday");
t.is (Date::dayName (2), "Tuesday", "2 == Tuesday");
t.is (Date::dayName (3), "Wednesday", "3 == Wednesday");
t.is (Date::dayName (4), "Thursday", "4 == Thursday");
t.is (Date::dayName (5), "Friday", "5 == Friday");
t.is (Date::dayName (6), "Saturday", "6 == Saturday");
is (Date::dayOfWeek ("SUNDAY"), 0, "SUNDAY == 0");
is (Date::dayOfWeek ("sunday"), 0, "sunday == 0");
is (Date::dayOfWeek ("Sunday"), 0, "Sunday == 0");
is (Date::dayOfWeek ("Monday"), 1, "Monday == 1");
is (Date::dayOfWeek ("Tuesday"), 2, "Tuesday == 2");
is (Date::dayOfWeek ("Wednesday"), 3, "Wednesday == 3");
is (Date::dayOfWeek ("Thursday"), 4, "Thursday == 4");
is (Date::dayOfWeek ("Friday"), 5, "Friday == 5");
is (Date::dayOfWeek ("Saturday"), 6, "Saturday == 6");
t.is (Date::dayOfWeek ("SUNDAY"), 0, "SUNDAY == 0");
t.is (Date::dayOfWeek ("sunday"), 0, "sunday == 0");
t.is (Date::dayOfWeek ("Sunday"), 0, "Sunday == 0");
t.is (Date::dayOfWeek ("Monday"), 1, "Monday == 1");
t.is (Date::dayOfWeek ("Tuesday"), 2, "Tuesday == 2");
t.is (Date::dayOfWeek ("Wednesday"), 3, "Wednesday == 3");
t.is (Date::dayOfWeek ("Thursday"), 4, "Thursday == 4");
t.is (Date::dayOfWeek ("Friday"), 5, "Friday == 5");
t.is (Date::dayOfWeek ("Saturday"), 6, "Saturday == 6");
Date happyNewYear (1, 1, 2008);
is (happyNewYear.dayOfWeek (), 2, "1/1/2008 == Tuesday");
is (happyNewYear.month (), 1, "1/1/2008 == January");
is (happyNewYear.day (), 1, "1/1/2008 == 1");
is (happyNewYear.year (), 2008, "1/1/2008 == 2008");
t.is (happyNewYear.dayOfWeek (), 2, "1/1/2008 == Tuesday");
t.is (happyNewYear.month (), 1, "1/1/2008 == January");
t.is (happyNewYear.day (), 1, "1/1/2008 == 1");
t.is (happyNewYear.year (), 2008, "1/1/2008 == 2008");
is (now - yesterday, 1, "today - yesterday == 1");
t.is (now - yesterday, 1, "today - yesterday == 1");
is (happyNewYear.toString (), "1/1/2008", "toString 1/1/2008");
t.is (happyNewYear.toString (), "1/1/2008", "toString 1/1/2008");
int m, d, y;
happyNewYear.toMDY (m, d, y);
is (m, 1, "1/1/2008 == January");
is (d, 1, "1/1/2008 == 1");
is (y, 2008, "1/1/2008 == 2008");
t.is (m, 1, "1/1/2008 == January");
t.is (d, 1, "1/1/2008 == 1");
t.is (y, 2008, "1/1/2008 == 2008");
Date epoch (9, 8, 2001);
ok ((int)epoch.toEpoch () < 1000000000, "9/8/2001 < 1,000,000,000");
t.ok ((int)epoch.toEpoch () < 1000000000, "9/8/2001 < 1,000,000,000");
epoch += 86400;
ok ((int)epoch.toEpoch () > 1000000000, "9/9/2001 > 1,000,000,000");
t.ok ((int)epoch.toEpoch () > 1000000000, "9/9/2001 > 1,000,000,000");
Date fromEpoch (epoch.toEpoch ());
is (fromEpoch.toString (), epoch.toString (), "ctor (time_t)");
t.is (fromEpoch.toString (), epoch.toString (), "ctor (time_t)");
// Date parsing.
Date fromString1 ("1/1/2008");
is (fromString1.month (), 1, "ctor (std::string) -> m");
is (fromString1.day (), 1, "ctor (std::string) -> d");
is (fromString1.year (), 2008, "ctor (std::string) -> y");
t.is (fromString1.month (), 1, "ctor (std::string) -> m");
t.is (fromString1.day (), 1, "ctor (std::string) -> d");
t.is (fromString1.year (), 2008, "ctor (std::string) -> y");
Date fromString2 ("1/1/2008", "m/d/Y");
is (fromString2.month (), 1, "ctor (std::string) -> m");
is (fromString2.day (), 1, "ctor (std::string) -> d");
is (fromString2.year (), 2008, "ctor (std::string) -> y");
t.is (fromString2.month (), 1, "ctor (std::string) -> m");
t.is (fromString2.day (), 1, "ctor (std::string) -> d");
t.is (fromString2.year (), 2008, "ctor (std::string) -> y");
Date fromString3 ("20080101", "YMD");
is (fromString3.month (), 1, "ctor (std::string) -> m");
is (fromString3.day (), 1, "ctor (std::string) -> d");
is (fromString3.year (), 2008, "ctor (std::string) -> y");
t.is (fromString3.month (), 1, "ctor (std::string) -> m");
t.is (fromString3.day (), 1, "ctor (std::string) -> d");
t.is (fromString3.year (), 2008, "ctor (std::string) -> y");
Date fromString4 ("12/31/2007");
is (fromString4.month (), 12, "ctor (std::string) -> m");
is (fromString4.day (), 31, "ctor (std::string) -> d");
is (fromString4.year (), 2007, "ctor (std::string) -> y");
t.is (fromString4.month (), 12, "ctor (std::string) -> m");
t.is (fromString4.day (), 31, "ctor (std::string) -> d");
t.is (fromString4.year (), 2007, "ctor (std::string) -> y");
Date fromString5 ("12/31/2007", "m/d/Y");
is (fromString5.month (), 12, "ctor (std::string) -> m");
is (fromString5.day (), 31, "ctor (std::string) -> d");
is (fromString5.year (), 2007, "ctor (std::string) -> y");
t.is (fromString5.month (), 12, "ctor (std::string) -> m");
t.is (fromString5.day (), 31, "ctor (std::string) -> d");
t.is (fromString5.year (), 2007, "ctor (std::string) -> y");
Date fromString6 ("20071231", "YMD");
is (fromString6.month (), 12, "ctor (std::string) -> m");
is (fromString6.day (), 31, "ctor (std::string) -> d");
is (fromString6.year (), 2007, "ctor (std::string) -> y");
t.is (fromString6.month (), 12, "ctor (std::string) -> m");
t.is (fromString6.day (), 31, "ctor (std::string) -> d");
t.is (fromString6.year (), 2007, "ctor (std::string) -> y");
Date fromString7 ("01/01/2008", "m/d/Y");
is (fromString7.month (), 1, "ctor (std::string) -> m");
is (fromString7.day (), 1, "ctor (std::string) -> d");
is (fromString7.year (), 2008, "ctor (std::string) -> y");
t.is (fromString7.month (), 1, "ctor (std::string) -> m");
t.is (fromString7.day (), 1, "ctor (std::string) -> d");
t.is (fromString7.year (), 2008, "ctor (std::string) -> y");
// Relative dates.
Date r1 ("today");
ok (r1.sameDay (now), "today = now");
t.ok (r1.sameDay (now), "today = now");
Date r2 ("tomorrow");
ok (r2.sameDay (now + 86400), "tomorrow = now + 1d");
t.ok (r2.sameDay (now + 86400), "tomorrow = now + 1d");
Date r3 ("yesterday");
ok (r3.sameDay (now - 86400), "yesterday = now - 1d");
t.ok (r3.sameDay (now - 86400), "yesterday = now - 1d");
Date r4 ("sunday");
if (now.dayOfWeek () >= 0)
ok (r4.sameDay (now + (0 - now.dayOfWeek () + 7) * 86400), "next sunday");
t.ok (r4.sameDay (now + (0 - now.dayOfWeek () + 7) * 86400), "next sunday");
else
ok (r4.sameDay (now + (0 - now.dayOfWeek ()) * 86400), "next sunday");;
t.ok (r4.sameDay (now + (0 - now.dayOfWeek ()) * 86400), "next sunday");;
Date r5 ("monday");
if (now.dayOfWeek () >= 1)
ok (r5.sameDay (now + (1 - now.dayOfWeek () + 7) * 86400), "next monday");
t.ok (r5.sameDay (now + (1 - now.dayOfWeek () + 7) * 86400), "next monday");
else
ok (r5.sameDay (now + (1 - now.dayOfWeek ()) * 86400), "next monday");;
t.ok (r5.sameDay (now + (1 - now.dayOfWeek ()) * 86400), "next monday");;
Date r6 ("tuesday");
if (now.dayOfWeek () >= 2)
ok (r6.sameDay (now + (2 - now.dayOfWeek () + 7) * 86400), "next tuesday");
t.ok (r6.sameDay (now + (2 - now.dayOfWeek () + 7) * 86400), "next tuesday");
else
ok (r6.sameDay (now + (2 - now.dayOfWeek ()) * 86400), "next tuesday");;
t.ok (r6.sameDay (now + (2 - now.dayOfWeek ()) * 86400), "next tuesday");;
Date r7 ("wednesday");
if (now.dayOfWeek () >= 3)
ok (r7.sameDay (now + (3 - now.dayOfWeek () + 7) * 86400), "next wednesday");
t.ok (r7.sameDay (now + (3 - now.dayOfWeek () + 7) * 86400), "next wednesday");
else
ok (r7.sameDay (now + (3 - now.dayOfWeek ()) * 86400), "next wednesday");;
t.ok (r7.sameDay (now + (3 - now.dayOfWeek ()) * 86400), "next wednesday");;
Date r8 ("thursday");
if (now.dayOfWeek () >= 4)
ok (r8.sameDay (now + (4 - now.dayOfWeek () + 7) * 86400), "next thursday");
t.ok (r8.sameDay (now + (4 - now.dayOfWeek () + 7) * 86400), "next thursday");
else
ok (r8.sameDay (now + (4 - now.dayOfWeek ()) * 86400), "next thursday");;
t.ok (r8.sameDay (now + (4 - now.dayOfWeek ()) * 86400), "next thursday");;
Date r9 ("friday");
if (now.dayOfWeek () >= 5)
ok (r9.sameDay (now + (5 - now.dayOfWeek () + 7) * 86400), "next friday");
t.ok (r9.sameDay (now + (5 - now.dayOfWeek () + 7) * 86400), "next friday");
else
ok (r9.sameDay (now + (5 - now.dayOfWeek ()) * 86400), "next friday");;
t.ok (r9.sameDay (now + (5 - now.dayOfWeek ()) * 86400), "next friday");;
Date r10 ("saturday");
if (now.dayOfWeek () >= 6)
ok (r10.sameDay (now + (6 - now.dayOfWeek () + 7) * 86400), "next saturday");
t.ok (r10.sameDay (now + (6 - now.dayOfWeek () + 7) * 86400), "next saturday");
else
ok (r10.sameDay (now + (6 - now.dayOfWeek ()) * 86400), "next saturday");;
t.ok (r10.sameDay (now + (6 - now.dayOfWeek ()) * 86400), "next saturday");;
Date r11 ("eow");
ok (r11 < now + (8 * 86400), "eow < 7 days away");
t.ok (r11 < now + (8 * 86400), "eow < 7 days away");
Date r12 ("eom");
ok (r12.sameMonth (now), "eom in same month as now");
t.ok (r12.sameMonth (now), "eom in same month as now");
Date r13 ("eoy");
ok (r13.sameYear (now), "eoy in same year as now");
t.ok (r13.sameYear (now), "eoy in same year as now");
}
catch (std::string& e)
{
fail ("Exception thrown.");
diag (e);
t.fail ("Exception thrown.");
t.diag (e);
}
return 0;

72
src/tests/dateformat.t Executable file
View File

@@ -0,0 +1,72 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 8;
# Create the rc file.
if (open my $fh, '>', 'date1.rc')
{
print $fh "data.location=.\n",
"dateformat=YMD\n";
close $fh;
ok (-r 'date1.rc', 'Created date1.rc');
}
if (open my $fh, '>', 'date2.rc')
{
print $fh "data.location=.\n",
"dateformat=m/d/y\n";
close $fh;
ok (-r 'date2.rc', 'Created date2.rc');
}
qx{../task rc:date1.rc add foo due:20091231};
my $output = qx{../task rc:date1.rc info 1};
like ($output, qr/\b20091231\b/, 'date format YMD parsed');
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
qx{../task rc:date2.rc add foo due:12/1/09};
$output = qx{../task rc:date2.rc info 1};
like ($output, qr/\b12\/1\/09\b/, 'date format m/d/y parsed');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'date1.rc';
ok (!-r 'date1.rc', 'Removed date1.rc');
unlink 'date2.rc';
ok (!-r 'date2.rc', 'Removed date2.rc');
exit 0;

83
src/tests/default.t Executable file
View File

@@ -0,0 +1,83 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 16;
# Create the rc file.
if (open my $fh, '>', 'default.rc')
{
print $fh "data.location=.\n",
"default.command=list\n",
"default.project=PROJECT\n",
"default.priority=M\n";
close $fh;
ok (-r 'default.rc', 'Created default.rc');
}
# Set up a default command, project and priority.
qx{../task rc:default.rc add all defaults};
my $output = qx{../task rc:default.rc list};
like ($output, qr/ all defaults/, 'task added');
like ($output, qr/ PROJECT /, 'default project added');
like ($output, qr/ M /, 'default priority added');
unlink 'pending.data';
qx{../task rc:default.rc add project:specific priority:L all specified};
$output = qx{../task rc:default.rc list};
like ($output, qr/ all specified/, 'task added');
like ($output, qr/ specific /, 'project specified');
like ($output, qr/ L /, 'priority specified');
unlink 'pending.data';
qx{../task rc:default.rc add project:specific project specified};
$output = qx{../task rc:default.rc list};
like ($output, qr/ project specified/, 'task added');
like ($output, qr/ specific /, 'project specified');
like ($output, qr/ M /, 'default priority added');
unlink 'pending.data';
qx{../task rc:default.rc add priority:L priority specified};
$output = qx{../task rc:default.rc list};
like ($output, qr/ priority specified/, 'task added');
like ($output, qr/ PROJECT /, 'default project added');
like ($output, qr/ L /, 'priority specified');
$output = qx{../task rc:default.rc};
like ($output, qr/1 PROJECT L .+ priority specified/, 'default command worked');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'default.rc';
ok (!-r 'default.rc', 'Removed default.rc');
exit 0;

78
src/tests/delete.t Executable file
View File

@@ -0,0 +1,78 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 16;
# Create the rc file.
if (open my $fh, '>', 'undelete.rc')
{
print $fh "data.location=.\n",
"echo.command=no\n";
close $fh;
ok (-r 'undelete.rc', 'Created undelete.rc');
}
# Add a task, delete it, undelete it.
my $output = qx{../task rc:undelete.rc add one; ../task rc:undelete.rc info 1};
ok (-r 'pending.data', 'pending.data created');
like ($output, qr/Status\s+Pending\n/, 'Pending');
$output = qx{../task rc:undelete.rc delete 1; ../task rc:undelete.rc info 1};
like ($output, qr/Status\s+Deleted\n/, 'Deleted');
ok (! -r 'completed.data', 'completed.data not created');
$output = qx{../task rc:undelete.rc undelete 1; ../task rc:undelete.rc info 1};
like ($output, qr/Status\s+Pending\n/, 'Pending');
ok (! -r 'completed.data', 'completed.data not created');
$output = qx{../task rc:undelete.rc delete 1; ../task rc:undelete.rc list};
like ($output, qr/^No matches/, 'No matches');
ok (-r 'completed.data', 'completed.data created');
$output = qx{../task rc:undelete.rc undelete 1};
like ($output, qr/reliably undeleted/, 'can only be reliable undeleted...');
$output = qx{../task rc:undelete.rc info 1};
like ($output, qr/No matches./, 'no matches');
# Cleanup.
ok (-r 'pending.data', 'Need to remove pending.data');
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
ok (-r 'completed.data', 'Need to remove completed.data');
unlink 'completed.data';
ok (!-r 'completed.data', 'Removed completed.data');
unlink 'undelete.rc';
ok (!-r 'undelete.rc', 'Removed undelete.rc');
exit 0;

67
src/tests/due.t Executable file
View File

@@ -0,0 +1,67 @@
#! /usr/bin/perl
################################################################################
## task - a command line task list manager.
##
## Copyright 2006 - 2009, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 5;
# Create the rc file.
if (open my $fh, '>', 'due.rc')
{
print $fh "data.location=.\n",
"due=4\n",
"color=on\n",
"color.due=red\n",
"_forcecolor=on\n",
"dateformat=m/d/Y\n";
close $fh;
ok (-r 'due.rc', 'Created due.rc');
}
# Add a task that is almost due, and one that is just due.
my ($d, $m, $y) = (localtime (time + 3 * 86_400))[3..5];
my $just = sprintf ("%d/%d/%d", $m + 1, $d, $y + 1900);
($d, $m, $y) = (localtime (time + 5 * 86_400))[3..5];
my $almost = sprintf ("%d/%d/%d", $m + 1, $d, $y + 1900);
qx{../task rc:due.rc add one due:$just};
qx{../task rc:due.rc add two due:$almost};
my $output = qx{../task rc:due.rc list};
like ($output, qr/\[31m.+$just.+\[0m/, 'one marked due');
like ($output, qr/\s+$almost\s+/, 'two not marked due');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'due.rc';
ok (!-r 'due.rc', 'Removed due.rc');
exit 0;

View File

@@ -1,5 +1,27 @@
////////////////////////////////////////////////////////////////////////////////
// Copyright 2005 - 2008, Paul Beckingham. All rights reserved.
// task - a command line task list manager.
//
// Copyright 2006 - 2009, Paul Beckingham.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#include <iostream>
@@ -16,27 +38,27 @@
// biannual, biyearly, annual, semiannual, yearly, Ny
int main (int argc, char** argv)
{
plan (17);
UnitTest t (17);
std::string d;
d = "daily"; is (convertDuration (d), 1, "duration daily = 1");
d = "day"; is (convertDuration (d), 1, "duration day = 1");
d = "0d"; is (convertDuration (d), 0, "duration 0d = 0");
d = "1d"; is (convertDuration (d), 1, "duration 1d = 1");
d = "7d"; is (convertDuration (d), 7, "duration 7d = 7");
d = "10d"; is (convertDuration (d), 10, "duration 10d = 10");
d = "100d"; is (convertDuration (d), 100, "duration 100d = 100");
d = "daily"; t.is (convertDuration (d), 1, "duration daily = 1");
d = "weekdays"; t.is (convertDuration (d), 1, "duration weekdays = 1");
d = "day"; t.is (convertDuration (d), 1, "duration day = 1");
d = "0d"; t.is (convertDuration (d), 0, "duration 0d = 0");
d = "1d"; t.is (convertDuration (d), 1, "duration 1d = 1");
d = "7d"; t.is (convertDuration (d), 7, "duration 7d = 7");
d = "10d"; t.is (convertDuration (d), 10, "duration 10d = 10");
d = "100d"; t.is (convertDuration (d), 100, "duration 100d = 100");
d = "weekly"; is (convertDuration (d), 7, "duration weekly = 7");
d = "sennight"; is (convertDuration (d), 7, "duration sennight = 7");
d = "biweekly"; is (convertDuration (d), 14, "duration biweekly = 14");
d = "fortnight"; is (convertDuration (d), 14, "duration fortnight = 14");
d = "week"; is (convertDuration (d), 7, "duration week = 7");
d = "0w"; is (convertDuration (d), 0, "duration 0w = 0");
d = "1w"; is (convertDuration (d), 7, "duration 1w = 7");
d = "7w"; is (convertDuration (d), 49, "duration 7w = 49");
d = "10w"; is (convertDuration (d), 70, "duration 10w = 70");
d = "100w"; is (convertDuration (d), 700, "duration 100w = 700");
d = "weekly"; t.is (convertDuration (d), 7, "duration weekly = 7");
d = "sennight"; t.is (convertDuration (d), 7, "duration sennight = 7");
d = "biweekly"; t.is (convertDuration (d), 14, "duration biweekly = 14");
d = "fortnight"; t.is (convertDuration (d), 14, "duration fortnight = 14");
d = "0w"; t.is (convertDuration (d), 0, "duration 0w = 0");
d = "1w"; t.is (convertDuration (d), 7, "duration 1w = 7");
d = "7w"; t.is (convertDuration (d), 49, "duration 7w = 49");
d = "10w"; t.is (convertDuration (d), 70, "duration 10w = 70");
d = "100w"; t.is (convertDuration (d), 700, "duration 100w = 700");
return 0;
}

Some files were not shown because too many files have changed in this diff Show More