Compare commits

..

94 Commits

Author SHA1 Message Date
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
103 changed files with 5831 additions and 1660 deletions

2
.gitignore vendored
View File

@@ -1,4 +1,3 @@
Makefile.in
aclocal.m4
autom4te.cache
auto.h*
@@ -11,3 +10,4 @@ stamp-h1
Makefile
configure
config.log
www.xls

View File

@@ -5,6 +5,9 @@ Contributing Authors:
Damian Glenny
Andy Lester
H. İbrahim Güngör
Stefan Dorn
Michael Greb
Benjamin Tegarden
With thanks to:
Eugene Kramer
@@ -18,4 +21,8 @@ With thanks to:
Vincent Fleuranceau
T. Charles Yun
ArchiMark
Carlos Yoder
Russell Friesenhahn
Paolo Marsi
Eric Farris

View File

@@ -1,7 +1,7 @@
------ current release ---------------------------
1.5.0 (?)
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.
@@ -11,10 +11,41 @@
which may be spelling mistakes or deprecated variables.
+ "configure --enable-debug" now supported to suppress compiler optimization
to allow debugging.
+ Allow lower case priorities, and automatically upper case them.
+ Added support for "due" configuration variable which defines the number
of days in the future when a task is considered due.
+ Added support for custom reports, comprised of a set of column names and
sort order, with optional filtering in the configuration file. This
means user-defined reports can be written, and the reports currently
in the configuration file can be renamed. Several of task's built in
reports have been converted to user-defined reports.
+ New online documentation for custom reports.
+ New algorithm for determining when the "nag" message is displayed.
+ Fixed bug where task hangs with a certain combination of recurring tasks
and shadow files.
+ Fixed bug with the task sort algorithm, which led to an unstable sequence
when there were only a handful of tasks.
+ Performance enhanced by eliminating unnecessary sorting.
+ Task now has a large (and growing) test suite and bug regression tests
to help ensure higher quality releases.
+ Fixed bug that caused performance hit during table rendering.
+ Fixed bug that concatenated a modified description without spaces.
+ Added new column 'recur' that displays the recurrence period of any
recurring tasks. This column can be added to any custom report.
+ Added support for "color.recurring" configuration variable which
specifies the color of recurring tasks.
+ Added support for "locking" configuration variable that controls whether
file locking is used.
+ Task export feature now includes recurrence information, removes nested
quotes, and limits output to pending tasks.
+ Task no longer includes deleted tasks in the summary report (thanks to
Benjamin Tegarden).
+ Fixed bug that prevented the summary report from properly reporting
recently completed tasks.
------ old releases ------------------------------
1.4.3 (11/1/2008)
1.4.3 (11/1/2008) 8639e9260646c8c9224e0fc47e5d2443b46eecfc
+ Fixed misleading task count at bottom on "info" report.
+ Added support for a shadow file that contains a plain text task report,
with the "shadow.file" and "shadow.command" configuration variables
@@ -28,7 +59,7 @@
+ Added documentation for Shadow files.
+ Added documentation for task filters.
1.4.2 (9/18/2008)
1.4.2 (9/18/2008) e7304e86ce9bb80978c7055fd2a9e999619a6fb8
+ "task undo" can now retract a "task done" command, provided no reports
have been run (and therefore TDB::gc run)
+ Task now correctly sorts on entire strings, instead of just the first
@@ -51,13 +82,13 @@
+ Bug: Source now properly includes <string.h> in order to build clean
using gcc 4.3 (thanks to H. İbrahim Güngör)
1.4.1 (7/18/2008)
1.4.1 (7/18/2008) e080c3168c6064628ab85b21bd859d9875a3a9a7
+ Bug: Descriptions can not be altered with "task 123 New description"
+ Tweak: For "task calendar" month names are now centered over the month
+ Removed TUTORIAL file contents in favor of online version
+ Provided Mac .pkg binary
1.4.0 (7/10/2008)
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)
@@ -75,7 +106,7 @@
+ 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
+ Bug: "showage" configuration variable should apply to all reports, not
@@ -86,7 +117,7 @@
+ Bug: Task now will recreate a missing ~/.taskrc file, OR a missing
~/.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
@@ -101,7 +132,7 @@
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
+ "task list x" now performs a caseless comparison between "x" and the
@@ -111,7 +142,7 @@
"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
@@ -119,11 +150,11 @@
+ 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)
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
@@ -136,19 +167,19 @@
+ 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)
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.

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:

4
NEWS
View File

@@ -6,8 +6,10 @@ 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
- Ubunto 8.10 Intrepid Ibex
- Solaris 10
- Cygwin 1.5.25-14

View File

@@ -4,7 +4,6 @@
AC_PREREQ(2.61)
AC_INIT(task, 1.5.0, bugs@beckingham.net)
CFLAGS="${CFLAGS=}"
CXXFLAGS="${CXXFLAGS=}"
# this macro is used to get the arguments supplied
@@ -15,16 +14,23 @@ debug_default="yes"
AC_ARG_ENABLE(debug, [ --enable-debug=[no/yes] turn on debugging
[default=$debug_default]],, enable_debug=$debug_default)
# Yes, shell scripts can be used
if test "x$enable_debug" = "xyes"; then
CFLAGS="$CFLAGS -Wall -pedantic -ggdb3 -DDEBUG"
CXXFLAGS="$CFLAGS -Wall -pedantic -ggdb3 -DDEBUG"
AC_MSG_RESULT(yes)
if test "$enable_debug" = "yes"; then
CXXFLAGS="$CFLAGS -Wall -pedantic -ggdb3 -DDEBUG"
AC_MSG_RESULT(yes)
else
CFLAGS="$CFLAGS -O3"
CXXFLAGS="$CFLAGS -O3"
AC_MSG_RESULT(no)
CXXFLAGS="$CFLAGS -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])
@@ -58,10 +64,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* "/" ;

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

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

@@ -398,7 +398,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

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

@@ -174,19 +174,9 @@
<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>
@@ -195,6 +185,14 @@
Defaults to 80.
</dd>
<dt>due</dt>
<dd>
This is the number of days into the future that define when a
task is considered due, and is colored accordingly.
Defaults to 7.
</dd>
<dt>color</dt>
<dd>
May be "on" or "off". Determines whether task uses color.
@@ -210,7 +208,8 @@
color.pri.L<br />
color.pri.none<br />
color.active<br />
color.tagged
color.tagged<br />
color.recurring
</dt>
<dd>
These are the coloration rules. They correspond to a particular
@@ -316,6 +315,21 @@ ID Project Pri Description
whenever the shadow file is updated by some task command.
</dd>
<dt>locking</dt>
<dd>
<p>
Determines whether task uses file locking when accessing the pending.data
and completed.data files. Default to "on". Solaris users who store
the task data files on an NFS mount may need to set locking to "off".
</p>
<p>
Note that setting this value to "off" is dangerous. It means that
another program may write to the task.pending file when task is
attempting to do the same.
</p>
</dd>
<p>
Note that the command:
</p>
@@ -332,7 +346,7 @@ ID Project Pri Description
<br />
<div class="content">
<p>
Copyright 2006-2008, P. Beckingham. All rights reserved.
Copyright 2006-2009, P. Beckingham. All rights reserved.
</p>
</div>

164
html/custom.html Normal file
View File

@@ -0,0 +1,164 @@
<!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>
<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
</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

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

View File

@@ -82,7 +82,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

@@ -37,6 +37,32 @@
Task links from around the web...
</p>
<dt>
February 2009, <a href="http://lifehacker.com/5155450/todotxt-cli-manages-your-tasks-from-the-command-line">Todo.txt CLI Manages Your Tasks from the Command Line</a>
</dt>
<dd>
Gina Trapani generously mentions task in an article about the newly updated, todo.sh 2.0.
</dd>
<br>
<dt>
February, 2009, <a href="http://forum.worklifecreativity.net/index.php/topic,219.0.html">My command line based task management tools</a>
</dt>
<dd>
Richard Querin talks about his task management tools.
Richard generously provides the Debian packages for task.
</dd>
<br>
<dt>
February, 2009, <a href="http://wiki.archlinux.org/index.php/Common_Apps">Common Apps</a>
</dt>
<dd>
<a href="http://wiki.archlinux.org">Archlinux.org</a> mentions task on a page which is
a point of reference for people looking for software to fill a particular need.
</dd>
<br>
<dt>
November 2008, <a href="http://github.com/pbeckingham/task/tree/master/">Task repository on GitHub</a>
</dt>
@@ -137,7 +163,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

@@ -155,7 +155,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

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

View File

@@ -43,7 +43,7 @@
<p>
This means there is always a current version of the task
report kept in a text file. Products such as
<a href="www.samurize.com">Samurize</a>,
<a href="http://www.samurize.com">Samurize</a>,
<a href="http://www.mulle-kybernetik.com/software/MkConsole/">MkConsole</a>,
or
<a href="http://projects.tynsoe.org/en/geektool/">GeekTool</a>
@@ -75,7 +75,7 @@ shadow.command=list pri:H</code></pre>
<br />
<div class="content">
<p>
Copyright 2006-2008, P. Beckingham. All rights reserved.
Copyright 2006-2009, P. Beckingham. All rights reserved.
</p>
</div>

View File

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

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

@@ -57,6 +57,7 @@
<li><a href="versions.html">Old Versions</a>
<li><a href="filter.html">Filters</a>
<li><a href="shadow.html">Shadow Files</a>
<li><a href="custom.html">Custom Reports</a>
</ul>
<p>
@@ -70,7 +71,7 @@
</p>
<br />
<h2 class="title">Get the Latest Release</h2>
<h2 class="title">Get the Latest Stable Release</h2>
<div class="content">
<table>
@@ -93,7 +94,7 @@
-->
</table>
<h4>New in version 1.5.0 (?)</h4>
<h4>New in version 1.5.0 (3/15/2009)</h4>
<ul>
<li>Removed deprecated TUTORIAL file.
<li>Removed support for the "showage" configuration variable.
@@ -104,27 +105,86 @@
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>
(Find out <a href="versions.html">what was new in prior versions</a>)
</p>
<!--
<h2>Task 1.5.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.5.0beta.tar.gz">task-1.5.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
@@ -143,7 +203,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

@@ -87,7 +87,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

@@ -34,12 +34,10 @@
<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 completed [tags] [attrs] desc...
task ID [tags] [attrs] ["desc..."]
task ID [tags] [attrs] [desc...]
task ID /from/to/
task delete ID
task undelete ID
@@ -57,12 +55,18 @@
task calendar
task active
task overdue
task oldest
task newest
task stats
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
@@ -74,8 +78,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
@@ -86,14 +93,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

@@ -250,7 +250,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

@@ -3,18 +3,18 @@
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
Oh, I spelled bike wrong
task 5 /bkie/bike/
task ls That's better
@@ -97,6 +97,10 @@ task summary Summary shows progress on all projec
task history History shows general activity - how many added,
completed etc, by month
task ghistory This report shows a histogram of tasks that were
added (in red), completed (in green) and deleted
(in yellow), all by month.
And that's it. There are more commands than this
covered in the online documentation, but this should give
the basic idea.

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,35 @@
#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.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.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.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.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.sort"] = "id+";
(*this)["report.oldest.limit"] = "10";
}
////////////////////////////////////////////////////////////////////////////////
@@ -47,9 +74,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;
@@ -115,24 +142,60 @@ void Config::createDefault (const std::string& home)
fprintf (out, "confirmation=yes\n");
fprintf (out, "next=2\n");
fprintf (out, "dateformat=m/d/Y\n");
fprintf (out, "monthsperline=1\n");
fprintf (out, "#monthsperline=2\n");
fprintf (out, "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.command=list\n");
fprintf (out, "#default.project=foo\n");
fprintf (out, "#default.priority=M\n");
fprintf (out, "default.command=list\n");
// Custom reports.
fprintf (out, "# Fields: id,uuid,project,priority,entry,start,due,recur,age,active,tags,description\n");
fprintf (out, "# Description: 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);
@@ -191,11 +254,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,2 +1,2 @@
bin_PROGRAMS = task
task_SOURCES = Config.cpp Date.cpp T.cpp TDB.cpp Table.cpp Grid.cpp color.cpp parse.cpp task.cpp command.cpp report.cpp util.cpp text.cpp rules.cpp Config.h Date.h T.h TDB.h Table.h Grid.h color.h task.h
task_SOURCES = Config.cpp Date.cpp T.cpp TDB.cpp Table.cpp Grid.cpp Timer.cpp color.cpp parse.cpp task.cpp command.cpp report.cpp util.cpp text.cpp rules.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)
task_OBJECTS = $(am_task_OBJECTS)
task_LDADD = $(LDADD)
DEFAULT_INCLUDES = -I. -I$(top_builddir)@am__isrc@
@@ -154,7 +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
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 Config.h Date.h T.h TDB.h Table.h Grid.h Timer.h color.h task.h
all: all-am
.SUFFIXES:
@@ -227,6 +228,7 @@ 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)/parse.Po@am__quote@

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
@@ -328,6 +328,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 +358,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;
}
@@ -468,7 +477,7 @@ void T::parse (const std::string& line)
break;
default:
throw std::string ();
throw std::string ("Unrecognized task file format.");
break;
}
}

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
@@ -38,6 +38,7 @@ TDB::TDB ()
: mPendingFile ("")
, mCompletedFile ("")
, mId (1)
, mNoLock (false)
{
}
@@ -289,11 +290,10 @@ bool TDB::modifyT (const T& t)
////////////////////////////////////////////////////////////////////////////////
bool TDB::lock (FILE* file) const
{
#ifdef HAVE_FLOCK
if (mNoLock)
return true;
return flock (fileno (file), LOCK_EX) ? false : true;
#else
return true;
#endif
}
////////////////////////////////////////////////////////////////////////////////
@@ -303,18 +303,16 @@ bool TDB::overwritePending (std::vector <T>& all)
FILE* out;
if ((out = fopen (mPendingFile.c_str (), "w")))
{
#ifdef HAVE_FLOCK
int retry = 0;
while (flock (fileno (out), LOCK_EX) && ++retry <= 3)
delay (0.25);
#endif
if (!mNoLock)
while (flock (fileno (out), LOCK_EX) && ++retry <= 3)
delay (0.1);
std::vector <T>::iterator it;
for (it = all.begin (); it != all.end (); ++it)
fputs (it->compose ().c_str (), out);
fclose (out);
dbChanged ();
return true;
}
@@ -328,16 +326,14 @@ bool TDB::writePending (const T& t)
FILE* out;
if ((out = fopen (mPendingFile.c_str (), "a")))
{
#ifdef HAVE_FLOCK
int retry = 0;
while (flock (fileno (out), LOCK_EX) && ++retry <= 3)
delay (0.25);
#endif
if (!mNoLock)
while (flock (fileno (out), LOCK_EX) && ++retry <= 3)
delay (0.1);
fputs (t.compose ().c_str (), out);
fclose (out);
dbChanged ();
return true;
}
@@ -351,17 +347,14 @@ bool TDB::writeCompleted (const T& t)
FILE* out;
if ((out = fopen (mCompletedFile.c_str (), "a")))
{
#ifdef HAVE_FLOCK
int retry = 0;
while (flock (fileno (out), LOCK_EX) && ++retry <= 3)
delay (0.25);
#endif
if (!mNoLock)
while (flock (fileno (out), LOCK_EX) && ++retry <= 3)
delay (0.1);
fputs (t.compose ().c_str (), out);
fclose (out);
// Note: No call to dbChanged here because this call never occurs by itself.
// It is always accompanied by an overwritePending call.
return true;
}
@@ -380,11 +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))
@@ -406,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;
@@ -423,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
@@ -448,19 +444,9 @@ int TDB::nextId ()
}
////////////////////////////////////////////////////////////////////////////////
void TDB::onChange (void (*callback)())
void TDB::noLock ()
{
if (callback)
mOnChange.push_back (callback);
}
////////////////////////////////////////////////////////////////////////////////
// Iterate over callbacks.
void TDB::dbChanged ()
{
foreach (i, mOnChange)
if (*i)
(**i) ();
mNoLock = true;
}
////////////////////////////////////////////////////////////////////////////////

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
@@ -51,7 +51,7 @@ public:
int gc ();
int nextId ();
void onChange (void (*)());
void noLock ();
private:
bool lock (FILE*) const;
@@ -59,13 +59,12 @@ private:
bool writePending (const T&);
bool writeCompleted (const T&);
bool readLockedFile (const std::string&, std::vector <std::string>&) const;
void dbChanged ();
private:
std::string mPendingFile;
std::string mCompletedFile;
int mId;
std::vector <void (*)()> mOnChange;
bool mNoLock;
};
#endif

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
@@ -736,34 +736,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 +826,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 +847,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 +929,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 +994,7 @@ void Table::clean (std::string& value)
}
////////////////////////////////////////////////////////////////////////////////
const std::string Table::render ()
const std::string Table::render (int maximum /* = 0 */)
{
calculateColumnWidths ();
@@ -946,8 +1028,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 +1069,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

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
@@ -48,8 +48,10 @@
#endif
////////////////////////////////////////////////////////////////////////////////
void handleAdd (TDB& tdb, T& task, Config& conf)
std::string handleAdd (TDB& tdb, T& task, Config& conf)
{
std::stringstream out;
char entryTime[16];
sprintf (entryTime, "%u", (unsigned int) time (NULL));
task.setAttribute ("entry", entryTime);
@@ -86,6 +88,8 @@ void handleAdd (TDB& tdb, T& task, Config& conf)
if (!tdb.addT (task))
throw std::string ("Could not create new task.");
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
@@ -113,7 +117,7 @@ std::string handleProjects (TDB& tdb, T& task, Config& conf)
table.addColumn ("Project");
table.addColumn ("Tasks");
if (conf.get ("color", true))
if (conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false))
{
table.setColumnUnderline (0);
table.setColumnUnderline (1);
@@ -307,7 +311,9 @@ std::string handleVersion (Config& conf)
link.setColumnWidth (0, Table::flexible);
link.setColumnJustification (0, Table::left);
link.addCell (link.addRow (), 0,
"See http://www.beckingham.net/task.html for the latest releases and a full tutorial.");
"See http://www.beckingham.net/task.html for the latest releases and a "
"full tutorial. New releases containing fixes and enhancements are "
"made frequently.");
// Create a table for output.
Table table;
@@ -316,7 +322,7 @@ std::string handleVersion (Config& conf)
table.addColumn ("Config variable");
table.addColumn ("Value");
if (conf.get ("color", true))
if (conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false))
{
table.setColumnUnderline (0);
table.setColumnUnderline (1);
@@ -343,11 +349,15 @@ std::string handleVersion (Config& conf)
}
}
out << "Copyright (C) 2006 - 2008, P. Beckingham."
out << "Copyright (C) 2006 - 2009, P. Beckingham."
<< std::endl
<< (conf.get ("color", true) ? Text::colorize (Text::bold, Text::nocolor, PACKAGE) : PACKAGE)
<< ((conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false))
? Text::colorize (Text::bold, Text::nocolor, PACKAGE)
: PACKAGE)
<< " "
<< (conf.get ("color", true) ? Text::colorize (Text::bold, Text::nocolor, VERSION) : VERSION)
<< ((conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false))
? Text::colorize (Text::bold, Text::nocolor, VERSION)
: VERSION)
<< std::endl
<< disclaimer.render ()
<< std::endl
@@ -359,10 +369,15 @@ std::string handleVersion (Config& conf)
// These are the regular configuration variables.
std::string recognized =
"blanklines color color.active color.due color.overdue color.pri.H "
"color.pri.L color.pri.M color.pri.none color.tagged confirmation curses "
"data.location dateformat default.command default.priority defaultwidth due "
"monthsperline nag newest next oldest project shadow.command shadow.file "
"shadow.notify";
"color.pri.L color.pri.M color.pri.none color.recurring color.tagged "
"confirmation curses data.location dateformat default.command "
"default.priority defaultwidth due locking monthsperline nag next project "
"shadow.command shadow.file shadow.notify";
// This configuration variable is supported, but not documented. It exists
// so that unit tests can force color to be on even when the output from task
// is redirected to a file, or stdout is not a tty.
recognized += " _forcecolor";
std::vector <std::string> unrecognized;
foreach (i, all)
@@ -520,7 +535,6 @@ std::string handleStop (TDB& tdb, T& task, Config& conf)
original.setId (task.getId ());
tdb.modifyT (original);
nag (tdb, task, conf);
return std::string ("");
}
else
@@ -537,8 +551,10 @@ std::string handleStop (TDB& tdb, T& task, Config& conf)
}
////////////////////////////////////////////////////////////////////////////////
void handleDone (TDB& tdb, T& task, Config& conf)
std::string handleDone (TDB& tdb, T& task, Config& conf)
{
std::stringstream out;
if (!tdb.completeT (task))
throw std::string ("Could not mark task as completed.");
@@ -556,11 +572,14 @@ void handleDone (TDB& tdb, T& task, Config& conf)
}
nag (tdb, task, conf);
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
void handleExport (TDB& tdb, T& task, Config& conf)
std::string handleExport (TDB& tdb, T& task, Config& conf)
{
std::stringstream output;
// Use the description as a file name, then clobber the description so the
// file name isn't used for filtering.
std::string file = trim (task.getDescription ());
@@ -578,6 +597,7 @@ void handleExport (TDB& tdb, T& task, Config& conf)
<< "'entry',"
<< "'start',"
<< "'due',"
<< "'recur',"
<< "'end',"
<< "'project',"
<< "'priority',"
@@ -586,25 +606,36 @@ void handleExport (TDB& tdb, T& task, Config& conf)
<< "'description'"
<< "\n";
int count = 0;
std::vector <T> all;
tdb.allT (all);
tdb.allPendingT (all);
filter (all, task);
foreach (t, all)
{
out << t->composeCSV ().c_str ();
if (t->getStatus () != T::recurring &&
t->getStatus () != T::deleted)
{
out << t->composeCSV ().c_str ();
++count;
}
}
out.close ();
output << count << " tasks exported to '" << file << "'" << std::endl;
}
else
throw std::string ("Could not write to export file.");
}
else
throw std::string ("You must specify a file to write to.");
return output.str ();
}
////////////////////////////////////////////////////////////////////////////////
void handleModify (TDB& tdb, T& task, Config& conf)
std::string handleModify (TDB& tdb, T& task, Config& conf)
{
std::stringstream out;
std::vector <T> all;
tdb.pendingT (all);
@@ -685,11 +716,12 @@ void handleModify (TDB& tdb, T& task, Config& conf)
tdb.modifyT (original);
}
return;
return out.str ();
}
}
throw std::string ("Task not found.");
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
@@ -697,7 +729,7 @@ std::string handleColor (Config& conf)
{
std::stringstream out;
if (conf.get ("color", true))
if (conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false))
{
out << optionalBlankLine (conf) << "Foreground" << std::endl
<< " "

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
@@ -130,12 +130,7 @@ static const char* commands[] =
"history",
"ghistory",
"info",
"list",
"long",
"ls",
"newest",
"next",
"oldest",
"overdue",
"projects",
"start",
@@ -164,7 +159,6 @@ void guess (const std::string& type, const char** list, std::string& candidate)
candidate = matches[0];
else if (0 == matches.size ())
// throw std::string ("Unrecognized ") + type + " '" + candidate + "'";
candidate = "";
else
@@ -463,12 +457,20 @@ void parse (
if (isCommand (l) && validCommand (l))
command = l;
else
descCandidate += arg;
{
if (descCandidate.length ())
descCandidate += " ";
descCandidate += std::string (arg);
}
}
// Anything else is just considered description.
else
descCandidate += std::string (arg) + " ";
{
if (descCandidate.length ())
descCandidate += " ";
descCandidate += std::string (arg);
}
}
}
@@ -495,7 +497,7 @@ void loadCustomReports (Config& conf)
if (i->substr (0, 7) == "report.")
{
std::string report = i->substr (7, std::string::npos);
unsigned int columns = report.find (".columns");
std::string::size_type columns = report.find (".columns");
if (columns != std::string::npos)
{
report = report.substr (0, columns);
@@ -515,4 +517,10 @@ bool isCustomReport (const std::string& report)
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,13 +48,9 @@
#endif
////////////////////////////////////////////////////////////////////////////////
// Globals for exclusive use by callback function.
static TDB* gTdb = NULL;
static Config* gConf = NULL;
////////////////////////////////////////////////////////////////////////////////
static void shortUsage (Config& conf)
static std::string shortUsage (Config& conf)
{
std::stringstream out;
Table table;
int width = conf.get ("defaultwidth", 80);
#ifdef HAVE_LIBNCURSES
@@ -87,18 +84,6 @@ static void shortUsage (Config& conf)
table.addCell (row, 1, "task add [tags] [attrs] desc...");
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");
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");
row = table.addRow ();
table.addCell (row, 1, "task completed [tags] [attrs] desc...");
table.addCell (row, 2, "Chronological listing of all completed tasks matching the specified criteria");
@@ -175,14 +160,6 @@ 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");
@@ -203,46 +180,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 ();
}
////////////////////////////////////////////////////////////////////////////////
@@ -274,9 +270,6 @@ void loadConfFile (int argc, char** argv, Config& conf)
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{
// TODO Find out what this is, and either promote it to live code, or remove it.
// std::set_terminate (__gnu_cxx::__verbose_terminate_handler);
// Set up randomness.
#ifdef HAVE_SRANDOM
srandom (time (NULL));
@@ -289,22 +282,26 @@ int main (int argc, char** argv)
// Load the config file from the home directory. If the file cannot be
// found, offer to create a sample one.
Config conf;
gConf = &conf;
loadConfFile (argc, argv, conf);
// When redirecting output to a file, do not use color, curses.
if (!isatty (fileno (stdout)))
{
conf.set ("curses", "off");
conf.set ("color", "off");
if (! conf.get (std::string ("_forcecolor"), false))
conf.set ("color", "off");
}
TDB tdb;
gTdb = &tdb;
std::string dataLocation = expandPath (conf.get ("data.location"));
tdb.dataDirectory (dataLocation);
// Set up TDB callback.
// Allow user override of file locking. Solaris/NFS machines may want this.
if (! conf.get ("locking", true))
tdb.noLock ();
// Check for silly shadow file settings.
std::string shadowFile = expandPath (conf.get ("shadow.file"));
if (shadowFile != "")
{
@@ -315,8 +312,6 @@ int main (int argc, char** argv)
if (shadowFile == dataLocation + "/completed.data")
throw std::string ("Configuration variable 'shadow.file' is set to "
"overwrite your completed tasks. Please change it.");
tdb.onChange (&onChangeCallback);
}
std::cout << runTaskCommand (argc, argv, tdb, conf);
@@ -343,18 +338,56 @@ void nag (TDB& tdb, T& task, Config& conf)
std::string nagMessage = conf.get ("nag", std::string (""));
if (nagMessage != "")
{
// Load all pending.
// Load all pending tasks.
std::vector <T> pending;
tdb.allPendingT (pending);
// Restrict to matching subset.
std::vector <int> matching;
gatherNextTasks (tdb, task, conf, pending, matching);
// Counters.
int overdue = 0;
int high = 0;
int medium = 0;
int low = 0;
bool isOverdue = false;
char pri = ' ';
foreach (i, matching)
if (pending[*i].getId () == task.getId ())
return;
// Scan all pending tasks.
foreach (t, pending)
{
if (t->getId () == task.getId ())
{
if (getDueState (t->getAttribute ("due")) == 2)
isOverdue = true;
std::string priority = t->getAttribute ("priority");
if (priority.length ())
pri = priority[0];
}
else if (t->getStatus () == T::pending)
{
if (getDueState (t->getAttribute ("due")) == 2)
overdue++;
std::string priority = t->getAttribute ("priority");
if (priority.length ())
{
switch (priority[0])
{
case 'H': high++; break;
case 'M': medium++; break;
case 'L': low++; break;
}
}
}
}
// General form is "if there are no more deserving tasks", suppress the nag.
if (isOverdue ) return;
if (pri == 'H' && !overdue ) return;
if (pri == 'M' && !overdue && !high ) return;
if (pri == 'L' && !overdue && !high && !medium ) return;
if (pri == ' ' && !overdue && !high && !medium && !low) return;
// All the excuses are made, all that remains is to nag the user.
std::cout << nagMessage << std::endl;
}
}
@@ -372,15 +405,12 @@ int getDueState (const std::string& due)
// rightNow is the current date + time.
Date rightNow;
Date midnight (rightNow.month (), rightNow.day (), rightNow.year ());
// By performing this conversion, today is set up as the same date, but
// midnight.
Date today (rightNow.month (), rightNow.day (), rightNow.year ());
if (dt < today)
if (dt < midnight)
return 2;
Date nextweek = today + 7 * 86400;
Date nextweek = midnight + 7 * 86400;
if (dt < nextweek)
return 1;
}
@@ -672,51 +702,43 @@ void updateRecurrenceMask (
}
////////////////////////////////////////////////////////////////////////////////
// Using gTdb and gConf, generate a report.
void onChangeCallback ()
void updateShadowFile (TDB& tdb, Config& conf)
{
try
{
if (gConf && gTdb)
// Determine if shadow file is enabled.
std::string shadowFile = expandPath (conf.get ("shadow.file"));
if (shadowFile != "")
{
// Determine if shadow file is enabled.
std::string shadowFile = expandPath (gConf->get ("shadow.file"));
if (shadowFile != "")
std::string oldCurses = conf.get ("curses");
std::string oldColor = conf.get ("color");
conf.set ("curses", "off");
conf.set ("color", "off");
// Run report. Use shadow.command, using default.command as a fallback
// with "list" as a default.
std::string command = conf.get ("shadow.command",
conf.get ("default.command", "list"));
std::vector <std::string> args;
split (args, command, ' ');
std::string result = runTaskCommand (args, tdb, conf);
std::ofstream out (shadowFile.c_str ());
if (out.good ())
{
std::string oldCurses = gConf->get ("curses");
std::string oldColor = gConf->get ("color");
gConf->set ("curses", "off");
gConf->set ("color", "off");
// Run report. Use shadow.command, using default.command as a fallback
// with "list" as a default.
std::string command = gConf->get ("shadow.command",
gConf->get ("default.command", "list"));
std::vector <std::string> args;
split (args, command, ' ');
std::string result = runTaskCommand (args, *gTdb, *gConf);
std::ofstream out (shadowFile.c_str ());
if (out.good ())
{
out << result;
out.close ();
}
else
throw std::string ("Could not write file '") + shadowFile + "'";
gConf->set ("curses", oldCurses);
gConf->set ("color", oldColor);
out << result;
out.close ();
}
else
throw std::string ("No specified shadow file '") + shadowFile + "'.";
throw std::string ("Could not write file '") + shadowFile + "'";
// Optionally display a notification that the shadow file was updated.
if (gConf->get (std::string ("shadow.notify"), false))
std::cout << "[Shadow file '" << shadowFile << "' updated]" << std::endl;
conf.set ("curses", oldCurses);
conf.set ("color", oldColor);
}
else
throw std::string ("Internal error (TDB/Config).");
// Optionally display a notification that the shadow file was updated.
if (conf.get (std::string ("shadow.notify"), false))
std::cout << "[Shadow file '" << shadowFile << "' updated]" << std::endl;
}
catch (std::string& error)
@@ -736,13 +758,14 @@ std::string runTaskCommand (
char** argv,
TDB& tdb,
Config& conf,
bool gc /* = true */)
bool gc /* = true */,
bool shadow /* = true */)
{
std::vector <std::string> args;
for (int i = 1; i < argc; ++i)
args.push_back (argv[i]);
return runTaskCommand (args, tdb, conf, gc);
return runTaskCommand (args, tdb, conf, gc, shadow);
}
////////////////////////////////////////////////////////////////////////////////
@@ -750,12 +773,15 @@ std::string runTaskCommand (
std::vector <std::string>& args,
TDB& tdb,
Config& conf,
bool gc /* = false */)
bool gc /* = false */,
bool shadow /* = false */)
{
// If argc == 1 and the default.command configuration variable is set,
// then use that, otherwise stick with argc/argv.
std::string defaultCommand = conf.get ("default.command");
if (args.size () == 0 && defaultCommand != "")
if ((args.size () == 0 ||
(args.size () == 1 && args[0].substr (0, 3) == "rc:")) &&
defaultCommand != "")
{
// Stuff the command line.
args.clear ();
@@ -769,39 +795,49 @@ std::string runTaskCommand (
T task;
parse (args, command, task, conf);
std::string out = "";
bool gcMod = false; // Change occurred by way of gc.
bool cmdMod = false; // Change occurred by way of command type.
std::string out;
if (command == "" && task.getId ()) { handleModify (tdb, task, conf ); }
else if (command == "add") { handleAdd (tdb, task, conf ); }
else if (command == "done") { handleDone (tdb, task, conf ); }
else if (command == "export") { handleExport (tdb, task, conf ); }
else if (command == "projects") { out = handleProjects (tdb, task, conf ); }
else if (command == "tags") { out = handleTags (tdb, task, conf ); }
else if (command == "info") { out = handleInfo (tdb, task, conf ); }
else if (command == "undelete") { out = handleUndelete (tdb, task, conf ); }
else if (command == "delete") { out = handleDelete (tdb, task, conf ); }
else if (command == "start") { out = handleStart (tdb, task, conf ); }
else if (command == "stop") { out = handleStop (tdb, task, conf ); }
else if (command == "undo") { out = handleUndo (tdb, task, conf ); }
else if (command == "stats") { out = handleReportStats (tdb, task, conf ); }
else if (command == "list") { if (gc) tdb.gc (); out = handleList (tdb, task, conf ); } // TODO replace with Custom
else if (command == "long") { if (gc) tdb.gc (); out = handleLongList (tdb, task, conf ); } // TODO replace with Custom
else if (command == "ls") { if (gc) tdb.gc (); out = handleSmallList (tdb, task, conf ); } // TODO replace with Custom
else if (command == "completed") { if (gc) tdb.gc (); out = handleCompleted (tdb, task, conf ); } // TODO replace with Custom
else if (command == "summary") { if (gc) tdb.gc (); out = handleReportSummary (tdb, task, conf ); }
else if (command == "next") { if (gc) tdb.gc (); out = handleReportNext (tdb, task, conf ); } // TODO replace with Custom
else if (command == "history") { if (gc) tdb.gc (); out = handleReportHistory (tdb, task, conf ); }
else if (command == "ghistory") { if (gc) tdb.gc (); out = handleReportGHistory (tdb, task, conf ); }
else if (command == "calendar") { if (gc) tdb.gc (); out = handleReportCalendar (tdb, task, conf ); }
else if (command == "active") { if (gc) tdb.gc (); out = handleReportActive (tdb, task, conf ); } // TODO replace with Custom
else if (command == "overdue") { if (gc) tdb.gc (); out = handleReportOverdue (tdb, task, conf ); } // TODO replace with Custom
else if (command == "oldest") { if (gc) tdb.gc (); out = handleReportOldest (tdb, task, conf ); } // TODO replace with Custom
else if (command == "newest") { if (gc) tdb.gc (); out = handleReportNewest (tdb, task, conf ); } // TODO replace with Custom
else if (command == "colors") { out = handleColor ( conf ); }
else if (command == "version") { out = handleVersion ( conf ); }
else if (command == "help") { longUsage ( conf ); }
else if (isCustomReport (command)) { if (gc) tdb.gc (); out = handleCustomReport (tdb, task, conf, command); } // New Custom reports
else { shortUsage ( conf ); }
// Read-only commands with no side effects.
if (command == "export") { out = handleExport (tdb, task, conf); }
else if (command == "projects") { out = handleProjects (tdb, task, conf); }
else if (command == "tags") { out = handleTags (tdb, task, conf); }
else if (command == "info") { out = handleInfo (tdb, task, conf); }
else if (command == "stats") { out = handleReportStats (tdb, task, conf); }
else if (command == "history") { out = handleReportHistory (tdb, task, conf); }
else if (command == "ghistory") { out = handleReportGHistory (tdb, task, conf); }
else if (command == "calendar") { out = handleReportCalendar (tdb, task, conf); }
else if (command == "summary") { out = handleReportSummary (tdb, task, conf); }
else if (command == "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 == "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); }
// 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
@@ -59,6 +59,7 @@ 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>&);
@@ -69,14 +70,14 @@ bool generateDueDates (T&, std::vector <Date>&);
Date getNextRecurrence (Date&, std::string&);
void updateRecurrenceMask (TDB&, std::vector <T>&, T&);
void onChangeCallback ();
std::string runTaskCommand (int, char**, TDB&, Config&, bool gc = true);
std::string runTaskCommand (std::vector <std::string>&, TDB&, Config&, bool gc = false);
std::string runTaskCommand (int, char**, TDB&, Config&, bool gc = true, bool shadow = true);
std::string runTaskCommand (std::vector <std::string>&, TDB&, Config&, bool gc = false, bool shadow = false);
// command.cpp
void handleAdd (TDB&, T&, Config&);
void handleExport (TDB&, T&, Config&);
void handleDone (TDB&, T&, Config&);
void handleModify (TDB&, T&, Config&);
std::string handleAdd (TDB&, T&, Config&);
std::string 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&);
@@ -89,10 +90,7 @@ std::string handleColor (Config&);
// report.cpp
void filter (std::vector<T>&, T&);
std::string handleList (TDB&, T&, Config&);
std::string handleInfo (TDB&, T&, Config&);
std::string handleLongList (TDB&, T&, Config&);
std::string handleSmallList (TDB&, T&, Config&);
std::string handleCompleted (TDB&, T&, Config&);
std::string handleReportSummary (TDB&, T&, Config&);
std::string handleReportNext (TDB&, T&, Config&);
@@ -102,10 +100,10 @@ std::string handleReportCalendar (TDB&, T&, Config&);
std::string handleReportActive (TDB&, T&, Config&);
std::string handleReportOverdue (TDB&, T&, Config&);
std::string handleReportStats (TDB&, T&, Config&);
std::string handleReportOldest (TDB&, T&, Config&);
std::string handleReportNewest (TDB&, T&, Config&);
std::string handleCustomReport (TDB&, T&, Config&, const std::string&);
void validReportColumns (const std::vector <std::string>&);
void validSortColumns (const std::vector <std::string>&, const std::vector <std::string>&);
// util.cpp
bool confirm (const std::string&);
@@ -127,11 +125,20 @@ void formatTimeDeltaDays (std::string&, time_t);
std::string formatSeconds (time_t);
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
// rules.cpp
void initializeColorRules (Config&);
void autoColorize (T&, Text::color&, Text::color&);
void autoColorize (T&, Text::color&, Text::color&, Config&);
////////////////////////////////////////////////////////////////////////////////

View File

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

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

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;

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

66
src/tests/bug.concat.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 => 5;
# 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');
# 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;

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;

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;

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;

77
src/tests/delete.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 => 16;
# Create the rc file.
if (open my $fh, '>', 'undelete.rc')
{
print $fh "data.location=.\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;

66
src/tests/due.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 => 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";
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/%02d/%d", $m + 1, $d, $y + 1900);
($d, $m, $y) = (localtime (time + 5 * 86_400))[3..5];
my $almost = sprintf ("%d/%02d/%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 = "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 = "week"; t.is (convertDuration (d), 7, "duration week = 7");
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;
}

72
src/tests/export.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 => 7;
# Create the rc file.
if (open my $fh, '>', 'export.rc')
{
print $fh "data.location=.\n";
close $fh;
ok (-r 'export.rc', 'Created export.rc');
}
# Add two tasks, export, examine result.
qx{../task rc:export.rc add priority:H project:A one};
qx{../task rc:export.rc add +tag1 +tag2 two};
qx{../task rc:export.rc export ./export.txt};
my @lines;
if (open my $fh, '<', './export.txt')
{
@lines = <$fh>;
close $fh;
}
my $line1 = qr/'id','uuid','status','tags','entry','start','due','recur','end','project','priority','fg','bg','description'\n/;
my $line2 = qr/'.{8}-.{4}-.{4}-.{4}-.{12}','pending','',\d+,,,,,'A','H',,,'one'\n/;
my $line3 = qr/'.{8}-.{4}-.{4}-.{4}-.{12}','pending','tag1 tag2',\d+,,,,,,,,,'two'\n/;
like ($lines[0], $line1, "export line one");
like ($lines[1], $line2, "export line two");
like ($lines[2], $line3, "export line three");
# Cleanup.
unlink 'export.txt';
ok (!-r 'export.txt', 'Removed export.txt');
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'export.rc';
ok (!-r 'export.rc', 'Removed export.rc');
exit 0;

193
src/tests/filter.t Executable file
View File

@@ -0,0 +1,193 @@
#! /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 => 108;
# Create the rc file.
if (open my $fh, '>', 'filter.rc')
{
print $fh "data.location=.\n";
close $fh;
ok (-r 'filter.rc', 'Created filter.rc');
}
# Test the filters.
qx{../task rc:filter.rc add project:A priority:H +tag one foo};
qx{../task rc:filter.rc add project:A priority:H two};
qx{../task rc:filter.rc add project:A three};
qx{../task rc:filter.rc add priority:H four};
qx{../task rc:filter.rc add +tag five};
qx{../task rc:filter.rc add six foo};
qx{../task rc:filter.rc add priority:L seven bar foo};
my $output = qx{../task rc:filter.rc list};
like ($output, qr/one/, 'a1');
like ($output, qr/two/, 'a2');
like ($output, qr/three/, 'a3');
like ($output, qr/four/, 'a4');
like ($output, qr/five/, 'a5');
like ($output, qr/six/, 'a6');
like ($output, qr/seven/, 'a7');
$output = qx{../task rc:filter.rc list project:A};
like ($output, qr/one/, 'b1');
like ($output, qr/two/, 'b2');
like ($output, qr/three/, 'b3');
unlike ($output, qr/four/, 'b4');
unlike ($output, qr/five/, 'b5');
unlike ($output, qr/six/, 'b6');
unlike ($output, qr/seven/, 'b7');
$output = qx{../task rc:filter.rc list priority:H};
like ($output, qr/one/, 'c1');
like ($output, qr/two/, 'c2');
unlike ($output, qr/three/, 'c3');
like ($output, qr/four/, 'c4');
unlike ($output, qr/five/, 'c5');
unlike ($output, qr/six/, 'c6');
unlike ($output, qr/seven/, 'c7');
$output = qx{../task rc:filter.rc list priority:};
unlike ($output, qr/one/, 'd1');
unlike ($output, qr/two/, 'd2');
like ($output, qr/three/, 'd3');
unlike ($output, qr/four/, 'd4');
like ($output, qr/five/, 'd5');
like ($output, qr/six/, 'd6');
unlike ($output, qr/seven/, 'd7');
$output = qx{../task rc:filter.rc list foo};
like ($output, qr/one/, 'e1');
unlike ($output, qr/two/, 'e2');
unlike ($output, qr/three/, 'e3');
unlike ($output, qr/four/, 'e4');
unlike ($output, qr/five/, 'e5');
like ($output, qr/six/, 'e6');
like ($output, qr/seven/, 'e7');
$output = qx{../task rc:filter.rc list foo bar};
unlike ($output, qr/one/, 'f1');
unlike ($output, qr/two/, 'f2');
unlike ($output, qr/three/, 'f3');
unlike ($output, qr/four/, 'f4');
unlike ($output, qr/five/, 'f5');
unlike ($output, qr/six/, 'f6');
like ($output, qr/seven/, 'f7');
$output = qx{../task rc:filter.rc list +tag};
like ($output, qr/one/, 'g1');
unlike ($output, qr/two/, 'g2');
unlike ($output, qr/three/, 'g3');
unlike ($output, qr/four/, 'g4');
like ($output, qr/five/, 'g5');
unlike ($output, qr/six/, 'g6');
unlike ($output, qr/seven/, 'g7');
$output = qx{../task rc:filter.rc list project:A priority:H};
like ($output, qr/one/, 'h1');
like ($output, qr/two/, 'h2');
unlike ($output, qr/three/, 'h3');
unlike ($output, qr/four/, 'h4');
unlike ($output, qr/five/, 'h5');
unlike ($output, qr/six/, 'h6');
unlike ($output, qr/seven/, 'h7');
$output = qx{../task rc:filter.rc list project:A priority:};
unlike ($output, qr/one/, 'i1');
unlike ($output, qr/two/, 'i2');
like ($output, qr/three/, 'i3');
unlike ($output, qr/four/, 'i4');
unlike ($output, qr/five/, 'i5');
unlike ($output, qr/six/, 'i6');
unlike ($output, qr/seven/, 'i7');
$output = qx{../task rc:filter.rc list project:A foo};
like ($output, qr/one/, 'j1');
unlike ($output, qr/two/, 'j2');
unlike ($output, qr/three/, 'j3');
unlike ($output, qr/four/, 'j4');
unlike ($output, qr/five/, 'j5');
unlike ($output, qr/six/, 'j6');
unlike ($output, qr/seven/, 'j7');
$output = qx{../task rc:filter.rc list project:A +tag};
like ($output, qr/one/, 'k1');
unlike ($output, qr/two/, 'k2');
unlike ($output, qr/three/, 'k3');
unlike ($output, qr/four/, 'k4');
unlike ($output, qr/five/, 'k5');
unlike ($output, qr/six/, 'k6');
unlike ($output, qr/seven/, 'k7');
$output = qx{../task rc:filter.rc list project:A priority:H foo};
like ($output, qr/one/, 'l1');
unlike ($output, qr/two/, 'l2');
unlike ($output, qr/three/, 'l3');
unlike ($output, qr/four/, 'l4');
unlike ($output, qr/five/, 'l5');
unlike ($output, qr/six/, 'l6');
unlike ($output, qr/seven/, 'l7');
$output = qx{../task rc:filter.rc list project:A priority:H +tag};
like ($output, qr/one/, 'm1');
unlike ($output, qr/two/, 'm2');
unlike ($output, qr/three/, 'm3');
unlike ($output, qr/four/, 'm4');
unlike ($output, qr/five/, 'm5');
unlike ($output, qr/six/, 'm6');
unlike ($output, qr/seven/, 'm7');
$output = qx{../task rc:filter.rc list project:A priority:H foo +tag};
like ($output, qr/one/, 'n1');
unlike ($output, qr/two/, 'n2');
unlike ($output, qr/three/, 'n3');
unlike ($output, qr/four/, 'n4');
unlike ($output, qr/five/, 'n5');
unlike ($output, qr/six/, 'n6');
unlike ($output, qr/seven/, 'n7');
$output = qx{../task rc:filter.rc list project:A priority:H foo +tag baz};
unlike ($output, qr/one/, 'n1');
unlike ($output, qr/two/, 'n2');
unlike ($output, qr/three/, 'n3');
unlike ($output, qr/four/, 'n4');
unlike ($output, qr/five/, 'n5');
unlike ($output, qr/six/, 'n6');
unlike ($output, qr/seven/, 'n7');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'filter.rc';
ok (!-r 'filter.rc', 'Removed filter.rc');
exit 0;

View File

@@ -1,15 +0,0 @@
./task add monday due:monday
./task add tuesday due:tuesday
./task add wednesday due:wednesday
./task add thursday due:thursday
./task add friday due:friday
./task add saturday due:saturday
./task add sunday due:sunday
./task add yesterday due:yesterday
./task add today due:today
./task add tomorrow due:tomorrow
./task add eow due:eow
./task add eom due:eom
./task add eoy due:eoy
./task add 21st due:21st

65
src/tests/nag.t Executable file
View File

@@ -0,0 +1,65 @@
#! /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 => 9;
# Create the rc file.
if (open my $fh, '>', 'nag.rc')
{
print $fh "data.location=.\n",
"nag=NAG\n";
close $fh;
ok (-r 'nag.rc', 'Created nag.rc');
}
my $setup = "../task rc:nag.rc add due:yesterday one;"
. "../task rc:nag.rc add due:tomorrow two;"
. "../task rc:nag.rc add priority:H three;"
. "../task rc:nag.rc add priority:M four;"
. "../task rc:nag.rc add priority:L five;"
. "../task rc:nag.rc add six;";
qx{$setup};
like (qx{../task rc:nag.rc do 6}, qr/NAG/, 'do pri: -> nag');
like (qx{../task rc:nag.rc do 5}, qr/NAG/, 'do pri:L -> nag');
like (qx{../task rc:nag.rc do 4}, qr/NAG/, 'do pri:M-> nag');
like (qx{../task rc:nag.rc do 3}, qr/NAG/, 'do pri:H-> nag');
like (qx{../task rc:nag.rc do 2}, qr/NAG/, 'do due:tomorrow -> nag');
ok (qx{../task rc:nag.rc do 1} !~ qr/NAG/, 'do due:yesterday -> no nag');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'nag.rc';
ok (!-r 'nag.rc', 'Removed nag.rc');
exit 0;

61
src/tests/next.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, '>', 'next.rc')
{
print $fh "data.location=.\n",
"next=1\n";
close $fh;
ok (-r 'next.rc', 'Created next.rc');
}
# Add two tasks for each of two projects, then run next. There should be only
# one task from each project shown.
qx{../task rc:next.rc add project:A priority:H AH};
qx{../task rc:next.rc add project:A priority:M AM};
qx{../task rc:next.rc add project:B priority:H BH};
qx{../task rc:next.rc add project:B Bnone};
my $output = qx{../task rc:next.rc next};
like ($output, qr/\s1\sA\s+H\s+-\sAH\n/, 'AH shown');
like ($output, qr/\s3\sB\s+H\s+-\sBH\n/, 'BH shown');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'next.rc';
ok (!-r 'next.rc', 'Removed next.rc');
exit 0;

89
src/tests/oldest.t Executable file
View File

@@ -0,0 +1,89 @@
#! /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 => 25;
# Create the rc file.
if (open my $fh, '>', 'oldest.rc')
{
print $fh "data.location=.\n";
close $fh;
ok (-r 'oldest.rc', 'Created oldest.rc');
}
# Add 11 tasks. Oldest should show 1-10, newest should show 2-11.
diag ("Adding 11 tasks - takes 10 seconds");
qx{../task rc:oldest.rc add one; sleep 1};
qx{../task rc:oldest.rc add two; sleep 1};
qx{../task rc:oldest.rc add three; sleep 1};
qx{../task rc:oldest.rc add four; sleep 1};
qx{../task rc:oldest.rc add five; sleep 1};
qx{../task rc:oldest.rc add six; sleep 1};
qx{../task rc:oldest.rc add seven; sleep 1};
qx{../task rc:oldest.rc add eight; sleep 1};
qx{../task rc:oldest.rc add nine; sleep 1};
qx{../task rc:oldest.rc add ten; sleep 1};
qx{../task rc:oldest.rc add eleven};
my $output = qx{../task rc:oldest.rc oldest};
like ($output, qr/one/, 'oldest: one');
like ($output, qr/two/, 'oldest: two');
like ($output, qr/three/, 'oldest: three');
like ($output, qr/four/, 'oldest: four');
like ($output, qr/five/, 'oldest: five');
like ($output, qr/six/, 'oldest: six');
like ($output, qr/seven/, 'oldest: seven');
like ($output, qr/eight/, 'oldest: eight');
like ($output, qr/nine/, 'oldest: nine');
like ($output, qr/ten/, 'oldest: ten');
unlike ($output, qr/eleven/, 'no: eleven');
$output = qx{../task rc:oldest.rc newest};
unlike ($output, qr/one/, 'no: one');
like ($output, qr/two/, 'newest: two');
like ($output, qr/three/, 'newest: three');
like ($output, qr/four/, 'newest: four');
like ($output, qr/five/, 'newest: five');
like ($output, qr/six/, 'newest: six');
like ($output, qr/seven/, 'newest: seven');
like ($output, qr/eight/, 'newest: eight');
like ($output, qr/nine/, 'newest: nine');
like ($output, qr/ten/, 'newest: ten');
like ($output, qr/eleven/, 'newest: eleven');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'oldest.rc';
ok (!-r 'oldest.rc', 'Removed oldest.rc');
exit 0;

60
src/tests/overdue.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 => 6;
# Create the rc file.
if (open my $fh, '>', 'due.rc')
{
print $fh "data.location=.\n",
"due=4\n";
close $fh;
ok (-r 'due.rc', 'Created due.rc');
}
# Add an overdue task, a due task, and a regular task. The "overdue" report
# should list only the one task.
qx{../task rc:due.rc add due:yesterday one};
qx{../task rc:due.rc add due:tomorrow two};
qx{../task rc:due.rc add due:eoy three};
my $output = qx{../task rc:due.rc overdue};
like ($output, qr/one/, 'overdue: task 1 shows up');
unlike ($output, qr/two/, 'overdue: task 2 does not show up');
unlike ($output, qr/three/, 'overdue: task 3 does not show up');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'due.rc';
ok (!-r 'due.rc', 'Removed due.rc');
exit 0;

67
src/tests/recur.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, '>', 'recur.rc')
{
print $fh "data.location=.\n",
"report.asc.columns=id,recur,description\n",
"report.asc.sort=recur+\n",
"report.desc.columns=id,recur,description\n",
"report.desc.sort=recur-\n";
close $fh;
ok (-r 'recur.rc', 'Created recur.rc');
}
# Create a few recurring tasks, and test the sort order of the recur column.
qx{../task rc:recur.rc add due:tomorrow recur:daily first};
qx{../task rc:recur.rc add due:tomorrow recur:weekly second};
qx{../task rc:recur.rc add due:tomorrow recur:3d third};
my $output = qx{../task rc:recur.rc asc};
like ($output, qr/first .* third .* second/msx, 'daily 3d weekly');
$output = qx{../task rc:recur.rc desc};
like ($output, qr/second .* third .* first/msx, 'weekly 3d daily');
# Cleanup.
unlink 'shadow.txt';
ok (!-r 'shadow.txt', 'Removed shadow.txt');
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'recur.rc';
ok (!-r 'recur.rc', 'Removed recur.rc');
exit 0;

11
src/tests/run_all Executable file
View File

@@ -0,0 +1,11 @@
#! /bin/bash
date > all.log
for i in *.t
do
./$i >> all.log 2>&1
done
date >> all.log

101
src/tests/shadow.t Executable file
View File

@@ -0,0 +1,101 @@
#! /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 => 21;
# Create the rc file.
if (open my $fh, '>', 'shadow.rc')
{
print $fh "data.location=.\n",
"shadow.file=./shadow.txt\n",
"shadow.command=stats\n",
"shadow.notify=on\n";
close $fh;
ok (-r 'shadow.rc', 'Created shadow.rc');
}
my $output = qx{../task rc:shadow.rc add one};
like ($output, qr/\[Shadow file '\.\/shadow\.txt' updated\]/, 'shadow file updated on add');
$output = qx{../task rc:shadow.rc list};
unlike ($output, qr/\[Shadow file '\.\/shadow\.txt' updated\]/, 'shadow file not updated on list');
$output = qx{../task rc:shadow.rc delete 1};
like ($output, qr/\[Shadow file '\.\/shadow\.txt' updated\]/, 'shadow file updated on delete');
$output = qx{../task rc:shadow.rc list};
like ($output, qr/\[Shadow file '\.\/shadow\.txt' updated\]/, 'shadow file updated on list');
# Inspect the shadow file.
my $file = slurp ('./shadow.txt');
like ($file, qr/Pending\s+0\n/, 'Pending 0');
like ($file, qr/Recurring\s+0\n/, 'Recurring 0');
like ($file, qr/Completed\s+0\n/, 'Completed 0');
like ($file, qr/Deleted\s+1\n/, 'Deleted 1');
like ($file, qr/Total\s+1\n/, 'Total 1');
like ($file, qr/Task used for\s+-\n/, 'Task used for -');
like ($file, qr/Task added every\s+-\n/, 'Task added every -');
like ($file, qr/Task deleted every\s+-\n/, 'Task deleted every -');
like ($file, qr/Average desc length\s+3 characters\n/, 'Average desc length 3 characters');
like ($file, qr/Tasks tagged\s+0%\n/, 'Tasks tagged 0%');
like ($file, qr/Unique tags\s+0\n/, 'Unique tags 0');
like ($file, qr/Projects\s+0\n/, 'Projects 0');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'completed.data';
ok (!-r 'completed.data', 'Removed completed.data');
unlink 'shadow.rc';
ok (!-r 'shadow.rc', 'Removed shadow.rc');
unlink 'shadow.txt';
ok (!-r 'shadow.txt', 'Removed shadow.txt');
exit 0;
################################################################################
sub slurp
{
my ($file) = @_;
local $/;
if (open my $fh, '<', $file)
{
my $contents = <$fh>;
close $fh;
return $contents;
}
'';
}

73
src/tests/start.t Executable file
View File

@@ -0,0 +1,73 @@
#! /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 => 12;
# Create the rc file.
if (open my $fh, '>', 'start.rc')
{
print $fh "data.location=.\n";
close $fh;
ok (-r 'start.rc', 'Created start.rc');
}
# Test the add/start/stop commands.
qx{../task rc:start.rc add one};
qx{../task rc:start.rc add two};
my $output = qx{../task rc:start.rc active};
unlike ($output, qr/one/, 'one not active');
unlike ($output, qr/two/, 'two not active');
qx{../task rc:start.rc start 1};
qx{../task rc:start.rc start 2};
$output = qx{../task rc:start.rc active};
like ($output, qr/one/, 'one active');
like ($output, qr/two/, 'two active');
qx{../task rc:start.rc stop 1};
$output = qx{../task rc:start.rc active};
unlike ($output, qr/one/, 'one not active');
like ($output, qr/two/, 'two active');
qx{../task rc:start.rc stop 2};
$output = qx{../task rc:start.rc active};
unlike ($output, qr/one/, 'one not active');
unlike ($output, qr/two/, 'two not active');
# Cleanup.
ok (-r 'pending.data', 'Need to remove pending.data');
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'start.rc';
ok (!-r 'start.rc', 'Removed start.rc');
exit 0;

73
src/tests/subproject.t Executable file
View File

@@ -0,0 +1,73 @@
#! /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 => 11;
# Create the rc file.
if (open my $fh, '>', 'sp.rc')
{
print $fh "data.location=.\n";
close $fh;
ok (-r 'sp.rc', 'Created sp.rc');
}
my $setup = "../task rc:sp.rc add project:abc abc;"
. "../task rc:sp.rc add project:ab ab;"
. "../task rc:sp.rc add project:a a;"
. "../task rc:sp.rc add project:b b;";
qx{$setup};
my $output = qx{../task rc:sp.rc list project:b};
like ($output, qr/\bb\s*$/m, 'abc,ab,a,b | b -> b');
$output = qx{../task rc:sp.rc list project:a};
like ($output, qr/\babc\s*$/m, 'abc,ab,a,b | a -> abc');
like ($output, qr/\bab\s*$/m, 'abc,ab,a,b | a -> ab');
like ($output, qr/\ba\s*$/m, 'abc,ab,a,b | a -> a');
$output = qx{../task rc:sp.rc list project:ab};
like ($output, qr/\babc\s*$/m, 'abc,ab,a,b | a -> abc');
like ($output, qr/\bab\s*$/m, 'abc,ab,a,b | a -> ab');
$output = qx{../task rc:sp.rc list project:abc};
like ($output, qr/\babc\s*$/m, 'abc,ab,a,b | a -> abc');
$output = qx{../task rc:sp.rc list project:abcd};
like ($output, qr/^No matches.$/, 'abc,ab,a,b | abcd -> nul');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'sp.rc';
ok (!-r 'sp.rc', 'Removed sp.rc');
exit 0;

View File

@@ -0,0 +1,69 @@
////////////////////////////////////////////////////////////////////////////////
// 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 <sys/time.h>
#include "../T.h"
#include "../task.h"
#include "test.h"
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{
UnitTest test (1);
std::string sample = "d346065c-7ef6-49af-ae77-19c1825807f5 "
"- "
"[bug performance solaris linux osx] "
"[due:1236142800 entry:1236177552 priority:H project:task-1.5.0 start:1236231761] "
"Profile task and identify performance bottlenecks";
// Start clock
test.diag ("start");
struct timeval start;
gettimeofday (&start, NULL);
for (int i = 0; i < 1000000; i++)
{
T t (sample);
}
// End clock
struct timeval end;
gettimeofday (&end, NULL);
test.diag ("end");
int diff = ((end.tv_sec * 1000000) + end.tv_usec) -
((start.tv_sec * 1000000) + start.tv_usec);
char s[16];
sprintf (s, "%d.%06d", diff/1000000, diff%1000000);
test.pass (std::string ("1,000,000 T::parse calls in ") + s + "s");
return 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
@@ -31,34 +31,34 @@
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{
plan (5);
UnitTest test (5);
T t;
std::string s = t.compose ();
is ((int)s.length (), 46, "T::T (); T::compose ()");
diag (s);
test.is ((int)s.length (), 46, "T::T (); T::compose ()");
test.diag (s);
t.setStatus (T::completed);
s = t.compose ();
is (s[37], '+', "T::setStatus (completed)");
diag (s);
test.is (s[37], '+', "T::setStatus (completed)");
test.diag (s);
t.setStatus (T::deleted);
s = t.compose ();
is (s[37], 'X', "T::setStatus (deleted)");
diag (s);
test.is (s[37], 'X', "T::setStatus (deleted)");
test.diag (s);
t.setStatus (T::recurring);
s = t.compose ();
is (s[37], 'r', "T::setStatus (recurring)");
diag (s);
test.is (s[37], 'r', "T::setStatus (recurring)");
test.diag (s);
// Round trip test.
std::string sample = "00000000-0000-0000-0000-000000000000 - [] [] Sample";
T t2;
t2.parse (sample);
sample += "\n";
is (t2.compose (), sample, "T::parse -> T::compose round trip");
test.is (t2.compose (), sample, "T::parse -> T::compose round trip");
return 0;
}

73
src/tests/tag.t Executable file
View File

@@ -0,0 +1,73 @@
#! /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 => 9;
# Create the rc file.
if (open my $fh, '>', 'tag.rc')
{
print $fh "data.location=.\n";
close $fh;
ok (-r 'tag.rc', 'Created tag.rc');
}
# Add task with tags.
my $output = qx{../task rc:tag.rc add +1 This +2 is a test +3; ../task rc:tag.rc info 1};
like ($output, qr/^Tags\s+1 2 3\n/m, 'tags found');
# Remove tags.
$output = qx{../task rc:tag.rc 1 -3 -2 -1; ../task rc:tag.rc info 1};
unlike ($output, qr/^Tags/m, '-3 -2 -1 tag removed');
# Add tags.
$output = qx{../task rc:tag.rc 1 +4 +5 +6; ../task rc:tag.rc info 1};
like ($output, qr/^Tags\s+4 5 6\n/m, 'tags found');
# Remove tags.
$output = qx{../task rc:tag.rc 1 -4 -5 -6; ../task rc:tag.rc info 1};
unlike ($output, qr/^Tags/m, '-4 -5 -6 tag removed');
# Add and remove tags.
$output = qx{../task rc:tag.rc 1 +duplicate -duplicate; ../task rc:tag.rc info 1};
unlike ($output, qr/^Tags/m, '+duplicate -duplicate NOP');
# Remove missing tag.
$output = qx{../task rc:tag.rc 1 -missing; ../task rc:tag.rc info 1};
unlike ($output, qr/^Tags/m, '-missing NOP');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'tag.rc';
ok (!-r 'tag.rc', 'Removed tag.rc');
exit 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
@@ -34,7 +34,7 @@
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{
plan (43);
UnitTest t (38);
try
{
@@ -46,14 +46,14 @@ int main (int argc, char** argv)
TDB tdb;
tdb.dataDirectory (".");
std::vector <T> all;
ok (!tdb.pendingT (all), "TDB::pendingT read empty db");
is ((int) all.size (), 0, "empty db");
ok (!tdb.allPendingT (all), "TDB::allPendingT read empty db");
is ((int) all.size (), 0, "empty db");
ok (!tdb.completedT (all), "TDB::completedT read empty db");
is ((int) all.size (), 0, "empty db");
ok (!tdb.allCompletedT (all), "TDB::allCompletedT read empty db");
is ((int) all.size (), 0, "empty db");
t.ok (!tdb.pendingT (all), "TDB::pendingT read empty db");
t.is ((int) all.size (), 0, "empty db");
t.ok (!tdb.allPendingT (all), "TDB::allPendingT read empty db");
t.is ((int) all.size (), 0, "empty db");
t.ok (!tdb.completedT (all), "TDB::completedT read empty db");
t.is ((int) all.size (), 0, "empty db");
t.ok (!tdb.allCompletedT (all), "TDB::allCompletedT read empty db");
t.is ((int) all.size (), 0, "empty db");
// Add a new task.
T t1;
@@ -61,86 +61,68 @@ int main (int argc, char** argv)
t1.setStatus (T::pending);
t1.setAttribute ("project", "p1");
t1.setDescription ("task 1");
diag (t1.compose ());
ok (tdb.addT (t1), "TDB::addT t1");
t.diag (t1.compose ());
t.ok (tdb.addT (t1), "TDB::addT t1");
// Verify as above.
ok (tdb.pendingT (all), "TDB::pendingT read db");
is ((int) all.size (), 1, "empty db");
ok (tdb.allPendingT (all), "TDB::allPendingT read db");
is ((int) all.size (), 1, "empty db");
ok (!tdb.completedT (all), "TDB::completedT read empty db");
is ((int) all.size (), 0, "empty db");
ok (!tdb.allCompletedT (all), "TDB::allCompletedT read empty db");
is ((int) all.size (), 0, "empty db");
t.ok (tdb.pendingT (all), "TDB::pendingT read db");
t.is ((int) all.size (), 1, "empty db");
t.ok (tdb.allPendingT (all), "TDB::allPendingT read db");
t.is ((int) all.size (), 1, "empty db");
t.ok (!tdb.completedT (all), "TDB::completedT read empty db");
t.is ((int) all.size (), 0, "empty db");
t.ok (!tdb.allCompletedT (all), "TDB::allCompletedT read empty db");
t.is ((int) all.size (), 0, "empty db");
// TODO Modify task.
fail ("modify");
fail ("verify");
// Complete task.
ok (tdb.completeT (t1), "TDB::completeT t1");;
ok (!tdb.pendingT (all), "TDB::pendingT read db");
is ((int) all.size (), 0, "empty db");
ok (tdb.allPendingT (all), "TDB::allPendingT read db");
is ((int) all.size (), 1, "empty db");
ok (!tdb.completedT (all), "TDB::completedT read empty db");
is ((int) all.size (), 0, "empty db");
ok (!tdb.allCompletedT (all), "TDB::allCompletedT read empty db");
is ((int) all.size (), 0, "empty db");
t.ok (tdb.completeT (t1), "TDB::completeT t1");;
t.ok (tdb.pendingT (all), "TDB::pendingT read db");
t.is ((int) all.size (), 0, "empty db");
t.ok (tdb.allPendingT (all), "TDB::allPendingT read db");
t.is ((int) all.size (), 1, "empty db");
t.ok (!tdb.completedT (all), "TDB::completedT read empty db");
t.is ((int) all.size (), 0, "empty db");
t.ok (!tdb.allCompletedT (all), "TDB::allCompletedT read empty db");
t.is ((int) all.size (), 0, "empty db");
is (tdb.gc (), 1, "TDB::gc");
ok (!tdb.pendingT (all), "TDB::pendingT read empty db");
is ((int) all.size (), 0, "empty db");
ok (!tdb.allPendingT (all), "TDB::allPendingT read empty db");
is ((int) all.size (), 0, "empty db");
ok (tdb.completedT (all), "TDB::completedT read db");
is ((int) all.size (), 1, "empty db");
ok (tdb.allCompletedT (all), "TDB::allCompletedT read db");
is ((int) all.size (), 1, "empty db");
t.is (tdb.gc (), 1, "TDB::gc");
t.ok (tdb.pendingT (all), "TDB::pendingT read empty db");
t.is ((int) all.size (), 0, "empty db");
t.ok (tdb.allPendingT (all), "TDB::allPendingT read empty db");
t.is ((int) all.size (), 0, "empty db");
t.ok (tdb.completedT (all), "TDB::completedT read db");
t.is ((int) all.size (), 1, "empty db");
t.ok (tdb.allCompletedT (all), "TDB::allCompletedT read db");
t.is ((int) all.size (), 1, "empty db");
// Add a new task.
T t2;
t2.setId (2);
t2.setId (1);
t2.setAttribute ("project", "p2");
t2.setDescription ("task 2");
diag (t2.compose ());
ok (tdb.addT (t2), "TDB::addT t2");
fail ("verify");
t.ok (tdb.addT (t2), "TDB::addT t2");
// Delete task.
ok (tdb.deleteT (t2), "TDB::deleteT t2");
fail ("verify");
t.ok (tdb.deleteT (t2), "TDB::deleteT t2");
// GC the files.
is (tdb.gc (), 1, "1 <- TDB::gc");
// Read log file.
std::vector <std::string> entries;
tdb.logRead (entries);
std::vector <std::string>::iterator it;
for (it = entries.begin (); it != entries.end (); ++it)
diag (*it);
// TODO Verify contents of above transactions.
fail ("verify");
t.is (tdb.gc (), 1, "1 <- TDB::gc");
}
catch (std::string& error)
{
diag (error);
t.diag (error);
return -1;
}
catch (...)
{
diag ("Unknown error.");
t.diag ("Unknown error.");
return -2;
}
unlink ("./pending.data");
unlink ("./completed.data");

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,81 +25,157 @@
//
////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <iomanip>
#include <string>
#include <task.h>
static int total = 0;
static int counter = 0;
#include "test.h"
///////////////////////////////////////////////////////////////////////////////
static void check (void)
UnitTest::UnitTest ()
: mPlanned (0)
, mCounter (0)
, mPassed (0)
, mFailed (0)
, mSkipped (0)
{
if (counter > total)
std::cout << "# Warning: There are more tests than planned."
}
///////////////////////////////////////////////////////////////////////////////
UnitTest::UnitTest (int planned)
: mPlanned (planned)
, mCounter (0)
, mPassed (0)
, mFailed (0)
, mSkipped (0)
{
std::cout << "1.." << mPlanned << std::endl;
}
///////////////////////////////////////////////////////////////////////////////
UnitTest::~UnitTest ()
{
float percentPassed = 0.0;
if (mPlanned > 0)
percentPassed = (100.0 * mPassed) / max (mPlanned, mPassed + mFailed + mSkipped);
if (mCounter < mPlanned)
{
std::cout << "# Only "
<< mCounter
<< " tests, out of a planned "
<< mPlanned
<< " were run."
<< std::endl;
mSkipped += mPlanned - mCounter;
}
else if (mCounter > mPlanned)
std::cout << "# "
<< mCounter
<< " tests were run, but only "
<< mPlanned
<< " were planned."
<< std::endl;
std::cout << "# "
<< mPassed
<< " passed, "
<< mFailed
<< " failed, "
<< mSkipped
<< " skipped. "
<< std::setprecision (3) << percentPassed
<< "% passed."
<< std::endl;
}
///////////////////////////////////////////////////////////////////////////////
void plan (int quantity)
void UnitTest::plan (int planned)
{
total = quantity;
std::cout << "1.." << quantity << std::endl;
check ();
mPlanned = planned;
mCounter = 0;
mPassed = 0;
mFailed = 0;
mSkipped = 0;
std::cout << "1.." << mPlanned << std::endl;
}
///////////////////////////////////////////////////////////////////////////////
void ok (bool expression, const std::string& name)
void UnitTest::planMore (int extra)
{
++counter;
mPlanned += extra;
std::cout << "1.." << mPlanned << std::endl;
}
///////////////////////////////////////////////////////////////////////////////
void UnitTest::ok (bool expression, const std::string& name)
{
++mCounter;
if (expression)
{
++mPassed;
std::cout << "ok "
<< counter
<< mCounter
<< " - "
<< name
<< std::endl;
}
else
{
++mFailed;
std::cout << "not ok "
<< counter
<< mCounter
<< " - "
<< name
<< std::endl;
check ();
}
}
///////////////////////////////////////////////////////////////////////////////
void notok (bool expression, const std::string& name)
void UnitTest::notok (bool expression, const std::string& name)
{
++counter;
++mCounter;
if (!expression)
{
++mPassed;
std::cout << "ok "
<< counter
<< mCounter
<< " - "
<< name
<< std::endl;
}
else
{
++mFailed;
std::cout << "not ok "
<< counter
<< mCounter
<< " - "
<< name
<< std::endl;
check ();
}
}
///////////////////////////////////////////////////////////////////////////////
void is (bool actual, bool expected, const std::string& name)
void UnitTest::is (bool actual, bool expected, const std::string& name)
{
++counter;
++mCounter;
if (actual == expected)
{
++mPassed;
std::cout << "ok "
<< counter
<< mCounter
<< " - "
<< name
<< std::endl;
}
else
{
++mFailed;
std::cout << "not ok "
<< counter
<< mCounter
<< " - "
<< name
<< std::endl
@@ -109,22 +185,27 @@ void is (bool actual, bool expected, const std::string& name)
<< "# got: "
<< actual
<< std::endl;
check ();
}
}
///////////////////////////////////////////////////////////////////////////////
void is (size_t actual, size_t expected, const std::string& name)
void UnitTest::is (size_t actual, size_t expected, const std::string& name)
{
++counter;
++mCounter;
if (actual == expected)
{
++mPassed;
std::cout << "ok "
<< counter
<< mCounter
<< " - "
<< name
<< std::endl;
}
else
{
++mFailed;
std::cout << "not ok "
<< counter
<< mCounter
<< " - "
<< name
<< std::endl
@@ -134,22 +215,27 @@ void is (size_t actual, size_t expected, const std::string& name)
<< "# got: "
<< actual
<< std::endl;
check ();
}
}
///////////////////////////////////////////////////////////////////////////////
void is (int actual, int expected, const std::string& name)
void UnitTest::is (int actual, int expected, const std::string& name)
{
++counter;
++mCounter;
if (actual == expected)
{
++mPassed;
std::cout << "ok "
<< counter
<< mCounter
<< " - "
<< name
<< std::endl;
}
else
{
++mFailed;
std::cout << "not ok "
<< counter
<< mCounter
<< " - "
<< name
<< std::endl
@@ -159,22 +245,27 @@ void is (int actual, int expected, const std::string& name)
<< "# got: "
<< actual
<< std::endl;
check ();
}
}
///////////////////////////////////////////////////////////////////////////////
void is (double actual, double expected, const std::string& name)
void UnitTest::is (double actual, double expected, const std::string& name)
{
++counter;
++mCounter;
if (actual == expected)
{
++mPassed;
std::cout << "ok "
<< counter
<< mCounter
<< " - "
<< name
<< std::endl;
}
else
{
++mFailed;
std::cout << "not ok "
<< counter
<< mCounter
<< " - "
<< name
<< std::endl
@@ -184,22 +275,27 @@ void is (double actual, double expected, const std::string& name)
<< "# got: "
<< actual
<< std::endl;
check ();
}
}
///////////////////////////////////////////////////////////////////////////////
void is (char actual, char expected, const std::string& name)
void UnitTest::is (char actual, char expected, const std::string& name)
{
++counter;
++mCounter;
if (actual == expected)
{
++mPassed;
std::cout << "ok "
<< counter
<< mCounter
<< " - "
<< name
<< std::endl;
}
else
{
++mFailed;
std::cout << "not ok "
<< counter
<< mCounter
<< " - "
<< name
<< std::endl
@@ -209,25 +305,30 @@ void is (char actual, char expected, const std::string& name)
<< "# got: "
<< actual
<< std::endl;
check ();
}
}
///////////////////////////////////////////////////////////////////////////////
void is (
void UnitTest::is (
const std::string& actual,
const std::string& expected,
const std::string& name)
{
++counter;
++mCounter;
if (actual == expected)
{
++mPassed;
std::cout << "ok "
<< counter
<< mCounter
<< " - "
<< name
<< std::endl;
}
else
{
++mFailed;
std::cout << "not ok "
<< counter
<< mCounter
<< " - "
<< name
<< std::endl
@@ -239,11 +340,46 @@ void is (
<< actual
<< "'"
<< std::endl;
check ();
}
}
///////////////////////////////////////////////////////////////////////////////
void diag (const std::string& text)
void UnitTest::is (
const char* actual,
const char* expected,
const std::string& name)
{
++mCounter;
if (! strcmp (actual, expected))
{
++mPassed;
std::cout << "ok "
<< mCounter
<< " - "
<< name
<< std::endl;
}
else
{
++mFailed;
std::cout << "not ok "
<< mCounter
<< " - "
<< name
<< std::endl
<< "# expected: '"
<< expected
<< "'"
<< std::endl
<< "# got: '"
<< actual
<< "'"
<< std::endl;
}
}
///////////////////////////////////////////////////////////////////////////////
void UnitTest::diag (const std::string& text)
{
std::string trimmed = trim (text, " \t\n\r\f");
@@ -251,22 +387,36 @@ void diag (const std::string& text)
}
///////////////////////////////////////////////////////////////////////////////
void pass (const std::string& text)
void UnitTest::pass (const std::string& text)
{
++counter;
++mCounter;
++mPassed;
std::cout << "ok "
<< counter
<< mCounter
<< " "
<< text
<< std::endl;
}
///////////////////////////////////////////////////////////////////////////////
void fail (const std::string& text)
void UnitTest::fail (const std::string& text)
{
++counter;
++mCounter;
++mFailed;
std::cout << "not ok "
<< counter
<< mCounter
<< " "
<< text
<< std::endl;
}
///////////////////////////////////////////////////////////////////////////////
void UnitTest::skip (const std::string& text)
{
++mCounter;
++mSkipped;
std::cout << "skip "
<< mCounter
<< " "
<< text
<< std::endl;

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
@@ -24,23 +24,42 @@
// USA
//
////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_TEST
#define INCLUDED_TEST
#ifndef INCLUDED_UNITTEST
#define INCLUDED_UNITTEST
#include <string>
void plan (int);
void ok (bool, const std::string&);
void notok (bool, const std::string&);
void is (bool, bool, const std::string&);
void is (int, int, const std::string&);
void is (size_t, size_t, const std::string&);
void is (double, double, const std::string&);
void is (char, char, const std::string&);
void is (const std::string&, const std::string&, const std::string&);
void diag (const std::string&);
void fail (const std::string&);
void pass (const std::string&);
class UnitTest
{
public:
UnitTest ();
UnitTest (int);
~UnitTest ();
void plan (int);
void planMore (int);
void ok (bool, const std::string&);
void notok (bool, const std::string&);
void is (bool, bool, const std::string&);
void is (size_t, size_t, const std::string&);
void is (int, int, const std::string&);
void is (double, double, const std::string&);
void is (char, char, const std::string&);
void is (const std::string&, const std::string&, const std::string&);
void is (const char*, const char*, const std::string&);
void diag (const std::string&);
void pass (const std::string&);
void fail (const std::string&);
void skip (const std::string&);
private:
int mPlanned;
int mCounter;
int mPassed;
int mFailed;
int mSkipped;
};
#endif
////////////////////////////////////////////////////////////////////////////////

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