Merge branch '2.4.3' into lexer2

This commit is contained in:
Paul Beckingham 2015-03-20 17:16:48 -04:00
commit 24a1cbefe9
49 changed files with 876 additions and 850 deletions

View file

@ -10,7 +10,7 @@ include (CheckStructHasMember)
set (HAVE_CMAKE true) set (HAVE_CMAKE true)
project (task) project (task)
set (PROJECT_VERSION "2.4.2") set (PROJECT_VERSION "2.4.3")
OPTION(USE_GNUTLS "Build gnutls support." ON) OPTION(USE_GNUTLS "Build gnutls support." ON)

View file

@ -1,4 +1,11 @@
2.4.2 () - 2.4.3 () -
- TW-1578 Bash tab completion problems on first run
(thanks to Renato Alves and Ptolemarch).
------ current release ---------------------------
2.4.2 (2015-03-15) b9dc0813d9a8922b4cef9595033f133f9fbabf44
- TW-41 Tasks in subprojects are not counted in project completion (thanks - TW-41 Tasks in subprojects are not counted in project completion (thanks
to Renato Alves). to Renato Alves).
@ -24,8 +31,8 @@
- The 'info' command now shows virtual tags. - The 'info' command now shows virtual tags.
- Fixed major on-modify hooks regression where hooks could no longer modify - Fixed major on-modify hooks regression where hooks could no longer modify
the tasks handed to them. the tasks handed to them.
- 'task _version' now outputs "2.4.2 (git-ref)" when built from git. "2.4.2"
------ current release --------------------------- when built from release tarballs (thanks to Renato Alves).
2.4.1 (2015-02-16) 82e019a4a8b20de63d53b51d59b8d1c89d3c05b2 2.4.1 (2015-02-16) 82e019a4a8b20de63d53b51d59b8d1c89d3c05b2
@ -122,6 +129,7 @@
- TW-52 "task add ... recur:2 months" interpreted as "2s" (thanks to jwhisnant). - TW-52 "task add ... recur:2 months" interpreted as "2s" (thanks to jwhisnant).
- TW-55 Bulk edit recurring tasks without answering yes/no for each? (thanks to - TW-55 Bulk edit recurring tasks without answering yes/no for each? (thanks to
Max Muller). Max Muller).
- TW-63 indicators for UDAs (thanks to David Patrick).
- TW-71 task ls/list/long/etc. should match contents of projects too (thanks to - TW-71 task ls/list/long/etc. should match contents of projects too (thanks to
Cory Donnelly). Cory Donnelly).
- TW-72 extend info report with urgency column. - TW-72 extend info report with urgency column.

View file

@ -10,7 +10,7 @@ How to Build Taskwarrior
Obtain and build code: Obtain and build code:
$ git clone https://git.tasktools.org/scm/tm/task.git task.git $ git clone https://git.tasktools.org/scm/tm/task.git task.git
$ cd task.git $ cd task.git
$ git checkout 2.4.2 # Latest dev branch $ git checkout 2.4.3 # Latest dev branch
$ cmake -DCMAKE_BUILD_TYPE=debug . # debug or release. Default: neither. $ cmake -DCMAKE_BUILD_TYPE=debug . # debug or release. Default: neither.
$ make VERBOSE=1 # Shows details $ make VERBOSE=1 # Shows details
@ -189,11 +189,11 @@ Work in Progress
Current Codebase Condition Current Codebase Condition
'master' branch: 'master' branch:
- 2.4.1 Current release, locked. - 2.4.2 Current release, locked.
'2.4.2' branch: '2.4.3' branch:
- Current development branch no plans yet. - Current development branch no plans yet.
--- ---
2015-02-14 Updated for 2.4.1 2015-03-15 Updated for 2.4.3

33
NEWS
View file

@ -1,39 +1,26 @@
New Features in taskwarrior 2.4.2 New Features in taskwarrior 2.4.3
- Ability to set context, which serves as a permanent user-defined filter. -
- The 'info' command now shows virtual tags.
New commands in taskwarrior 2.4.2 New commands in taskwarrior 2.4.3
- The 'context' command has been added, along with it subcommands 'define', -
'delete', 'show', 'list' and 'none'.
New configuration options in taskwarrior 2.4.2 New configuration options in taskwarrior 2.4.3
- 'context' to store the current context applied. -
- 'context.<name>' to store the definition of context 'name'
Newly deprecated features in taskwarrior 2.4.2 Newly deprecated features in taskwarrior 2.4.3
- None -
Removed features in 2.4.2 Removed features in 2.4.3
- None -
Known Issues Known Issues
- If you upgraded from Taskwarrior 2.3.0, you will need one of the following
settings to allow continued syncing to a Taskserver:
$ task config taskd.trust strict
$ task config taskd.trust 'ignore hostname'
$ task config taskd.trust 'allow all'
These are presented in order of preference from most to least secure, and
depend on how your certs were generated.
- https://bug.tasktools.org/ - https://bug.tasktools.org/
Taskwarrior has been built and tested on the following configurations: Taskwarrior has been built and tested on the following configurations:

View file

@ -1,4 +1,4 @@
.TH task-color 5 2015-02-16 "${PACKAGE_STRING}" "User Manuals" .TH task-color 5 2015-03-15 "${PACKAGE_STRING}" "User Manuals"
.SH NAME .SH NAME
task-color \- A color tutorial for the taskwarrior command line todo manager. task-color \- A color tutorial for the taskwarrior command line todo manager.

View file

@ -1,4 +1,4 @@
.TH task-sync 5 2015-02-16 "${PACKAGE_STRING}" "User Manuals" .TH task-sync 5 2015-03-15 "${PACKAGE_STRING}" "User Manuals"
.SH NAME .SH NAME
task-sync \- A discussion and tutorial for the various task(1) data task-sync \- A discussion and tutorial for the various task(1) data

View file

@ -1,4 +1,4 @@
.TH task 1 2015-02-16 "${PACKAGE_STRING}" "User Manuals" .TH task 1 2015-03-15 "${PACKAGE_STRING}" "User Manuals"
.SH NAME .SH NAME
task \- A command line todo manager. task \- A command line todo manager.
@ -379,6 +379,22 @@ time from the specified task.
Miscellaneous subcommands either accept no command line arguments, or accept Miscellaneous subcommands either accept no command line arguments, or accept
non-standard arguments. non-standard arguments.
.TP
.B task calc <expression>
Evaluates an algebraic expression. Can be used to test how TaskWarrior
parses and evaluates the expression given on the command line.
Examples:
task calc 1 + 1
2
task calc now + 8d
2015-03-26T18:06:57
task calc eom
2015-03-31T23:59:59
.TP .TP
.B task config [name [value | '']] .B task config [name [value | '']]
Add, modify and remove settings directly in the taskwarrior configuration. Add, modify and remove settings directly in the taskwarrior configuration.
@ -1161,11 +1177,11 @@ the 'data.location' configuration setting of the task data directory.
For examples please see the online documentation starting at For examples please see the online documentation starting at
.RS .RS
<http://taskwarrior.org/projects/taskwarrior/wiki> <http://taskwarrior.org/docs>
.RE .RE
Note that the online documentation is more detailed and more current than this Note that the online documentation can be more detailed and more current than
man page. this man page.
.SH FILES .SH FILES

View file

@ -1,4 +1,4 @@
.TH taskrc 5 2015-02-16 "${PACKAGE_STRING}" "User Manuals" .TH taskrc 5 2015-03-15 "${PACKAGE_STRING}" "User Manuals"
.SH NAME .SH NAME
taskrc \- Configuration details for the task(1) command taskrc \- Configuration details for the task(1) command
@ -288,7 +288,7 @@ value is "yes". Consider leaving this setting as "yes", for safety.
.TP .TP
.B allow.empty.filter=yes .B allow.empty.filter=yes
An empty filter combined with a write command is potentially a way to modify An empty filter combined with a write command is potentially a way to modify
all tasks by mistkae, and when this is detected, confirmation is required. all tasks by mistake, and when this is detected, confirmation is required.
Setting this to 'no' means that it is an error to use a write command with no Setting this to 'no' means that it is an error to use a write command with no
filter. filter.

View file

@ -1,15 +1,24 @@
Themes Themes
To generate samples of themes, first execute the 'run' script to generate the To generate samples of themes, first execute the 'setup' script to generate the
sample data. Note that this data may need to be tweaked to include qualities sample data. Note that this data may need to be tweaked to include qualities
that need to be illustrated in theme sample. that need to be illustrated in theme sample.
Then edit the 'rc' file to include the desired theme file. Using a dark-background terminal (black recommended), run the following:
Then run 'per' to run a few commands for each theme. run.dark
Note that this will require that the terminal window be switched between a black Using a light-background terminal, run the following:
and white background to properly show the light and dark themes.
run.light
Using a solarized dark terminal, run the following:
run.solar.dark
Using a solarized light terminal, run the following:
run.solar.light
Note that for the solarized themes, the terminal color palette needs to be set Note that for the solarized themes, the terminal color palette needs to be set
to specific colors. to specific colors.

View file

@ -1,23 +0,0 @@
for theme in $PWD/../../rc/*.theme
do
cat <<EOF >>x
data.location=.
confirmation=off
_forcecolor=on
include $theme
EOF
echo "--- $theme -----------------------------------------------------"
echo '$ task list'
task rc:x list
echo '$ task summary'
task rc:x summary
echo '$ task ghistory'
task rc:x ghistory
echo '$ task calendar'
task rc:x calendar
echo '$ task burndown.daily'
task rc:x burndown.daily
done

View file

@ -21,6 +21,8 @@ include $theme
EOF EOF
echo "--- $theme -----------------------------------------------------" echo "--- $theme -----------------------------------------------------"
echo '$ task color legend'
task rc:x color legend
echo '$ task list' echo '$ task list'
task rc:x list task rc:x list
echo '$ task summary' echo '$ task summary'

24
doc/misc/themes/run.default Executable file
View file

@ -0,0 +1,24 @@
#!/bin/bash
cat <<EOF >x
data.location=.
confirmation=off
detection=off
_forcecolor=on
default.height=24
verbose=off
EOF
echo "--- DEFAULT -----------------------------------------------------"
echo '$ task color legend'
task rc:x color legend
echo '$ task list'
task rc:x list
echo '$ task summary'
task rc:x summary
echo '$ task ghistory'
task rc:x ghistory
echo '$ task calendar'
task rc:x calendar
echo '$ task burndown.daily'
task rc:x burndown.daily

View file

@ -14,6 +14,8 @@ include $theme
EOF EOF
echo "--- $theme -----------------------------------------------------" echo "--- $theme -----------------------------------------------------"
echo '$ task color legend'
task rc:x color legend
echo '$ task list' echo '$ task list'
task rc:x list task rc:x list
echo '$ task summary' echo '$ task summary'

View file

@ -13,6 +13,8 @@ include $theme
EOF EOF
echo "--- $theme -----------------------------------------------------" echo "--- $theme -----------------------------------------------------"
echo '$ task color legend'
task rc:x color legend
echo '$ task list' echo '$ task list'
task rc:x list task rc:x list
echo '$ task summary' echo '$ task summary'

View file

@ -13,6 +13,8 @@ include $theme
EOF EOF
echo "--- $theme -----------------------------------------------------" echo "--- $theme -----------------------------------------------------"
echo '$ task color legend'
task rc:x color legend
echo '$ task list' echo '$ task list'
task rc:x list task rc:x list
echo '$ task summary' echo '$ task summary'

View file

@ -33,15 +33,15 @@ color.alternate=
color.header=yellow color.header=yellow
color.footnote=yellow color.footnote=yellow
color.warning=bold red color.warning=bold red
color.error=yellow color.error=white on red
color.debug=yellow color.debug=blue
# Task state # Task state
color.completed=green on white color.completed=
color.deleted=red on white color.deleted=
color.active=black on bright green color.active=black on bright green
color.recurring=magenta color.recurring=magenta
color.scheduled=on green color.scheduled=white on green
color.until= color.until=
color.blocked=black on white color.blocked=black on white
color.blocking=black on bright white color.blocking=black on bright white

View file

@ -29,16 +29,16 @@ rule.precedence.color=deleted,completed,active,keyword.,tag.,uda.,project.,overd
# General decoration # General decoration
color.label= color.label=
color.label.sort= color.label.sort=
color.alternate=on gray1 color.alternate=on gray2
color.header=color3 color.header=color3
color.footnote=color3 color.footnote=color3
color.warning=bold red color.warning=bold red
color.error=color3 color.error=white on red
color.debug=color3 color.debug=color4
# Task state # Task state
color.completed=rgb010 on white color.completed=
color.deleted=rgb100 on white color.deleted=
color.active=rgb555 on rgb410 color.active=rgb555 on rgb410
color.recurring=rgb013 color.recurring=rgb013
color.scheduled=on rgb001 color.scheduled=on rgb001

View file

@ -29,19 +29,19 @@ rule.precedence.color=deleted,completed,active,keyword.,tag.,uda.,project.,overd
# General decoration # General decoration
color.label= color.label=
color.label.sort= color.label.sort=
color.alternate=on gray1 color.alternate=on gray2
color.header=rgb013 color.header=rgb013
color.footnote=rgb013 color.footnote=rgb013
color.warning=bold red color.warning=bold red
color.error=rgb013 color.error=white on red
color.debug=rgb013 color.debug=rgb013
# Task state # Task state
color.completed=rgb001 on white color.completed=
color.deleted=rgb100 on white color.deleted=
color.active=rgb045 on rgb015 color.active=rgb045 on rgb015
color.recurring=rgb115 color.recurring=rgb115
color.scheduled=on rgb011 color.scheduled=on rgb012
color.until= color.until=
color.blocked=white on rgb001 color.blocked=white on rgb001
color.blocking=white on rgb002 color.blocking=white on rgb002
@ -76,8 +76,8 @@ color.history.delete=color0 on rgb035
color.history.done=color0 on rgb025 color.history.done=color0 on rgb025
# Report: summary # Report: summary
color.summary.background=white on color0 color.summary.background=on rgb001
color.summary.bar=white on rgb003 color.summary.bar=on rgb114
# Command: calendar # Command: calendar
color.calendar.due.today=color0 on color252 color.calendar.due.today=color0 on color252

View file

@ -29,16 +29,16 @@ rule.precedence.color=deleted,completed,active,keyword.,tag.,uda.,project.,overd
# General decoration # General decoration
color.label= color.label=
color.label.sort= color.label.sort=
color.alternate=on gray1 color.alternate=on gray2
color.header=color0 on gray11 color.header=color0 on gray11
color.footnote=on gray5 color.footnote=on gray5
color.warning=bold red color.warning=bold red
color.error=red on white color.error=white on red
color.debug=black on white color.debug=blue
# Task state # Task state
color.completed=black on white color.completed=
color.deleted=black on white color.deleted=
color.active=black on gray18 color.active=black on gray18
color.recurring= color.recurring=
color.scheduled=on gray8 color.scheduled=on gray8
@ -61,7 +61,7 @@ color.tag.none=
color.tagged= color.tagged=
# Due # Due
color.due=on gray2 color.due=on gray3
color.due.today=on gray4 color.due.today=on gray4
color.overdue=on gray6 color.overdue=on gray6
@ -76,12 +76,12 @@ color.history.delete=black on gray10
color.history.done=gray5 on gray23 color.history.done=gray5 on gray23
# Report: summary # Report: summary
color.summary.bar=on gray15 color.summary.bar=on gray12
color.summary.background=on black color.summary.background=on gray5
# Command: calendar # Command: calendar
color.calendar.due=on gray8 color.calendar.due=on gray8
color.calendar.due.today=on gray15 color.calendar.due.today=black on gray15
color.calendar.holiday=black on gray20 color.calendar.holiday=black on gray20
color.calendar.overdue=gray2 on gray10 color.calendar.overdue=gray2 on gray10
color.calendar.today=bold white color.calendar.today=bold white
@ -89,7 +89,7 @@ color.calendar.weekend=on gray2
color.calendar.weeknumber=gray6 color.calendar.weeknumber=gray6
# Command: sync # Command: sync
color.sync.add=gray15 on gray5 color.sync.added=gray15 on gray5
color.sync.changed=black on gray10 color.sync.changed=black on gray10
color.sync.rejected=gray5 on gray23 color.sync.rejected=gray5 on gray23

View file

@ -29,12 +29,12 @@ rule.precedence.color=deleted,completed,active,keyword.,tag.,uda.,project.,overd
# General decoration # General decoration
color.label= color.label=
color.label.sort= color.label.sort=
color.alternate=on gray0 color.alternate=on gray2
color.header=gray10 color.header=gray10
color.footnote=gray10 color.footnote=gray10
color.warning= color.warning=
color.error=rgb500 color.error=white on red
color.debug=rgb500 color.debug=blue
# Task state # Task state
color.completed= color.completed=
@ -66,18 +66,18 @@ color.due.today=color0 on rgb024
color.overdue=color0 on rgb035 color.overdue=color0 on rgb035
# Report: burndown # Report: burndown
color.burndown.pending=on gray9 color.burndown.pending=white on gray9
color.burndown.started=on gray16 color.burndown.started=black on gray16
color.burndown.done=on rgb013 color.burndown.done=white on rgb013
# Report: history # Report: history
color.history.add=on gray9 color.history.add=white on gray6
color.history.delete=black on gray23 color.history.delete=black on gray18
color.history.done=black on rgb013 color.history.done=black on rgb024
# Report: summary # Report: summary
color.summary.bar=on rgb012 color.summary.bar=on rgb012
color.summary.background=on color0 color.summary.background=on gray2
# Command: calendar # Command: calendar
color.calendar.due=color0 on gray10 color.calendar.due=color0 on gray10
@ -94,6 +94,6 @@ color.sync.changed=gray15
color.sync.rejected=gray23 color.sync.rejected=gray23
# Command: undo # Command: undo
color.undo.before=green color.undo.before=rgb013
color.undo.after=red color.undo.after=rgb035

View file

@ -29,19 +29,19 @@ rule.precedence.color=deleted,completed,active,keyword.,tag.,uda.,project.,overd
# General decoration # General decoration
color.label= color.label=
color.label.sort= color.label.sort=
color.alternate=on gray1 color.alternate=on gray2
color.header=rgb031 color.header=rgb031
color.footnote=rgb031 color.footnote=rgb031
color.warning=bold red color.warning=rgb020
color.error=rgb031 color.error=white on red
color.debug=rgb031 color.debug=blue
# Task state # Task state
color.completed=rgb020 on white color.completed=
color.deleted=rgb200 on white color.deleted=
color.active=rgb050 on rgb010 color.active=rgb050 on rgb010
color.recurring=rgb151 color.recurring=rgb151
color.scheduled=on rgb011 color.scheduled=black on rgb031
color.until= color.until=
color.blocked=white on rgb010 color.blocked=white on rgb010
color.blocking=white on rgb020 color.blocking=white on rgb020
@ -76,7 +76,7 @@ color.history.delete=color0 on rgb050
color.history.done=color0 on rgb030 color.history.done=color0 on rgb030
# Report: summary # Report: summary
color.summary.background=white on color0 color.summary.background=white on gray3
color.summary.bar=white on rgb030 color.summary.bar=white on rgb030
# Command: calendar # Command: calendar
@ -95,4 +95,4 @@ color.sync.rejected=rgb010
# Command: undo # Command: undo
color.undo.after=rgb053 color.undo.after=rgb053
color.undo.before=rgb031 color.undo.before=rgb021

View file

@ -29,19 +29,19 @@ rule.precedence.color=deleted,completed,active,keyword.,tag.,uda.,project.,overd
# General decoration # General decoration
color.label= color.label=
color.label.sort= color.label.sort=
color.alternate=on gray1 color.alternate=on gray2
color.header=rgb100 color.header=rgb100
color.footnote=rgb100 color.footnote=rgb100
color.warning=bold red color.warning=red
color.error=rgb100 color.error=white on red
color.debug=rgb100 color.debug=blue
# Task state # Task state
color.completed=rgb020 on white color.completed=
color.deleted=rgb200 on white color.deleted=
color.active=rgb500 on rgb100 color.active=rgb500 on rgb100
color.recurring=rgb511 color.recurring=rgb511
color.scheduled=on rgb201 color.scheduled=white on rgb311
color.until= color.until=
color.blocked=white on rgb100 color.blocked=white on rgb100
color.blocking=white on rgb200 color.blocking=white on rgb200
@ -56,7 +56,7 @@ color.pri.M=rgb400
color.pri.none= color.pri.none=
# Tags # Tags
color.tag.next=rgb440 color.tag.next=rgb511
color.tag.none= color.tag.none=
color.tagged=color246 color.tagged=color246
@ -94,6 +94,6 @@ color.sync.changed=rgb411
color.sync.rejected=rgb200 color.sync.rejected=rgb200
# Command: undo # Command: undo
color.undo.after=rgb503 color.undo.after=rgb511
color.undo.before=rgb301 color.undo.before=rgb200

View file

@ -33,15 +33,15 @@ color.alternate=on gray2
color.header=rgb013 color.header=rgb013
color.footnote=rgb013 color.footnote=rgb013
color.warning= color.warning=
color.error=rgb013 color.error=white on red
color.debug=rgb013 color.debug=blue
# Task state # Task state
color.completed= color.completed=
color.deleted= color.deleted=
color.active=rgb445 on rgb213 color.active=rgb445 on rgb213
color.recurring=rgb115 color.recurring=rgb115
color.scheduled= color.scheduled=white on rgb113
color.until= color.until=
color.blocked=white on rgb101 color.blocked=white on rgb101
color.blocking=white on rgb202 color.blocking=white on rgb202
@ -61,9 +61,9 @@ color.tag.none=
color.tagged=rgb334 color.tagged=rgb334
# Due # Due
color.due=rgb055 color.due=rgb015
color.due.today=rgb533 color.due.today=rgb125
color.overdue=color9 color.overdue=color5
# Report: burndown # Report: burndown
color.burndown.pending=on rgb103 color.burndown.pending=on rgb103
@ -76,14 +76,14 @@ color.history.done=color0 on rgb205
color.history.delete=color0 on rgb305 color.history.delete=color0 on rgb305
# Report: summary # Report: summary
color.summary.bar=white on rgb103 color.summary.bar=white on rgb104
color.summary.background=white on color0 color.summary.background=white on rgb001
# Command: calendar # Command: calendar
color.calendar.due=color0 on rgb325 color.calendar.due=color0 on rgb325
color.calendar.due.today=color0 on rgb404 color.calendar.due.today=color0 on rgb404
color.calendar.holiday=color15 on rgb022 color.calendar.holiday=color15 on rgb102
color.calendar.overdue=color0 on color9 color.calendar.overdue=color0 on color5
color.calendar.today=color15 on rgb103 color.calendar.today=color15 on rgb103
color.calendar.weekend=gray12 on gray3 color.calendar.weekend=gray12 on gray3
color.calendar.weeknumber=rgb104 color.calendar.weeknumber=rgb104

View file

@ -33,15 +33,15 @@ color.alternate=on gray2
color.header=rgb031 color.header=rgb031
color.footnote=rgb031 color.footnote=rgb031
color.warning= color.warning=
color.error=rgb031 color.error=white on red
color.debug=rgb031 color.debug=blue
# Task state # Task state
color.completed= color.completed=
color.deleted= color.deleted=
color.active=rgb451 on rgb310 color.active=rgb451 on rgb320
color.recurring=rgb343 color.recurring=rgb343
color.scheduled= color.scheduled=black on rgb441
color.until= color.until=
color.blocked=white on rgb110 color.blocked=white on rgb110
color.blocking=white on rgb220 color.blocking=white on rgb220
@ -61,9 +61,9 @@ color.tag.none=
color.tagged=rgb342 color.tagged=rgb342
# Due # Due
color.due=rgb420 color.due=rgb440
color.due.today=rgb410 color.due.today=rgb430
color.overdue=rgb400 color.overdue=rgb420
# Report: burndown # Report: burndown
color.burndown.pending=on rgb110 color.burndown.pending=on rgb110
@ -71,19 +71,19 @@ color.burndown.started=on rgb430
color.burndown.done=on gray4 color.burndown.done=on gray4
# Report: history # Report: history
color.history.add=color0 on rgb010 color.history.add=color0 on rgb110
color.history.done=color0 on rgb030 color.history.done=color0 on rgb430
color.history.delete=color0 on rgb050 color.history.delete=white on gray4
# Report: summary # Report: summary
color.summary.bar=white on rgb030 color.summary.bar=white on rgb330
color.summary.background=white on color0 color.summary.background=white on rgb110
# Command: calendar # Command: calendar
color.calendar.due=color0 on rgb430 color.calendar.due=color0 on rgb440
color.calendar.due.today=color0 on rgb410 color.calendar.due.today=color0 on rgb430
color.calendar.holiday=rgb151 on rgb020 color.calendar.holiday=rgb151 on rgb020
color.calendar.overdue=color0 on rgb400 color.calendar.overdue=color0 on rgb420
color.calendar.today=color15 on rgb110 color.calendar.today=color15 on rgb110
color.calendar.weekend=on color235 color.calendar.weekend=on color235
color.calendar.weeknumber=rgb110 color.calendar.weeknumber=rgb110
@ -94,6 +94,6 @@ color.sync.changed=rgb430
color.sync.rejected=rgb110 color.sync.rejected=rgb110
# Command: undo # Command: undo
color.undo.before=rgb031 color.undo.before=rgb021
color.undo.after=rgb053 color.undo.after=rgb042

View file

@ -33,12 +33,12 @@ color.alternate=
color.header=bold white on bright black color.header=bold white on bright black
color.footnote=bold cyan on bright black color.footnote=bold cyan on bright black
color.warning=bold red color.warning=bold red
color.error=red on white color.error=white on red
color.debug=white on black color.debug=blue
# Task state # Task state
color.completed=green on black color.completed=
color.deleted=red on black color.deleted=
color.active=bold yellow on bright black color.active=bold yellow on bright black
color.recurring= color.recurring=
color.scheduled=on bright cyan color.scheduled=on bright cyan
@ -63,17 +63,17 @@ color.tagged=
# Due # Due
color.due=on bright green color.due=on bright green
color.due.today=on bright yellow color.due.today=on bright yellow
color.overdue=on bright magenta color.overdue=on bright red
# Report: burndown # Report: burndown
color.burndown.pending=on bright green color.burndown.pending=on bright red
color.burndown.started=on bright yellow color.burndown.started=on bright yellow
color.burndown.done=on green color.burndown.done=on green
# Report: history # Report: history
color.history.add=blue on bright yellow color.history.add=black on bright red
color.history.done=green on bright green color.history.done=black on bright green
color.history.delete=black on red color.history.delete=black on yellow
# Report: summary # Report: summary
color.summary.bar=on bright green color.summary.bar=on bright green
@ -82,11 +82,11 @@ color.summary.background=on white
# Command: calendar # Command: calendar
color.calendar.due=on bright green color.calendar.due=on bright green
color.calendar.due.today=blue on bright yellow color.calendar.due.today=blue on bright yellow
color.calendar.holiday=yellow color.calendar.holiday=on yellow
color.calendar.overdue=on bright magenta color.calendar.overdue=on bright red
color.calendar.today=blue color.calendar.today=blue
color.calendar.weekend=on white color.calendar.weekend=on white
color.calendar.weeknumber=white on bright black color.calendar.weeknumber=blue
# Command: sync # Command: sync
color.sync.added=green color.sync.added=green

View file

@ -33,13 +33,13 @@ color.alternate=on gray22
color.header=color15 on gray8 color.header=color15 on gray8
color.footnote=on gray18 color.footnote=on gray18
color.warning=color9 color.warning=color9
color.error=red on white color.error=white on red
color.debug=color7 on color0 color.debug=rgb025
# Task state # Task state
color.completed=rgb353 on rgb000 color.completed=
color.deleted=rgb533 on rgb000 color.deleted=
color.active=rgb420 color.active=rgb510
color.recurring= color.recurring=
color.scheduled=on rgb345 color.scheduled=on rgb345
color.until= color.until=
@ -53,7 +53,7 @@ color.project.none=
color.pri.H=gray0 color.pri.H=gray0
color.pri.M=gray5 color.pri.M=gray5
color.pri.L=gray10 color.pri.L=gray10
color.pri.none=gray5 color.pri.none=
# Tags # Tags
color.tag.next=rgb420 color.tag.next=rgb420
@ -66,14 +66,14 @@ color.due.today=on rgb353
color.overdue=on rgb544 color.overdue=on rgb544
# Report: burndown # Report: burndown
color.burndown.pending=on rgb141 color.burndown.pending=on rgb411
color.burndown.started=on rgb440 color.burndown.started=on rgb550
color.burndown.done=on rgb151 color.burndown.done=on rgb151
# Report: history # Report: history
color.history.add=rgb005 on rgb440 color.history.add=color0 on rgb411
color.history.done=rgb020 on rgb343 color.history.done=color0 on rgb151
color.history.delete=rgb300 on rgb533 color.history.delete=color0 on rgb550
# Report: summary # Report: summary
color.summary.bar=on rgb141 color.summary.bar=on rgb141
@ -82,7 +82,7 @@ color.summary.background=on gray20
# Command: calendar # Command: calendar
color.calendar.due=on rgb343 color.calendar.due=on rgb343
color.calendar.due.today=on rgb353 color.calendar.due.today=on rgb353
color.calendar.holiday=rgb420 color.calendar.holiday=color0 on rgb530
color.calendar.overdue=on rgb533 color.calendar.overdue=on rgb533
color.calendar.today=rgb005 color.calendar.today=rgb005
color.calendar.weekend=on gray21 color.calendar.weekend=on gray21

View file

@ -83,14 +83,14 @@ color.due.today=color1
color.overdue=color5 color.overdue=color5
# Report: burndown # Report: burndown
color.burndown.done=color0 on color4 color.burndown.done=color0 on color6
color.burndown.pending=color0 on color1 color.burndown.pending=color0 on color1
color.burndown.started=color0 on color9 color.burndown.started=color0 on color3
# Report: history # Report: history
color.history.add=color0 on color1 color.history.add=color0 on color1
color.history.delete=color0 on color3 color.history.delete=color0 on color3
color.history.done=color0 on color10 color.history.done=color0 on color6
# Report: summary # Report: summary
color.summary.background=on color0 color.summary.background=on color0

View file

@ -46,7 +46,7 @@ rule.precedence.color=deleted,completed,active,keyword.,tag.,uda.,project.,overd
# General decoration # General decoration
color.label= color.label=
color.label.sort= color.label.sort=
color.alternate=on white #color7 (allows bold for alternate rows) color.alternate=on color7
color.header=color2 color.header=color2
color.footnote=color2 color.footnote=color2
color.warning= color.warning=
@ -56,20 +56,20 @@ color.debug=color3
# Task state # Task state
color.completed= color.completed=
color.deleted= color.deleted=
color.active=bold red #color9 color.active=color9
color.recurring=color4 color.recurring=color4
color.scheduled= color.scheduled=
color.until= color.until=
color.blocked=on color14 color.blocked=color0 on color14
color.blocking=on color14 color.blocking=color15 on color0
# Project # Project
color.project.none= color.project.none=
# Priority # Priority
color.pri.H=bold black #color0 color.pri.H=bold color0
color.pri.M=bold yellow #color11 color.pri.M=bold color11
color.pri.L=bold cyan #color14 color.pri.L=bold color14
color.pri.none= color.pri.none=
# Tags # Tags
@ -83,14 +83,14 @@ color.due.today=color1
color.overdue=color5 color.overdue=color5
# Report: burndown # Report: burndown
color.burndown.done=color0 on color4 color.burndown.done=color0 on color6
color.burndown.pending=color0 on color1 color.burndown.pending=color0 on color1
color.burndown.started=color0 on color9 color.burndown.started=color0 on color3
# Report: history # Report: history
color.history.add=color0 on color1 color.history.add=color0 on color1
color.history.delete=color0 on color3 color.history.delete=color0 on color3
color.history.done=color14 on color0 color.history.done=color0 on color6
# Report: summary # Report: summary
color.summary.background=on color7 color.summary.background=on color7

Binary file not shown.

Binary file not shown.

View file

@ -50,7 +50,7 @@
# #
################################################################################ ################################################################################
#the following variable is substituted for by ../../test/bash_completion.t #the following variable is substituted for by ../../test/bash_completion.t
taskcommand='task rc.verbose:nothing' taskcommand='task rc.verbose:nothing rc.confirmation:no'
_task_get_tags() { _task_get_tags() {
$taskcommand _tags $taskcommand _tags

View file

@ -529,9 +529,12 @@ void CLI::applyOverrides ()
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Extract all the FILTER-tagged items. // Extract all the FILTER-tagged items.
const std::string CLI::getFilter () const std::string CLI::getFilter (bool applyContext /* = true */)
{ {
// Handle context setting // Handle context setting
// Commands that don't want to respect current context should leverage
// the applyContext argument
if (applyContext)
addContextFilter (); addContextFilter ();
std::string filter = ""; std::string filter = "";

View file

@ -81,7 +81,7 @@ public:
void addRawFilter (const std::string& arg); void addRawFilter (const std::string& arg);
void analyze (bool parse = true, bool strict = false); void analyze (bool parse = true, bool strict = false);
void applyOverrides (); void applyOverrides ();
const std::string getFilter (); const std::string getFilter (bool applyContext = true);
const std::vector <std::string> getWords (); const std::vector <std::string> getWords ();
bool canonicalize (std::string&, const std::string&, const std::string&) const; bool canonicalize (std::string&, const std::string&, const std::string&) const;
std::string getBinary () const; std::string getBinary () const;

View file

@ -165,29 +165,29 @@ std::string Config::_defaults =
"\n" "\n"
"# Color controls.\n" "# Color controls.\n"
"color=on # Enable color\n" "color=on # Enable color\n"
#ifdef LINUX #if defined(LINUX) || defined(DARWIN)
"\n" "\n"
"rule.precedence.color=deleted,completed,active,keyword.,tag.,uda.,project.,overdue,scheduled,due.today,due,blocked,blocking,recurring,tagged,pri.\n" "rule.precedence.color=deleted,completed,active,keyword.,tag.,uda.,project.,overdue,scheduled,due.today,due,blocked,blocking,recurring,tagged,pri.\n"
"\n" "\n"
"# General decoration\n" "# General decoration\n"
"color.label=\n" "color.label=\n"
"color.label.sort=\n" "color.label.sort=\n"
"color.alternate=on gray1\n" "color.alternate=on gray2\n"
"color.header=color3\n" "color.header=color3\n"
"color.footnote=color3\n" "color.footnote=color3\n"
"color.warning=bold red\n" "color.warning=bold red\n"
"color.error=color3\n" "color.error=white on red\n"
"color.debug=color3\n" "color.debug=color4\n"
"\n" "\n"
"# Task state\n" "# Task state\n"
"color.completed=rgb010 on white\n" "color.completed=\n"
"color.deleted=rgb100 on white\n" "color.deleted=\n"
"color.active=rgb555 on rgb410\n" "color.active=rgb555 on rgb410\n"
"color.recurring=rgb013\n" "color.recurring=rgb013\n"
"color.scheduled=on rgb001\n" "color.scheduled=on rgb001\n"
"color.until=\n" "color.until=\n"
"color.blocked=white on color8\n" "color.blocked=white on color8\n"
"color.blocking=white on color15\n" "color.blocking=black on color15\n"
"\n" "\n"
"# Project\n" "# Project\n"
"color.project.none=\n" "color.project.none=\n"
@ -251,15 +251,15 @@ std::string Config::_defaults =
"color.header=yellow\n" "color.header=yellow\n"
"color.footnote=yellow\n" "color.footnote=yellow\n"
"color.warning=bold red\n" "color.warning=bold red\n"
"color.error=yellow\n" "color.error=white on red\n"
"color.debug=yellow\n" "color.debug=blue\n"
"\n" "\n"
"# Task state\n" "# Task state\n"
"color.completed=green on white\n" "color.completed=\n"
"color.deleted=red on white\n" "color.deleted=\n"
"color.active=black on bright green\n" "color.active=black on bright green\n"
"color.recurring=magenta\n" "color.recurring=magenta\n"
"color.scheduled=on green\n" "color.scheduled=white on green\n"
"color.until=\n" "color.until=\n"
"color.blocked=black on white\n" "color.blocked=black on white\n"
"color.blocking=black on bright white\n" "color.blocking=black on bright white\n"

View file

@ -67,7 +67,7 @@ Filter::~Filter ()
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Take an input set of tasks and filter into a subset. // Take an input set of tasks and filter into a subset.
void Filter::subset (const std::vector <Task>& input, std::vector <Task>& output) void Filter::subset (const std::vector <Task>& input, std::vector <Task>& output, bool applyContext /* = true */)
{ {
context.timer_filter.start (); context.timer_filter.start ();
_startCount = (int) input.size (); _startCount = (int) input.size ();
@ -75,7 +75,7 @@ void Filter::subset (const std::vector <Task>& input, std::vector <Task>& output
if (context.config.getInteger ("debug.parser") >= 1) if (context.config.getInteger ("debug.parser") >= 1)
context.debug (context.cli.dump ("Filter::subset")); context.debug (context.cli.dump ("Filter::subset"));
std::string filterExpr = context.cli.getFilter (); std::string filterExpr = context.cli.getFilter (applyContext);
if (filterExpr.length ()) if (filterExpr.length ())
{ {
Eval eval; Eval eval;
@ -111,7 +111,7 @@ void Filter::subset (const std::vector <Task>& input, std::vector <Task>& output
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Take the set of all tasks and filter into a subset. // Take the set of all tasks and filter into a subset.
void Filter::subset (std::vector <Task>& output) void Filter::subset (std::vector <Task>& output, bool applyContext /* = true */)
{ {
context.timer_filter.start (); context.timer_filter.start ();
@ -119,7 +119,7 @@ void Filter::subset (std::vector <Task>& output)
context.debug (context.cli.dump ("Filter::subset")); context.debug (context.cli.dump ("Filter::subset"));
bool shortcut = false; bool shortcut = false;
std::string filterExpr = context.cli.getFilter (); std::string filterExpr = context.cli.getFilter (applyContext);
if (filterExpr.length ()) if (filterExpr.length ())
{ {
context.timer_filter.stop (); context.timer_filter.stop ();

View file

@ -40,8 +40,8 @@ public:
Filter (); Filter ();
~Filter (); ~Filter ();
void subset (const std::vector <Task>&, std::vector <Task>&); void subset (const std::vector <Task>&, std::vector <Task>&, bool applyContext = true);
void subset (std::vector <Task>&); void subset (std::vector <Task>&, bool applyContext = true);
bool pendingOnly (); bool pendingOnly ();
void safety (); void safety ();

View file

@ -54,7 +54,7 @@ int CmdExport::execute (std::string& output)
// Apply filter. // Apply filter.
Filter filter; Filter filter;
std::vector <Task> filtered; std::vector <Task> filtered;
filter.subset (filtered); filter.subset (filtered, false);
// Obey 'limit:N'. // Obey 'limit:N'.
int rows = 0; int rows = 0;

View file

@ -135,7 +135,10 @@ CmdCompletionVersion::CmdCompletionVersion ()
int CmdCompletionVersion::execute (std::string& output) int CmdCompletionVersion::execute (std::string& output)
{ {
#ifdef HAVE_COMMIT #ifdef HAVE_COMMIT
output = COMMIT; output = std::string (VERSION)
+ std::string (" (")
+ std::string (COMMIT)
+ std::string (")");
#else #else
output = VERSION; output = VERSION;
#endif #endif

View file

@ -1,86 +0,0 @@
#! /usr/bin/env perl
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
use strict;
use warnings;
use Test::More tests => 5;
# Ensure environment has no influence.
delete $ENV{'TASKDATA'};
delete $ENV{'TASKRC'};
use File::Basename;
my $ut = basename ($0);
my $rc = $ut . '.rc';
# Create the rc file.
if (open my $fh, '>', $rc)
{
print $fh "data.location=.\n",
"default.command=\n";
close $fh;
}
# Get the version number from configure.ac
my $version = slurp ('../CMakeLists.txt');
# Test the usage command.
my $output = qx{../src/task rc:$rc 2>&1 >/dev/null};
like ($output, qr/You must specify a command or a task to modify./m, "$ut: missing command and ID");
# Test the version command.
$output = qx{../src/task rc:$rc version 2>&1};
like ($output, qr/task $version/, "$ut: version - task version number");
like ($output, qr/MIT\slicense/, "$ut: version - license");
like ($output, qr/http:\/\/taskwarrior\.org/, "$ut: version - url");
# Test the _version command.
$output = qx{../src/task rc:$rc _version 2>&1};
like ($output, qr/[a-f0-9]{7}/, "$ut: _version - task version number");
# Cleanup.
unlink $rc;
exit 0;
################################################################################
sub slurp
{
my ($file) = @_;
if (open my $fh, '<', $file)
{
while (<$fh>) {
if (/PROJECT_VERSION/) {
chomp;
s/^set \(PROJECT_VERSION "//;
s/"\).*$//;
close $fh;
return $_;
}
}
}
'';
}

View file

@ -1,72 +0,0 @@
#! /usr/bin/env perl
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
use strict;
use warnings;
use Test::More tests => 7;
# Ensure environment has no influence.
delete $ENV{'TASKDATA'};
delete $ENV{'TASKRC'};
use File::Basename;
my $ut = basename ($0);
my $rc = $ut . '.rc';
# Create the rc file.
if (open my $fh, '>', $rc)
{
print $fh "data.location=.\n",
"confirmation=off\n",
"color=off\n",
"verbose=nothing\n";
close $fh;
}
# Bug 1056: Project indentation in CmdSummary.
qx{../src/task rc:$rc add testing project:existingParent 2>&1 >/dev/null};
qx{../src/task rc:$rc add testing project:existingParent.child 2>&1 >/dev/null};
qx{../src/task rc:$rc add testing project:abstractParent.kid 2>&1 >/dev/null};
qx{../src/task rc:$rc add testing project:.myProject 2>&1 >/dev/null};
qx{../src/task rc:$rc add testing project:myProject. 2>&1 >/dev/null};
qx{../src/task rc:$rc add testing project:.myProject. 2>&1 >/dev/null};
my $output = qx{../src/task rc:$rc summary 2>&1};
my @lines = split ('\n',$output);
like ($lines[0], qr/^\.myProject\s/, "$ut: '.myProject' not indented");
like ($lines[1], qr/^\.myProject\.\s/, "$ut: '.myProject.' not indented");
like ($lines[2], qr/^abstractParent\s*$/, "$ut: 'abstractParent' not indented, no data");
like ($lines[3], qr/^\s\skid\s+\d/, "$ut: ' kid' indented, without parent, with data");
like ($lines[4], qr/^existingParent\s+\d/, "$ut: 'existingParent' not indented, with data");
like ($lines[5], qr/^\s\schild\s+\d/, "$ut: ' child' indented, without parent, with data");
like ($lines[6], qr/^myProject\.\s+\d/, "$ut: 'myProject.' not indented, with data");
# Cleanup.
unlink qw(pending.data completed.data undo.data backlog.data), $rc;
exit 0;

View file

@ -1,72 +1,74 @@
#! /usr/bin/env perl #!/usr/bin/env python2.7
################################################################################ # -*- coding: utf-8 -*-
## ###############################################################################
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. #
## # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
## Permission is hereby granted, free of charge, to any person obtaining a copy #
## of this software and associated documentation files (the "Software"), to deal # Permission is hereby granted, free of charge, to any person obtaining a copy
## in the Software without restriction, including without limitation the rights # of this software and associated documentation files (the "Software"), to deal
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # in the Software without restriction, including without limitation the rights
## copies of the Software, and to permit persons to whom the Software is # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## furnished to do so, subject to the following conditions: # copies of the Software, and to permit persons to whom the Software is
## # furnished to do so, subject to the following conditions:
## The above copyright notice and this permission notice shall be included #
## in all copies or substantial portions of the Software. # The above copyright notice and this permission notice shall be included
## # in all copies or substantial portions of the Software.
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS #
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## SOFTWARE. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## # SOFTWARE.
## http://www.opensource.org/licenses/mit-license.php #
## # http://www.opensource.org/licenses/mit-license.php
################################################################################ #
###############################################################################
use strict; import sys
use warnings; import os
use Test::More tests => 6; import re
import unittest
# Ensure python finds the local simpletap module
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
# Ensure environment has no influence. from basetest import Task, TestCase
delete $ENV{'TASKDATA'};
delete $ENV{'TASKRC'};
use File::Basename;
my $ut = basename ($0);
my $rc = $ut . '.rc';
# Create the rc file. class TestBug1063(TestCase):
if (open my $fh, '>', $rc) def setUp(self):
{ self.t = Task()
print $fh "data.location=.\n",
"confirmation=off\n",
"uda.foo.type=numeric\n",
"uda.foo.label=Foo\n",
"report.bar.columns=foo,description\n",
"report.bar.description=Bar\n",
"report.bar.labels=Foo,Desc\n",
"report.bar.sort=foo-\n";
close $fh;
}
# Bug 1063 - Numeric UDA fields are not sortable. self.t.config("uda.foo.type", "numeric")
qx{../src/task rc:$rc add four foo:4 2>&1}; self.t.config("uda.foo.label", "Foo")
ok ($? == 0, "$ut: add four"); self.t.config("report.bar.columns", "foo,description")
qx{../src/task rc:$rc add one foo:1 2>&1}; self.t.config("report.bar.description", "Bar")
ok ($? == 0, "$ut: add one"); self.t.config("report.bar.labels", "Foo,Desc")
qx{../src/task rc:$rc add three foo:3 2>&1}; self.t.config("report.bar.sort", "foo-")
ok ($? == 0, "$ut: add three");
qx{../src/task rc:$rc add two foo:2 2>&1};
ok ($? == 0, "$ut: add two");
my $output = qx{../src/task rc:$rc bar 2>&1}; def test_sortable_uda(self):
like ($output, qr/4.+3.+2.+1/ms, "$ut: Default descending sort correct"); """numeric UDA fields are sortable
$output = qx{../src/task rc:$rc bar rc.report.bar.sort=foo+ 2>&1}; Reported as bug 1063
like ($output, qr/1.+2.+3.+4/ms, "$ut: Default ascending sort correct"); """
## Cleanup. self.t(("add", "four", "foo:4"))
unlink qw(pending.data completed.data undo.data backlog.data), $rc; self.t(("add", "one", "foo:1"))
exit 0; self.t(("add", "three", "foo:3"))
self.t(("add", "two", "foo:2"))
code, out, err = self.t(("bar",))
expected = re.compile("4.+3.+2.+1", re.DOTALL) # dot matches \n too
self.assertRegexpMatches(out, expected)
code, out, err = self.t(("bar", "rc.report.bar.sort=foo+"))
expected = re.compile("1.+2.+3.+4", re.DOTALL) # dot matches \n too
self.assertRegexpMatches(out, expected)
if __name__ == "__main__":
from simpletap import TAPTestRunner
unittest.main(testRunner=TAPTestRunner())
# vim: ai sts=4 et sw=4

View file

@ -1,78 +0,0 @@
#! /usr/bin/env perl
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
use strict;
use warnings;
use Test::More tests => 12;
# Ensure environment has no influence.
delete $ENV{'TASKDATA'};
delete $ENV{'TASKRC'};
use File::Basename;
my $ut = basename ($0);
my $rc = $ut . '.rc';
# Create the rc file.
if (open my $fh, '>', $rc)
{
print $fh "data.location=.\n";
print $fh "alias.xyzzyx=status:waiting\n";
print $fh "imnotrecognized=kai\n";
close $fh;
}
# Bug 1065 - CmdShow should not display the differ message if no non-default in matched elements.
my $output = qx{../src/task rc:$rc show alias 2>&1};
ok ($? == 0, "$ut: Exit status check");
like ($output, qr/Some of your .taskrc variables differ from the default values./, "$ut: Message is shown when non-default matches in pattern");
$output = qx{../src/task rc:$rc show 2>&1};
ok ($? == 0, "$ut: Exit status check");
like ($output, qr/Some of your .taskrc variables differ from the default values./, "$ut: Message is shown when non-default matches in all");
$output = qx{../src/task rc:$rc show report.overdue 2>&1};
ok ($? == 0, "$ut: Exit status check");
unlike ($output, qr/Some of your .taskrc variables differ/, "$ut: Message is not shown when no non-default matches in pattern");
# Bug 1065 - CmdShow should not display the unrecognized message if no non-default in matched elements.
$output = qx{../src/task rc:$rc show notrecog 2>&1};
ok ($? == 0, "$ut: Exit status check");
like ($output, qr/Your .taskrc file contains these unrecognized variables:/, "$ut: Message is shown when unrecognized matches in pattern");
$output = qx{../src/task rc:$rc show 2>&1};
ok ($? == 0, "$ut: Exit status check");
like ($output, qr/Your .taskrc file contains these unrecognized variables:/, "$ut: Message is shown when unrecognized matches in all");
$output = qx{../src/task rc:$rc show report.overdue 2>&1};
ok ($? == 0, "$ut: Exit status check");
unlike ($output, qr/unrecognized variables/, "$ut: Message is not shown when no non-default matches in pattern");
# Cleanup.
unlink qw(pending.data completed.data undo.data backlog.data), $rc;
exit 0;

View file

@ -1,60 +0,0 @@
#! /usr/bin/env perl
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
use strict;
use warnings;
use Test::More tests => 2;
# Ensure environment has no influence.
delete $ENV{'TASKDATA'};
delete $ENV{'TASKRC'};
use File::Basename;
my $ut = basename ($0);
my $rc = $ut . '.rc';
# Create the rc file.
if (open my $fh, '>', $rc)
{
print $fh "data.location=.\n",
"confirmation=off\n";
close $fh;
}
# Bug 1110: reports print "Completed" but "Completed" != "completed"
qx{../src/task rc:$rc add ToBeCompleted 2>&1};
qx{../src/task rc:$rc 1 done 2>&1};
my $output = qx{../src/task all status:Completed rc:$rc 2>&1};
like ($output, qr/ToBeCompleted/, "$ut: status:Completed returns Completed tasks");
$output = qx{../src/task all status:completed rc:$rc 2>&1};
like ($output, qr/ToBeCompleted/, "$ut: status:completed returns completed tasks");
# Cleanup.
unlink qw(pending.data completed.data undo.data backlog.data), $rc;
exit 0;

95
test/custom.config.t Executable file
View file

@ -0,0 +1,95 @@
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
###############################################################################
#
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://www.opensource.org/licenses/mit-license.php
#
###############################################################################
import sys
import os
import unittest
# Ensure python finds the local simpletap module
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from basetest import Task, TestCase, Taskd, ServerTestCase
class TestCustomConfig(TestCase):
def setUp(self):
self.t = Task()
self.t.config("alias.xyzzyx", "status:waiting")
self.t.config("imnotrecognized", "kai")
self.DIFFER_MSG = ("Some of your .taskrc variables differ from the "
"default values.")
self.NOT_RECOG_MSG = ("Your .taskrc file contains these unrecognized "
"variables:")
def test_show_alias(self):
"""task show <filter> - warns when non-default values are matched
Reported in bug 1065
"""
code, out, err = self.t(("show", "alias"))
self.assertIn(self.DIFFER_MSG, out)
self.assertNotIn(self.NOT_RECOG_MSG, out)
def test_show(self):
"""task show - warns when non-default values are matched
Reported in bug 1065
"""
code, out, err = self.t(("show",))
self.assertIn(self.DIFFER_MSG, out)
self.assertIn(self.NOT_RECOG_MSG, out)
def test_show_report_overdue(self):
"""task show <filter> - no warn when no non-default values are matched
Reported in bug 1065
"""
code, out, err = self.t(("show", "report.overdue"))
self.assertNotIn(self.DIFFER_MSG, out)
self.assertNotIn(self.NOT_RECOG_MSG, out)
def test_show_notrecog(self):
"""task show <filter> - warns when unrecognized values are matched
Reported in bug 1065
"""
code, out, err = self.t(("show", "notrecog"))
self.assertNotIn(self.DIFFER_MSG, out)
self.assertIn(self.NOT_RECOG_MSG, out)
if __name__ == "__main__":
from simpletap import TAPTestRunner
unittest.main(testRunner=TAPTestRunner())
# vim: ai sts=4 et sw=4

View file

@ -88,7 +88,7 @@ class TestFilterPrefix(TestCase):
self.assertIn('seven', out) self.assertIn('seven', out)
self.assertIn('eight', out) self.assertIn('eight', out)
def test_list_project_startwsith_bar(self): def test_list_project_startswith_bar(self):
"""Filter on project name start.""" """Filter on project name start."""
code, out, err = self.t(('list', 'project.startswith:bar')) code, out, err = self.t(('list', 'project.startswith:bar'))
self.assertNotIn('one', out) self.assertNotIn('one', out)
@ -124,7 +124,7 @@ class TestFilterPrefix(TestCase):
self.assertNotIn('seven', out) self.assertNotIn('seven', out)
self.assertNotIn('eight', out) self.assertNotIn('eight', out)
def test_list_descrtiption_has_foo(self): def test_list_description_has_foo(self):
"""Filter on description pattern.""" """Filter on description pattern."""
code, out, err = self.t(('list', 'description.has:foo')) code, out, err = self.t(('list', 'description.has:foo'))
self.assertIn('one', out) self.assertIn('one', out)

View file

@ -1,281 +1,375 @@
#! /usr/bin/env perl #!/usr/bin/env python2.7
################################################################################ # -*- coding: utf-8 -*-
## ###############################################################################
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. #
## # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
## Permission is hereby granted, free of charge, to any person obtaining a copy #
## of this software and associated documentation files (the "Software"), to deal # Permission is hereby granted, free of charge, to any person obtaining a copy
## in the Software without restriction, including without limitation the rights # of this software and associated documentation files (the "Software"), to deal
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # in the Software without restriction, including without limitation the rights
## copies of the Software, and to permit persons to whom the Software is # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## furnished to do so, subject to the following conditions: # copies of the Software, and to permit persons to whom the Software is
## # furnished to do so, subject to the following conditions:
## The above copyright notice and this permission notice shall be included #
## in all copies or substantial portions of the Software. # The above copyright notice and this permission notice shall be included
## # in all copies or substantial portions of the Software.
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS #
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## SOFTWARE. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## # SOFTWARE.
## http://www.opensource.org/licenses/mit-license.php #
## # http://www.opensource.org/licenses/mit-license.php
################################################################################ #
###############################################################################
use strict; import sys
use warnings; import os
use Test::More tests => 161; import unittest
# Ensure python finds the local simpletap module
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
# Ensure environment has no influence. from basetest import Task, TestCase
delete $ENV{'TASKDATA'};
delete $ENV{'TASKRC'};
# Create the rc file.
if (open my $fh, '>', 'filter.rc')
{
print $fh "data.location=.\n";
close $fh;
}
# Test the filters. class TestFilter(TestCase):
qx{../src/task rc:filter.rc add project:A priority:H +tag one foo 2>&1}; def setUp(self):
qx{../src/task rc:filter.rc add project:A priority:H two 2>&1}; self.t = Task()
qx{../src/task rc:filter.rc add project:A three 2>&1};
qx{../src/task rc:filter.rc add priority:H four 2>&1};
qx{../src/task rc:filter.rc add +tag five 2>&1};
qx{../src/task rc:filter.rc add six foo 2>&1};
qx{../src/task rc:filter.rc add priority:L seven bar foo 2>&1};
my $output = qx{../src/task rc:filter.rc list 2>&1}; self.t(("add", "project:A", "prio:H", "+tag", "one", "foo"))
like ($output, qr/one/, 'a1'); self.t(("add", "project:A", "prio:H", "two"))
like ($output, qr/two/, 'a2'); self.t(("add", "project:A", "three"))
like ($output, qr/three/, 'a3'); self.t(("add", "prio:H", "four"))
like ($output, qr/four/, 'a4'); self.t(("add", "+tag", "five"))
like ($output, qr/five/, 'a5'); self.t(("add", "six", "foo"))
like ($output, qr/six/, 'a6'); self.t(("add", "prio:L", "seven", "bar", "foo"))
like ($output, qr/seven/, 'a7');
$output = qx{../src/task rc:filter.rc list project:A 2>&1}; def test_list(self):
like ($output, qr/one/, 'b1'); """filter - list"""
like ($output, qr/two/, 'b2'); code, out, err = self.t(("list",))
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{../src/task rc:filter.rc list priority:H 2>&1}; self.assertIn("one", out)
like ($output, qr/one/, 'c1'); self.assertIn("two", out)
like ($output, qr/two/, 'c2'); self.assertIn("three", out)
unlike ($output, qr/three/, 'c3'); self.assertIn("four", out)
like ($output, qr/four/, 'c4'); self.assertIn("five", out)
unlike ($output, qr/five/, 'c5'); self.assertIn("six", out)
unlike ($output, qr/six/, 'c6'); self.assertIn("seven", out)
unlike ($output, qr/seven/, 'c7');
$output = qx{../src/task rc:filter.rc list priority: 2>&1}; def test_list_projectA(self):
unlike ($output, qr/one/, 'd1'); """filter - list project:A"""
unlike ($output, qr/two/, 'd2'); code, out, err = self.t(("list", "project:A"))
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{../src/task rc:filter.rc list /foo/ 2>&1}; self.assertIn("one", out)
like ($output, qr/one/, 'e1'); self.assertIn("two", out)
unlike ($output, qr/two/, 'e2'); self.assertIn("three", out)
unlike ($output, qr/three/, 'e3'); self.assertNotIn("four", out)
unlike ($output, qr/four/, 'e4'); self.assertNotIn("five", out)
unlike ($output, qr/five/, 'e5'); self.assertNotIn("six", out)
like ($output, qr/six/, 'e6'); self.assertNotIn("seven", out)
like ($output, qr/seven/, 'e7');
$output = qx{../src/task rc:filter.rc list /foo/ /bar/ 2>&1}; def test_list_priorityH(self):
unlike ($output, qr/one/, 'f1'); """filter - list priority:H"""
unlike ($output, qr/two/, 'f2'); code, out, err = self.t(("list", "priority:H"))
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{../src/task rc:filter.rc list +tag 2>&1}; self.assertIn("one", out)
like ($output, qr/one/, 'g1'); self.assertIn("two", out)
unlike ($output, qr/two/, 'g2'); self.assertNotIn("three", out)
unlike ($output, qr/three/, 'g3'); self.assertIn("four", out)
unlike ($output, qr/four/, 'g4'); self.assertNotIn("five", out)
like ($output, qr/five/, 'g5'); self.assertNotIn("six", out)
unlike ($output, qr/six/, 'g6'); self.assertNotIn("seven", out)
unlike ($output, qr/seven/, 'g7');
$output = qx{../src/task rc:filter.rc list -tag 2>&1}; def test_list_priority(self):
unlike ($output, qr/one/, 'h1'); """filter - list priority:"""
like ($output, qr/two/, 'h2'); code, out, err = self.t(("list", "priority:"))
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{../src/task rc:filter.rc list -missing 2>&1}; self.assertNotIn("one", out)
like ($output, qr/one/, 'i1'); self.assertNotIn("two", out)
like ($output, qr/two/, 'i2'); self.assertIn("three", out)
like ($output, qr/three/, 'i3'); self.assertNotIn("four", out)
like ($output, qr/four/, 'i4'); self.assertIn("five", out)
like ($output, qr/five/, 'i5'); self.assertIn("six", out)
like ($output, qr/six/, 'i6'); self.assertNotIn("seven", out)
like ($output, qr/seven/, 'i7');
$output = qx{../src/task rc:filter.rc list +tag -tag 2>&1}; def test_list_substring(self):
unlike ($output, qr/one/, 'j1'); """filter - list /foo/"""
unlike ($output, qr/two/, 'j2'); code, out, err = self.t(("list", "/foo/"))
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{../src/task rc:filter.rc list project:A priority:H 2>&1}; self.assertIn("one", out)
like ($output, qr/one/, 'k1'); self.assertNotIn("two", out)
like ($output, qr/two/, 'k2'); self.assertNotIn("three", out)
unlike ($output, qr/three/, 'k3'); self.assertNotIn("four", out)
unlike ($output, qr/four/, 'k4'); self.assertNotIn("five", out)
unlike ($output, qr/five/, 'k5'); self.assertIn("six", out)
unlike ($output, qr/six/, 'k6'); self.assertIn("seven", out)
unlike ($output, qr/seven/, 'k7');
$output = qx{../src/task rc:filter.rc list project:A priority: 2>&1}; def test_list_double_substring(self):
unlike ($output, qr/one/, 'l1'); """filter - list /foo/ /bar/"""
unlike ($output, qr/two/, 'l2'); code, out, err = self.t(("list", "/foo/", "/bar/"))
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{../src/task rc:filter.rc list project:A /foo/ 2>&1}; self.assertNotIn("one", out)
like ($output, qr/one/, 'm1'); self.assertNotIn("two", out)
unlike ($output, qr/two/, 'm2'); self.assertNotIn("three", out)
unlike ($output, qr/three/, 'm3'); self.assertNotIn("four", out)
unlike ($output, qr/four/, 'm4'); self.assertNotIn("five", out)
unlike ($output, qr/five/, 'm5'); self.assertNotIn("six", out)
unlike ($output, qr/six/, 'm6'); self.assertIn("seven", out)
unlike ($output, qr/seven/, 'm7');
$output = qx{../src/task rc:filter.rc list project:A +tag 2>&1}; def test_list_include_tag(self):
like ($output, qr/one/, 'n1'); """filter - list +tag"""
unlike ($output, qr/two/, 'n2'); code, out, err = self.t(("list", "+tag"))
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{../src/task rc:filter.rc list project:A priority:H /foo/ 2>&1}; self.assertIn("one", out)
like ($output, qr/one/, 'o1'); self.assertNotIn("two", out)
unlike ($output, qr/two/, 'o2'); self.assertNotIn("three", out)
unlike ($output, qr/three/, 'o3'); self.assertNotIn("four", out)
unlike ($output, qr/four/, 'o4'); self.assertIn("five", out)
unlike ($output, qr/five/, 'o5'); self.assertNotIn("six", out)
unlike ($output, qr/six/, 'o6'); self.assertNotIn("seven", out)
unlike ($output, qr/seven/, 'o7');
$output = qx{../src/task rc:filter.rc list project:A priority:H +tag 2>&1}; def test_list_exclude_tag(self):
like ($output, qr/one/, 'p1'); """filter - list -tag"""
unlike ($output, qr/two/, 'p2'); code, out, err = self.t(("list", "-tag"))
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{../src/task rc:filter.rc list project:A priority:H /foo/ +tag 2>&1}; self.assertNotIn("one", out)
like ($output, qr/one/, 'q1'); self.assertIn("two", out)
unlike ($output, qr/two/, 'q2'); self.assertIn("three", out)
unlike ($output, qr/three/, 'q3'); self.assertIn("four", out)
unlike ($output, qr/four/, 'q4'); self.assertNotIn("five", out)
unlike ($output, qr/five/, 'q5'); self.assertIn("six", out)
unlike ($output, qr/six/, 'q6'); self.assertIn("seven", out)
unlike ($output, qr/seven/, 'q7');
$output = qx{../src/task rc:filter.rc list project:A priority:H /foo/ +tag /baz/ 2>&1}; def test_list_non_existing_tag(self):
unlike ($output, qr/one/, 'r1'); """filter - list -missing"""
unlike ($output, qr/two/, 'r2'); code, out, err = self.t(("list", "-missing"))
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');
# Regex filters. self.assertIn("one", out)
#$output = qx{../src/task rc:filter.rc list rc.regex:on project:/[A-Z]/ 2>&1}; self.assertIn("two", out)
#like ($output, qr/one/, 's1'); self.assertIn("three", out)
#like ($output, qr/two/, 's2'); self.assertIn("four", out)
#like ($output, qr/three/, 's3'); self.assertIn("five", out)
#unlike ($output, qr/four/, 's4'); self.assertIn("six", out)
#unlike ($output, qr/five/, 's5'); self.assertIn("seven", out)
#unlike ($output, qr/six/, 's6');
#unlike ($output, qr/seven/, 's7');
#$output = qx{../src/task rc:filter.rc list rc.regex:on project:. 2>&1}; def test_list_mutually_exclusive_tag(self):
#like ($output, qr/one/, 't1'); """filter - list +tag -tag"""
#like ($output, qr/two/, 't2'); code, out, err = self.t.runError(("list", "+tag", "-tag"))
#like ($output, qr/three/, 't3');
#unlike ($output, qr/four/, 't4');
#unlike ($output, qr/five/, 't5');
#unlike ($output, qr/six/, 't6');
#unlike ($output, qr/seven/, 't7');
$output = qx{../src/task rc:filter.rc rc.regex:on list /fo\{2\}/ 2>&1}; self.assertNotIn("one", out)
like ($output, qr/one/, 'u1'); self.assertNotIn("two", out)
unlike ($output, qr/two/, 'u2'); self.assertNotIn("three", out)
unlike ($output, qr/three/, 'u3'); self.assertNotIn("four", out)
unlike ($output, qr/four/, 'u4'); self.assertNotIn("five", out)
unlike ($output, qr/five/, 'u5'); self.assertNotIn("six", out)
like ($output, qr/six/, 'u6'); self.assertNotIn("seven", out)
like ($output, qr/seven/, 'u7');
$output = qx{../src/task rc:filter.rc rc.regex:on list /f../ /b../ 2>&1}; def test_list_projectA_priorityH(self):
unlike ($output, qr/one/, 'v1'); """filter - list project:A priority:H"""
unlike ($output, qr/two/, 'v2'); code, out, err = self.t(("list", "project:A", "priority:H"))
unlike ($output, qr/three/, 'v3');
unlike ($output, qr/four/, 'v4');
unlike ($output, qr/five/, 'v5');
unlike ($output, qr/six/, 'v6');
like ($output, qr/seven/, 'v7');
$output = qx{../src/task rc:filter.rc rc.regex:on list /\\^s/ 2>&1}; self.assertIn("one", out)
unlike ($output, qr/one/, 'w1'); self.assertIn("two", out)
unlike ($output, qr/two/, 'w2'); self.assertNotIn("three", out)
unlike ($output, qr/three/, 'w3'); self.assertNotIn("four", out)
unlike ($output, qr/four/, 'w4'); self.assertNotIn("five", out)
unlike ($output, qr/five/, 'w5'); self.assertNotIn("six", out)
like ($output, qr/six/, 'w6'); self.assertNotIn("seven", out)
like ($output, qr/seven/, 'w7');
$output = qx{../src/task rc:filter.rc rc.regex:on list /\\^.i/ 2>&1}; def test_list_projectA_priority(self):
unlike ($output, qr/one/, 'x1'); """filter - list project:A priority:"""
unlike ($output, qr/two/, 'x2'); code, out, err = self.t(("list", "project:A", "priority:"))
unlike ($output, qr/three/, 'x3');
unlike ($output, qr/four/, 'x4');
like ($output, qr/five/, 'x5');
like ($output, qr/six/, 'x6');
unlike ($output, qr/seven/, 'x7');
$output = qx{../src/task rc:filter.rc rc.regex:on list "/two|five/" 2>&1}; self.assertNotIn("one", out)
unlike ($output, qr/one/, 'y1'); self.assertNotIn("two", out)
like ($output, qr/two/, 'y2'); self.assertIn("three", out)
unlike ($output, qr/three/, 'y3'); self.assertNotIn("four", out)
unlike ($output, qr/four/, 'y4'); self.assertNotIn("five", out)
like ($output, qr/five/, 'y5'); self.assertNotIn("six", out)
unlike ($output, qr/six/, 'y6'); self.assertNotIn("seven", out)
unlike ($output, qr/seven/, 'y7');
# Cleanup. def test_list_projectA_substring(self):
unlink qw(pending.data completed.data undo.data backlog.data filter.rc); """filter - list project:A /foo/"""
exit 0; code, out, err = self.t(("list", "project:A", "/foo/"))
self.assertIn("one", out)
self.assertNotIn("two", out)
self.assertNotIn("three", out)
self.assertNotIn("four", out)
self.assertNotIn("five", out)
self.assertNotIn("six", out)
self.assertNotIn("seven", out)
def test_list_projectA_tag(self):
"""filter - list project:A +tag"""
code, out, err = self.t(("list", "project:A", "+tag"))
self.assertIn("one", out)
self.assertNotIn("two", out)
self.assertNotIn("three", out)
self.assertNotIn("four", out)
self.assertNotIn("five", out)
self.assertNotIn("six", out)
self.assertNotIn("seven", out)
def test_list_projectA_priorityH_substring(self):
"""filter - list project:A priority:H /foo/"""
code, out, err = self.t(("list", "project:A", "priority:H", "/foo/"))
self.assertIn("one", out)
self.assertNotIn("two", out)
self.assertNotIn("three", out)
self.assertNotIn("four", out)
self.assertNotIn("five", out)
self.assertNotIn("six", out)
self.assertNotIn("seven", out)
def test_list_projectA_priorityH_tag(self):
"""filter - list project:A priority:H +tag"""
code, out, err = self.t(("list", "project:A", "priority:H", "+tag"))
self.assertIn("one", out)
self.assertNotIn("two", out)
self.assertNotIn("three", out)
self.assertNotIn("four", out)
self.assertNotIn("five", out)
self.assertNotIn("six", out)
self.assertNotIn("seven", out)
def test_list_projectA_priorityH_substring_tag(self):
"""filter - list project:A priority:H /foo/ +tag"""
code, out, err = self.t(("list", "project:A", "priority:H", "/foo/",
"+tag"))
self.assertIn("one", out)
self.assertNotIn("two", out)
self.assertNotIn("three", out)
self.assertNotIn("four", out)
self.assertNotIn("five", out)
self.assertNotIn("six", out)
self.assertNotIn("seven", out)
def test_list_projectA_priorityH_substring_tag_substring(self):
"""filter - list project:A priority:H /foo/ +tag /baz/"""
code, out, err = self.t.runError(("list", "project:A", "priority:H",
"/foo/", "+tag", "/baz/"))
self.assertNotIn("one", out)
self.assertNotIn("two", out)
self.assertNotIn("three", out)
self.assertNotIn("four", out)
self.assertNotIn("five", out)
self.assertNotIn("six", out)
self.assertNotIn("seven", out)
@unittest.expectedFailure
def test_regex_list_project(self):
"""filter - rc.regex:on list project:/[A-Z]/"""
code, out, err = self.t(("rc.regex:on", "list", "project:/[A-Z]/"))
self.assertIn("one", out)
self.assertIn("two", out)
self.assertIn("three", out)
self.assertNotIn("four", out)
self.assertNotIn("five", out)
self.assertNotIn("six", out)
self.assertNotIn("seven", out)
@unittest.expectedFailure
def test_regex_list_project_any(self):
"""filter - rc.regex:on list project:."""
code, out, err = self.t(("rc.regex:on", "list", "project:."))
self.assertIn("one", out)
self.assertIn("two", out)
self.assertIn("three", out)
self.assertNotIn("four", out)
self.assertNotIn("five", out)
self.assertNotIn("six", out)
self.assertNotIn("seven", out)
def test_regex_list_substring(self):
"""filter - rc.regex:on list /fo{2}/"""
code, out, err = self.t(("rc.regex:on", "list", "/fo{2}/"))
self.assertIn("one", out)
self.assertNotIn("two", out)
self.assertNotIn("three", out)
self.assertNotIn("four", out)
self.assertNotIn("five", out)
self.assertIn("six", out)
self.assertIn("seven", out)
def test_regex_list_double_substring_wildcard(self):
"""filter - rc.regex:on list /f../ /b../"""
code, out, err = self.t(("rc.regex:on", "list", "/f../", "/b../"))
self.assertNotIn("one", out)
self.assertNotIn("two", out)
self.assertNotIn("three", out)
self.assertNotIn("four", out)
self.assertNotIn("five", out)
self.assertNotIn("six", out)
self.assertIn("seven", out)
def test_regex_list_substring_startswith(self):
"""filter - rc.regex:on list /^s/"""
code, out, err = self.t(("rc.regex:on", "list", "/^s/"))
self.assertNotIn("one", out)
self.assertNotIn("two", out)
self.assertNotIn("three", out)
self.assertNotIn("four", out)
self.assertNotIn("five", out)
self.assertIn("six", out)
self.assertIn("seven", out)
def test_regex_list_substring_wildcard_startswith(self):
"""filter - rc.regex:on list /^.i/"""
code, out, err = self.t(("rc.regex:on", "list", "/^.i/"))
self.assertNotIn("one", out)
self.assertNotIn("two", out)
self.assertNotIn("three", out)
self.assertNotIn("four", out)
self.assertIn("five", out)
self.assertIn("six", out)
self.assertNotIn("seven", out)
def test_regex_list_substring_or(self):
"""filter - rc.regex:on list /two|five/"""
code, out, err = self.t(("rc.regex:on", "list", "/two|five/"))
self.assertNotIn("one", out)
self.assertIn("two", out)
self.assertNotIn("three", out)
self.assertNotIn("four", out)
self.assertIn("five", out)
self.assertNotIn("six", out)
self.assertNotIn("seven", out)
class TestBug1110(TestCase):
def setUp(self):
self.t = Task()
def test_status_is_case_insensitive(self):
"""filter - status:Completed / status:completed - behave the same"""
self.t(("add", "ToBeCompleted"))
self.t(("1", "done"))
code, out, err = self.t(("all", "status:Completed"))
self.assertIn("ToBeCompleted", out)
code, out, err = self.t(("all", "status:completed"))
self.assertIn("ToBeCompleted", out)
if __name__ == "__main__":
from simpletap import TAPTestRunner
unittest.main(testRunner=TAPTestRunner())
# vim: ai sts=4 et sw=4

View file

@ -96,13 +96,7 @@ class TestProjects(TestCase):
self.assertRegexpMatches(err, self.STATUS.format("foo bar", "0%", self.assertRegexpMatches(err, self.STATUS.format("foo bar", "0%",
"1 task")) "1 task"))
def test_project_indentation(self): def add_tasks(self):
"""check project/subproject indentation
Reported in bug 1056
See also the tests of helper functions for CmdProjects in util.t.cpp
"""
self.t(("add", "testing", "project:existingParent")) self.t(("add", "testing", "project:existingParent"))
self.t(("add", "testing", "project:existingParent.child")) self.t(("add", "testing", "project:existingParent.child"))
self.t(("add", "testing", "project:abstractParent.kid")) self.t(("add", "testing", "project:abstractParent.kid"))
@ -110,8 +104,7 @@ class TestProjects(TestCase):
self.t(("add", "testing", "project:myProject")) self.t(("add", "testing", "project:myProject"))
self.t(("add", "testing", "project:.myProject.")) self.t(("add", "testing", "project:.myProject."))
code, out, err = self.t(("projects",)) def validate_indentation(self, out):
order = ( order = (
".myProject ", ".myProject ",
".myProject. ", ".myProject. ",
@ -135,6 +128,30 @@ class TestProjects(TestCase):
"indentation.{2}".format(proj, pos, out)) "indentation.{2}".format(proj, pos, out))
) )
def test_project_indentation(self):
"""check project/subproject indentation in 'task projects'
Reported in bug 1056
See also the tests of helper functions for CmdProjects in util.t.cpp
"""
self.add_tasks()
code, out, err = self.t(("projects",))
self.validate_indentation(out)
def test_project_indentation_in_summary(self):
"""check project/subproject indentation in 'task summary'
Reported in bug 1056
"""
self.add_tasks()
code, out, err = self.t(("summary",))
self.validate_indentation(out)
if __name__ == "__main__": if __name__ == "__main__":
from simpletap import TAPTestRunner from simpletap import TAPTestRunner

View file

@ -33,6 +33,23 @@ import warnings
import traceback import traceback
def color(text, c):
"""
Add color on the keyword that identifies the state of the test
"""
if sys.stdout.isatty():
clear = "\033[0m"
colors = {
"red": "\033[1m\033[91m",
"yellow": "\033[1m\033[93m",
"green": "\033[1m\033[92m",
}
return colors[c] + text + clear
else:
return text
class TAPTestResult(unittest.result.TestResult): class TAPTestResult(unittest.result.TestResult):
def __init__(self, stream, descriptions, verbosity): def __init__(self, stream, descriptions, verbosity):
super(TAPTestResult, self).__init__(stream, descriptions, verbosity) super(TAPTestResult, self).__init__(stream, descriptions, verbosity)
@ -126,13 +143,20 @@ class TAPTestResult(unittest.result.TestResult):
if status: if status:
if status == "SKIP": if status == "SKIP":
self.stream.writeln("skip {0} - {1}".format( self.stream.writeln("{0} {1} - {2}".format(
self.testsRun, desc)) color("skip", "yellow"), self.testsRun, desc)
)
elif status == "EXPECTED_FAILURE":
self.stream.writeln("{0} {1} - {2}".format(
color("ok", "green"), self.testsRun, desc)
)
else: else:
self.stream.writeln("not ok {0} - {1}".format( self.stream.writeln("{0} {1} - {2}".format(
self.testsRun, desc)) color("not ok", "red"), self.testsRun, desc)
)
self.stream.writeln("# {0}: {1} {2}:".format( self.stream.writeln("# {0}: {1} {2}:".format(
status, exception_name, trace_msg)) status, exception_name, trace_msg)
)
# Magic 3 is just for pretty indentation # Magic 3 is just for pretty indentation
padding = " " * (len(status) + 3) padding = " " * (len(status) + 3)
@ -142,7 +166,9 @@ class TAPTestResult(unittest.result.TestResult):
line = line.replace("\\n", "\n# ") line = line.replace("\\n", "\n# ")
self.stream.writeln("#{0}{1}".format(padding, line)) self.stream.writeln("#{0}{1}".format(padding, line))
else: else:
self.stream.writeln("ok {0} - {1}".format(self.testsRun, desc)) self.stream.writeln("{0} {1} - {2}".format(
color("ok", "green"), self.testsRun, desc)
)
# Flush all buffers to stdout # Flush all buffers to stdout
self._mergeStdout() self._mergeStdout()
@ -163,6 +189,10 @@ class TAPTestResult(unittest.result.TestResult):
super(TAPTestResult, self).addSkip(test, reason) super(TAPTestResult, self).addSkip(test, reason)
self.report(test, "SKIP", reason) self.report(test, "SKIP", reason)
def addExpectedFailure(self, test, err):
super(TAPTestResult, self).addExpectedFailure(test, err)
self.report(test, "EXPECTED_FAILURE", err)
class TAPTestRunner(unittest.runner.TextTestRunner): class TAPTestRunner(unittest.runner.TextTestRunner):
"""A test runner that displays results using the Test Anything Protocol """A test runner that displays results using the Test Anything Protocol

View file

@ -29,6 +29,7 @@
import sys import sys
import os import os
import unittest import unittest
import re
from datetime import datetime from datetime import datetime
# Ensure python finds the local simpletap module # Ensure python finds the local simpletap module
sys.path.append(os.path.dirname(os.path.abspath(__file__))) sys.path.append(os.path.dirname(os.path.abspath(__file__)))
@ -41,28 +42,76 @@ class TestVersion(TestCase):
def setUp(self): def setUp(self):
self.t = Task() self.t = Task()
def test_version(self): self.t.config("default.command", "")
"""Copyright is current"""
args = ("version",)
code, out, err = self.t(args) def test_usage_command(self):
"""no_command = usage - reports failure"""
code, out, err = self.t.runError()
self.assertIn("You must specify a command or a task to modify", err)
def test_copyright_up_to_date(self):
"""Copyright is current"""
code, out, err = self.t(("version",))
expected = "Copyright \(C\) \d{4} - %d" % (datetime.now().year,) expected = "Copyright \(C\) \d{4} - %d" % (datetime.now().year,)
self.assertRegexpMatches(out.decode("utf8"), expected) self.assertRegexpMatches(out, expected)
def slurp(self, file="../CMakeLists.txt"):
number = "\.".join(["[0-9]+"] * 3)
ver = re.compile("^set \(PROJECT_VERSION \"({0})\"\)$".format(number))
with open(file) as fh:
for line in fh:
if "PROJECT_VERSION" in line:
match = ver.match(line)
if match:
return match.group(1)
raise ValueError("Couldn't find matching version in {0}".format(file))
def test_version(self):
"""version command outputs expected version and license"""
code, out, err = self.t(("version",))
expected = "task {0}".format(self.slurp())
self.assertIn(expected, out)
self.assertIn("MIT license", out)
self.assertIn("http://taskwarrior.org", out)
def slurp_git(self):
git_cmd = ("git", "rev-parse", "--short", "--verify", "HEAD")
_, hash, _ = run_cmd_wait(git_cmd)
return hash.rstrip("\n")
def test_under_version(self):
"""_version outputs expected version and syntax"""
code, out, err = self.t(("_version",))
# version = "x.x.x (git-hash)" or simply "x.x.x"
# corresponding to "compiled from git" or "compiled from tarball"
version = out.split()
if 2 >= len(version) > 0:
git = version[1]
git_expected = "({0})".format(self.slurp_git())
self.assertEqual(git_expected, git)
else:
raise ValueError("Unexpected output from _version '{0}'".format(
out))
ver = version[0]
ver_expected = self.slurp()
self.assertEqual(ver_expected, ver)
def test_task_git_version(self): def test_task_git_version(self):
"""Task binary matches the current git commit""" """Task binary matches the current git commit"""
expected = "Commit: {0}".format(self.slurp_git())
git_cmd = ("git", "rev-parse", "--short", "--verify", "HEAD")
_, hash, _ = run_cmd_wait(git_cmd)
expected = "Commit: {0}".format(hash)
args = ("diag",) args = ("diag",)
code, out, err = self.t(args) code, out, err = self.t(args)
self.assertIn(expected, out) self.assertIn(expected, out)
if __name__ == "__main__": if __name__ == "__main__":
from simpletap import TAPTestRunner from simpletap import TAPTestRunner
unittest.main(testRunner=TAPTestRunner()) unittest.main(testRunner=TAPTestRunner())