Compare commits

...

36 Commits

Author SHA1 Message Date
Federico Hernandez
35792e7874 Added release date for 1.8.1 to ChangeLog 2009-08-20 22:48:22 +02:00
Federico Hernandez
083407f789 Pushing package build scripts for fedora, ubuntu and cygwin to 1.8.1 2009-08-19 23:50:47 +02:00
Federico Hernandez
e1146cdd20 Changed epoch to be 12/22 for UTC 2009-08-18 13:46:19 +02:00
Paul Beckingham
f04205be4c Documentation Update
- Added a load of missing ChangeLog entries, by running the timesheet
  report and comparing.
2009-08-16 23:10:21 -04:00
Paul Beckingham
07da2396fc Bug Fix - #251
- Fixed bug #251 that caused the .hasnt attribute modifier to fail
  when annotations were present.  Thanks to John Florian.
2009-08-16 22:38:33 -04:00
Paul Beckingham
ec7f7cc939 Bug Fix - #260
- Fixed bug whereby the start, stop and delete commands were not
  complaining when filter arguments were specified, even though they
  were ignored.  Thanks to Charles T. Yun.
2009-08-16 18:39:35 -04:00
Paul Beckingham
1b28d8714b Bug Fix - #249
- Fixed bug that caused two annotations with the same date to be parsed
  identically, and therefore were not considered unique annotations after
  the "edit" command.
2009-08-16 17:22:17 -04:00
Paul Beckingham
79f59f12ae Bug Fix - #252
- Fixed bug that prevented using end.after: and end.before: together
  to effect a range.
- Required differentiation between positive and negative attribute
  modifiers, and special handling.
2009-08-16 13:01:28 -04:00
Paul Beckingham
f595bc4731 Bug Fix - #259
- Fixed broken build on Snow Leopard - missing include.
2009-08-15 14:20:20 -04:00
Federico Hernandez
972efc58f4 Pushing man pages to 1.8.1 2009-08-12 14:43:05 +02:00
Paul Beckingham
dc9ba6d6b8 Bug Fix - #250
- Fixed bug #250 whereby rc.dateformat was not observed when parsing the
  creation date of an annotation (thanks to Federico Hernandez).
2009-08-07 16:53:25 -06:00
Paul Beckingham
a7196ca181 Bug Fix - #257
- Fixed bug #257 where an extant ~/.taskrc file prevented the override and
  automatic creation of an alternate rc file (thanks to Zach Frazier).
2009-08-07 16:11:09 -06:00
Paul Beckingham
1355571876 Bug Fix - #252
- Fixed bug that prevented the chaining of two attributes with
  different modifiers to effect a date range, such as:
    task ls due.after:8/1/2009 due.before:8/31/2009
  Thanks to John Florian.
2009-08-05 10:15:33 -06:00
Paul Beckingham
d3fcd40279 Bug Fix - Bug #248
- Fixed bug where both single and double quotes are stored as
  ampersand-quote-semi-colon, leading to the gradual conversion of
  one to the other.  Fix is backward compatible.  Thanks to John
  Florian.
2009-08-05 07:24:00 -06:00
Paul Beckingham
c4dcdbff0f Unit Tests - range
- Added unit tests to check the behavior when a data range is created
  with "task list due.before:... due.after:...".
2009-08-04 17:24:06 -06:00
Paul Beckingham
d39e45841d Bug Fix - Bug #241
- Fixed bug #241 that caused redirected output to retain color control codes
  for colored header and footnotes (thanks to John Florian).
2009-08-04 16:59:52 -06:00
Paul Beckingham
b28575625e Bug Fix - Bug #243
- Fixed bug that caused due dates and recurrence periods to be quoted on
  export, which then caused confusion on a subsequent import (thanks to
  John Florian).
2009-08-04 16:47:49 -06:00
Paul Beckingham
fc8f8957c4 Bug Fix - recurring task with no due date
- A recurring task may not be added without a due date.  Previously,
  this restriction only applied to modified tasks.
2009-08-04 16:26:23 -06:00
Paul Beckingham
0499bfff49 Bug Fix - Bug #242
-  Fixed bug that caused the reported ID after an add to be incorrect.
2009-08-04 16:08:56 -06:00
Paul Beckingham
af49ccf508 Bug Fix - wrong .taskrc file in message
- When a .taskrc file is overridden (with rc:...) task still refers to
  the default file name in output.
2009-08-04 16:01:20 -06:00
Paul Beckingham
7b0edfdeba Unit Test - recurring task with no due date
- Should generate error, but doesn't.
2009-08-03 07:38:22 -06:00
Federico Hernandez
e5d56e3075 Enhancement:
* Remove trailing whitespace from completions.
	* Complete rc.<variable> with ":'.
2009-08-01 01:24:46 +02:00
John Florian
ede746ba16 Fixed bug #241
Completion behavior has changed from bash-3 to bash-4.  Even the colon
character appears in COMP_WORDBREAKS of both versions, only bash-4 seems to
honor it.  This appears to be a bug in bash-3.  Changes made here work around
the problem so that completion of project names works for either version of
bash.
2009-07-30 23:19:10 -04:00
Paul Beckingham
0bad0277fe Documentation Update
- Added bug fix info to ChangeLog.  This is now ready to release, if
  necessary.
2009-07-26 16:31:40 -04:00
Paul Beckingham
8488cbd1a6 Bug Fix - #231 time_t/int collision on 32-bit systems
- Fixed bug #231 by removing the operator int () cast from the Duration
  class.  On a 32-bit system, "time_t" may be defined as "int", in
  which case the int cast and time_t cast are essentially duplicates.
  Thanks to Pietro Cerutti, who also provided a patch.
2009-07-26 16:11:14 -04:00
Paul Beckingham
6f9356da64 Updated version to 1.8.1
- Changed program version number.
- Changed NEWS file to refer only to 1.8, not 1.8.1.  This means we now only
  need to update the NEWS file on major releases, not patches.  This is the
  right thing to do now that we have only "whats new" in the NEWS file.
2009-07-26 16:06:14 -04:00
Paul Beckingham
90d53245c3 Merge branch '1.8.0'
Conflicts:
	.gitignore
	AUTHORS
	ChangeLog
	DEVELOPERS
	Makefile.am
	NEWS
	README
	configure.ac
	doc/man/task.1
	doc/man/taskrc.5
	src/T.cpp
	src/T.h
	src/TDB.cpp
	src/TDB.h
	src/command.cpp
	src/edit.cpp
	src/import.cpp
	src/parse.cpp
	src/report.cpp
	src/rules.cpp
	src/task.cpp
	src/task.h
	task_completion.sh
2009-07-21 19:15:54 -04:00
Paul Beckingham
1422a15cbc Merge branch '1.7.1'
Conflicts:
	doc/man5/taskrc.5
2009-06-09 19:49:36 -04:00
Paul Beckingham
9c15457d7f Merge branch '1.7.1' 2009-06-09 19:35:24 -04:00
Federico Hernandez
20d8124a1d Fixed documentation for 1.7.1 2009-06-09 17:30:09 +02:00
Federico Hernandez
db6de54ccc * Updated project homepage reference and license text 2009-06-09 09:32:23 +02:00
Federico Hernandez
eb864820cf * Removed hard-coded version number 2009-06-09 09:31:44 +02:00
Federico Hernandez
0291e4c72e Changed some more references from beckingham.net to taskwarrior.org 2009-06-09 08:56:59 +02:00
Paul Beckingham
6e27feb8a3 Code Cleanup
- Removed Makefile.in from repository.  This was done in 1.8.0, but
  wasn't in 1.7.0.  It's time.
- Added Makefile.in to the .gitignore files.
2009-06-08 23:24:09 -04:00
Paul Beckingham
1dcba4619e Documentation Update
- Bumped version to 1.7.1.
- Changed references to email addresses, URLs.
2009-06-08 23:14:38 -04:00
Paul Beckingham
7538b43c68 Bug Fix - Build failure on OpenBSD
- Fixed build failure on OpenBSD (thanks to Mike Adonay).
2009-06-08 23:03:30 -04:00
38 changed files with 762 additions and 204 deletions

1
.gitignore vendored
View File

@@ -15,5 +15,4 @@ www.xls
src/tests/all.log
src/tests/*.data
*~
movie*
.*.swp

View File

@@ -17,6 +17,7 @@ The following submitted code, packages or analysis, and deserve special thanks:
P.C. Shyamshankar
Johan Friis
Steven de Brouwer
Pietro Cerutti
Thanks to the following, who submitted detailed bug reports and excellent suggestions:
Eugene Kramer
@@ -34,6 +35,7 @@ Thanks to the following, who submitted detailed bug reports and excellent sugges
Eric Farris
Bruce Dillahunty
Askme Too
Mike Adonay
Thomas@BIC
Ian Mortimer

View File

@@ -1,7 +1,42 @@
------ current release ---------------------------
1.8.0 (7/21/2009)
1.8.1 (8/20/2009)
+ Fixed bug #231 that broke the build on OpenBSD 32-bit due to a time_t
and int collision (thanks to Pietro Cerutti).
+ Fixed bug #241 that prevented bash's tab-completion of projects in Fedora
11 and likely anything using bash-4 (thanks to John Florian).
+ Fixed bug #242 that sometimes causes the ID echoed after a task is added
to be incorrect (thanks to John Florian).
+ Fixed bug #245 that quoted date fields on export, that were subsequently
improperly parsed on import (thanks to John Florian).
+ Fixed bug #248 where single and double quotes are both stored as
ampersand-quot-semi (thanks to John Florian).
+ Fixed bug #249 that caused annotations with the same date to be lost after
a "task edit" command (thanks to Federico Hernandez).
+ Fixed bug #250 whereby rc.dateformat was not observed when parsing the
creation date of an annotation (thanks to Federico Hernandez).
+ Fixed bug #251 whereby the presence of annotations cause the .hasnt attribute
modifier to not work (thanks to John Florian).
+ Fixed bug #252 that prevented use of attribute modifiers on dates to effect
a range, such as "task ls due.after:eom due.before:eoy" (thanks to John
Florian).
+ Fixed bug #256 that allowed a recurring task with no due date.
+ Fixed bug #257 where an extant ~/.taskrc file prevented the override and
automatic creation of an alternate rc file (thanks to Zach Frazier).
+ Fixed bug #259 that cause a build failure on Snow Leopard 10a432.
+ Fixed bug #260 whereby the start, stop and delete commands did not complain
when filter arguments were specified, even though they were ignored
(thanks to T. Charles Yun).
+ Fixed bug that allowed a recurring task to be added without a due date.
+ Fixed bug that displays the wrong .taskrc file name on override (thanks to
Federico Hernandez).
+ Fixed bug that failed to suppress color control code in the header and footnote
when redirecting output to a file (thanks to John Florian).
------ old releases ------------------------------
1.8.0 (7/21/2009) 14977ef317bd004dae2f2c313e806af9f2a2140c
+ Added zsh tab completion script (thanks to P.C. Shyamshankar).
+ Fixed bug that cause the _forcecolor configuration variable to be
considered obsolete (thank to Bruce Dillahunty).
@@ -70,9 +105,7 @@
and completed tasks.
+ Now over 1,600 unit tests, helping to maintain code quality.
------ old releases ------------------------------
1.7.1 (6/8/2009)
1.7.1 (6/8/2009) 1422a15cbc470cff590bf06daad20d01fe1b05ef
+ Fixed build failure on OpenBSD (thanks to Mike Adonay).
+ Took the opportunity of a patch release to update the various email
addresses and URLs in the various documents.

2
NEWS
View File

@@ -1,5 +1,5 @@
New Features in task 1.8.0
New Features in task 1.8
- Attribute modifiers, for precise queries
- Improved calendar feature

View File

@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.61)
AC_INIT(task, 1.8.0, support@taskwarrior.org)
AC_INIT(task, 1.8.1, support@taskwarrior.org)
CFLAGS="${CFLAGS=}"
CXXFLAGS="${CXXFLAGS=}"

View File

@@ -1,4 +1,4 @@
.TH task-tutorial 5 2009-07-14 "Task 1.8.0" "User Manuals"
.TH task-tutorial 5 2009-08-14 "task 1.8.1" "User Manuals"
.SH NAME
task-tutorial \- A tutorial for the task(1) command line todo manager.

View File

@@ -1,4 +1,4 @@
.TH task 1 2009-07-14 "Task 1.8.0" "User Manuals"
.TH task 1 2009-08-14 "task 1.8.1" "User Manuals"
.SH NAME
task \- A command line todo manager.

View File

@@ -1,4 +1,4 @@
.TH taskrc 5 2009-07-14 "Task 1.8.0" "User Manuals"
.TH taskrc 5 2009-08-14 "task 1.8.1" "User Manuals"
.SH NAME
taskrc \- Configuration file for the task(1) command

View File

@@ -1,4 +1,4 @@
# setup.hint for task 1.7.1-1
# setup.hint for task 1.8.1-1
category: Utils
requires: libncurses9 cygwin
sdesc: A command-line to do list manager

View File

@@ -1,4 +1,4 @@
task 1.7.1-1
task 1.8.1-1
------------------------------------------
A command-line to do list manager that can be used
@@ -28,10 +28,10 @@ Language:
------------------------------------
Build instructions:
unpack task-1.7.1-1-src.tar.bz2
unpack task-1.8.1-1-src.tar.bz2
if you use setup to install this src package,
it will be unpacked under /usr/src automatically
cd /usr/src/task-1.7.1-1
cd /usr/src/task-1.8.1-1
./configure --prefix=/usr
make
make install
@@ -42,4 +42,4 @@ task was packaged for cygwin by
Federico Hernandez <ultrafredde@gmail.com> and
is licensed under the GPL
---- task-1.7.1-1 -- 2009-06-17 ----
---- task-1.8.1-1 -- 2009-08-20 ----

View File

@@ -1,8 +1,8 @@
diff -Nrup task-1.7.1-1/CYGWIN-PATCHES/setup.hint task-1.7.1-1.cygwin/CYGWIN-PATCHES/setup.hint
--- task-1.7.1-1/CYGWIN-PATCHES/setup.hint 1970-01-01 01:00:00.000000000 +0100
+++ task-1.7.1-1.cygwin/CYGWIN-PATCHES/setup.hint 2009-06-17 15:47:56.304750000 +0200
diff -Nrup task-1.8.1-1/CYGWIN-PATCHES/setup.hint task-1.8.1-1.cygwin/CYGWIN-PATCHES/setup.hint
--- task-1.8.1-1/CYGWIN-PATCHES/setup.hint 1970-01-01 01:00:00.000000000 +0100
+++ task-1.8.1-1.cygwin/CYGWIN-PATCHES/setup.hint 2009-08-20 15:47:56.304750000 +0200
@@ -0,0 +1,10 @@
+# setup.hint for task 1.7.1-1
+# setup.hint for task 1.8.1-1
+category: Utils
+requires: libncurses9 cygwin
+sdesc: A command-line to do list manager
@@ -12,11 +12,11 @@ diff -Nrup task-1.7.1-1/CYGWIN-PATCHES/setup.hint task-1.7.1-1.cygwin/CYGWIN-PAT
+reports and graphs, lots of manipulation commands,
+low-level API, abbreviations for all commands and
+options, multiuser file locking, recurring tasks."
diff -Nrup task-1.7.1-1/CYGWIN-PATCHES/task-1.7.1-1.README task-1.7.1-1.cygwin/CYGWIN-PATCHES/task-1.7.1-1.README
--- task-1.7.1-1/CYGWIN-PATCHES/task-1.7.1-1.README 1970-01-01 01:00:00.000000000 +0100
+++ task-1.7.1-1.cygwin/CYGWIN-PATCHES/task-1.7.1-1.README 2009-06-17 15:47:44.320375000 +0200
diff -Nrup task-1.8.1-1/CYGWIN-PATCHES/task-1.8.1-1.README task-1.8.1-1.cygwin/CYGWIN-PATCHES/task-1.8.1-1.README
--- task-1.8.1-1/CYGWIN-PATCHES/task-1.8.1-1.README 1970-01-01 01:00:00.000000000 +0100
+++ task-1.8.1-1.cygwin/CYGWIN-PATCHES/task-1.8.1-1.README 2009-08-20 15:47:44.320375000 +0200
@@ -0,0 +1,45 @@
+task 1.7.1-1
+task 1.8.1-1
+------------------------------------------
+
+A command-line to do list manager that can be used
@@ -46,10 +46,10 @@ diff -Nrup task-1.7.1-1/CYGWIN-PATCHES/task-1.7.1-1.README task-1.7.1-1.cygwin/C
+------------------------------------
+
+Build instructions:
+ unpack task-1.7.1-1-src.tar.bz2
+ unpack task-1.8.1-1-src.tar.bz2
+ if you use setup to install this src package,
+ it will be unpacked under /usr/src automatically
+ cd /usr/src/task-1.7.1-1
+ cd /usr/src/task-1.8.1-1
+ ./configure --prefix=/usr
+ make
+ make install
@@ -60,4 +60,4 @@ diff -Nrup task-1.7.1-1/CYGWIN-PATCHES/task-1.7.1-1.README task-1.7.1-1.cygwin/C
+Federico Hernandez <ultrafredde@gmail.com> and
+is licensed under the GPL
+
+---- task-1.7.1-1 -- 2009-06-17 ----
+---- task-1.8.1-1 -- 2009-08-20 ----

View File

@@ -1,4 +1,4 @@
task 1.7.1-1
task 1.8.1-1
------------------------------------------
A command-line to do list manager that can be used
@@ -28,10 +28,10 @@ Language:
------------------------------------
Build instructions:
unpack task-1.7.1-1-src.tar.bz2
unpack task-1.8.1-1-src.tar.bz2
if you use setup to install this src package,
it will be unpacked under /usr/src automatically
cd /usr/src/task-1.7.1-1
cd /usr/src/task-1.8.1-1
./configure --prefix=/usr
make
make install
@@ -42,4 +42,4 @@ task was packaged for cygwin by
Federico Hernandez <ultrafredde@gmail.com> and
is licensed under the GPL
---- task-1.7.1-1 -- 2009-06-17 ----
---- task-1.8.1-1 -- 2009-08-20 ----

View File

@@ -1,6 +1,6 @@
Name: task
Version: 1.8.0
Release: 0%{?dist}
Version: 1.8.1
Release: 1%{?dist}
Summary: A command-line to do list manager
Group: Applications/Productivity
@@ -40,18 +40,25 @@ rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root,-)
%doc AUTHORS ChangeLog COPYING NEWS README scripts
%doc AUTHORS ChangeLog COPYING NEWS README scripts i18n
%{_bindir}/task
%{_mandir}/man1/task.1.gz
%{_mandir}/man5/taskrc.5.gz
%{_mandir}/man5/task-tutorial.5.gz
%{_sysconfdir}/bash_completion.d
%config(noreplace) %{_sysconfdir}/bash_completion.d
%changelog
* Mon Jun 15 2009 Federico Hernandez <ultrafredde@gmail.com> - 1.8.0-0
* Thu Aug 20 2009 Federico Hernandez <ultrafredde@gmail.com> - 1.8.1-1
Intial RPM for task bugfix release 1.8.1
* Tue Jul 21 2009 Federico Hernandez <ultrafredde@gmail.com> - 1.8.0-1
Intial RPM for task release 1.8.0
Installs now bash_completion file
* Mon Jul 13 2009 Federico Hernandez <ultrafredde@gmail.com> - 1.8.0.beta3-1
Intial RPM for task beta release 1.8.0.beta3
* Wed Jul 08 2009 Federico Hernandez <ultrafredde@gmail.com> - 1.8.0.beta2-1
Intial RPM for task beta release 1.8.0.beta2
* Tue Jul 07 2009 Federico Hernandez <ultrafredde@gmail.com> - 1.8.0.beta1-1
Intial RPM for task beta release 1.8.0.beta1
* Tue Jun 08 2009 Federico Hernandez <ultrafredde@gmail.com> - 1.7.1-2
- Fixed inclusion of manpages.
* Tue Jun 08 2009 Federico Hernandez <ultrafredde@gmail.com> - 1.7.1-1

View File

@@ -1,8 +1,32 @@
task (1.8.1-0ubuntu1) jaunty; urgency=low
* Initial deb package for task bugfix release 1.8.1
-- Federico Hernandez <ultrafredde@gmail.com> Thu, 20 Aug 2009 20:26:33 +0200
task (1.8.0-0ubuntu1) jaunty; urgency=low
* Initial deb package for task release 1.8.0
-- Federico Hernandez <ultrafredde@gmail.com> Thu, 11 Jun 2009 23:02:28 +0200
-- Federico Hernandez <ultrafredde@gmail.com> Tue, 21 Jul 2009 15:26:33 +0200
task (1.8.0-0ubuntu1~beta3) jaunty; urgency=low
* Initial deb package for task beta release 1.8.0.beta3
-- Federico Hernandez <ultrafredde@gmail.com> Mon, 13 Jul 2009 15:09:38 +0200
task (1.8.0-0ubuntu1~beta2) jaunty; urgency=low
* Initial deb package for task beta release 1.8.0.beta2
-- Federico Hernandez <ultrafredde@gmail.com> Wed, 08 Jul 2009 15:40:50 +0200
task (1.8.0-0ubuntu1~beta1) jaunty; urgency=low
* Initial deb package for task beta release 1.8.0.beta1
-- Federico Hernandez <ultrafredde@gmail.com> Tue, 07 Jul 2009 01:35:28 +0200
task (1.7.1-0ubuntu1) jaunty; urgency=low

View File

@@ -1,6 +1,6 @@
This package was debianized by:
Federico Hernandez <ultrafredde@gmail.com> on Thu, 11 Jun 2009 23:02:28 +0200
Federico Hernandez <ultrafredde@gmail.com> on Thu, 20 Aug 2009 20:26:33 +0200
It was downloaded from:
@@ -9,6 +9,9 @@ It was downloaded from:
Upstream Authors:
Paul Beckingham <paul@beckingham.net>
Federico Hernandez
David J Patrick
John Florian
Damian Glenny
Andy Lester
H. İbrahim Güngör
@@ -17,18 +20,18 @@ Upstream Authors:
Benjamin Tegarden
Chris Pride
Richard Querin
Federico Hernandez
T. Charles Yun
David J Patrick
P.C. Shyamshankar
Johan Friis
Steven de Brouwer
Pietro Cerutti
Copyright:
Copyright 2006 - 2009, Paul Beckingham
Copyright 2009 Federico Hernandez
Copyright 2009 P.C. Shyamshankar
Copyright 2009 John Florian
License:

View File

@@ -0,0 +1,2 @@
scripts
i18n

View File

@@ -31,8 +31,9 @@ binary-arch: install
dh_installchangelogs
dh_installdocs
dh_installman
install -D -m644 task_completion.sh $(CURDIR)/debian/task/etc/bash_completion.d/task
rm -rf $(CURDIR)/debian/task/usr/share/doc/task-1.7.1
dh_installexamples
install -D -m644 scripts/bash/task_completion.sh $(CURDIR)/debian/task/etc/bash_completion.d/task
rm -rf $(CURDIR)/debian/task/usr/share/doc/task-1.8.1
dh_strip
dh_compress
dh_fixperms

View File

@@ -48,10 +48,6 @@
# http://taskwarrior.org
#
_task_get_projects() {
task _projects
}
_task_get_tags() {
task _tags
}
@@ -60,6 +56,10 @@ _task_get_config() {
task _config
}
_task_offer_projects() {
COMPREPLY=( $(compgen -W "$(task _projects)" -- ${cur/*:/}) )
}
_task()
{
local cur prev opts base
@@ -67,34 +67,61 @@ _task()
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
if [ ${#COMP_WORDS[*]} -gt 2 ]
then
prev2="${COMP_WORDS[COMP_CWORD-2]}"
else
prev2=""
fi
# echo -e "\ncur='$cur'"
# echo "prev='$prev'"
# echo "prev2='$prev2'"
opts="$(task _commands) $(task _ids)"
case "${cur}" in
pro*:*)
local projects=$(_task_get_projects)
local partial_project="${cur/*:/}"
COMPREPLY=( $(compgen -W "${projects}" -- ${partial_project}) )
return 0
case "${prev}" in
:)
case "${prev2}" in
pro*)
_task_offer_projects
return 0
;;
esac
;;
+*)
local tags=$(_task_get_tags | sed 's/^/+/')
COMPREPLY=( $(compgen -W "${tags}" -- ${cur}) )
return 0
;;
-*)
local tags=$(_task_get_tags | sed 's/^/-/')
COMPREPLY=( $(compgen -W "${tags}" -- ${cur}) )
return 0
;;
rc.*)
local config=$(_task_get_config | sed 's/^/rc\./')
COMPREPLY=( $(compgen -W "${config}" -- ${cur}) )
return 0
*)
case "${cur}" in
pro*:*)
_task_offer_projects
return 0
;;
:)
case "${prev}" in
pro*)
_task_offer_projects
return 0
;;
esac
;;
+*)
local tags=$(_task_get_tags | sed 's/^/+/')
COMPREPLY=( $(compgen -W "${tags}" -- ${cur}) )
return 0
;;
-*)
local tags=$(_task_get_tags | sed 's/^/-/')
COMPREPLY=( $(compgen -W "${tags}" -- ${cur}) )
return 0
;;
rc.*)
local config=$(_task_get_config | sed -e 's/^/rc\./' -e 's/$/:/')
COMPREPLY=( $(compgen -W "${config}" -- ${cur}) )
return 0
;;
esac
;;
esac
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
}
complete -F _task task
complete -o nospace -F _task task

View File

@@ -407,6 +407,17 @@ std::string Att::type (const std::string& name) const
return "text";
}
////////////////////////////////////////////////////////////////////////////////
// The type of an attribute is useful for modifier evaluation.
std::string Att::modType (const std::string& name) const
{
if (name == "hasnt" ||
name == "isnt")
return "negative";
return "positive";
}
////////////////////////////////////////////////////////////////////////////////
//
// start --> name --> . --> mod --> : --> " --> value --> " --> end
@@ -461,7 +472,7 @@ void Att::parse (Nibbler& n)
else
throw std::string ("Missing : after attribute name"); // TODO i18n
/* TODO This might be too slow to include. Test.
/* TODO This might be too slow to include. Test this assumption.
validNameValue (mName, mMod, mValue);
*/
}
@@ -711,8 +722,11 @@ void Att::encode (std::string& value) const
while ((i = value.find ('\t')) != std::string::npos)
value.replace (i, 1, "&tab;"); // no i18n
while ((i = value.find ('\'')) != std::string::npos)
value.replace (i, 1, "&squot;"); // no i18n
while ((i = value.find ('"')) != std::string::npos)
value.replace (i, 1, "&quot;"); // no i18n
value.replace (i, 1, "&dquot;"); // no i18n
while ((i = value.find (',')) != std::string::npos)
value.replace (i, 1, "&comma;"); // no i18n
@@ -730,7 +744,8 @@ void Att::encode (std::string& value) const
////////////////////////////////////////////////////////////////////////////////
// Decode values after parse.
// \t <- &tab;
// " <- &quot;
// " <- &quot; or &dquot;
// ' <- &squot;
// , <- &comma;
// [ <- &open;
// ] <- &close;
@@ -742,6 +757,12 @@ void Att::decode (std::string& value) const
while ((i = value.find ("&tab;")) != std::string::npos) // no i18n
value.replace (i, 5, "\t");
while ((i = value.find ("&dquot;")) != std::string::npos) // no i18n
value.replace (i, 7, "\"");
while ((i = value.find ("&squot;")) != std::string::npos) // no i18n
value.replace (i, 7, "'");
while ((i = value.find ("&quot;")) != std::string::npos) // no i18n
value.replace (i, 6, "\"");

View File

@@ -50,6 +50,7 @@ public:
static bool validNameValue (std::string&, std::string&, std::string&);
static bool validMod (const std::string&);
std::string type (const std::string&) const;
std::string modType (const std::string&) const;
void parse (const std::string&);
void parse (Nibbler&);
bool match (const Att&) const;

View File

@@ -148,18 +148,27 @@ int Context::run ()
// Dump all debug messages.
if (config.get (std::string ("debug"), false))
foreach (d, debugMessages)
std::cout << colorizeDebug (*d) << std::endl;
if (config.get ("color", true) || config.get (std::string ("_forcecolor"), false))
std::cout << colorizeDebug (*d) << std::endl;
else
std::cout << *d << std::endl;
// Dump all headers.
foreach (h, headers)
std::cout << colorizeHeader (*h) << std::endl;
if (config.get ("color", true) || config.get (std::string ("_forcecolor"), false))
std::cout << colorizeHeader (*h) << std::endl;
else
std::cout << *h << std::endl;
// Dump the report output.
std::cout << output;
// Dump all footnotes.
foreach (f, footnotes)
std::cout << colorizeFootnote (*f) << std::endl;
if (config.get ("color", true) || config.get (std::string ("_forcecolor"), false))
std::cout << colorizeFootnote (*f) << std::endl;
else
std::cout << *f << std::endl;
return 0;
}
@@ -307,6 +316,18 @@ std::string Context::canonicalize (const std::string& input) const
return canonical;
}
////////////////////////////////////////////////////////////////////////////////
void Context::disallowModification () const
{
if (task.size () ||
subst.mFrom != "" ||
tagAdditions.size () ||
tagRemovals.size ())
throw std::string ("The '")
+ cmd.command
+ "' command does not allow further modification of a task.";
}
////////////////////////////////////////////////////////////////////////////////
void Context::loadCorrectConfigFile ()
{
@@ -330,6 +351,14 @@ void Context::loadCorrectConfigFile ()
else if (arg->substr (0, 3) == "rc:")
{
rc = arg->substr (3, std::string::npos);
home = rc;
std::string::size_type last_slash = rc.rfind ("/");
if (last_slash != std::string::npos)
home = rc.substr (0, last_slash);
else
home = ".";
args.erase (arg);
header ("Using alternate .taskrc file " + rc); // TODO i18n
break;
@@ -358,13 +387,19 @@ void Context::loadCorrectConfigFile ()
}
// Do we need to create a default rc?
if (access (rc.c_str (), F_OK) &&
confirm ("A configuration file could not be found in " // TODO i18n
+ home
+ "\n\n"
+ "Would you like a sample .taskrc created, so task can proceed?"))
if (access (rc.c_str (), F_OK))
{
config.createDefaultRC (rc, data);
if (confirm ("A configuration file could not be found in " // TODO i18n
+ home
+ "\n\n"
+ "Would you like a sample "
+ rc
+ " created, so task can proceed?"))
{
config.createDefaultRC (rc, data);
}
else
throw std::string ("Cannot proceed without rc file.");
}
// Create data location, if necessary.
@@ -528,7 +563,12 @@ void Context::parse (
attribute.mod (mod);
attribute.value (value);
parseTask[attribute.name ()] = attribute;
// Preserve modifier in the key, to allow multiple modifiers on the
// same attribute. Bug #252.
if (name != "" && mod != "")
parseTask[name + "." + mod] = attribute;
else
parseTask[name] = attribute;
}
// *arg has the appearance of an attribute (foo:bar), but isn't
@@ -657,46 +697,46 @@ void Context::autoFilter (Task& t, Filter& f)
foreach (att, t)
{
// Words are found in the description using the .has modifier.
if (att->first == "description" && att->second.mod () == "")
if (att->second.name () == "description" && att->second.mod () == "")
{
std::vector <std::string> words;
split (words, att->second.value (), ' ');
foreach (word, words)
{
f.push_back (Att ("description", "has", *word));
debug ("auto filter: " + att->first + ".has:" + *word);
debug ("auto filter: " + att->second.name () + ".has:" + *word);
}
}
// Projects are matched left-most.
else if (att->first == "project" && att->second.mod () == "")
else if (att->second.name () == "project" && att->second.mod () == "")
{
if (att->second.value () != "")
{
f.push_back (Att ("project", "startswith", att->second.value ()));
debug ("auto filter: " + att->first + ".startswith:" + att->second.value ());
debug ("auto filter: " + att->second.name () + ".startswith:" + att->second.value ());
}
else
{
f.push_back (Att ("project", "is", att->second.value ()));
debug ("auto filter: " + att->first + ".is:" + att->second.value ());
debug ("auto filter: " + att->second.name () + ".is:" + att->second.value ());
}
}
// The limit attribute does not participate in filtering, and needs to be
// specifically handled in handleCustomReport.
else if (att->first == "limit")
else if (att->second.name () == "limit")
{
}
// Every task has a unique uuid by default, and it shouldn't be included,
// because it is guaranteed to not match.
else if (att->first == "uuid")
else if (att->second.name () == "uuid")
{
}
// The mechanism for filtering on tags is +/-<tag>.
else if (att->first == "tags")
else if (att->second.name () == "tags")
{
}
@@ -705,7 +745,7 @@ void Context::autoFilter (Task& t, Filter& f)
{
f.push_back (att->second);
debug ("auto filter: " +
att->first +
att->second.name () +
(att->second.mod () != "" ?
("." + att->second.mod () + ":") :
":") +

View File

@@ -65,6 +65,7 @@ public:
void clear ();
std::string canonicalize (const std::string&) const;
void disallowModification () const;
private:
void loadCorrectConfigFile ();

View File

@@ -51,12 +51,6 @@ Duration::Duration (const std::string& input)
parse (input);
}
////////////////////////////////////////////////////////////////////////////////
Duration::operator int ()
{
return (int) mDays;
}
////////////////////////////////////////////////////////////////////////////////
Duration::operator time_t ()
{

View File

@@ -40,7 +40,6 @@ public:
bool operator> (const Duration&);
~Duration (); // Destructor
operator int ();
operator time_t ();
operator std::string ();

View File

@@ -40,37 +40,51 @@ bool Filter::pass (const Record& record) const
// First do description/annotation matches.
foreach (att, (*this))
{
// Descriptions have special handling.
// Descriptions have special handling such that they are linked to
// annotations, and filtering on description implies identical filtering
// on annotations, and that both filter matches must succeed for the filter
// to succeed overall.
if (att->name () == "description")
{
bool description_result = true;
int annotation_pass_count = 0;
int annotation_fail_count = 0;
if ((r = record.find (att->name ())) != record.end ())
{
// A description match failure can be salvaged by an annotation match.
if (! att->match (r->second))
{
bool annoMatch = false;
foreach (ra, record)
{
if (ra->first.length () > 11 &&
ra->first.substr (0, 11) == "annotation_")
{
if (att->match (ra->second))
{
annoMatch = true;
break;
}
}
}
description_result = att->match (r->second);
if (!annoMatch)
return false;
foreach (ra, record)
{
if (ra->first.length () > 11 &&
ra->first.substr (0, 11) == "annotation_")
{
if (att->match (ra->second))
++annotation_pass_count;
else
++annotation_fail_count;
}
}
}
else if (! att->match (Att ()))
return false;
// This innocuous little if-else took significantly more thinking and
// debugging than anything else in task. Only change this code if you
// are willing to invest a week understanding and testing it.
if (att->modType (att->mod ()) == "positive")
{
if (! (description_result || annotation_pass_count > 0))
return false;
}
else
{
if (!description_result || annotation_fail_count > 0)
return false;
}
}
// Annotations are skipped.
// Annotations are skipped, because they are handled above.
else if (att->name ().length () > 11 &&
att->name ().substr (0, 11) == "annotation_")
{

View File

@@ -67,8 +67,8 @@ bool Task::operator== (const Task& other)
return false;
foreach (att, *this)
if (att->first != "uuid")
if (att->second.value () != other.get (att->first))
if (att->second.name () != "uuid")
if (att->second.value () != other.get (att->second.name ()))
return false;
return true;
@@ -363,12 +363,12 @@ std::string Task::composeCSV () const
out << get ("start") << ","; // No i18n
if (has ("due"))
out << "'" << get ("due") << "',"; // No i18n
out << get ("due") << ","; // No i18n
else
out << ","; // No i18n
if (has ("recur"))
out << "'" << get ("recur") << "',"; // No i18n
out << get ("recur") << ","; // No i18n
else
out << ","; // No i18n

View File

@@ -84,6 +84,15 @@ std::string handleAdd ()
foreach (tag, context.tagAdditions)
context.task.addTag (*tag);
// Perform some logical consistency checks.
if (context.task.has ("recur") &&
!context.task.has ("due"))
throw std::string ("You cannot specify a recurring task without a due date.");
if (context.task.has ("until") &&
!context.task.has ("recur"))
throw std::string ("You cannot specify an until date for a non-recurring task.");
// Only valid tasks can be added.
context.task.validate ();
@@ -113,7 +122,6 @@ std::string handleProjects ()
std::vector <Task> tasks;
context.tdb.lock (context.config.get ("locking", true));
handleRecurrence ();
int quantity = context.tdb.loadPending (tasks, context.filter);
context.tdb.commit ();
context.tdb.unlock ();
@@ -199,7 +207,6 @@ std::string handleCompletionProjects ()
{
std::vector <Task> tasks;
context.tdb.lock (context.config.get ("locking", true));
handleRecurrence ();
Filter filter;
if (context.config.get (std::string ("complete.all.projects"), false))
@@ -233,7 +240,6 @@ std::string handleTags ()
std::vector <Task> tasks;
context.tdb.lock (context.config.get ("locking", true));
handleRecurrence ();
int quantity = context.tdb.loadPending (tasks, context.filter);
context.tdb.commit ();
context.tdb.unlock ();
@@ -296,7 +302,6 @@ std::string handleCompletionTags ()
{
std::vector <Task> tasks;
context.tdb.lock (context.config.get ("locking", true));
handleRecurrence ();
Filter filter;
if (context.config.get (std::string ("complete.all.tags"), false))
@@ -359,7 +364,6 @@ std::string handleCompletionIDs ()
{
std::vector <Task> tasks;
context.tdb.lock (context.config.get ("locking", true));
handleRecurrence ();
Filter filter;
context.tdb.loadPending (tasks, filter);
context.tdb.commit ();
@@ -383,6 +387,8 @@ std::string handleCompletionIDs ()
////////////////////////////////////////////////////////////////////////////////
void handleUndo ()
{
context.disallowModification ();
context.tdb.lock (context.config.get ("locking", true));
context.tdb.undo ();
context.tdb.unlock ();
@@ -553,9 +559,10 @@ std::string handleDelete ()
{
std::stringstream out;
context.disallowModification ();
std::vector <Task> tasks;
context.tdb.lock (context.config.get ("locking", true));
handleRecurrence ();
Filter filter;
context.tdb.loadPending (tasks, filter);
@@ -653,9 +660,10 @@ std::string handleStart ()
{
std::stringstream out;
context.disallowModification ();
std::vector <Task> tasks;
context.tdb.lock (context.config.get ("locking", true));
handleRecurrence ();
Filter filter;
context.tdb.loadPending (tasks, filter);
@@ -705,9 +713,10 @@ std::string handleStop ()
{
std::stringstream out;
context.disallowModification ();
std::vector <Task> tasks;
context.tdb.lock (context.config.get ("locking", true));
handleRecurrence ();
Filter filter;
context.tdb.loadPending (tasks, filter);
@@ -754,7 +763,6 @@ std::string handleDone ()
std::vector <Task> tasks;
context.tdb.lock (context.config.get ("locking", true));
handleRecurrence ();
Filter filter;
context.tdb.loadPending (tasks, filter);
@@ -885,7 +893,6 @@ std::string handleModify ()
std::vector <Task> tasks;
context.tdb.lock (context.config.get ("locking", true));
handleRecurrence ();
Filter filter;
context.tdb.loadPending (tasks, filter);
@@ -963,7 +970,6 @@ std::string handleAppend ()
std::vector <Task> tasks;
context.tdb.lock (context.config.get ("locking", true));
handleRecurrence ();
Filter filter;
context.tdb.loadPending (tasks, filter);
@@ -1359,12 +1365,12 @@ int deltaAttributes (Task& task)
foreach (att, context.task)
{
if (att->first != "uuid" &&
att->first != "description" &&
att->first != "tags")
if (att->second.name () != "uuid" &&
att->second.name () != "description" &&
att->second.name () != "tags")
{
// Modifying "wait" changes status.
if (att->first == "wait")
if (att->second.name () == "wait")
{
if (att->second.value () == "")
task.setStatus (Task::pending);
@@ -1373,8 +1379,9 @@ int deltaAttributes (Task& task)
}
if (att->second.value () == "")
task.remove (att->first);
task.remove (att->second.name ());
else
// One of the few places where the compound attribute name is used.
task.set (att->first, att->second.value ());
++changes;

View File

@@ -499,7 +499,13 @@ static void parseTask (Task& task, const std::string& after)
std::string::size_type gap = value.find (" ");
if (gap != std::string::npos)
{
Date when (value.substr (0, gap));
Date when (value.substr (0, gap), context.config.get ("dateformat", "m/d/Y"));
// This guarantees that if more than one annotation has the same date,
// that the seconds will be different, thus unique, thus not squashed.
// Bug #249
when += (const int) annotations.size ();
std::stringstream name;
name << "annotation_" << when.toEpoch ();
std::string text = trim (value.substr (gap, std::string::npos), "\t ");

View File

@@ -34,7 +34,7 @@
#include "Context.h"
//#include "text.h"
//#include "util.h"
//#include "main.h"
#include "main.h"
#include "i18n.h"
#include "../auto.h"

83
src/task.h Normal file
View File

@@ -0,0 +1,83 @@
////////////////////////////////////////////////////////////////////////////////
// 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_TASK
#define INCLUDED_TASK
#include <string>
#include "Record.h"
#include "Subst.h"
#include "Sequence.h"
class Task : public Record
{
public:
Task (); // Default constructor
Task (const Task&); // Copy constructor
Task& operator= (const Task&); // Assignment operator
bool operator== (const Task&); // Comparison operator
Task (const std::string&); // Parse
~Task (); // Destructor
void parse (const std::string&);
std::string composeCSV () const;
// Status values.
enum status {pending, completed, deleted, recurring, waiting};
// Public data.
int id;
// Series of helper functions.
static status textToStatus (const std::string&);
static std::string statusToText (status);
void setEntry ();
status getStatus ();
void setStatus (status);
int getTagCount ();
bool hasTag (const std::string&);
void addTag (const std::string&);
void addTags (const std::vector <std::string>&);
void getTags (std::vector<std::string>&) const;
void removeTag (const std::string&);
void getAnnotations (std::vector <Att>&) const;
void setAnnotations (const std::vector <Att>&);
void addAnnotation (const std::string&);
void removeAnnotations ();
void validate () const;
private:
int determineVersion (const std::string&);
void legacyParse (const std::string&);
};
#endif
////////////////////////////////////////////////////////////////////////////////

View File

@@ -75,9 +75,9 @@ int main (int argc, char** argv)
Att a5 ("name", "value");
t.is (a5.composeF4 (), "name:\"value\"", "Att::composeF4 simple");
a5.value ("\"");
t.is (a5.composeF4 (), "name:\"&quot;\"", "Att::composeF4 encoded \"");
t.is (a5.composeF4 (), "name:\"&dquot;\"", "Att::composeF4 encoded \"");
a5.value ("\t\",[]:");
t.is (a5.composeF4 (), "name:\"&tab;&quot;&comma;&open;&close;&colon;\"", "Att::composeF4 fully encoded \\t\",[]:");
t.is (a5.composeF4 (), "name:\"&tab;&dquot;&comma;&open;&close;&colon;\"", "Att::composeF4 fully encoded \\t\",[]:");
Att a6 ("name", 6);
t.is (a6.value_int (), 6, "Att::value_int get");
@@ -174,12 +174,12 @@ int main (int argc, char** argv)
n = Nibbler ("name:\"&quot;\"");
a7.parse (n);
t.is (a7.composeF4 (), "name:\"&quot;\"",
t.is (a7.composeF4 (), "name:\"&dquot;\"",
"Att::parse (name:\"&quot;\")");
n = Nibbler ("name:\"&tab;&quot;&comma;&open;&close;&colon;\"");
a7.parse (n);
t.is (a7.composeF4 (), "name:\"&tab;&quot;&comma;&open;&close;&colon;\"",
t.is (a7.composeF4 (), "name:\"&tab;&dquot;&comma;&open;&close;&colon;\"",
"Att::parse (name:\"&tab;&quot;&comma;&open;&close;&colon;\")");
n = Nibbler ("total gibberish");
@@ -216,19 +216,19 @@ int main (int argc, char** argv)
good = true;
try {a7.parse (n);} catch (...) {good = false;}
t.ok (good, "Att::parse (name:\"value)");
t.is (a7.composeF4 (), "name:\"&quot;value\"", "Att::composeF4 -> name:\"&quot;value\"");
t.is (a7.composeF4 (), "name:\"&dquot;value\"", "Att::composeF4 -> name:\"&dquot;value\"");
n = Nibbler ("name:value\"");
good = true;
try {a7.parse (n);} catch (...) {good = false;}
t.ok (good, "Att::parse (name:value\")");
t.is (a7.composeF4 (), "name:\"value&quot;\"", "Att::composeF4 -> name:\"value&quot;\"");
t.is (a7.composeF4 (), "name:\"value&dquot;\"", "Att::composeF4 -> name:\"value&dquot;\"");
n = Nibbler ("name:val\"ue");
good = true;
try {a7.parse (n);} catch (...) {good = false;}
t.ok (good, "Att::parse (name:val\"ue)");
t.is (a7.composeF4 (), "name:\"val&quot;ue\"", "Att::composeF4 -> name:\"val&quot;ue\"");
t.is (a7.composeF4 (), "name:\"val&dquot;ue\"", "Att::composeF4 -> name:\"val&dquot;ue\"");
n = Nibbler ("name\"");
good = true;

View File

@@ -43,10 +43,10 @@ if (open my $fh, '>', 'before.rc')
# Create some exampel data directly.
if (open my $fh, '>', 'pending.data')
{
# 1230000000 = 12/22/2008
# 1229947200 = 12/22/2008
# 1240000000 = 4/17/2009
print $fh <<EOF;
[description:"foo" entry:"1230000000" start:"1230000000" status:"pending" uuid:"27097693-91c2-4cbe-ba89-ddcc87e5582c"]
[description:"foo" entry:"1229947200" start:"1229947200" status:"pending" uuid:"27097693-91c2-4cbe-ba89-ddcc87e5582c"]
[description:"bar" entry:"1240000000" start:"1240000000" status:"pending" uuid:"08f72d91-964c-424b-8fd5-556434648b6b"]
EOF

106
src/tests/bug.hasnt.t Executable file
View File

@@ -0,0 +1,106 @@
#! /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 => 19;
# Create the rc file.
if (open my $fh, '>', 'hasnt.rc')
{
print $fh "data.location=.\n",
"confirmation=no\n";
close $fh;
ok (-r 'hasnt.rc', 'Created hasnt.rc');
}
# 1
qx{../task rc:hasnt.rc add foo};
# 2
qx{../task rc:hasnt.rc add foo};
qx{../task rc:hasnt.rc 2 annotate bar};
# 3
qx{../task rc:hasnt.rc add foo};
qx{../task rc:hasnt.rc 3 annotate bar};
sleep 2;
qx{../task rc:hasnt.rc 3 annotate baz};
# 4
qx{../task rc:hasnt.rc add bar};
# 5
qx{../task rc:hasnt.rc add bar};
qx{../task rc:hasnt.rc 5 annotate foo};
# 6
qx{../task rc:hasnt.rc add bar};
qx{../task rc:hasnt.rc 6 annotate foo};
sleep 2;
qx{../task rc:hasnt.rc 6 annotate baz};
#7
qx{../task rc:hasnt.rc add one};
qx{../task rc:hasnt.rc 7 annotate two};
sleep 2;
qx{../task rc:hasnt.rc 7 annotate three};
my $output = qx{../task rc:hasnt.rc ls description.has:foo};
like ($output, qr/\n 1/, '1 has foo -> yes');
like ($output, qr/\n 2/, '2 has foo -> yes');
like ($output, qr/\n 3/, '3 has foo -> yes');
unlike ($output, qr/\n 4/, '4 has foo -> no');
like ($output, qr/\n 5/, '5 has foo -> yes');
like ($output, qr/\n 6/, '6 has foo -> yes');
unlike ($output, qr/\n 7/, '7 has foo -> no');
$output = qx{../task rc:hasnt.rc ls description.hasnt:foo};
unlike ($output, qr/\n 1/, '1 hasnt foo -> no');
unlike ($output, qr/\n 2/, '2 hasnt foo -> no');
unlike ($output, qr/\n 3/, '3 hasnt foo -> no');
like ($output, qr/\n 4/, '4 hasnt foo -> yes');
unlike ($output, qr/\n 5/, '5 hasnt foo -> no');
unlike ($output, qr/\n 6/, '6 hasnt foo -> no');
like ($output, qr/\n 7/, '7 hasnt foo -> yes');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'completed.data';
ok (!-r 'completed.data', 'Removed completed.data');
unlink 'undo.data';
ok (!-r 'undo.data', 'Removed undo.data');
unlink 'hasnt.rc';
ok (!-r 'hasnt.rc', 'Removed hasnt.rc');
exit 0;

65
src/tests/bug.range.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 => 8;
# Create the rc file.
if (open my $fh, '>', 'range.rc')
{
print $fh "data.location=.\n",
"confirmation=no\n";
close $fh;
ok (-r 'range.rc', 'Created range.rc');
}
# Add three tasks, and attempt to list the middle one within a range.
qx{../task rc:range.rc add one due:8/1/2009};
qx{../task rc:range.rc add two due:8/3/2009};
qx{../task rc:range.rc add three due:8/5/2009};
my $output = qx{../task rc:range.rc ls due.after:8/2/2009 due.before:8/4/2009};
unlike ($output, qr/one/, 'Missing prior to range');
like ($output, qr/two/, 'Found within range');
unlike ($output, qr/three/, 'Missing after range');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'completed.data';
ok (!-r 'completed.data', 'Removed completed.data');
unlink 'undo.data';
ok (!-r 'undo.data', 'Removed undo.data');
unlink 'range.rc';
ok (!-r 'range.rc', 'Removed range.rc');
exit 0;

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

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

62
src/tests/bug.start.extra.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 => 7;
# Create the rc file.
if (open my $fh, '>', 'extra.rc')
{
print $fh "data.location=.\n",
"confirmation=no\n";
close $fh;
ok (-r 'extra.rc', 'Created extra.rc');
}
qx{../task rc:extra.rc add foo};
my $output = qx{../task rc:extra.rc 1 start pri:L};
like ($output, qr/The 'start' command does not allow further modification of a task\./, 'no modifications allowed for start');
$output = qx{../task rc:extra.rc 1 stop pro:bar};
like ($output, qr/The 'stop' command does not allow further modification of a task\./, 'no modifications allowed for stop');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'completed.data';
ok (!-r 'completed.data', 'Removed completed.data');
unlink 'undo.data';
ok (!-r 'undo.data', 'Removed undo.data');
unlink 'extra.rc';
ok (!-r 'extra.rc', 'Removed extra.rc');
exit 0;

View File

@@ -42,7 +42,7 @@ if (open my $fh, '>', 'custom.rc')
ok (-r 'custom.rc', 'Created custom.rc');
}
# Generate the usage screen, and locate the custom report on it.
# Add a recurring and non-recurring task, look for the indicator.
qx{../task rc:custom.rc add foo due:tomorrow recur:weekly};
qx{../task rc:custom.rc add bar};
my $output = qx{../task rc:custom.rc foo 2>&1};

View File

@@ -111,52 +111,25 @@ unlike ($output, qr/six/, 'g6');
unlike ($output, qr/seven/, 'g7');
$output = qx{../task rc:filter.rc list -tag};
unlike ($output, qr/one/, 'g1');
like ($output, qr/two/, 'g2');
like ($output, qr/three/, 'g3');
like ($output, qr/four/, 'g4');
unlike ($output, qr/five/, 'g5');
like ($output, qr/six/, 'g6');
like ($output, qr/seven/, 'g7');
unlike ($output, qr/one/, 'h1');
like ($output, qr/two/, 'h2');
like ($output, qr/three/, 'h3');
like ($output, qr/four/, 'h4');
unlike ($output, qr/five/, 'h5');
like ($output, qr/six/, 'h6');
like ($output, qr/seven/, 'h7');
$output = qx{../task rc:filter.rc list -missing};
like ($output, qr/one/, 'g1');
like ($output, qr/two/, 'g2');
like ($output, qr/three/, 'g3');
like ($output, qr/four/, 'g4');
like ($output, qr/five/, 'g5');
like ($output, qr/six/, 'g6');
like ($output, qr/seven/, 'g7');
like ($output, qr/one/, 'i1');
like ($output, qr/two/, 'i2');
like ($output, qr/three/, 'i3');
like ($output, qr/four/, 'i4');
like ($output, qr/five/, 'i5');
like ($output, qr/six/, 'i6');
like ($output, qr/seven/, 'i7');
$output = qx{../task rc:filter.rc list +tag -tag};
unlike ($output, qr/one/, 'g1');
unlike ($output, qr/two/, 'g2');
unlike ($output, qr/three/, 'g3');
unlike ($output, qr/four/, 'g4');
unlike ($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/one/, 'j1');
unlike ($output, qr/two/, 'j2');
unlike ($output, qr/three/, 'j3');
unlike ($output, qr/four/, 'j4');
@@ -164,25 +137,25 @@ 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};
$output = qx{../task rc:filter.rc list project:A priority:H};
like ($output, qr/one/, 'k1');
unlike ($output, qr/two/, 'k2');
like ($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');
$output = qx{../task rc:filter.rc list project:A priority:};
unlike ($output, qr/one/, 'l1');
unlike ($output, qr/two/, 'l2');
unlike ($output, qr/three/, 'l3');
like ($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};
$output = qx{../task rc:filter.rc list project:A foo};
like ($output, qr/one/, 'm1');
unlike ($output, qr/two/, 'm2');
unlike ($output, qr/three/, 'm3');
@@ -191,7 +164,7 @@ 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};
$output = qx{../task rc:filter.rc list project:A +tag};
like ($output, qr/one/, 'n1');
unlike ($output, qr/two/, 'n2');
unlike ($output, qr/three/, 'n3');
@@ -200,14 +173,41 @@ 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};
like ($output, qr/one/, 'o1');
unlike ($output, qr/two/, 'o2');
unlike ($output, qr/three/, 'o3');
unlike ($output, qr/four/, 'o4');
unlike ($output, qr/five/, 'o5');
unlike ($output, qr/six/, 'o6');
unlike ($output, qr/seven/, 'o7');
$output = qx{../task rc:filter.rc list project:A priority:H +tag};
like ($output, qr/one/, 'p1');
unlike ($output, qr/two/, 'p2');
unlike ($output, qr/three/, 'p3');
unlike ($output, qr/four/, 'p4');
unlike ($output, qr/five/, 'p5');
unlike ($output, qr/six/, 'p6');
unlike ($output, qr/seven/, 'p7');
$output = qx{../task rc:filter.rc list project:A priority:H foo +tag};
like ($output, qr/one/, 'q1');
unlike ($output, qr/two/, 'q2');
unlike ($output, qr/three/, 'q3');
unlike ($output, qr/four/, 'q4');
unlike ($output, qr/five/, 'q5');
unlike ($output, qr/six/, 'q6');
unlike ($output, qr/seven/, 'q7');
$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');
unlike ($output, qr/one/, 'r1');
unlike ($output, qr/two/, 'r2');
unlike ($output, qr/three/, 'r3');
unlike ($output, qr/four/, 'r4');
unlike ($output, qr/five/, 'r5');
unlike ($output, qr/six/, 'r6');
unlike ($output, qr/seven/, 'r7');
# Cleanup.
unlink 'pending.data';