Compare commits
279 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd758f8b33 | ||
|
|
adf07a9af0 | ||
|
|
be62157308 | ||
|
|
061639a370 | ||
|
|
ad7abec3d7 | ||
|
|
e923282181 | ||
|
|
6554e4d0f4 | ||
|
|
eb65dd42e4 | ||
|
|
d917215417 | ||
|
|
69f2669bee | ||
|
|
dfc35f3744 | ||
|
|
56dee6975e | ||
|
|
9b80017323 | ||
|
|
75666c56cc | ||
|
|
0a3ee9f0a7 | ||
|
|
67546f8163 | ||
|
|
22d99806d0 | ||
|
|
883e264319 | ||
|
|
e80769794e | ||
|
|
4adfec4482 | ||
|
|
adb72ef023 | ||
|
|
69e0893c61 | ||
|
|
10318fd19e | ||
|
|
756200676d | ||
|
|
73d8fb96cb | ||
|
|
e9cbedd042 | ||
|
|
b22869f9ef | ||
|
|
1a02cacc53 | ||
|
|
cb952329d3 | ||
|
|
579ebe6130 | ||
|
|
89ae64c5fb | ||
|
|
ad9f318e10 | ||
|
|
0e411cd646 | ||
|
|
2b2795077b | ||
|
|
58910b07ef | ||
|
|
5567b04277 | ||
|
|
73d6e05c0e | ||
|
|
0642c37c04 | ||
|
|
45b66cd785 | ||
|
|
ed7c3fad57 | ||
|
|
fa37e002f0 | ||
|
|
f99cd158dd | ||
|
|
a790958daa | ||
|
|
3341f74374 | ||
|
|
1505743fbf | ||
|
|
625ad3d7cf | ||
|
|
f351e17a63 | ||
|
|
c1360506c9 | ||
|
|
50f27e0952 | ||
|
|
dd423d315b | ||
|
|
78c7408380 | ||
|
|
d09a079199 | ||
|
|
ea8b4beede | ||
|
|
30e8b03038 | ||
|
|
79050c29d7 | ||
|
|
98f4e22950 | ||
|
|
47f5a45e47 | ||
|
|
c37f36510a | ||
|
|
c65cb536cc | ||
|
|
4a8b356867 | ||
|
|
ea2d57edd3 | ||
|
|
585cbdfcac | ||
|
|
572a833a51 | ||
|
|
b1700f3cf6 | ||
|
|
4f1183a358 | ||
|
|
180d4ece77 | ||
|
|
0c5a71b02f | ||
|
|
9cab749016 | ||
|
|
06ecef76d3 | ||
|
|
2dfe144236 | ||
|
|
3e5ea8cb6c | ||
|
|
56edf73d93 | ||
|
|
2b63f781e9 | ||
|
|
ccb6327131 | ||
|
|
401f1b6496 | ||
|
|
48bf9d9f85 | ||
|
|
cc82823c47 | ||
|
|
383962173e | ||
|
|
c8d208b9be | ||
|
|
d6daa336ca | ||
|
|
b02374c3f5 | ||
|
|
03f7e0686f | ||
|
|
545013e839 | ||
|
|
4025488cf8 | ||
|
|
4ce2a1d071 | ||
|
|
a7244a999e | ||
|
|
5b2cde4e30 | ||
|
|
21d5607af2 | ||
|
|
1cd6d4c7e7 | ||
|
|
8540cab0a6 | ||
|
|
e3c28f3fb3 | ||
|
|
f6f84aaf42 | ||
|
|
b927d95d58 | ||
|
|
dd5623be65 | ||
|
|
78063c4df7 | ||
|
|
ab86490b37 | ||
|
|
69cae7731f | ||
|
|
eeefc8a992 | ||
|
|
77e98c8c03 | ||
|
|
fccd0d6c96 | ||
|
|
4f70969306 | ||
|
|
57e94585e8 | ||
|
|
c66d6b0500 | ||
|
|
31055360dc | ||
|
|
229a3d309c | ||
|
|
c82469fa2c | ||
|
|
5a886f6e58 | ||
|
|
abffaa184b | ||
|
|
70a0cd670b | ||
|
|
720f28c09c | ||
|
|
a8f03679ed | ||
|
|
0b67dfa38c | ||
|
|
e53ba8110b | ||
|
|
a6875ced6e | ||
|
|
57cac49362 | ||
|
|
81acaa6ae0 | ||
|
|
b596e96b43 | ||
|
|
8e47342a18 | ||
|
|
cb821c2a25 | ||
|
|
0faf7fa8ee | ||
|
|
0002376f2a | ||
|
|
f87b2ee636 | ||
|
|
3aae7b180b | ||
|
|
b001c2f40b | ||
|
|
660d0cca3e | ||
|
|
db1a6601eb | ||
|
|
78778c2819 | ||
|
|
585020ef97 | ||
|
|
e1f3f2355a | ||
|
|
c02cfd594c | ||
|
|
5dbadda512 | ||
|
|
c73376cb2f | ||
|
|
0b5a105b9b | ||
|
|
e92fb9287a | ||
|
|
875c5c1880 | ||
|
|
2b71317e09 | ||
|
|
44aeea8e45 | ||
|
|
f435eeed7a | ||
|
|
a5cb041ef2 | ||
|
|
bfdeee2cea | ||
|
|
414cdf8669 | ||
|
|
3b52b75d2a | ||
|
|
f56e1bef54 | ||
|
|
1b60c20bad | ||
|
|
7ef5233547 | ||
|
|
d552b208dd | ||
|
|
6dd00f41e9 | ||
|
|
a75e7978ab | ||
|
|
6abc40ef46 | ||
|
|
0ab2169c65 | ||
|
|
93067f3c3b | ||
|
|
8d8f7ddb40 | ||
|
|
be75b4bf3a | ||
|
|
3031cf8da9 | ||
|
|
db707d5e15 | ||
|
|
065384027e | ||
|
|
dca4772f33 | ||
|
|
48daf13d7f | ||
|
|
79113668cd | ||
|
|
167b9aa8eb | ||
|
|
9ce55bcf67 | ||
|
|
6cfb913e45 | ||
|
|
5ef3bcc243 | ||
|
|
f43e093515 | ||
|
|
ecb4190e0b | ||
|
|
338e4dfbc7 | ||
|
|
1046555c9c | ||
|
|
b8377b7e5c | ||
|
|
2a8acaf351 | ||
|
|
2ec5a315cb | ||
|
|
be86c52dc0 | ||
|
|
2cf25b7c35 | ||
|
|
75e738a9c9 | ||
|
|
42981c746e | ||
|
|
5a66ac94ee | ||
|
|
eaeca45eae | ||
|
|
37411c7521 | ||
|
|
4ea71c939a | ||
|
|
81ce844d79 | ||
|
|
0780919c2e | ||
|
|
8d43a35ca4 | ||
|
|
42c1b30c31 | ||
|
|
b032a00283 | ||
|
|
b684ded845 | ||
|
|
780d9bb7e7 | ||
|
|
7acef0c9fd | ||
|
|
d019126086 | ||
|
|
a7feed2ae9 | ||
|
|
64c643920f | ||
|
|
2c5f590fed | ||
|
|
3003cdaf08 | ||
|
|
5f353f800d | ||
|
|
f3d31834ee | ||
|
|
28377502f6 | ||
|
|
a6c7236ff3 | ||
|
|
204d287b20 | ||
|
|
6fc34eef42 | ||
|
|
e99c01c92c | ||
|
|
b3e3c36d50 | ||
|
|
e717345f20 | ||
|
|
850135376d | ||
|
|
5d0e6c3435 | ||
|
|
3b354b6d47 | ||
|
|
2c0da35225 | ||
|
|
13955bc6ae | ||
|
|
1d80a2ebdc | ||
|
|
d4910f65eb | ||
|
|
2b44d513e8 | ||
|
|
7f11f1b560 | ||
|
|
b246fae889 | ||
|
|
8c5508de4b | ||
|
|
b3db2245fa | ||
|
|
00b246ce8a | ||
|
|
b94706c56e | ||
|
|
8d784da0ae | ||
|
|
b5f65850f8 | ||
|
|
b7726bce21 | ||
|
|
d44e9363f0 | ||
|
|
5e905742ad | ||
|
|
549e700bc8 | ||
|
|
b2fc4969b9 | ||
|
|
e319359935 | ||
|
|
331b08055a | ||
|
|
847a8b6d49 | ||
|
|
3abce22f0c | ||
|
|
c090367eb8 | ||
|
|
fff789a509 | ||
|
|
e7c8114dff | ||
|
|
fbb217538e | ||
|
|
12c4983936 | ||
|
|
39d9f235de | ||
|
|
7aa0c3698a | ||
|
|
bc40ab63b3 | ||
|
|
6e673d2834 | ||
|
|
30c6dd0047 | ||
|
|
64bc2a165a | ||
|
|
5b96dbbce8 | ||
|
|
3214dc5d37 | ||
|
|
bb89e1a70f | ||
|
|
a16122bbe9 | ||
|
|
57ef35441d | ||
|
|
77dd930574 | ||
|
|
e222090d1f | ||
|
|
bf077c0f97 | ||
|
|
f6842941f3 | ||
|
|
e2e0851a69 | ||
|
|
1299fe468b | ||
|
|
de50b2902c | ||
|
|
bcdcbeeea0 | ||
|
|
469cafa053 | ||
|
|
fdb359c180 | ||
|
|
d321ee242d | ||
|
|
9f9c19d4ae | ||
|
|
179b51278f | ||
|
|
1bb907f76d | ||
|
|
99641e7b0b | ||
|
|
d7bded0d73 | ||
|
|
80a3196097 | ||
|
|
010ef7cd07 | ||
|
|
e5fce9ac08 | ||
|
|
175dd3eb4f | ||
|
|
3cd45c3acd | ||
|
|
157b32e93b | ||
|
|
0b187f3ff8 | ||
|
|
b3d40b2554 | ||
|
|
bb2eb5f266 | ||
|
|
675df6487a | ||
|
|
b2b4fc6b54 | ||
|
|
2074c8bb27 | ||
|
|
ff3b7cf337 | ||
|
|
58730a48b3 | ||
|
|
37436071a0 | ||
|
|
de8a2c36a0 | ||
|
|
1d4c942675 | ||
|
|
fba076a0d0 | ||
|
|
09d7940dd3 | ||
|
|
00031dc1ab | ||
|
|
3ef844de5f | ||
|
|
bb45d91ddb |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -16,3 +16,4 @@ src/tests/all.log
|
||||
src/tests/*.data
|
||||
*~
|
||||
.*.swp
|
||||
package-config/osx/binary/task
|
||||
|
||||
5
AUTHORS
5
AUTHORS
@@ -3,6 +3,7 @@ The development of task was made possible by the significant contributions of th
|
||||
Federico Hernandez (Package Maintainer & Contributing Author)
|
||||
David J Patrick (Designer)
|
||||
John Florian (Contributing Author)
|
||||
Cory Donnelly (Contributing Author)
|
||||
|
||||
The following submitted code, packages or analysis, and deserve special thanks:
|
||||
Damian Glenny
|
||||
@@ -18,6 +19,7 @@ The following submitted code, packages or analysis, and deserve special thanks:
|
||||
Johan Friis
|
||||
Steven de Brouwer
|
||||
Pietro Cerutti
|
||||
Alexander Neumann
|
||||
|
||||
Thanks to the following, who submitted detailed bug reports and excellent suggestions:
|
||||
Eugene Kramer
|
||||
@@ -39,3 +41,6 @@ Thanks to the following, who submitted detailed bug reports and excellent sugges
|
||||
Thomas@BIC
|
||||
Ian Mortimer
|
||||
Zach Frazier
|
||||
Ivo Jimenez
|
||||
Joe Pulliam
|
||||
Juergen Daubert
|
||||
|
||||
159
ChangeLog
159
ChangeLog
@@ -1,7 +1,155 @@
|
||||
|
||||
------ current release ---------------------------
|
||||
|
||||
1.8.2 (9/7/2009)
|
||||
1.9.0 (2/22/2010)
|
||||
+ Added feature #283 that makes it possible to control the verbosity
|
||||
of the output of annotations.
|
||||
+ Added feature #254 (#295) which gives task a second date format to be
|
||||
used in the reports with more conversion sequences like weekday name
|
||||
or weeknumber. The date format is set with variable "dateformat.report".
|
||||
+ Added feature #292 that permits alternate line coloration in reports
|
||||
(thanks to Richard Querin).
|
||||
+ Added feature #307 that provides vim with syntax highlighting for .taskrc.
|
||||
+ Added feature #336 which gives task a 'prepend' command for symmetry
|
||||
with the 'append' command.
|
||||
+ Added feature #341 that makes explicit references to the task and taskrc
|
||||
man pages, both in the auto-generated .taskrc file and the version command
|
||||
output (thanks to Cory Donnelly).
|
||||
+ The 'delete' command is now aliased to 'rm' (thanks to Ivo Jimenez).
|
||||
+ Added new attribute modifiers 'word' and 'noword' which find the existence
|
||||
of whole words, or prove the non-existence of whole words. If a task has
|
||||
the description "Pay the bill", then "description.word:the" will match, but
|
||||
"description.word:th" will not. For partial word matches, there is still
|
||||
"description.contains:th".
|
||||
+ Added new 'config' command to display the configuration settings of task.
|
||||
As a consequence 'version' now only shows the version number and legal
|
||||
information.
|
||||
+ The 'config' command now complains about use of deprecated color names in
|
||||
your .taskrc file.
|
||||
+ Added feature #296, that allows the 'config' command to modify your .taskrc
|
||||
settings directly, with the command 'task config <name> <value>', or
|
||||
'task config <name>' to remove the setting.
|
||||
+ Task now supports nested .taskrc files using the "include /path" directive.
|
||||
+ The 'entry', 'start' and 'end' columns now have equivalents that include the
|
||||
time, and are called 'entry_time', 'start_time', and 'end_time', for use in
|
||||
custom reports.
|
||||
+ 2 new columns have been added to the reports: countdown and
|
||||
countdown_compact. They show the days left until a task is due or how many
|
||||
days a task has been overdue.
|
||||
+ The new 'priority_long' field can be shown in custom reports, and will
|
||||
display 'High' rather than the abbreviated 'H'.
|
||||
+ Task now supports .taskrc command line overrides using rc.name:value and
|
||||
the new rc.name=value to accommodate a frequent mistake.
|
||||
+ The color rules for projects (color.project.foo) now matches on partial
|
||||
project names, the same way as filters.
|
||||
+ The color command now takes a color as an argument, and displays that color
|
||||
with sample text.
|
||||
+ Added 2 new configuration variables to display the details of tasks with due
|
||||
dates when doing a 'task cal' for the corresponding months:
|
||||
'calendar.details' and 'calendar.details.report'
|
||||
+ Added 5 new color configuration variables to colorize today, days with due
|
||||
tasks, days with overdue tasks, weekend days and week numbers in the
|
||||
calendar:
|
||||
'calendar.color.today', 'color.calendar.due', 'calendar.calendar.overdue',
|
||||
'color.calendar.weekend'and 'color.calendar.weeknumber'.
|
||||
+ Added support for holidays in the calendar by using calendar.holidays
|
||||
and the corresponding holiday.X.name and holiday.X.date variables.
|
||||
The default dateformat being YMD (20101224) set by dateformat.holiday.
|
||||
+ The coloring of due tasks in reports can now be enabled for all tasks, and
|
||||
not only the imminent ones, by setting the configuration variable due=0.
|
||||
+ Tasks due on the current day ("today") can now have their own color setting
|
||||
color.due.today and color.calendar.due.today.
|
||||
+ Added a new 'task-faq' man page for common questions and answers.
|
||||
+ Added a new 'task-color' man page detailing how to set up and use color in
|
||||
task.
|
||||
+ Added feature #176, which allows for configurable case-sensitivity for
|
||||
keyword
|
||||
searches and substitutions (thanks to John Florian).
|
||||
+ Task can now use an alternate tag indicator by setting the tag.indicator
|
||||
configuration variable to something other than the default of +.
|
||||
+ Task can now use an alternate active indicator by setting the
|
||||
active.indicator configuration variable to something other than the default
|
||||
of *.
|
||||
+ Task can now use an alternate recurrence indicator by setting the
|
||||
recurrence.indicator configuration variable to something other than the
|
||||
default of R.
|
||||
+ Added a new file, README.build, which provides assistance troubleshooting
|
||||
build-related problems on different operating systems and environments.
|
||||
+ Fixed bug #316 which caused the timesheet report to display an oddly sorted
|
||||
list.
|
||||
+ Fixed bug #317 which colored tasks in the 'completed' report according to
|
||||
due dates, which are no longer relevant to a completed task (thanks to
|
||||
Cory Donnelly).
|
||||
+ Fixed bug #347 which used only a lowercase "all" to confirm multiple changes
|
||||
instead of an uppercase "All" like the "Yes" answer.
|
||||
+ Fixed bug that was causing the 'completed' report to sort incorrectly.
|
||||
+ Fixed bug that showed a calendar for the year 2037 when 'task calendar due'
|
||||
was run, and there are no tasks with due dates.
|
||||
+ Fixed bug #360 which prevented certain modifications to recurring tasks
|
||||
(thanks to John Florian).
|
||||
+ Fixed bug #299 which prevented excluding multiple projects from a report,
|
||||
by using "task list project.isnt:foo project.isnt:bar" (thanks to John
|
||||
Florian).
|
||||
+ Fixed bug #368 which caused recurring tasks 'until' dates to be rendered as
|
||||
epoch numbers instead of dates (thanks to Cory Donnelly).
|
||||
+ Fixed bug #369 which prevented the config command from setting quoted or
|
||||
unquoted multi-word values (thanks to Richard Querin).
|
||||
+ Fixed bug #370 which prevented the removal of a due date from a task,
|
||||
mis-identifying the task as recurring just because it had a due date
|
||||
(thanks to John Florian).
|
||||
+ Fixed bug #371 which caused task to mis-apply certain color rules, like
|
||||
color.alternate, which was (a) not applied first, and (b) not blended
|
||||
with the other color rules (thanks to Richard Querin).
|
||||
+ Fixed bug #372 which incorrectly mapped 16-color backgrounds into the
|
||||
256-color space.
|
||||
|
||||
------ old releases ------------------------------
|
||||
|
||||
1.8.5 (12/05/2009) a6c7236ff34e5eee3ef1693b97cb1367e6e3c607
|
||||
+ Added feature to allow the user to quit when asked to confirm multiple
|
||||
changes. Now task asks "Proceed with change? (Yes/no/all/quit)".
|
||||
+ Added feature #341 that makes explicit references to the task and taskrc
|
||||
man pages, both in the auto-generated .taskrc file and the version command
|
||||
output (thanks to Cory Donnelly).
|
||||
+ Added feature - #310 that simplified and make clearer an error message
|
||||
that complained about things that were beyond user control (thanks to
|
||||
John Florian).
|
||||
+ Fixed bug that was causing the 'completed' report to sort incorrectly.
|
||||
+ Fixed bug #321 where all shell input was converted to lower case (thanks
|
||||
to Juergen Daubert).
|
||||
+ Fixed bug #327 that allowed the removal of a due date from a recurring
|
||||
task.
|
||||
+ Fixed bug #317 which colored tasks in the 'completed' report according
|
||||
to due dates, which are no longer relevant to a completed task (thanks
|
||||
to Cory Donnelly).
|
||||
+ Fixed bug that was causing the 'completed' report to sort incorrectly.
|
||||
+ Fixed bug #322 which failed to propagate rc overrides to shell commands.
|
||||
+ Fixed redundant messages when exiting shell mode.
|
||||
+ Fixed bug #333 which failed to display the ID of a duplicated task (thanks
|
||||
to Cory Donnelly).
|
||||
+ Fixed bug #332 where task complained that the 'recur_ind' custom report
|
||||
column was invalid. It was misnamed in the documentation, which should
|
||||
have read 'recurrence_indicator'. Also, the 'tag_indicator' column was
|
||||
not mentioned anywhere (thanks to T. Charles Yun).
|
||||
+ Fixed bug #319 that caused task to not properly detect the removal of a
|
||||
tag when obtaining confirmation from the user fora bulk modification
|
||||
(thanks to Cory Donnelly).
|
||||
|
||||
1.8.4 (11/17/2009) 12c4983936d27317df100f05da8244139dd06a3f
|
||||
+ Fixed bug that caused wait: dates to not be properly rendered in a
|
||||
readable and preferred format with the "edit" command.
|
||||
+ Fixed bug that caused a hang on cygwin, when a task with multiple
|
||||
annotations was edited (thanks to Joe Pulliam).
|
||||
+ Fixed bug #314 where the edit command fails when data.location includes
|
||||
directories containing spaces (thanks to Cory Donnelly).
|
||||
+ Added a warning (issue #312) when modifying recurring tasks, that all
|
||||
instances of that task may be modified. When task confirms a bulk edit
|
||||
the recurrence is again indicated (thanks to Cory Donnelly).
|
||||
|
||||
1.8.3 (10/21/2009) bcdcbeeea0d92f21c3565aebfaf6332b959f4025
|
||||
+ Added support for Haiku R1/alpha1
|
||||
|
||||
1.8.2 (9/7/2009) f243f0ed443ecd7dde779de8a6525222591024db
|
||||
+ Added feature #282 that returns useful exit codes to the shell. Now a
|
||||
script can detect whether no tasks were returned by a report (thanks to
|
||||
Pietro Cerutti).
|
||||
@@ -14,8 +162,6 @@
|
||||
+ Fixed bug #288 which failed to propagate rc file overrides on the command
|
||||
line to the default command (thanks to Zach Frazier).
|
||||
|
||||
------ old releases ------------------------------
|
||||
|
||||
1.8.1 (8/20/2009) 35792e7874d2bb664abb1a0a67960b7fe7e0fccf
|
||||
+ Fixed bug #231 that broke the build on OpenBSD 32-bit due to a time_t
|
||||
and int collision (thanks to Pietro Cerutti).
|
||||
@@ -46,8 +192,8 @@
|
||||
+ 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).
|
||||
+ Fixed bug that failed to suppress color control code in the header and
|
||||
footnote when redirecting output to a file (thanks to John Florian).
|
||||
|
||||
1.8.0 (7/21/2009) 14977ef317bd004dae2f2c313e806af9f2a2140c
|
||||
+ Added zsh tab completion script (thanks to P.C. Shyamshankar).
|
||||
@@ -364,7 +510,8 @@
|
||||
+ Bug: configure.ac does not properly determine ncurses availability.
|
||||
+ Bug: Cannot seem to use the percent character in a task description.
|
||||
+ Bug: New installation "task stats" reports newest task 12/31/1969.
|
||||
+ Bug: New installation task projects displays header but no data - should short-circuit.
|
||||
+ Bug: New installation task projects displays header but no data - should
|
||||
short-circuit.
|
||||
+ Bug: incorrect color specification in sample .taskrc file.
|
||||
+ Bug: when run without arguments, task dumps core on Solaris 10.
|
||||
+ "task calendar" now reports all months with due pending tasks.
|
||||
|
||||
12
Makefile.am
12
Makefile.am
@@ -1,11 +1,11 @@
|
||||
SUBDIRS = src
|
||||
|
||||
dist_man_MANS = doc/man/task.1 doc/man/taskrc.5 doc/man/task-tutorial.5
|
||||
dist_man_MANS = doc/man/task.1 doc/man/taskrc.5 doc/man/task-tutorial.5 doc/man/task-faq.5 doc/man/task-color.5
|
||||
|
||||
docdir = $(datadir)/doc/${PACKAGE}-${VERSION}
|
||||
#docdir = $(datadir)/doc/${PACKAGE}-${VERSION}
|
||||
doc_DATA = AUTHORS ChangeLog COPYING NEWS README
|
||||
|
||||
EXTRA_DIST = INSTALL
|
||||
EXTRA_DIST = INSTALL README.build
|
||||
|
||||
bashscriptsdir = $(docdir)
|
||||
nobase_dist_bashscripts_DATA = scripts/bash/task_completion.sh
|
||||
@@ -14,7 +14,11 @@ zshscriptsdir = $(docdir)
|
||||
nobase_dist_zshscripts_DATA = scripts/zsh/_task
|
||||
|
||||
vimscriptsdir = $(docdir)
|
||||
nobase_dist_vimscripts_DATA = scripts/vim/README scripts/vim/ftdetect/task.vim scripts/vim/syntax/taskdata.vim scripts/vim/syntax/taskedit.vim
|
||||
nobase_dist_vimscripts_DATA = scripts/vim/README scripts/vim/ftdetect/task.vim scripts/vim/syntax/taskdata.vim scripts/vim/syntax/taskedit.vim scripts/vim/syntax/taskrc.vim
|
||||
|
||||
i18ndir = $(docdir)
|
||||
nobase_dist_i18n_DATA = i18n/strings.de-DE i18n/strings.en-US i18n/strings.es-ES i18n/strings.fr-FR i18n/strings.nl-NL i18n/strings.sv-SE i18n/tips.de-DE i18n/tips.en-US i18n/tips.sv-SE
|
||||
|
||||
rcfiledir = $(docdir)/rc
|
||||
dist_rcfile_DATA = doc/rc/holidays-US.rc doc/rc/holidays-SE.rc doc/rc/dark-16.theme doc/rc/dark-256.theme doc/rc/light-16.theme doc/rc/light-256.theme
|
||||
|
||||
|
||||
50
NEWS
50
NEWS
@@ -1,31 +1,41 @@
|
||||
|
||||
New Features in task 1.8
|
||||
New Features in task 1.9
|
||||
|
||||
- Attribute modifiers, for precise queries
|
||||
- Improved calendar feature
|
||||
- Full undo capability
|
||||
- All reports now customizable
|
||||
- Command aliases can now be created
|
||||
- In addition to being a standard part of Fedora 10 and 11 (yum install task),
|
||||
task is now also a standard part of Cygwin 1.5
|
||||
- There are new demo movies on taskwarrior.org
|
||||
- Shell-friendly exit codes
|
||||
- 256-color support
|
||||
- Support for coloring alternate lines of output. Remember that old green
|
||||
and white fan-fold printer paper?
|
||||
- Supports nested .taskrc files with the new "include" statement"
|
||||
- New columns that include the time as well as date
|
||||
- New attribute modifiers
|
||||
- New date format for reports
|
||||
- Improved .taskrc validation
|
||||
- Improved calendar report with custom coloring and optional task details output
|
||||
- Holidays are now supported in the calendar report
|
||||
- Ability to use multiple, similar filter terms, like:
|
||||
task list project.not:foo project.not:bar
|
||||
- Ability to do case-sensitive or case-insensitive search for keywords, and
|
||||
substitutions in the description and annotations.
|
||||
- Task is now part of Debian
|
||||
|
||||
Please refer to the ChangeLog file for full details. There are too many to
|
||||
list here.
|
||||
|
||||
Task has been built and tested on the following configurations:
|
||||
|
||||
- OS X 10.6 Snow Leopard and 10.5 Leopard
|
||||
- Fedora 11 Leonidas and 10 Cambridge
|
||||
- Ubuntu 9.04 Jaunty Jackalope and 8.10 Intrepid Ibex
|
||||
- Slackware 12.2
|
||||
- Arch Linux
|
||||
- Gentoo Linux
|
||||
- Solaris 10 and 8
|
||||
- OpenBSD 4.5
|
||||
- FreeBSD
|
||||
- Cygwin 1.5
|
||||
* OS X 10.6 Snow Leopard and 10.5 Leopard
|
||||
* Fedora 12 Constantine and 11 Leonidas
|
||||
* Ubuntu 9.10 Karmic Koala and 9.04 Jaunty Jackalope
|
||||
* Debian Sid
|
||||
* Slackware 12.2
|
||||
* Arch Linux
|
||||
* Gentoo Linux
|
||||
* SliTaz Linux
|
||||
* CRUX Linux
|
||||
* Solaris 10 and 8
|
||||
* OpenBSD 4.5
|
||||
* FreeBSD
|
||||
* Cygwin 1.7 and 1.5
|
||||
* Haiku R1/alpha1
|
||||
|
||||
While Task has undergone testing, bugs are sure to remain. If you encounter a
|
||||
bug, please enter a new issue at:
|
||||
|
||||
7
README
7
README
@@ -4,16 +4,15 @@ Thank you for taking a look at task!
|
||||
Task is a GTD, todo list, task management, command line utility with a multitude
|
||||
of features. It is a portable, well supported, very active project, and it is
|
||||
Open Source. Task has binary distributions, online documentation, demonstration
|
||||
movies, and you'll find all the details at the site:
|
||||
movies, and you'll find all the details at:
|
||||
|
||||
http://taskwarrior.org
|
||||
|
||||
At the site you'll find a wiki, discussion forums, downloads, news and more.
|
||||
|
||||
|
||||
Your contributions are especially welcome. Whether it comes in the form of
|
||||
code patches, ideas, discussion, bug reports or just encouragement, your input
|
||||
is needed.
|
||||
code patches, ideas, discussion, bug reports, encouragement or criticism, your
|
||||
input is needed.
|
||||
|
||||
Please send your support questions and code patches to:
|
||||
|
||||
|
||||
98
README.build
Normal file
98
README.build
Normal file
@@ -0,0 +1,98 @@
|
||||
|
||||
Task Build Notes
|
||||
----------------
|
||||
|
||||
Task 1.9 has dependencies that are detected by the configure program in almost
|
||||
all cases, but there are situations and operating systems that mean you will
|
||||
need to offer configure a little help.
|
||||
|
||||
If task will not build on your system, first take a look at the Operating System
|
||||
notes below. If this doesn't help, then go to the Troubleshooting section,
|
||||
which includes instructions on how to contact us for help.
|
||||
|
||||
|
||||
|
||||
Operating System Notes
|
||||
----------------------
|
||||
|
||||
Cygwin 1.7
|
||||
Building task on Cygwin 1.7 requires a configure option:
|
||||
|
||||
./configure --with-ncurses-inc=/usr/include/ncurses
|
||||
|
||||
This is because the ncurses include files are in a different location to
|
||||
Cygwin 1.5.
|
||||
|
||||
|
||||
Haiku Alpha/R1
|
||||
Task must be built with gcc version 4.x, so make sure you run:
|
||||
|
||||
$ setgcc gcc4
|
||||
|
||||
To switch from gcc 2.95 to gcc 4.x.
|
||||
|
||||
|
||||
|
||||
Troubleshooting
|
||||
---------------
|
||||
|
||||
In most cases, it is sufficient to run the configure program like this:
|
||||
|
||||
$ ./configure
|
||||
|
||||
Configure will run and locate all the necessary pieces for the build, and create
|
||||
a Makefile. There may be errors and warnings when running configure, or there
|
||||
may be compiler errors and warnings when running 'make'. Sometimes you will run
|
||||
configure with no reported problems, and the build will fail later. This is
|
||||
almost always because configure is mistaken about some assumption.
|
||||
|
||||
The configure program can accept several options that help with its ability to
|
||||
locate and use the ncurses library. They are:
|
||||
|
||||
--with-ncurses
|
||||
|
||||
This option tells configure that no matter what it thinks, ncurses is
|
||||
definitely on this system and should be enabled. If needed, this option
|
||||
probable needs to be accompanied by the next two options.
|
||||
|
||||
--with-ncurses-inc=/usr/include
|
||||
|
||||
If configure cannot find ncurses header files, this option will tell it
|
||||
exactly where to look. The path specified in this example is the default,
|
||||
so that probably won't help you. The path should be the directory in which
|
||||
the file 'ncurses.h' resides. Here are some possible values to try:
|
||||
|
||||
/usr/include (the default shown above)
|
||||
/usr/include/ncurses
|
||||
/usr/local/include
|
||||
/usr/local/include/ncurses
|
||||
|
||||
This should cover most systems, but new variations keeps cropping up.
|
||||
|
||||
--with-ncurses-lib=/usr/lib
|
||||
|
||||
If configure cannot find the ncurses library, this option will tell it
|
||||
exactly where to look. The path specified in this example is the default,
|
||||
so that probably won't help you. The path should be the directory in which
|
||||
the file 'libncurses.a' (or your system's equivalent) resides. Here are
|
||||
some possible values to try:
|
||||
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
|
||||
This should cover most systems, but new variations keeps cropping up.
|
||||
|
||||
--without-ncurses
|
||||
|
||||
This disables ncurses support in task, and should really be used as a last
|
||||
resort. We know of no systems where this is needed.
|
||||
|
||||
If trying these options does not succeed, please send the contents of the
|
||||
'config.log' files to support@taskwarrior.org, or post a message in the support
|
||||
forums at taskwarrior.org along with the information.
|
||||
|
||||
If configure runs, but task does not build, when ideally you would send both the
|
||||
contents of config.log, and a transcript from the build, which is not written to
|
||||
a file, and must be captured from the terminal.
|
||||
|
||||
---
|
||||
164
configure.ac
164
configure.ac
@@ -2,10 +2,20 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ(2.61)
|
||||
AC_INIT(task, 1.8.2, support@taskwarrior.org)
|
||||
AC_INIT(task, 1.9.0, support@taskwarrior.org)
|
||||
|
||||
|
||||
# Source type.
|
||||
AC_PROG_CXX
|
||||
AC_PROG_CC
|
||||
AC_LANG(C++)
|
||||
|
||||
|
||||
# Local copies for modification and later AC_SUBST.
|
||||
CFLAGS="${CFLAGS=}"
|
||||
CXXFLAGS="${CXXFLAGS=}"
|
||||
|
||||
|
||||
# this macro is used to get the arguments supplied
|
||||
# to the configure script (./configure --enable-debug)
|
||||
# Check if we have enable debug support.
|
||||
@@ -13,44 +23,158 @@ AC_MSG_CHECKING(whether to enable debugging)
|
||||
debug_default="no"
|
||||
AC_ARG_ENABLE(debug, [ --enable-debug=[no/yes] turn on debugging
|
||||
[default=$debug_default]],, enable_debug=$debug_default)
|
||||
# Yes, shell scripts can be used
|
||||
if test "$enable_debug" = "yes"; then
|
||||
CXXFLAGS="$CFLAGS -Wall -pedantic -ggdb3 -DDEBUG"
|
||||
|
||||
if test "x$enable_debug" = "xyes"; then
|
||||
CFLAGS="$CFLAGS -Wall -pedantic -ggdb3 -DDEBUG"
|
||||
CXXFLAGS="$CXXFLAGS -Wall -pedantic -ggdb3 -DDEBUG"
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
CXXFLAGS="$CFLAGS -Wall -pedantic -O3"
|
||||
CFLAGS="$CFLAGS -Wall -pedantic -O3"
|
||||
CXXFLAGS="$CXXFLAGS -Wall -pedantic -O3"
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
|
||||
# Check for OS.
|
||||
OS=`uname|sed -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'`
|
||||
OS=`uname|sed -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'|cut -c 1-5`
|
||||
if test "$OS" = "sunos"; then
|
||||
AC_MSG_NOTICE([OS Solaris detected])
|
||||
AC_DEFINE([SOLARIS], [], [Compiling on Solaris])
|
||||
elif test "$OS" = "darwi"; then
|
||||
AC_MSG_NOTICE([OS Darwin detected])
|
||||
AC_DEFINE([DARWIN], [], [Compiling on Darwin])
|
||||
elif test "$OS" = "cygwi"; then
|
||||
AC_MSG_NOTICE([OS Cygwin detected])
|
||||
AC_DEFINE([CYGWIN], [], [Compiling on Cygwin])
|
||||
elif test "$OS" = "openb"; then
|
||||
AC_MSG_NOTICE([OS OpenBSD detected])
|
||||
AC_DEFINE([OPENBSD], [], [Compiling on OpenBSD])
|
||||
elif test "$OS" = "haiku"; then
|
||||
AC_MSG_NOTICE([OS Haiku detected])
|
||||
AC_DEFINE([HAIKU], [], [Compiling on Haiku])
|
||||
elif test "$OS" = "freeb"; then
|
||||
AC_MSG_NOTICE([OS FreeBSD detected])
|
||||
AC_DEFINE([FREEBSD], [], [Compiling on FreeBSD])
|
||||
elif test "$OS" = "linux"; then
|
||||
AC_MSG_NOTICE([OS Linux detected])
|
||||
AC_DEFINE([LINUX], [], [Compiling on Linux])
|
||||
else
|
||||
AC_MSG_NOTICE([OS Non-Solaris detected])
|
||||
AC_DEFINE([LINUX], [], [Compiling on Non-Solaris])
|
||||
AC_MSG_NOTICE([OS not detected])
|
||||
AC_DEFINE([UNKNOWN], [], [Compiling on Unknown])
|
||||
fi
|
||||
|
||||
|
||||
# ncurses enabled by default.
|
||||
AC_ARG_WITH([ncurses],
|
||||
[AS_HELP_STRING([--without-ncurses], [disable support for ncurses])],
|
||||
[with_ncurses=no],
|
||||
[with_ncurses=yes])
|
||||
|
||||
AC_ARG_WITH([ncurses-inc],
|
||||
[AS_HELP_STRING ([--with-ncurses-inc=DIR], [ncurses include files are in DIR])],
|
||||
[ncurses_inc=$withval],
|
||||
[ncurses_inc=''])
|
||||
|
||||
AC_ARG_WITH([ncurses-lib],
|
||||
[AS_HELP_STRING ([--with-ncurses-lib=DIR], [ncurses lib files are in DIR])],
|
||||
[ncurses_lib=$withval],
|
||||
[ncurses_lib=''])
|
||||
|
||||
if test "x$with_ncurses" == "xyes" ; then
|
||||
AC_DEFINE([HAVE_LIBNCURSES], [1], [Defined if you have libncurses])
|
||||
if test -n "$ncurses_inc"; then
|
||||
CFLAGS="$CFLAGS -I$ncurses_inc"
|
||||
CXXFLAGS="$CXXFLAGS -I$ncurses_inc"
|
||||
fi
|
||||
|
||||
if test -n "$ncurses_lib"; then
|
||||
LDFLAGS="$LDFLAGS -L$ncurses_lib"
|
||||
fi
|
||||
|
||||
AC_CHECK_LIB([ncurses],[main])
|
||||
fi
|
||||
|
||||
|
||||
# Readline enabled by default.
|
||||
#AC_ARG_WITH([readline],
|
||||
# [AS_HELP_STRING([--without-readline], [disable support for readline])],
|
||||
# [with_readline=no],
|
||||
# [with_readline=yes])
|
||||
#
|
||||
#AC_ARG_WITH([readline-inc],
|
||||
# [AS_HELP_STRING ([--with-readline-inc=DIR], [readline include files are in DIR])],
|
||||
# [readline_inc=$withval],
|
||||
# [readline_inc=''])
|
||||
#
|
||||
#AC_ARG_WITH([readline-lib],
|
||||
# [AS_HELP_STRING ([--with-readline-lib=DIR], [readline lib files are in DIR])],
|
||||
# [readline_lib=$withval],
|
||||
# [readline_lib=''])
|
||||
#
|
||||
#if test "x$with_readline" == "xyes" ; then
|
||||
# AC_DEFINE([HAVE_LIBREADLINE], [1], [Defined if you have libreadline])
|
||||
# if test -n "$readline_inc"; then
|
||||
# CFLAGS="$CFLAGS -I$readline_inc"
|
||||
# CXXFLAGS="$CXXFLAGS -I$readline_inc"
|
||||
# fi
|
||||
#
|
||||
# if test -n "$readline_lib"; then
|
||||
# LDFLAGS="$LDFLAGS -L$readline_lib"
|
||||
# fi
|
||||
#
|
||||
# AC_CHECK_LIB([readline],[main])
|
||||
#fi
|
||||
|
||||
|
||||
# Lua disabled by default.
|
||||
AC_ARG_WITH([lua],
|
||||
[AS_HELP_STRING([--with-lua], [enable support for lua])],
|
||||
[with_lua=yes],
|
||||
[with_lua=no])
|
||||
|
||||
AC_ARG_WITH([lua-inc],
|
||||
[AS_HELP_STRING ([--with-lua-inc=DIR], [lua include files are in DIR])],
|
||||
[lua_inc=$withval],
|
||||
[lua_inc=''])
|
||||
|
||||
AC_ARG_WITH([lua-lib],
|
||||
[AS_HELP_STRING ([--with-lua-lib=DIR], [lua lib files are in DIR])],
|
||||
[lua_lib=$withval],
|
||||
[lua_lib=''])
|
||||
|
||||
if test "x$with_lua" == "xyes" ; then
|
||||
AC_DEFINE([HAVE_LIBLUA], [1], [Defined if you have liblua])
|
||||
if test -n "$lua_inc"; then
|
||||
CFLAGS="$CFLAGS -I$lua_inc"
|
||||
CXXFLAGS="$CXXFLAGS -I$lua_inc"
|
||||
fi
|
||||
|
||||
if test -n "$lua_lib"; then
|
||||
LDFLAGS="$LDFLAGS -L$lua_lib"
|
||||
fi
|
||||
|
||||
AC_CHECK_LIB([lua],[main])
|
||||
fi
|
||||
|
||||
|
||||
# Allow the changes above to take effect.
|
||||
AC_SUBST(CFLAGS)
|
||||
AC_SUBST(CXXFLAGS)
|
||||
AC_SUBST(LDFLAGS)
|
||||
|
||||
|
||||
# Now the smaller details.
|
||||
AM_INIT_AUTOMAKE
|
||||
AC_CONFIG_SRCDIR([src/main.cpp])
|
||||
AC_CONFIG_HEADER([auto.h])
|
||||
|
||||
# Checks for programs.
|
||||
AC_PROG_CXX
|
||||
AC_PROG_CC
|
||||
AC_LANG(C++)
|
||||
|
||||
AC_SUBST(CFLAGS)
|
||||
|
||||
# Checks for libraries.
|
||||
AC_CHECK_LIB(ncurses,initscr)
|
||||
|
||||
# Checks for header files.
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS([stdlib.h sys/file.h sys/stat.h sys/time.h unistd.h])
|
||||
AC_CHECK_HEADERS([sstream string vector map])
|
||||
|
||||
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_HEADER_STDBOOL
|
||||
AC_C_CONST
|
||||
@@ -59,15 +183,19 @@ AC_TYPE_SIZE_T
|
||||
AC_HEADER_TIME
|
||||
AC_STRUCT_TM
|
||||
|
||||
|
||||
# Checks for library functions.
|
||||
AC_FUNC_MKTIME
|
||||
AC_FUNC_SELECT_ARGTYPES
|
||||
AC_CHECK_FUNCS([select])
|
||||
#AC_CHECK_FUNC(flock, [AC_DEFINE([HAVE_FLOCK], [1], [Found flock])])
|
||||
AC_CHECK_FUNC(uuid_unparse_lower, [AC_DEFINE([HAVE_UUID], [1], [Found uuid_unparse_lower])])
|
||||
AC_CHECK_FUNC(random, [AC_DEFINE([HAVE_RANDOM], [1], [Found random])])
|
||||
AC_CHECK_FUNC(srandom, [AC_DEFINE([HAVE_SRANDOM], [1], [Found srandom])])
|
||||
|
||||
|
||||
# Generate the Makefiles.
|
||||
AC_CONFIG_FILES([Makefile src/Makefile])
|
||||
AC_OUTPUT
|
||||
|
||||
# End.
|
||||
|
||||
|
||||
274
doc/man/task-color.5
Normal file
274
doc/man/task-color.5
Normal file
@@ -0,0 +1,274 @@
|
||||
.TH task-color 5 2010-02-03 "task 1.9.0" "User Manuals"
|
||||
|
||||
.SH NAME
|
||||
task-color \- A color tutorial for the task(1) command line todo manager.
|
||||
|
||||
.SH SETUP
|
||||
The first thing you need is a terminal program that supports color. All
|
||||
terminal programs support color, but only a few support lots of colors. First
|
||||
tell your terminal program to use color by specifying the TERM environment
|
||||
variable like this:
|
||||
|
||||
TERM=xterm-color
|
||||
|
||||
In this example, xterm-color is used - a common value, and one that doesn't
|
||||
require that you use xterm. This works for most setups. This setting belongs
|
||||
in your shell profile (~/.bash_profile, ~/.bashrc, ~/.cshrc etc, depending on
|
||||
which shell you use). If this is a new setting, you will need to either run
|
||||
that profile script, or close and reopen the terminal window (which does the
|
||||
same thing).
|
||||
|
||||
Now tell task that you want to use color. This is the default for task, so
|
||||
the following step may be unnecessary.
|
||||
|
||||
$ task config color on
|
||||
|
||||
This command will make sure there is an entry in your ~/.taskrc file that looks
|
||||
like:
|
||||
|
||||
color=on
|
||||
|
||||
Now task is ready.
|
||||
|
||||
.SH AUTOMATIC MONOCHROME
|
||||
It should be mentioned that task is aware of whether it's output is going to a
|
||||
terminal, or to a file or through a pipe. When task output goes to a terminal,
|
||||
color is desirable, but consider the following command:
|
||||
|
||||
$ task list > file.txt
|
||||
|
||||
Do we really want all those color control codes in the file? Task assumes that
|
||||
you do not, and temporarily sets color to 'off' while generating the output.
|
||||
This explains the output from the following command:
|
||||
|
||||
$ task config | grep '^color '
|
||||
color off
|
||||
|
||||
it always returns 'off', no matter what the setting.
|
||||
|
||||
The reason is that the task output gets piped into grep, and the color is
|
||||
disabled. If you wanted those color codes, you can override this behavior by
|
||||
setting the _forcecolor variable to on, like this:
|
||||
|
||||
$ task config _forcecolor on
|
||||
$ task config | grep '^color '
|
||||
color on
|
||||
|
||||
or by temporarily overriding it like this:
|
||||
|
||||
$ task rc._forcecolor=on config | grep '^color '
|
||||
color on
|
||||
|
||||
.SH AVAILABLE COLORS
|
||||
Task has a 'color' command that will show all the colors it is capable of
|
||||
displaying. Try this:
|
||||
|
||||
$ task color
|
||||
|
||||
The output cannot be replicated here in a man page, but you should see a set of
|
||||
color samples. How many you see depends on your terminal program's ability to
|
||||
render them.
|
||||
|
||||
You should at least see the Basic colors and Effects - if you do, then you have
|
||||
16-color support. If your terminal supports 256 colors, you'll know it!
|
||||
|
||||
.SH 16-COLOR SUPPORT
|
||||
The basic color support is provided through named colors:
|
||||
|
||||
black, red, blue, green, magenta, cyan, yellow, white
|
||||
|
||||
Foreground color (for text) is simply specified as one of the above colors, or
|
||||
not specified at all to use the default terminal text color.
|
||||
|
||||
Background color is specified by using the word 'on', and one of the above
|
||||
colors. Some examples:
|
||||
|
||||
green # green text, default background color
|
||||
green on yellow # green text, yellow background
|
||||
on yellow # default text color, yellow background
|
||||
|
||||
These colors can be modified further, by making the foreground bold, or by
|
||||
making the background bright. Some examples:
|
||||
|
||||
bold green
|
||||
bold white on bright red
|
||||
on bright cyan
|
||||
|
||||
The order of the words is not important, so the following are equivalent:
|
||||
|
||||
bold green
|
||||
green bold
|
||||
|
||||
But the 'on' is important - colors before the 'on' are foreground, and colors
|
||||
after 'on' are background.
|
||||
|
||||
There is an additional 'underline' attribute that may be used:
|
||||
|
||||
underline bright red on black
|
||||
|
||||
Task has a command that helps you visualize these color combinations. Try this:
|
||||
|
||||
$ task color underline bright red on black
|
||||
|
||||
You can use this command to see how the various color combinations work. You
|
||||
will also see some sample colors displayed, like the ones above, in addition to
|
||||
the sample requested.
|
||||
|
||||
Some combinations look very nice, some look terrible. Different terminal
|
||||
programs do implement slightly different versions of 'red', for example, so you
|
||||
may see some unwanted variation due to the program. The brightness of your
|
||||
display is also a factor.
|
||||
|
||||
.SH 256-COLOR SUPPORT
|
||||
|
||||
Using 256 colors follows the same form, but the names are different, and some
|
||||
colors can be referenced in different ways. First there is by color ordinal,
|
||||
which is like this:
|
||||
|
||||
color0
|
||||
color1
|
||||
color2
|
||||
...
|
||||
color255
|
||||
|
||||
This gives you access to all 256 colors, but doesn't help you much. This range
|
||||
is a combination of 8 basic colors (color0 - color7), then 8 brighter variations
|
||||
(color8 - color15). Then a block of 216 colors (color16 - color231). Then a
|
||||
block of 24 gray colors (color232 - color255).
|
||||
|
||||
The large block of 216 colors (6x6x6 = 216) represents a color cube, which can
|
||||
be addressed via RGB values from 0 to 5 for each component color. A value of 0
|
||||
means none of this component color, and a value of 5 means the most intense
|
||||
component color. For example, a bright red is specified as:
|
||||
|
||||
rgb500
|
||||
|
||||
And a darker red would be:
|
||||
|
||||
rgb300
|
||||
|
||||
Note that the three digits represent the three component values, so in this
|
||||
example the 5, 0 and 0 represent red=5, green=0, blue=0. Combining intense red
|
||||
with no green and no blue yields red. Similarly, blue and green are:
|
||||
|
||||
rgb005
|
||||
rgb050
|
||||
|
||||
Another example - bright yellow - is a mix of bright red and bright green, but
|
||||
no blue component, so bright yellow is addressed as:
|
||||
|
||||
rgb550
|
||||
|
||||
A soft pink would be addressed as:
|
||||
|
||||
rgb515
|
||||
|
||||
See if you agree, by running:
|
||||
|
||||
$ task color black on rgb515
|
||||
|
||||
You may notice that the large color block is represented as 6 squares. All
|
||||
colors in the first square have a red value of 0. All colors in the 6th square
|
||||
have a red value of 5. Within each square, blue ranges from 0 to 5 left to
|
||||
right, and within each square green ranges from 0 to 5, top to bottom. This
|
||||
scheme takes some getting used to.
|
||||
|
||||
The block of 24 gray colors can also be accessed as gray0 - gray23, in a
|
||||
continuous ramp from black to white.
|
||||
|
||||
.SH MIXING 16- AND 256-COLORS
|
||||
|
||||
If you specify 16-colors, and view on a 256-color terminal, no problem. If you
|
||||
try the reverse, specifying 256-colors and viewing on a 16-color terminal, you
|
||||
will be disappointed, perhaps even appalled.
|
||||
|
||||
There is some limited color mapping - for example, if you were to specify this
|
||||
combination:
|
||||
|
||||
red on gray3
|
||||
|
||||
you are mixing a 16-color and 256-color specification. Task will map red to
|
||||
color1, and proceed. Note that red and color1 are not quite the same.
|
||||
|
||||
Note also that there is no bold or bright attributes when dealing with 256
|
||||
colors, but there is still underline available.
|
||||
|
||||
.SH RULES
|
||||
Task supports colorization rules. These are configuration values that specify
|
||||
a color, and the conditions under which that color is used. By example, let's
|
||||
add a few tasks:
|
||||
|
||||
$ task add project:Home priority:H pay the bills (1)
|
||||
$ task add project:Home clean the rug (2)
|
||||
$ task add project:Garden clean out the garage (3)
|
||||
|
||||
We can add a color rule that uses a blue background for all tasks in the Home
|
||||
project:
|
||||
|
||||
$ task config color.project.Home on blue
|
||||
|
||||
We use quotes around "on blue" because there are two words, but they represent
|
||||
one value in the .taskrc file. Now suppose we which to use a bold yellow text
|
||||
color for all cleaning work:
|
||||
|
||||
$ task config color.keyword.clean bold yellow
|
||||
|
||||
Now what happens to task 2, which belongs to project Home (blue background), and
|
||||
is also a cleaning task (bold yellow foreground)? The colors are combined, and
|
||||
the task is shown as "bold yellow on blue".
|
||||
|
||||
Color rules can be applied by project and description keyword, as shown, and
|
||||
also by priority (or lack of priority), by active status, by being due or
|
||||
overdue, by being tagged, or having a specific tag (perhaps the most useful
|
||||
rule) or by being a recurring task.
|
||||
|
||||
It is possible to create a very colorful mix of rules. With 256-color support,
|
||||
those colors can be made subtle, and complementary, but without care, this can
|
||||
be a visual mess. Beware!
|
||||
|
||||
.SH THEMES
|
||||
Task supports themes. What this really means is that with the ability to
|
||||
include other files into the .taskrc file, different sets of color rules can
|
||||
be included.
|
||||
|
||||
To get a good idea of what a color theme looks like, try adding this entry to
|
||||
your .taskrc file:
|
||||
|
||||
include /usr/local/share/doc/task/themes/dark-256.theme
|
||||
|
||||
Better yet, create your own, and share it.
|
||||
|
||||
.SH "CREDITS & COPYRIGHTS"
|
||||
task was written by P. Beckingham <paul@beckingham.net>.
|
||||
.br
|
||||
Copyright (C) 2006 \- 2010 P. Beckingham
|
||||
|
||||
This man page was originally written by Paul Beckingham.
|
||||
|
||||
task is distributed under the GNU General Public License. See
|
||||
http://www.gnu.org/licenses/gpl-2.0.txt for more information.
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR task(1),
|
||||
.BR taskrc(5),
|
||||
.BR task-faq(5)
|
||||
.BR task-tutorial(5)
|
||||
|
||||
For more information regarding task, the following may be referenced:
|
||||
|
||||
.TP
|
||||
The official site at
|
||||
<http://taskwarrior.org>
|
||||
|
||||
.TP
|
||||
The official code repository at
|
||||
<git://tasktools.org/task.git/>
|
||||
|
||||
.TP
|
||||
You can contact the project by writing an email to
|
||||
<support@taskwarrior.org>
|
||||
|
||||
.SH REPORTING BUGS
|
||||
.TP
|
||||
Bugs in task may be reported to the issue-tracker at
|
||||
<http://taskwarrior.org>
|
||||
175
doc/man/task-faq.5
Normal file
175
doc/man/task-faq.5
Normal file
@@ -0,0 +1,175 @@
|
||||
.TH task-faq 5 2010-02-03 "task 1.9.0" "User Manuals"
|
||||
|
||||
.SH NAME
|
||||
task-faq \- A FAQ for the task(1) command line todo manager.
|
||||
|
||||
.SH DESCRIPTION
|
||||
Task is a command line TODO list manager. It maintains a list of tasks that you
|
||||
want to do, allowing you to add/remove, and otherwise manipulate them. Task
|
||||
has a rich list of commands that allow you to do various things with it.
|
||||
|
||||
.SH WELCOME
|
||||
Welcome to the task FAQ. If you have would like to see a question answered
|
||||
here, please send us a note at <support@taskwarrior.org>.
|
||||
|
||||
.TP
|
||||
.B Q: Where does task store the data?
|
||||
By default, task creates a .taskrc file in your home directory and populates it
|
||||
with defaults. Task also creates a .task directory in your home directory and
|
||||
puts data files there.
|
||||
|
||||
.TP
|
||||
.B Q: Can I edit that data?
|
||||
Of course you can. It is a simple text file, and looks somewhat like the JSON
|
||||
format, and if you are careful not to break the format, there is no reason not
|
||||
to edit it. But task provides a rich command set to do that manipulation for
|
||||
you, so it is probably best to leave those files alone.
|
||||
|
||||
.TP
|
||||
.B Q: How do I restore my .taskrc file to defaults?
|
||||
If you delete (or rename) your .taskrc file, task will offer to create a default
|
||||
one for you. Another way to do this is with the command:
|
||||
|
||||
$ task rc:new-file version
|
||||
|
||||
Task will create 'new-file' if it doesn't already exist. Note that this is a
|
||||
good way to learn about new configuration settings, if your .taskrc file was
|
||||
created by an older version of task.
|
||||
|
||||
.TP
|
||||
.B Q: Do I need to back up my task data?
|
||||
Yes. You should back up your ~/.task directory, and probably your ~/.taskrc
|
||||
file too.
|
||||
|
||||
.TP
|
||||
.B Q: Can I share my tasks between different machines?
|
||||
Yes, you can. Most people have success with a DropBox - a free and secure file
|
||||
synching tool. Simply configure task to store it's data in a dropbox folder, by
|
||||
modifying the:
|
||||
|
||||
data.location=...
|
||||
|
||||
configuration variable. Check out DropBox at http://www.dropbox.com.
|
||||
|
||||
.TP
|
||||
.B Q: The undo.data file gets very large - do I need it?
|
||||
You need it if you want the undo capability. But if it gets large, you can
|
||||
certainly truncate it to save space, just be careful to delete lines from the
|
||||
top of the file, up to and including a separator '---'. The simplest way is to
|
||||
simply delete the undo.data file. Note that it does not slow down task, because
|
||||
task never reads it until you want to undo. Otherwise task only appends to the
|
||||
file.
|
||||
|
||||
.TP
|
||||
.B Q: How do I know whether my terminal support 256 colors?
|
||||
You will need to make sure your TERM environment variable is set to xterm-color,
|
||||
otherwise the easiest way is to just try it! With task 1.9 or later, you simply
|
||||
run
|
||||
|
||||
$ task color
|
||||
|
||||
and a full color palette is displayed. If you see only 8 or 16 colors, perhaps
|
||||
with those colors repeated, then your terminal does not support 256 colors.
|
||||
|
||||
See the task-color(5) man page for more details.
|
||||
|
||||
.TP
|
||||
.B Q: How do I make use of all these colors?
|
||||
See the task-color(5) man page for an in-depth explanation of the task color
|
||||
rules.
|
||||
|
||||
.TP
|
||||
.B Q: How can I make task put the command in the terminal window title?
|
||||
You cannot. But you can make the shell do it, and you can make the shell
|
||||
call the task program. Here is a Bash script that does this:
|
||||
|
||||
#! /bin/bash
|
||||
|
||||
printf "\033]0;task $*\a"
|
||||
/usr/local/bin/task $*
|
||||
|
||||
You just need to run the script, and let the script run task. Here is a Bash
|
||||
function that does the same thing:
|
||||
|
||||
t ()
|
||||
{
|
||||
printf "\033]0;task $*\a"
|
||||
/usr/local/bin/task $*
|
||||
}
|
||||
|
||||
.TP
|
||||
.B Q: Task searches in a case-sensitive fashion - can I change that?
|
||||
You can. Just set the following value in your .taskrc file:
|
||||
|
||||
search.case.sensitive=no
|
||||
|
||||
This will affect searching for keywords:
|
||||
|
||||
$ task list Document
|
||||
|
||||
task will perform a caseless search in the description and any annotations for
|
||||
the keyword 'Document'. It also affects description and annotation
|
||||
substitutions:
|
||||
|
||||
$ task 1 /teh/the/
|
||||
|
||||
The pattern on the left will now be a caseless search term.
|
||||
|
||||
.TP
|
||||
.B Q: Why do the task ID numbers change?
|
||||
Task does this to always show you the smallest numbers it can. The idea is that
|
||||
if your tasks are numbered 1 - 33, for example, those are easy to type in. If
|
||||
instead task kept a rolling sequence number, after a while your tasks might be
|
||||
numbered 481 - 513, which makes it more likely to enter one incorrectly, because
|
||||
there are more digits.
|
||||
|
||||
When you run a report (such as "list"), task assigns the numbers before it
|
||||
displays them. For example, you can do this:
|
||||
|
||||
$ task list
|
||||
$ task do 12
|
||||
$ task add Pay the rent
|
||||
$ task delete 31
|
||||
|
||||
Those id numbers are then good until the next report is run. This is because
|
||||
task performs a garbage-collect operation on the pending tasks file when a
|
||||
report is run, which moves the deleted and completed tasks from the pending.data
|
||||
file to the completed.data file. This keeps the pending tasks file small, and
|
||||
therefore keeps task fast. The completed data file is the one that grows
|
||||
unbounded with use, but that one isn't accessed as much, so it doesn't matter as
|
||||
much. So in all, the ID number resequencing is about efficiency.
|
||||
|
||||
.SH "CREDITS & COPYRIGHTS"
|
||||
task was written by P. Beckingham <paul@beckingham.net>.
|
||||
.br
|
||||
Copyright (C) 2006 \- 2010 P. Beckingham
|
||||
|
||||
This man page was originally written by P. Beckingham.
|
||||
|
||||
task is distributed under the GNU General Public License. See
|
||||
http://www.gnu.org/licenses/gpl-2.0.txt for more information.
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR task(1),
|
||||
.BR taskrc(5),
|
||||
.BR task-tutorial(5)
|
||||
.BR task-color(5)
|
||||
|
||||
For more information regarding task, the following may be referenced:
|
||||
|
||||
.TP
|
||||
The official site at
|
||||
<http://taskwarrior.org>
|
||||
|
||||
.TP
|
||||
The official code repository at
|
||||
<git://tasktools.org/task.git/>
|
||||
|
||||
.TP
|
||||
You can contact the project by writing an email to
|
||||
<support@taskwarrior.org>
|
||||
|
||||
.SH REPORTING BUGS
|
||||
.TP
|
||||
Bugs in task may be reported to the issue-tracker at
|
||||
<http://taskwarrior.org>
|
||||
@@ -1,12 +1,17 @@
|
||||
.TH task-tutorial 5 2009-09-07 "task 1.8.2" "User Manuals"
|
||||
.TH task-tutorial 5 2010-02-03 "task 1.9.0" "User Manuals"
|
||||
|
||||
.SH NAME
|
||||
task-tutorial \- A tutorial for the task(1) command line todo manager.
|
||||
|
||||
.SH NOTE
|
||||
Please note that this tutorial was written for task 1.7.0. Though it is still
|
||||
accurate on the general usage of task, it might not longer be 100% correct in
|
||||
all details. A new tutorial for task is planned for task 2.0.0.
|
||||
|
||||
.SH DESCRIPTION
|
||||
Task is a command line TODO list manager. It maintains a list of tasks that you
|
||||
want to do, allowing you to add/remove, and otherwise manipulate them. Task
|
||||
has a rich list of subcommands that allow you to do various things with it.
|
||||
has a rich list of commands that allow you to do various things with it.
|
||||
|
||||
.SH 30 second tutorial
|
||||
|
||||
@@ -53,7 +58,8 @@ $ task ls
|
||||
No matches
|
||||
.RE
|
||||
|
||||
Easy. But now consider checking out what task can really do...
|
||||
That's how easy managing your task list can be. But now consider learning what
|
||||
task can really do...
|
||||
|
||||
.SH Simple usage of task
|
||||
Let us begin by adding some tasks:
|
||||
@@ -68,8 +74,8 @@ $ task add Reserve a rental car
|
||||
$ task add Reserve a hotel room
|
||||
.RE
|
||||
|
||||
That's it. You'll notice immediately that task has a very minimalist
|
||||
interface. Let us take a look at those tasks:
|
||||
You'll notice immediately that task has a very minimalist interface. Let us take
|
||||
a look at those tasks:
|
||||
.br
|
||||
.RS
|
||||
$ task ls
|
||||
@@ -96,18 +102,18 @@ $ task 2 delete
|
||||
Permanently delete task? (y/n) y
|
||||
.RE
|
||||
|
||||
Task wants you to confirm deletions. To remove the confirmation, edit
|
||||
Task wants you to confirm deletions. To suppress the confirmation, edit
|
||||
your .taskrc file and change the line:
|
||||
.br
|
||||
.RS
|
||||
confirmation=yes
|
||||
.RE
|
||||
.br
|
||||
to have a value of "no".
|
||||
to have a value of "no". If the entry is not there, then add it.
|
||||
|
||||
While the use of projects and priorities are not essential to benefiting
|
||||
from task, they can be very useful when the list of tasks grows large.
|
||||
Let's assign a project to these tasks:
|
||||
While the use of projects and priorities are not essential, they can be very
|
||||
useful when the list of tasks grows large. Let's assign projects to these
|
||||
tasks:
|
||||
.br
|
||||
.RS
|
||||
$ task 1 project:Wedding
|
||||
@@ -153,8 +159,8 @@ ID Project Pri Description
|
||||
1 Wedding Book plane ticket
|
||||
.RE
|
||||
|
||||
Task matches the leftmost part of the project when searching, so projects may
|
||||
be abbreviated:
|
||||
Task matches the leftmost part of the project when searching, so projects may be
|
||||
abbreviated:
|
||||
.br
|
||||
.RS
|
||||
$ task ls project:Wedding.Tra
|
||||
@@ -240,20 +246,37 @@ ID Project Pri Description
|
||||
2 Wedding M Reserve a rental car
|
||||
.RE
|
||||
|
||||
Notice that task supports the abbreviation of words such as priority,
|
||||
project. Priority can be abbreviated to pri, but not pr, because it
|
||||
is ambiguous. Now that tasks have been prioritized, you can see that
|
||||
the tasks are being sorted by priority, with the highest priority
|
||||
tasks at the top.
|
||||
Notice that task supports the abbreviation of words such as priority and
|
||||
project. Priority can be abbreviated to pri, but not pr, because it is
|
||||
ambiguous. Now that tasks have been prioritized, you can see that the tasks are
|
||||
being sorted by priority, with the highest priority tasks at the top.
|
||||
|
||||
These attributes can all be provided when the task is added, instead of
|
||||
applying them afterwards, as shown. The following command shows how to
|
||||
set all the attributes at once:
|
||||
These attributes can all be provided when the task is added, instead of applying
|
||||
them afterwards, as shown. The following command shows how to set all the
|
||||
attributes at once:
|
||||
.br
|
||||
.RS
|
||||
$ task add project:Wedding priority:H Book plane ticket
|
||||
.RE
|
||||
|
||||
The sequence of those arguments is not important, so you could have entered the
|
||||
following command instead:
|
||||
.br
|
||||
.RS
|
||||
$ task project:Wedding add Book plane priority:H ticket
|
||||
.RE
|
||||
|
||||
This is because task knows what attributes look like (name:value), knows what
|
||||
commands it supports (add, ...), and just assumes the rest is part of the
|
||||
description. Incidentally, if you wanted 'priority:H' to be part of your task
|
||||
description, you need to fool task into ignoring it as an attribute. That can
|
||||
be done in two ways:
|
||||
.br
|
||||
.RS
|
||||
$ task add "quoting makes task consider priority:H part of one big argument"
|
||||
$ task add -- the hyphens make task treat everything after it as description
|
||||
.RE
|
||||
|
||||
The 'ls' command provides the least information for each task. The 'list'
|
||||
command provides more:
|
||||
.br
|
||||
@@ -288,29 +311,8 @@ ID Project Pri Due Active Age Description
|
||||
2 Wedding M 7 mins Reserve a rental car
|
||||
.RE
|
||||
|
||||
If today's date is 6/23/2008, then task 3 is due in 2 days. It will be colored
|
||||
yellow if your terminal supports color. To change this color, edit your .taskrc
|
||||
file, and change the line to one of these alternatives:
|
||||
.br
|
||||
.RS
|
||||
color.due=red
|
||||
.br
|
||||
color.due=on_blue
|
||||
.br
|
||||
color.due=red on_blue
|
||||
.br
|
||||
color.due=bold_red on_blue
|
||||
.RE
|
||||
|
||||
Where color is one of the following:
|
||||
|
||||
.br
|
||||
.RS
|
||||
black, blue, red, green, cyan, magenta, yellow or white
|
||||
.RE
|
||||
|
||||
All colors are specified in this way. Take a look in .taskrc for all the other
|
||||
color rules that you control.
|
||||
Note that due tasks may be colored to highlight the importance. See the
|
||||
task-color(5) man page for full details.
|
||||
|
||||
Tagging tasks is a good way to group them, aside from specifying a project.
|
||||
To add a tag to a task:
|
||||
@@ -357,13 +359,13 @@ $ task 3 \-john
|
||||
.RE
|
||||
|
||||
.SH Advanced usage of task
|
||||
Advanced examples of the usage of task can be found at
|
||||
the official site at <http://taskwarrior.org>
|
||||
Advanced examples of the usage of task can be found at the official site at
|
||||
<http://taskwarrior.org>
|
||||
|
||||
.SH "CREDITS & COPYRIGHTS"
|
||||
task was written by P. Beckingham <paul@beckingham.net>.
|
||||
.br
|
||||
Copyright (C) 2006 \- 2009 P. Beckingham
|
||||
Copyright (C) 2006 \- 2010 P. Beckingham
|
||||
|
||||
This man page was originally written by Federico Hernandez.
|
||||
|
||||
@@ -372,7 +374,9 @@ http://www.gnu.org/licenses/gpl-2.0.txt for more information.
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR task(1),
|
||||
.BR taskrc(5)
|
||||
.BR taskrc(5),
|
||||
.BR task-faq(5)
|
||||
.BR task-color(5)
|
||||
|
||||
For more information regarding task, the following may be referenced:
|
||||
|
||||
@@ -382,7 +386,7 @@ The official site at
|
||||
|
||||
.TP
|
||||
The official code repository at
|
||||
<http://github.com/pbeckingham/task/>
|
||||
<git://tasktools.org/task.git/>
|
||||
|
||||
.TP
|
||||
You can contact the project by writing an email to
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.TH task 1 2009-09-07 "task 1.8.2" "User Manuals"
|
||||
.TH task 1 2010-02-03 "task 1.9.0" "User Manuals"
|
||||
|
||||
.SH NAME
|
||||
task \- A command line todo manager.
|
||||
@@ -19,8 +19,11 @@ Adds a new task to the task list.
|
||||
|
||||
.TP
|
||||
.B append [tags] [attrs] description
|
||||
Appends more information to an existing
|
||||
task.
|
||||
Appends information to an existing task.
|
||||
|
||||
.TP
|
||||
.B prepend [tags] [attrs] description
|
||||
Prepends information to an existing task.
|
||||
|
||||
.TP
|
||||
.B annotate ID description
|
||||
@@ -118,13 +121,30 @@ Imports tasks from a variety of formats.
|
||||
Exports all tasks as a CSV file.
|
||||
|
||||
.TP
|
||||
.B color
|
||||
Displays all possible colors.
|
||||
.B color [sample]
|
||||
Displays all possible colors, or a sample.
|
||||
|
||||
.TP
|
||||
.B version
|
||||
Shows the task version number and current settings in the task configuration
|
||||
file.
|
||||
Shows the task version number
|
||||
|
||||
.TP
|
||||
.B config [name [value | '']]
|
||||
Shows the current settings in the task configuration file. Also supports
|
||||
directly modifying the .taskrc file. This command either modifies
|
||||
the 'name' setting with a new value of 'value', or adds a new entry that
|
||||
is equivalent to 'name=value':
|
||||
|
||||
task config name value
|
||||
|
||||
This command sets a blank value. This has the effect of suppressing any
|
||||
default value:
|
||||
|
||||
task config name ''
|
||||
|
||||
Finally, this command removes any 'name=...' entry from the .taskrc file:
|
||||
|
||||
task config name
|
||||
|
||||
.TP
|
||||
.B help
|
||||
@@ -151,9 +171,13 @@ Shows all tasks matching the specified criteria
|
||||
that are completed.
|
||||
|
||||
.TP
|
||||
.B ls [tags] [attrs] [description]
|
||||
.B minimal [tags] [attrs] [description]
|
||||
Provides a minimal listing of tasks with specified criteria.
|
||||
|
||||
.TP
|
||||
.B ls [tags] [attrs] [description]
|
||||
Provides a short listing of tasks with specified criteria.
|
||||
|
||||
.TP
|
||||
.B list [tags] [attrs] [description]
|
||||
Provides a more detailed listing of tasks with specified criteria.
|
||||
@@ -263,6 +287,10 @@ Attribute modifiers improve filters. Supported modifiers are:
|
||||
.B startswith (synonym left)
|
||||
.br
|
||||
.B endswith (synonym right)
|
||||
.br
|
||||
.B word
|
||||
.br
|
||||
.B noword
|
||||
.RE
|
||||
|
||||
For example:
|
||||
@@ -437,7 +465,7 @@ can be configured in the configuration file.
|
||||
.SH "CREDITS & COPYRIGHTS"
|
||||
task was written by P. Beckingham <paul@beckingham.net>.
|
||||
.br
|
||||
Copyright (C) 2006 \- 2009 P. Beckingham
|
||||
Copyright (C) 2006 \- 2010 P. Beckingham
|
||||
|
||||
This man page was originally written by P.C. Shyamshankar, and has been modified
|
||||
and supplemented by Federico Hernandez.
|
||||
@@ -447,7 +475,9 @@ http://www.gnu.org/licenses/gpl-2.0.txt for more information.
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR taskrc(5),
|
||||
.BR task-tutorial(5)
|
||||
.BR task-tutorial(5),
|
||||
.BR task-faq(5)
|
||||
.BR task-color(5)
|
||||
|
||||
For more information regarding task, the following may be referenced:
|
||||
|
||||
@@ -457,7 +487,7 @@ The official site at
|
||||
|
||||
.TP
|
||||
The official code repository at
|
||||
<http://github.com/pbeckingham/task/>
|
||||
<git://tasktools.org/task.git/>
|
||||
|
||||
.TP
|
||||
You can contact the project by writing an email to
|
||||
|
||||
480
doc/man/taskrc.5
480
doc/man/taskrc.5
@@ -1,4 +1,4 @@
|
||||
.TH taskrc 5 2009-09-07 "task 1.8.2" "User Manuals"
|
||||
.TH taskrc 5 2010-02-03 "task 1.9.0" "User Manuals"
|
||||
|
||||
.SH NAME
|
||||
taskrc \- Configuration file for the task(1) command
|
||||
@@ -36,11 +36,13 @@ $ task rc.<name>:<value> ...
|
||||
|
||||
If
|
||||
.B task
|
||||
is run without an existing configuration file it will ask if it should create a default, sample
|
||||
is run without an existing configuration file it will ask if it should create a
|
||||
default, sample
|
||||
.I .taskrc
|
||||
file in the user's home directory.
|
||||
|
||||
The task configuration file consists of a series of "assignments" in each line. The "assignments" have the syntax:
|
||||
The task configuration file consists of a series of "assignments" in each line.
|
||||
The "assignments" have the syntax:
|
||||
|
||||
.RS
|
||||
<name-of-configuration-variable>=<value-to-be-set>
|
||||
@@ -57,11 +59,46 @@ is one of the variables described below
|
||||
is the value the variable is to be set to.
|
||||
.RE
|
||||
|
||||
and set a configuration variable to a certain value. The equal sign ("=") is used to separate the variable
|
||||
name from the value to be set.
|
||||
and set a configuration variable to a certain value. The equal sign ("=") is
|
||||
used to separate the variable name from the value to be set.
|
||||
|
||||
The hash mark, or pound sign ("#") is used as a "comment" character. It can be used to annotate the
|
||||
configuration file. All text after the character to the end of the line is ignored.
|
||||
The hash mark, or pound sign ("#") is used as a "comment" character. It can be
|
||||
used to annotate the configuration file. All text after the character to the end
|
||||
of the line is ignored.
|
||||
|
||||
Note that task is flexible about the values used to represent Boolean items.
|
||||
You can use "on", "yes", "y", "1", "true", "t", "+", "enabled". Anything else
|
||||
means "off".
|
||||
|
||||
.SH EDITING
|
||||
You can edit your .taskrc file by hand if you wish, or you can use the 'config'
|
||||
command. To permanently set a value in your .taskrc file, use this command:
|
||||
|
||||
.RS
|
||||
$ task config nag "You have higher priority tasks!"
|
||||
.RE
|
||||
|
||||
To delete an entry, use this command:
|
||||
|
||||
.RS
|
||||
$ task config nag
|
||||
.RE
|
||||
|
||||
Task will then use the default value. To explicitly set a value to blank, and
|
||||
therefore avoid using the default value, use this command:
|
||||
|
||||
.RS
|
||||
$ task config nag ""
|
||||
.RE
|
||||
|
||||
Task will also display all your settings with this command:
|
||||
|
||||
.RS
|
||||
$ task config
|
||||
.RE
|
||||
|
||||
and in addition, will also perform a check of all the values in the file,
|
||||
warning you of anything it finds amiss.
|
||||
|
||||
.SH CONFIGURATION VARIABLES
|
||||
Valid variable names and their default values are:
|
||||
@@ -70,15 +107,20 @@ Valid variable names and their default values are:
|
||||
|
||||
.TP
|
||||
.B data.location=$HOME/.task
|
||||
This is a path to the directory containing all the task files. By default, it is set up to be ~/.task,
|
||||
for example: /home/paul/.task
|
||||
This is a path to the directory containing all the task files. By default, it is
|
||||
set up to be ~/.task, for example: /home/paul/.task
|
||||
|
||||
Note that you can use the
|
||||
.B ~
|
||||
shell meta character, which will be properly expanded.
|
||||
|
||||
.TP
|
||||
.B locking=on
|
||||
Determines whether task uses file locking when accessing the pending.data and completed.data files.
|
||||
Default to "on". Solaris users who store the task data files on an NFS mount may need to set locking
|
||||
to "off". Note that setting this value to "off" is dangerous. It means that another program may write
|
||||
to the task.pending file when task is attempting to do the same.
|
||||
Determines whether task uses file locking when accessing the pending.data and
|
||||
completed.data files. Defaults to "on". Solaris users who store the task data
|
||||
files on an NFS mount may need to set locking to "off". Note that there is
|
||||
danger in setting this value to "off" - another program (or another instance of
|
||||
task) may write to the task.pending file at the same time.
|
||||
|
||||
.SS TERMINAL
|
||||
.TP
|
||||
@@ -94,9 +136,9 @@ The width of tables used when ncurses support is not available. Defaults to 80.
|
||||
.B editor=vi
|
||||
Specifies which text editor you wish to use for when the
|
||||
.B task edit <ID>
|
||||
command is used. Task will first look for this configuration variable. If found, it is used.
|
||||
Otherwise task will look for the $VISUAL or $EDITOR environment variables, before it defaults
|
||||
to using "vi".
|
||||
command is used. Task will first look for this configuration variable. If found,
|
||||
it is used. Otherwise task will look for the $VISUAL or $EDITOR environment
|
||||
variables, before it defaults to using "vi".
|
||||
|
||||
.SS MISCELLANEOUS
|
||||
|
||||
@@ -109,93 +151,263 @@ locale for which there is no strings file.
|
||||
|
||||
.TP
|
||||
.B confirmation=yes
|
||||
May be "yes" or "no", and determines whether task will ask for confirmation before deleting a task or doing bulk changes.
|
||||
May be "yes" or "no", and determines whether task will ask for confirmation
|
||||
before deleting a task or doing bulk changes. The default value is "yes".
|
||||
|
||||
.TP
|
||||
.B echo.command=yes
|
||||
May be "yes" or "no", and causes task to display the ID and description of any task when you run the start, stop, do, undo or delete commands. The default value is "yes".
|
||||
May be "yes" or "no", and causes task to display the ID and description of any
|
||||
task when you run the start, stop, do, undo or delete commands. The default
|
||||
value is "yes".
|
||||
|
||||
.TP
|
||||
.B annotations=full
|
||||
.TP
|
||||
.B report.X.annotations=full
|
||||
Controls the display of annotations in reports. Defaults to full - all
|
||||
annotations are displayed. Set to "sparse" only the last (newest) annotation
|
||||
is displayed and if there are more than one present for a task a "+" sign is
|
||||
added to the description. Set to "none" the output of annotations is disabled
|
||||
and a "+" sign will be added if there are any annotations present. The default
|
||||
value is "full".
|
||||
|
||||
.TP
|
||||
.B next=2
|
||||
Is a number, defaulting to 2, which is the number of tasks for each project that are shown in the
|
||||
Is a number, defaulting to 2, which is the number of tasks for each project that
|
||||
are shown in the
|
||||
.B task next
|
||||
command.
|
||||
|
||||
.TP
|
||||
.B bulk=2
|
||||
Is a number, defaulting to 2. When more than this number of tasks are modified in a single command, confirmation will be required, unless the
|
||||
Is a number, defaulting to 2. When more than this number of tasks are modified
|
||||
in a single command, confirmation will be required, unless the
|
||||
.B confirmation
|
||||
variable is "no".
|
||||
|
||||
This is useful for preventing large-scale unintended changes.
|
||||
|
||||
.TP
|
||||
.B nag=You have higher priority tasks.
|
||||
This may be a string of text, or blank. It is used as a prompt when a task is completed
|
||||
that is not considered high priority. The "task next" command lists important tasks, and
|
||||
completing one of those does not generate this nagging. Default value is: You have higher
|
||||
priority tasks.
|
||||
This may be a string of text, or blank. It is used as a prompt when a task is
|
||||
started or completed that is not considered high priority. The "task next"
|
||||
command lists important tasks, and completing one of those does not generate
|
||||
this nagging. Default value is: You have higher priority tasks. It is a gentle
|
||||
reminder that you are contradicting your own priority settings.
|
||||
|
||||
.TP
|
||||
.B complete.all.projects=yes
|
||||
May be yes or no, and determines whether the tab completion scripts consider all the
|
||||
project names you have used, or just the ones used in active tasks.
|
||||
May be yes or no, and determines whether the tab completion scripts consider all
|
||||
the project names you have used, or just the ones used in active tasks. The
|
||||
default value is "no".
|
||||
|
||||
.TP
|
||||
.B complete.all.tags=yes
|
||||
May be yes or no, and determines whether the tab completion scripts consider all the
|
||||
tag names you have used, or just the ones used in active tasks.
|
||||
May be yes or no, and determines whether the tab completion scripts consider all
|
||||
the tag names you have used, or just the ones used in active tasks. The default
|
||||
value is "no".
|
||||
|
||||
.TP
|
||||
.B search.case.sensitive=yes
|
||||
May be yes or no, and determines whether keyword lookup and substitutions on the
|
||||
description and annotations are done in a case sensitive way. Defaults to yes.
|
||||
|
||||
.TP
|
||||
.B _forcecolor=no
|
||||
Task shuts off color automatically when the output is not sent directly to a
|
||||
a TTY. For example, this command:
|
||||
|
||||
.RS
|
||||
.RS
|
||||
$ task list > file
|
||||
.RE
|
||||
|
||||
will not use any color. To override this, use:
|
||||
|
||||
.RS
|
||||
$ task rc._forcecolor=yes list > file
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B blanklines=yes
|
||||
Turning this value off causes task to generate a more vertically compact output.
|
||||
|
||||
.TP
|
||||
.B shell.prompt=task>
|
||||
The task shell command uses this value as a prompt. You can change it to any
|
||||
string you like.
|
||||
|
||||
.TP
|
||||
.B active.indicator=*
|
||||
The character or string to show in the active column. Defaults to *.
|
||||
|
||||
.TP
|
||||
.B tag.indicator=+
|
||||
The character or string to show in the tag_indicator column. Defaults to +.
|
||||
|
||||
.TP
|
||||
.B recurrence.indicator=R
|
||||
The character or string to show in the recurrence_indicator column. Defaults to R.
|
||||
|
||||
.TP
|
||||
.B debug=off
|
||||
Task has a debug mode that causes diagnostic output to be displayed. Typically
|
||||
this is not something anyone would want, but when reporting a bug, debug output
|
||||
can be useful. It can also help explain how the command line is being parsed,
|
||||
but the information is displayed in a developer-friendly, not a user-friendly
|
||||
way.
|
||||
|
||||
.TP
|
||||
.B alias.rm=delete
|
||||
Task supports command aliases. This alias provides an alternate name (rm) for
|
||||
the delete command. You can use aliases to provide alternate names for any of
|
||||
task's commands.
|
||||
|
||||
.SS DATES
|
||||
|
||||
.TP
|
||||
.B dateformat=m/d/Y
|
||||
This is a string of characters that define how task formats dates. The default value is: m/d/Y.
|
||||
The string should contain the characters
|
||||
.TP
|
||||
.B dateformat.report=m/d/Y
|
||||
.TP
|
||||
.B dateformat.holiday=YMD
|
||||
.TP
|
||||
.B report.X.dateformat=m/d/Y
|
||||
This is a string of characters that define how task formats date values. The
|
||||
precedence order for the configuration variable is report.X.dateformat then
|
||||
reportdateformat then dateformat. While report.X.dateformat only formats the
|
||||
due date in reports, reportdateformat formats the due date both in reports
|
||||
and "task info". If both of these are not set then dateformat will be applied
|
||||
to the due date. Entered dates as well as all other displayed dates in reports
|
||||
are formatted according to dateformat.
|
||||
|
||||
The default value is: m/d/Y. The string should contain the characters:
|
||||
|
||||
.RS
|
||||
m minimal-digit month, for example 1 or 12
|
||||
.RS
|
||||
m minimal-digit month, for example 1 or 12
|
||||
.br
|
||||
d minimal-digit day, for example 1 or 30
|
||||
d minimal-digit day, for example 1 or 30
|
||||
.br
|
||||
y two-digit year, for example 09
|
||||
y two-digit year, for example 09
|
||||
.br
|
||||
D two-digit day, for example 01 or 30
|
||||
D two-digit day, for example 01 or 30
|
||||
.br
|
||||
M two-digit month, for example 01 or 12
|
||||
M two-digit month, for example 01 or 12
|
||||
.br
|
||||
Y four-digit year, for example 2009
|
||||
Y four-digit year, for example 2009
|
||||
.br
|
||||
a short name of weekday, for example Mon or Wed
|
||||
.br
|
||||
A long name of weekday, for example Monday or Wednesday
|
||||
.br
|
||||
b short name of month, for example Jan or Aug
|
||||
.br
|
||||
B long name of month, for example January or August
|
||||
.br
|
||||
V weeknumber, for example 03 or 37
|
||||
.RE
|
||||
.RE
|
||||
|
||||
The string may also contain other characters to act as spacers, or formatting. Examples for other
|
||||
variable values:
|
||||
.RS
|
||||
The string may also contain other characters to act as spacers, or formatting.
|
||||
Examples for other values of dateformat:
|
||||
.RE
|
||||
|
||||
.RS
|
||||
.RS
|
||||
.br
|
||||
d/m/Y would output 24/7/2009
|
||||
d/m/Y would use for input and output 24/7/2009
|
||||
.br
|
||||
YMD would output 20090724
|
||||
yMD would use for input and output 090724
|
||||
.br
|
||||
m-d-y would output 07-24-09
|
||||
M-D-Y would use for input and output 07-24-2009
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.RS
|
||||
Examples for other values of reportdateformat:
|
||||
.RE
|
||||
|
||||
.RS
|
||||
.RS
|
||||
.br
|
||||
a D b Y (V) would do an output as "Fri 24 Jul 2009 (30)"
|
||||
.br
|
||||
A, B D, Y would do an output as "Friday, July 24, 2009"
|
||||
.br
|
||||
vV a Y-M-D would do an output as "v30 Fri 2009-07.24"
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B weekstart=Sunday
|
||||
Determines the day a week starts. Valid values are Sunday or Monday only.
|
||||
Determines the day a week starts. Valid values are Sunday or Monday only. The
|
||||
default value is "Sunday".
|
||||
|
||||
.TP
|
||||
.B displayweeknumber=yes
|
||||
Determines if week numbers are displayed when using the "task calendar" command.
|
||||
The week number is dependent on the day a week starts.
|
||||
The week number is dependent on the day a week starts. The default value is
|
||||
"yes".
|
||||
|
||||
.TP
|
||||
.B due=7
|
||||
This is the number of days into the future that define when a task is considered due,
|
||||
and is colored accordingly. Defaults to 7.
|
||||
This is the number of days into the future that define when a task is
|
||||
considered due, and is colored accordingly. The default value is 7.
|
||||
|
||||
.TP
|
||||
.B monthsperline=2
|
||||
Determines how many months the "task calendar" command renders across the screen.
|
||||
Defaults to however many will fit. If more months that will fit are specified,
|
||||
task will only show as many that will fit.
|
||||
.B calendar.details=sparse
|
||||
If set to full running "task calendar" will display the details of tasks with
|
||||
due dates that fall into the calendar period. The corresponding days will be
|
||||
color-coded in the calendar. If set to sparse only the corresponding days will
|
||||
be color coded and no details will be displayed. The displaying of due dates
|
||||
with details is turned off by setting the variable to none. The default value
|
||||
is "sparse".
|
||||
|
||||
.TP
|
||||
.B calendar.details.report=list
|
||||
The report to run when displaying the details of tasks with due date when
|
||||
running the "task calendar" command. The default value is "list".
|
||||
|
||||
.TP
|
||||
.B calendar.holidays=full
|
||||
If set to full running "task calendar" will display holidays in the calendar by
|
||||
color-coding the corresponding days. A detailed list with the dates and names
|
||||
of the holidays is also shown. If set to sparse only the days are color-coded
|
||||
and no details on the holidays will be displayed. The displaying of holidays is
|
||||
turned off by setting the variable to none. The default value is "none".
|
||||
|
||||
.TP
|
||||
.B Holidays
|
||||
Holidays are entered either directly in the .taskrc file or via an include file
|
||||
that is specified in .taskrc. For each holiday the name and the date is
|
||||
required to be given:
|
||||
|
||||
.RS
|
||||
.RS
|
||||
.br
|
||||
holiday.towel.name=Day of the towel
|
||||
.br
|
||||
holiday.towel.date=20100525
|
||||
.br
|
||||
holiday.sysadmin.name=System Administrator Appreciation Day
|
||||
.br
|
||||
holiday.sysadmin.date=20100730
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.RS
|
||||
Dates are to be entered according to the setting in the dateformat.holiday
|
||||
variable.
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B monthsperline=3
|
||||
Determines how many months the "task calendar" command renders across the
|
||||
screen. Defaults to however many will fit. If more months than will fit are
|
||||
specified, task will only show as many that will fit.
|
||||
|
||||
.SS COLOR CONTROLS
|
||||
|
||||
@@ -207,12 +419,12 @@ use dashes (-----) to underline column headings.
|
||||
.TP
|
||||
.B fontunderline=on
|
||||
Determines if font underlines or ASCII dashes should be used to underline
|
||||
headers.
|
||||
headers, even when color is enabled.
|
||||
|
||||
Task has a number of coloration rules. They correspond to a particular attribute
|
||||
of a task, such as it being due, or being active, and specifies the automatic
|
||||
coloring of that task. A list of valid color, depending on your terminal, can be
|
||||
obtained by running the command
|
||||
Task has a number of coloration rules. They correspond to a particular
|
||||
attribute of a task, such as it being due, or being active, and specifies the
|
||||
automatic coloring of that task. A list of valid colors, depending on your
|
||||
terminal, can be obtained by running the command:
|
||||
|
||||
.RS
|
||||
.B task color
|
||||
@@ -224,48 +436,53 @@ The coloration rules and their defaults are:
|
||||
|
||||
.RS
|
||||
.RS
|
||||
.B color.overdue=bold_red
|
||||
.B color.overdue=bold red
|
||||
The color for overdue tasks.
|
||||
.br
|
||||
.B color.due=bold_yellow
|
||||
.B color.due.today=bold magenta
|
||||
The color of tasks due today.
|
||||
.br
|
||||
.B color.due=bold yellow
|
||||
The color of due tasks.
|
||||
.br
|
||||
.B color.pri.H=bold
|
||||
The color of priority:H tasks.
|
||||
.br
|
||||
.B color.pri.M=on_yellow
|
||||
The color of priority:M tasks.
|
||||
.B color.pri.M=on yellow
|
||||
The color of priority:M tasks. No default value.
|
||||
.br
|
||||
.B color.pri.L=on_green
|
||||
The color of priority:L tasks.
|
||||
.B color.pri.L=on green
|
||||
The color of priority:L tasks. No default value.
|
||||
.br
|
||||
.B color.pri.none=white on_blue
|
||||
The color of priority: tasks.
|
||||
.B color.pri.none=white on blue
|
||||
The color of priority: tasks. No default value.
|
||||
.br
|
||||
.B color.active=bold_cyan
|
||||
.B color.active=bold cyan
|
||||
The color of active tasks.
|
||||
.br
|
||||
.B color.tagged=yellow
|
||||
The color of tagged tasks.
|
||||
.br
|
||||
.B color.recurring=on_red
|
||||
.B color.recurring=on red
|
||||
The color for recurring tasks.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.RS
|
||||
The value for the coloration rules may be one optional foreground color and one optional
|
||||
color. For example, the value may be
|
||||
.RE
|
||||
|
||||
To disable a coloration rule for which there is a default, set the value to
|
||||
nothing, for example:
|
||||
.RS
|
||||
.RS
|
||||
bold_red on_bright_yellow
|
||||
.B color.tagged=
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.RS
|
||||
Certain attributes like tags, projects and keywords can also have their own coloration rules.
|
||||
See the task-color(5) man pages for color details.
|
||||
.RE
|
||||
|
||||
.RS
|
||||
Certain attributes like tags, projects and keywords can have their own
|
||||
coloration rules.
|
||||
.RE
|
||||
|
||||
.RS
|
||||
@@ -274,24 +491,58 @@ Certain attributes like tags, projects and keywords can also have their own colo
|
||||
Colors any task that has the tag X.
|
||||
|
||||
.TP
|
||||
.B color.project.X=on_green
|
||||
.B color.project.X=on green
|
||||
Colors any task assigned to project X.
|
||||
|
||||
.TP
|
||||
.B color.keyword.X=on_blue
|
||||
Colors any task where the description contains X.
|
||||
.B color.keyword.X=on blue
|
||||
Colors any task where the description or any annotation contains X.
|
||||
|
||||
.TP
|
||||
.B color.header=green
|
||||
Colors any of the messages printed prior to the report output.
|
||||
|
||||
.TP
|
||||
.B color.message=green
|
||||
Colors any of the messages printed after the report output.
|
||||
|
||||
.TP
|
||||
.B color.footnote=green
|
||||
Colors any of the messages printed last.
|
||||
|
||||
.TP
|
||||
.B color.calendar.today=black on cyan
|
||||
Color of today in calendar.
|
||||
|
||||
.TP
|
||||
.B color.calendar.due=black on green
|
||||
Color of days with due tasks in calendar.
|
||||
|
||||
.TP
|
||||
.B color.calendar.due.today=black on magenta
|
||||
Color of today with due tasks in calendar.
|
||||
|
||||
.TP
|
||||
.B color.calendar.overdue=black on red
|
||||
Color of days with overdue tasks in calendar.
|
||||
|
||||
.TP
|
||||
.B color.calendar.weekend=bright white on black
|
||||
Color of weekend days in calendar.
|
||||
|
||||
.TP
|
||||
.B color.calendar.holiday=black on bright yellow
|
||||
Color of holidays in calendar.
|
||||
|
||||
.TP
|
||||
.B color.calendar.weeknumber=black on white
|
||||
Color of weeknumbers in calendar.
|
||||
.RE
|
||||
|
||||
.RS
|
||||
It is possible to apply a specific color to every other task in a report,
|
||||
which can make it easier to visually separate tasks. This is especially
|
||||
useful when tasks are displayed over multiple lines due to long descriptions
|
||||
or annotations.
|
||||
.TP
|
||||
.B color.alternate=on rgb253
|
||||
Color of alternate tasks.
|
||||
.RE
|
||||
|
||||
.SS SHADOW FILE
|
||||
@@ -299,11 +550,12 @@ Colors any of the messages printed last.
|
||||
.TP
|
||||
.B
|
||||
shadow.file=$HOME/.task/shadow.txt
|
||||
If specified, designates a file path that will be automatically written to by task,
|
||||
whenever the task database changes. In other words, it is automatically kept up to date.
|
||||
The shadow.command configuration variable is used to determine which report is written
|
||||
to the shadow file. There is no color used in the shadow file. This feature can be useful
|
||||
in maintaining a current file for use by programs like GeekTool, Conky or Samurize.
|
||||
If specified, designates a file path that will be automatically written to by
|
||||
task, whenever the task database changes. In other words, it is automatically
|
||||
kept up to date. The shadow.command configuration variable is used to determine
|
||||
which report is written to the shadow file. There is no color used in the
|
||||
shadow file. This feature can be useful in maintaining a current file for use by
|
||||
programs like GeekTool, Conky or Samurize.
|
||||
|
||||
.TP
|
||||
.B
|
||||
@@ -327,20 +579,20 @@ file is updated by some task command.
|
||||
default.project=foo
|
||||
Provides a default project name for the
|
||||
.I task add
|
||||
command.
|
||||
command, if you don't specify one. The default is blank.
|
||||
|
||||
.TP
|
||||
.B
|
||||
default.priority=M
|
||||
Provides a default priority for the
|
||||
.I task add
|
||||
command.
|
||||
command, if you don't specify one. The default is blank.
|
||||
|
||||
.TP
|
||||
.B
|
||||
default.command=list
|
||||
Provides a default command that is run every time task is invoked with no arguments.
|
||||
For example, if set to:
|
||||
Provides a default command that is run every time task is invoked with no
|
||||
arguments. For example, if set to:
|
||||
|
||||
.RS
|
||||
.RS
|
||||
@@ -349,8 +601,8 @@ default.command=list project:foo
|
||||
.RE
|
||||
|
||||
.RS
|
||||
then task will run the "list project:foo" command if no command is specified. This means that
|
||||
by merely typing
|
||||
then task will run the "list project:foo" command if no command is specified.
|
||||
This means that by merely typing
|
||||
.RE
|
||||
|
||||
.RS
|
||||
@@ -384,24 +636,41 @@ The description for report X when running the "task help" command.
|
||||
.TP
|
||||
.B report.X.columns
|
||||
The columns that will be used when generating the report X. Valid columns are:
|
||||
id, uuid, project, priority, entry, start, due, recur, recur_ind, age, age_compact,
|
||||
active, tags, description, description_only. The IDs are separated by commas.
|
||||
id, uuid, project, priority, entry, start, due, recur, recur_indicator, age,
|
||||
age_compact, active, tags, tag_indicator, description, description_only,
|
||||
countdown, countdown_compact.
|
||||
The IDs are separated by commas.
|
||||
|
||||
.TP
|
||||
.B report.X.labels
|
||||
The labels for each column that will be used when generating report X. The labels
|
||||
are a comma separated list.
|
||||
The labels for each column that will be used when generating report X. The
|
||||
labels are a comma separated list.
|
||||
|
||||
.TP
|
||||
.B report.X.sort
|
||||
The sort order of the tasks in the generated report X. The sort order is specified
|
||||
by using the column ids post-fixed by a "+" for ascending sort order or a "-" for
|
||||
descending sort order. The sort IDs are separated by commas
|
||||
The sort order of the tasks in the generated report X. The sort order is
|
||||
specified by using the column ids post-fixed by a "+" for ascending sort order
|
||||
or a "-" for descending sort order. The sort IDs are separated by commas
|
||||
|
||||
.TP
|
||||
.B report.X.filter
|
||||
This adds a filter to the report X so that only tasks matching the filter criteria
|
||||
are displayed in the generated report.
|
||||
This adds a filter to the report X so that only tasks matching the filter
|
||||
criteria are displayed in the generated report.
|
||||
|
||||
.TP
|
||||
.B report.X.dateformat
|
||||
This adds a dateformat to the report X that will be used by the "due date"
|
||||
column. If it is not set then reportdateformat and dateformat will be used in
|
||||
this order. See the
|
||||
.B DATES
|
||||
section for details on the sequence placeholders.
|
||||
|
||||
.TP
|
||||
.B report.X.annotations
|
||||
This adds the possibility to control the output of annotations for a task in a
|
||||
report. See the
|
||||
.B annotations
|
||||
variable for details on the possible values.
|
||||
|
||||
.TP
|
||||
.B report.X.limit
|
||||
@@ -409,7 +678,8 @@ An optional value to a report limiting the number of displayed tasks in the
|
||||
generated report.
|
||||
|
||||
.TP
|
||||
Task comes with a number of predefined reports in its default configuration file. These reports are:
|
||||
Task comes with a number of predefined reports in its default configuration
|
||||
file. These reports are:
|
||||
|
||||
.TP
|
||||
.B long
|
||||
@@ -421,6 +691,10 @@ Lists all tasks matching the specified criteria.
|
||||
|
||||
.TP
|
||||
.B ls
|
||||
Short listing of all tasks matching the specified criteria.
|
||||
|
||||
.TP
|
||||
.B minimal
|
||||
Minimal listing of all tasks matching the specified criteria.
|
||||
|
||||
.TP
|
||||
@@ -462,7 +736,7 @@ Lists all tasks with upcoming due dates matching the specified criteria.
|
||||
.SH "CREDITS & COPYRIGHTS"
|
||||
task was written by P. Beckingham <paul@beckingham.net>.
|
||||
.br
|
||||
Copyright (C) 2006 \- 2009 P. Beckingham
|
||||
Copyright (C) 2006 \- 2010 P. Beckingham
|
||||
|
||||
This man page was originally written by Federico Hernandez.
|
||||
|
||||
@@ -471,7 +745,9 @@ http://www.gnu.org/licenses/gpl-2.0.txt for more information.
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR task(1),
|
||||
.BR task-tutorial(5)
|
||||
.BR task-tutorial(5),
|
||||
.BR task-faq(5)
|
||||
.BR task-color(5)
|
||||
|
||||
For more information regarding task, the following may be referenced:
|
||||
|
||||
@@ -481,7 +757,7 @@ The official site at
|
||||
|
||||
.TP
|
||||
The official code repository at
|
||||
<http://github.com/pbeckingham/task/>
|
||||
<git://tasktools.org/task.git/>
|
||||
|
||||
.TP
|
||||
You can contact the project by writing an email to
|
||||
|
||||
34
doc/misc/script-color.txt
Normal file
34
doc/misc/script-color.txt
Normal file
@@ -0,0 +1,34 @@
|
||||
Hello. This is a demonstration of the
|
||||
task program color capabilities coming
|
||||
in version 1.9.
|
||||
|
||||
task color The color command shows the various
|
||||
supported colors. For this you will
|
||||
need an xterm with 256-color support,
|
||||
or an equivalent.
|
||||
|
||||
This demo uses iTerm running on Snow
|
||||
Leopard.
|
||||
|
||||
task add Prepare 1.9 for release Let's create a few tasks, to illustrate
|
||||
task add Update the various docs the features. Five should be enough.
|
||||
task add Run the regression tests
|
||||
task add Make the packages
|
||||
task add Upload to distributions
|
||||
|
||||
--- NOTES
|
||||
|
||||
16-color mode
|
||||
upgrade
|
||||
blending
|
||||
alternate lines
|
||||
|
||||
--- NOTES
|
||||
|
||||
task ls Okay, let's color any tasks that
|
||||
mention tests a nice medium blue.
|
||||
|
||||
echo 'color.keyword.test=color23' >> ~/.taskrc
|
||||
|
||||
|
||||
|
||||
40
doc/misc/script-hooks-2.txt
Normal file
40
doc/misc/script-hooks-2.txt
Normal file
@@ -0,0 +1,40 @@
|
||||
$ # Q: What is a formatting hook?
|
||||
$ # A: Lua code that modifies task output at run time.
|
||||
$
|
||||
$ cat > hooks.lua
|
||||
|
||||
-- Make ID not show up
|
||||
function id (name, value)
|
||||
return "(shhh - it's a secret)", 0, nil
|
||||
end
|
||||
|
||||
-- Decorate the UUID
|
||||
function uuid (name, value)
|
||||
return '<<<' .. value .. '>>>', 0, nil
|
||||
end
|
||||
|
||||
^D
|
||||
|
||||
$ # Q: What is a command hook?
|
||||
$ # A: Lua code that changes the way commands work.
|
||||
$
|
||||
$ cat >> hooks.lua
|
||||
|
||||
-- Disable tags
|
||||
function notags ()
|
||||
return 1, 'Tags have been disabled'
|
||||
end
|
||||
|
||||
^D
|
||||
|
||||
$
|
||||
$ task config -- hook.format-id ~/demo/hooks.lua:id
|
||||
$ task config -- hook.format-uuid ~/demo/hooks.lua:uuid
|
||||
$ task config -- hook.pre-tag ~/demo/hooks.lua:notags
|
||||
$ task list
|
||||
$ task add Demonstrate formatting hooks
|
||||
$ task 1 info
|
||||
$ task config hooks on
|
||||
$ task 1 info
|
||||
$ task 1 +try_to_tag
|
||||
|
||||
33
doc/misc/script-hooks.txt
Normal file
33
doc/misc/script-hooks.txt
Normal file
@@ -0,0 +1,33 @@
|
||||
$
|
||||
$ # Task now has Lua 5.1.4 built in.
|
||||
$
|
||||
$ task version
|
||||
$ cat > hooks.lua
|
||||
function foo ()
|
||||
print ("Hello from Lua")
|
||||
return 0, nil
|
||||
end
|
||||
^D
|
||||
$
|
||||
$ # Task can call into Lua at many points during execution.
|
||||
$ # This one is called immediately before task quits.
|
||||
$
|
||||
$ task rc.hook.pre-exit=~/hooks.lua:foo version
|
||||
$
|
||||
$ # While task is calling Lua code, the Lua can also call
|
||||
$ # back into a task API, for information.
|
||||
$
|
||||
$ cat > hooks.lua
|
||||
function foo ()
|
||||
print "Lua version is " .. task_lua_version ())
|
||||
print "Task version is " .. task_version ())
|
||||
return 0, nil
|
||||
end
|
||||
^D
|
||||
$
|
||||
$ cat >> .taskrc
|
||||
hook.pre-exit=~/hooks.lua:foo
|
||||
^D
|
||||
$
|
||||
$ task version
|
||||
|
||||
1
doc/rc/dark-16.theme
Normal file
1
doc/rc/dark-16.theme
Normal file
@@ -0,0 +1 @@
|
||||
# Sample task 1.9 (or later) color theme
|
||||
1
doc/rc/dark-256.theme
Normal file
1
doc/rc/dark-256.theme
Normal file
@@ -0,0 +1 @@
|
||||
# Sample task 1.9 (or later) color theme
|
||||
34
doc/rc/holidays-SE.rc
Normal file
34
doc/rc/holidays-SE.rc
Normal file
@@ -0,0 +1,34 @@
|
||||
holiday.nyårsdagen.name=Nyårsdagen
|
||||
holiday.nyårsdagen.date=20100101
|
||||
holiday.trettondedagjul.name=Trettondedag jul
|
||||
holiday.trettondedagjul.date=20100106
|
||||
holiday.långfredagen.name=Långfredagen
|
||||
holiday.långfredagen.date=20100402
|
||||
holiday.påskdagen.name=Påskdagen
|
||||
holiday.påskdagen.date=20100404
|
||||
holiday.annandagpåsk.name=Annandag påsk
|
||||
holiday.annandagpåsk.date=20100405
|
||||
holiday.valborgmässoafton.name=Valborgmässoafton
|
||||
holiday.valborgmässoafton.date=20100430
|
||||
holiday.förstamaj.name=Första maj
|
||||
holiday.förstamaj.date=20100501
|
||||
holiday.kristihimmelfärdsdag.name=Kristi Himmelsfärdsdag
|
||||
holiday.kristihimmelfärdsdag.date=20100513
|
||||
holiday.pingstdagen.name=Pingstdagen
|
||||
holiday.pingstdagen.date=20100523
|
||||
holiday.nationaldagen.name=Nationaldagen
|
||||
holiday.nationaldagen.date=20100606
|
||||
holiday.midsommarafton.name=Midsommarafton
|
||||
holiday.midsommarafton.date=20100625
|
||||
holiday.midsommardagen.name=Midsommardagen
|
||||
holiday.midsommardagen.date=20100626
|
||||
holiday.allahelgonsdag.name=Alla Helgons Dag
|
||||
holiday.allahelgonsdag.date=20101106
|
||||
holiday.julafton.name=Julafton
|
||||
holiday.julafton.date=20101224
|
||||
holiday.juldagen.name=Juldagen
|
||||
holiday.juldagen.date=20101225
|
||||
holiday.annandagjul.name=Annandag jul
|
||||
holiday.annandagjul.date=20101226
|
||||
holiday.nyårsafton.name=Nyårsafton
|
||||
holiday.nyårsafton.date=20101231
|
||||
28
doc/rc/holidays-US.rc
Normal file
28
doc/rc/holidays-US.rc
Normal file
@@ -0,0 +1,28 @@
|
||||
holiday.newyearsday.name=New Years Day
|
||||
holiday.newyearsday.date=20100101
|
||||
holiday.martinlutherkingday.name=Martin Luther King Day
|
||||
holiday.martinlutherkingday.date=20100118
|
||||
holiday.presidentsday.name=Presidents Day
|
||||
holiday.presidentsday.date=20100215
|
||||
holiday.patriotsday.name=Patriots Day
|
||||
holiday.patriotsday.date=20100419
|
||||
holiday.memorialday.name=Memorial Day
|
||||
holiday.memorialday.date=20100531
|
||||
holiday.independenceday.name=Independence Day
|
||||
holiday.independenceday.date=20100704
|
||||
holiday.independenceday2.name=Independence Day observed
|
||||
holiday.independenceday2.date=20100705
|
||||
holiday.laborday.name=Labor Day
|
||||
holiday.laborday.date=20100906
|
||||
holiday.columbusday.name=Columbus Day
|
||||
holiday.columbusday.date=20101011
|
||||
holiday.veteransdays.name=Veterans Day
|
||||
holiday.veteransdays.date=20101111
|
||||
holiday.thanksgiving.name=Thanksgiving Day
|
||||
holiday.thanksgiving.date=20101125
|
||||
holiday.christmaseve.name=Christmas Eve
|
||||
holiday.christmaseve.date=20101224
|
||||
holiday.christmasday.name=Christmas Day
|
||||
holiday.christmasday.date=20101225
|
||||
holiday.newyearseve.name=New Years Eve
|
||||
holiday.newyearseve.date=20101231
|
||||
1
doc/rc/light-16.theme
Normal file
1
doc/rc/light-16.theme
Normal file
@@ -0,0 +1 @@
|
||||
# Sample task 1.9 (or later) color theme
|
||||
1
doc/rc/light-256.theme
Normal file
1
doc/rc/light-256.theme
Normal file
@@ -0,0 +1 @@
|
||||
# Sample task 1.9 (or later) color theme
|
||||
@@ -46,7 +46,7 @@
|
||||
214 ghistory
|
||||
215 import
|
||||
216 info
|
||||
|
||||
217 prepend
|
||||
218 overdue
|
||||
219 projects
|
||||
220 start
|
||||
@@ -99,57 +99,20 @@
|
||||
# 5xx Colors
|
||||
500 bold
|
||||
501 underline
|
||||
502 bold_underline
|
||||
503 black
|
||||
504 red
|
||||
505 green
|
||||
506 yellow
|
||||
507 blue
|
||||
508 magenta
|
||||
509 cyan
|
||||
510 white
|
||||
511 bold_black
|
||||
512 bold_red
|
||||
513 bold_green
|
||||
514 bold_yellow
|
||||
515 bold_blue
|
||||
516 bold_magenta
|
||||
517 bold_cyan
|
||||
518 bold_white
|
||||
519 underline_black
|
||||
520 underline_red
|
||||
521 underline_green
|
||||
522 underline_yellow
|
||||
523 underline_blue
|
||||
524 underline_magenta
|
||||
525 underline_cyan
|
||||
526 underline_white
|
||||
527 bold_underline_black
|
||||
528 bold_underline_red
|
||||
529 bold_underline_green
|
||||
530 bold_underline_yellow
|
||||
531 bold_underline_blue
|
||||
532 bold_underline_magenta
|
||||
533 bold_underline_cyan
|
||||
534 bold_underline_white
|
||||
535 on_black
|
||||
536 on_red
|
||||
537 on_green
|
||||
538 on_yellow
|
||||
539 on_blue
|
||||
540 on_magenta
|
||||
541 on_cyan
|
||||
542 on_white
|
||||
543 on_bright_black
|
||||
544 on_bright_red
|
||||
545 on_bright_green
|
||||
546 on_bright_yellow
|
||||
547 on_bright_blue
|
||||
548 on_bright_magenta
|
||||
549 on_bright_cyan
|
||||
550 on_bright_white
|
||||
551 off
|
||||
552 Unknown color name
|
||||
502 on
|
||||
503 bright
|
||||
|
||||
504 black
|
||||
505 red
|
||||
506 green
|
||||
507 yellow
|
||||
508 blue
|
||||
509 magenta
|
||||
510 cyan
|
||||
511 white
|
||||
|
||||
520 off
|
||||
521 Unknown color name
|
||||
|
||||
# 6xx Config
|
||||
|
||||
|
||||
@@ -1,281 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
|
||||
Thank you for taking a look at task!
|
||||
|
||||
Task is a GTD, todo list, task management, command line utility with a multitude
|
||||
of features. It is a portable, well supported, very active project, and it is
|
||||
Open Source. Task has binary distributions, online documentation, demonstration
|
||||
movies, and you'll find all the details at the site:
|
||||
|
||||
http://taskwarrior.org
|
||||
|
||||
At the site you'll find a wiki, discussion forums, downloads, news and more.
|
||||
|
||||
|
||||
Your contributions are especially welcome. Whether it comes in the form of
|
||||
code patches, ideas, discussion, bug reports or just encouragement, your input
|
||||
is needed.
|
||||
|
||||
Please send your support questions and code patches to:
|
||||
|
||||
support@taskwarrior.org
|
||||
|
||||
Consider joining taskwarrior.org and participating in the future of task.
|
||||
|
||||
---
|
||||
1
package-config/osx/task.pmdoc/01local-contents.xml
Normal file
1
package-config/osx/task.pmdoc/01local-contents.xml
Normal file
@@ -0,0 +1 @@
|
||||
<pkg-contents spec="1.12"><f n="local" o="root" g="staff" p="16877" pt="/Users/paul/task-1.9.0.git/package-config/osx/local" m="false" t="file"><f n="bin" o="root" g="wheel" p="16877"><f n="task" o="root" g="wheel" p="33261"><mod>mode</mod><mod>owner</mod></f><mod>owner</mod></f><f n="share" o="root" g="wheel" p="16877"><f n="doc" o="root" g="wheel" p="16877"><f n="task" o="root" g="wheel" p="16877"><f n="AUTHORS" o="root" g="wheel" p="33188"><mod>mode</mod><mod>owner</mod></f><f n="ChangeLog" o="root" g="wheel" p="33188"><mod>mode</mod><mod>owner</mod></f><f n="COPYING" o="root" g="wheel" p="33188"><mod>mode</mod><mod>owner</mod></f><f n="NEWS" o="root" g="wheel" p="33188"><mod>mode</mod><mod>owner</mod></f><f n="README" o="root" g="wheel" p="33188"><mod>mode</mod><mod>owner</mod></f><f n="scripts" o="root" g="wheel" p="16877"><f n="bash" o="root" g="wheel" p="16877"><f n="task_completion.sh" o="root" g="wheel" p="33188"><mod>mode</mod><mod>group</mod><mod>owner</mod></f><mod>mode</mod><mod>owner</mod></f><f n="vim" o="root" g="wheel" p="16877"><f n="ftdetect" o="root" g="wheel" p="16877"><f n="task.vim" o="root" g="wheel" p="33188"><mod>mode</mod></f><mod>mode</mod></f><f n="README" o="root" g="wheel" p="33188"><mod>mode</mod></f><f n="syntax" o="root" g="wheel" p="16877"><f n="taskdata.vim" o="root" g="wheel" p="33188"><mod>mode</mod></f><f n="taskedit.vim" o="root" g="wheel" p="33188"><mod>mode</mod></f><f n="taskrc.vim" o="root" g="wheel" p="33188"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><f n="zsh" o="root" g="wheel" p="16877"><f n="_task" o="root" g="wheel" p="33188"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod><mod>owner</mod></f><mod>mode</mod><mod>owner</mod></f><mod>mode</mod><mod>owner</mod></f><f n="man" o="root" g="wheel" p="16877"><f n="man1" o="root" g="wheel" p="16877"><f n="task.1" o="root" g="wheel" p="33188"><mod>mode</mod></f><mod>mode</mod></f><f n="man5" o="root" g="wheel" p="16877"><f n="task-color.5" o="root" g="wheel" p="33188"><mod>mode</mod></f><f n="task-faq.5" o="root" g="wheel" p="33188"><mod>mode</mod></f><f n="task-tutorial.5" o="root" g="wheel" p="33188"><mod>mode</mod></f><f n="taskrc.5" o="root" g="wheel" p="33188"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod><mod>owner</mod></f><mod>owner</mod></f></pkg-contents>
|
||||
1
package-config/osx/task.pmdoc/01local.xml
Normal file
1
package-config/osx/task.pmdoc/01local.xml
Normal file
@@ -0,0 +1 @@
|
||||
<pkgref spec="1.12" uuid="3BCF9CAB-ED33-4182-AC52-29B9F8FF9B87"><config><identifier>com.beckingham.task190Beta3.local.pkg</identifier><version>1.0</version><description/><post-install type="none"/><requireAuthorization/><installFrom>/Users/paul/task-1.9.0.git/package-config/osx/local</installFrom><installTo mod="true">/usr/local</installTo><flags><followSymbolicLinks/></flags><packageStore type="internal"/><mod>installTo</mod><mod>installTo.path</mod><mod>parent</mod></config><contents><file-list>01local-contents.xml</file-list><filter>/CVS$</filter><filter>/\.svn$</filter><filter>/\.cvsignore$</filter><filter>/\.cvspass$</filter><filter>/\.DS_Store$</filter></contents></pkgref>
|
||||
@@ -1 +0,0 @@
|
||||
<pkg-contents spec="1.12"><f n="task" o="paul" g="staff" p="33261" pt="/Users/paul/task.git/package-config/osx/binary/task" m="false" t="file"/></pkg-contents>
|
||||
@@ -1 +0,0 @@
|
||||
<pkgref spec="1.12" uuid="C71026FD-E252-42CD-89C3-2F6F087AAF17"><config><identifier>com.beckingham.task180.task.pkg</identifier><version>1.8.0</version><description></description><post-install type="none"/><requireAuthorization/><installFrom mod="true">/Users/paul/task.git/package-config/osx/binary/task</installFrom><installTo mod="true" relocatable="true">/usr/local/bin</installTo><flags><followSymbolicLinks/></flags><packageStore type="internal"></packageStore><mod>parent</mod><mod>locationType</mod><mod>relocatable</mod><mod>version</mod><mod>installTo.path</mod><mod>installTo</mod></config><contents><file-list>01task-contents.xml</file-list><filter>/CVS$</filter><filter>/\.svn$</filter><filter>/\.cvsignore$</filter><filter>/\.cvspass$</filter><filter>/\.DS_Store$</filter></contents></pkgref>
|
||||
@@ -1 +1 @@
|
||||
<pkmkdoc spec="1.12"><properties><title>Task 1.8.0</title><build>/Users/paul/Desktop/task-1.8.0.pkg</build><organization>com.beckingham</organization><userSees ui="easy"/><min-target os="3"/><domain anywhere="true" system="true"/></properties><distribution><versions min-spec="1.000000"/><scripts></scripts></distribution><contents><choice title="task" id="choice0" starts_selected="true" starts_enabled="true" starts_hidden="false"><pkgref id="com.beckingham.task180.task.pkg"/><choice-reqs><requirement id="tosv" operator="ge" value="'10.5.0'" selected="no" enabled="no" hidden="unchanged" startSelected="unchanged" startEnabled="unchanged" startHidden="unchanged"/></choice-reqs></choice></contents><resources bg-scale="proportional" bg-align="center"><locale lang="en"><resource mod="true" type="license">/Users/paul/task.git/package-config/osx/binary/COPYING.txt</resource><resource mod="true" type="readme">/Users/paul/task.git/package-config/osx/binary/README.txt</resource></locale></resources><flags/><item type="file">01task.xml</item><mod>properties.title</mod><mod>properties.anywhereDomain</mod><mod>properties.systemDomain</mod></pkmkdoc>
|
||||
<pkmkdoc spec="1.12"><properties><title>Task 1.9.0 beta3</title><build>/Users/paul/Desktop/task-1.9.0.beta3-sl.pkg</build><organization>com.beckingham</organization><userSees ui="easy"/><min-target os="3"/><domain anywhere="true" system="true"/></properties><distribution><versions min-spec="1.000000"/><scripts></scripts></distribution><description>Task 1.9.0 beta 3 install for Snow Leopard.</description><contents><choice title="local" id="choice36" starts_selected="true" starts_enabled="true" starts_hidden="false"><pkgref id="com.beckingham.task190Beta3.local.pkg"/></choice></contents><resources bg-scale="proportional" bg-align="center"><locale lang="en"><resource mod="true" type="license">/Users/paul/task-1.9.0.git/package-config/osx/COPYING.txt</resource><resource mod="true" type="welcome">/Users/paul/task-1.9.0.git/package-config/osx/README.txt</resource></locale></resources><requirements><requirement id="tosv" operator="ge" value="'10.6.0'"><message>Task requires Mac OSX 10.6.0 (Snow Leopard) or later.</message></requirement></requirements><flags/><item type="file">01local.xml</item><mod>properties.title</mod><mod>properties.customizeOption</mod><mod>description</mod><mod>properties.anywhereDomain</mod><mod>properties.systemDomain</mod></pkmkdoc>
|
||||
30
package-config/osx/update
Executable file
30
package-config/osx/update
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
|
||||
mkdir -p local/bin
|
||||
mkdir -p local/share/doc/task/scripts/bash
|
||||
mkdir -p local/share/doc/task/scripts/vim/ftdetect
|
||||
mkdir -p local/share/doc/task/scripts/vim/syntax
|
||||
mkdir -p local/share/doc/task/scripts/zsh
|
||||
mkdir -p local/share/man/man1
|
||||
mkdir -p local/share/man/man5
|
||||
|
||||
cp ../../README README.txt
|
||||
cp ../../COPYING COPYING.txt
|
||||
|
||||
cp ../../src/task local/bin/
|
||||
|
||||
cp ../../AUTHORS local/share/doc/task/
|
||||
cp ../../ChangeLog local/share/doc/task/
|
||||
cp ../../COPYING local/share/doc/task/
|
||||
cp ../../NEWS local/share/doc/task/
|
||||
cp ../../README local/share/doc/task/
|
||||
|
||||
cp ../../scripts/bash/* local/share/doc/task/scripts/bash
|
||||
cp ../../scripts/vim/README local/share/doc/task/scripts/vim
|
||||
cp ../../scripts/vim/ftdetect/* local/share/doc/task/scripts/vim/ftdetect
|
||||
cp ../../scripts/vim/syntax/* local/share/doc/task/scripts/vim/syntax
|
||||
cp ../../scripts/zsh/* local/share/doc/task/scripts/zsh
|
||||
|
||||
cp ../../doc/man/*.1 local/share/man/man1
|
||||
cp ../../doc/man/*.5 local/share/man/man5
|
||||
|
||||
@@ -1,3 +1,39 @@
|
||||
task (1.8.5-1ubuntu2) karmic; urgency=low
|
||||
|
||||
* Fixed wrong ChangeLog file
|
||||
|
||||
-- Federico Hernandez <ultrafredde@gmail.com> Sat, 05 Dec 2009 23:58:36 +0100
|
||||
|
||||
task (1.8.5-1ubuntu1) karmic; urgency=low
|
||||
|
||||
* Initial deb package for task bugfix release 1.8.5
|
||||
|
||||
-- Federico Hernandez <ultrafredde@gmail.com> Sat, 05 Dec 2009 23:56:36 +0100
|
||||
|
||||
task (1.8.4-1ubuntu1) karmic; urgency=low
|
||||
|
||||
* Initial deb package for task bugfix release 1.8.4 on karmic koala
|
||||
|
||||
-- Federico Hernandez <ultrafredde@gmail.com> Tue, 17 Nov 2009 13:12:28 +0100
|
||||
|
||||
task (1.8.3-1ubuntu1) karmic; urgency=low
|
||||
|
||||
* Initial deb package for task bugfix release 1.8.3 on karmic koala
|
||||
|
||||
-- Federico Hernandez <ultrafredde@gmail.com> Sat, 31 Oct 2009 22:45:10 +0100
|
||||
|
||||
task (1.8.3-0ubuntu1) jaunty; urgency=low
|
||||
|
||||
* Initial deb package for task bugfix release 1.8.3
|
||||
|
||||
-- Federico Hernandez <ultrafredde@gmail.com> Wed, 21 Oct 2009 23:22:25 +0200
|
||||
|
||||
task (1.8.2-0ubuntu1) jaunty; urgency=low
|
||||
|
||||
* Initial deb package for task bugfix release 1.8.2
|
||||
|
||||
-- Federico Hernandez <ultrafredde@gmail.com> Mon, 07 Sep 2009 11:35:22 +0200
|
||||
|
||||
task (1.8.1-0ubuntu1) jaunty; urgency=low
|
||||
|
||||
* Initial deb package for task bugfix release 1.8.1
|
||||
|
||||
@@ -4,7 +4,7 @@ Priority: optional
|
||||
Maintainer: Federico Hernandez <ultrafredde@gmail.com>
|
||||
XSBC-Original-Maintainer: Federico Hernandez <ultrafredde@gmail.com>
|
||||
Build-Depends: debhelper (>= 7), autotools-dev, libncurses5-dev
|
||||
Standards-Version: 3.8.0.1
|
||||
Standards-Version: 3.8.3
|
||||
Homepage: http://taskwarrior.org
|
||||
|
||||
Package: task
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
This package was debianized by:
|
||||
|
||||
Federico Hernandez <ultrafredde@gmail.com> on Thu, 20 Aug 2009 20:26:33 +0200
|
||||
Federico Hernandez <ultrafredde@gmail.com> on Sat, 05 Dec 2009 23:58:36 +0100
|
||||
|
||||
It was downloaded from:
|
||||
|
||||
@@ -25,13 +25,14 @@ Upstream Authors:
|
||||
Johan Friis
|
||||
Steven de Brouwer
|
||||
Pietro Cerutti
|
||||
Cory Donnelly
|
||||
|
||||
Copyright:
|
||||
|
||||
Copyright 2006 - 2009, Paul Beckingham
|
||||
Copyright 2009 Federico Hernandez
|
||||
Copyright 2006 - 2010, Paul Beckingham
|
||||
Copyright 2009 - 2010 Federico Hernandez
|
||||
Copyright 2009 - 2010 John Florian
|
||||
Copyright 2009 P.C. Shyamshankar
|
||||
Copyright 2009 John Florian
|
||||
|
||||
License:
|
||||
|
||||
@@ -54,6 +55,6 @@ Public License can be found in `/usr/share/common-licenses/GPL-2'.
|
||||
|
||||
The Debian packaging is:
|
||||
|
||||
Copyright (C) 2009, Federico Hernandez <ultrafredde@gmail.com>
|
||||
Copyright (C) 2009 - 2010, Federico Hernandez <ultrafredde@gmail.com>
|
||||
|
||||
and is licensed under the GPL, see above.
|
||||
|
||||
@@ -33,7 +33,7 @@ binary-arch: install
|
||||
dh_installman
|
||||
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
|
||||
rm -rf $(CURDIR)/debian/task/usr/share/doc/task-1.8.5
|
||||
dh_strip
|
||||
dh_compress
|
||||
dh_fixperms
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# bash completion support for task
|
||||
#
|
||||
# Copyright 2009 Federico Hernandez
|
||||
# Copyright 2009-2010 Federico Hernandez
|
||||
# All rights reserved.
|
||||
#
|
||||
# This script is part of the task project.
|
||||
|
||||
@@ -2,21 +2,21 @@
|
||||
Configure VIM for Syntax Highlighting of Task Data
|
||||
|
||||
|
||||
The task data files (pending.data, completed.data and undo.data) as well as
|
||||
edits made via commands like "task 1 edit" can be color-highlighted if you
|
||||
happen to use VIM as your preferred text editor. Eventually this will happen
|
||||
automatically in newer versions of VIM, but for now you have to do a little
|
||||
bit of file shuffling.
|
||||
The task data files (pending.data, completed.data and undo.data),
|
||||
configuration file (.taskrc) as well as edits made via commands like "task 1
|
||||
edit" can be color-highlighted if you happen to use VIM as your preferred text
|
||||
editor. Eventually this will happen automatically in newer versions of VIM,
|
||||
but for now you have to do a little bit of file shuffling.
|
||||
|
||||
|
||||
Prerequisites
|
||||
|
||||
For this to work, you need to first have syntax highlighting enabled when you
|
||||
use VIM. This happens to be the default for most VIM installations, but it is
|
||||
usually quite simple if that doesn't happen to be so in your case. Rather than
|
||||
repeat the excellent VIM documentation here, please see the appropriate VIM
|
||||
documentation itself. Generally this can be made seen by starting vim/gvim and
|
||||
issuing the following command:
|
||||
use VIM. This happens to be the default for most VIM installations, but it is
|
||||
usually quite simple if that doesn't happen to be so in your case. Rather
|
||||
than repeat the excellent VIM documentation here, please see the appropriate
|
||||
VIM documentation itself. Generally this can be made seen by starting
|
||||
vim/gvim and issuing the following command:
|
||||
|
||||
:help syntax
|
||||
|
||||
@@ -27,18 +27,20 @@ You may prefer instead to read the help online at:
|
||||
Configuring VIM to Understand Task Data
|
||||
|
||||
Once you have VIM's syntax highlighting enabled and working with other file
|
||||
types properly, configuring it for use with task is simple. You simply need to
|
||||
copy some files that came with task into your home directory so that you have:
|
||||
types properly, configuring it for use with task is simple. You simply need
|
||||
to copy some files that came with task into your home directory so that you
|
||||
have:
|
||||
|
||||
~/.vim/ftdetect/task.vim
|
||||
~/.vim/syntax/taskdata.vim
|
||||
~/.vim/syntax/taskedit.vim
|
||||
~/.vim/syntax/taskrc.vim
|
||||
|
||||
The source of these files varies depending on how you installed task. If you
|
||||
The source of these files varies depending on how you installed task. If you
|
||||
installed task via a regular package (rpm or deb) you can find these files in
|
||||
/usr/share/doc/task-VERSION/scripts/vim/. If you built task yourself from the
|
||||
/usr/share/doc/task-VERSION/scripts/vim/. If you built task yourself from the
|
||||
tarball (using the default configure options), these will be in
|
||||
/usr/local/share/doc/task-VERSION/scripts/vim/ instead. So you should be able
|
||||
/usr/local/share/doc/task-VERSION/scripts/vim/ instead. So you should be able
|
||||
to do one of the following:
|
||||
|
||||
cp -av /usr/share/doc/task-VERSION/scripts/vim/* ~/.vim/
|
||||
@@ -49,9 +51,9 @@ or
|
||||
|
||||
You should then be ready to go.
|
||||
---
|
||||
All three above mentioned files are
|
||||
All four above mentioned files are
|
||||
|
||||
Copyright 2009 John Florian
|
||||
Copyright 2009-2010 John Florian
|
||||
|
||||
and are available under the GNU Public License version 2 or later.
|
||||
For the full text of this license, see COPYING.
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
" Vim support file to detect task data files and single task edits
|
||||
" Vim support file to detect Task Warrior data and configuration files and
|
||||
" single task edits
|
||||
"
|
||||
" Maintainer: John Florian <jflorian@doubledog.org>
|
||||
" Updated: Wed Jul 8 19:45:55 EDT 2009
|
||||
" Updated: Thu Dec 10 18:28:26 EST 2009
|
||||
"
|
||||
" Copyright 2009 John Florian
|
||||
" Copyright 2009-2010 John Florian
|
||||
"
|
||||
" This file is available under the GNU Public License version 2 or later.
|
||||
" For the full text of this license, see COPYING.
|
||||
|
||||
|
||||
" for the raw data files
|
||||
" Task Warrior data files
|
||||
au BufRead,BufNewFile {pending,completed,undo}.data set filetype=taskdata
|
||||
|
||||
" for 'task 42 edit'
|
||||
" Task Warrior configuration file
|
||||
au BufRead,BufNewFile .taskrc set filetype=taskrc
|
||||
|
||||
" Task Warrior handling of 'task 42 edit'
|
||||
au BufRead,BufNewFile *.task set filetype=taskedit
|
||||
|
||||
" vim:noexpandtab
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
" Maintainer: John Florian <jflorian@doubledog.org>
|
||||
" Updated: Wed Jul 8 19:46:20 EDT 2009
|
||||
"
|
||||
" Copyright 2009 John Florian
|
||||
" Copyright 2009-2010 John Florian
|
||||
"
|
||||
" This file is available under the GNU Public License version 2 or later.
|
||||
" For the full text of this license, see COPYING.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
" Maintainer: John Florian <jflorian@doubledog.org>
|
||||
" Updated: Wed Jul 8 19:46:32 EDT 2009
|
||||
"
|
||||
" Copyright 2009 John Florian
|
||||
" Copyright 2009-2010 John Florian
|
||||
"
|
||||
" This file is available under the GNU Public License version 2 or later.
|
||||
" For the full text of this license, see COPYING.
|
||||
|
||||
52
scripts/vim/syntax/taskrc.vim
Normal file
52
scripts/vim/syntax/taskrc.vim
Normal file
@@ -0,0 +1,52 @@
|
||||
" Vim syntax file
|
||||
" Language: support for editing task configuration file
|
||||
" Maintainer: John Florian <jflorian@doubledog.org>
|
||||
" Updated: Sat Feb 20 14:14:44 EST 2010
|
||||
"
|
||||
" Copyright 2009-2010 John Florian
|
||||
"
|
||||
" This file is available under the GNU Public License version 2 or later.
|
||||
" For the full text of this license, see COPYING.
|
||||
|
||||
|
||||
" For version 5.x: Clear all syntax items.
|
||||
" For version 6.x: Quit when a syntax file was already loaded.
|
||||
if version < 600
|
||||
syntax clear
|
||||
elseif exists("b:current_syntax")
|
||||
finish
|
||||
endif
|
||||
|
||||
syn match taskrcVal ".\{-}$" contains=taskrcComment
|
||||
syn match taskrcEqual "="
|
||||
syn match taskrcKey "^\s*.\{-}="he=e-1 contains=taskrcEqual
|
||||
|
||||
syn keyword taskrcGoodKey locking curses confirmation next bulk nag weekstart displayweeknumber defaultwidth editor monthsperline annotations _forcecolor blanklines debug hooks fontunderline
|
||||
|
||||
syn match taskrcGoodKey "\(active\|tag\|recurrence\)\.indicator"
|
||||
syn match taskrcGoodKey "alias\.\S\{-}="he=e-1
|
||||
syn match taskrcGoodKey "calendar\.\(legend\|holidays\|details\(\.report\)\?\)"
|
||||
syn match taskrcGoodKey "color\(\.\(alternate\|overdue\|due\(\.today\)\?\|pri\.\([HML]\|none\)\|active\|tagged\|recurring\|header\|footnote\|\(\(tag\|project\|keyword\)\.\S\{-}\)\|debug\|\(calendar\.\(today\|due\(\.today\)\?\|overdue\|weekend\|holiday\|weeknumber\)\)\)\)\?="he=e-1
|
||||
syn match taskrcGoodKey "complete\.all\.\(projects\|tags\)"
|
||||
syn match taskrcGoodKey "data\.location"
|
||||
syn match taskrcGoodKey "dateformat\(\.\(holiday\|report\)\)\?"
|
||||
syn match taskrcGoodKey "default\.\(command\|project\|priority\)"
|
||||
syn match taskrcGoodKey "due="he=e-1
|
||||
syn match taskrcGoodKey "echo\.command"
|
||||
syn match taskrcGoodKey "import\.synonym\.\(bg\|description\|due\|end\|entry\|fg\|id\|priority\|project\|recur\|start\|status\|tags\|uuid\)"
|
||||
syn match taskrcGoodKey "report\.\S\{-}\.\(description\|columns\|labels\|sort\|filter\|dateformat\|annotations\)="he=e-1
|
||||
syn match taskrcGoodKey "search\.case\.sensitive"
|
||||
syn match taskrcGoodKey "shadow\.\(file\|command\|notify\)"
|
||||
syn match taskrcGoodKey "shell\.prompt"
|
||||
|
||||
syn match taskrcComment "#.*$"
|
||||
|
||||
" The default methods for highlighting. Can be overridden later.
|
||||
hi def link taskrcComment Comment
|
||||
hi def link taskrcKey Statement
|
||||
hi def link taskrcVal String
|
||||
hi def link taskrcGoodKey Function
|
||||
|
||||
let b:current_syntax = "taskrc"
|
||||
|
||||
" vim:noexpandtab
|
||||
@@ -1,4 +1,11 @@
|
||||
#compdef task
|
||||
#
|
||||
# This script is currently unmaintained and was released for an earlier version
|
||||
# of task. We welcome any zsh user that wants to contribute to task to take a
|
||||
# look at this script and either confirm its working status or improve it.
|
||||
# Please contact us at support@taskwarrior.org if you have further questions on
|
||||
# how to contribute to task.
|
||||
#
|
||||
# zsh completion for task
|
||||
#
|
||||
# Copyright 2009 P.C. Shyamshankar
|
||||
@@ -27,10 +34,7 @@
|
||||
#
|
||||
|
||||
typeset -g _task_cmds
|
||||
_task_cmds=($(task rubbish-command | sed -n -e 's/^\s\+task \(\w\+\) .*/\1/p' | grep -v ID))
|
||||
|
||||
# As of task 1.7.0,
|
||||
# _task_cmds=(add append annotate completed edit duplicate delete undelete info start stop done undo projects tags summary timesheet history ghistory next calendar active overdue stats import export color version help list long ls newest oldest)
|
||||
_task_cmds=($(task _commands))
|
||||
|
||||
_task() {
|
||||
_arguments -s -S \
|
||||
|
||||
715
src/API.cpp
Normal file
715
src/API.cpp
Normal file
@@ -0,0 +1,715 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Task Lua API
|
||||
//
|
||||
// Copyright 2006 - 2010, 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
|
||||
//
|
||||
// -------------
|
||||
//
|
||||
// Copyright © 1994–2008 Lua.org, PUC-Rio.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <iostream> // TODO Remove
|
||||
#include <algorithm>
|
||||
#include "Context.h"
|
||||
#include "API.h"
|
||||
|
||||
extern Context context;
|
||||
Task* the_task = NULL;
|
||||
|
||||
#ifdef HAVE_LIBLUA
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Returns a string representing the task version number, such as '1.9.0'.
|
||||
static int api_task_version (lua_State* L)
|
||||
{
|
||||
lua_pushstring (L, PACKAGE_VERSION);
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Returns a string representing the Lua version number, such as '5.1.4'.
|
||||
// Lua 5.2.0 has a 'lua_version' call, but 5.1.4 is the target.
|
||||
static int api_task_lua_version (lua_State* L)
|
||||
{
|
||||
// Convert "Lua 5.1.4" -> "5.1.4"
|
||||
std::string ver = LUA_RELEASE;
|
||||
lua_pushstring (L, ver.substr (4, std::string::npos).c_str ());
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Returns the type of OS that task is running on.
|
||||
static int api_task_os (lua_State* L)
|
||||
{
|
||||
#if defined (DARWIN)
|
||||
lua_pushstring (L, "darwin");
|
||||
#elif defined (SOLARIS)
|
||||
lua_pushstring (L, "solaris");
|
||||
#elif defined (CYGWIN)
|
||||
lua_pushstring (L, "cygwin");
|
||||
#elif defined (OPENBSD)
|
||||
lua_pushstring (L, "openbsd");
|
||||
#elif defined (HAIKU)
|
||||
lua_pushstring (L, "haiku");
|
||||
#elif defined (FREEBSD)
|
||||
lua_pushstring (L, "freebsd");
|
||||
#elif defined (LINUX)
|
||||
lua_pushstring (L, "linux");
|
||||
#else
|
||||
lua_pushstring (L, "unknown");
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static int api_task_feature (lua_State* L)
|
||||
{
|
||||
std::string name = luaL_checkstring (L, 1);
|
||||
bool value = false;
|
||||
|
||||
if (name == "readline")
|
||||
{
|
||||
#ifdef HAVE_READLINE
|
||||
value = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
else if (name == "ncurses")
|
||||
{
|
||||
#ifdef HAVE_NCURSES
|
||||
value = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
else if (name == "lua")
|
||||
value = true;
|
||||
|
||||
lua_pushboolean (L, value ? 1 : 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static int api_task_aliases ()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Returns values from .taskrc, by name.
|
||||
static int api_task_get_config (lua_State* L)
|
||||
{
|
||||
std::string name = luaL_checkstring (L, 1);
|
||||
lua_pushstring (L, context.config.get (name).c_str ());
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
-- Temporarily sets .taskrc values, by name.
|
||||
static int api_task_set_config (name, value)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
-- Returns an internationalized string, by string ID, from the appropriate
|
||||
-- locale-based strings file.
|
||||
static int api_task_i18n_string (id)
|
||||
{
|
||||
return "le foo"
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
-- Returns a list of tips, from the appropriate locale-based tips file.
|
||||
static int api_task_i18n_tips ()
|
||||
{
|
||||
return {}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
-- Returns the name of the current command.
|
||||
static int api_task_get_command ()
|
||||
{
|
||||
return "list"
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
-- Returns a list of string messages generated so far.
|
||||
static int api_task_get_header_messages ()
|
||||
{
|
||||
return {}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static int api_task_get_footnote_messages ()
|
||||
{
|
||||
return {}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static int api_task_get_debug_messages ()
|
||||
{
|
||||
return {}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
-- Records additional messages, for subsequent display.
|
||||
static int api_task_header_message (text)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static int api_task_footnote_message (text)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static int api_task_debug_message (text)
|
||||
{
|
||||
}
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Causes the shell or interactive mode task to exit. Ordinarily this does not
|
||||
// occur.
|
||||
static int api_task_exit (lua_State* L)
|
||||
{
|
||||
// TODO Is this the correct exception? How does the shell handle this?
|
||||
throw std::string ("Exiting.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
-- Shuts off the hook system for any subsequent hook calls for this command.
|
||||
static int api_task_inhibit_further_hooks ()
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
-- Returns a table that contains a complete copy of the task.
|
||||
static int api_task_get (lua_State* L)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
-- Creates a new task from the data specified in the table t.
|
||||
static int api_task_add (t)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
-- Modifies the task described in the table t.
|
||||
static int api_task_modify (t)
|
||||
{
|
||||
}
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// -- 'id' is the task id passed to the hook function. Date attributes are
|
||||
// -- returned as a numeric epoch offset. Tags and annotations are returned
|
||||
// -- as tables. A nil value indicates a missing value.
|
||||
static int api_task_get_uuid (lua_State* L)
|
||||
{
|
||||
if (the_task != NULL)
|
||||
lua_pushstring (L, the_task->get ("uuid").c_str ());
|
||||
else
|
||||
lua_pushnil (L);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static int api_task_get_description (lua_State* L)
|
||||
{
|
||||
if (the_task != NULL)
|
||||
lua_pushstring (L, the_task->get ("description").c_str ());
|
||||
else
|
||||
lua_pushnil (L);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static int api_task_get_annotations (id)
|
||||
{
|
||||
return task.annotations
|
||||
}
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static int api_task_get_project (lua_State* L)
|
||||
{
|
||||
if (the_task != NULL)
|
||||
lua_pushstring (L, the_task->get ("project").c_str ());
|
||||
else
|
||||
lua_pushnil (L);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static int api_task_get_priority (lua_State* L)
|
||||
{
|
||||
if (the_task != NULL)
|
||||
lua_pushstring (L, the_task->get ("priority").c_str ());
|
||||
else
|
||||
lua_pushnil (L);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static int api_task_get_tags (id)
|
||||
{
|
||||
return task.tags
|
||||
}
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static int api_task_get_status (lua_State* L)
|
||||
{
|
||||
if (the_task != NULL)
|
||||
lua_pushstring (L, Task::statusToText (the_task->getStatus ()).c_str ());
|
||||
else
|
||||
lua_pushnil (L);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static int api_task_get_due (id)
|
||||
{
|
||||
return task.due_date
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static int api_task_get_entry (id)
|
||||
{
|
||||
return task.entry_date
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static int api_task_get_start (id)
|
||||
{
|
||||
return task.start_date
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static int api_task_get_end (id)
|
||||
{
|
||||
return task.end_date
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static int api_task_get_recur (id)
|
||||
{
|
||||
return task.recur
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static int api_task_get_until (id)
|
||||
{
|
||||
return task.until_date
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static int api_task_get_wait (id)
|
||||
{
|
||||
return task.wait_date
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
-- 'id' is the task id passed to the hook function. Date attributes are
|
||||
-- expected as numeric epoch offsets. Tags and annotations are expected
|
||||
-- as tables. A nil value indicates a missing value.
|
||||
static int api_task_set_description (id, value)
|
||||
{
|
||||
task.description = value
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static int api_task_set_annotations (id, value)
|
||||
{
|
||||
task.annotations = value
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static int api_task_set_project (id, value)
|
||||
{
|
||||
task.project = value
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static int api_task_set_priority (id, value)
|
||||
{
|
||||
task.priority = value
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static int api_task_set_tags (id, value)
|
||||
{
|
||||
task.tags = value
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static int api_task_set_status (id, value)
|
||||
{
|
||||
task.status = value
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static int api_task_set_due (id, value)
|
||||
{
|
||||
task.due_date = value
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static int api_task_set_start (id, value)
|
||||
{
|
||||
task.start_date = value
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static int api_task_set_recur (id, value)
|
||||
{
|
||||
task.recur = value
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static int api_task_set_until (id, value)
|
||||
{
|
||||
task.until_date = value
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static int api_task_set_wait (id, value)
|
||||
{
|
||||
task.wait_date = value
|
||||
}
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
API::API ()
|
||||
: L (NULL)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
API::~API ()
|
||||
{
|
||||
if (L)
|
||||
{
|
||||
lua_close (L);
|
||||
L = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void API::initialize ()
|
||||
{
|
||||
// Initialize Lua.
|
||||
L = lua_open ();
|
||||
luaL_openlibs (L); // TODO Error handling
|
||||
|
||||
// Register all the API functions in Lua global space.
|
||||
lua_pushcfunction (L, api_task_version); lua_setglobal (L, "task_version");
|
||||
lua_pushcfunction (L, api_task_lua_version); lua_setglobal (L, "task_lua_version");
|
||||
lua_pushcfunction (L, api_task_os); lua_setglobal (L, "task_os");
|
||||
lua_pushcfunction (L, api_task_feature); lua_setglobal (L, "task_feature");
|
||||
/*
|
||||
lua_pushcfunction (L, api_task_aliases); lua_setglobal (L, "task_aliases");
|
||||
*/
|
||||
lua_pushcfunction (L, api_task_get_config); lua_setglobal (L, "task_get_config");
|
||||
/*
|
||||
lua_pushcfunction (L, api_task_set_config); lua_setglobal (L, "task_set_config");
|
||||
lua_pushcfunction (L, api_task_i18n_string); lua_setglobal (L, "task_i18n_string");
|
||||
lua_pushcfunction (L, api_task_i18n_tips); lua_setglobal (L, "task_i18n_tips");
|
||||
lua_pushcfunction (L, api_task_get_command); lua_setglobal (L, "task_get_command");
|
||||
lua_pushcfunction (L, api_task_get_header_messages); lua_setglobal (L, "task_get_header_messages");
|
||||
lua_pushcfunction (L, api_task_get_footnote_messages); lua_setglobal (L, "task_get_footnote_messages");
|
||||
lua_pushcfunction (L, api_task_get_debug_messages); lua_setglobal (L, "task_get_debug_messages");
|
||||
lua_pushcfunction (L, api_task_header_message); lua_setglobal (L, "task_header_message");
|
||||
lua_pushcfunction (L, api_task_footnote_message); lua_setglobal (L, "task_footnote_message");
|
||||
lua_pushcfunction (L, api_task_debug_message); lua_setglobal (L, "task_debug_message");
|
||||
*/
|
||||
lua_pushcfunction (L, api_task_exit); lua_setglobal (L, "task_exit");
|
||||
/*
|
||||
lua_pushcfunction (L, api_task_inhibit_further_hooks); lua_setglobal (L, "task_inhibit_further_hooks");
|
||||
lua_pushcfunction (L, api_task_get); lua_setglobal (L, "task_get");
|
||||
lua_pushcfunction (L, api_task_add); lua_setglobal (L, "task_add");
|
||||
lua_pushcfunction (L, api_task_modify); lua_setglobal (L, "task_modify");
|
||||
*/
|
||||
lua_pushcfunction (L, api_task_get_uuid); lua_setglobal (L, "task_get_uuid");
|
||||
lua_pushcfunction (L, api_task_get_description); lua_setglobal (L, "task_get_description");
|
||||
/*
|
||||
lua_pushcfunction (L, api_task_get_annotations); lua_setglobal (L, "task_get_annotations");
|
||||
*/
|
||||
lua_pushcfunction (L, api_task_get_project); lua_setglobal (L, "task_get_project");
|
||||
lua_pushcfunction (L, api_task_get_priority); lua_setglobal (L, "task_get_priority");
|
||||
/*
|
||||
lua_pushcfunction (L, api_task_get_tags); lua_setglobal (L, "task_get_tags");
|
||||
*/
|
||||
lua_pushcfunction (L, api_task_get_status); lua_setglobal (L, "task_get_status");
|
||||
/*
|
||||
lua_pushcfunction (L, api_task_get_due); lua_setglobal (L, "task_get_due");
|
||||
lua_pushcfunction (L, api_task_get_entry); lua_setglobal (L, "task_get_entry");
|
||||
lua_pushcfunction (L, api_task_get_start); lua_setglobal (L, "task_get_start");
|
||||
lua_pushcfunction (L, api_task_get_end); lua_setglobal (L, "task_get_end");
|
||||
lua_pushcfunction (L, api_task_get_recur); lua_setglobal (L, "task_get_recur");
|
||||
lua_pushcfunction (L, api_task_get_until); lua_setglobal (L, "task_get_until");
|
||||
lua_pushcfunction (L, api_task_get_wait); lua_setglobal (L, "task_get_wait");
|
||||
lua_pushcfunction (L, api_task_set_description); lua_setglobal (L, "task_set_description");
|
||||
lua_pushcfunction (L, api_task_set_annotations); lua_setglobal (L, "task_set_annotations");
|
||||
lua_pushcfunction (L, api_task_set_project); lua_setglobal (L, "task_set_project");
|
||||
lua_pushcfunction (L, api_task_set_priority); lua_setglobal (L, "task_set_priority");
|
||||
lua_pushcfunction (L, api_task_set_tags); lua_setglobal (L, "task_set_tags");
|
||||
lua_pushcfunction (L, api_task_set_status); lua_setglobal (L, "task_set_status");
|
||||
lua_pushcfunction (L, api_task_set_due); lua_setglobal (L, "task_set_due");
|
||||
lua_pushcfunction (L, api_task_set_start); lua_setglobal (L, "task_set_start");
|
||||
lua_pushcfunction (L, api_task_set_recur); lua_setglobal (L, "task_set_recur");
|
||||
lua_pushcfunction (L, api_task_set_until); lua_setglobal (L, "task_set_until");
|
||||
lua_pushcfunction (L, api_task_set_wait); lua_setglobal (L, "task_set_wait");
|
||||
*/
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool API::callProgramHook (
|
||||
const std::string& file,
|
||||
const std::string& function)
|
||||
{
|
||||
loadFile (file);
|
||||
|
||||
// Get function.
|
||||
lua_getglobal (L, function.c_str ());
|
||||
if (!lua_isfunction (L, -1))
|
||||
{
|
||||
lua_pop (L, 1);
|
||||
throw std::string ("The Lua function '") + function + "' was not found.";
|
||||
}
|
||||
|
||||
// Make call.
|
||||
if (lua_pcall (L, 0, 2, 0) != 0)
|
||||
throw std::string ("Error calling '") + function + "' - " + lua_tostring (L, -1);
|
||||
|
||||
// Call successful - get return values.
|
||||
if (!lua_isnumber (L, -2))
|
||||
throw std::string ("Error: '") + function + "' did not return a success indicator";
|
||||
|
||||
if (!lua_isstring (L, -1) && !lua_isnil (L, -1))
|
||||
throw std::string ("Error: '") + function + "' did not return a message or nil";
|
||||
|
||||
int rc = lua_tointeger (L, -2);
|
||||
const char* message = lua_tostring (L, -1);
|
||||
|
||||
if (rc == 0)
|
||||
{
|
||||
if (message)
|
||||
context.footnote (std::string ("Warning: ") + message);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (message)
|
||||
throw std::string (message);
|
||||
}
|
||||
|
||||
lua_pop (L, 1);
|
||||
return rc == 0 ? true : false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// TODO No intention of implementing this before task 2.0. Why? Because we
|
||||
// need to implement a Lua iterator, in C++, to iterate over a std::vector.
|
||||
bool API::callListHook (
|
||||
const std::string& file,
|
||||
const std::string& function,
|
||||
std::vector <Task>& all)
|
||||
{
|
||||
loadFile (file);
|
||||
|
||||
// TODO Get function.
|
||||
// TODO Prepare args.
|
||||
// TODO Make call.
|
||||
// TODO Get exit status.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool API::callTaskHook (
|
||||
const std::string& file,
|
||||
const std::string& function,
|
||||
Task& task)
|
||||
{
|
||||
loadFile (file);
|
||||
|
||||
// Save the task for reference via the API.
|
||||
current = task;
|
||||
|
||||
// Get function.
|
||||
lua_getglobal (L, function.c_str ());
|
||||
if (!lua_isfunction (L, -1))
|
||||
{
|
||||
lua_pop (L, 1);
|
||||
throw std::string ("The Lua function '") + function + "' was not found.";
|
||||
}
|
||||
|
||||
// Prepare args.
|
||||
lua_pushnumber (L, current.id);
|
||||
|
||||
// Expose the task.
|
||||
the_task = ¤t;
|
||||
|
||||
// Make call.
|
||||
if (lua_pcall (L, 1, 2, 0) != 0)
|
||||
throw std::string ("Error calling '") + function + "' - " + lua_tostring (L, -1);
|
||||
|
||||
// Hide the task.
|
||||
the_task = NULL;
|
||||
|
||||
// Call successful - get return values.
|
||||
if (!lua_isnumber (L, -2))
|
||||
throw std::string ("Error: '") + function + "' did not return a success indicator";
|
||||
|
||||
if (!lua_isstring (L, -1) && !lua_isnil (L, -1))
|
||||
throw std::string ("Error: '") + function + "' did not return a message or nil";
|
||||
|
||||
int rc = lua_tointeger (L, -2);
|
||||
const char* message = lua_tostring (L, -1);
|
||||
|
||||
if (rc == 0)
|
||||
{
|
||||
if (message)
|
||||
context.footnote (std::string ("Warning: ") + message);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (message)
|
||||
throw std::string (message);
|
||||
}
|
||||
|
||||
lua_pop (L, 1);
|
||||
return rc == 0 ? true : false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool API::callFieldHook (
|
||||
const std::string& file,
|
||||
const std::string& function,
|
||||
const std::string& name,
|
||||
std::string& value)
|
||||
{
|
||||
loadFile (file);
|
||||
|
||||
// Get function.
|
||||
lua_getglobal (L, function.c_str ());
|
||||
if (!lua_isfunction (L, -1))
|
||||
{
|
||||
lua_pop (L, 1);
|
||||
throw std::string ("The Lua function '") + function + "' was not found.";
|
||||
}
|
||||
|
||||
// Prepare args.
|
||||
lua_pushstring (L, name.c_str ());
|
||||
lua_pushstring (L, value.c_str ());
|
||||
|
||||
// Make call.
|
||||
if (lua_pcall (L, 2, 3, 0) != 0)
|
||||
throw std::string ("Error calling '") + function + "' - " + lua_tostring (L, -1);
|
||||
|
||||
// Call successful - get return values.
|
||||
if (!lua_isstring (L, -3))
|
||||
throw std::string ("Error: '") + function + "' did not return a modified value";
|
||||
|
||||
if (!lua_isnumber (L, -2))
|
||||
throw std::string ("Error: '") + function + "' did not return a success indicator";
|
||||
|
||||
if (!lua_isstring (L, -1) && !lua_isnil (L, -1))
|
||||
throw std::string ("Error: '") + function + "' did not return a message or nil";
|
||||
|
||||
const char* new_value = lua_tostring (L, -3);
|
||||
int rc = lua_tointeger (L, -2);
|
||||
const char* message = lua_tostring (L, -1);
|
||||
|
||||
if (rc == 0)
|
||||
{
|
||||
// Overwrite with the modified value.
|
||||
value = new_value;
|
||||
|
||||
if (message)
|
||||
context.footnote (std::string ("Warning: ") + message);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (message)
|
||||
throw std::string (message);
|
||||
}
|
||||
|
||||
lua_pop (L, 1);
|
||||
return rc == 0 ? true : false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void API::loadFile (const std::string& file)
|
||||
{
|
||||
// If the file is not loaded.
|
||||
if (std::find (loaded.begin (), loaded.end (), file) == loaded.end ())
|
||||
{
|
||||
// Load the file, if possible.
|
||||
if (luaL_loadfile (L, file.c_str ()) || lua_pcall (L, 0, 0, 0))
|
||||
throw std::string ("Error: ") + std::string (lua_tostring (L, -1));
|
||||
|
||||
// Mark this as loaded, so as to not bother again.
|
||||
loaded.push_back (file);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif
|
||||
|
||||
74
src/API.h
Normal file
74
src/API.h
Normal file
@@ -0,0 +1,74 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2010, 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_API
|
||||
#define INCLUDED_API
|
||||
|
||||
#include "auto.h"
|
||||
#ifdef HAVE_LIBLUA
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "Task.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "lua.h"
|
||||
#include "lualib.h"
|
||||
#include "lauxlib.h"
|
||||
}
|
||||
|
||||
class API
|
||||
{
|
||||
public:
|
||||
API ();
|
||||
API (const API&);
|
||||
API& operator= (const API&);
|
||||
~API ();
|
||||
|
||||
void initialize ();
|
||||
bool callProgramHook (const std::string&, const std::string&);
|
||||
bool callListHook (const std::string&, const std::string&, std::vector <Task>&);
|
||||
bool callTaskHook (const std::string&, const std::string&, Task&);
|
||||
bool callFieldHook (const std::string&, const std::string&, const std::string&, std::string&);
|
||||
|
||||
private:
|
||||
void loadFile (const std::string&);
|
||||
|
||||
public:
|
||||
lua_State* L;
|
||||
std::vector <std::string> loaded;
|
||||
|
||||
// Context for the API.
|
||||
// std::vector <Task> all;
|
||||
Task current;
|
||||
// std::string& name;
|
||||
// std::string& value;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
89
src/Att.cpp
89
src/Att.cpp
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -29,7 +29,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "text.h"
|
||||
#include "color.h"
|
||||
#include "Color.h"
|
||||
#include "util.h"
|
||||
#include "Date.h"
|
||||
#include "Duration.h"
|
||||
@@ -77,6 +77,8 @@ static const char* modifierNames[] =
|
||||
"hasnt",
|
||||
"startswith", "left",
|
||||
"endswith", "right",
|
||||
"word",
|
||||
"noword"
|
||||
};
|
||||
|
||||
#define NUM_INTERNAL_NAMES (sizeof (internalNames) / sizeof (internalNames[0]))
|
||||
@@ -102,7 +104,7 @@ Att::Att (const std::string& name, const std::string& mod, const std::string& va
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Att::Att (const std::string& name, const std::string& mod, int value)
|
||||
{
|
||||
mName = name;
|
||||
mName = name;
|
||||
|
||||
std::stringstream s;
|
||||
s << value;
|
||||
@@ -122,7 +124,7 @@ Att::Att (const std::string& name, const std::string& value)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Att::Att (const std::string& name, int value)
|
||||
{
|
||||
mName = name;
|
||||
mName = name;
|
||||
|
||||
std::stringstream s;
|
||||
s << value;
|
||||
@@ -319,8 +321,8 @@ bool Att::validNameValue (
|
||||
|
||||
else if (name == "fg" || name == "bg")
|
||||
{
|
||||
if (value != "")
|
||||
Text::guessColor (value);
|
||||
// TODO Determine whether color abbreviations are supported, and if so,
|
||||
// modify 'value' here accordingly.
|
||||
}
|
||||
|
||||
else if (name == "due" ||
|
||||
@@ -329,7 +331,7 @@ bool Att::validNameValue (
|
||||
{
|
||||
// Validate and convert to epoch.
|
||||
if (value != "")
|
||||
value = Date (value, context.config.get ("dateformat", "m/d/Y")).toEpochString ();
|
||||
value = Date (value, context.config.get ("dateformat")).toEpochString ();
|
||||
}
|
||||
|
||||
else if (name == "recur")
|
||||
@@ -375,7 +377,7 @@ bool Att::validNameValue (
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// TODO Obsolete
|
||||
// TODO Deprecated - remove.
|
||||
bool Att::validMod (const std::string& mod)
|
||||
{
|
||||
for (unsigned int i = 0; i < NUM_MODIFIER_NAMES; ++i)
|
||||
@@ -412,7 +414,9 @@ std::string Att::type (const std::string& name) const
|
||||
std::string Att::modType (const std::string& name) const
|
||||
{
|
||||
if (name == "hasnt" ||
|
||||
name == "isnt")
|
||||
name == "isnt" ||
|
||||
name == "not" || // TODO Verify this.
|
||||
name == "noword")
|
||||
return "negative";
|
||||
|
||||
return "positive";
|
||||
@@ -483,32 +487,33 @@ void Att::parse (Nibbler& n)
|
||||
bool Att::match (const Att& other) const
|
||||
{
|
||||
// All matches are assumed to pass, any short-circuit on non-match.
|
||||
bool case_sensitive = context.config.getBoolean ("search.case.sensitive");
|
||||
|
||||
// If there are no mods, just perform a straight compare on value.
|
||||
if (mMod == "")
|
||||
{
|
||||
if (mValue != other.mValue)
|
||||
if (!compare (mValue, other.mValue, (bool) case_sensitive))
|
||||
return false;
|
||||
}
|
||||
|
||||
// has = contains as a substring.
|
||||
else if (mMod == "has" || mMod == "contains") // TODO i18n
|
||||
{
|
||||
if (other.mValue.find (mValue) == std::string::npos)
|
||||
if (find (other.mValue, mValue, (bool) case_sensitive) == std::string::npos)
|
||||
return false;
|
||||
}
|
||||
|
||||
// is = equal. Nop.
|
||||
else if (mMod == "is" || mMod == "equals") // TODO i18n
|
||||
{
|
||||
if (mValue != other.mValue)
|
||||
if (!compare (mValue, other.mValue, (bool) case_sensitive))
|
||||
return false;
|
||||
}
|
||||
|
||||
// isnt = not equal.
|
||||
else if (mMod == "isnt" || mMod == "not") // TODO i18n
|
||||
{
|
||||
if (mValue == other.mValue)
|
||||
if (compare (mValue, other.mValue, (bool) case_sensitive))
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -532,7 +537,7 @@ bool Att::match (const Att& other) const
|
||||
if (other.mValue.length () < mValue.length ())
|
||||
return false;
|
||||
|
||||
if (mValue != other.mValue.substr (0, mValue.length ()))
|
||||
if (!compare (mValue, other.mValue.substr (0, mValue.length ())))
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -542,16 +547,16 @@ bool Att::match (const Att& other) const
|
||||
if (other.mValue.length () < mValue.length ())
|
||||
return false;
|
||||
|
||||
if (mValue != other.mValue.substr (
|
||||
if (!compare (mValue, other.mValue.substr (
|
||||
other.mValue.length () - mValue.length (),
|
||||
std::string::npos))
|
||||
std::string::npos), (bool) case_sensitive))
|
||||
return false;
|
||||
}
|
||||
|
||||
// hasnt = does not contain as a substring.
|
||||
else if (mMod == "hasnt") // TODO i18n
|
||||
{
|
||||
if (other.mValue.find (mValue) != std::string::npos)
|
||||
if (find (other.mValue, mValue, (bool) case_sensitive) != std::string::npos)
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -562,20 +567,20 @@ bool Att::match (const Att& other) const
|
||||
if (which == "duration")
|
||||
{
|
||||
Duration literal (mValue);
|
||||
Duration variable ((time_t)::atoi (other.mValue.c_str ()));
|
||||
Duration variable ((time_t)atoi (other.mValue.c_str ()));
|
||||
if (!(variable < literal))
|
||||
return false;
|
||||
}
|
||||
else if (which == "date")
|
||||
{
|
||||
Date literal (mValue.c_str (), context.config.get ("dateformat", "m/d/Y"));
|
||||
Date variable ((time_t)::atoi (other.mValue.c_str ()));
|
||||
Date literal (mValue.c_str (), context.config.get ("dateformat"));
|
||||
Date variable ((time_t)atoi (other.mValue.c_str ()));
|
||||
if (other.mValue == "" || ! (variable < literal))
|
||||
return false;
|
||||
}
|
||||
else if (which == "number")
|
||||
{
|
||||
if (::atoi (mValue.c_str ()) >= ::atoi (other.mValue.c_str ()))
|
||||
if (atoi (mValue.c_str ()) >= atoi (other.mValue.c_str ()))
|
||||
return false;
|
||||
}
|
||||
else if (which == "text")
|
||||
@@ -592,20 +597,20 @@ bool Att::match (const Att& other) const
|
||||
if (which == "duration")
|
||||
{
|
||||
Duration literal (mValue);
|
||||
Duration variable ((time_t)::atoi (other.mValue.c_str ()));
|
||||
Duration variable ((time_t)atoi (other.mValue.c_str ()));
|
||||
if (! (variable > literal))
|
||||
return false;
|
||||
}
|
||||
else if (which == "date")
|
||||
{
|
||||
Date literal (mValue.c_str (), context.config.get ("dateformat", "m/d/Y"));
|
||||
Date variable ((time_t)::atoi (other.mValue.c_str ()));
|
||||
Date literal (mValue.c_str (), context.config.get ("dateformat"));
|
||||
Date variable ((time_t)atoi (other.mValue.c_str ()));
|
||||
if (! (variable > literal))
|
||||
return false;
|
||||
}
|
||||
else if (which == "number")
|
||||
{
|
||||
if (::atoi (mValue.c_str ()) <= ::atoi (other.mValue.c_str ()))
|
||||
if (atoi (mValue.c_str ()) <= atoi (other.mValue.c_str ()))
|
||||
return false;
|
||||
}
|
||||
else if (which == "text")
|
||||
@@ -615,6 +620,35 @@ bool Att::match (const Att& other) const
|
||||
}
|
||||
}
|
||||
|
||||
// word = contains as a substring, with word boundaries.
|
||||
else if (mMod == "word") // TODO i18n
|
||||
{
|
||||
// Fail if the substring is not found.
|
||||
std::string::size_type sub = find (other.mValue, mValue, (bool) case_sensitive);
|
||||
if (sub == std::string::npos)
|
||||
return false;
|
||||
|
||||
// Also fail if there is no word boundary at beginning and end.
|
||||
if (!isWordStart (other.mValue, sub))
|
||||
return false;
|
||||
|
||||
if (!isWordEnd (other.mValue, sub + mValue.length () - 1))
|
||||
return false;
|
||||
}
|
||||
|
||||
// noword = does not contain as a substring, with word boundaries.
|
||||
else if (mMod == "noword") // TODO i18n
|
||||
{
|
||||
// Fail if the substring is not found.
|
||||
std::string::size_type sub = find (other.mValue, mValue);
|
||||
if (sub != std::string::npos &&
|
||||
isWordStart (other.mValue, sub) &&
|
||||
isWordEnd (other.mValue, sub + mValue.length () - 1))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -678,7 +712,7 @@ void Att::value (const std::string& value)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int Att::value_int () const
|
||||
{
|
||||
return ::atoi (mValue.c_str ());
|
||||
return atoi (mValue.c_str ());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -710,7 +744,8 @@ void Att::dequote (std::string& value) const
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Encode values prior to serialization.
|
||||
// \t -> &tab;
|
||||
// " -> "
|
||||
// ' -> &squot;
|
||||
// " -> &dquot;
|
||||
// , -> ,
|
||||
// [ -> &open;
|
||||
// ] -> &close;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
|
||||
10
src/Cmd.cpp
10
src/Cmd.cpp
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -110,11 +110,13 @@ void Cmd::load ()
|
||||
commands.push_back ("_commands");
|
||||
commands.push_back ("_ids");
|
||||
commands.push_back ("_config");
|
||||
commands.push_back ("_version");
|
||||
commands.push_back (context.stringtable.get (CMD_ADD, "add"));
|
||||
commands.push_back (context.stringtable.get (CMD_APPEND, "append"));
|
||||
commands.push_back (context.stringtable.get (CMD_ANNOTATE, "annotate"));
|
||||
commands.push_back (context.stringtable.get (CMD_CALENDAR, "calendar"));
|
||||
commands.push_back (context.stringtable.get (CMD_COLORS, "colors"));
|
||||
commands.push_back (context.stringtable.get (CMD_CONFIG, "config"));
|
||||
commands.push_back (context.stringtable.get (CMD_DELETE, "delete"));
|
||||
commands.push_back (context.stringtable.get (CMD_DONE, "done"));
|
||||
commands.push_back (context.stringtable.get (CMD_DUPLICATE, "duplicate"));
|
||||
@@ -125,6 +127,7 @@ void Cmd::load ()
|
||||
commands.push_back (context.stringtable.get (CMD_GHISTORY, "ghistory"));
|
||||
commands.push_back (context.stringtable.get (CMD_IMPORT, "import"));
|
||||
commands.push_back (context.stringtable.get (CMD_INFO, "info"));
|
||||
commands.push_back (context.stringtable.get (CMD_PREPEND, "prepend"));
|
||||
commands.push_back (context.stringtable.get (CMD_PROJECTS, "projects"));
|
||||
#ifdef FEATURE_SHELL
|
||||
commands.push_back (context.stringtable.get (CMD_SHELL, "shell"));
|
||||
@@ -146,7 +149,7 @@ void Cmd::load ()
|
||||
{
|
||||
if (i->substr (0, 7) == "report.")
|
||||
{
|
||||
std::string report = i->substr (7, std::string::npos);
|
||||
std::string report = i->substr (7);
|
||||
std::string::size_type columns = report.find (".columns");
|
||||
if (columns != std::string::npos)
|
||||
{
|
||||
@@ -191,8 +194,10 @@ bool Cmd::isReadOnlyCommand ()
|
||||
command == "_commands" ||
|
||||
command == "_ids" ||
|
||||
command == "_config" ||
|
||||
command == "_version" ||
|
||||
command == context.stringtable.get (CMD_CALENDAR, "calendar") ||
|
||||
command == context.stringtable.get (CMD_COLORS, "colors") ||
|
||||
command == context.stringtable.get (CMD_CONFIG, "config") ||
|
||||
command == context.stringtable.get (CMD_EXPORT, "export") ||
|
||||
command == context.stringtable.get (CMD_HELP, "help") ||
|
||||
command == context.stringtable.get (CMD_HISTORY, "history") ||
|
||||
@@ -223,6 +228,7 @@ bool Cmd::isWriteCommand ()
|
||||
command == context.stringtable.get (CMD_DUPLICATE, "duplicate") ||
|
||||
command == context.stringtable.get (CMD_EDIT, "edit") ||
|
||||
command == context.stringtable.get (CMD_IMPORT, "import") ||
|
||||
command == context.stringtable.get (CMD_PREPEND, "prepend") ||
|
||||
command == context.stringtable.get (CMD_START, "start") ||
|
||||
command == context.stringtable.get (CMD_STOP, "stop") ||
|
||||
command == context.stringtable.get (CMD_UNDO, "undo"))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
|
||||
557
src/Color.cpp
Normal file
557
src/Color.cpp
Normal file
@@ -0,0 +1,557 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free Software
|
||||
// Foundation; either version 2 of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
// details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program; if not, write to the
|
||||
//
|
||||
// Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor,
|
||||
// Boston, MA
|
||||
// 02110-1301
|
||||
// USA
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include "Color.h"
|
||||
#include "text.h"
|
||||
#include "i18n.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static struct
|
||||
{
|
||||
Color::color_id id;
|
||||
int string_id;
|
||||
std::string english_name;
|
||||
int index; // offset red=3 (therefore fg=33, bg=43)
|
||||
} allColors[] =
|
||||
{
|
||||
// Color.h enum i18n.h English Index
|
||||
{ Color::nocolor, 0, "none", 0},
|
||||
{ Color::black, CCOLOR_BLACK, "black", 1}, // fg 29+0 bg 39+0
|
||||
{ Color::red, CCOLOR_RED, "red", 2},
|
||||
{ Color::green, CCOLOR_GREEN, "green", 3},
|
||||
{ Color::yellow, CCOLOR_YELLOW, "yellow", 4},
|
||||
{ Color::blue, CCOLOR_BLUE, "blue", 5},
|
||||
{ Color::magenta, CCOLOR_MAGENTA, "magenta", 6},
|
||||
{ Color::cyan, CCOLOR_CYAN, "cyan", 7},
|
||||
{ Color::white, CCOLOR_WHITE, "white", 8},
|
||||
|
||||
};
|
||||
|
||||
#define NUM_COLORS (sizeof (allColors) / sizeof (allColors[0]))
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Color::Color ()
|
||||
: value (0)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Color::Color (const Color& other)
|
||||
{
|
||||
value = other.value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Color::Color (unsigned int c)
|
||||
: value (0)
|
||||
{
|
||||
if (!(c & _COLOR_HASFG)) value &= ~_COLOR_FG;
|
||||
if (!(c & _COLOR_HASBG)) value &= ~_COLOR_BG;
|
||||
|
||||
value = c & (_COLOR_256 | _COLOR_HASBG | _COLOR_HASFG |_COLOR_UNDERLINE |
|
||||
_COLOR_BOLD | _COLOR_BRIGHT | _COLOR_BG | _COLOR_FG);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Supports the following constructs:
|
||||
// [bright] [color] [on color] [bright] [underline]
|
||||
//
|
||||
// Where [color] is one of:
|
||||
// black
|
||||
// red
|
||||
// ...
|
||||
// grayN 0 <= N <= 23 fg 38;5;232 + N bg 48;5;232 + N
|
||||
// greyN 0 <= N <= 23 fg 38;5;232 + N bg 48;5;232 + N
|
||||
// colorN 0 <= N <= 255 fg 38;5;N bg 48;5;N
|
||||
// rgbRGB 0 <= R,G,B <= 5 fg 38;5;16 + R*36 + G*6 + B bg 48;5;16 + R*36 + G*6 + B
|
||||
Color::Color (const std::string& spec)
|
||||
: value (0)
|
||||
{
|
||||
// By converting underscores to spaces, we inherently support the old "on_red"
|
||||
// style of specifying background colors. We consider underscores to be
|
||||
// deprecated.
|
||||
std::string modifiable_spec = spec;
|
||||
std::replace (modifiable_spec.begin (), modifiable_spec.end (), '_', ' ');
|
||||
|
||||
// Split spec into words.
|
||||
std::vector <std::string> words;
|
||||
split (words, modifiable_spec, ' ');
|
||||
|
||||
// Construct the color as two separate colors, then blend them later. This
|
||||
// make it possible to declare a color such as "color1 on black", and have
|
||||
// the upgrade work properly.
|
||||
unsigned int fg_value = 0;
|
||||
unsigned int bg_value = 0;
|
||||
|
||||
bool bg = false;
|
||||
int index;
|
||||
std::string word;
|
||||
std::vector <std::string>::iterator it;
|
||||
for (it = words.begin (); it != words.end (); ++it)
|
||||
{
|
||||
word = lowerCase (trim (*it));
|
||||
|
||||
if (word == "bold") fg_value |= _COLOR_BOLD;
|
||||
else if (word == "bright") bg_value |= _COLOR_BRIGHT;
|
||||
else if (word == "underline") fg_value |= _COLOR_UNDERLINE;
|
||||
else if (word == "on") bg = true;
|
||||
|
||||
// X where X is one of black, red, blue ...
|
||||
else if ((index = find (word)) != -1)
|
||||
{
|
||||
if (bg)
|
||||
{
|
||||
bg_value |= _COLOR_HASBG;
|
||||
bg_value |= index << 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
fg_value |= _COLOR_HASFG;
|
||||
fg_value |= index;
|
||||
}
|
||||
}
|
||||
|
||||
// greyN/grayN, where 0 <= N <= 23.
|
||||
else if (word.substr (0, 4) == "grey" ||
|
||||
word.substr (0, 4) == "gray")
|
||||
{
|
||||
index = atoi (word.substr (4).c_str ());
|
||||
if (index < 0 || index > 23)
|
||||
throw std::string ("The color '") + *it + "' is not recognized.";
|
||||
|
||||
if (bg)
|
||||
{
|
||||
bg_value |= _COLOR_HASBG;
|
||||
bg_value |= (index + 232) << 8;
|
||||
bg_value |= _COLOR_256;
|
||||
}
|
||||
else
|
||||
{
|
||||
fg_value |= _COLOR_HASFG;
|
||||
fg_value |= index + 232;
|
||||
fg_value |= _COLOR_256;
|
||||
}
|
||||
}
|
||||
|
||||
// rgbRGB, where 0 <= R,G,B <= 5.
|
||||
else if (word.substr (0, 3) == "rgb")
|
||||
{
|
||||
index = atoi (word.substr (3).c_str ());
|
||||
if (word.length () != 6 ||
|
||||
index < 0 || index > 555)
|
||||
throw std::string ("The color '") + *it + "' is not recognized.";
|
||||
|
||||
int r = atoi (word.substr (3, 1).c_str ());
|
||||
int g = atoi (word.substr (4, 1).c_str ());
|
||||
int b = atoi (word.substr (5, 1).c_str ());
|
||||
if (r < 0 || r > 5 ||
|
||||
g < 0 || g > 5 ||
|
||||
b < 0 || b > 5)
|
||||
throw std::string ("The color '") + *it + "' is not recognized.";
|
||||
|
||||
index = 16 + r*36 + g*6 + b;
|
||||
|
||||
if (bg)
|
||||
{
|
||||
bg_value |= _COLOR_HASBG;
|
||||
bg_value |= index << 8;
|
||||
bg_value |= _COLOR_256;
|
||||
}
|
||||
else
|
||||
{
|
||||
fg_value |= _COLOR_HASFG;
|
||||
fg_value |= index;
|
||||
fg_value |= _COLOR_256;
|
||||
}
|
||||
}
|
||||
|
||||
// colorN, where 0 <= N <= 255.
|
||||
else if (word.substr (0, 5) == "color")
|
||||
{
|
||||
index = atoi (word.substr (5).c_str ());
|
||||
if (index < 0 || index > 255)
|
||||
throw std::string ("The color '") + *it + "' is not recognized.";
|
||||
|
||||
upgrade ();
|
||||
|
||||
if (bg)
|
||||
{
|
||||
bg_value |= _COLOR_HASBG;
|
||||
bg_value |= index << 8;
|
||||
bg_value |= _COLOR_256;
|
||||
}
|
||||
else
|
||||
{
|
||||
fg_value |= _COLOR_HASFG;
|
||||
fg_value |= index;
|
||||
fg_value |= _COLOR_256;
|
||||
}
|
||||
}
|
||||
else if (word != "")
|
||||
throw std::string ("The color '") + *it + "' is not recognized.";
|
||||
}
|
||||
|
||||
// Now combine the fg and bg into a single color.
|
||||
value = fg_value;
|
||||
blend (Color (bg_value));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Color::Color (color_id fg)
|
||||
: value (0)
|
||||
{
|
||||
if (fg != Color::nocolor)
|
||||
{
|
||||
value |= _COLOR_HASFG;
|
||||
value |= fg;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Color::Color (color_id fg, color_id bg)
|
||||
: value (0)
|
||||
{
|
||||
if (bg != Color::nocolor)
|
||||
{
|
||||
value |= _COLOR_HASBG;
|
||||
value |= (bg << 8);
|
||||
}
|
||||
|
||||
if (fg != Color::nocolor)
|
||||
{
|
||||
value |= _COLOR_HASFG;
|
||||
value |= fg;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Color::Color (color_id fg, color_id bg, bool underline, bool bold, bool bright)
|
||||
: value (0)
|
||||
{
|
||||
value |= ((underline ? 1 : 0) << 18)
|
||||
| ((bold ? 1 : 0) << 17)
|
||||
| ((bright ? 1 : 0) << 16);
|
||||
|
||||
if (bg != Color::nocolor)
|
||||
{
|
||||
value |= _COLOR_HASBG;
|
||||
value |= (bg << 8);
|
||||
}
|
||||
|
||||
if (fg != Color::nocolor)
|
||||
{
|
||||
value |= _COLOR_HASFG;
|
||||
value |= fg;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Color::~Color ()
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Color& Color::operator= (const Color& other)
|
||||
{
|
||||
if (this != &other)
|
||||
value = other.value;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Color::operator std::string () const
|
||||
{
|
||||
std::string description;
|
||||
if (value & _COLOR_BOLD) description += "bold";
|
||||
|
||||
if (value & _COLOR_UNDERLINE)
|
||||
description += std::string (description.length () ? " " : "") + "underline";
|
||||
|
||||
if (value & _COLOR_HASFG)
|
||||
description += std::string (description.length () ? " " : "") + fg ();
|
||||
|
||||
if (value & _COLOR_HASBG)
|
||||
{
|
||||
description += std::string (description.length () ? " " : "") + "on";
|
||||
|
||||
if (value & _COLOR_BRIGHT)
|
||||
description += std::string (description.length () ? " " : "") + "bright";
|
||||
|
||||
description += " " + bg ();
|
||||
}
|
||||
|
||||
return description;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Color::operator int () const
|
||||
{
|
||||
return (int) value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// If 'other' has styles that are compatible, merge them into this. Colors in
|
||||
// other take precedence.
|
||||
void Color::blend (const Color& other)
|
||||
{
|
||||
Color c (other);
|
||||
value |= (c.value & _COLOR_UNDERLINE); // Always inherit underline.
|
||||
|
||||
// 16 <-- 16.
|
||||
if (!(value & _COLOR_256) &&
|
||||
!(c.value & _COLOR_256))
|
||||
{
|
||||
value |= (c.value & _COLOR_BOLD); // Inherit bold.
|
||||
value |= (c.value & _COLOR_BRIGHT); // Inherit bright.
|
||||
|
||||
if (c.value & _COLOR_HASFG)
|
||||
{
|
||||
value |= _COLOR_HASFG; // There is now a color.
|
||||
value &= ~_COLOR_FG; // Remove previous color.
|
||||
value |= (c.value & _COLOR_FG); // Apply other color.
|
||||
}
|
||||
|
||||
if (c.value & _COLOR_HASBG)
|
||||
{
|
||||
value |= _COLOR_HASBG; // There is now a color.
|
||||
value &= ~_COLOR_BG; // Remove previous color.
|
||||
value |= (c.value & _COLOR_BG); // Apply other color.
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Upgrade either color, if necessary.
|
||||
if (!(value & _COLOR_256)) upgrade ();
|
||||
if (!(c.value & _COLOR_256)) c.upgrade ();
|
||||
|
||||
// 256 <-- 256.
|
||||
if (c.value & _COLOR_HASFG)
|
||||
{
|
||||
value |= _COLOR_HASFG; // There is now a color.
|
||||
value &= ~_COLOR_FG; // Remove previous color.
|
||||
value |= (c.value & _COLOR_FG); // Apply other color.
|
||||
}
|
||||
|
||||
if (c.value & _COLOR_HASBG)
|
||||
{
|
||||
value |= _COLOR_HASBG; // There is now a color.
|
||||
value &= ~_COLOR_BG; // Remove previous color.
|
||||
value |= (c.value & _COLOR_BG); // Apply other color.
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Color::upgrade ()
|
||||
{
|
||||
if (!(value & _COLOR_256))
|
||||
{
|
||||
if (value & _COLOR_HASFG)
|
||||
{
|
||||
bool bold = value & _COLOR_BOLD;
|
||||
unsigned int fg = value & _COLOR_FG;
|
||||
value &= ~_COLOR_FG;
|
||||
value &= ~_COLOR_BOLD;
|
||||
value |= (bold ? fg + 7 : fg - 1);
|
||||
}
|
||||
|
||||
if (value & _COLOR_HASBG)
|
||||
{
|
||||
bool bright = value & _COLOR_BRIGHT;
|
||||
unsigned int bg = (value & _COLOR_BG) >> 8;
|
||||
value &= ~_COLOR_BG;
|
||||
value &= ~_COLOR_BRIGHT;
|
||||
value |= (bright ? bg + 7 : bg - 1) << 8;
|
||||
}
|
||||
|
||||
value |= _COLOR_256;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Sample color codes:
|
||||
// red \033[31m
|
||||
// bold red \033[91m
|
||||
// underline red \033[4;31m
|
||||
// bold underline red \033[1;4;31m
|
||||
//
|
||||
// on red \033[41m
|
||||
// on bright red \033[101m
|
||||
//
|
||||
// 256 fg \033[38;5;Nm
|
||||
// 256 bg \033[48;5;Nm
|
||||
std::string Color::colorize (const std::string& input)
|
||||
{
|
||||
if (value == 0)
|
||||
return input;
|
||||
|
||||
int count = 0;
|
||||
std::stringstream result;
|
||||
|
||||
// 256 color
|
||||
if (value & _COLOR_256)
|
||||
{
|
||||
bool needTerminator = false;
|
||||
|
||||
if (value & _COLOR_UNDERLINE)
|
||||
{
|
||||
result << "\033[4m";
|
||||
needTerminator = true;
|
||||
}
|
||||
|
||||
if (value & _COLOR_HASFG)
|
||||
{
|
||||
result << "\033[38;5;" << (value & _COLOR_FG) << "m";
|
||||
needTerminator = true;
|
||||
}
|
||||
|
||||
if (value & _COLOR_HASBG)
|
||||
{
|
||||
result << "\033[48;5;" << ((value & _COLOR_BG) >> 8) << "m";
|
||||
needTerminator = true;
|
||||
}
|
||||
|
||||
result << input;
|
||||
if (needTerminator)
|
||||
result << "\033[0m";
|
||||
|
||||
return result.str ();
|
||||
}
|
||||
|
||||
// 16 color
|
||||
if (value != 0)
|
||||
{
|
||||
result << "\033[";
|
||||
|
||||
if (value & _COLOR_BOLD)
|
||||
{
|
||||
if (count++) result << ";";
|
||||
result << "1";
|
||||
}
|
||||
|
||||
if (value & _COLOR_UNDERLINE)
|
||||
{
|
||||
if (count++) result << ";";
|
||||
result << "4";
|
||||
}
|
||||
|
||||
if (value & _COLOR_HASFG)
|
||||
{
|
||||
if (count++) result << ";";
|
||||
result << (29 + (value & _COLOR_FG));
|
||||
}
|
||||
|
||||
if (value & _COLOR_HASBG)
|
||||
{
|
||||
if (count++) result << ";";
|
||||
result << ((value & _COLOR_BRIGHT ? 99 : 39) + ((value & _COLOR_BG) >> 8));
|
||||
}
|
||||
|
||||
result << "m" << input << "\033[0m";
|
||||
return result.str ();
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string Color::colorize (const std::string& input, const std::string& spec)
|
||||
{
|
||||
Color c (spec);
|
||||
return c.colorize (input);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Color::nontrivial ()
|
||||
{
|
||||
return value != 0 ? true : false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int Color::find (const std::string& input)
|
||||
{
|
||||
for (unsigned int i = 0; i < NUM_COLORS; ++i)
|
||||
if (allColors[i].english_name == input)
|
||||
return (int) i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string Color::fg () const
|
||||
{
|
||||
int index = value & _COLOR_FG;
|
||||
|
||||
if (value & _COLOR_256)
|
||||
{
|
||||
if (value & _COLOR_HASFG)
|
||||
{
|
||||
std::stringstream s;
|
||||
s << "color" << (value & _COLOR_FG);
|
||||
return s.str ();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 0; i < NUM_COLORS; ++i)
|
||||
if (allColors[i].index == index)
|
||||
return allColors[i].english_name;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string Color::bg () const
|
||||
{
|
||||
int index = (value & _COLOR_BG) >> 8;
|
||||
|
||||
if (value & _COLOR_256)
|
||||
{
|
||||
if (value & _COLOR_HASBG)
|
||||
{
|
||||
std::stringstream s;
|
||||
s << "color" << ((value & _COLOR_BG) >> 8);
|
||||
return s.str ();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 0; i < NUM_COLORS; ++i)
|
||||
if (allColors[i].index == index)
|
||||
return allColors[i].english_name;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
78
src/Color.h
Normal file
78
src/Color.h
Normal file
@@ -0,0 +1,78 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2010, 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_COLOR
|
||||
#define INCLUDED_COLOR
|
||||
|
||||
#include <string>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define _COLOR_256 0x00200000 // 256-color mode.
|
||||
#define _COLOR_HASBG 0x00100000 // Has background color (all values taken).
|
||||
#define _COLOR_HASFG 0x00080000 // Has foreground color (all values taken).
|
||||
#define _COLOR_UNDERLINE 0x00040000 // General underline attribute.
|
||||
#define _COLOR_BOLD 0x00020000 // 16-color bold attribute.
|
||||
#define _COLOR_BRIGHT 0x00010000 // 16-color bright background attribute.
|
||||
#define _COLOR_BG 0x0000FF00 // 8-bit background color index.
|
||||
#define _COLOR_FG 0x000000FF // 8-bit foreground color index.
|
||||
|
||||
class Color
|
||||
{
|
||||
public:
|
||||
enum color_id {nocolor = 0, black, red, green, yellow, blue, magenta, cyan, white};
|
||||
|
||||
Color ();
|
||||
Color (const Color&);
|
||||
Color (unsigned int); // 256 | UNDERLINE | BOLD | BRIGHT | (BG << 8) | FG
|
||||
Color (const std::string&); // "red on bright black"
|
||||
Color (color_id); // fg.
|
||||
Color (color_id, color_id); // fg, bg.
|
||||
Color (color_id, color_id, bool, bool, bool); // fg, bg, underline, bold, bright
|
||||
~Color ();
|
||||
Color& operator= (const Color&);
|
||||
operator std::string () const;
|
||||
operator int () const;
|
||||
|
||||
void upgrade ();
|
||||
void blend (const Color&);
|
||||
|
||||
std::string colorize (const std::string&);
|
||||
static std::string colorize (const std::string&, const std::string&);
|
||||
|
||||
bool nontrivial ();
|
||||
|
||||
private:
|
||||
int find (const std::string&);
|
||||
std::string fg () const;
|
||||
std::string bg () const;
|
||||
|
||||
private:
|
||||
unsigned int value;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
694
src/Config.cpp
694
src/Config.cpp
@@ -1,7 +1,7 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -27,30 +27,279 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <pwd.h>
|
||||
#include "Directory.h"
|
||||
#include "File.h"
|
||||
#include "Config.h"
|
||||
#include "text.h"
|
||||
#include "util.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// These are default (but overridable) reports. These entries are necessary
|
||||
// because these three reports were converted from hard-coded reports to custom
|
||||
// reports, and therefore need these config file entries. However, users are
|
||||
// already used to seeing these five reports, but do not have these entries.
|
||||
// The choice was a) make users edit their .taskrc files, b) write a .taskrc
|
||||
// upgrade program to make the change, or c) this.
|
||||
// This string is used in two ways:
|
||||
// 1) It is used to create a new .taskrc file, by copying it directly to disk.
|
||||
// 2) It is parsed and used as default values for all Config.get calls.
|
||||
std::string Config::defaults =
|
||||
"# Task program configuration file.\n"
|
||||
"# For more documentation, see http://taskwarrior.org or try 'man task', 'man task-faq',\n"
|
||||
"# 'man task-tutorial', 'man task-color' or 'man taskrc'\n"
|
||||
"\n"
|
||||
"# Here is an example of entries that use the default, override and blank values\n"
|
||||
"# variable=foo -- By specifying a value, this overrides the default\n"
|
||||
"# variable= -- By specifying no value, this means no default\n"
|
||||
"# #variable=foo -- By commenting out the line, this uses the default\n"
|
||||
"\n"
|
||||
"# Files\n"
|
||||
"data.location=~/.task\n"
|
||||
"locking=on # Use file-level locking\n"
|
||||
"\n"
|
||||
"# Terminal\n"
|
||||
"curses=on # Use ncurses library to determine terminal width\n"
|
||||
"defaultwidth=80 # Without ncurses, assumed width\n"
|
||||
"#editor=vi # Preferred text editor\n"
|
||||
"\n"
|
||||
"# Miscellaneous\n"
|
||||
"confirmation=yes # Confirmation on delete, big changes\n"
|
||||
"echo.command=yes # Details on command just run\n"
|
||||
"annotations=full # Level of verbosity for annotations: full, sparse or none\n"
|
||||
"next=2 # How many tasks per project in next report\n"
|
||||
"bulk=2 # > 2 tasks considered 'a lot', for confirmation\n"
|
||||
"nag=You have higher priority tasks. # Nag message to keep you honest\n" // TODO
|
||||
"search.case.sensitive=yes # Setting to no allows case insensitive searches\n"
|
||||
"active.indicator=* # What to show as an active task indicator\n"
|
||||
"tag.indicator=+ # What to show as a tag indicator\n"
|
||||
"recurrence.indicator=R # What to show as a task recurrence indicator\n"
|
||||
"\n"
|
||||
"# Dates\n"
|
||||
"dateformat=m/d/Y # Preferred input and display date format\n"
|
||||
"dateformat.holiday=YMD # Preferred input date format for holidays\n"
|
||||
"dateformat.report=m/d/Y # Preferred display date format for repors\n"
|
||||
"weekstart=Sunday # Sunday or Monday only\n"
|
||||
"displayweeknumber=yes # Show week numbers on calendar\n"
|
||||
"due=7 # Task is considered due in 7 days\n"
|
||||
"\n"
|
||||
"# Calendar controls\n"
|
||||
"calendar.legend=yes # Display the legend on calendar\n"
|
||||
"calendar.details=sparse # Calendar shows information for tasks w/due dates: full, sparse or none\n"
|
||||
"calendar.details.report=list # Report to use when showing task information in cal\n"
|
||||
"calendar.holidays=none # Show public holidays on calendar:full, sparse or none\n"
|
||||
"#monthsperline=3 # Number of calendar months on a line\n"
|
||||
"\n"
|
||||
"# Color controls.\n"
|
||||
"color=on # Enable color\n"
|
||||
"#color.header=bold green # Color of header messages\n"
|
||||
"#color.footnote=bold green # Color of footnote messages\n"
|
||||
"color.calendar.today=black on cyan # Color of today in calendar\n"
|
||||
"color.calendar.due=black on green # Color of days with due tasks in calendar\n"
|
||||
"color.calendar.due.today=black on magenta # Color of today with due tasks in calendar\n"
|
||||
"color.calendar.overdue=black on red # Color of days with overdue tasks in calendar\n"
|
||||
"color.calendar.weekend=bright white on black # Color of weekend days in calendar\n"
|
||||
"color.calendar.holiday=black on bright yellow # Color of public holidays in calendar\n"
|
||||
"color.calendar.weeknumber=black on white # Color of the weeknumbers in calendar\n"
|
||||
"#color.debug=magenta # Color of diagnostic output\n"
|
||||
"\n"
|
||||
"# The following rules are presented in their order of precedence.\n"
|
||||
"# The higher the color rule is up this list, the higher precedence\n"
|
||||
"# it has in determining the color for the task. Precedence is shown\n"
|
||||
"# in brackets [1]\n"
|
||||
"#color.recurring=on red # [1] Color of recur.any: tasks\n"
|
||||
"color.overdue=bold red # [2] Color of overdue tasks\n"
|
||||
"color.due.today=bold magenta # [3] Color of tasks due today\n"
|
||||
"color.due=bold yellow # [4] Color of due tasks\n"
|
||||
"#color.keyword.car=on blue # [5] Color of description.contains:car tasks\n"
|
||||
"#color.project.garden=on green # [6] Color of project:garden tasks\n"
|
||||
"#color.tag.bug=yellow # [7] Color of +bug tasks\n"
|
||||
"color.active=bold cyan # [8] Color of active tasks\n"
|
||||
"#color.pri.none=white on blue # [9] Color of priority: tasks\n"
|
||||
"color.pri.H=bold # [9] Color of priority:H tasks\n"
|
||||
"#color.pri.M=on yellow # [9] Color of priority:M tasks\n"
|
||||
"#color.pri.L=on green # [9] Color of priority:L tasks\n"
|
||||
"color.tagged=yellow # [10] Color of tagged tasks\n"
|
||||
"#color.alternate=on rgb253 # [11] Alternate color for line coloring\n"
|
||||
"\n"
|
||||
"# Shadow file support\n"
|
||||
"#shadow.file=/tmp/shadow.txt # Location of shadow file\n"
|
||||
"#shadow.command=list # Task command for shadow file\n"
|
||||
"#shadow.notify=on # Footnote when updated\n"
|
||||
"\n"
|
||||
"#default.project=foo # Default project for 'add' command\n"
|
||||
"#default.priority=M # Default priority for 'add' command\n"
|
||||
"default.command=list # When no arguments are specified\n"
|
||||
"\n"
|
||||
"_forcecolor=no # Forces color to be on, even for non TTY output\n"
|
||||
"blanklines=true # Use more whitespace in output\n"
|
||||
"complete.all.projects=no # Include old project names in 'projects' command\n" // TODO
|
||||
"complete.all.tags=no # Include old tag names in 'tags' command\n" // TODO
|
||||
"debug=no # Display diagnostics\n"
|
||||
"hooks=off # Hook system master switch\n"
|
||||
"fontunderline=yes # Uses underlines rather than -------\n"
|
||||
"shell.prompt=task> # Prompt used by the shell command\n" // TODO
|
||||
"\n"
|
||||
"# Import heuristics - alternate names for fields (comma-separated list of names)\n"
|
||||
"#import.synonym.bg=?\n"
|
||||
"#import.synonym.description=?\n"
|
||||
"#import.synonym.due=?\n"
|
||||
"#import.synonym.end=?\n"
|
||||
"#import.synonym.entry=?\n"
|
||||
"#import.synonym.fg=?\n"
|
||||
"#import.synonym.id=?\n"
|
||||
"#import.synonym.priority=?\n"
|
||||
"#import.synonym.project=?\n"
|
||||
"#import.synonym.recur=?\n"
|
||||
"#import.synonym.start=?\n"
|
||||
"#import.synonym.status=?\n"
|
||||
"#import.synonym.tags=?\n"
|
||||
"#import.synonym.uuid=?\n"
|
||||
"\n"
|
||||
"# Aliases - alternate names for commands\n"
|
||||
"alias.rm=delete # Alias for the delete command\n"
|
||||
"\n"
|
||||
"# Fields: id,uuid,project,priority,priority_long,entry,entry_time,\n" // TODO
|
||||
"# start,entry_time,due,recur,recurrence_indicator,age,\n" // TODO
|
||||
"# age_compact,active,tags,tag_indicator,description,\n" // TODO
|
||||
"# description_only,end,end_time,countdown,countdown_compact\n" // TODO
|
||||
"# Description: This report is ...\n"
|
||||
"# Sort: due+,priority-,project+\n"
|
||||
"# Filter: pro:x pri:H +bug limit:10\n"
|
||||
"# Dateformat: due date format in reports\n"
|
||||
"\n"
|
||||
"# task long\n"
|
||||
"report.long.description=Lists all task, all data, matching the specified criteria\n"
|
||||
"report.long.columns=id,project,priority,entry,start,due,recur,countdown,age,tags,description\n"
|
||||
"report.long.labels=ID,Project,Pri,Added,Started,Due,Recur,Countdown,Age,Tags,Description\n"
|
||||
"report.long.sort=due+,priority-,project+\n"
|
||||
"report.long.filter=status:pending\n"
|
||||
"#report.long.dateformat=m/d/Y\n"
|
||||
"#report.long.annotations=full\n"
|
||||
"\n"
|
||||
"# task list\n"
|
||||
"report.list.description=Lists all tasks matching the specified criteria\n"
|
||||
"report.list.columns=id,project,priority,due,active,age,description\n"
|
||||
"report.list.labels=ID,Project,Pri,Due,Active,Age,Description\n"
|
||||
"report.list.sort=due+,priority-,project+\n"
|
||||
"report.list.filter=status:pending\n"
|
||||
"#report.list.dateformat=m/d/Y\n"
|
||||
"#report.list.annotations=full\n"
|
||||
"\n"
|
||||
"# task ls\n"
|
||||
"report.ls.description=Minimal listing of all tasks matching the specified criteria\n"
|
||||
"report.ls.columns=id,project,priority,description\n"
|
||||
"report.ls.labels=ID,Project,Pri,Description\n"
|
||||
"report.ls.sort=priority-,project+\n"
|
||||
"report.ls.filter=status:pending\n"
|
||||
"#report.ls.dateformat=m/d/Y\n"
|
||||
"#report.ls.annotations=full\n"
|
||||
"\n"
|
||||
"# task minimal\n"
|
||||
"report.minimal.description=A really minimal listing\n"
|
||||
"report.minimal.columns=id,project,description\n"
|
||||
"report.minimal.labels=ID,Project,Description\n"
|
||||
"report.minimal.sort=project+,description+\n"
|
||||
"report.minimal.filter=status:pending\n"
|
||||
"#report.minimal.dateformat=m/d/Y\n"
|
||||
"#report.minimal.annotations=full\n"
|
||||
"\n"
|
||||
"# task newest\n"
|
||||
"report.newest.description=Shows the newest tasks\n"
|
||||
"report.newest.columns=id,project,priority,due,active,age,description\n"
|
||||
"report.newest.labels=ID,Project,Pri,Due,Active,Age,Description\n"
|
||||
"report.newest.sort=id-\n"
|
||||
"report.newest.filter=status:pending limit:10\n"
|
||||
"#report.newest.dateformat=m/d/Y\n"
|
||||
"#report.newest.annotations=full\n"
|
||||
"\n"
|
||||
"# task oldest\n"
|
||||
"report.oldest.description=Shows the oldest tasks\n"
|
||||
"report.oldest.columns=id,project,priority,due,active,age,description\n"
|
||||
"report.oldest.labels=ID,Project,Pri,Due,Active,Age,Description\n"
|
||||
"report.oldest.sort=id+\n"
|
||||
"report.oldest.filter=status:pending limit:10\n"
|
||||
"#report.oldest.dateformat=m/d/Y\n"
|
||||
"#report.oldest.annotations=full\n"
|
||||
"\n"
|
||||
"# task overdue\n"
|
||||
"report.overdue.description=Lists overdue tasks matching the specified criteria\n"
|
||||
"report.overdue.columns=id,project,priority,due,active,age,description\n"
|
||||
"report.overdue.labels=ID,Project,Pri,Due,Active,Age,Description\n"
|
||||
"report.overdue.sort=due+,priority-,project+\n"
|
||||
"report.overdue.filter=status:pending due.before:today\n"
|
||||
"#report.overdue.dateformat=m/d/Y\n"
|
||||
"#report.overdue.annotations=full\n"
|
||||
"\n"
|
||||
"# task active\n"
|
||||
"report.active.description=Lists active tasks matching the specified criteria\n"
|
||||
"report.active.columns=id,project,priority,due,active,age,description\n"
|
||||
"report.active.labels=ID,Project,Pri,Due,Active,Age,Description\n"
|
||||
"report.active.sort=due+,priority-,project+\n"
|
||||
"report.active.filter=status:pending start.any:\n"
|
||||
"#report.active.dateformat=m/d/Y\n"
|
||||
"#report.active.annotations=full\n"
|
||||
"\n"
|
||||
"# task completed\n"
|
||||
"report.completed.description=Lists completed tasks matching the specified criteria\n"
|
||||
"report.completed.columns=end,project,priority,age,description\n"
|
||||
"report.completed.labels=Complete,Project,Pri,Age,Description\n"
|
||||
"report.completed.sort=end+,priority-,project+\n"
|
||||
"report.completed.filter=status:completed\n"
|
||||
"#report.completed.dateformat=m/d/Y\n"
|
||||
"#report.completed.annotations=full\n"
|
||||
"\n"
|
||||
"# task recurring\n"
|
||||
"report.recurring.description=Lists recurring tasks matching the specified criteria\n"
|
||||
"report.recurring.columns=id,project,priority,due,recur,active,age,description\n"
|
||||
"report.recurring.labels=ID,Project,Pri,Due,Recur,Active,Age,Description\n"
|
||||
"report.recurring.sort=due+,priority-,project+\n"
|
||||
"report.recurring.filter=status:pending parent.any:\n"
|
||||
"#report.recurring.dateformat=m/d/Y\n"
|
||||
"#report.recurring.annotations=full\n"
|
||||
"\n"
|
||||
"# task waiting\n"
|
||||
"report.waiting.description=Lists all waiting tasks matching the specified criteria\n"
|
||||
"report.waiting.columns=id,project,priority,wait,age,description\n"
|
||||
"report.waiting.labels=ID,Project,Pri,Wait,Age,Description\n"
|
||||
"report.waiting.sort=wait+,priority-,project+\n"
|
||||
"report.waiting.filter=status:waiting\n"
|
||||
"#report.waiting.dateformat=m/d/Y\n"
|
||||
"#report.waiting.annotations=full\n"
|
||||
"\n"
|
||||
"# task all\n"
|
||||
"report.all.description=Lists all tasks matching the specified criteria\n"
|
||||
"report.all.columns=id,project,priority,due,active,age,description\n"
|
||||
"report.all.labels=ID,Project,Pri,Due,Active,Age,Description\n"
|
||||
"report.all.sort=due+,priority-,project+\n"
|
||||
"#report.all.dateformat=m/d/Y\n"
|
||||
"#report.all.annotations=full\n"
|
||||
"\n"
|
||||
"# task next\n"
|
||||
"report.next.description=Lists the most urgent tasks\n"
|
||||
"report.next.columns=id,project,priority,due,active,age,description\n"
|
||||
"report.next.labels=ID,Project,Pri,Due,Active,Age,Description\n"
|
||||
"report.next.sort=due+,priority-,project+\n"
|
||||
"report.next.filter=status:pending\n"
|
||||
"#report.next.dateformat=m/d/Y\n"
|
||||
"#report.next.annotations=full\n"
|
||||
"\n";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// DO NOT CALL Config::setDefaults.
|
||||
//
|
||||
// This is a default constructor, and as such is only used to:
|
||||
// a) initialize a default Context constructor
|
||||
// b) run unit tests
|
||||
//
|
||||
// In all real use cases, Config::load is called.
|
||||
Config::Config ()
|
||||
{
|
||||
setDefaults ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Config::Config (const std::string& file)
|
||||
{
|
||||
setDefaults ();
|
||||
load (file);
|
||||
}
|
||||
|
||||
@@ -58,288 +307,121 @@ Config::Config (const std::string& file)
|
||||
// Read the Configuration file and populate the *this map. The file format is
|
||||
// simply lines with name=value pairs. Whitespace between name, = and value is
|
||||
// not tolerated, but blank lines and comments starting with # are allowed.
|
||||
bool Config::load (const std::string& file)
|
||||
//
|
||||
// Nested files are now supported, with the following construct:
|
||||
// include /absolute/path/to/file
|
||||
//
|
||||
void Config::load (const std::string& file, int nest /* = 1 */)
|
||||
{
|
||||
std::ifstream in;
|
||||
in.open (file.c_str (), std::ifstream::in);
|
||||
if (in.good ())
|
||||
if (nest > 10)
|
||||
throw std::string ("Configuration file nested to more than 10 levels deep"
|
||||
" - this has to be a mistake.");
|
||||
|
||||
// First time in, load the default values.
|
||||
if (nest == 1)
|
||||
{
|
||||
std::string line;
|
||||
while (getline (in, line))
|
||||
{
|
||||
// Remove comments.
|
||||
std::string::size_type pound = line.find ("#"); // no i18n
|
||||
if (pound != std::string::npos)
|
||||
line = line.substr (0, pound);
|
||||
|
||||
line = trim (line, " \t"); // no i18n
|
||||
|
||||
// Skip empty lines.
|
||||
if (line.length () > 0)
|
||||
{
|
||||
std::string::size_type equal = line.find ("="); // no i18n
|
||||
if (equal != std::string::npos)
|
||||
{
|
||||
std::string key = trim (line.substr (0, equal), " \t"); // no i18n
|
||||
std::string value = trim (line.substr (equal+1, line.length () - equal), " \t"); // no i18n
|
||||
(*this)[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
in.close ();
|
||||
return true;
|
||||
setDefaults ();
|
||||
original_file = File (file);
|
||||
}
|
||||
|
||||
return false;
|
||||
// Read the file, then parse the contents.
|
||||
std::string contents;
|
||||
if (File::read (file, contents) && contents.length ())
|
||||
parse (contents, nest);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Config::parse (const std::string& input, int nest /* = 1 */)
|
||||
{
|
||||
// Shortcut case for default constructor.
|
||||
if (input.length () == 0)
|
||||
return;
|
||||
|
||||
// Split the input into lines.
|
||||
std::vector <std::string> lines;
|
||||
split (lines, input, "\n");
|
||||
|
||||
// Parse each line.
|
||||
std::vector <std::string>::iterator it;
|
||||
for (it = lines.begin (); it != lines.end (); ++it)
|
||||
{
|
||||
std::string line = *it;
|
||||
|
||||
// Remove comments.
|
||||
std::string::size_type pound = line.find ("#"); // no i18n
|
||||
if (pound != std::string::npos)
|
||||
line = line.substr (0, pound);
|
||||
|
||||
line = trim (line, " \t"); // no i18n
|
||||
|
||||
// Skip empty lines.
|
||||
if (line.length () > 0)
|
||||
{
|
||||
std::string::size_type equal = line.find ("="); // no i18n
|
||||
if (equal != std::string::npos)
|
||||
{
|
||||
std::string key = trim (line.substr (0, equal), " \t"); // no i18n
|
||||
std::string value = trim (line.substr (equal+1, line.length () - equal), " \t"); // no i18n
|
||||
|
||||
(*this)[key] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string::size_type include = line.find ("include"); // no i18n.
|
||||
if (include != std::string::npos)
|
||||
{
|
||||
Path included (trim (line.substr (include + 7), " \t"));
|
||||
if (included.is_absolute ())
|
||||
{
|
||||
if (included.readable ())
|
||||
this->load (included, nest + 1);
|
||||
else
|
||||
throw std::string ("Could not read include file '") + included.data + "'";
|
||||
}
|
||||
else
|
||||
throw std::string ("Can only include files with absolute paths, not '") + included.data + "'";
|
||||
}
|
||||
else
|
||||
throw std::string ("Malformed entry '") + line + "'";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Config::createDefaultRC (const std::string& rc, const std::string& data)
|
||||
{
|
||||
// Create a sample .taskrc file.
|
||||
std::stringstream contents;
|
||||
contents << "# Task program configuration file.\n"
|
||||
<< "# For more documentation, see http://taskwarrior.org\n"
|
||||
<< "\n"
|
||||
<< "# Files\n"
|
||||
<< "data.location=" << data << "\n"
|
||||
<< "locking=on # Use file-level locking\n"
|
||||
<< "\n"
|
||||
<< "# Terminal\n"
|
||||
<< "curses=on # Use ncurses library to determine terminal width\n"
|
||||
<< "#defaultwidth=80 # Without ncurses, assumed width\n"
|
||||
<< "#editor=vi # Preferred text editor\n"
|
||||
<< "\n"
|
||||
<< "# Miscellaneous\n"
|
||||
<< "confirmation=yes # Confirmation on delete, big changes\n"
|
||||
<< "echo.command=yes # Details on command just run\n"
|
||||
<< "next=2 # How many tasks per project in next report\n"
|
||||
<< "bulk=2 # > 2 tasks considered 'a lot', for confirmation\n"
|
||||
<< "nag=You have higher priority tasks. # Nag message to keep you honest\n"
|
||||
<< "\n"
|
||||
<< "# Dates\n"
|
||||
<< "dateformat=m/d/Y # Preferred input and display date format\n"
|
||||
<< "weekstart=Sunday # Sunday or Monday only\n"
|
||||
<< "displayweeknumber=yes # Show week numbers on calendar\n"
|
||||
<< "due=7 # Task is considered due in 7 days\n"
|
||||
<< "#monthsperline=2 # Number of calendar months on a line\n"
|
||||
<< "\n"
|
||||
<< "# Color controls.\n"
|
||||
<< "color=on # Use color\n"
|
||||
<< "color.overdue=bold_red # Color of overdue tasks\n"
|
||||
<< "color.due=bold_yellow # Color of due tasks\n"
|
||||
<< "color.pri.H=bold # Color of priority:H tasks\n"
|
||||
<< "#color.pri.M=on_yellow # Color of priority:M tasks\n"
|
||||
<< "#color.pri.L=on_green # Color of priority:L tasks\n"
|
||||
<< "#color.pri.none=white on_blue # Color of priority: tasks\n"
|
||||
<< "color.active=bold_cyan # Color of active tasks\n"
|
||||
<< "color.tagged=yellow # Color of tagged tasks\n"
|
||||
<< "#color.tag.bug=yellow # Color of +bug tasks\n"
|
||||
<< "#color.project.garden=on_green # Color of project:garden tasks\n"
|
||||
<< "#color.keyword.car=on_blue # Color of description.contains:car tasks\n"
|
||||
<< "#color.recurring=on_red # Color of recur.any: tasks\n"
|
||||
<< "#color.header=bold_green # Color of header messages\n"
|
||||
<< "#color.footnote=bold_green # Color of footnote messages\n"
|
||||
<< "\n"
|
||||
<< "#shadow.file=/tmp/shadow.txt # Location of shadow file\n"
|
||||
<< "#shadow.command=list # Task command for shadow file\n"
|
||||
<< "#shadow.notify=on # Footnote when updated\n"
|
||||
<< "\n"
|
||||
<< "#default.project=foo # Unless otherwise specified\n"
|
||||
<< "#default.priority=M # Unless otherwise specified\n"
|
||||
<< "default.command=list # Unless otherwise specified\n"
|
||||
<< "\n"
|
||||
<< "# Fields: id,uuid,project,priority,entry,start,due,recur,recur_ind,age,\n"
|
||||
<< "# age_compact,active,tags,description,description_only\n"
|
||||
<< "# Description: This report is ...\n"
|
||||
<< "# Sort: due+,priority-,project+\n"
|
||||
<< "# Filter: pro:x pri:H +bug limit:10\n"
|
||||
<< "\n"
|
||||
<< "# task long\n"
|
||||
<< "report.long.description=Lists all task, all data, matching the specified criteria\n"
|
||||
<< "report.long.columns=id,project,priority,entry,start,due,recur,age,tags,description\n"
|
||||
<< "report.long.labels=ID,Project,Pri,Added,Started,Due,Recur,Age,Tags,Description\n"
|
||||
<< "report.long.sort=due+,priority-,project+\n"
|
||||
<< "report.long.filter=status:pending\n"
|
||||
<< "\n"
|
||||
<< "# task list\n"
|
||||
<< "report.list.description=Lists all tasks matching the specified criteria\n"
|
||||
<< "report.list.columns=id,project,priority,due,active,age,description\n"
|
||||
<< "report.list.labels=ID,Project,Pri,Due,Active,Age,Description\n"
|
||||
<< "report.list.sort=due+,priority-,project+\n"
|
||||
<< "report.list.filter=status:pending\n"
|
||||
<< "\n"
|
||||
<< "# task ls\n"
|
||||
<< "report.ls.description=Minimal listing of all tasks matching the specified criteria\n"
|
||||
<< "report.ls.columns=id,project,priority,description\n"
|
||||
<< "report.ls.labels=ID,Project,Pri,Description\n"
|
||||
<< "report.ls.sort=priority-,project+\n"
|
||||
<< "report.ls.filter=status:pending\n"
|
||||
<< "\n"
|
||||
<< "# task newest\n"
|
||||
<< "report.newest.description=Shows the newest tasks\n"
|
||||
<< "report.newest.columns=id,project,priority,due,active,age,description\n"
|
||||
<< "report.newest.labels=ID,Project,Pri,Due,Active,Age,Description\n"
|
||||
<< "report.newest.sort=id-\n"
|
||||
<< "report.newest.filter=status:pending limit:10\n"
|
||||
<< "\n"
|
||||
<< "# task oldest\n"
|
||||
<< "report.oldest.description=Shows the oldest tasks\n"
|
||||
<< "report.oldest.columns=id,project,priority,due,active,age,description\n"
|
||||
<< "report.oldest.labels=ID,Project,Pri,Due,Active,Age,Description\n"
|
||||
<< "report.oldest.sort=id+\n"
|
||||
<< "report.oldest.filter=status:pending limit:10\n"
|
||||
<< "\n"
|
||||
<< "# task overdue\n"
|
||||
<< "report.overdue.description=Lists overdue tasks matching the specified criteria\n"
|
||||
<< "report.overdue.columns=id,project,priority,due,active,age,description\n"
|
||||
<< "report.overdue.labels=ID,Project,Pri,Due,Active,Age,Description\n"
|
||||
<< "report.overdue.sort=due+,priority-,project+\n"
|
||||
<< "report.overdue.filter=status:pending due.before:today\n"
|
||||
<< "\n"
|
||||
<< "# task active\n"
|
||||
<< "report.active.description=Lists active tasks matching the specified criteria\n"
|
||||
<< "report.active.columns=id,project,priority,due,active,age,description\n"
|
||||
<< "report.active.labels=ID,Project,Pri,Due,Active,Age,Description\n"
|
||||
<< "report.active.sort=due+,priority-,project+\n"
|
||||
<< "report.active.filter=status:pending start.any:\n"
|
||||
<< "\n"
|
||||
<< "# task completed\n"
|
||||
<< "report.completed.description=Lists completed tasks matching the specified criteria\n"
|
||||
<< "report.completed.columns=end,project,priority,age,description\n"
|
||||
<< "report.completed.labels=Complete,Project,Pri,Age,Description\n"
|
||||
<< "report.completed.sort=end+,priority-,project+\n"
|
||||
<< "report.completed.filter=status:completed\n"
|
||||
<< "\n"
|
||||
<< "# task recurring\n"
|
||||
<< "report.recurring.description=Lists recurring tasks matching the specified criteria\n"
|
||||
<< "report.recurring.columns=id,project,priority,due,recur,active,age,description\n"
|
||||
<< "report.recurring.labels=ID,Project,Pri,Due,Recur,Active,Age,Description\n"
|
||||
<< "report.recurring.sort=due+,priority-,project+\n"
|
||||
<< "report.recurring.filter=status:pending parent.any:\n"
|
||||
<< "\n"
|
||||
<< "# task waiting\n"
|
||||
<< "report.waiting.description=Lists all waiting tasks matching the specified criteria\n"
|
||||
<< "report.waiting.columns=id,project,priority,wait,age,description\n"
|
||||
<< "report.waiting.labels=ID,Project,Pri,Wait,Age,Description\n"
|
||||
<< "report.waiting.sort=wait+,priority-,project+\n"
|
||||
<< "report.waiting.filter=status:waiting\n"
|
||||
<< "\n"
|
||||
<< "# task all\n"
|
||||
<< "report.all.description=Lists all tasks matching the specified criteria\n"
|
||||
<< "report.all.columns=id,project,priority,due,active,age,description\n"
|
||||
<< "report.all.labels=ID,Project,Pri,Due,Active,Age,Description\n"
|
||||
<< "report.all.sort=due+,priority-,project+\n"
|
||||
<< "\n"
|
||||
<< "# task next\n"
|
||||
<< "report.next.description=Lists the most urgent tasks\n"
|
||||
<< "report.next.columns=id,project,priority,due,active,age,description\n"
|
||||
<< "report.next.labels=ID,Project,Pri,Due,Active,Age,Description\n"
|
||||
<< "report.next.sort=due+,priority-,project+\n"
|
||||
<< "report.next.filter=status:pending\n"
|
||||
<< "\n";
|
||||
// Override data.location in the defaults.
|
||||
std::string::size_type loc = defaults.find ("data.location=~/.task");
|
||||
// loc+0^ +14^ +21^
|
||||
|
||||
spit (rc, contents.str ());
|
||||
std::string contents = defaults.substr (0, loc + 14) +
|
||||
data +
|
||||
defaults.substr (loc + 21, std::string::npos);
|
||||
|
||||
// Write out the new file.
|
||||
if (! File::write (rc, contents))
|
||||
throw std::string ("Could not write to '") + rc + "'";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Config::createDefaultData (const std::string& data)
|
||||
{
|
||||
if (access (data.c_str (), F_OK))
|
||||
mkdir (data.c_str (), S_IRWXU);
|
||||
Directory d (data);
|
||||
if (! d.exists ())
|
||||
d.create ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Config::setDefaults ()
|
||||
{
|
||||
set ("report.long.description", "Lists all task, all data, matching the specified criteria"); // TODO i18n
|
||||
set ("report.long.columns", "id,project,priority,entry,start,due,recur,age,tags,description"); // TODO i18n
|
||||
set ("report.long.labels", "ID,Project,Pri,Added,Started,Due,Recur,Age,Tags,Description"); // TODO i18n
|
||||
set ("report.long.sort", "due+,priority-,project+"); // TODO i18n
|
||||
set ("report.long.filter", "status:pending"); // TODO i18n
|
||||
|
||||
set ("report.list.description", "Lists all tasks matching the specified criteria"); // TODO i18n
|
||||
set ("report.list.columns", "id,project,priority,due,active,age,description"); // TODO i18n
|
||||
set ("report.list.labels", "ID,Project,Pri,Due,Active,Age,Description"); // TODO i18n
|
||||
set ("report.list.sort", "due+,priority-,project+"); // TODO i18n
|
||||
set ("report.list.filter", "status:pending"); // TODO i18n
|
||||
|
||||
set ("report.ls.description", "Minimal listing of all tasks matching the specified criteria"); // TODO i18n
|
||||
set ("report.ls.columns", "id,project,priority,description"); // TODO i18n
|
||||
set ("report.ls.labels", "ID,Project,Pri,Description"); // TODO i18n
|
||||
set ("report.ls.sort", "priority-,project+"); // TODO i18n
|
||||
set ("report.ls.filter", "status:pending"); // TODO i18n
|
||||
|
||||
set ("report.newest.description", "Shows the newest tasks"); // TODO i18n
|
||||
set ("report.newest.columns", "id,project,priority,due,active,age,description"); // TODO i18n
|
||||
set ("report.newest.labels", "ID,Project,Pri,Due,Active,Age,Description"); // TODO i18n
|
||||
set ("report.newest.sort", "id-"); // TODO i18n
|
||||
set ("report.newest.filter", "status:pending limit:10"); // TODO i18n
|
||||
|
||||
set ("report.oldest.description", "Shows the oldest tasks"); // TODO i18n
|
||||
set ("report.oldest.columns", "id,project,priority,due,active,age,description"); // TODO i18n
|
||||
set ("report.oldest.labels", "ID,Project,Pri,Due,Active,Age,Description"); // TODO i18n
|
||||
set ("report.oldest.sort", "id+"); // TODO i18n
|
||||
set ("report.oldest.filter", "status:pending limit:10"); // TODO i18n
|
||||
|
||||
set ("report.overdue.description", "Lists overdue tasks matching the specified criteria"); // TODO i18n
|
||||
set ("report.overdue.columns", "id,project,priority,due,active,age,description"); // TODO i18n
|
||||
set ("report.overdue.labels", "ID,Project,Pri,Due,Active,Age,Description"); // TODO i18n
|
||||
set ("report.overdue.sort", "due+,priority-,project+"); // TODO i18n
|
||||
set ("report.overdue.filter", "status:pending due.before:today"); // TODO i18n
|
||||
|
||||
set ("report.active.description", "Lists active tasks matching the specified criteria"); // TODO i18n
|
||||
set ("report.active.columns", "id,project,priority,due,active,age,description"); // TODO i18n
|
||||
set ("report.active.labels", "ID,Project,Pri,Due,Active,Age,Description"); // TODO i18n
|
||||
set ("report.active.sort", "due+,priority-,project+"); // TODO i18n
|
||||
set ("report.active.filter", "status:pending start.any:"); // TODO i18n
|
||||
|
||||
set ("report.completed.description", "Lists completed tasks matching the specified criteria"); // TODO i18n
|
||||
set ("report.completed.columns", "end,project,priority,age,description"); // TODO i18n
|
||||
set ("report.completed.labels", "Complete,Project,Pri,Age,Description"); // TODO i18n
|
||||
set ("report.completed.sort", "end+,priority-,project+"); // TODO i18n
|
||||
set ("report.completed.filter", "status:completed"); // TODO i18n
|
||||
|
||||
set ("report.recurring.description", "Lists recurring tasks matching the specified criteria"); // TODO i18n
|
||||
set ("report.recurring.columns", "id,project,priority,due,recur,active,age,description"); // TODO i18n
|
||||
set ("report.recurring.labels", "ID,Project,Pri,Due,Recur,Active,Age,Description"); // TODO i18n
|
||||
set ("report.recurring.sort", "due+,priority-,project+"); // TODO i18n
|
||||
set ("report.recurring.filter", "status:pending parent.any:"); // TODO i18n
|
||||
|
||||
set ("report.waiting.description", "Lists all waiting tasks matching the specified criteria"); // TODO i18n
|
||||
set ("report.waiting.columns", "id,project,priority,wait,age,description"); // TODO i18n
|
||||
set ("report.waiting.labels", "ID,Project,Pri,Wait,Age,Description"); // TODO i18n
|
||||
set ("report.waiting.sort", "wait+,priority-,project+"); // TODO i18n
|
||||
set ("report.waiting.filter", "status:waiting"); // TODO i18n
|
||||
|
||||
set ("report.all.description", "Lists all tasks matching the specified criteria"); // TODO i18n
|
||||
set ("report.all.columns", "id,project,priority,due,active,age,description"); // TODO i18n
|
||||
set ("report.all.labels", "ID,Project,Pri,Due,Active,Age,Description"); // TODO i18n
|
||||
set ("report.all.sort", "due+,priority-,project+"); // TODO i18n
|
||||
|
||||
set ("report.next.description", "Lists the most urgent tasks"); // TODO i18n
|
||||
set ("report.next.columns", "id,project,priority,due,active,age,description"); // TODO i18n
|
||||
set ("report.next.labels", "ID,Project,Pri,Due,Active,Age,Description"); // TODO i18n
|
||||
set ("report.next.sort", "due+,priority-,project+"); // TODO i18n
|
||||
set ("report.next.filter", "status:pending"); // TODO i18n
|
||||
parse (defaults);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Return the configuration value given the specified key.
|
||||
const std::string Config::get (const char* key)
|
||||
void Config::clear ()
|
||||
{
|
||||
return this->get (std::string (key));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Return the configuration value given the specified key. If a default_value
|
||||
// is present, it will be the returned value in the event of a missing key.
|
||||
const std::string Config::get (
|
||||
const char* key,
|
||||
const char* default_value)
|
||||
{
|
||||
return this->get (std::string (key), std::string (default_value));
|
||||
std::map <std::string, std::string>::clear ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -350,56 +432,42 @@ const std::string Config::get (const std::string& key)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Return the configuration value given the specified key. If a default_value
|
||||
// is present, it will be the returned value in the event of a missing key.
|
||||
const std::string Config::get (
|
||||
const std::string& key,
|
||||
const std::string& default_value)
|
||||
const int Config::getInteger (const std::string& key)
|
||||
{
|
||||
if ((*this).find (key) != (*this).end ())
|
||||
return (*this)[key];
|
||||
return atoi ((*this)[key].c_str ());
|
||||
|
||||
return default_value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Config::get (const std::string& key, const bool default_value)
|
||||
const double Config::getReal (const std::string& key)
|
||||
{
|
||||
if ((*this).find (key) != (*this).end ())
|
||||
return atof ((*this)[key].c_str ());
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const bool Config::getBoolean (const std::string& key)
|
||||
{
|
||||
if ((*this).find (key) != (*this).end ())
|
||||
{
|
||||
std::string value = lowerCase ((*this)[key]);
|
||||
|
||||
if (value == "t" || // TODO i18n
|
||||
value == "true" || // TODO i18n
|
||||
value == "1" || // no i18n
|
||||
value == "+" || // no i18n
|
||||
value == "y" || // TODO i18n
|
||||
value == "yes" || // TODO i18n
|
||||
value == "on" || // TODO i18n
|
||||
value == "enable" || // TODO i18n
|
||||
value == "enabled") // TODO i18n
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return default_value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int Config::get (const std::string& key, const int default_value)
|
||||
{
|
||||
if ((*this).find (key) != (*this).end ())
|
||||
return ::atoi ((*this)[key].c_str ());
|
||||
|
||||
return default_value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
double Config::get (const std::string& key, const double default_value)
|
||||
{
|
||||
if ((*this).find (key) != (*this).end ())
|
||||
return ::atof ((*this)[key].c_str ());
|
||||
|
||||
return default_value;
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -433,3 +501,37 @@ void Config::all (std::vector<std::string>& items)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string Config::checkForDeprecatedColor ()
|
||||
{
|
||||
int count = 0;
|
||||
std::vector <std::string> deprecated;
|
||||
foreach (i, *this)
|
||||
{
|
||||
if (i->first.find ("color.") != std::string::npos)
|
||||
{
|
||||
std::string value = get (i->first);
|
||||
if (value.find ("_") != std::string::npos)
|
||||
{
|
||||
++count;
|
||||
deprecated.push_back (i->first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::stringstream out;
|
||||
if (count)
|
||||
{
|
||||
out << "Your .taskrc file contains color settings that use deprecated "
|
||||
<< "underscores. Please check:"
|
||||
<< std::endl;
|
||||
|
||||
foreach (i, deprecated)
|
||||
out << " " << *i << "=" << get (*i) << std::endl;
|
||||
|
||||
out << std::endl;
|
||||
}
|
||||
|
||||
return out.str ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
28
src/Config.h
28
src/Config.h
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "File.h"
|
||||
|
||||
class Config : public std::map <std::string, std::string>
|
||||
{
|
||||
@@ -40,22 +41,31 @@ public:
|
||||
Config (const Config&);
|
||||
Config& operator= (const Config&);
|
||||
|
||||
bool load (const std::string&);
|
||||
void load (const std::string&, int nest = 1);
|
||||
void parse (const std::string&, int nest = 1);
|
||||
|
||||
void createDefaultRC (const std::string&, const std::string&);
|
||||
void createDefaultData (const std::string&);
|
||||
void setDefaults ();
|
||||
void clear ();
|
||||
|
||||
const std::string get (const std::string&);
|
||||
const int getInteger (const std::string&);
|
||||
const double getReal (const std::string&);
|
||||
const bool getBoolean (const std::string&);
|
||||
|
||||
const std::string get (const char*);
|
||||
const std::string get (const char*, const char*);
|
||||
const std::string get (const std::string&);
|
||||
const std::string get (const std::string&, const std::string&);
|
||||
bool get (const std::string&, const bool);
|
||||
int get (const std::string&, const int);
|
||||
double get (const std::string&, const double);
|
||||
void set (const std::string&, const int);
|
||||
void set (const std::string&, const double);
|
||||
void set (const std::string&, const std::string&);
|
||||
void all (std::vector <std::string>&);
|
||||
|
||||
std::string checkForDeprecatedColor ();
|
||||
|
||||
public:
|
||||
File original_file;
|
||||
|
||||
private:
|
||||
static std::string defaults;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
292
src/Context.cpp
292
src/Context.cpp
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -30,7 +30,10 @@
|
||||
#include <pwd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "Context.h"
|
||||
#include "Directory.h"
|
||||
#include "File.h"
|
||||
#include "Timer.h"
|
||||
#include "text.h"
|
||||
#include "util.h"
|
||||
@@ -49,7 +52,8 @@ Context::Context ()
|
||||
, tdb ()
|
||||
, stringtable ()
|
||||
, program ("")
|
||||
, overrides ("")
|
||||
, file_override ("")
|
||||
, var_overrides ("")
|
||||
, cmd ()
|
||||
, inShadow (false)
|
||||
{
|
||||
@@ -65,6 +69,7 @@ void Context::initialize (int argc, char** argv)
|
||||
{
|
||||
// Capture the args.
|
||||
for (int i = 0; i < argc; ++i)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
program = argv[i];
|
||||
@@ -75,8 +80,14 @@ void Context::initialize (int argc, char** argv)
|
||||
}
|
||||
else
|
||||
args.push_back (argv[i]);
|
||||
}
|
||||
|
||||
initialize ();
|
||||
|
||||
// Hook system init, plus post-start event occurring at the first possible
|
||||
// moment after hook initialization.
|
||||
hooks.initialize ();
|
||||
hooks.trigger ("post-start");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -94,16 +105,16 @@ void Context::initialize ()
|
||||
{
|
||||
config.set ("curses", "off");
|
||||
|
||||
if (! config.get (std::string ("_forcecolor"), false))
|
||||
if (! config.getBoolean ("_forcecolor"))
|
||||
config.set ("color", "off");
|
||||
}
|
||||
|
||||
if (config.get ("color", true))
|
||||
if (config.getBoolean ("color"))
|
||||
initializeColorRules ();
|
||||
|
||||
// Load appropriate stringtable as soon after the config file as possible, to
|
||||
// allow all subsequent messages to be localizable.
|
||||
std::string location = expandPath (config.get ("data.location"));
|
||||
Directory location (config.get ("data.location"));
|
||||
std::string locale = config.get ("locale");
|
||||
|
||||
// If there is a locale variant (en-US.<variant>), then strip it.
|
||||
@@ -112,7 +123,7 @@ void Context::initialize ()
|
||||
locale = locale.substr (0, period);
|
||||
|
||||
if (locale != "")
|
||||
stringtable.load (location + "/strings." + locale);
|
||||
stringtable.load (location.data + "/strings." + locale);
|
||||
|
||||
// TODO Handle "--version, -v" right here?
|
||||
|
||||
@@ -121,15 +132,13 @@ void Context::initialize ()
|
||||
std::vector <std::string> all;
|
||||
split (all, location, ',');
|
||||
foreach (path, all)
|
||||
tdb.location (expandPath (*path));
|
||||
tdb.location (*path);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int Context::run ()
|
||||
{
|
||||
int rc;
|
||||
Timer t ("Context::run");
|
||||
|
||||
std::string output;
|
||||
try
|
||||
{
|
||||
@@ -150,30 +159,39 @@ int Context::run ()
|
||||
}
|
||||
|
||||
// Dump all debug messages.
|
||||
if (config.get (std::string ("debug"), false))
|
||||
hooks.trigger ("pre-debug");
|
||||
if (config.getBoolean ("debug"))
|
||||
foreach (d, debugMessages)
|
||||
if (config.get ("color", true) || config.get (std::string ("_forcecolor"), false))
|
||||
if (config.getBoolean ("color") || config.getBoolean ("_forcecolor"))
|
||||
std::cout << colorizeDebug (*d) << std::endl;
|
||||
else
|
||||
std::cout << *d << std::endl;
|
||||
hooks.trigger ("post-debug");
|
||||
|
||||
// Dump all headers.
|
||||
hooks.trigger ("pre-header");
|
||||
foreach (h, headers)
|
||||
if (config.get ("color", true) || config.get (std::string ("_forcecolor"), false))
|
||||
if (config.getBoolean ("color") || config.getBoolean ("_forcecolor"))
|
||||
std::cout << colorizeHeader (*h) << std::endl;
|
||||
else
|
||||
std::cout << *h << std::endl;
|
||||
hooks.trigger ("post-header");
|
||||
|
||||
// Dump the report output.
|
||||
hooks.trigger ("pre-output");
|
||||
std::cout << output;
|
||||
hooks.trigger ("post-output");
|
||||
|
||||
// Dump all footnotes.
|
||||
hooks.trigger ("pre-footnote");
|
||||
foreach (f, footnotes)
|
||||
if (config.get ("color", true) || config.get (std::string ("_forcecolor"), false))
|
||||
if (config.getBoolean ("color") || config.getBoolean ("_forcecolor"))
|
||||
std::cout << colorizeFootnote (*f) << std::endl;
|
||||
else
|
||||
std::cout << *f << std::endl;
|
||||
hooks.trigger ("post-footnote");
|
||||
|
||||
hooks.trigger ("pre-exit");
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -181,13 +199,17 @@ int Context::run ()
|
||||
int Context::dispatch (std::string &out)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
Timer t ("Context::dispatch");
|
||||
|
||||
hooks.trigger ("pre-dispatch");
|
||||
|
||||
// TODO Just look at this thing. It cries out for a dispatch table.
|
||||
if (cmd.command == "projects") { rc = handleProjects (out); }
|
||||
else if (cmd.command == "tags") { rc = handleTags (out); }
|
||||
else if (cmd.command == "colors") { rc = handleColor (out); }
|
||||
else if (cmd.command == "version") { rc = handleVersion (out); }
|
||||
else if (cmd.command == "config") { rc = handleConfig (out); }
|
||||
else if (cmd.command == "help") { rc = longUsage (out); }
|
||||
else if (cmd.command == "stats") { rc = handleReportStats (out); }
|
||||
else if (cmd.command == "info") { rc = handleInfo (out); }
|
||||
@@ -198,6 +220,7 @@ int Context::dispatch (std::string &out)
|
||||
else if (cmd.command == "timesheet") { rc = handleReportTimesheet (out); }
|
||||
else if (cmd.command == "add") { rc = handleAdd (out); }
|
||||
else if (cmd.command == "append") { rc = handleAppend (out); }
|
||||
else if (cmd.command == "prepend") { rc = handlePrepend (out); }
|
||||
else if (cmd.command == "annotate") { rc = handleAnnotate (out); }
|
||||
else if (cmd.command == "done") { rc = handleDone (out); }
|
||||
else if (cmd.command == "delete") { rc = handleDelete (out); }
|
||||
@@ -216,6 +239,7 @@ int Context::dispatch (std::string &out)
|
||||
else if (cmd.command == "_commands") { rc = handleCompletionCommands (out); }
|
||||
else if (cmd.command == "_ids") { rc = handleCompletionIDs (out); }
|
||||
else if (cmd.command == "_config") { rc = handleCompletionConfig (out); }
|
||||
else if (cmd.command == "_version") { rc = handleCompletionVersion (out); }
|
||||
else if (cmd.command == "" &&
|
||||
sequence.size ()) { rc = handleModify (out); }
|
||||
|
||||
@@ -224,12 +248,15 @@ int Context::dispatch (std::string &out)
|
||||
else if (cmd.validCustom (cmd.command)) { if (!inShadow) tdb.gc (); rc = handleCustomReport (cmd.command, out); }
|
||||
|
||||
// If the command is not recognized, display usage.
|
||||
else { rc = shortUsage (out); }
|
||||
else { hooks.trigger ("pre-usage-command");
|
||||
rc = shortUsage (out);
|
||||
hooks.trigger ("post-usage-command"); }
|
||||
|
||||
// Only update the shadow file if such an update was not suppressed (shadow),
|
||||
if (cmd.isWriteCommand () && !inShadow)
|
||||
shadow ();
|
||||
|
||||
hooks.trigger ("post-dispatch");
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -237,8 +264,8 @@ int Context::dispatch (std::string &out)
|
||||
void Context::shadow ()
|
||||
{
|
||||
// Determine if shadow file is enabled.
|
||||
std::string shadowFile = expandPath (config.get ("shadow.file"));
|
||||
if (shadowFile != "")
|
||||
File shadowFile (config.get ("shadow.file"));
|
||||
if (shadowFile.data != "")
|
||||
{
|
||||
inShadow = true; // Prevents recursion in case shadow command writes.
|
||||
|
||||
@@ -261,8 +288,10 @@ void Context::shadow ()
|
||||
|
||||
// Run report. Use shadow.command, using default.command as a fallback
|
||||
// with "list" as a default.
|
||||
std::string command = config.get ("shadow.command",
|
||||
config.get ("default.command", "list"));
|
||||
std::string command = config.get ("shadow.command");
|
||||
if (command == "")
|
||||
command = config.get ("default.command");
|
||||
|
||||
split (args, command, ' ');
|
||||
|
||||
initialize ();
|
||||
@@ -272,21 +301,21 @@ void Context::shadow ()
|
||||
parse ();
|
||||
std::string result;
|
||||
(void)dispatch (result);
|
||||
std::ofstream out (shadowFile.c_str ());
|
||||
std::ofstream out (shadowFile.data.c_str ());
|
||||
if (out.good ())
|
||||
{
|
||||
out << result;
|
||||
out.close ();
|
||||
}
|
||||
else
|
||||
throw std::string ("Could not write file '") + shadowFile + "'";
|
||||
throw std::string ("Could not write file '") + shadowFile.data + "'";
|
||||
|
||||
config.set ("curses", oldCurses);
|
||||
config.set ("color", oldColor);
|
||||
|
||||
// Optionally display a notification that the shadow file was updated.
|
||||
if (config.get (std::string ("shadow.notify"), false))
|
||||
footnote (std::string ("[Shadow file '") + shadowFile + "' updated]");
|
||||
if (config.getBoolean ("shadow.notify"))
|
||||
footnote (std::string ("[Shadow file '") + shadowFile.data + "' updated]");
|
||||
|
||||
inShadow = false;
|
||||
}
|
||||
@@ -346,60 +375,61 @@ void Context::loadCorrectConfigFile ()
|
||||
"Could not read home directory from the passwd file."));
|
||||
|
||||
std::string home = pw->pw_dir;
|
||||
std::string rc = home + "/.taskrc";
|
||||
std::string data = home + "/.task";
|
||||
File rc (home + "/.taskrc");
|
||||
Directory data (home + "./task");
|
||||
|
||||
// Is there an override for rc?
|
||||
// Is there an file_override for rc:?
|
||||
foreach (arg, args)
|
||||
{
|
||||
if (*arg == "--")
|
||||
break;
|
||||
else if (arg->substr (0, 3) == "rc:")
|
||||
{
|
||||
rc = arg->substr (3, std::string::npos);
|
||||
file_override = *arg;
|
||||
rc = File (arg->substr (3));
|
||||
|
||||
home = rc;
|
||||
std::string::size_type last_slash = rc.rfind ("/");
|
||||
std::string::size_type last_slash = rc.data.rfind ("/");
|
||||
if (last_slash != std::string::npos)
|
||||
home = rc.substr (0, last_slash);
|
||||
home = rc.data.substr (0, last_slash);
|
||||
else
|
||||
home = ".";
|
||||
|
||||
args.erase (arg);
|
||||
header ("Using alternate .taskrc file " + rc); // TODO i18n
|
||||
header ("Using alternate .taskrc file " + rc.data); // TODO i18n
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Load rc file.
|
||||
config.clear (); // Dump current values.
|
||||
config.setDefaults (); // Add in the custom reports.
|
||||
config.load (rc); // Load new file.
|
||||
config.load (rc); // Load new file.
|
||||
|
||||
if (config.get ("data.location") != "")
|
||||
data = config.get ("data.location");
|
||||
data = Directory (config.get ("data.location"));
|
||||
|
||||
// Is there an override for data?
|
||||
// Are there any var_overrides for data.location?
|
||||
foreach (arg, args)
|
||||
{
|
||||
if (*arg == "--")
|
||||
break;
|
||||
else if (arg->substr (0, 17) == "rc.data.location:")
|
||||
else if (arg->substr (0, 17) == "rc.data.location:" ||
|
||||
arg->substr (0, 17) == "rc.data.location=")
|
||||
{
|
||||
data = arg->substr (17, std::string::npos);
|
||||
header ("Using alternate data.location " + data); // TODO i18n
|
||||
data = Directory (arg->substr (17));
|
||||
header ("Using alternate data.location " + data.data); // TODO i18n
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Do we need to create a default rc?
|
||||
if (access (rc.c_str (), F_OK))
|
||||
if (! rc.exists ())
|
||||
{
|
||||
if (confirm ("A configuration file could not be found in " // TODO i18n
|
||||
+ home
|
||||
+ "\n\n"
|
||||
+ "Would you like a sample "
|
||||
+ rc
|
||||
+ rc.data
|
||||
+ " created, so task can proceed?"))
|
||||
{
|
||||
config.createDefaultRC (rc, data);
|
||||
@@ -411,12 +441,13 @@ void Context::loadCorrectConfigFile ()
|
||||
// Create data location, if necessary.
|
||||
config.createDefaultData (data);
|
||||
|
||||
// TODO find out why this was done twice - see tw #355
|
||||
// Load rc file.
|
||||
config.clear (); // Dump current values.
|
||||
config.setDefaults (); // Add in the custom reports.
|
||||
config.load (rc); // Load new file.
|
||||
//config.clear (); // Dump current values.
|
||||
//config.setDefaults (); // Add in the custom reports.
|
||||
//config.load (rc); // Load new file.
|
||||
|
||||
// Apply overrides of type: "rc.name:value"
|
||||
// Apply overrides of type: "rc.name:value", or "rc.name=value".
|
||||
std::vector <std::string> filtered;
|
||||
bool foundTerminator = false;
|
||||
foreach (arg, args)
|
||||
@@ -432,16 +463,16 @@ void Context::loadCorrectConfigFile ()
|
||||
std::string name;
|
||||
std::string value;
|
||||
Nibbler n (*arg);
|
||||
if (n.getUntil ('.', name) &&
|
||||
n.skip ('.') &&
|
||||
n.getUntil (':', name) &&
|
||||
n.skip (':') &&
|
||||
if (n.getUntil ('.', name) &&
|
||||
n.skip ('.') &&
|
||||
n.getUntilOneOf (":=", name) &&
|
||||
n.skipN (1) &&
|
||||
n.getUntilEOS (value))
|
||||
{
|
||||
config.set (name, value);
|
||||
overrides += " " + *arg;
|
||||
var_overrides += " " + *arg;
|
||||
footnote (std::string ("Configuration override ") + // TODO i18n
|
||||
arg->substr (3, std::string::npos));
|
||||
arg->substr (3));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -462,7 +493,7 @@ void Context::loadAliases ()
|
||||
{
|
||||
if (var->substr (0, 6) == "alias.")
|
||||
{
|
||||
std::string alias = var->substr (6, std::string::npos);
|
||||
std::string alias = var->substr (6);
|
||||
std::string canonical = config.get (*var);
|
||||
|
||||
aliases[alias] = canonical;
|
||||
@@ -531,8 +562,8 @@ void Context::parse (
|
||||
throw stringtable.get (TAGS_NO_COMMA,
|
||||
"Tags are not permitted to contain commas.");
|
||||
|
||||
tagAdditions.push_back (arg->substr (1, std::string::npos));
|
||||
parseTask.addTag (arg->substr (1, std::string::npos));
|
||||
tagAdditions.push_back (arg->substr (1));
|
||||
parseTask.addTag (arg->substr (1));
|
||||
}
|
||||
|
||||
// Tags to remove begin with '-'.
|
||||
@@ -548,7 +579,7 @@ void Context::parse (
|
||||
throw stringtable.get (TAGS_NO_COMMA,
|
||||
"Tags are not permitted to contain commas.");
|
||||
|
||||
tagRemovals.push_back (arg->substr (1, std::string::npos));
|
||||
tagRemovals.push_back (arg->substr (1));
|
||||
}
|
||||
|
||||
// Atributes - name[.mod]:[value]
|
||||
@@ -576,6 +607,8 @@ void Context::parse (
|
||||
parseTask[name + "." + mod] = attribute;
|
||||
else
|
||||
parseTask[name] = attribute;
|
||||
|
||||
autoFilter (attribute, parseFilter);
|
||||
}
|
||||
|
||||
// *arg has the appearance of an attribute (foo:bar), but isn't
|
||||
@@ -641,6 +674,19 @@ void Context::parse (
|
||||
{
|
||||
debug ("parse description '" + descCandidate + "'");
|
||||
parseTask.set ("description", descCandidate);
|
||||
|
||||
// Now convert the description to a filter on each word, if necessary.
|
||||
if (parseCmd.isReadOnlyCommand ())
|
||||
{
|
||||
std::vector <std::string> words;
|
||||
split (words, descCandidate, ' ');
|
||||
std::vector <std::string>::iterator it;
|
||||
for (it = words.begin (); it != words.end (); ++it)
|
||||
{
|
||||
Att a ("description", "contains", *it);
|
||||
autoFilter (a, parseFilter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// At this point, either a sequence or a command should have been found.
|
||||
@@ -648,24 +694,31 @@ void Context::parse (
|
||||
parseCmd.parse (descCandidate);
|
||||
|
||||
// Read-only command (reports, status, info ...) use filters. Write commands
|
||||
// (add, done ...) do not.
|
||||
// (add, done ...) do not. The filter was constructed iteratively above, but
|
||||
// tags were omitted, so they are added now.
|
||||
if (parseCmd.isReadOnlyCommand ())
|
||||
autoFilter (parseTask, parseFilter);
|
||||
autoFilter (parseFilter);
|
||||
|
||||
// If no command was specified, and there were no command line arguments
|
||||
// then invoke the default command.
|
||||
if (parseCmd.command == "" && parseArgs.size () == 0)
|
||||
{
|
||||
// Apply overrides, if any.
|
||||
std::string defaultCommand = config.get ("default.command") + overrides;
|
||||
std::string defaultCommand = config.get ("default.command");
|
||||
if (defaultCommand != "")
|
||||
{
|
||||
// Add on the overrides.
|
||||
defaultCommand += " " + file_override + " " + var_overrides;
|
||||
|
||||
// Stuff the command line.
|
||||
args.clear ();
|
||||
split (args, defaultCommand, ' ');
|
||||
header ("[task " + defaultCommand + "]");
|
||||
header ("[task " + trim (defaultCommand) + "]");
|
||||
|
||||
// Reinitialize the context and recurse.
|
||||
file_override = "";
|
||||
var_overrides = "";
|
||||
footnotes.clear ();
|
||||
initialize ();
|
||||
parse (args, cmd, task, sequence, subst, filter);
|
||||
}
|
||||
@@ -677,6 +730,9 @@ void Context::parse (
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Note: The reason some of these are commented out is because the ::clear
|
||||
// method is not really "clear" but "clear_some". Some members do not need to
|
||||
// be initialized. That makes this method something of a misnomer. So be it.
|
||||
void Context::clear ()
|
||||
{
|
||||
// Config config;
|
||||
@@ -690,6 +746,8 @@ void Context::clear ()
|
||||
// stringtable.clear ();
|
||||
program = "";
|
||||
args.clear ();
|
||||
file_override = "";
|
||||
var_overrides = "";
|
||||
cmd.command = "";
|
||||
tagAdditions.clear ();
|
||||
tagRemovals.clear ();
|
||||
@@ -700,78 +758,86 @@ void Context::clear ()
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Add all the attributes in the task to the filter. All except uuid.
|
||||
void Context::autoFilter (Task& t, Filter& f)
|
||||
void Context::autoFilter (Att& a, Filter& f)
|
||||
{
|
||||
foreach (att, t)
|
||||
// Words are found in the description using the .has modifier.
|
||||
if (a.name () == "description" && a.mod () == "")
|
||||
{
|
||||
// Words are found in the description using the .has modifier.
|
||||
if (att->second.name () == "description" && att->second.mod () == "")
|
||||
std::vector <std::string> words;
|
||||
split (words, a.value (), ' ');
|
||||
foreach (word, words)
|
||||
{
|
||||
std::vector <std::string> words;
|
||||
split (words, att->second.value (), ' ');
|
||||
foreach (word, words)
|
||||
{
|
||||
f.push_back (Att ("description", "has", *word));
|
||||
debug ("auto filter: " + att->second.name () + ".has:" + *word);
|
||||
}
|
||||
}
|
||||
|
||||
// Projects are matched left-most.
|
||||
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->second.name () + ".startswith:" + att->second.value ());
|
||||
}
|
||||
else
|
||||
{
|
||||
f.push_back (Att ("project", "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->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->second.name () == "uuid")
|
||||
{
|
||||
}
|
||||
|
||||
// The mechanism for filtering on tags is +/-<tag>.
|
||||
else if (att->second.name () == "tags")
|
||||
{
|
||||
}
|
||||
|
||||
// Generic attribute matching.
|
||||
else
|
||||
{
|
||||
f.push_back (att->second);
|
||||
debug ("auto filter: " +
|
||||
att->second.name () +
|
||||
(att->second.mod () != "" ?
|
||||
("." + att->second.mod () + ":") :
|
||||
":") +
|
||||
att->second.value ());
|
||||
f.push_back (Att ("description", "has", *word));
|
||||
debug ("auto filter: " + a.name () + ".has:" + *word);
|
||||
}
|
||||
}
|
||||
|
||||
// Projects are matched left-most.
|
||||
else if (a.name () == "project" && a.mod () == "")
|
||||
{
|
||||
if (a.value () != "")
|
||||
{
|
||||
f.push_back (Att ("project", "startswith", a.value ()));
|
||||
debug ("auto filter: " + a.name () + ".startswith:" + a.value ());
|
||||
}
|
||||
else
|
||||
{
|
||||
f.push_back (Att ("project", "is", a.value ()));
|
||||
debug ("auto filter: " + a.name () + ".is:" + a.value ());
|
||||
}
|
||||
}
|
||||
|
||||
// The limit attribute does not participate in filtering, and needs to be
|
||||
// specifically handled in handleCustomReport.
|
||||
else if (a.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 (a.name () == "uuid")
|
||||
{
|
||||
}
|
||||
|
||||
// The mechanism for filtering on tags is +/-<tag>.
|
||||
// Do not handle here - see below.
|
||||
else if (a.name () == "tags")
|
||||
{
|
||||
}
|
||||
|
||||
// Generic attribute matching.
|
||||
else
|
||||
{
|
||||
f.push_back (a);
|
||||
debug ("auto filter: " +
|
||||
a.name () +
|
||||
(a.mod () != "" ?
|
||||
("." + a.mod () + ":") :
|
||||
":") +
|
||||
a.value ());
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Add all the tags in the task to the filter.
|
||||
void Context::autoFilter (Filter& f)
|
||||
{
|
||||
// This is now a correct implementation of a filter on the presence or absence
|
||||
// of a tag. The prior code provided the illusion of leftmost partial tag
|
||||
// matches, but was really using the 'contains' and 'nocontains' attribute
|
||||
// modifiers. See bug #293.
|
||||
|
||||
// Include tagAdditions.
|
||||
foreach (tag, tagAdditions)
|
||||
{
|
||||
f.push_back (Att ("tags", "has", *tag));
|
||||
f.push_back (Att ("tags", "word", *tag));
|
||||
debug ("auto filter: +" + *tag);
|
||||
}
|
||||
|
||||
// Include tagRemovals.
|
||||
foreach (tag, tagRemovals)
|
||||
{
|
||||
f.push_back (Att ("tags", "hasnt", *tag));
|
||||
f.push_back (Att ("tags", "noword", *tag));
|
||||
debug ("auto filter: -" + *tag);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "Task.h"
|
||||
#include "TDB.h"
|
||||
#include "StringTable.h"
|
||||
#include "Hooks.h"
|
||||
|
||||
class Context
|
||||
{
|
||||
@@ -70,7 +71,8 @@ public:
|
||||
private:
|
||||
void loadCorrectConfigFile ();
|
||||
void loadAliases ();
|
||||
void autoFilter (Task&, Filter&);
|
||||
void autoFilter (Att&, Filter&);
|
||||
void autoFilter (Filter&);
|
||||
|
||||
public:
|
||||
Config config;
|
||||
@@ -83,11 +85,13 @@ public:
|
||||
StringTable stringtable;
|
||||
std::string program;
|
||||
std::vector <std::string> args;
|
||||
std::string overrides;
|
||||
std::string file_override;
|
||||
std::string var_overrides;
|
||||
Cmd cmd;
|
||||
std::map <std::string, std::string> aliases;
|
||||
std::vector <std::string> tagAdditions;
|
||||
std::vector <std::string> tagRemovals;
|
||||
Hooks hooks;
|
||||
|
||||
private:
|
||||
std::vector <std::string> headers;
|
||||
|
||||
231
src/Date.cpp
231
src/Date.cpp
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham, Federico Hernandez.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -29,9 +29,13 @@
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include "Date.h"
|
||||
#include "text.h"
|
||||
#include "util.h"
|
||||
#include "Context.h"
|
||||
|
||||
extern Context context;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Defaults to "now".
|
||||
@@ -82,103 +86,166 @@ Date::Date (const std::string& mdy, const std::string& format /* = "m/d/Y" */)
|
||||
// Single or double digit.
|
||||
case 'm':
|
||||
if (i >= mdy.length () ||
|
||||
! ::isdigit (mdy[i]))
|
||||
! isdigit (mdy[i]))
|
||||
{
|
||||
throw std::string ("\"") + mdy + "\" is not a valid date.";
|
||||
throw std::string ("\"") + mdy + "\" is not a valid date (m).";
|
||||
}
|
||||
|
||||
if (i + 1 < mdy.length () &&
|
||||
(mdy[i + 0] == '0' || mdy[i + 0] == '1') &&
|
||||
::isdigit (mdy[i + 1]))
|
||||
isdigit (mdy[i + 1]))
|
||||
{
|
||||
month = ::atoi (mdy.substr (i, 2).c_str ());
|
||||
month = atoi (mdy.substr (i, 2).c_str ());
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
month = ::atoi (mdy.substr (i, 1).c_str ());
|
||||
month = atoi (mdy.substr (i, 1).c_str ());
|
||||
++i;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
if (i >= mdy.length () ||
|
||||
! ::isdigit (mdy[i]))
|
||||
! isdigit (mdy[i]))
|
||||
{
|
||||
throw std::string ("\"") + mdy + "\" is not a valid date.";
|
||||
throw std::string ("\"") + mdy + "\" is not a valid date (d).";
|
||||
}
|
||||
|
||||
if (i + 1 < mdy.length () &&
|
||||
(mdy[i + 0] == '0' || mdy[i + 0] == '1' || mdy[i + 0] == '2' || mdy[i + 0] == '3') &&
|
||||
::isdigit (mdy[i + 1]))
|
||||
isdigit (mdy[i + 1]))
|
||||
{
|
||||
day = ::atoi (mdy.substr (i, 2).c_str ());
|
||||
day = atoi (mdy.substr (i, 2).c_str ());
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
day = ::atoi (mdy.substr (i, 1).c_str ());
|
||||
day = atoi (mdy.substr (i, 1).c_str ());
|
||||
++i;
|
||||
}
|
||||
break;
|
||||
|
||||
// Double digit.
|
||||
case 'y':
|
||||
if (i + 1 >= mdy.length () ||
|
||||
! ::isdigit (mdy[i + 0]) ||
|
||||
! ::isdigit (mdy[i + 1]))
|
||||
if (i + 1 >= mdy.length () ||
|
||||
! isdigit (mdy[i + 0]) ||
|
||||
! isdigit (mdy[i + 1]))
|
||||
{
|
||||
throw std::string ("\"") + mdy + "\" is not a valid date.";
|
||||
throw std::string ("\"") + mdy + "\" is not a valid date (y).";
|
||||
}
|
||||
|
||||
year = ::atoi (mdy.substr (i, 2).c_str ()) + 2000;
|
||||
year = atoi (mdy.substr (i, 2).c_str ()) + 2000;
|
||||
i += 2;
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
if (i + 1 >= mdy.length () ||
|
||||
! ::isdigit (mdy[i + 0]) ||
|
||||
! ::isdigit (mdy[i + 1]))
|
||||
! isdigit (mdy[i + 0]) ||
|
||||
! isdigit (mdy[i + 1]))
|
||||
{
|
||||
throw std::string ("\"") + mdy + "\" is not a valid date.";
|
||||
throw std::string ("\"") + mdy + "\" is not a valid date (M).";
|
||||
}
|
||||
|
||||
month = ::atoi (mdy.substr (i, 2).c_str ());
|
||||
month = atoi (mdy.substr (i, 2).c_str ());
|
||||
i += 2;
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
if (i + 1 >= mdy.length () ||
|
||||
! ::isdigit (mdy[i + 0]) ||
|
||||
! ::isdigit (mdy[i + 1]))
|
||||
! isdigit (mdy[i + 0]) ||
|
||||
! isdigit (mdy[i + 1]))
|
||||
{
|
||||
throw std::string ("\"") + mdy + "\" is not a valid date.";
|
||||
throw std::string ("\"") + mdy + "\" is not a valid date (D).";
|
||||
}
|
||||
|
||||
day = atoi (mdy.substr (i, 2).c_str ());
|
||||
i += 2;
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
if (i + 1 >= mdy.length () ||
|
||||
! isdigit (mdy[i + 0]) ||
|
||||
! isdigit (mdy[i + 1]))
|
||||
{
|
||||
throw std::string ("\"") + mdy + "\" is not a valid date (V).";
|
||||
}
|
||||
|
||||
day = ::atoi (mdy.substr (i, 2).c_str ());
|
||||
i += 2;
|
||||
break;
|
||||
|
||||
// Quadruple digit.
|
||||
case 'Y':
|
||||
if (i + 3 >= mdy.length () ||
|
||||
! ::isdigit (mdy[i + 0]) ||
|
||||
! ::isdigit (mdy[i + 1]) ||
|
||||
! ::isdigit (mdy[i + 2]) ||
|
||||
! ::isdigit (mdy[i + 3]))
|
||||
! isdigit (mdy[i + 0]) ||
|
||||
! isdigit (mdy[i + 1]) ||
|
||||
! isdigit (mdy[i + 2]) ||
|
||||
! isdigit (mdy[i + 3]))
|
||||
{
|
||||
throw std::string ("\"") + mdy + "\" is not a valid date.";
|
||||
throw std::string ("\"") + mdy + "\" is not a valid date (Y).";
|
||||
}
|
||||
|
||||
year = ::atoi (mdy.substr (i, 4).c_str ());
|
||||
year = atoi (mdy.substr (i, 4).c_str ());
|
||||
i += 4;
|
||||
break;
|
||||
|
||||
// Short names with 3 characters
|
||||
case 'a':
|
||||
if (i + 2 >= mdy.length () ||
|
||||
isdigit (mdy[i + 0]) ||
|
||||
isdigit (mdy[i + 1]) ||
|
||||
isdigit (mdy[i + 2]))
|
||||
{
|
||||
throw std::string ("\"") + mdy + "\" is not a valid date (a).";
|
||||
}
|
||||
|
||||
i += 3;
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
if (i + 2 >= mdy.length () ||
|
||||
isdigit (mdy[i + 0]) ||
|
||||
isdigit (mdy[i + 1]) ||
|
||||
isdigit (mdy[i + 2]))
|
||||
{
|
||||
throw std::string ("\"") + mdy + "\" is not a valid date (b).";
|
||||
}
|
||||
|
||||
month = Date::monthOfYear (mdy.substr (i, 3).c_str());
|
||||
i += 3;
|
||||
break;
|
||||
|
||||
// Long names
|
||||
case 'A':
|
||||
if (i + 2 >= mdy.length () ||
|
||||
isdigit (mdy[i + 0]) ||
|
||||
isdigit (mdy[i + 1]) ||
|
||||
isdigit (mdy[i + 2]))
|
||||
{
|
||||
throw std::string ("\"") + mdy + "\" is not a valid date (A).";
|
||||
}
|
||||
|
||||
i += Date::dayName( Date::dayOfWeek (mdy.substr (i, 3).c_str()) ).size();
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
if (i + 2 >= mdy.length () ||
|
||||
isdigit (mdy[i + 0]) ||
|
||||
isdigit (mdy[i + 1]) ||
|
||||
isdigit (mdy[i + 2]))
|
||||
{
|
||||
throw std::string ("\"") + mdy + "\" is not a valid date (B).";
|
||||
}
|
||||
|
||||
month = Date::monthOfYear (mdy.substr (i, 3).c_str());
|
||||
i += Date::monthName(month).size();
|
||||
break;
|
||||
|
||||
default:
|
||||
if (i >= mdy.length () ||
|
||||
mdy[i] != format[f])
|
||||
{
|
||||
throw std::string ("\"") + mdy + "\" is not a valid date.";
|
||||
throw std::string ("\"") + mdy + "\" is not a valid date (DEFAULT).";
|
||||
}
|
||||
++i;
|
||||
break;
|
||||
@@ -189,7 +256,7 @@ Date::Date (const std::string& mdy, const std::string& format /* = "m/d/Y" */)
|
||||
throw std::string ("\"") + mdy + "\" is not a valid date in " + format + " format.";
|
||||
|
||||
if (!valid (month, day, year))
|
||||
throw std::string ("\"") + mdy + "\" is not a valid date.";
|
||||
throw std::string ("\"") + mdy + "\" is not a valid date (VALID).";
|
||||
|
||||
// Duplicate Date::Date (const int, const int, const int);
|
||||
struct tm t = {0};
|
||||
@@ -255,13 +322,18 @@ const std::string Date::toString (const std::string& format /*= "m/d/Y" */) cons
|
||||
char c = localFormat[i];
|
||||
switch (c)
|
||||
{
|
||||
case 'm': sprintf (buffer, "%d", this->month ()); break;
|
||||
case 'M': sprintf (buffer, "%02d", this->month ()); break;
|
||||
case 'd': sprintf (buffer, "%d", this->day ()); break;
|
||||
case 'D': sprintf (buffer, "%02d", this->day ()); break;
|
||||
case 'y': sprintf (buffer, "%02d", this->year () % 100); break;
|
||||
case 'Y': sprintf (buffer, "%d", this->year ()); break;
|
||||
default: sprintf (buffer, "%c", c); break;
|
||||
case 'm': sprintf (buffer, "%d", this->month ()); break;
|
||||
case 'M': sprintf (buffer, "%02d", this->month ()); break;
|
||||
case 'd': sprintf (buffer, "%d", this->day ()); break;
|
||||
case 'D': sprintf (buffer, "%02d", this->day ()); break;
|
||||
case 'y': sprintf (buffer, "%02d", this->year () % 100); break;
|
||||
case 'Y': sprintf (buffer, "%d", this->year ()); break;
|
||||
case 'a': sprintf (buffer, "%.3s", Date::dayName (dayOfWeek ()).c_str ()); break;
|
||||
case 'A': sprintf (buffer, "%s", Date::dayName (dayOfWeek ()).c_str ()); break;
|
||||
case 'b': sprintf (buffer, "%.3s", Date::monthName (month ()).c_str ()); break;
|
||||
case 'B': sprintf (buffer, "%.9s", Date::monthName (month ()).c_str ()); break;
|
||||
case 'V': sprintf (buffer, "%02d", Date::weekOfYear (Date::dayOfWeek (context.config.get ("weekstart")))); break;
|
||||
default: sprintf (buffer, "%c", c); break;
|
||||
}
|
||||
|
||||
formatted += buffer;
|
||||
@@ -270,6 +342,19 @@ const std::string Date::toString (const std::string& format /*= "m/d/Y" */) cons
|
||||
return formatted;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const std::string Date::toStringWithTime (const std::string& format /*= "m/d/Y" */) const
|
||||
{
|
||||
// Format as above.
|
||||
std::string formatted = toString (format);
|
||||
|
||||
char buffer[12];
|
||||
sprintf (buffer, " %d:%02d:%02d", hour (), minute (), second ());
|
||||
formatted += buffer;
|
||||
|
||||
return formatted;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Date::valid (const std::string& input, const std::string& format)
|
||||
{
|
||||
@@ -403,7 +488,7 @@ int Date::weekOfYear (int weekStart) const
|
||||
throw std::string ("The 'weekstart' configuration variable may "
|
||||
"only contain 'Sunday' or 'Monday'.");
|
||||
|
||||
int weekNumber = ::atoi (weekStr);
|
||||
int weekNumber = atoi (weekStr);
|
||||
|
||||
if (weekStart == 0)
|
||||
weekNumber += 1;
|
||||
@@ -423,13 +508,34 @@ int Date::dayOfWeek (const std::string& input)
|
||||
{
|
||||
std::string in = lowerCase (input);
|
||||
|
||||
if (in == "sunday") return 0;
|
||||
if (in == "monday") return 1;
|
||||
if (in == "tuesday") return 2;
|
||||
if (in == "wednesday") return 3;
|
||||
if (in == "thursday") return 4;
|
||||
if (in == "friday") return 5;
|
||||
if (in == "saturday") return 6;
|
||||
if (in == "sunday" || in == "sun") return 0;
|
||||
if (in == "monday" || in == "mon") return 1;
|
||||
if (in == "tuesday" || in == "tue") return 2;
|
||||
if (in == "wednesday" || in == "wed") return 3;
|
||||
if (in == "thursday" || in == "thu") return 4;
|
||||
if (in == "friday" || in == "fri") return 5;
|
||||
if (in == "saturday" || in == "sat") return 6;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int Date::monthOfYear (const std::string& input)
|
||||
{
|
||||
std::string in = lowerCase (input);
|
||||
|
||||
if (in == "january" || in == "jan") return 1;
|
||||
if (in == "february" || in == "feb") return 2;
|
||||
if (in == "march" || in == "mar") return 3;
|
||||
if (in == "april" || in == "apr") return 4;
|
||||
if (in == "may" || in == "may") return 5;
|
||||
if (in == "june" || in == "jun") return 6;
|
||||
if (in == "july" || in == "jul") return 7;
|
||||
if (in == "august" || in == "aug") return 8;
|
||||
if (in == "september" || in == "sep") return 9;
|
||||
if (in == "october" || in == "oct") return 10;
|
||||
if (in == "november" || in == "nov") return 11;
|
||||
if (in == "december" || in == "dec") return 12;
|
||||
|
||||
return -1;
|
||||
}
|
||||
@@ -455,6 +561,27 @@ int Date::year () const
|
||||
return t->tm_year + 1900;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int Date::hour () const
|
||||
{
|
||||
struct tm* t = localtime (&mT);
|
||||
return t->tm_hour;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int Date::minute () const
|
||||
{
|
||||
struct tm* t = localtime (&mT);
|
||||
return t->tm_min;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int Date::second () const
|
||||
{
|
||||
struct tm* t = localtime (&mT);
|
||||
return t->tm_sec;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Date::operator== (const Date& rhs)
|
||||
{
|
||||
@@ -553,7 +680,7 @@ bool Date::isEpoch (const std::string& input)
|
||||
if (digitsOnly (input) &&
|
||||
input.length () > 8)
|
||||
{
|
||||
mT = (time_t) ::atoi (input.c_str ());
|
||||
mT = (time_t) atoi (input.c_str ());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -669,13 +796,13 @@ bool Date::isRelativeDate (const std::string& input)
|
||||
|
||||
if (isdigit (input[1]))
|
||||
{
|
||||
number = ::atoi (input.substr (0, 2).c_str ());
|
||||
ordinal = lowerCase (input.substr (2, std::string::npos));
|
||||
number = atoi (input.substr (0, 2).c_str ());
|
||||
ordinal = lowerCase (input.substr (2));
|
||||
}
|
||||
else
|
||||
{
|
||||
number = ::atoi (input.substr (0, 2).c_str ());
|
||||
ordinal = lowerCase (input.substr (1, std::string::npos));
|
||||
number = atoi (input.substr (0, 2).c_str ());
|
||||
ordinal = lowerCase (input.substr (1));
|
||||
}
|
||||
|
||||
// Sanity check.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham, Federico Hernandez.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -47,6 +47,7 @@ public:
|
||||
std::string toEpochString ();
|
||||
void toMDY (int&, int&, int&);
|
||||
const std::string toString (const std::string& format = "m/d/Y") const;
|
||||
const std::string toStringWithTime (const std::string& format = "m/d/Y") const;
|
||||
static bool valid (const std::string&, const std::string& format = "m/d/Y");
|
||||
static bool valid (const int, const int, const int);
|
||||
|
||||
@@ -57,12 +58,16 @@ public:
|
||||
static std::string dayName (int);
|
||||
static int weekOfYear (const std::string&);
|
||||
static int dayOfWeek (const std::string&);
|
||||
static int monthOfYear (const std::string&);
|
||||
|
||||
int month () const;
|
||||
int day () const;
|
||||
int year () const;
|
||||
int weekOfYear (int) const;
|
||||
int dayOfWeek () const;
|
||||
int hour () const;
|
||||
int minute () const;
|
||||
int second () const;
|
||||
|
||||
bool operator== (const Date&);
|
||||
bool operator!= (const Date&);
|
||||
|
||||
144
src/Directory.cpp
Normal file
144
src/Directory.cpp
Normal file
@@ -0,0 +1,144 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free Software
|
||||
// Foundation; either version 2 of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
// details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program; if not, write to the
|
||||
//
|
||||
// Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor,
|
||||
// Boston, MA
|
||||
// 02110-1301
|
||||
// USA
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
#include "Directory.h"
|
||||
#include "../auto.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Directory::Directory ()
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Directory::Directory (const Directory& other)
|
||||
: File::File (other)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Directory::Directory (const File& other)
|
||||
: File::File (other)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Directory::Directory (const Path& other)
|
||||
: File::File (other)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Directory::Directory (const std::string& in)
|
||||
: File::File (in)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Directory::~Directory ()
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Directory& Directory::operator= (const Directory& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
File::operator= (other);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Directory::create ()
|
||||
{
|
||||
return mkdir (data.c_str (), 0755) == 0 ? true : false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Directory::remove ()
|
||||
{
|
||||
return rmdir (data.c_str ()) == 0 ? true : false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::vector <std::string> Directory::list ()
|
||||
{
|
||||
std::vector <std::string> files;
|
||||
list (data, files, false);
|
||||
return files;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::vector <std::string> Directory::listRecursive ()
|
||||
{
|
||||
std::vector <std::string> files;
|
||||
list (data, files, true);
|
||||
return files;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Directory::list (
|
||||
const std::string& base,
|
||||
std::vector <std::string>& results,
|
||||
bool recursive)
|
||||
{
|
||||
DIR* dp = opendir (base.c_str ());
|
||||
if (dp != NULL)
|
||||
{
|
||||
struct dirent* de;
|
||||
while ((de = readdir (dp)) != NULL)
|
||||
{
|
||||
if (!strcmp (de->d_name, ".") ||
|
||||
!strcmp (de->d_name, ".."))
|
||||
continue;
|
||||
|
||||
#if defined (SOLARIS) || defined (HAIKU)
|
||||
struct stat s;
|
||||
stat (de->d_name, &s);
|
||||
if (recursive && s.st_mode & S_IFDIR)
|
||||
list (base + "/" + de->d_name, results, recursive);
|
||||
else
|
||||
results.push_back (base + "/" + de->d_name);
|
||||
#else
|
||||
if (recursive && de->d_type == DT_DIR)
|
||||
list (base + "/" + de->d_name, results, recursive);
|
||||
else
|
||||
results.push_back (base + "/" + de->d_name);
|
||||
#endif
|
||||
}
|
||||
|
||||
closedir (dp);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
55
src/Directory.h
Normal file
55
src/Directory.h
Normal file
@@ -0,0 +1,55 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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_DIRECTORY
|
||||
#define INCLUDED_DIRECTORY
|
||||
|
||||
#include "File.h"
|
||||
|
||||
class Directory : public File
|
||||
{
|
||||
public:
|
||||
Directory ();
|
||||
Directory (const Directory&);
|
||||
Directory (const File&);
|
||||
Directory (const Path&);
|
||||
Directory (const std::string&);
|
||||
virtual ~Directory ();
|
||||
|
||||
Directory& operator= (const Directory&);
|
||||
|
||||
virtual bool create ();
|
||||
virtual bool remove ();
|
||||
|
||||
std::vector <std::string> list ();
|
||||
std::vector <std::string> listRecursive ();
|
||||
|
||||
private:
|
||||
void list (const std::string&, std::vector <std::string>&, bool);
|
||||
};
|
||||
|
||||
#endif
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -116,7 +116,7 @@ bool Duration::valid (const std::string& input) const
|
||||
if (! isdigit (lower_input[i]) &&
|
||||
i == length - 1)
|
||||
{
|
||||
std::string type = lower_input.substr (length - 1, std::string::npos);
|
||||
std::string type = lower_input.substr (length - 1);
|
||||
if (type == "d" || // TODO i18n
|
||||
type == "w" || // TODO i18n
|
||||
type == "m" || // TODO i18n
|
||||
@@ -178,7 +178,7 @@ void Duration::parse (const std::string& input)
|
||||
if (! isdigit (lower_input[i]) &&
|
||||
i == length - 1)
|
||||
{
|
||||
int number = ::atoi (lower_input.substr (0, i).c_str ());
|
||||
int number = atoi (lower_input.substr (0, i).c_str ());
|
||||
|
||||
switch (lower_input[length - 1])
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
|
||||
286
src/File.cpp
Normal file
286
src/File.cpp
Normal file
@@ -0,0 +1,286 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free Software
|
||||
// Foundation; either version 2 of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
// details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program; if not, write to the
|
||||
//
|
||||
// Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor,
|
||||
// Boston, MA
|
||||
// 02110-1301
|
||||
// USA
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <fstream>
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#include <unistd.h>
|
||||
#include "File.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
File::File ()
|
||||
: Path::Path ()
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
File::File (const Path& other)
|
||||
: Path::Path (other)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
File::File (const File& other)
|
||||
: Path::Path (other)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
File::File (const std::string& in)
|
||||
: Path::Path (in)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
File::~File ()
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
File& File::operator= (const File& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
Path::operator= (other);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool File::create ()
|
||||
{
|
||||
std::ofstream out (data.c_str ());
|
||||
if (out.good ())
|
||||
{
|
||||
out.close ();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool File::remove ()
|
||||
{
|
||||
return unlink (data.c_str ()) == 0 ? true : false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// S_IFMT 0170000 type of file
|
||||
// S_IFIFO 0010000 named pipe (fifo)
|
||||
// S_IFCHR 0020000 character special
|
||||
// S_IFDIR 0040000 directory
|
||||
// S_IFBLK 0060000 block special
|
||||
// S_IFREG 0100000 regular
|
||||
// S_IFLNK 0120000 symbolic link
|
||||
// S_IFSOCK 0140000 socket
|
||||
// S_IFWHT 0160000 whiteout
|
||||
// S_ISUID 0004000 set user id on execution
|
||||
// S_ISGID 0002000 set group id on execution
|
||||
// S_ISVTX 0001000 save swapped text even after use
|
||||
// S_IRUSR 0000400 read permission, owner
|
||||
// S_IWUSR 0000200 write permission, owner
|
||||
// S_IXUSR 0000100 execute/search permission, owner
|
||||
mode_t File::mode ()
|
||||
{
|
||||
struct stat s;
|
||||
if (!stat (data.c_str (), &s))
|
||||
return s.st_mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
size_t File::size () const
|
||||
{
|
||||
struct stat s;
|
||||
if (!stat (data.c_str (), &s))
|
||||
return s.st_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool File::create (const std::string& name)
|
||||
{
|
||||
std::ofstream out (expand (name).c_str ());
|
||||
if (out.good ())
|
||||
{
|
||||
out.close ();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string File::read (const std::string& name)
|
||||
{
|
||||
std::string contents = "";
|
||||
|
||||
std::ifstream in (name.c_str ());
|
||||
if (in.good ())
|
||||
{
|
||||
std::string line;
|
||||
while (getline (in, line))
|
||||
contents += line + "\n";
|
||||
|
||||
in.close ();
|
||||
}
|
||||
|
||||
return contents;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool File::read (const std::string& name, std::string& contents)
|
||||
{
|
||||
contents = "";
|
||||
|
||||
std::ifstream in (name.c_str ());
|
||||
if (in.good ())
|
||||
{
|
||||
std::string line;
|
||||
while (getline (in, line))
|
||||
contents += line + "\n";
|
||||
|
||||
in.close ();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool File::read (const std::string& name, std::vector <std::string>& contents)
|
||||
{
|
||||
contents.clear ();
|
||||
|
||||
std::ifstream in (name.c_str ());
|
||||
if (in.good ())
|
||||
{
|
||||
std::string line;
|
||||
while (getline (in, line))
|
||||
contents.push_back (line);
|
||||
|
||||
in.close ();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool File::write (const std::string& name, const std::string& contents)
|
||||
{
|
||||
std::ofstream out (expand (name).c_str (),
|
||||
std::ios_base::out | std::ios_base::trunc);
|
||||
if (out.good ())
|
||||
{
|
||||
out << contents;
|
||||
out.close ();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool File::write (
|
||||
const std::string& name,
|
||||
const std::vector <std::string>& lines,
|
||||
bool addNewlines /* = true */)
|
||||
{
|
||||
std::ofstream out (expand (name).c_str (),
|
||||
std::ios_base::out | std::ios_base::trunc);
|
||||
if (out.good ())
|
||||
{
|
||||
std::vector <std::string>::const_iterator it;
|
||||
for (it = lines.begin (); it != lines.end (); ++it)
|
||||
{
|
||||
out << *it;
|
||||
|
||||
if (addNewlines)
|
||||
out << "\n";
|
||||
}
|
||||
|
||||
out.close ();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool File::append (const std::string& name, const std::string& contents)
|
||||
{
|
||||
std::ofstream out (expand (name).c_str (),
|
||||
std::ios_base::out | std::ios_base::app);
|
||||
if (out.good ())
|
||||
{
|
||||
out << contents;
|
||||
out.close ();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool File::append (
|
||||
const std::string& name,
|
||||
const std::vector <std::string>& lines,
|
||||
bool addNewlines /* = true */)
|
||||
{
|
||||
std::ofstream out (expand (name).c_str (),
|
||||
std::ios_base::out | std::ios_base::app);
|
||||
if (out.good ())
|
||||
{
|
||||
std::vector <std::string>::const_iterator it;
|
||||
for (it = lines.begin (); it != lines.end (); ++it)
|
||||
{
|
||||
out << *it;
|
||||
|
||||
if (addNewlines)
|
||||
out << "\n";
|
||||
}
|
||||
|
||||
out.close ();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool File::remove (const std::string& name)
|
||||
{
|
||||
return unlink (expand (name).c_str ()) == 0 ? true : false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
81
src/File.h
Normal file
81
src/File.h
Normal file
@@ -0,0 +1,81 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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_FILE
|
||||
#define INCLUDED_FILE
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sys/stat.h>
|
||||
#include "Path.h"
|
||||
|
||||
class File : public Path
|
||||
{
|
||||
public:
|
||||
File ();
|
||||
File (const Path&);
|
||||
File (const File&);
|
||||
File (const std::string&);
|
||||
virtual ~File ();
|
||||
|
||||
File& operator= (const File&);
|
||||
|
||||
virtual bool create ();
|
||||
virtual bool remove ();
|
||||
|
||||
// bool open ();
|
||||
// bool openAndLock ();
|
||||
// void close ();
|
||||
|
||||
// bool lock ();
|
||||
// bool lockNoWait ();
|
||||
// void unlock ();
|
||||
|
||||
// void read (std::string&);
|
||||
// void read (std::vector <std::string>&);
|
||||
|
||||
// void write (const std::string&);
|
||||
// void write (const std::vector <std::string>&);
|
||||
|
||||
virtual mode_t mode ();
|
||||
virtual size_t size () const;
|
||||
|
||||
static bool create (const std::string&);
|
||||
static std::string read (const std::string&);
|
||||
static bool read (const std::string&, std::string&);
|
||||
static bool read (const std::string&, std::vector <std::string>&);
|
||||
static bool write (const std::string&, const std::string&);
|
||||
static bool write (const std::string&, const std::vector <std::string>&, bool addNewlines = true);
|
||||
static bool append (const std::string&, const std::string&);
|
||||
static bool append (const std::string&, const std::vector <std::string>&, bool addNewlines = true);
|
||||
static bool remove (const std::string&);
|
||||
|
||||
private:
|
||||
// int handle;
|
||||
};
|
||||
|
||||
#endif
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -42,17 +42,22 @@ bool Filter::pass (const Record& record) const
|
||||
{
|
||||
// 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.
|
||||
// on annotations.
|
||||
//
|
||||
// For positive modifiers (has, is ...) either the description or the
|
||||
// annotation filter must succeed.
|
||||
//
|
||||
// For negative modifiers (hasnt, isnt ...) both the description and the
|
||||
// annotation filter must succeed.
|
||||
if (att->name () == "description")
|
||||
{
|
||||
bool description_result = true;
|
||||
bool pass = true;
|
||||
int annotation_pass_count = 0;
|
||||
int annotation_fail_count = 0;
|
||||
|
||||
if ((r = record.find (att->name ())) != record.end ())
|
||||
{
|
||||
description_result = att->match (r->second);
|
||||
pass = att->match (r->second);
|
||||
|
||||
foreach (ra, record)
|
||||
{
|
||||
@@ -66,6 +71,8 @@ bool Filter::pass (const Record& record) const
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Missing attribute implies failure.
|
||||
else if (! att->match (Att ()))
|
||||
return false;
|
||||
|
||||
@@ -74,12 +81,12 @@ bool Filter::pass (const Record& record) const
|
||||
// are willing to invest a week understanding and testing it.
|
||||
if (att->modType (att->mod ()) == "positive")
|
||||
{
|
||||
if (! (description_result || annotation_pass_count > 0))
|
||||
if (! (pass || annotation_pass_count))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!description_result || annotation_fail_count > 0)
|
||||
if (! (pass && annotation_fail_count == 0))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -125,7 +132,7 @@ void Filter::applySequence (std::vector<Task>& all, Sequence& sequence)
|
||||
std::vector <int> right;
|
||||
listDiff (filteredSequence, (std::vector <int>&)sequence, left, right);
|
||||
if (left.size ())
|
||||
throw std::string ("Sequence filtering error - please report this error");
|
||||
throw std::string ("Sequence filtering error - please report this error to support@taskwarrior.org");
|
||||
|
||||
if (right.size ())
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -326,7 +326,7 @@ Grid::Cell::operator int () const
|
||||
case CELL_INT: return mInt;
|
||||
case CELL_FLOAT: return (int) mFloat;
|
||||
case CELL_DOUBLE: return (int) mDouble;
|
||||
case CELL_STRING: return ::atoi (mString.c_str ());
|
||||
case CELL_STRING: return atoi (mString.c_str ());
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -341,7 +341,7 @@ Grid::Cell::operator float () const
|
||||
case CELL_INT: return (float) mInt;
|
||||
case CELL_FLOAT: return mFloat;
|
||||
case CELL_DOUBLE: return (float) mDouble;
|
||||
case CELL_STRING: return (float) ::atof (mString.c_str ());
|
||||
case CELL_STRING: return (float) atof (mString.c_str ());
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
@@ -356,7 +356,7 @@ Grid::Cell::operator double () const
|
||||
case CELL_INT: return (double) mInt;
|
||||
case CELL_FLOAT: return (double) mFloat;
|
||||
case CELL_DOUBLE: return mDouble;
|
||||
case CELL_STRING: return (double) ::atof (mString.c_str ());
|
||||
case CELL_STRING: return (double) atof (mString.c_str ());
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
|
||||
381
src/Hooks.cpp
Normal file
381
src/Hooks.cpp
Normal file
@@ -0,0 +1,381 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free Software
|
||||
// Foundation; either version 2 of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
// details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program; if not, write to the
|
||||
//
|
||||
// Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor,
|
||||
// Boston, MA
|
||||
// 02110-1301
|
||||
// USA
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <iostream>
|
||||
#include "Context.h"
|
||||
#include "Hooks.h"
|
||||
#include "Timer.h"
|
||||
|
||||
extern Context context;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Hook::Hook ()
|
||||
: event ("")
|
||||
, file ("")
|
||||
, function ("")
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Hook::Hook (const std::string& e, const std::string& f, const std::string& fn)
|
||||
: event (e)
|
||||
, file (f)
|
||||
, function (fn)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Hook::Hook (const Hook& other)
|
||||
{
|
||||
event = other.event;
|
||||
file = other.file;
|
||||
function = other.function;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Hook& Hook::operator= (const Hook& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
event = other.event;
|
||||
file = other.file;
|
||||
function = other.function;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Hooks::Hooks ()
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Hooks::~Hooks ()
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Enumerate all hooks, and tell API about the script files it must load in
|
||||
// order to call them. Note that API will perform a deferred read, which means
|
||||
// that if it isn't called, a script will not be loaded.
|
||||
void Hooks::initialize ()
|
||||
{
|
||||
#ifdef HAVE_LIBLUA
|
||||
api.initialize ();
|
||||
#endif
|
||||
|
||||
// Allow a master switch to turn the whole thing off.
|
||||
bool big_red_switch = context.config.getBoolean ("hooks");
|
||||
if (big_red_switch)
|
||||
{
|
||||
std::vector <std::string> vars;
|
||||
context.config.all (vars);
|
||||
|
||||
std::vector <std::string>::iterator it;
|
||||
for (it = vars.begin (); it != vars.end (); ++it)
|
||||
{
|
||||
std::string type;
|
||||
std::string name;
|
||||
std::string value;
|
||||
|
||||
// "<type>.<name>"
|
||||
Nibbler n (*it);
|
||||
if (n.getUntil ('.', type) &&
|
||||
type == "hook" &&
|
||||
n.skip ('.') &&
|
||||
n.getUntilEOS (name))
|
||||
{
|
||||
std::string value = context.config.get (*it);
|
||||
Nibbler n (value);
|
||||
|
||||
// <path>:<function> [, ...]
|
||||
while (!n.depleted ())
|
||||
{
|
||||
std::string file;
|
||||
std::string function;
|
||||
if (n.getUntil (':', file) &&
|
||||
n.skip (':') &&
|
||||
n.getUntil (',', function))
|
||||
{
|
||||
context.debug (std::string ("Event '") + name + "' hooked by " + file + ", function " + function);
|
||||
Hook h (name, Path::expand (file), function);
|
||||
all.push_back (h);
|
||||
|
||||
(void) n.skip (',');
|
||||
}
|
||||
else
|
||||
throw std::string ("Malformed hook definition '") + *it + "'";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
context.debug ("Hooks::initialize - hook system shut off");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Program hooks.
|
||||
bool Hooks::trigger (const std::string& event)
|
||||
{
|
||||
#ifdef HAVE_LIBLUA
|
||||
std::vector <Hook>::iterator it;
|
||||
for (it = all.begin (); it != all.end (); ++it)
|
||||
{
|
||||
if (it->event == event)
|
||||
{
|
||||
Timer timer (std::string ("Hooks::trigger ") + event);
|
||||
|
||||
if (validProgramEvent (event))
|
||||
{
|
||||
context.debug (std::string ("Event ") + event + " triggered");
|
||||
if (! api.callProgramHook (it->file, it->function))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
throw std::string ("Unrecognized hook event '") + event + "'";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// List hooks.
|
||||
bool Hooks::trigger (const std::string& event, std::vector <Task>& tasks)
|
||||
{
|
||||
#ifdef HAVE_LIBLUA
|
||||
std::vector <Hook>::iterator it;
|
||||
for (it = all.begin (); it != all.end (); ++it)
|
||||
{
|
||||
if (it->event == event)
|
||||
{
|
||||
Timer timer (std::string ("Hooks::trigger ") + event);
|
||||
|
||||
if (validListEvent (event))
|
||||
{
|
||||
context.debug (std::string ("Event ") + event + " triggered");
|
||||
if (! api.callListHook (it->file, it->function, tasks))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
throw std::string ("Unrecognized hook event '") + event + "'";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Task hooks.
|
||||
bool Hooks::trigger (const std::string& event, Task& task)
|
||||
{
|
||||
#ifdef HAVE_LIBLUA
|
||||
std::vector <Hook>::iterator it;
|
||||
for (it = all.begin (); it != all.end (); ++it)
|
||||
{
|
||||
if (it->event == event)
|
||||
{
|
||||
Timer timer (std::string ("Hooks::trigger ") + event);
|
||||
|
||||
if (validTaskEvent (event))
|
||||
{
|
||||
context.debug (std::string ("Event ") + event + " triggered");
|
||||
if (! api.callTaskHook (it->file, it->function, task))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
throw std::string ("Unrecognized hook event '") + event + "'";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Field hooks.
|
||||
bool Hooks::trigger (
|
||||
const std::string& event,
|
||||
const std::string& name,
|
||||
std::string& value)
|
||||
{
|
||||
#ifdef HAVE_LIBLUA
|
||||
std::vector <Hook>::iterator it;
|
||||
for (it = all.begin (); it != all.end (); ++it)
|
||||
{
|
||||
if (it->event == event)
|
||||
{
|
||||
Timer timer (std::string ("Hooks::trigger ") + event);
|
||||
|
||||
if (validFieldEvent (event))
|
||||
{
|
||||
context.debug (std::string ("Event ") + event + " triggered");
|
||||
if (! api.callFieldHook (it->file, it->function, name, value))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
throw std::string ("Unrecognized hook event '") + event + "'";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Hooks::validProgramEvent (const std::string& event)
|
||||
{
|
||||
if (event == "post-start" ||
|
||||
event == "pre-fatal-error" ||
|
||||
event == "pre-exit" ||
|
||||
event == "pre-command-line" || event == "post-command-line" ||
|
||||
event == "pre-command-line-override" || event == "post-command-line-override" ||
|
||||
event == "pre-config-create" || event == "post-config-create" ||
|
||||
event == "pre-config-read" || event == "post-config-read" ||
|
||||
event == "pre-config-value-read" || event == "post-config-value-read" ||
|
||||
event == "pre-config-value-write" || event == "post-config-value-write" ||
|
||||
event == "pre-file-lock" || event == "post-file-lock" ||
|
||||
event == "pre-file-unlock" || event == "post-file-unlock" ||
|
||||
event == "pre-file-read" || event == "post-file-read" ||
|
||||
event == "pre-file-write" || event == "post-file-write" ||
|
||||
event == "pre-output" || event == "post-output" ||
|
||||
event == "pre-debug" || event == "post-debug" ||
|
||||
event == "pre-header" || event == "post-header" ||
|
||||
event == "pre-footnote" || event == "post-footnote" ||
|
||||
event == "pre-dispatch" || event == "post-dispatch" ||
|
||||
event == "pre-gc" || event == "post-gc" ||
|
||||
event == "pre-archive" || event == "post-archive" ||
|
||||
event == "pre-purge" || event == "post-purge" ||
|
||||
event == "pre-recurrence" || event == "post-recurrence" ||
|
||||
event == "pre-interactive" || event == "post-interactive" ||
|
||||
event == "pre-undo" || event == "post-undo" ||
|
||||
event == "pre-confirm" || event == "post-confirm" ||
|
||||
event == "pre-shell-prompt" || event == "post-shell-prompt" ||
|
||||
event == "pre-add-command" || event == "post-add-command" ||
|
||||
event == "pre-annotate-command" || event == "post-annotate-command" ||
|
||||
event == "pre-append-command" || event == "post-append-command" ||
|
||||
event == "pre-calendar-command" || event == "post-calendar-command" ||
|
||||
event == "pre-color-command" || event == "post-color-command" ||
|
||||
event == "pre-config-command" || event == "post-config-command" ||
|
||||
event == "pre-custom-report-command" || event == "post-custom-report-command" ||
|
||||
event == "pre-default-command" || event == "post-default-command" ||
|
||||
event == "pre-delete-command" || event == "post-delete-command" ||
|
||||
event == "pre-done-command" || event == "post-done-command" ||
|
||||
event == "pre-duplicate-command" || event == "post-duplicate-command" ||
|
||||
event == "pre-edit-command" || event == "post-edit-command" ||
|
||||
event == "pre-export-command" || event == "post-export-command" ||
|
||||
event == "pre-ghistory-command" || event == "post-ghistory-command" ||
|
||||
event == "pre-history-command" || event == "post-history-command" ||
|
||||
event == "pre-import-command" || event == "post-import-command" ||
|
||||
event == "pre-info-command" || event == "post-info-command" ||
|
||||
event == "pre-prepend-command" || event == "post-prepend-command" ||
|
||||
event == "pre-projects-command" || event == "post-projects-command" ||
|
||||
event == "pre-shell-command" || event == "post-shell-command" ||
|
||||
event == "pre-start-command" || event == "post-start-command" ||
|
||||
event == "pre-stats-command" || event == "post-stats-command" ||
|
||||
event == "pre-stop-command" || event == "post-stop-command" ||
|
||||
event == "pre-summary-command" || event == "post-summary-command" ||
|
||||
event == "pre-tags-command" || event == "post-tags-command" ||
|
||||
event == "pre-timesheet-command" || event == "post-timesheet-command" ||
|
||||
event == "pre-undo-command" || event == "post-undo-command" ||
|
||||
event == "pre-usage-command" || event == "post-usage-command" ||
|
||||
event == "pre-version-command" || event == "post-version-command")
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Hooks::validListEvent (const std::string& event)
|
||||
{
|
||||
if (event == "pre-filter" || event == "post-filter")
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Hooks::validTaskEvent (const std::string& event)
|
||||
{
|
||||
if (event == "pre-display" ||
|
||||
event == "pre-modification" || event == "post-modification" ||
|
||||
event == "pre-delete" || event == "post-delete" ||
|
||||
event == "pre-add" || event == "post-add" ||
|
||||
event == "pre-undo" || event == "post-undo" ||
|
||||
event == "pre-wait" || event == "post-wait" ||
|
||||
event == "pre-unwait" || event == "post-unwait" ||
|
||||
event == "pre-completed" || event == "post-completed" ||
|
||||
event == "pre-priority-change" || event == "post-priority-change" ||
|
||||
event == "pre-project-change" || event == "post-project-change" ||
|
||||
event == "pre-substitution" || event == "post-substitution" ||
|
||||
event == "pre-annotation" || event == "post-annotation" ||
|
||||
event == "pre-tag" || event == "post-tag" ||
|
||||
event == "pre-detag" || event == "post-detag" ||
|
||||
event == "pre-colorization" || event == "post-colorization")
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Hooks::validFieldEvent (const std::string& event)
|
||||
{
|
||||
if (
|
||||
event == "format-number" ||
|
||||
event == "format-date" ||
|
||||
event == "format-duration" ||
|
||||
event == "format-text" ||
|
||||
event == "format-id" ||
|
||||
event == "format-uuid" ||
|
||||
event == "format-project" ||
|
||||
event == "format-priority" ||
|
||||
event == "format-priority_long" ||
|
||||
event == "format-entry" ||
|
||||
event == "format-entry_time" ||
|
||||
event == "format-start" ||
|
||||
event == "format-start_time" ||
|
||||
event == "format-end" ||
|
||||
event == "format-end_time" ||
|
||||
event == "format-due" ||
|
||||
event == "format-countdown" ||
|
||||
event == "format-countdown_compact" ||
|
||||
event == "format-age" ||
|
||||
event == "format-age_compact" ||
|
||||
event == "format-active" ||
|
||||
event == "format-tags" ||
|
||||
event == "format-recur" ||
|
||||
event == "format-recurrence_indicator" ||
|
||||
event == "format-tag_indicator" ||
|
||||
event == "format-description_only" ||
|
||||
event == "format-description" ||
|
||||
event == "format-wait")
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
80
src/Hooks.h
Normal file
80
src/Hooks.h
Normal file
@@ -0,0 +1,80 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2010, 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_HOOKS
|
||||
#define INCLUDED_HOOKS
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "API.h"
|
||||
#include "auto.h"
|
||||
|
||||
// Hook class representing a single hook, which is just a three-way map.
|
||||
class Hook
|
||||
{
|
||||
public:
|
||||
Hook ();
|
||||
Hook (const std::string&, const std::string&, const std::string&);
|
||||
Hook (const Hook&);
|
||||
Hook& operator= (const Hook&);
|
||||
|
||||
public:
|
||||
std::string event;
|
||||
std::string file;
|
||||
std::string function;
|
||||
};
|
||||
|
||||
// Hooks class for managing the loading and calling of hook functions.
|
||||
class Hooks
|
||||
{
|
||||
public:
|
||||
Hooks (); // Default constructor
|
||||
~Hooks (); // Destructor
|
||||
Hooks (const Hooks&); // Deliberately unimplemented
|
||||
Hooks& operator= (const Hooks&); // Deliberately unimplemented
|
||||
|
||||
void initialize ();
|
||||
|
||||
bool trigger (const std::string&); // Program
|
||||
bool trigger (const std::string&, std::vector <Task>&); // List
|
||||
bool trigger (const std::string&, Task&); // Task
|
||||
bool trigger (const std::string&, const std::string&, std::string&); // Field
|
||||
|
||||
private:
|
||||
bool validProgramEvent (const std::string&);
|
||||
bool validListEvent (const std::string&);
|
||||
bool validTaskEvent (const std::string&);
|
||||
bool validFieldEvent (const std::string&);
|
||||
|
||||
private:
|
||||
#ifdef HAVE_LIBLUA
|
||||
API api;
|
||||
#endif
|
||||
std::vector <Hook> all; // All current hooks.
|
||||
};
|
||||
|
||||
#endif
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
bin_PROGRAMS = task
|
||||
task_SOURCES = Att.cpp Cmd.cpp Config.cpp Context.cpp Date.cpp Duration.cpp \
|
||||
Filter.cpp Grid.cpp Keymap.cpp Location.cpp Nibbler.cpp \
|
||||
Record.cpp Sequence.cpp StringTable.cpp Subst.cpp Task.cpp \
|
||||
TDB.cpp Table.cpp Timer.cpp Permission.cpp color.cpp edit.cpp \
|
||||
command.cpp import.cpp interactive.cpp recur.cpp report.cpp \
|
||||
custom.cpp rules.cpp main.cpp text.cpp util.cpp \
|
||||
Att.h Cmd.h Config.h Context.h Date.h Duration.h Filter.h \
|
||||
Grid.h Keymap.h Location.h Nibbler.h Record.h Sequence.h \
|
||||
StringTable.h Subst.h Task.h TDB.h Table.h Timer.h \
|
||||
Permission.h color.h i18n.h main.h text.h util.h
|
||||
task_SHORTNAME = t
|
||||
task_SOURCES = API.cpp Att.cpp Cmd.cpp Color.cpp Config.cpp Context.cpp \
|
||||
Date.cpp Directory.cpp Duration.cpp File.cpp Filter.cpp \
|
||||
Grid.cpp Hooks.cpp Keymap.cpp Location.cpp Nibbler.cpp \
|
||||
Path.cpp Permission.cpp Record.cpp Sequence.cpp \
|
||||
StringTable.cpp Subst.cpp TDB.cpp Table.cpp Task.cpp Timer.cpp \
|
||||
command.cpp custom.cpp edit.cpp import.cpp interactive.cpp \
|
||||
main.cpp recur.cpp report.cpp rules.cpp text.cpp util.cpp \
|
||||
API.h Att.h Cmd.h Color.h Config.h Context.h Date.h \
|
||||
Directory.h Duration.h File.h Filter.h Grid.h Hooks.h Keymap.h \
|
||||
Location.h Nibbler.h Path.h Permission.h Record.h Sequence.h \
|
||||
StringTable.h Subst.h TDB.h Table.h Task.h Timer.h i18n.h \
|
||||
main.h text.h util.h
|
||||
task_CPPFLAGS=$(LUA_CFLAGS)
|
||||
task_LDFLAGS=$(LUA_LFLAGS)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -88,7 +88,7 @@ bool Nibbler::getUntil (char c, std::string& result)
|
||||
}
|
||||
else
|
||||
{
|
||||
result = mInput.substr (mCursor, std::string::npos);
|
||||
result = mInput.substr (mCursor);
|
||||
mCursor = mInput.length ();
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ bool Nibbler::getUntil (const std::string& terminator, std::string& result)
|
||||
}
|
||||
else
|
||||
{
|
||||
result = mInput.substr (mCursor, std::string::npos);
|
||||
result = mInput.substr (mCursor);
|
||||
mCursor = mInput.length ();
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ bool Nibbler::getUntilOneOf (const std::string& chars, std::string& result)
|
||||
}
|
||||
else
|
||||
{
|
||||
result = mInput.substr (mCursor, std::string::npos);
|
||||
result = mInput.substr (mCursor);
|
||||
mCursor = mInput.length ();
|
||||
}
|
||||
|
||||
@@ -243,12 +243,12 @@ bool Nibbler::getInt (int& result)
|
||||
++i;
|
||||
}
|
||||
|
||||
while (i < mInput.length () && ::isdigit (mInput[i]))
|
||||
while (i < mInput.length () && isdigit (mInput[i]))
|
||||
++i;
|
||||
|
||||
if (i > mCursor)
|
||||
{
|
||||
result = ::atoi (mInput.substr (mCursor, i - mCursor).c_str ());
|
||||
result = atoi (mInput.substr (mCursor, i - mCursor).c_str ());
|
||||
mCursor = i;
|
||||
return true;
|
||||
}
|
||||
@@ -260,12 +260,12 @@ bool Nibbler::getInt (int& result)
|
||||
bool Nibbler::getUnsignedInt (int& result)
|
||||
{
|
||||
std::string::size_type i = mCursor;
|
||||
while (i < mInput.length () && ::isdigit (mInput[i]))
|
||||
while (i < mInput.length () && isdigit (mInput[i]))
|
||||
++i;
|
||||
|
||||
if (i > mCursor)
|
||||
{
|
||||
result = ::atoi (mInput.substr (mCursor, i - mCursor).c_str ());
|
||||
result = atoi (mInput.substr (mCursor, i - mCursor).c_str ());
|
||||
mCursor = i;
|
||||
return true;
|
||||
}
|
||||
@@ -284,7 +284,7 @@ bool Nibbler::getUntilEOS (std::string& result)
|
||||
{
|
||||
if (mCursor < mInput.length ())
|
||||
{
|
||||
result = mInput.substr (mCursor, std::string::npos);
|
||||
result = mInput.substr (mCursor);
|
||||
mCursor = mInput.length ();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
|
||||
217
src/Path.cpp
Normal file
217
src/Path.cpp
Normal file
@@ -0,0 +1,217 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free Software
|
||||
// Foundation; either version 2 of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
// details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program; if not, write to the
|
||||
//
|
||||
// Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor,
|
||||
// Boston, MA
|
||||
// 02110-1301
|
||||
// USA
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <fstream>
|
||||
#include <glob.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <pwd.h>
|
||||
#include <unistd.h>
|
||||
#include "Path.h"
|
||||
#include "../auto.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Path::Path ()
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Path::Path (const Path& other)
|
||||
{
|
||||
if (this != &other)
|
||||
data = other.data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Path::Path (const std::string& in)
|
||||
{
|
||||
data = expand (in);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Path::~Path ()
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Path& Path::operator= (const Path& other)
|
||||
{
|
||||
if (this != &other)
|
||||
this->data = other.data;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Path::operator std::string () const
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string Path::name () const
|
||||
{
|
||||
if (data.length ())
|
||||
{
|
||||
std::string::size_type slash = data.rfind ('/');
|
||||
if (slash != std::string::npos)
|
||||
return data.substr (slash + 1, std::string::npos);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string Path::parent () const
|
||||
{
|
||||
if (data.length ())
|
||||
{
|
||||
std::string::size_type slash = data.rfind ('/');
|
||||
if (slash != std::string::npos)
|
||||
return data.substr (0, slash);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string Path::extension () const
|
||||
{
|
||||
if (data.length ())
|
||||
{
|
||||
std::string::size_type dot = data.rfind ('.');
|
||||
if (dot != std::string::npos)
|
||||
return data.substr (dot + 1, std::string::npos);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Path::exists () const
|
||||
{
|
||||
return access (data.c_str (), F_OK) ? false : true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Path::is_directory () const
|
||||
{
|
||||
struct stat s = {0};
|
||||
if (! stat (data.c_str (), &s) &&
|
||||
s.st_mode & S_IFDIR)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Path::is_absolute () const
|
||||
{
|
||||
if (data.length () && data.substr (0, 1) == "/")
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Path::readable () const
|
||||
{
|
||||
return access (data.c_str (), R_OK) ? false : true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Path::writable () const
|
||||
{
|
||||
return access (data.c_str (), W_OK) ? false : true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Path::executable () const
|
||||
{
|
||||
return access (data.c_str (), X_OK) ? false : true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// ~ --> /home/user
|
||||
// ~foo/x --> /home/foo/s
|
||||
// ~/x --> /home/foo/x
|
||||
std::string Path::expand (const std::string& in)
|
||||
{
|
||||
std::string copy = in;
|
||||
|
||||
std::string::size_type tilde = copy.find ("~");
|
||||
std::string::size_type slash;
|
||||
|
||||
if (tilde != std::string::npos)
|
||||
{
|
||||
struct passwd* pw = getpwuid (getuid ());
|
||||
|
||||
// Convert: ~ --> /home/user
|
||||
if (copy.length () == 1)
|
||||
{
|
||||
copy = pw->pw_dir;
|
||||
}
|
||||
|
||||
// Convert: ~/x --> /home/user/x
|
||||
else if (copy.length () > tilde + 1 &&
|
||||
copy[tilde + 1] == '/')
|
||||
{
|
||||
copy.replace (tilde, 1, pw->pw_dir);
|
||||
}
|
||||
|
||||
// Convert: ~foo/x --> /home/foo/x
|
||||
else if ((slash = copy.find ("/", tilde)) != std::string::npos)
|
||||
{
|
||||
std::string name = copy.substr (tilde + 1, slash - tilde - 1);
|
||||
struct passwd* pw = getpwnam (name.c_str ());
|
||||
if (pw)
|
||||
copy.replace (tilde, slash - tilde, pw->pw_dir);
|
||||
}
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::vector <std::string> Path::glob (const std::string& pattern)
|
||||
{
|
||||
std::vector <std::string> results;
|
||||
|
||||
glob_t g;
|
||||
#ifdef SOLARIS
|
||||
if (!::glob (pattern.c_str (), GLOB_ERR, NULL, &g))
|
||||
#else
|
||||
if (!::glob (pattern.c_str (), GLOB_ERR | GLOB_BRACE | GLOB_TILDE, NULL, &g))
|
||||
#endif
|
||||
for (int i = 0; i < (int) g.gl_pathc; ++i)
|
||||
results.push_back (g.gl_pathv[i]);
|
||||
|
||||
globfree (&g);
|
||||
return results;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
63
src/Path.h
Normal file
63
src/Path.h
Normal file
@@ -0,0 +1,63 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free Software
|
||||
// Foundation; either version 2 of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
// details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program; if not, write to the
|
||||
//
|
||||
// Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor,
|
||||
// Boston, MA
|
||||
// 02110-1301
|
||||
// USA
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef INCLUDED_PATH
|
||||
#define INCLUDED_PATH
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
class Path
|
||||
{
|
||||
public:
|
||||
Path ();
|
||||
Path (const Path&);
|
||||
Path (const std::string&);
|
||||
virtual ~Path ();
|
||||
|
||||
Path& operator= (const Path&);
|
||||
operator std::string () const;
|
||||
|
||||
std::string name () const;
|
||||
std::string parent () const;
|
||||
std::string extension () const;
|
||||
bool exists () const;
|
||||
bool is_directory () const;
|
||||
bool is_absolute () const;
|
||||
bool readable () const;
|
||||
bool writable () const;
|
||||
bool executable () const;
|
||||
|
||||
// Statics
|
||||
static std::string expand (const std::string&);
|
||||
static std::vector<std::string> glob (const std::string&);
|
||||
|
||||
public:
|
||||
std::string data;
|
||||
};
|
||||
|
||||
#endif
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -37,15 +37,19 @@ extern Context context;
|
||||
Permission::Permission ()
|
||||
: needConfirmation (false)
|
||||
, allConfirmed (false)
|
||||
, quit (false)
|
||||
{
|
||||
// Turning confirmations off is the same as entering "all".
|
||||
if (context.config.get ("confirmation", true) == false)
|
||||
if (context.config.getBoolean ("confirmation") == false)
|
||||
allConfirmed = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Permission::confirmed (const Task& task, const std::string& question)
|
||||
{
|
||||
if (quit)
|
||||
return false;
|
||||
|
||||
if (!needConfirmation)
|
||||
return true;
|
||||
|
||||
@@ -57,16 +61,25 @@ bool Permission::confirmed (const Task& task, const std::string& question)
|
||||
<< task.id
|
||||
<< " \""
|
||||
<< task.get ("description")
|
||||
<< "\""
|
||||
<< std::endl;
|
||||
<< "\"";
|
||||
|
||||
int answer = confirm3 (question);
|
||||
if (task.getStatus () == Task::recurring ||
|
||||
task.has ("parent"))
|
||||
{
|
||||
std::cout << " (Recurring)";
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
int answer = confirm4 (question);
|
||||
if (answer == 2)
|
||||
allConfirmed = true;
|
||||
|
||||
if (answer > 0)
|
||||
if (answer == 1 || answer == 2)
|
||||
return true;
|
||||
|
||||
if (answer == 3)
|
||||
quit = true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -44,6 +44,7 @@ public:
|
||||
private:
|
||||
bool needConfirmation;
|
||||
bool allConfirmed;
|
||||
bool quit;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -152,7 +152,7 @@ int Record::get_int (const std::string& name) const
|
||||
{
|
||||
Record::const_iterator i = this->find (name);
|
||||
if (i != this->end ())
|
||||
return ::atoi (i->second.value ().c_str ());
|
||||
return atoi (i->second.value ().c_str ());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -98,7 +98,7 @@ void Sequence::parse (const std::string& input)
|
||||
if (! validId (range[0]))
|
||||
throw context.stringtable.get (SEQUENCE_BAD_SEQ, "Invalid ID in sequence");
|
||||
|
||||
int id = ::atoi (range[0].c_str ());
|
||||
int id = atoi (range[0].c_str ());
|
||||
this->push_back (id);
|
||||
}
|
||||
break;
|
||||
@@ -109,8 +109,8 @@ void Sequence::parse (const std::string& input)
|
||||
! validId (range[1]))
|
||||
throw context.stringtable.get (SEQUENCE_BAD_SEQ, "Invalid ID in range");
|
||||
|
||||
int low = ::atoi (range[0].c_str ());
|
||||
int high = ::atoi (range[1].c_str ());
|
||||
int low = atoi (range[0].c_str ());
|
||||
int high = atoi (range[1].c_str ());
|
||||
if (low > high)
|
||||
throw context.stringtable.get (SEQUENCE_INVERTED, "Inverted sequence range high-low");
|
||||
|
||||
@@ -153,7 +153,7 @@ bool Sequence::validId (const std::string& input) const
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < input.length (); ++i)
|
||||
if (!::isdigit (input[i]))
|
||||
if (!isdigit (input[i]))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -72,7 +72,7 @@ void StringTable::load (const std::string& file)
|
||||
std::string::size_type equal = line.find (" "); // no i18n
|
||||
if (equal != std::string::npos)
|
||||
{
|
||||
int key = ::atoi (trim (line.substr (0, equal), " \t").c_str ()); // no i18n
|
||||
int key = atoi (trim (line.substr (0, equal), " \t").c_str ()); // no i18n
|
||||
std::string value = trim (line.substr (equal+1, line.length () - equal), " \t"); // no i18n
|
||||
(*this)[key] = value;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "Subst.h"
|
||||
#include "Nibbler.h"
|
||||
#include "Context.h"
|
||||
#include "text.h"
|
||||
#include "i18n.h"
|
||||
|
||||
extern Context context;
|
||||
@@ -121,31 +122,48 @@ void Subst::apply (
|
||||
std::vector <Att>& annotations) const
|
||||
{
|
||||
std::string::size_type pattern;
|
||||
bool sensitive = context.config.getBoolean ("search.case.sensitive");
|
||||
|
||||
if (mFrom != "")
|
||||
{
|
||||
if (mGlobal)
|
||||
{
|
||||
// Perform all subs on description.
|
||||
while ((pattern = description.find (mFrom)) != std::string::npos)
|
||||
int counter = 0;
|
||||
pattern = 0;
|
||||
|
||||
while ((pattern = find (description, mFrom, pattern, sensitive)) != std::string::npos)
|
||||
{
|
||||
description.replace (pattern, mFrom.length (), mTo);
|
||||
pattern += mTo.length ();
|
||||
|
||||
if (++counter > 1000)
|
||||
throw ("Terminated substitution because more than a thousand changes were made - infinite loop protection.");
|
||||
}
|
||||
|
||||
// Perform all subs on annotations.
|
||||
counter = 0;
|
||||
pattern = 0;
|
||||
std::vector <Att>::iterator i;
|
||||
for (i = annotations.begin (); i != annotations.end (); ++i)
|
||||
{
|
||||
std::string description = i->value ();
|
||||
while ((pattern = description.find (mFrom)) != std::string::npos)
|
||||
std::string annotation = i->value ();
|
||||
while ((pattern = find (annotation, mFrom, pattern, sensitive)) != std::string::npos)
|
||||
{
|
||||
description.replace (pattern, mFrom.length (), mTo);
|
||||
i->value (description);
|
||||
annotation.replace (pattern, mFrom.length (), mTo);
|
||||
pattern += mTo.length ();
|
||||
|
||||
i->value (annotation);
|
||||
|
||||
if (++counter > 1000)
|
||||
throw ("Terminated substitution because more than a thousand changes were made - infinite loop protection.");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Perform first description substitution.
|
||||
if ((pattern = description.find (mFrom)) != std::string::npos)
|
||||
if ((pattern = find (description, mFrom, sensitive)) != std::string::npos)
|
||||
description.replace (pattern, mFrom.length (), mTo);
|
||||
|
||||
// Failing that, perform the first annotation substitution.
|
||||
@@ -154,11 +172,11 @@ void Subst::apply (
|
||||
std::vector <Att>::iterator i;
|
||||
for (i = annotations.begin (); i != annotations.end (); ++i)
|
||||
{
|
||||
std::string description = i->value ();
|
||||
if ((pattern = description.find (mFrom)) != std::string::npos)
|
||||
std::string annotation = i->value ();
|
||||
if ((pattern = find (annotation, mFrom, sensitive)) != std::string::npos)
|
||||
{
|
||||
description.replace (pattern, mFrom.length (), mTo);
|
||||
i->value (description);
|
||||
annotation.replace (pattern, mFrom.length (), mTo);
|
||||
i->value (annotation);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
|
||||
143
src/TDB.cpp
143
src/TDB.cpp
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -35,9 +35,11 @@
|
||||
#include "text.h"
|
||||
#include "util.h"
|
||||
#include "TDB.h"
|
||||
#include "Directory.h"
|
||||
#include "File.h"
|
||||
#include "Table.h"
|
||||
#include "Timer.h"
|
||||
#include "color.h"
|
||||
#include "Color.h"
|
||||
#include "main.h"
|
||||
|
||||
extern Context context;
|
||||
@@ -107,59 +109,61 @@ void TDB::clear ()
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TDB::location (const std::string& path)
|
||||
{
|
||||
if (access (expandPath (path).c_str (), F_OK))
|
||||
Directory d (path);
|
||||
if (!d.exists ())
|
||||
throw std::string ("Data location '") +
|
||||
path +
|
||||
"' does not exist, or is not readable and writable.";
|
||||
|
||||
mLocations.push_back (Location (path));
|
||||
mLocations.push_back (Location (d));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TDB::lock (bool lockFile /* = true */)
|
||||
{
|
||||
mLock = lockFile;
|
||||
|
||||
mPending.clear ();
|
||||
mNew.clear ();
|
||||
mPending.clear ();
|
||||
|
||||
foreach (location, mLocations)
|
||||
if (context.hooks.trigger ("pre-file-lock"))
|
||||
{
|
||||
location->pending = openAndLock (location->path + "/pending.data");
|
||||
location->completed = openAndLock (location->path + "/completed.data");
|
||||
location->undo = openAndLock (location->path + "/undo.data");
|
||||
}
|
||||
mLock = lockFile;
|
||||
|
||||
mAllOpenAndLocked = true;
|
||||
mPending.clear ();
|
||||
mNew.clear ();
|
||||
mPending.clear ();
|
||||
|
||||
foreach (location, mLocations)
|
||||
{
|
||||
location->pending = openAndLock (location->path + "/pending.data");
|
||||
location->completed = openAndLock (location->path + "/completed.data");
|
||||
location->undo = openAndLock (location->path + "/undo.data");
|
||||
}
|
||||
|
||||
mAllOpenAndLocked = true;
|
||||
context.hooks.trigger ("post-file-lock");
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TDB::unlock ()
|
||||
{
|
||||
if (mAllOpenAndLocked)
|
||||
mPending.clear ();
|
||||
mNew.clear ();
|
||||
mModified.clear ();
|
||||
|
||||
foreach (location, mLocations)
|
||||
{
|
||||
mPending.clear ();
|
||||
mNew.clear ();
|
||||
mModified.clear ();
|
||||
fflush (location->pending);
|
||||
fclose (location->pending);
|
||||
location->pending = NULL;
|
||||
|
||||
foreach (location, mLocations)
|
||||
{
|
||||
fflush (location->pending);
|
||||
fclose (location->pending);
|
||||
location->pending = NULL;
|
||||
fflush (location->completed);
|
||||
fclose (location->completed);
|
||||
location->completed = NULL;
|
||||
|
||||
fflush (location->completed);
|
||||
fclose (location->completed);
|
||||
location->completed = NULL;
|
||||
|
||||
fflush (location->undo);
|
||||
fclose (location->undo);
|
||||
location->completed = NULL;
|
||||
}
|
||||
|
||||
mAllOpenAndLocked = false;
|
||||
fflush (location->undo);
|
||||
fclose (location->undo);
|
||||
location->completed = NULL;
|
||||
}
|
||||
|
||||
mAllOpenAndLocked = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -227,7 +231,7 @@ int TDB::loadPending (std::vector <Task>& tasks, Filter& filter)
|
||||
fseek (location->pending, 0, SEEK_SET);
|
||||
while (fgets (line, T_LINE_MAX, location->pending))
|
||||
{
|
||||
int length = ::strlen (line);
|
||||
int length = strlen (line);
|
||||
if (length > 3) // []\n
|
||||
{
|
||||
// TODO Add hidden attribute indicating source?
|
||||
@@ -290,7 +294,7 @@ int TDB::loadCompleted (std::vector <Task>& tasks, Filter& filter)
|
||||
fseek (location->completed, 0, SEEK_SET);
|
||||
while (fgets (line, T_LINE_MAX, location->completed))
|
||||
{
|
||||
int length = ::strlen (line);
|
||||
int length = strlen (line);
|
||||
if (length > 3) // []\n
|
||||
{
|
||||
// TODO Add hidden attribute indicating source?
|
||||
@@ -340,6 +344,7 @@ void TDB::update (const Task& task)
|
||||
int TDB::commit ()
|
||||
{
|
||||
Timer t ("TDB::commit");
|
||||
context.hooks.trigger ("pre-gc");
|
||||
|
||||
int quantity = mNew.size () + mModified.size ();
|
||||
|
||||
@@ -359,6 +364,7 @@ int TDB::commit ()
|
||||
writeUndo (*task, mLocations[0].undo);
|
||||
|
||||
mNew.clear ();
|
||||
context.hooks.trigger ("post-gc");
|
||||
return quantity;
|
||||
}
|
||||
|
||||
@@ -405,6 +411,7 @@ int TDB::commit ()
|
||||
mNew.clear ();
|
||||
}
|
||||
|
||||
context.hooks.trigger ("post-gc");
|
||||
return quantity;
|
||||
}
|
||||
|
||||
@@ -447,7 +454,7 @@ int TDB::gc ()
|
||||
else if (s == Task::waiting)
|
||||
{
|
||||
// Wake up tasks that are waiting.
|
||||
Date wait_date (::atoi (task->get ("wait").c_str ()));
|
||||
Date wait_date (atoi (task->get ("wait").c_str ()));
|
||||
if (now > wait_date)
|
||||
{
|
||||
task->setStatus (Task::pending);
|
||||
@@ -503,15 +510,16 @@ int TDB::nextId ()
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TDB::undo ()
|
||||
{
|
||||
std::string location = expandPath (context.config.get ("data.location"));
|
||||
context.hooks.trigger ("pre-undo");
|
||||
Directory location (context.config.get ("data.location"));
|
||||
|
||||
std::string undoFile = location + "/undo.data";
|
||||
std::string pendingFile = location + "/pending.data";
|
||||
std::string completedFile = location + "/completed.data";
|
||||
std::string undoFile = location.data + "/undo.data";
|
||||
std::string pendingFile = location.data + "/pending.data";
|
||||
std::string completedFile = location.data + "/completed.data";
|
||||
|
||||
// load undo.data
|
||||
std::vector <std::string> u;
|
||||
slurp (undoFile, u);
|
||||
File::read (undoFile, u);
|
||||
|
||||
if (u.size () < 3)
|
||||
throw std::string ("There are no recorded transactions to undo.");
|
||||
@@ -519,26 +527,26 @@ void TDB::undo ()
|
||||
// pop last tx
|
||||
u.pop_back (); // separator.
|
||||
|
||||
std::string current = u.back ().substr (4, std::string::npos);
|
||||
std::string current = u.back ().substr (4);
|
||||
u.pop_back ();
|
||||
|
||||
std::string prior;
|
||||
std::string when;
|
||||
if (u.back ().substr (0, 5) == "time ")
|
||||
{
|
||||
when = u.back ().substr (5, std::string::npos);
|
||||
when = u.back ().substr (5);
|
||||
u.pop_back ();
|
||||
prior = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
prior = u.back ().substr (4, std::string::npos);
|
||||
prior = u.back ().substr (4);
|
||||
u.pop_back ();
|
||||
when = u.back ().substr (5, std::string::npos);
|
||||
when = u.back ().substr (5);
|
||||
u.pop_back ();
|
||||
}
|
||||
|
||||
Date lastChange (::atoi (when.c_str ()));
|
||||
Date lastChange (atoi (when.c_str ()));
|
||||
std::cout << std::endl
|
||||
<< "The last modification was made "
|
||||
<< lastChange.toString ()
|
||||
@@ -582,7 +590,7 @@ void TDB::undo ()
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 0, *name);
|
||||
table.addCell (row, 1, renderAttribute (*name, before.get (*name)));
|
||||
table.setCellFg (row, 1, Text::red);
|
||||
table.setCellColor (row, 1, Color (Color::red));
|
||||
}
|
||||
|
||||
foreach (name, before)
|
||||
@@ -599,8 +607,8 @@ void TDB::undo ()
|
||||
|
||||
if (priorValue != currentValue)
|
||||
{
|
||||
table.setCellFg (row, 1, Text::red);
|
||||
table.setCellFg (row, 2, Text::green);
|
||||
table.setCellColor (row, 1, Color (Color::red));
|
||||
table.setCellColor (row, 2, Color (Color::green));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -610,7 +618,7 @@ void TDB::undo ()
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 0, *name);
|
||||
table.addCell (row, 2, renderAttribute (*name, after.get (*name)));
|
||||
table.setCellFg (row, 2, Text::green);
|
||||
table.setCellColor (row, 2, Color (Color::green));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -621,7 +629,7 @@ void TDB::undo ()
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 0, name->first);
|
||||
table.addCell (row, 2, renderAttribute (name->first, after.get (name->first)));
|
||||
table.setCellFg (row, 2, Text::green);
|
||||
table.setCellColor (row, 2, Color (Color::green));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -643,7 +651,7 @@ void TDB::undo ()
|
||||
|
||||
// load pending.data
|
||||
std::vector <std::string> p;
|
||||
slurp (pendingFile, p);
|
||||
File::read (pendingFile, p);
|
||||
|
||||
// is 'current' in pending?
|
||||
foreach (task, p)
|
||||
@@ -665,15 +673,16 @@ void TDB::undo ()
|
||||
}
|
||||
|
||||
// Rewrite files.
|
||||
spit (pendingFile, p);
|
||||
spit (undoFile, u);
|
||||
File::write (pendingFile, p);
|
||||
File::write (undoFile, u);
|
||||
context.hooks.trigger ("post-undo");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// load completed.data
|
||||
std::vector <std::string> c;
|
||||
slurp (completedFile, c);
|
||||
File::read (completedFile, c);
|
||||
|
||||
// is 'current' in completed?
|
||||
foreach (task, c)
|
||||
@@ -689,22 +698,23 @@ void TDB::undo ()
|
||||
{
|
||||
c.erase (task);
|
||||
p.push_back (prior);
|
||||
spit (completedFile, c);
|
||||
spit (pendingFile, p);
|
||||
spit (undoFile, u);
|
||||
File::write (completedFile, c);
|
||||
File::write (pendingFile, p);
|
||||
File::write (undoFile, u);
|
||||
std::cout << "Modified task reverted." << std::endl;
|
||||
context.debug ("TDB::undo - task belongs in pending.data");
|
||||
}
|
||||
else
|
||||
{
|
||||
*task = prior;
|
||||
spit (completedFile, c);
|
||||
spit (undoFile, u);
|
||||
File::write (completedFile, c);
|
||||
File::write (undoFile, u);
|
||||
std::cout << "Modified task reverted." << std::endl;
|
||||
context.debug ("TDB::undo - task belongs in completed.data");
|
||||
}
|
||||
|
||||
std::cout << "Undo complete." << std::endl;
|
||||
context.hooks.trigger ("post-undo");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -725,9 +735,10 @@ FILE* TDB::openAndLock (const std::string& file)
|
||||
// TODO Need provision here for read-only locations.
|
||||
|
||||
// Check for access.
|
||||
bool exists = access (file.c_str (), F_OK) ? false : true;
|
||||
File f (file);
|
||||
bool exists = f.exists ();
|
||||
if (exists)
|
||||
if (access (file.c_str (), R_OK | W_OK))
|
||||
if (!f.readable () || !f.writable ())
|
||||
throw std::string ("Task does not have the correct permissions for '") +
|
||||
file + "'.";
|
||||
|
||||
@@ -755,8 +766,6 @@ FILE* TDB::openAndLock (const std::string& file)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TDB::writeUndo (const Task& after, FILE* file)
|
||||
{
|
||||
Timer t ("TDB::writeUndo");
|
||||
|
||||
fprintf (file,
|
||||
"time %u\nnew %s---\n",
|
||||
(unsigned int) time (NULL),
|
||||
@@ -766,8 +775,6 @@ void TDB::writeUndo (const Task& after, FILE* file)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TDB::writeUndo (const Task& before, const Task& after, FILE* file)
|
||||
{
|
||||
Timer t ("TDB::writeUndo");
|
||||
|
||||
fprintf (file,
|
||||
"time %u\nold %snew %s---\n",
|
||||
(unsigned int) time (NULL),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
|
||||
308
src/Table.cpp
308
src/Table.cpp
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -52,6 +52,9 @@
|
||||
#include "Timer.h"
|
||||
#include "text.h"
|
||||
#include "util.h"
|
||||
#include "Context.h"
|
||||
|
||||
extern Context context;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Table::Table ()
|
||||
@@ -70,22 +73,17 @@ Table::~Table ()
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setTableColor (Text::color fg, Text::color bg)
|
||||
/*
|
||||
void Table::setTableColor (const Color& c)
|
||||
{
|
||||
mFg["table"] = Text::colorName (fg);
|
||||
mBg["table"] = Text::colorName (bg);
|
||||
mColor["table"] = c;
|
||||
}
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setTableFg (Text::color c)
|
||||
void Table::setTableAlternateColor (const Color& c)
|
||||
{
|
||||
mFg["table"] = Text::colorName (c);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setTableBg (Text::color c)
|
||||
{
|
||||
mBg["table"] = Text::colorName (c);
|
||||
alternate = c;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -126,36 +124,22 @@ int Table::addColumn (const std::string& col)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setColumnColor (int column, Text::color fg, Text::color bg)
|
||||
// TODO Obsolete - this call is not used. Consider removal.
|
||||
/*
|
||||
void Table::setColumnColor (int column, const Color& c)
|
||||
{
|
||||
char id[12];
|
||||
sprintf (id, "col:%d", column);
|
||||
mFg[id] = Text::colorName (fg);
|
||||
mBg[id] = Text::colorName (bg);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setColumnFg (int column, Text::color c)
|
||||
{
|
||||
char id[12];
|
||||
sprintf (id, "col:%d", column);
|
||||
mFg[id] = Text::colorName (c);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setColumnBg (int column, Text::color c)
|
||||
{
|
||||
char id[12];
|
||||
sprintf (id, "col:%d", column);
|
||||
mBg[id] = Text::colorName (c);
|
||||
mColor[id] = c;
|
||||
}
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setColumnUnderline (int column)
|
||||
{
|
||||
char id[12];
|
||||
sprintf (id, "col:%d", column);
|
||||
mUnderline[id] = Text::underline;
|
||||
mUnderline[id] = Color (Color::nocolor, Color::nocolor, true, false, false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -203,28 +187,11 @@ int Table::addRow ()
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setRowColor (const int row, const Text::color fg, const Text::color bg)
|
||||
void Table::setRowColor (const int row, const Color& c)
|
||||
{
|
||||
char id[12];
|
||||
sprintf (id, "row:%d", row);
|
||||
mFg[id] = Text::colorName (fg);
|
||||
mBg[id] = Text::colorName (bg);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setRowFg (const int row, const Text::color c)
|
||||
{
|
||||
char id[12];
|
||||
sprintf (id, "row:%d", row);
|
||||
mFg[id] = Text::colorName (c);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setRowBg (const int row, const Text::color c)
|
||||
{
|
||||
char id[12];
|
||||
sprintf (id, "row:%d", row);
|
||||
mBg[id] = Text::colorName (c);
|
||||
mColor[id].blend (c);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -302,7 +269,7 @@ void Table::addCell (const int row, const int col, const int data)
|
||||
mData.add (row, col, value);
|
||||
|
||||
// Automatically maintain max width.
|
||||
mMaxDataWidth[col] = max (mMaxDataWidth[col], (signed) ::strlen (value));
|
||||
mMaxDataWidth[col] = max (mMaxDataWidth[col], (signed) strlen (value));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -317,7 +284,7 @@ void Table::addCell (const int row, const int col, const float data)
|
||||
mData.add (row, col, value);
|
||||
|
||||
// Automatically maintain max width.
|
||||
mMaxDataWidth[col] = max (mMaxDataWidth[col], (signed) ::strlen (value));
|
||||
mMaxDataWidth[col] = max (mMaxDataWidth[col], (signed) strlen (value));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -332,32 +299,15 @@ void Table::addCell (const int row, const int col, const double data)
|
||||
mData.add (row, col, value);
|
||||
|
||||
// Automatically maintain max width.
|
||||
mMaxDataWidth[col] = max (mMaxDataWidth[col], (signed) ::strlen (value));
|
||||
mMaxDataWidth[col] = max (mMaxDataWidth[col], (signed) strlen (value));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setCellColor (const int row, const int col, const Text::color fg, const Text::color bg)
|
||||
void Table::setCellColor (const int row, const int col, const Color& c)
|
||||
{
|
||||
char id[24];
|
||||
sprintf (id, "cell:%d,%d", row, col);
|
||||
mFg[id] = Text::colorName (fg);
|
||||
mBg[id] = Text::colorName (bg);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setCellFg (const int row, const int col, const Text::color c)
|
||||
{
|
||||
char id[24];
|
||||
sprintf (id, "cell:%d,%d", row, col);
|
||||
mFg[id] = Text::colorName (c);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setCellBg (const int row, const int col, const Text::color c)
|
||||
{
|
||||
char id[24];
|
||||
sprintf (id, "cell:%d,%d", row, col);
|
||||
mBg[id] = Text::colorName (c);
|
||||
mColor[id] = c;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -371,83 +321,75 @@ std::string Table::getCell (const int row, const int col)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Text::color Table::getFg (const int row, const int col)
|
||||
Color Table::getColor (const int index, const int row, const int col)
|
||||
{
|
||||
char idCell[24];
|
||||
sprintf (idCell, "cell:%d,%d", row, col);
|
||||
if (mFg.find (idCell) != mFg.end ())
|
||||
return Text::colorCode (mFg[idCell]);
|
||||
// Color defaults to trivial.
|
||||
Color c;
|
||||
|
||||
char idRow[12];
|
||||
sprintf (idRow, "row:%d", row);
|
||||
if (mFg.find (idRow) != mFg.end ())
|
||||
return Text::colorCode (mFg[idRow]);
|
||||
// For alternating rows, use Table::alternate.
|
||||
std::map <std::string, Color>::iterator i;
|
||||
char id[24];
|
||||
|
||||
char idCol[12];
|
||||
sprintf (idCol, "col:%d", col);
|
||||
if (mFg.find (idCol) != mFg.end ())
|
||||
return Text::colorCode (mFg[idCol]);
|
||||
if (index % 2)
|
||||
c = alternate;
|
||||
|
||||
if (mFg.find ("table") != mFg.end ())
|
||||
return Text::colorCode (mFg["table"]);
|
||||
/*
|
||||
// TODO Obsolete - this is not used. Consider removal.
|
||||
// Blend with a table color, if specified.
|
||||
if ((i = mColor.find ("table")) != mColor.end ())
|
||||
c.blend (i->second);
|
||||
|
||||
return Text::nocolor;
|
||||
// Blend with a column color, if specified.
|
||||
sprintf (id, "col:%d", col);
|
||||
if ((i = mColor.find (id)) != mColor.end ())
|
||||
c.blend (i->second);
|
||||
*/
|
||||
|
||||
// Blend with a row color, if specified.
|
||||
sprintf (id, "row:%d", row);
|
||||
if ((i = mColor.find (id)) != mColor.end ())
|
||||
c.blend (i->second);
|
||||
|
||||
// Blend with a cell color, if specified.
|
||||
sprintf (id, "cell:%d,%d", row, col);
|
||||
if ((i = mColor.find (id)) != mColor.end ())
|
||||
c.blend (i->second);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Text::color Table::getHeaderFg (int col)
|
||||
// TODO Obsolete - this is not used. Consider removal.
|
||||
Color Table::getHeaderColor (int col)
|
||||
{
|
||||
// Color defaults to trivial.
|
||||
Color c;
|
||||
|
||||
/*
|
||||
std::map <std::string, Color>::iterator i;
|
||||
char id[24];
|
||||
|
||||
// Blend with a table color, if specified.
|
||||
if ((i = mColor.find ("table")) != mColor.end ())
|
||||
c.blend (i->second);
|
||||
|
||||
// Blend with a column color, if specified.
|
||||
sprintf (id, "col:%d", col);
|
||||
if ((i = mColor.find (id)) != mColor.end ())
|
||||
c.blend (i->second);
|
||||
*/
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Color Table::getHeaderUnderline (int col)
|
||||
{
|
||||
char idCol[12];
|
||||
sprintf (idCol, "col:%d", col);
|
||||
|
||||
return mFg.find (idCol) != mFg.end () ? Text::colorCode (mFg[idCol])
|
||||
: mFg.find ("table") != mFg.end () ? Text::colorCode (mFg["table"])
|
||||
: Text::nocolor;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Text::color Table::getBg (const int row, const int col)
|
||||
{
|
||||
char idCell[24];
|
||||
sprintf (idCell, "cell:%d,%d", row, col);
|
||||
if (mBg.find (idCell) != mBg.end ())
|
||||
return Text::colorCode (mBg[idCell]);
|
||||
|
||||
char idRow[12];
|
||||
sprintf (idRow, "row:%d", row);
|
||||
if (mBg.find (idRow) != mBg.end ())
|
||||
return Text::colorCode (mBg[idRow]);
|
||||
|
||||
char idCol[12];
|
||||
sprintf (idCol, "col:%d", col);
|
||||
if (mBg.find (idCol) != mBg.end ())
|
||||
return Text::colorCode (mBg[idCol]);
|
||||
|
||||
if (mBg.find ("table") != mBg.end ())
|
||||
return Text::colorCode (mBg["table"]);
|
||||
|
||||
return Text::nocolor;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Text::color Table::getHeaderBg (int col)
|
||||
{
|
||||
char idCol[12];
|
||||
sprintf (idCol, "col:%d", col);
|
||||
|
||||
return mBg.find (idCol) != mBg.end () ? Text::colorCode (mBg[idCol])
|
||||
: mBg.find ("table") != mBg.end () ? Text::colorCode (mBg["table"])
|
||||
: Text::nocolor;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Text::color Table::getHeaderUnderline (int col)
|
||||
{
|
||||
char idCol[12];
|
||||
sprintf (idCol, "col:%d", col);
|
||||
|
||||
return mUnderline.find (idCol) != mUnderline.end () ? Text::underline
|
||||
: Text::nocolor;
|
||||
return mUnderline.find (idCol) != mUnderline.end () ? mUnderline[idCol]
|
||||
: Color ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -584,10 +526,9 @@ const std::string Table::formatHeader (
|
||||
{
|
||||
assert (width > 0);
|
||||
|
||||
Text::color fg = getHeaderFg (col);
|
||||
Text::color bg = getHeaderBg (col);
|
||||
std::string data = mColumns[col];
|
||||
Text::color decoration = getHeaderUnderline (col);
|
||||
Color c = getHeaderColor (col);
|
||||
std::string data = mColumns[col];
|
||||
c.blend (getHeaderUnderline (col));
|
||||
|
||||
std::string pad = "";
|
||||
std::string intraPad = "";
|
||||
@@ -609,11 +550,7 @@ const std::string Table::formatHeader (
|
||||
for (int i = 0; i < getIntraPadding (); ++i)
|
||||
intraPad += " ";
|
||||
|
||||
return Text::colorize (
|
||||
fg, bg,
|
||||
Text::colorize (
|
||||
decoration, Text::nocolor,
|
||||
pad + preJust + data + postJust + pad) + intraPad);
|
||||
return c.colorize (pad + preJust + data + postJust + pad) + intraPad;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -638,9 +575,8 @@ const std::string Table::formatHeaderDashedUnderline (
|
||||
{
|
||||
assert (width > 0);
|
||||
|
||||
Text::color fg = getHeaderFg (col);
|
||||
Text::color bg = getHeaderBg (col);
|
||||
Text::color decoration = getHeaderUnderline (col);
|
||||
Color c = getHeaderColor (col);
|
||||
c.blend (getHeaderUnderline (col));
|
||||
|
||||
std::string data = "";
|
||||
for (int i = 0; i < width; ++i)
|
||||
@@ -659,15 +595,12 @@ const std::string Table::formatHeaderDashedUnderline (
|
||||
for (int i = 0; i < getIntraPadding (); ++i)
|
||||
intraPad += " ";
|
||||
|
||||
return Text::colorize (
|
||||
fg, bg,
|
||||
Text::colorize (
|
||||
decoration, Text::nocolor,
|
||||
pad + data + pad) + intraPad);
|
||||
return c.colorize (pad + data + pad) + intraPad;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::formatCell (
|
||||
const int index,
|
||||
const int row,
|
||||
const int col,
|
||||
const int width,
|
||||
@@ -677,8 +610,7 @@ void Table::formatCell (
|
||||
{
|
||||
assert (width > 0);
|
||||
|
||||
Text::color fg = getFg (row, col);
|
||||
Text::color bg = getBg (row, col);
|
||||
Color c = getColor (index, row, col);
|
||||
just justification = getJustification (row, col);
|
||||
std::string data = getCell (row, col);
|
||||
|
||||
@@ -722,8 +654,7 @@ void Table::formatCell (
|
||||
postJust += " ";
|
||||
}
|
||||
|
||||
lines.push_back (
|
||||
Text::colorize (fg, bg, pad + preJust + chunks[chunk] + postJust + pad + intraPad));
|
||||
lines.push_back (c.colorize (pad + preJust + chunks[chunk] + postJust + pad + intraPad));
|
||||
}
|
||||
|
||||
// The blank is used to vertically pad cells that have blank lines.
|
||||
@@ -731,7 +662,7 @@ void Table::formatCell (
|
||||
for (int i = 0; i < width; ++i)
|
||||
pad += " ";
|
||||
|
||||
blank = Text::colorize (fg, bg, pad + intraPad);
|
||||
blank = c.colorize (pad + intraPad);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -746,6 +677,12 @@ void Table::setDateFormat (const std::string& dateFormat)
|
||||
mDateFormat = dateFormat;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setReportName (const std::string& reportName)
|
||||
{
|
||||
mReportName = reportName;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int Table::rowCount ()
|
||||
{
|
||||
@@ -876,7 +813,7 @@ void Table::sort (std::vector <int>& order)
|
||||
if (gap > 1)
|
||||
{
|
||||
gap = (int) ((float)gap / 1.3);
|
||||
if (gap == 10 or gap == 9)
|
||||
if (gap == 10 || gap == 9)
|
||||
gap = 11;
|
||||
}
|
||||
|
||||
@@ -973,6 +910,54 @@ void Table::sort (std::vector <int>& order)
|
||||
}
|
||||
break;
|
||||
|
||||
case ascendingDueDate:
|
||||
{
|
||||
if ((std::string)*left != "" && (std::string)*right == "")
|
||||
break;
|
||||
|
||||
else if ((std::string)*left == "" && (std::string)*right != "")
|
||||
SWAP
|
||||
|
||||
else
|
||||
{
|
||||
std::string format = context.config.get ("report." + mReportName + ".dateformat");
|
||||
if (format == "")
|
||||
format = context.config.get ("dateformat.report");
|
||||
if (format == "")
|
||||
format = context.config.get ("dateformat");
|
||||
|
||||
Date dl ((std::string)*left, format);
|
||||
Date dr ((std::string)*right, format);
|
||||
if (dl > dr)
|
||||
SWAP
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case descendingDueDate:
|
||||
{
|
||||
if ((std::string)*left != "" && (std::string)*right == "")
|
||||
break;
|
||||
|
||||
else if ((std::string)*left == "" && (std::string)*right != "")
|
||||
SWAP
|
||||
|
||||
else
|
||||
{
|
||||
std::string format = context.config.get ("report." + mReportName + ".dateformat");
|
||||
if (format == "")
|
||||
format = context.config.get ("dateformat.report");
|
||||
if (format == "")
|
||||
format = context.config.get ("dateformat");
|
||||
|
||||
Date dl ((std::string)*left, format);
|
||||
Date dr ((std::string)*right, format);
|
||||
if (dl < dr)
|
||||
SWAP
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ascendingPriority:
|
||||
if (((std::string)*left == "" && (std::string)*right != "") ||
|
||||
((std::string)*left == "M" && (std::string)*right == "L") ||
|
||||
@@ -1093,6 +1078,7 @@ const std::string Table::render (int maximum /* = 0 */)
|
||||
std::vector <std::string> lines;
|
||||
std::string blank;
|
||||
formatCell (
|
||||
row,
|
||||
order[row],
|
||||
col,
|
||||
mCalculatedWidth[col],
|
||||
|
||||
45
src/Table.h
45
src/Table.h
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -30,8 +30,8 @@
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <color.h>
|
||||
#include <Grid.h>
|
||||
#include "Color.h"
|
||||
#include "Grid.h"
|
||||
|
||||
class Table
|
||||
{
|
||||
@@ -41,11 +41,13 @@ public:
|
||||
ascendingCharacter,
|
||||
ascendingPriority,
|
||||
ascendingDate,
|
||||
ascendingDueDate,
|
||||
ascendingPeriod,
|
||||
descendingNumeric,
|
||||
descendingCharacter,
|
||||
descendingPriority,
|
||||
descendingDate,
|
||||
descendingDueDate,
|
||||
descendingPeriod};
|
||||
enum sizing {minimum = -1, flexible = 0};
|
||||
|
||||
@@ -55,18 +57,17 @@ public:
|
||||
Table (const Table&);
|
||||
Table& operator= (const Table&);
|
||||
|
||||
void setTableColor (Text::color, Text::color);
|
||||
void setTableFg (Text::color);
|
||||
void setTableBg (Text::color);
|
||||
// TODO Obsolete - this is not used. Consider removal.
|
||||
// void setTableColor (const Color&);
|
||||
void setTableAlternateColor (const Color&);
|
||||
void setTablePadding (int);
|
||||
void setTableIntraPadding (int);
|
||||
void setTableWidth (int);
|
||||
void setTableDashedUnderline ();
|
||||
|
||||
int addColumn (const std::string&);
|
||||
void setColumnColor (int, Text::color, Text::color);
|
||||
void setColumnFg (int, Text::color);
|
||||
void setColumnBg (int, Text::color);
|
||||
// TODO Obsolete - this is not used. Consider removal.
|
||||
// void setColumnColor (int, const Color&);
|
||||
void setColumnUnderline (int);
|
||||
void setColumnPadding (int, int);
|
||||
void setColumnWidth (int, int);
|
||||
@@ -76,21 +77,18 @@ public:
|
||||
void sortOn (int, order);
|
||||
|
||||
int addRow ();
|
||||
void setRowColor (int, Text::color, Text::color);
|
||||
void setRowFg (int, Text::color);
|
||||
void setRowBg (int, Text::color);
|
||||
void setRowColor (int, const Color&);
|
||||
|
||||
void addCell (int, int, const std::string&);
|
||||
void addCell (int, int, char);
|
||||
void addCell (int, int, int);
|
||||
void addCell (int, int, float);
|
||||
void addCell (int, int, double);
|
||||
void setCellColor (int, int, Text::color, Text::color);
|
||||
void setCellFg (int, int, Text::color);
|
||||
void setCellBg (int, int, Text::color);
|
||||
void setCellColor (int, int, const Color&);
|
||||
|
||||
void suppressWS ();
|
||||
void setDateFormat (const std::string&);
|
||||
void setReportName (const std::string&);
|
||||
|
||||
int rowCount ();
|
||||
int columnCount ();
|
||||
@@ -98,11 +96,9 @@ public:
|
||||
|
||||
private:
|
||||
std::string getCell (const int, const int);
|
||||
Text::color getFg (const int, const int);
|
||||
Text::color getHeaderFg (const int);
|
||||
Text::color getBg (const int, const int);
|
||||
Text::color getHeaderBg (const int);
|
||||
Text::color getHeaderUnderline (const int);
|
||||
Color getColor (const int, const int, const int);
|
||||
Color getHeaderColor (const int);
|
||||
Color getHeaderUnderline (const int);
|
||||
int getPadding (const int);
|
||||
int getIntraPadding ();
|
||||
void calculateColumnWidths ();
|
||||
@@ -110,7 +106,7 @@ private:
|
||||
just getHeaderJustification (const int);
|
||||
const std::string formatHeader (const int, const int, const int);
|
||||
const std::string formatHeaderDashedUnderline (const int, const int, const int);
|
||||
void formatCell (const int, const int, const int, const int, std::vector <std::string>&, std::string&);
|
||||
void formatCell (const int, const int, const int, const int, const int, std::vector <std::string>&, std::string&);
|
||||
void sort (std::vector <int>&);
|
||||
void clean (std::string&);
|
||||
void optimize (std::string&) const;
|
||||
@@ -119,10 +115,10 @@ private:
|
||||
std::vector <std::string> mColumns;
|
||||
int mRows;
|
||||
int mIntraPadding;
|
||||
std::map <std::string, std::string> mFg;
|
||||
std::map <std::string, std::string> mBg;
|
||||
std::map <std::string, std::string> mUnderline;
|
||||
std::map <std::string, Color> mColor;
|
||||
std::map <std::string, Color> mUnderline;
|
||||
bool mDashedUnderline;
|
||||
Color alternate;
|
||||
|
||||
// Padding...
|
||||
int mTablePadding;
|
||||
@@ -143,6 +139,7 @@ private:
|
||||
// Misc...
|
||||
bool mSuppressWS;
|
||||
std::string mDateFormat;
|
||||
std::string mReportName;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
23
src/Task.cpp
23
src/Task.cpp
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include "Context.h"
|
||||
#include "Nibbler.h"
|
||||
#include "Date.h"
|
||||
#include "Duration.h"
|
||||
@@ -34,6 +35,8 @@
|
||||
#include "text.h"
|
||||
#include "util.h"
|
||||
|
||||
extern Context context;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Task::Task ()
|
||||
: id (0)
|
||||
@@ -134,7 +137,7 @@ void Task::setEntry ()
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Task::status Task::getStatus ()
|
||||
Task::status Task::getStatus () const
|
||||
{
|
||||
return textToStatus (get ("status")); // No i18n
|
||||
}
|
||||
@@ -220,7 +223,7 @@ void Task::legacyParse (const std::string& line)
|
||||
set (pair[0], pair[1]);
|
||||
}
|
||||
|
||||
set ("description", line.substr (closeAttrBracket + 2, std::string::npos)); // No i18n
|
||||
set ("description", line.substr (closeAttrBracket + 2)); // No i18n
|
||||
}
|
||||
else
|
||||
throw std::string ("Missing attribute brackets"); // TODO i18n
|
||||
@@ -321,7 +324,7 @@ void Task::legacyParse (const std::string& line)
|
||||
}
|
||||
}
|
||||
|
||||
set ("description", line.substr (closeAnnoBracket + 2, std::string::npos)); // No i18n
|
||||
set ("description", line.substr (closeAnnoBracket + 2)); // No i18n
|
||||
}
|
||||
else
|
||||
throw std::string ("Missing annotation brackets."); // TODO i18n
|
||||
@@ -441,10 +444,14 @@ void Task::addAnnotation (const std::string& description)
|
||||
void Task::removeAnnotations ()
|
||||
{
|
||||
// Erase old annotations.
|
||||
Record::iterator i;
|
||||
for (i = this->begin (); i != this->end (); ++i)
|
||||
Record::iterator i = this->begin ();
|
||||
while (i != this->end ())
|
||||
{
|
||||
if (i->first.substr (0, 11) == "annotation_") // No i18n
|
||||
this->erase (i);
|
||||
this->erase (i++);
|
||||
else
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -523,7 +530,7 @@ void Task::validate () const
|
||||
if (!has ("uuid") ||
|
||||
!has ("entry") ||
|
||||
!has ("description"))
|
||||
throw std::string ("A task must have a uuid, entry date and description in order to be valid."); // TODO i18n
|
||||
throw std::string ("A task must have a description in order to be valid."); // TODO i18n
|
||||
|
||||
if (get ("description") == "") // No i18n
|
||||
throw std::string ("Cannot add a task that is blank, or contains <CR> or <LF> characters."); // TODO i18n
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
|
||||
void setEntry ();
|
||||
|
||||
status getStatus ();
|
||||
status getStatus () const;
|
||||
void setStatus (status);
|
||||
|
||||
int getTagCount ();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -37,7 +37,7 @@ extern Context context;
|
||||
Timer::Timer (const std::string& description)
|
||||
: mDescription (description)
|
||||
{
|
||||
::gettimeofday (&mStart, NULL);
|
||||
gettimeofday (&mStart, NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -45,14 +45,19 @@ Timer::Timer (const std::string& description)
|
||||
Timer::~Timer ()
|
||||
{
|
||||
struct timeval end;
|
||||
::gettimeofday (&end, NULL);
|
||||
gettimeofday (&end, NULL);
|
||||
|
||||
std::stringstream s;
|
||||
s << "Timer " // No i18n
|
||||
<< mDescription
|
||||
<< " "
|
||||
<< std::setprecision (6)
|
||||
|
||||
#ifndef HAIKU
|
||||
// Haiku fails on this - don't know why.
|
||||
<< std::fixed
|
||||
#endif
|
||||
|
||||
<< ((end.tv_sec - mStart.tv_sec) + ((end.tv_usec - mStart.tv_usec )
|
||||
/ 1000000.0))
|
||||
<< " sec";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
|
||||
196
src/color.cpp
196
src/color.cpp
@@ -1,196 +0,0 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free Software
|
||||
// Foundation; either version 2 of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
// details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program; if not, write to the
|
||||
//
|
||||
// Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor,
|
||||
// Boston, MA
|
||||
// 02110-1301
|
||||
// USA
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#include <string>
|
||||
#include "Context.h"
|
||||
#include "text.h"
|
||||
#include "util.h"
|
||||
#include "i18n.h"
|
||||
#include "color.h"
|
||||
|
||||
extern Context context;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
namespace Text
|
||||
{
|
||||
|
||||
static struct
|
||||
{
|
||||
color id;
|
||||
int string_id;
|
||||
std::string english_name;
|
||||
std::string escape_sequence;
|
||||
} allColors[] =
|
||||
{
|
||||
// Text::color i18n.h English vt220? xterm?
|
||||
{ nocolor, 0, "", "" },
|
||||
{ off, COLOR_OFF, "off", "[0m" },
|
||||
|
||||
{ bold, COLOR_BOLD, "bold", "\033[1m" },
|
||||
{ underline, COLOR_UL, "underline", "\033[4m" },
|
||||
{ bold_underline, COLOR_B_UL, "bold_underline", "\033[1;4m" },
|
||||
|
||||
{ black, COLOR_BLACK, "black", "\033[30m" },
|
||||
{ red, COLOR_RED, "red", "\033[31m" },
|
||||
{ green, COLOR_GREEN, "green", "\033[32m" },
|
||||
{ yellow, COLOR_YELLOW, "yellow", "\033[33m" },
|
||||
{ blue, COLOR_BLUE, "blue", "\033[34m" },
|
||||
{ magenta, COLOR_MAGENTA, "magenta", "\033[35m" },
|
||||
{ cyan, COLOR_CYAN, "cyan", "\033[36m" },
|
||||
{ white, COLOR_WHITE, "white", "\033[37m" },
|
||||
|
||||
{ bold_black, COLOR_B_BLACK, "bold_black", "\033[90m" },
|
||||
{ bold_red, COLOR_B_RED, "bold_red", "\033[91m" },
|
||||
{ bold_green, COLOR_B_GREEN, "bold_green", "\033[92m" },
|
||||
{ bold_yellow, COLOR_B_YELLOW, "bold_yellow", "\033[93m" },
|
||||
{ bold_blue, COLOR_B_BLUE, "bold_blue", "\033[94m" },
|
||||
{ bold_magenta, COLOR_B_MAGENTA, "bold_magenta", "\033[95m" },
|
||||
{ bold_cyan, COLOR_B_CYAN, "bold_cyan", "\033[96m" },
|
||||
{ bold_white, COLOR_B_WHITE, "bold_white", "\033[97m" },
|
||||
|
||||
{ underline_black, COLOR_UL_BLACK, "underline_black", "\033[4;30m" },
|
||||
{ underline_red, COLOR_UL_RED, "underline_red", "\033[4;31m" },
|
||||
{ underline_green, COLOR_UL_GREEN, "underline_green", "\033[4;32m" },
|
||||
{ underline_yellow, COLOR_UL_YELLOW, "underline_yellow", "\033[4;33m" },
|
||||
{ underline_blue, COLOR_UL_BLUE, "underline_blue", "\033[4;34m" },
|
||||
{ underline_magenta, COLOR_UL_MAGENTA, "underline_magenta", "\033[4;35m" },
|
||||
{ underline_cyan, COLOR_UL_CYAN, "underline_cyan", "\033[4;36m" },
|
||||
{ underline_white, COLOR_UL_WHITE, "underline_white", "\033[4;37m" },
|
||||
|
||||
{ bold_underline_black, COLOR_B_UL_BLACK, "bold_underline_black", "\033[1;4;30m" },
|
||||
{ bold_underline_red, COLOR_B_UL_RED, "bold_underline_red", "\033[1;4;31m" },
|
||||
{ bold_underline_green, COLOR_B_UL_GREEN, "bold_underline_green", "\033[1;4;32m" },
|
||||
{ bold_underline_yellow, COLOR_B_UL_YELLOW, "bold_underline_yellow", "\033[1;4;33m" },
|
||||
{ bold_underline_blue, COLOR_B_UL_BLUE, "bold_underline_blue", "\033[1;4;34m" },
|
||||
{ bold_underline_magenta, COLOR_B_UL_MAGENTA, "bold_underline_magenta", "\033[1;4;35m" },
|
||||
{ bold_underline_cyan, COLOR_B_UL_CYAN, "bold_underline_cyan", "\033[1;4;36m" },
|
||||
{ bold_underline_white, COLOR_B_UL_WHITE, "bold_underline_white", "\033[1;4;37m" },
|
||||
|
||||
{ on_black, COLOR_ON_BLACK, "on_black", "\033[40m" },
|
||||
{ on_red, COLOR_ON_RED, "on_red", "\033[41m" },
|
||||
{ on_green, COLOR_ON_GREEN, "on_green", "\033[42m" },
|
||||
{ on_yellow, COLOR_ON_YELLOW, "on_yellow", "\033[43m" },
|
||||
{ on_blue, COLOR_ON_BLUE, "on_blue", "\033[44m" },
|
||||
{ on_magenta, COLOR_ON_MAGENTA, "on_magenta", "\033[45m" },
|
||||
{ on_cyan, COLOR_ON_CYAN, "on_cyan", "\033[46m" },
|
||||
{ on_white, COLOR_ON_WHITE, "on_white", "\033[47m" },
|
||||
|
||||
{ on_bright_black, COLOR_ON_BRIGHT_BLACK, "on_bright_black", "\033[100m" },
|
||||
{ on_bright_red, COLOR_ON_BRIGHT_RED, "on_bright_red", "\033[101m" },
|
||||
{ on_bright_green, COLOR_ON_BRIGHT_GREEN, "on_bright_green", "\033[102m" },
|
||||
{ on_bright_yellow, COLOR_ON_BRIGHT_YELLOW, "on_bright_yellow", "\033[103m" },
|
||||
{ on_bright_blue, COLOR_ON_BRIGHT_BLUE, "on_bright_blue", "\033[104m" },
|
||||
{ on_bright_magenta, COLOR_ON_BRIGHT_MAGENTA, "on_bright_magenta", "\033[105m" },
|
||||
{ on_bright_cyan, COLOR_ON_BRIGHT_CYAN, "on_bright_cyan", "\033[106m" },
|
||||
{ on_bright_white, COLOR_ON_BRIGHT_WHITE, "on_bright_white", "\033[107m" },
|
||||
};
|
||||
|
||||
#define NUM_COLORS (sizeof (allColors) / sizeof (allColors[0]))
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string colorName (color c)
|
||||
{
|
||||
for (unsigned int i = 0; i < NUM_COLORS; ++i)
|
||||
if (allColors[i].id == c)
|
||||
return allColors[i].english_name;
|
||||
|
||||
throw context.stringtable.get (COLOR_UNKNOWN, "Unknown color value");
|
||||
return "";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
color colorCode (const std::string& c)
|
||||
{
|
||||
for (unsigned int i = 0; i < NUM_COLORS; ++i)
|
||||
if (context.stringtable.get (allColors[i].string_id, allColors[i].english_name) == c)
|
||||
return allColors[i].id;
|
||||
|
||||
return nocolor;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string decode (color c)
|
||||
{
|
||||
for (unsigned int i = 0; i < NUM_COLORS; ++i)
|
||||
if (allColors[i].id == c)
|
||||
return allColors[i].escape_sequence;
|
||||
|
||||
throw context.stringtable.get (COLOR_UNKNOWN, "Unknown color value");
|
||||
return "";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string colorize (color fg, color bg, const std::string& input)
|
||||
{
|
||||
if (input.length ())
|
||||
if (fg != nocolor || bg != nocolor)
|
||||
return decode (fg) + decode (bg) + input + decode (off);
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string colorize (color fg, color bg)
|
||||
{
|
||||
return decode (fg) + decode (bg);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string colorize ()
|
||||
{
|
||||
return decode (off);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string guessColor (const std::string& name)
|
||||
{
|
||||
std::vector <std::string> all;
|
||||
for (unsigned int i = 0; i < NUM_COLORS; ++i)
|
||||
all.push_back (context.stringtable.get (
|
||||
allColors[i].string_id,
|
||||
allColors[i].english_name));
|
||||
|
||||
std::vector <std::string> matches;
|
||||
autoComplete (name, all, matches);
|
||||
|
||||
if (matches.size () == 0)
|
||||
throw std::string ("Unrecognized color '") + name + "'";
|
||||
|
||||
else if (matches.size () != 1)
|
||||
{
|
||||
std::string error = "Ambiguous color '" + name + "' - could be either of "; // TODO i18n
|
||||
|
||||
std::string combined;
|
||||
join (combined, ", ", matches);
|
||||
|
||||
throw error + combined;
|
||||
}
|
||||
|
||||
return matches[0];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
58
src/color.h
58
src/color.h
@@ -1,58 +0,0 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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_COLOR
|
||||
#define INCLUDED_COLOR
|
||||
|
||||
namespace Text
|
||||
{
|
||||
enum color
|
||||
{
|
||||
nocolor = 0,
|
||||
off,
|
||||
bold, underline, bold_underline,
|
||||
black, bold_black, underline_black, bold_underline_black, on_black, on_bright_black,
|
||||
red, bold_red, underline_red, bold_underline_red, on_red, on_bright_red,
|
||||
green, bold_green, underline_green, bold_underline_green, on_green, on_bright_green,
|
||||
yellow, bold_yellow, underline_yellow, bold_underline_yellow, on_yellow, on_bright_yellow,
|
||||
blue, bold_blue, underline_blue, bold_underline_blue, on_blue, on_bright_blue,
|
||||
magenta, bold_magenta, underline_magenta, bold_underline_magenta, on_magenta, on_bright_magenta,
|
||||
cyan, bold_cyan, underline_cyan, bold_underline_cyan, on_cyan, on_bright_cyan,
|
||||
white, bold_white, underline_white, bold_underline_white, on_white, on_bright_white
|
||||
};
|
||||
|
||||
std::string colorName (color);
|
||||
color colorCode (const std::string&);
|
||||
|
||||
std::string colorize (color, color, const std::string& string);
|
||||
std::string colorize (color, color);
|
||||
std::string colorize ();
|
||||
std::string guessColor (const std::string&);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
2260
src/command.cpp
2260
src/command.cpp
File diff suppressed because it is too large
Load Diff
957
src/custom.cpp
957
src/custom.cpp
File diff suppressed because it is too large
Load Diff
111
src/edit.cpp
111
src/edit.cpp
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// Copyright 2006 - 2010, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -33,6 +33,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include "Directory.h"
|
||||
#include "File.h"
|
||||
#include "Date.h"
|
||||
#include "Duration.h"
|
||||
#include "text.h"
|
||||
@@ -80,7 +82,7 @@ static std::string findDate (
|
||||
|
||||
if (value != "")
|
||||
{
|
||||
Date dt (value, context.config.get ("dateformat", "m/d/Y"));
|
||||
Date dt (value, context.config.get ("dateformat"));
|
||||
char epoch [16];
|
||||
sprintf (epoch, "%d", (int)dt.toEpoch ());
|
||||
return std::string (epoch);
|
||||
@@ -100,7 +102,7 @@ static std::string formatDate (
|
||||
if (value.length ())
|
||||
{
|
||||
Date dt (::atoi (value.c_str ()));
|
||||
value = dt.toString (context.config.get ("dateformat", "m/d/Y"));
|
||||
value = dt.toString (context.config.get ("dateformat"));
|
||||
}
|
||||
|
||||
return value;
|
||||
@@ -150,7 +152,7 @@ static std::string formatTask (Task task)
|
||||
<< " Due: " << formatDate (task, "due") << std::endl
|
||||
<< " Until: " << formatDate (task, "until") << std::endl
|
||||
<< " Recur: " << task.get ("recur") << std::endl
|
||||
<< " Wait until: " << task.get ("wait") << std::endl
|
||||
<< " Wait until: " << formatDate (task, "wait") << std::endl
|
||||
<< " Parent: " << task.get ("parent") << std::endl
|
||||
<< " Foreground color: " << task.get ("fg") << std::endl
|
||||
<< " Background color: " << task.get ("bg") << std::endl
|
||||
@@ -161,8 +163,8 @@ static std::string formatTask (Task task)
|
||||
task.getAnnotations (annotations);
|
||||
foreach (anno, annotations)
|
||||
{
|
||||
Date dt (::atoi (anno->name ().substr (11, std::string::npos).c_str ()));
|
||||
before << " Annotation: " << dt.toString (context.config.get ("dateformat", "m/d/Y"))
|
||||
Date dt (::atoi (anno->name ().substr (11).c_str ()));
|
||||
before << " Annotation: " << dt.toString (context.config.get ("dateformat"))
|
||||
<< " " << anno->value () << std::endl;
|
||||
}
|
||||
|
||||
@@ -499,7 +501,7 @@ 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), context.config.get ("dateformat", "m/d/Y"));
|
||||
Date when (value.substr (0, gap), context.config.get ("dateformat"));
|
||||
|
||||
// This guarantees that if more than one annotation has the same date,
|
||||
// that the seconds will be different, thus unique, thus not squashed.
|
||||
@@ -508,7 +510,7 @@ static void parseTask (Task& task, const std::string& after)
|
||||
|
||||
std::stringstream name;
|
||||
name << "annotation_" << when.toEpoch ();
|
||||
std::string text = trim (value.substr (gap, std::string::npos), "\t ");
|
||||
std::string text = trim (value.substr (gap), "\t ");
|
||||
annotations.push_back (Att (name.str (), text));
|
||||
}
|
||||
}
|
||||
@@ -521,20 +523,20 @@ static void parseTask (Task& task, const std::string& after)
|
||||
void editFile (Task& task)
|
||||
{
|
||||
// Check for file permissions.
|
||||
std::string dataLocation = expandPath (context.config.get ("data.location"));
|
||||
if (access (dataLocation.c_str (), X_OK))
|
||||
Directory location (context.config.get ("data.location"));
|
||||
if (! location.writable ())
|
||||
throw std::string ("Your data.location directory is not writable.");
|
||||
|
||||
// Create a temp file name in data.location.
|
||||
std::stringstream file;
|
||||
file << dataLocation << "/task." << getpid () << "." << task.id << ".task";
|
||||
file << location.data << "/task." << getpid () << "." << task.id << ".task";
|
||||
|
||||
// Format the contents, T -> text, write to a file.
|
||||
std::string before = formatTask (task);
|
||||
spit (file.str (), before);
|
||||
File::write (file.str (), before);
|
||||
|
||||
// Determine correct editor: .taskrc:editor > $VISUAL > $EDITOR > vi
|
||||
std::string editor = context.config.get ("editor", "");
|
||||
std::string editor = context.config.get ("editor");
|
||||
char* peditor = getenv ("VISUAL");
|
||||
if (editor == "" && peditor) editor = std::string (peditor);
|
||||
peditor = getenv ("EDITOR");
|
||||
@@ -543,7 +545,7 @@ void editFile (Task& task)
|
||||
|
||||
// Complete the command line.
|
||||
editor += " ";
|
||||
editor += file.str ();
|
||||
editor += "\"" + file.str () + "\"";
|
||||
|
||||
ARE_THESE_REALLY_HARMFUL:
|
||||
// Launch the editor.
|
||||
@@ -555,7 +557,7 @@ ARE_THESE_REALLY_HARMFUL:
|
||||
|
||||
// Slurp file.
|
||||
std::string after;
|
||||
slurp (file.str (), after, false);
|
||||
File::read (file.str (), after);
|
||||
|
||||
// Update task based on what can be parsed back out of the file, but only
|
||||
// if changes were made.
|
||||
@@ -582,7 +584,7 @@ ARE_THESE_REALLY_HARMFUL:
|
||||
|
||||
// Preserve the edits.
|
||||
before = after;
|
||||
spit (file.str (), before);
|
||||
File::write (file.str (), before);
|
||||
|
||||
if (confirm ("Task couldn't handle your edits. Would you like to try again?"))
|
||||
goto ARE_THESE_REALLY_HARMFUL;
|
||||
@@ -592,7 +594,7 @@ ARE_THESE_REALLY_HARMFUL:
|
||||
std::cout << "No edits were detected." << std::endl;
|
||||
|
||||
// Cleanup.
|
||||
unlink (file.str ().c_str ());
|
||||
File::remove (file.str ());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -601,50 +603,57 @@ ARE_THESE_REALLY_HARMFUL:
|
||||
// wrench. To be used sparingly.
|
||||
int handleEdit (std::string &outs)
|
||||
{
|
||||
std::stringstream out;
|
||||
int rc = 0;
|
||||
|
||||
std::vector <Task> tasks;
|
||||
context.tdb.lock (context.config.get ("locking", true));
|
||||
handleRecurrence ();
|
||||
Filter filter;
|
||||
context.tdb.loadPending (tasks, filter);
|
||||
|
||||
// Filter sequence.
|
||||
std::vector <Task> all = tasks;
|
||||
context.filter.applySequence (tasks, context.sequence);
|
||||
|
||||
foreach (task, tasks)
|
||||
if (context.hooks.trigger ("pre-edit-command"))
|
||||
{
|
||||
editFile (*task);
|
||||
context.tdb.update (*task);
|
||||
/*
|
||||
foreach (other, all)
|
||||
std::stringstream out;
|
||||
|
||||
std::vector <Task> tasks;
|
||||
context.tdb.lock (context.config.getBoolean ("locking"));
|
||||
handleRecurrence ();
|
||||
Filter filter;
|
||||
context.tdb.loadPending (tasks, filter);
|
||||
|
||||
// Filter sequence.
|
||||
std::vector <Task> all = tasks;
|
||||
context.filter.applySequence (tasks, context.sequence);
|
||||
|
||||
foreach (task, tasks)
|
||||
{
|
||||
if (other->id != task.id) // Don't edit the same task again.
|
||||
editFile (*task);
|
||||
context.tdb.update (*task);
|
||||
/*
|
||||
foreach (other, all)
|
||||
{
|
||||
if (task.has ("parent") &&
|
||||
if (other is parent of task)
|
||||
if (other->id != task.id) // Don't edit the same task again.
|
||||
{
|
||||
// Transfer everything but mask, imask, uuid, parent.
|
||||
}
|
||||
else if (task is parent of other)
|
||||
{
|
||||
// Transfer everything but mask, imask, uuid, parent.
|
||||
}
|
||||
else if (task and other are siblings)
|
||||
{
|
||||
// Transfer everything but mask, imask, uuid, parent.
|
||||
if (task.has ("parent") &&
|
||||
if (other is parent of task)
|
||||
{
|
||||
// Transfer everything but mask, imask, uuid, parent.
|
||||
}
|
||||
else if (task is parent of other)
|
||||
{
|
||||
// Transfer everything but mask, imask, uuid, parent.
|
||||
}
|
||||
else if (task and other are siblings)
|
||||
{
|
||||
// Transfer everything but mask, imask, uuid, parent.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
context.tdb.commit ();
|
||||
context.tdb.unlock ();
|
||||
|
||||
outs = out.str ();
|
||||
context.hooks.trigger ("post-edit-command");
|
||||
}
|
||||
|
||||
context.tdb.commit ();
|
||||
context.tdb.unlock ();
|
||||
|
||||
outs = out.str ();
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user