Compare commits
128 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b9dc0813d9 | ||
|
|
25c687e1ec | ||
|
|
6e98bbbd85 | ||
|
|
06c8976be5 | ||
|
|
d13a5a3f47 | ||
|
|
b662afa1ff | ||
|
|
bde83d3195 | ||
|
|
0edb7e57f6 | ||
|
|
4569d2da24 | ||
|
|
6b00f08794 | ||
|
|
e83809c6aa | ||
|
|
39b736d23e | ||
|
|
3e90554f40 | ||
|
|
4690b1a6cb | ||
|
|
ce1a7b921c | ||
|
|
7a1645bba3 | ||
|
|
9f1b3e0d56 | ||
|
|
0af8b1dbab | ||
|
|
1465bcb918 | ||
|
|
4eb70e68b7 | ||
|
|
cd216bd4fd | ||
|
|
ac4a5c6d62 | ||
|
|
a67593decf | ||
|
|
7be294267b | ||
|
|
920cdcca10 | ||
|
|
7cc410f58e | ||
|
|
5d42c0f6b6 | ||
|
|
cff680d074 | ||
|
|
dda190703e | ||
|
|
281edcc38f | ||
|
|
87d00698db | ||
|
|
19674ee339 | ||
|
|
9f654a5c95 | ||
|
|
87e9578666 | ||
|
|
e3ec52f6ca | ||
|
|
70c3d9845c | ||
|
|
9d1c4101c2 | ||
|
|
44ed974fa2 | ||
|
|
3cf7a701c8 | ||
|
|
d390f99fc5 | ||
|
|
a2cae67644 | ||
|
|
ebd6977480 | ||
|
|
276050ce0b | ||
|
|
197815a3a7 | ||
|
|
5e8426f0cc | ||
|
|
138360b7bc | ||
|
|
7fa3c5ac84 | ||
|
|
b5da4acab9 | ||
|
|
180c382de2 | ||
|
|
23d4e2b3c9 | ||
|
|
96185cbd61 | ||
|
|
7665d13d42 | ||
|
|
a40967a324 | ||
|
|
01feec568b | ||
|
|
104aeb3905 | ||
|
|
f0cc0151b7 | ||
|
|
48be6986c2 | ||
|
|
ffd6465661 | ||
|
|
58e62711f3 | ||
|
|
3b9d88a87b | ||
|
|
aa8cd54142 | ||
|
|
651ac3f174 | ||
|
|
ea78200ae3 | ||
|
|
ad89a90d12 | ||
|
|
85d0e1789a | ||
|
|
e19c99ce1e | ||
|
|
0868ba757c | ||
|
|
bf5f246168 | ||
|
|
9748fa2ab1 | ||
|
|
1a0f479394 | ||
|
|
e2f35a1a06 | ||
|
|
394acae790 | ||
|
|
e8d385119a | ||
|
|
070fdf60fa | ||
|
|
1278226c16 | ||
|
|
98410cff42 | ||
|
|
ee23a099f2 | ||
|
|
0ab1dc0c9c | ||
|
|
c2a9bb65e6 | ||
|
|
75cf742a55 | ||
|
|
dc0502dd9f | ||
|
|
3a77a5f291 | ||
|
|
1abda3900b | ||
|
|
09fe5be086 | ||
|
|
1a3550541b | ||
|
|
371ca27da0 | ||
|
|
5f3dd43893 | ||
|
|
edb54a51b3 | ||
|
|
636f6bfd96 | ||
|
|
e91063426a | ||
|
|
a4d5ab07e9 | ||
|
|
49a7e46eaf | ||
|
|
0891ed4b57 | ||
|
|
af772f4c49 | ||
|
|
3484e44c7d | ||
|
|
be855af8c4 | ||
|
|
1ae4ea2ea3 | ||
|
|
d37937d970 | ||
|
|
51e947064f | ||
|
|
606a7505d3 | ||
|
|
846dd14a9f | ||
|
|
d8f436cca9 | ||
|
|
ac9c726782 | ||
|
|
88d65b23c1 | ||
|
|
f2998aba74 | ||
|
|
d2b2631db7 | ||
|
|
4c491d8a0d | ||
|
|
917a152a1e | ||
|
|
289e45499a | ||
|
|
2efb9594d9 | ||
|
|
0d096a5a42 | ||
|
|
cc1c063925 | ||
|
|
dd31a15001 | ||
|
|
c11601e30e | ||
|
|
520067f522 | ||
|
|
693fe9b8fd | ||
|
|
fa249bfedd | ||
|
|
952d743218 | ||
|
|
91f6980d2f | ||
|
|
d211969236 | ||
|
|
bd320b6729 | ||
|
|
3f004f547e | ||
|
|
3b192cddcf | ||
|
|
ca6061a987 | ||
|
|
2787ee960b | ||
|
|
c27ad4dc27 | ||
|
|
a36eb974ee | ||
|
|
a55a7bf1a2 |
1
AUTHORS
1
AUTHORS
@@ -245,3 +245,4 @@ suggestions:
|
||||
Scott Carter
|
||||
Taisuke Hachimura
|
||||
Martin
|
||||
Alexandre de Verteuil
|
||||
|
||||
@@ -10,17 +10,40 @@ include (CheckStructHasMember)
|
||||
set (HAVE_CMAKE true)
|
||||
|
||||
project (task)
|
||||
set (PROJECT_VERSION "2.4.1")
|
||||
set (PROJECT_VERSION "2.4.2")
|
||||
|
||||
OPTION(USE_GNUTLS "Build gnutls support." ON)
|
||||
|
||||
message ("CMAKE_SYSTEM_NAME ${CMAKE_SYSTEM_NAME}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
|
||||
include (CheckCXXCompilerFlag)
|
||||
|
||||
# NOTE: If we are to actually use C++11 features, we should either require
|
||||
# a compiler that supports the -std=c++11 flag or check for the
|
||||
# features used.
|
||||
# Relying on -std=c++0x or even -std=gnu++0x is highly volatile.
|
||||
|
||||
CHECK_CXX_COMPILER_FLAG("-std=c++11" _HAS_CXX11)
|
||||
CHECK_CXX_COMPILER_FLAG("-std=c++0x" _HAS_CXX0X)
|
||||
CHECK_CXX_COMPILER_FLAG("-std=gnu++0x" _HAS_GNU0X)
|
||||
|
||||
if (_HAS_CXX11)
|
||||
set (_CXX11_FLAGS "-std=c++11")
|
||||
elseif (_HAS_CXX0X)
|
||||
message (WARNING "Enabling -std=c++0x draft compile flag. Your compiler does not support the standard '-std=c++11' option. Consider upgrading.")
|
||||
set (_CXX11_FLAGS "-std=c++0x")
|
||||
elseif (_HAS_GNU0X)
|
||||
message (WARNING "Enabling -std=gnu++0x draft compile flag. Your compiler does not support the standard '-std=c++11' option. Consider upgrading.")
|
||||
set (_CXX11_FLAGS "-std=gnu++0x")
|
||||
else (_HAS_CXX11)
|
||||
message (FATAL_ERROR "C++11 support missing. Try upgrading your C++ compiler. If you have a good reason for using an outdated compiler, please let us know at support@taskwarrior.org.")
|
||||
endif (_HAS_CXX11)
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
set (LINUX true)
|
||||
elseif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
set (DARWIN true)
|
||||
set (CMAKE_CXX_FLAGS "-std=c++11 -stdlib=libc++")
|
||||
set (_CXX11_FLAGS "${_CXX11_FLAGS} -stdlib=libc++")
|
||||
elseif (${CMAKE_SYSTEM_NAME} MATCHES "kFreeBSD")
|
||||
set (KFREEBSD true)
|
||||
elseif (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
|
||||
@@ -35,11 +58,16 @@ elseif (${CMAKE_SYSTEM_NAME} STREQUAL "GNU")
|
||||
set (GNUHURD true)
|
||||
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "CYGWIN")
|
||||
set (CYGWIN true)
|
||||
set (CMAKE_CXX_FLAGS "-std=gnu++0x")
|
||||
# NOTE: Not setting -std=gnu++0x leads to compile errors even with
|
||||
# GCC 4.8.3, and debugging those leads to insanity. Adding this
|
||||
# workaround instead of fixing Cygwin.
|
||||
set (_CXX11_FLAGS "-std=gnu++0x")
|
||||
else (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
set (UNKNOWN true)
|
||||
endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
|
||||
set (CMAKE_CXX_FLAGS "${_CXX11_FLAGS} ${CMAKE_CXX_FLAGS}")
|
||||
|
||||
if (NETBSD)
|
||||
# Since readline, etc likely to be in /usr/pkg/lib, not standard library
|
||||
# Otherwise will remove links during install
|
||||
@@ -86,16 +114,6 @@ if (USE_GNUTLS)
|
||||
endif (GNUTLS_FOUND)
|
||||
endif (USE_GNUTLS)
|
||||
|
||||
#message ("-- Looking for pthread")
|
||||
#find_path (PTHREAD_INCLUDE_DIR pthread.h)
|
||||
#find_library (PTHREAD_LIBRARY NAMES pthread)
|
||||
#if (PTHREAD_INCLUDE_DIR AND PTHREAD_LIBRARY)
|
||||
# message ("-- Found pthread: ${PTHREAD_LIBRARY}")
|
||||
# set (HAVE_LIBPTHREAD true)
|
||||
# set (TASK_INCLUDE_DIRS ${TASK_INCLUDE_DIRS} ${PTHREAD_INCLUDE_DIR})
|
||||
# set (TASK_LIBRARIES ${TASK_LIBRARIES} ${PTHREAD_LIBRARIES})
|
||||
#endif (PTHREAD_INCLUDE_DIR AND PTHREAD_LIBRARY)
|
||||
|
||||
check_function_exists (timegm HAVE_TIMEGM)
|
||||
check_function_exists (get_current_dir_name HAVE_GET_CURRENT_DIR_NAME)
|
||||
check_function_exists (wordexp HAVE_WORDEXP)
|
||||
|
||||
36
ChangeLog
36
ChangeLog
@@ -1,4 +1,35 @@
|
||||
2.4.1 (2015-02-16) -
|
||||
2.4.2 (2015-03-15) -
|
||||
|
||||
- TW-41 Tasks in subprojects are not counted in project completion (thanks
|
||||
to Renato Alves).
|
||||
- TW-1450 Projects command should trigger running garbage collector (thanks to
|
||||
Tomas Babej).
|
||||
- TW-1535 move default listing-break from list to ls (thanks to David Patrick).
|
||||
- TW-1545 cc1plus: error: unrecognized command line option '-std=c++11' (thanks
|
||||
to Petteri).
|
||||
- TW-1546 column type due.remaining breaks colors on due tasks (thanks to
|
||||
Renato Alves).
|
||||
- TW-1547 Recur column is always shown even if no recurring task is displayed
|
||||
(thanks to Renato Alves).
|
||||
- TW-1549 task annotate hangs with specific text pattern (thanks to Alexandre
|
||||
de Verteuil).
|
||||
- TW-1550 _contexts helper-command (thanks to David Patrick).
|
||||
- TW-1551 Unable to get a UDA value from DOM (thanks to Tomas Babej).
|
||||
- Eliminated some code that is not UTF8-safe.
|
||||
- Removed pthreads linkage.
|
||||
- Implemented the context feature.
|
||||
- Closed dangling pipes in execute (), resolving problems when a hook script
|
||||
forks (thanks to Jens Erat).
|
||||
- Re-enabled hook script feedback when exiting with 0 exit status.
|
||||
- The 'info' command now shows virtual tags.
|
||||
- Fixed major on-modify hooks regression where hooks could no longer modify
|
||||
the tasks handed to them.
|
||||
- 'task _version' now outputs "2.4.2 (git-ref)" when built from git. "2.4.2"
|
||||
when built from release tarballs (thanks to Renato Alves).
|
||||
|
||||
------ current release ---------------------------
|
||||
|
||||
2.4.1 (2015-02-16) 82e019a4a8b20de63d53b51d59b8d1c89d3c05b2
|
||||
|
||||
- TW-1457 Non-existent attributes are not properly handled (thanks to Tomas
|
||||
Babej).
|
||||
@@ -46,8 +77,6 @@
|
||||
Sujeevan Vijayakumaran).
|
||||
- New 'recurrence' configuration setting can disable recurring task generation.
|
||||
|
||||
------ current release ---------------------------
|
||||
|
||||
2.4.0 (2015-01-01) 670102842c39bdc62ef84ae4b679a8f5a2d89523
|
||||
|
||||
- TD-42 Cannot compile taskd - GNUTLS_VERSION undefined in diag.cpp (thanks
|
||||
@@ -95,6 +124,7 @@
|
||||
- TW-52 "task add ... recur:2 months" interpreted as "2s" (thanks to jwhisnant).
|
||||
- TW-55 Bulk edit recurring tasks without answering yes/no for each? (thanks to
|
||||
Max Muller).
|
||||
- TW-63 indicators for UDAs (thanks to David Patrick).
|
||||
- TW-71 task ls/list/long/etc. should match contents of projects too (thanks to
|
||||
Cory Donnelly).
|
||||
- TW-72 extend info report with urgency column.
|
||||
|
||||
@@ -10,7 +10,7 @@ How to Build Taskwarrior
|
||||
Obtain and build code:
|
||||
$ git clone https://git.tasktools.org/scm/tm/task.git task.git
|
||||
$ cd task.git
|
||||
$ git checkout 2.4.1 # Latest dev branch
|
||||
$ git checkout 2.4.2 # Latest dev branch
|
||||
$ cmake -DCMAKE_BUILD_TYPE=debug . # debug or release. Default: neither.
|
||||
$ make VERBOSE=1 # Shows details
|
||||
|
||||
|
||||
11
INSTALL
11
INSTALL
@@ -8,16 +8,17 @@ Pre-requisites
|
||||
--------------
|
||||
|
||||
You will need the CMake build system installed in order to build taskwarrior
|
||||
from source.
|
||||
from source. More information on cmake can be obtained at http://cmake.org
|
||||
|
||||
You will need a C++ compiler that support C++11 N1984, which includes:
|
||||
You will need a C++ compiler that supports C++11 N1984, which includes:
|
||||
|
||||
- gcc 4.4 (released 2009-04-21)
|
||||
- clang 2.9 (released 2011-04-06)
|
||||
- uuid lib
|
||||
- gnutls (optional)
|
||||
|
||||
More information on cmake can be obtained at http://cmake.org
|
||||
In addition:
|
||||
|
||||
- uuid lib
|
||||
- gnutls (optional - for syncing)
|
||||
|
||||
It is HIGHLY RECOMMENDED that you build with a library that provides uuid_*
|
||||
functions, such as libuuid.
|
||||
|
||||
46
NEWS
46
NEWS
@@ -1,26 +1,24 @@
|
||||
|
||||
New Features in taskwarrior 2.4.1
|
||||
New Features in taskwarrior 2.4.2
|
||||
|
||||
- New German translation.
|
||||
- Hook scripts are now under much stricter control.
|
||||
- Ability to set context, which serves as a permanent user-defined filter.
|
||||
- The 'info' command now shows virtual tags.
|
||||
|
||||
New commands in taskwarrior 2.4.1
|
||||
New commands in taskwarrior 2.4.2
|
||||
|
||||
- The 'context' command has been added, along with it subcommands 'define',
|
||||
'delete', 'show', 'list' and 'none'.
|
||||
|
||||
New configuration options in taskwarrior 2.4.2
|
||||
|
||||
- 'context' to store the current context applied.
|
||||
- 'context.<name>' to store the definition of context 'name'
|
||||
|
||||
Newly deprecated features in taskwarrior 2.4.2
|
||||
|
||||
- None
|
||||
|
||||
New configuration options in taskwarrior 2.4.1
|
||||
|
||||
- The 'date.iso' setting allows you to enable (default) or disable support
|
||||
for ISO-8601 dates. This is because some of you have 'dateformat' settings
|
||||
that conflict.
|
||||
- The 'recurrence' setting enables (default) or disables recurring task
|
||||
instance generation.
|
||||
|
||||
Newly deprecated features in taskwarrior 2.4.1
|
||||
|
||||
- None
|
||||
|
||||
Removed features in 2.4.1
|
||||
Removed features in 2.4.2
|
||||
|
||||
- None
|
||||
|
||||
@@ -40,13 +38,13 @@ Known Issues
|
||||
|
||||
Taskwarrior has been built and tested on the following configurations:
|
||||
|
||||
* OS X 10.10 Yosemite
|
||||
* Fedora 20 Heisenbug
|
||||
* Ubuntu 14.04 Trusty Tahr
|
||||
* Debian 7.0 Wheezy (stable)
|
||||
* Arch 2014.05
|
||||
* FreeBSD 10
|
||||
* Cygwin 1.7.29, 1.7.32
|
||||
* OS X
|
||||
* Fedora
|
||||
* Ubuntu
|
||||
* Debian
|
||||
* Arch
|
||||
* FreeBSD
|
||||
* Cygwin
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.TH task-color 5 2015-02-16 "${PACKAGE_STRING}" "User Manuals"
|
||||
.TH task-color 5 2015-03-15 "${PACKAGE_STRING}" "User Manuals"
|
||||
|
||||
.SH NAME
|
||||
task-color \- A color tutorial for the taskwarrior command line todo manager.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.TH task-sync 5 2015-02-16 "${PACKAGE_STRING}" "User Manuals"
|
||||
.TH task-sync 5 2015-03-15 "${PACKAGE_STRING}" "User Manuals"
|
||||
|
||||
.SH NAME
|
||||
task-sync \- A discussion and tutorial for the various task(1) data
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.TH task 1 2015-02-16 "${PACKAGE_STRING}" "User Manuals"
|
||||
.TH task 1 2015-03-15 "${PACKAGE_STRING}" "User Manuals"
|
||||
|
||||
.SH NAME
|
||||
task \- A command line todo manager.
|
||||
@@ -396,6 +396,46 @@ Finally, this command removes any 'name=...' entry from the .taskrc file:
|
||||
|
||||
task config name
|
||||
|
||||
.TP
|
||||
.B task context <name>
|
||||
Sets the currectly active context. See the CONTEXT section.
|
||||
|
||||
Example:
|
||||
|
||||
task context work
|
||||
|
||||
.TP
|
||||
.B task context delete <name>
|
||||
Deletes the context with the name <name>. If the context being deleted is currently
|
||||
set as active, it will be unset.
|
||||
|
||||
Example:
|
||||
|
||||
task context delete work
|
||||
|
||||
.TP
|
||||
.B task context define <name> <filter>
|
||||
Defines a new context with name <name> and definition <filter>. This command
|
||||
does not affect the currently set context, just adds a new context definition.
|
||||
|
||||
Examples:
|
||||
|
||||
task context define work project:Work
|
||||
task context define home project:Home or +home
|
||||
task context define superurgent due:today and +urgent
|
||||
|
||||
.TP
|
||||
.B task context list
|
||||
Outputs a list of available contexts along with their definitions.
|
||||
|
||||
.TP
|
||||
.B task context none
|
||||
Unsets the currently active context, if any was set.
|
||||
|
||||
.TP
|
||||
.B task context show
|
||||
Shows the currently active context, along with its definition.
|
||||
|
||||
.TP
|
||||
.B task diagnostics
|
||||
Shows diagnostic information, of the kind needed when reporting a problem.
|
||||
@@ -474,6 +514,10 @@ Generates a list of all commands, for autocompletion purposes.
|
||||
.B task _config
|
||||
Lists all supported configuration variables, for completion purposes.
|
||||
|
||||
.TP
|
||||
.B task _context
|
||||
Lists all available context variables, for completion purposes.
|
||||
|
||||
.TP
|
||||
.B task <filter> _ids
|
||||
Shows only the IDs of matching tasks, in the form of a list.
|
||||
@@ -962,6 +1006,66 @@ biannual, biyearly, 2yr
|
||||
Every two years.
|
||||
.RE
|
||||
|
||||
.SH CONTEXT
|
||||
Context is a user-defined filter, which is automatically applied to all commands
|
||||
that filter the task list. In particular, any report command will have its
|
||||
result affected by the current active context.
|
||||
|
||||
$ task list
|
||||
ID Age Project Description Urg
|
||||
1 2d Sport Run 5 miles 1.42
|
||||
2 1d Home Clean the dishes 1.14
|
||||
|
||||
$ task context home
|
||||
Context 'home' set. Use 'task context none' to remove.
|
||||
|
||||
$ task list
|
||||
ID Age Project Description Urg
|
||||
2 1d Home Clean the dishes 1.14
|
||||
Context 'home' set. Use 'task context none' to remove.
|
||||
|
||||
As seen in the example above, context is applied by specifying its name to the
|
||||
"context" command. To change the currently applied context, just pass the
|
||||
new context's name to the 'context' command.
|
||||
|
||||
To unset any context, use the 'none' subcommand.
|
||||
|
||||
$ task context none
|
||||
Context unset.
|
||||
|
||||
$ task list
|
||||
ID Age Project Description Urg
|
||||
1 2d Sport Run 5 miles 1.42
|
||||
2 1d Home Clean the dishes 1.14
|
||||
|
||||
Context can be defined using the 'define' subcommand, specifying both the name
|
||||
of the new context, and it's assigned filter.
|
||||
|
||||
$ task context define home
|
||||
Are you sure you want to add 'context.home' with a value of 'project:Home'? (yes/no) yes
|
||||
Context 'home' successfully defined.
|
||||
|
||||
To remove the definition, use the 'delete' subcommand.
|
||||
|
||||
$ task context delete home
|
||||
Are you sure you want to remove 'context.home'? (yes/no) yes
|
||||
Context 'home' successfully undefined.
|
||||
|
||||
To check what is the currently active context, use the 'show' subcommand.
|
||||
|
||||
$ task context show
|
||||
Context 'home' with filter 'project:Home' is currently applied.
|
||||
|
||||
Contexts can store arbitrarily complex filters.
|
||||
|
||||
$ task context define family project:Family or +paul or +nancy
|
||||
Are you sure you want to add 'context.home' with a value of 'project:Family or +paul or +nancy'? (yes/no) yes
|
||||
Context 'family' successfully defined.
|
||||
|
||||
Contexts are permanent, and the currently set context name is stored in the
|
||||
"context" configuration variable. The context definition is stored in the
|
||||
"context.<name>" configuration variable.
|
||||
|
||||
.SH COMMAND ABBREVIATION
|
||||
All taskwarrior commands may be abbreviated as long as a unique prefix is used,
|
||||
for example:
|
||||
@@ -1057,11 +1161,11 @@ the 'data.location' configuration setting of the task data directory.
|
||||
For examples please see the online documentation starting at
|
||||
|
||||
.RS
|
||||
<http://taskwarrior.org/projects/taskwarrior/wiki>
|
||||
<http://taskwarrior.org/docs>
|
||||
.RE
|
||||
|
||||
Note that the online documentation is more detailed and more current than this
|
||||
man page.
|
||||
Note that the online documentation can be more detailed and more current than
|
||||
this man page.
|
||||
|
||||
.SH FILES
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.TH taskrc 5 2015-02-16 "${PACKAGE_STRING}" "User Manuals"
|
||||
.TH taskrc 5 2015-03-15 "${PACKAGE_STRING}" "User Manuals"
|
||||
|
||||
.SH NAME
|
||||
taskrc \- Configuration details for the task(1) command
|
||||
@@ -1351,6 +1351,26 @@ of a task.
|
||||
.B uda.estimate.values=trivial,small,medium,large,huge
|
||||
.RE
|
||||
|
||||
.SS CONTEXT
|
||||
Context setting is a mechanism which allows the user to set a permanent filter,
|
||||
thus avoiding the need to specify one filter repeatedly. More details on usage
|
||||
can be found in the task(1) manpage.
|
||||
|
||||
The current context is stored in the taskrc file, along with definitions for
|
||||
all user provided contexts.
|
||||
|
||||
.TP
|
||||
.B context=<name>
|
||||
.RS
|
||||
Stores the value of the currently active context.
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B context.<name>=<filter>
|
||||
.RS
|
||||
Stores the definition of the context with the name <name>.
|
||||
.RE
|
||||
|
||||
.SS SYNC
|
||||
|
||||
These configuration settings are used to connect and sync tasks with the task
|
||||
|
||||
@@ -1,15 +1,24 @@
|
||||
Themes
|
||||
|
||||
To generate samples of themes, first execute the 'run' script to generate the
|
||||
To generate samples of themes, first execute the 'setup' script to generate the
|
||||
sample data. Note that this data may need to be tweaked to include qualities
|
||||
that need to be illustrated in theme sample.
|
||||
|
||||
Then edit the 'rc' file to include the desired theme file.
|
||||
Using a dark-background terminal (black recommended), run the following:
|
||||
|
||||
Then run 'per' to run a few commands for each theme.
|
||||
run.dark
|
||||
|
||||
Note that this will require that the terminal window be switched between a black
|
||||
and white background to properly show the light and dark themes.
|
||||
Using a light-background terminal, run the following:
|
||||
|
||||
run.light
|
||||
|
||||
Using a solarized dark terminal, run the following:
|
||||
|
||||
run.solar.dark
|
||||
|
||||
Using a solarized light terminal, run the following:
|
||||
|
||||
run.solar.light
|
||||
|
||||
Note that for the solarized themes, the terminal color palette needs to be set
|
||||
to specific colors.
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
|
||||
|
||||
for theme in $PWD/../../rc/*.theme
|
||||
do
|
||||
cat <<EOF >>x
|
||||
data.location=.
|
||||
confirmation=off
|
||||
_forcecolor=on
|
||||
include $theme
|
||||
EOF
|
||||
|
||||
echo "--- $theme -----------------------------------------------------"
|
||||
echo '$ task list'
|
||||
task rc:x list
|
||||
echo '$ task summary'
|
||||
task rc:x summary
|
||||
echo '$ task ghistory'
|
||||
task rc:x ghistory
|
||||
echo '$ task calendar'
|
||||
task rc:x calendar
|
||||
echo '$ task burndown.daily'
|
||||
task rc:x burndown.daily
|
||||
done
|
||||
@@ -21,6 +21,8 @@ include $theme
|
||||
EOF
|
||||
|
||||
echo "--- $theme -----------------------------------------------------"
|
||||
echo '$ task color legend'
|
||||
task rc:x color legend
|
||||
echo '$ task list'
|
||||
task rc:x list
|
||||
echo '$ task summary'
|
||||
|
||||
24
doc/misc/themes/run.default
Executable file
24
doc/misc/themes/run.default
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/bin/bash
|
||||
|
||||
cat <<EOF >x
|
||||
data.location=.
|
||||
confirmation=off
|
||||
detection=off
|
||||
_forcecolor=on
|
||||
default.height=24
|
||||
verbose=off
|
||||
EOF
|
||||
|
||||
echo "--- DEFAULT -----------------------------------------------------"
|
||||
echo '$ task color legend'
|
||||
task rc:x color legend
|
||||
echo '$ task list'
|
||||
task rc:x list
|
||||
echo '$ task summary'
|
||||
task rc:x summary
|
||||
echo '$ task ghistory'
|
||||
task rc:x ghistory
|
||||
echo '$ task calendar'
|
||||
task rc:x calendar
|
||||
echo '$ task burndown.daily'
|
||||
task rc:x burndown.daily
|
||||
@@ -14,6 +14,8 @@ include $theme
|
||||
EOF
|
||||
|
||||
echo "--- $theme -----------------------------------------------------"
|
||||
echo '$ task color legend'
|
||||
task rc:x color legend
|
||||
echo '$ task list'
|
||||
task rc:x list
|
||||
echo '$ task summary'
|
||||
|
||||
@@ -13,6 +13,8 @@ include $theme
|
||||
EOF
|
||||
|
||||
echo "--- $theme -----------------------------------------------------"
|
||||
echo '$ task color legend'
|
||||
task rc:x color legend
|
||||
echo '$ task list'
|
||||
task rc:x list
|
||||
echo '$ task summary'
|
||||
|
||||
@@ -13,6 +13,8 @@ include $theme
|
||||
EOF
|
||||
|
||||
echo "--- $theme -----------------------------------------------------"
|
||||
echo '$ task color legend'
|
||||
task rc:x color legend
|
||||
echo '$ task list'
|
||||
task rc:x list
|
||||
echo '$ task summary'
|
||||
|
||||
@@ -33,15 +33,15 @@ color.alternate=
|
||||
color.header=yellow
|
||||
color.footnote=yellow
|
||||
color.warning=bold red
|
||||
color.error=yellow
|
||||
color.debug=yellow
|
||||
color.error=white on red
|
||||
color.debug=blue
|
||||
|
||||
# Task state
|
||||
color.completed=green on white
|
||||
color.deleted=red on white
|
||||
color.completed=
|
||||
color.deleted=
|
||||
color.active=black on bright green
|
||||
color.recurring=magenta
|
||||
color.scheduled=on green
|
||||
color.scheduled=white on green
|
||||
color.until=
|
||||
color.blocked=black on white
|
||||
color.blocking=black on bright white
|
||||
|
||||
@@ -29,16 +29,16 @@ rule.precedence.color=deleted,completed,active,keyword.,tag.,uda.,project.,overd
|
||||
# General decoration
|
||||
color.label=
|
||||
color.label.sort=
|
||||
color.alternate=on gray1
|
||||
color.alternate=on gray2
|
||||
color.header=color3
|
||||
color.footnote=color3
|
||||
color.warning=bold red
|
||||
color.error=color3
|
||||
color.debug=color3
|
||||
color.error=white on red
|
||||
color.debug=color4
|
||||
|
||||
# Task state
|
||||
color.completed=rgb010 on white
|
||||
color.deleted=rgb100 on white
|
||||
color.completed=
|
||||
color.deleted=
|
||||
color.active=rgb555 on rgb410
|
||||
color.recurring=rgb013
|
||||
color.scheduled=on rgb001
|
||||
|
||||
@@ -29,19 +29,19 @@ rule.precedence.color=deleted,completed,active,keyword.,tag.,uda.,project.,overd
|
||||
# General decoration
|
||||
color.label=
|
||||
color.label.sort=
|
||||
color.alternate=on gray1
|
||||
color.alternate=on gray2
|
||||
color.header=rgb013
|
||||
color.footnote=rgb013
|
||||
color.warning=bold red
|
||||
color.error=rgb013
|
||||
color.error=white on red
|
||||
color.debug=rgb013
|
||||
|
||||
# Task state
|
||||
color.completed=rgb001 on white
|
||||
color.deleted=rgb100 on white
|
||||
color.completed=
|
||||
color.deleted=
|
||||
color.active=rgb045 on rgb015
|
||||
color.recurring=rgb115
|
||||
color.scheduled=on rgb011
|
||||
color.scheduled=on rgb012
|
||||
color.until=
|
||||
color.blocked=white on rgb001
|
||||
color.blocking=white on rgb002
|
||||
@@ -76,8 +76,8 @@ color.history.delete=color0 on rgb035
|
||||
color.history.done=color0 on rgb025
|
||||
|
||||
# Report: summary
|
||||
color.summary.background=white on color0
|
||||
color.summary.bar=white on rgb003
|
||||
color.summary.background=on rgb001
|
||||
color.summary.bar=on rgb114
|
||||
|
||||
# Command: calendar
|
||||
color.calendar.due.today=color0 on color252
|
||||
|
||||
@@ -29,16 +29,16 @@ rule.precedence.color=deleted,completed,active,keyword.,tag.,uda.,project.,overd
|
||||
# General decoration
|
||||
color.label=
|
||||
color.label.sort=
|
||||
color.alternate=on gray1
|
||||
color.alternate=on gray2
|
||||
color.header=color0 on gray11
|
||||
color.footnote=on gray5
|
||||
color.warning=bold red
|
||||
color.error=red on white
|
||||
color.debug=black on white
|
||||
color.error=white on red
|
||||
color.debug=blue
|
||||
|
||||
# Task state
|
||||
color.completed=black on white
|
||||
color.deleted=black on white
|
||||
color.completed=
|
||||
color.deleted=
|
||||
color.active=black on gray18
|
||||
color.recurring=
|
||||
color.scheduled=on gray8
|
||||
@@ -61,7 +61,7 @@ color.tag.none=
|
||||
color.tagged=
|
||||
|
||||
# Due
|
||||
color.due=on gray2
|
||||
color.due=on gray3
|
||||
color.due.today=on gray4
|
||||
color.overdue=on gray6
|
||||
|
||||
@@ -76,12 +76,12 @@ color.history.delete=black on gray10
|
||||
color.history.done=gray5 on gray23
|
||||
|
||||
# Report: summary
|
||||
color.summary.bar=on gray15
|
||||
color.summary.background=on black
|
||||
color.summary.bar=on gray12
|
||||
color.summary.background=on gray5
|
||||
|
||||
# Command: calendar
|
||||
color.calendar.due=on gray8
|
||||
color.calendar.due.today=on gray15
|
||||
color.calendar.due.today=black on gray15
|
||||
color.calendar.holiday=black on gray20
|
||||
color.calendar.overdue=gray2 on gray10
|
||||
color.calendar.today=bold white
|
||||
@@ -89,7 +89,7 @@ color.calendar.weekend=on gray2
|
||||
color.calendar.weeknumber=gray6
|
||||
|
||||
# Command: sync
|
||||
color.sync.add=gray15 on gray5
|
||||
color.sync.added=gray15 on gray5
|
||||
color.sync.changed=black on gray10
|
||||
color.sync.rejected=gray5 on gray23
|
||||
|
||||
|
||||
@@ -29,12 +29,12 @@ rule.precedence.color=deleted,completed,active,keyword.,tag.,uda.,project.,overd
|
||||
# General decoration
|
||||
color.label=
|
||||
color.label.sort=
|
||||
color.alternate=on gray0
|
||||
color.alternate=on gray2
|
||||
color.header=gray10
|
||||
color.footnote=gray10
|
||||
color.warning=
|
||||
color.error=rgb500
|
||||
color.debug=rgb500
|
||||
color.error=white on red
|
||||
color.debug=blue
|
||||
|
||||
# Task state
|
||||
color.completed=
|
||||
@@ -66,18 +66,18 @@ color.due.today=color0 on rgb024
|
||||
color.overdue=color0 on rgb035
|
||||
|
||||
# Report: burndown
|
||||
color.burndown.pending=on gray9
|
||||
color.burndown.started=on gray16
|
||||
color.burndown.done=on rgb013
|
||||
color.burndown.pending=white on gray9
|
||||
color.burndown.started=black on gray16
|
||||
color.burndown.done=white on rgb013
|
||||
|
||||
# Report: history
|
||||
color.history.add=on gray9
|
||||
color.history.delete=black on gray23
|
||||
color.history.done=black on rgb013
|
||||
color.history.add=white on gray6
|
||||
color.history.delete=black on gray18
|
||||
color.history.done=black on rgb024
|
||||
|
||||
# Report: summary
|
||||
color.summary.bar=on rgb012
|
||||
color.summary.background=on color0
|
||||
color.summary.background=on gray2
|
||||
|
||||
# Command: calendar
|
||||
color.calendar.due=color0 on gray10
|
||||
@@ -94,6 +94,6 @@ color.sync.changed=gray15
|
||||
color.sync.rejected=gray23
|
||||
|
||||
# Command: undo
|
||||
color.undo.before=green
|
||||
color.undo.after=red
|
||||
color.undo.before=rgb013
|
||||
color.undo.after=rgb035
|
||||
|
||||
|
||||
@@ -29,19 +29,19 @@ rule.precedence.color=deleted,completed,active,keyword.,tag.,uda.,project.,overd
|
||||
# General decoration
|
||||
color.label=
|
||||
color.label.sort=
|
||||
color.alternate=on gray1
|
||||
color.alternate=on gray2
|
||||
color.header=rgb031
|
||||
color.footnote=rgb031
|
||||
color.warning=bold red
|
||||
color.error=rgb031
|
||||
color.debug=rgb031
|
||||
color.warning=rgb020
|
||||
color.error=white on red
|
||||
color.debug=blue
|
||||
|
||||
# Task state
|
||||
color.completed=rgb020 on white
|
||||
color.deleted=rgb200 on white
|
||||
color.completed=
|
||||
color.deleted=
|
||||
color.active=rgb050 on rgb010
|
||||
color.recurring=rgb151
|
||||
color.scheduled=on rgb011
|
||||
color.scheduled=black on rgb031
|
||||
color.until=
|
||||
color.blocked=white on rgb010
|
||||
color.blocking=white on rgb020
|
||||
@@ -76,7 +76,7 @@ color.history.delete=color0 on rgb050
|
||||
color.history.done=color0 on rgb030
|
||||
|
||||
# Report: summary
|
||||
color.summary.background=white on color0
|
||||
color.summary.background=white on gray3
|
||||
color.summary.bar=white on rgb030
|
||||
|
||||
# Command: calendar
|
||||
@@ -95,4 +95,4 @@ color.sync.rejected=rgb010
|
||||
|
||||
# Command: undo
|
||||
color.undo.after=rgb053
|
||||
color.undo.before=rgb031
|
||||
color.undo.before=rgb021
|
||||
|
||||
@@ -29,19 +29,19 @@ rule.precedence.color=deleted,completed,active,keyword.,tag.,uda.,project.,overd
|
||||
# General decoration
|
||||
color.label=
|
||||
color.label.sort=
|
||||
color.alternate=on gray1
|
||||
color.alternate=on gray2
|
||||
color.header=rgb100
|
||||
color.footnote=rgb100
|
||||
color.warning=bold red
|
||||
color.error=rgb100
|
||||
color.debug=rgb100
|
||||
color.warning=red
|
||||
color.error=white on red
|
||||
color.debug=blue
|
||||
|
||||
# Task state
|
||||
color.completed=rgb020 on white
|
||||
color.deleted=rgb200 on white
|
||||
color.completed=
|
||||
color.deleted=
|
||||
color.active=rgb500 on rgb100
|
||||
color.recurring=rgb511
|
||||
color.scheduled=on rgb201
|
||||
color.scheduled=white on rgb311
|
||||
color.until=
|
||||
color.blocked=white on rgb100
|
||||
color.blocking=white on rgb200
|
||||
@@ -56,7 +56,7 @@ color.pri.M=rgb400
|
||||
color.pri.none=
|
||||
|
||||
# Tags
|
||||
color.tag.next=rgb440
|
||||
color.tag.next=rgb511
|
||||
color.tag.none=
|
||||
color.tagged=color246
|
||||
|
||||
@@ -94,6 +94,6 @@ color.sync.changed=rgb411
|
||||
color.sync.rejected=rgb200
|
||||
|
||||
# Command: undo
|
||||
color.undo.after=rgb503
|
||||
color.undo.before=rgb301
|
||||
color.undo.after=rgb511
|
||||
color.undo.before=rgb200
|
||||
|
||||
|
||||
@@ -33,15 +33,15 @@ color.alternate=on gray2
|
||||
color.header=rgb013
|
||||
color.footnote=rgb013
|
||||
color.warning=
|
||||
color.error=rgb013
|
||||
color.debug=rgb013
|
||||
color.error=white on red
|
||||
color.debug=blue
|
||||
|
||||
# Task state
|
||||
color.completed=
|
||||
color.deleted=
|
||||
color.active=rgb445 on rgb213
|
||||
color.recurring=rgb115
|
||||
color.scheduled=
|
||||
color.scheduled=white on rgb113
|
||||
color.until=
|
||||
color.blocked=white on rgb101
|
||||
color.blocking=white on rgb202
|
||||
@@ -61,9 +61,9 @@ color.tag.none=
|
||||
color.tagged=rgb334
|
||||
|
||||
# Due
|
||||
color.due=rgb055
|
||||
color.due.today=rgb533
|
||||
color.overdue=color9
|
||||
color.due=rgb015
|
||||
color.due.today=rgb125
|
||||
color.overdue=color5
|
||||
|
||||
# Report: burndown
|
||||
color.burndown.pending=on rgb103
|
||||
@@ -76,14 +76,14 @@ color.history.done=color0 on rgb205
|
||||
color.history.delete=color0 on rgb305
|
||||
|
||||
# Report: summary
|
||||
color.summary.bar=white on rgb103
|
||||
color.summary.background=white on color0
|
||||
color.summary.bar=white on rgb104
|
||||
color.summary.background=white on rgb001
|
||||
|
||||
# Command: calendar
|
||||
color.calendar.due=color0 on rgb325
|
||||
color.calendar.due.today=color0 on rgb404
|
||||
color.calendar.holiday=color15 on rgb022
|
||||
color.calendar.overdue=color0 on color9
|
||||
color.calendar.holiday=color15 on rgb102
|
||||
color.calendar.overdue=color0 on color5
|
||||
color.calendar.today=color15 on rgb103
|
||||
color.calendar.weekend=gray12 on gray3
|
||||
color.calendar.weeknumber=rgb104
|
||||
|
||||
@@ -33,15 +33,15 @@ color.alternate=on gray2
|
||||
color.header=rgb031
|
||||
color.footnote=rgb031
|
||||
color.warning=
|
||||
color.error=rgb031
|
||||
color.debug=rgb031
|
||||
color.error=white on red
|
||||
color.debug=blue
|
||||
|
||||
# Task state
|
||||
color.completed=
|
||||
color.deleted=
|
||||
color.active=rgb451 on rgb310
|
||||
color.active=rgb451 on rgb320
|
||||
color.recurring=rgb343
|
||||
color.scheduled=
|
||||
color.scheduled=black on rgb441
|
||||
color.until=
|
||||
color.blocked=white on rgb110
|
||||
color.blocking=white on rgb220
|
||||
@@ -61,9 +61,9 @@ color.tag.none=
|
||||
color.tagged=rgb342
|
||||
|
||||
# Due
|
||||
color.due=rgb420
|
||||
color.due.today=rgb410
|
||||
color.overdue=rgb400
|
||||
color.due=rgb440
|
||||
color.due.today=rgb430
|
||||
color.overdue=rgb420
|
||||
|
||||
# Report: burndown
|
||||
color.burndown.pending=on rgb110
|
||||
@@ -71,19 +71,19 @@ color.burndown.started=on rgb430
|
||||
color.burndown.done=on gray4
|
||||
|
||||
# Report: history
|
||||
color.history.add=color0 on rgb010
|
||||
color.history.done=color0 on rgb030
|
||||
color.history.delete=color0 on rgb050
|
||||
color.history.add=color0 on rgb110
|
||||
color.history.done=color0 on rgb430
|
||||
color.history.delete=white on gray4
|
||||
|
||||
# Report: summary
|
||||
color.summary.bar=white on rgb030
|
||||
color.summary.background=white on color0
|
||||
color.summary.bar=white on rgb330
|
||||
color.summary.background=white on rgb110
|
||||
|
||||
# Command: calendar
|
||||
color.calendar.due=color0 on rgb430
|
||||
color.calendar.due.today=color0 on rgb410
|
||||
color.calendar.due=color0 on rgb440
|
||||
color.calendar.due.today=color0 on rgb430
|
||||
color.calendar.holiday=rgb151 on rgb020
|
||||
color.calendar.overdue=color0 on rgb400
|
||||
color.calendar.overdue=color0 on rgb420
|
||||
color.calendar.today=color15 on rgb110
|
||||
color.calendar.weekend=on color235
|
||||
color.calendar.weeknumber=rgb110
|
||||
@@ -94,6 +94,6 @@ color.sync.changed=rgb430
|
||||
color.sync.rejected=rgb110
|
||||
|
||||
# Command: undo
|
||||
color.undo.before=rgb031
|
||||
color.undo.after=rgb053
|
||||
color.undo.before=rgb021
|
||||
color.undo.after=rgb042
|
||||
|
||||
|
||||
@@ -33,12 +33,12 @@ color.alternate=
|
||||
color.header=bold white on bright black
|
||||
color.footnote=bold cyan on bright black
|
||||
color.warning=bold red
|
||||
color.error=red on white
|
||||
color.debug=white on black
|
||||
color.error=white on red
|
||||
color.debug=blue
|
||||
|
||||
# Task state
|
||||
color.completed=green on black
|
||||
color.deleted=red on black
|
||||
color.completed=
|
||||
color.deleted=
|
||||
color.active=bold yellow on bright black
|
||||
color.recurring=
|
||||
color.scheduled=on bright cyan
|
||||
@@ -63,17 +63,17 @@ color.tagged=
|
||||
# Due
|
||||
color.due=on bright green
|
||||
color.due.today=on bright yellow
|
||||
color.overdue=on bright magenta
|
||||
color.overdue=on bright red
|
||||
|
||||
# Report: burndown
|
||||
color.burndown.pending=on bright green
|
||||
color.burndown.pending=on bright red
|
||||
color.burndown.started=on bright yellow
|
||||
color.burndown.done=on green
|
||||
|
||||
# Report: history
|
||||
color.history.add=blue on bright yellow
|
||||
color.history.done=green on bright green
|
||||
color.history.delete=black on red
|
||||
color.history.add=black on bright red
|
||||
color.history.done=black on bright green
|
||||
color.history.delete=black on yellow
|
||||
|
||||
# Report: summary
|
||||
color.summary.bar=on bright green
|
||||
@@ -82,11 +82,11 @@ color.summary.background=on white
|
||||
# Command: calendar
|
||||
color.calendar.due=on bright green
|
||||
color.calendar.due.today=blue on bright yellow
|
||||
color.calendar.holiday=yellow
|
||||
color.calendar.overdue=on bright magenta
|
||||
color.calendar.holiday=on yellow
|
||||
color.calendar.overdue=on bright red
|
||||
color.calendar.today=blue
|
||||
color.calendar.weekend=on white
|
||||
color.calendar.weeknumber=white on bright black
|
||||
color.calendar.weeknumber=blue
|
||||
|
||||
# Command: sync
|
||||
color.sync.added=green
|
||||
|
||||
@@ -33,13 +33,13 @@ color.alternate=on gray22
|
||||
color.header=color15 on gray8
|
||||
color.footnote=on gray18
|
||||
color.warning=color9
|
||||
color.error=red on white
|
||||
color.debug=color7 on color0
|
||||
color.error=white on red
|
||||
color.debug=rgb025
|
||||
|
||||
# Task state
|
||||
color.completed=rgb353 on rgb000
|
||||
color.deleted=rgb533 on rgb000
|
||||
color.active=rgb420
|
||||
color.completed=
|
||||
color.deleted=
|
||||
color.active=rgb510
|
||||
color.recurring=
|
||||
color.scheduled=on rgb345
|
||||
color.until=
|
||||
@@ -53,7 +53,7 @@ color.project.none=
|
||||
color.pri.H=gray0
|
||||
color.pri.M=gray5
|
||||
color.pri.L=gray10
|
||||
color.pri.none=gray5
|
||||
color.pri.none=
|
||||
|
||||
# Tags
|
||||
color.tag.next=rgb420
|
||||
@@ -66,14 +66,14 @@ color.due.today=on rgb353
|
||||
color.overdue=on rgb544
|
||||
|
||||
# Report: burndown
|
||||
color.burndown.pending=on rgb141
|
||||
color.burndown.started=on rgb440
|
||||
color.burndown.pending=on rgb411
|
||||
color.burndown.started=on rgb550
|
||||
color.burndown.done=on rgb151
|
||||
|
||||
# Report: history
|
||||
color.history.add=rgb005 on rgb440
|
||||
color.history.done=rgb020 on rgb343
|
||||
color.history.delete=rgb300 on rgb533
|
||||
color.history.add=color0 on rgb411
|
||||
color.history.done=color0 on rgb151
|
||||
color.history.delete=color0 on rgb550
|
||||
|
||||
# Report: summary
|
||||
color.summary.bar=on rgb141
|
||||
@@ -82,7 +82,7 @@ color.summary.background=on gray20
|
||||
# Command: calendar
|
||||
color.calendar.due=on rgb343
|
||||
color.calendar.due.today=on rgb353
|
||||
color.calendar.holiday=rgb420
|
||||
color.calendar.holiday=color0 on rgb530
|
||||
color.calendar.overdue=on rgb533
|
||||
color.calendar.today=rgb005
|
||||
color.calendar.weekend=on gray21
|
||||
|
||||
@@ -83,14 +83,14 @@ color.due.today=color1
|
||||
color.overdue=color5
|
||||
|
||||
# Report: burndown
|
||||
color.burndown.done=color0 on color4
|
||||
color.burndown.done=color0 on color6
|
||||
color.burndown.pending=color0 on color1
|
||||
color.burndown.started=color0 on color9
|
||||
color.burndown.started=color0 on color3
|
||||
|
||||
# Report: history
|
||||
color.history.add=color0 on color1
|
||||
color.history.delete=color0 on color3
|
||||
color.history.done=color0 on color10
|
||||
color.history.done=color0 on color6
|
||||
|
||||
# Report: summary
|
||||
color.summary.background=on color0
|
||||
|
||||
@@ -46,7 +46,7 @@ rule.precedence.color=deleted,completed,active,keyword.,tag.,uda.,project.,overd
|
||||
# General decoration
|
||||
color.label=
|
||||
color.label.sort=
|
||||
color.alternate=on white #color7 (allows bold for alternate rows)
|
||||
color.alternate=on color7
|
||||
color.header=color2
|
||||
color.footnote=color2
|
||||
color.warning=
|
||||
@@ -56,20 +56,20 @@ color.debug=color3
|
||||
# Task state
|
||||
color.completed=
|
||||
color.deleted=
|
||||
color.active=bold red #color9
|
||||
color.active=color9
|
||||
color.recurring=color4
|
||||
color.scheduled=
|
||||
color.until=
|
||||
color.blocked=on color14
|
||||
color.blocking=on color14
|
||||
color.blocked=color0 on color14
|
||||
color.blocking=color15 on color0
|
||||
|
||||
# Project
|
||||
color.project.none=
|
||||
|
||||
# Priority
|
||||
color.pri.H=bold black #color0
|
||||
color.pri.M=bold yellow #color11
|
||||
color.pri.L=bold cyan #color14
|
||||
color.pri.H=bold color0
|
||||
color.pri.M=bold color11
|
||||
color.pri.L=bold color14
|
||||
color.pri.none=
|
||||
|
||||
# Tags
|
||||
@@ -83,14 +83,14 @@ color.due.today=color1
|
||||
color.overdue=color5
|
||||
|
||||
# Report: burndown
|
||||
color.burndown.done=color0 on color4
|
||||
color.burndown.done=color0 on color6
|
||||
color.burndown.pending=color0 on color1
|
||||
color.burndown.started=color0 on color9
|
||||
color.burndown.started=color0 on color3
|
||||
|
||||
# Report: history
|
||||
color.history.add=color0 on color1
|
||||
color.history.delete=color0 on color3
|
||||
color.history.done=color14 on color0
|
||||
color.history.done=color0 on color6
|
||||
|
||||
# Report: summary
|
||||
color.summary.background=on color7
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -68,7 +68,13 @@ _task_offer_projects() {
|
||||
COMPREPLY=( $(compgen -W "$($taskcommand _projects)" -- ${cur/*:/}) )
|
||||
}
|
||||
|
||||
_task()
|
||||
_task_offer_contexts() {
|
||||
COMPREPLY=( $(compgen -W "$($taskcommand _context) define delete list none show" -- $cur) )
|
||||
}
|
||||
|
||||
_task_context_alias=$($taskcommand show | grep alias.*context | cut -d' ' -f1 | cut -d. -f2)
|
||||
|
||||
_task()
|
||||
{
|
||||
local cur prev opts base
|
||||
|
||||
@@ -91,6 +97,10 @@ _task()
|
||||
opts="$commands_aliases $($taskcommand _columns)"
|
||||
|
||||
case "${prev}" in
|
||||
$_task_context_alias|cont|conte|contex|context)
|
||||
_task_offer_contexts
|
||||
return 0
|
||||
;;
|
||||
:)
|
||||
case "${prev2}" in
|
||||
pri|prior|priori|priorit|priority)
|
||||
|
||||
67
src/CLI.cpp
67
src/CLI.cpp
@@ -374,6 +374,64 @@ void CLI::add (const std::string& arg)
|
||||
analyze ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void CLI::addContextFilter ()
|
||||
{
|
||||
// Detect if any context is set, and bail out if not
|
||||
std::string contextName = context.config.get ("context");
|
||||
|
||||
if (contextName == "")
|
||||
{
|
||||
context.debug("No context applied.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Detect if UUID or ID is set, and bail out
|
||||
if (_args.size ())
|
||||
{
|
||||
std::vector <A>::const_iterator a;
|
||||
for (a = _args.begin (); a != _args.end (); ++a)
|
||||
{
|
||||
if (a->hasTag ("FILTER") &&
|
||||
a->hasTag ("ATTRIBUTE") &&
|
||||
! a->hasTag ("TERMINATED") &&
|
||||
! a->hasTag ("WORD") &&
|
||||
(a->attribute ("raw") == "id" || a->attribute ("raw") == "uuid"))
|
||||
{
|
||||
context.debug(format("UUID/ID lexeme found '{1}', not applying context.", a->attribute ("raw")));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply context
|
||||
context.debug("Applying context: " + contextName);
|
||||
std::string contextFilter = context.config.get ("context." + contextName);
|
||||
|
||||
if (contextFilter == "")
|
||||
context.debug("Context '" + contextName + "' not defined!");
|
||||
else
|
||||
{
|
||||
addRawFilter("( " + contextFilter + " )");
|
||||
if (context.verbose ("context"))
|
||||
context.footnote (format("Context '{1}' set. Use 'task context none' to remove.", contextName));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Process raw string into parsed filter.
|
||||
//
|
||||
void CLI::addRawFilter (const std::string& arg)
|
||||
{
|
||||
std::string lexeme;
|
||||
Lexer::Type type;
|
||||
Lexer lex (arg);
|
||||
lex.ambiguity (false);
|
||||
|
||||
while (lex.token (lexeme, type))
|
||||
add (lexeme);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Intended to be called after ::initialize() and ::add(), to perform the final
|
||||
// analysis. Analysis is also performed directly after the above, because there
|
||||
@@ -474,8 +532,14 @@ void CLI::applyOverrides ()
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Extract all the FILTER-tagged items.
|
||||
const std::string CLI::getFilter ()
|
||||
const std::string CLI::getFilter (bool applyContext /* = true */)
|
||||
{
|
||||
// Handle context setting
|
||||
// Commands that don't want to respect current context should leverage
|
||||
// the applyContext argument
|
||||
if (applyContext)
|
||||
addContextFilter ();
|
||||
|
||||
std::string filter = "";
|
||||
if (_args.size ())
|
||||
{
|
||||
@@ -500,6 +564,7 @@ const std::string CLI::getFilter ()
|
||||
filter = "( " + filter + " )";
|
||||
}
|
||||
|
||||
context.debug("Derived filter: '" + filter + "'");
|
||||
return filter;
|
||||
}
|
||||
|
||||
|
||||
@@ -77,9 +77,11 @@ public:
|
||||
void entity (const std::string&, const std::string&);
|
||||
void initialize (int, const char**);
|
||||
void add (const std::string&);
|
||||
void addContextFilter ();
|
||||
void addRawFilter (const std::string& arg);
|
||||
void analyze (bool parse = true, bool strict = false);
|
||||
void applyOverrides ();
|
||||
const std::string getFilter ();
|
||||
const std::string getFilter (bool applyContext = true);
|
||||
const std::vector <std::string> getWords ();
|
||||
bool canonicalize (std::string&, const std::string&, const std::string&) const;
|
||||
std::string getBinary () const;
|
||||
|
||||
@@ -165,29 +165,29 @@ std::string Config::_defaults =
|
||||
"\n"
|
||||
"# Color controls.\n"
|
||||
"color=on # Enable color\n"
|
||||
#ifdef LINUX
|
||||
#if defined(LINUX) || defined(DARWIN)
|
||||
"\n"
|
||||
"rule.precedence.color=deleted,completed,active,keyword.,tag.,uda.,project.,overdue,scheduled,due.today,due,blocked,blocking,recurring,tagged,pri.\n"
|
||||
"\n"
|
||||
"# General decoration\n"
|
||||
"color.label=\n"
|
||||
"color.label.sort=\n"
|
||||
"color.alternate=on gray1\n"
|
||||
"color.alternate=on gray2\n"
|
||||
"color.header=color3\n"
|
||||
"color.footnote=color3\n"
|
||||
"color.warning=bold red\n"
|
||||
"color.error=color3\n"
|
||||
"color.debug=color3\n"
|
||||
"color.error=white on red\n"
|
||||
"color.debug=color4\n"
|
||||
"\n"
|
||||
"# Task state\n"
|
||||
"color.completed=rgb010 on white\n"
|
||||
"color.deleted=rgb100 on white\n"
|
||||
"color.completed=\n"
|
||||
"color.deleted=\n"
|
||||
"color.active=rgb555 on rgb410\n"
|
||||
"color.recurring=rgb013\n"
|
||||
"color.scheduled=on rgb001\n"
|
||||
"color.until=\n"
|
||||
"color.blocked=white on color8\n"
|
||||
"color.blocking=white on color15\n"
|
||||
"color.blocking=black on color15\n"
|
||||
"\n"
|
||||
"# Project\n"
|
||||
"color.project.none=\n"
|
||||
@@ -251,15 +251,15 @@ std::string Config::_defaults =
|
||||
"color.header=yellow\n"
|
||||
"color.footnote=yellow\n"
|
||||
"color.warning=bold red\n"
|
||||
"color.error=yellow\n"
|
||||
"color.debug=yellow\n"
|
||||
"color.error=white on red\n"
|
||||
"color.debug=blue\n"
|
||||
"\n"
|
||||
"# Task state\n"
|
||||
"color.completed=green on white\n"
|
||||
"color.deleted=red on white\n"
|
||||
"color.completed=\n"
|
||||
"color.deleted=\n"
|
||||
"color.active=black on bright green\n"
|
||||
"color.recurring=magenta\n"
|
||||
"color.scheduled=on green\n"
|
||||
"color.scheduled=white on green\n"
|
||||
"color.until=\n"
|
||||
"color.blocked=black on white\n"
|
||||
"color.blocking=black on bright white\n"
|
||||
@@ -368,7 +368,7 @@ std::string Config::_defaults =
|
||||
"report.list.labels=ID,Active,Age,D,P,Project,Tags,R,Sch,Due,Until,Description,Urg\n"
|
||||
"report.list.columns=id,start.age,entry.age,depends.indicator,priority,project,tags,recur.indicator,scheduled.countdown,due,until.remaining,description.count,urgency\n"
|
||||
"report.list.filter=status:pending\n"
|
||||
"report.list.sort=start-,due+,project+/,urgency-\n"
|
||||
"report.list.sort=start-,due+,project+,urgency-\n"
|
||||
"\n"
|
||||
"report.ls.description=Few details of tasks\n"
|
||||
"report.ls.labels=ID,A,D,Project,Tags,R,Wait,S,Due,Until,Description\n"
|
||||
@@ -433,7 +433,7 @@ std::string Config::_defaults =
|
||||
"report.next.labels=ID,Active,Age,Deps,P,Project,Tag,Recur,S,Due,Until,Description,Urg\n"
|
||||
"report.next.columns=id,start.age,entry.age,depends,priority,project,tags,recur,scheduled.countdown,due.remaining,until.remaining,description,urgency\n"
|
||||
"report.next.filter=status:pending limit:page\n"
|
||||
"report.next.sort=start-,urgency-\n"
|
||||
"report.next.sort=urgency-\n"
|
||||
"\n"
|
||||
"report.ready.description=Most urgent actionable tasks\n"
|
||||
"report.ready.labels=ID,Active,Age,D,P,Project,Tags,R,S,Due,Until,Description,Urg\n"
|
||||
|
||||
@@ -275,7 +275,7 @@ int Context::initialize (int argc, const char** argv)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// [8] Run on.launch hooks.
|
||||
// [8] Initialize hooks.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -313,7 +313,7 @@ bool DOM::get (const std::string& name, const Task& task, Variant& value)
|
||||
Column* column = context.columns[canonical];
|
||||
if (column)
|
||||
{
|
||||
if (column->is_uda () && ! task.has (canonical))
|
||||
if (column->is_uda () && ! ref.has (canonical))
|
||||
{
|
||||
value = Variant ("''");
|
||||
return true;
|
||||
|
||||
@@ -61,31 +61,48 @@ static struct
|
||||
{"fortnight", 14 * DAY, true},
|
||||
{"hours", 1 * HOUR, false},
|
||||
{"hour", 1 * HOUR, true},
|
||||
{"hrs", 1 * HOUR, true},
|
||||
{"hr", 1 * HOUR, true},
|
||||
{"h", 1 * HOUR, false},
|
||||
{"minutes", 1 * MINUTE, false},
|
||||
{"minute", 1 * MINUTE, false},
|
||||
{"mins", 1 * MINUTE, false},
|
||||
{"min", 1 * MINUTE, false},
|
||||
{"monthly", 30 * DAY, true},
|
||||
{"months", 30 * DAY, false},
|
||||
{"month", 30 * DAY, true},
|
||||
{"mnths", 30 * DAY, false},
|
||||
{"mths", 30 * DAY, false},
|
||||
{"mth", 30 * DAY, false},
|
||||
{"mos", 30 * DAY, false},
|
||||
{"mo", 30 * DAY, false},
|
||||
{"m", 30 * DAY, false},
|
||||
{"quarterly", 91 * DAY, true},
|
||||
{"quarters", 91 * DAY, false},
|
||||
{"quarter", 91 * DAY, true},
|
||||
{"qrtrs", 91 * DAY, false},
|
||||
{"qtrs", 91 * DAY, false},
|
||||
{"qtr", 91 * DAY, false},
|
||||
{"q", 91 * DAY, false},
|
||||
{"semiannual", 183 * DAY, true},
|
||||
{"sennight", 14 * DAY, false},
|
||||
{"seconds", 1 * SECOND, false},
|
||||
{"second", 1 * SECOND, true},
|
||||
{"secs", 1 * SECOND, true},
|
||||
{"sec", 1 * SECOND, true},
|
||||
{"s", 1 * SECOND, false},
|
||||
{"weekdays", 1 * DAY, true},
|
||||
{"weekly", 7 * DAY, true},
|
||||
{"weeks", 7 * DAY, false},
|
||||
{"week", 7 * DAY, true},
|
||||
{"wks", 7 * DAY, true},
|
||||
{"wk", 7 * DAY, true},
|
||||
{"w", 7 * DAY, false},
|
||||
{"yearly", 365 * DAY, true},
|
||||
{"years", 365 * DAY, false},
|
||||
{"year", 365 * DAY, true},
|
||||
{"yrs", 365 * DAY, true},
|
||||
{"yr", 365 * DAY, true},
|
||||
{"y", 365 * DAY, false},
|
||||
};
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ Filter::~Filter ()
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Take an input set of tasks and filter into a subset.
|
||||
void Filter::subset (const std::vector <Task>& input, std::vector <Task>& output)
|
||||
void Filter::subset (const std::vector <Task>& input, std::vector <Task>& output, bool applyContext /* = true */)
|
||||
{
|
||||
context.timer_filter.start ();
|
||||
_startCount = (int) input.size ();
|
||||
@@ -75,7 +75,7 @@ void Filter::subset (const std::vector <Task>& input, std::vector <Task>& output
|
||||
if (context.config.getInteger ("debug.parser") >= 1)
|
||||
context.debug (context.cli.dump ("Filter::subset"));
|
||||
|
||||
std::string filterExpr = context.cli.getFilter ();
|
||||
std::string filterExpr = context.cli.getFilter (applyContext);
|
||||
if (filterExpr.length ())
|
||||
{
|
||||
Eval eval;
|
||||
@@ -111,7 +111,7 @@ void Filter::subset (const std::vector <Task>& input, std::vector <Task>& output
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Take the set of all tasks and filter into a subset.
|
||||
void Filter::subset (std::vector <Task>& output)
|
||||
void Filter::subset (std::vector <Task>& output, bool applyContext /* = true */)
|
||||
{
|
||||
context.timer_filter.start ();
|
||||
|
||||
@@ -119,7 +119,7 @@ void Filter::subset (std::vector <Task>& output)
|
||||
context.debug (context.cli.dump ("Filter::subset"));
|
||||
|
||||
bool shortcut = false;
|
||||
std::string filterExpr = context.cli.getFilter ();
|
||||
std::string filterExpr = context.cli.getFilter (applyContext);
|
||||
if (filterExpr.length ())
|
||||
{
|
||||
context.timer_filter.stop ();
|
||||
|
||||
@@ -40,8 +40,8 @@ public:
|
||||
Filter ();
|
||||
~Filter ();
|
||||
|
||||
void subset (const std::vector <Task>&, std::vector <Task>&);
|
||||
void subset (std::vector <Task>&);
|
||||
void subset (const std::vector <Task>&, std::vector <Task>&, bool applyContext = true);
|
||||
void subset (std::vector <Task>&, bool applyContext = true);
|
||||
bool pendingOnly ();
|
||||
void safety ();
|
||||
|
||||
|
||||
@@ -141,7 +141,7 @@ void Hooks::onLaunch ()
|
||||
{
|
||||
std::vector <std::string>::iterator message;
|
||||
for (message = outputFeedback.begin (); message != outputFeedback.end (); ++message)
|
||||
context.debug (*message);
|
||||
context.footnote (*message);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -208,7 +208,7 @@ void Hooks::onExit ()
|
||||
{
|
||||
std::vector <std::string>::iterator message;
|
||||
for (message = outputFeedback.begin (); message != outputFeedback.end (); ++message)
|
||||
context.debug (*message);
|
||||
context.footnote (*message);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -274,7 +274,7 @@ void Hooks::onAdd (Task& task)
|
||||
|
||||
std::vector <std::string>::iterator message;
|
||||
for (message = outputFeedback.begin (); message != outputFeedback.end (); ++message)
|
||||
context.debug (*message);
|
||||
context.footnote (*message);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -345,7 +345,7 @@ void Hooks::onModify (const Task& before, Task& after)
|
||||
|
||||
std::vector <std::string>::iterator message;
|
||||
for (message = outputFeedback.begin (); message != outputFeedback.end (); ++message)
|
||||
context.debug (*message);
|
||||
context.footnote (*message);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -358,6 +358,8 @@ void Hooks::onModify (const Task& before, Task& after)
|
||||
throw 0; // This is how hooks silently terminate processing.
|
||||
}
|
||||
}
|
||||
|
||||
after = Task (input[1]);
|
||||
}
|
||||
|
||||
context.timer_hooks.stop ();
|
||||
|
||||
@@ -387,6 +387,12 @@ bool Lexer::token (std::string& result, Type& type)
|
||||
result += utf8_character (_n0);
|
||||
shift ();
|
||||
}
|
||||
else
|
||||
{
|
||||
result += utf8_character (hex_to_int (_n0, _n1, _n2, _n3));
|
||||
shift ();
|
||||
type = quote ? typeString : typeIdentifier;
|
||||
}
|
||||
break;
|
||||
|
||||
case typeExponent:
|
||||
|
||||
@@ -403,33 +403,6 @@ bool Nibbler::getInt (int& result)
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Nibbler::getHex (int& result)
|
||||
{
|
||||
std::string::size_type i = _cursor;
|
||||
|
||||
if (i < _length)
|
||||
{
|
||||
if (_input[i] == '-')
|
||||
++i;
|
||||
else if (_input[i] == '+')
|
||||
++i;
|
||||
}
|
||||
|
||||
// TODO Potential for use of find_first_not_of
|
||||
while (i < _length && isxdigit (_input[i]))
|
||||
++i;
|
||||
|
||||
if (i > _cursor)
|
||||
{
|
||||
result = strtoimax (_input.substr (_cursor, i - _cursor).c_str (), NULL, 16);
|
||||
_cursor = i;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Nibbler::getUnsignedInt (int& result)
|
||||
{
|
||||
|
||||
@@ -68,7 +68,6 @@ public:
|
||||
bool getDigit3 (int&);
|
||||
bool getDigit2 (int&);
|
||||
bool getInt (int&);
|
||||
bool getHex (int&);
|
||||
bool getUnsignedInt (int&);
|
||||
bool getNumber (std::string&);
|
||||
bool getNumber (double&);
|
||||
|
||||
22
src/TDB2.cpp
22
src/TDB2.cpp
@@ -572,7 +572,7 @@ void TDB2::add (Task& task, bool add_to_backlog /* = true */)
|
||||
if (add_to_backlog)
|
||||
context.hooks.onAdd (task);
|
||||
|
||||
update (uuid, task, add_to_backlog);
|
||||
update (uuid, task, add_to_backlog, true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -580,7 +580,6 @@ void TDB2::modify (Task& task, bool add_to_backlog /* = true */)
|
||||
{
|
||||
// Ensure the task is consistent, and provide defaults if necessary.
|
||||
task.validate (false);
|
||||
task.upgradeLegacyValues ();
|
||||
std::string uuid = task.get ("uuid");
|
||||
|
||||
// Get the unmodified task as reference, so the hook can compare.
|
||||
@@ -598,14 +597,15 @@ void TDB2::modify (Task& task, bool add_to_backlog /* = true */)
|
||||
void TDB2::update (
|
||||
const std::string& uuid,
|
||||
Task& task,
|
||||
const bool add_to_backlog)
|
||||
const bool add_to_backlog,
|
||||
const bool addition)
|
||||
{
|
||||
// Validate to add metadata.
|
||||
task.validate (false);
|
||||
|
||||
// If the task already exists, it is a modification, else addition.
|
||||
Task original;
|
||||
if (get (task.get ("uuid"), original))
|
||||
if (not addition && get (task.get ("uuid"), original))
|
||||
{
|
||||
// Update the task, wherever it is.
|
||||
if (!pending.modify_task (task))
|
||||
@@ -1179,18 +1179,21 @@ int TDB2::gc ()
|
||||
// Allowed as an override, but not recommended.
|
||||
if (context.config.getBoolean ("gc"))
|
||||
{
|
||||
std::vector <Task> pending_tasks = pending.get_tasks ();
|
||||
std::vector <Task> pending_tasks = pending.get_tasks ();
|
||||
|
||||
// TODO Thread.
|
||||
std::vector <Task> completed_tasks = completed.get_tasks ();
|
||||
|
||||
// TODO Assume pending < completed, therefore there is room here to process
|
||||
// data before joining with the completed.data thread.
|
||||
|
||||
bool pending_changes = false;
|
||||
bool completed_changes = false;
|
||||
|
||||
std::vector <Task> pending_tasks_after;
|
||||
std::vector <Task> completed_tasks_after;
|
||||
|
||||
// Reduce unnecessary allocation/copies.
|
||||
pending_tasks_after.reserve (pending_tasks.size ());
|
||||
completed_tasks_after.reserve (completed_tasks.size ());
|
||||
|
||||
// Scan all pending tasks, looking for any that need to be relocated to
|
||||
// completed, or need to be 'woken'.
|
||||
@@ -1227,6 +1230,11 @@ int TDB2::gc ()
|
||||
}
|
||||
}
|
||||
|
||||
// TODO Join completed.data thread.
|
||||
|
||||
// Reduce unnecessary allocation/copies.
|
||||
completed_tasks_after.reserve (completed_tasks.size ());
|
||||
|
||||
// Scan all completed tasks, looking for any that need to be relocated to
|
||||
// pending.
|
||||
for (task = completed_tasks.begin ();
|
||||
|
||||
@@ -128,7 +128,7 @@ public:
|
||||
|
||||
private:
|
||||
void gather_changes ();
|
||||
void update (const std::string&, Task&, const bool);
|
||||
void update (const std::string&, Task&, const bool, const bool addition = false);
|
||||
bool verifyUniqueUUID (const std::string&);
|
||||
void show_diff (const std::string&, const std::string&, const std::string&);
|
||||
void revert_undo (std::vector <std::string>&, std::string&, std::string&, std::string&, std::string&);
|
||||
|
||||
81
src/Task.cpp
81
src/Task.cpp
@@ -565,7 +565,6 @@ void Task::parse (const std::string& input)
|
||||
nl.getQuoted ('"', value))
|
||||
{
|
||||
legacyAttributeMap (name);
|
||||
legacyValueMap (name, value);
|
||||
|
||||
if (name.substr (0, 11) == "annotation_")
|
||||
++annotation_count;
|
||||
@@ -586,8 +585,6 @@ void Task::parse (const std::string& input)
|
||||
parseJSON (copy);
|
||||
else
|
||||
throw std::string (STRING_RECORD_NOT_FF4);
|
||||
|
||||
upgradeLegacyValues ();
|
||||
}
|
||||
|
||||
catch (const std::string&)
|
||||
@@ -719,8 +716,6 @@ void Task::parseJSON (const std::string& line)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
upgradeLegacyValues ();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1105,6 +1100,7 @@ int Task::getTagCount () const
|
||||
bool Task::hasTag (const std::string& tag) const
|
||||
{
|
||||
// Synthetic tags - dynamically generated, but do not occupy storage space.
|
||||
// Note: This list must match that in CmdInfo::execute.
|
||||
if (tag == "BLOCKED") return is_blocked;
|
||||
if (tag == "UNBLOCKED") return !is_blocked;
|
||||
if (tag == "BLOCKING") return is_blocking;
|
||||
@@ -2218,78 +2214,3 @@ void Task::modify (modType type, bool text_required /* = false */)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Task::upgradeLegacyValues ()
|
||||
{
|
||||
// 2.4.0 Update recurrence values.
|
||||
if (has ("recur"))
|
||||
{
|
||||
std::string value = get ("recur");
|
||||
if (value != "")
|
||||
{
|
||||
std::string new_value = value;
|
||||
upgradeLegacyValue (new_value);
|
||||
|
||||
if (new_value != value)
|
||||
{
|
||||
set ("recur", new_value);
|
||||
context.debug (format ("Legacy upgrade: recur {1} --> {2}", value, new_value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2.4.0 Update UDA duration values.
|
||||
Config::const_iterator name;
|
||||
for (name = context.config.begin (); name != context.config.end (); ++name)
|
||||
{
|
||||
if (name->first.substr (0, 4) == "uda." &&
|
||||
name->first.find (".type") != std::string::npos)
|
||||
{
|
||||
if (name->second == "duration")
|
||||
{
|
||||
std::string::size_type period = name->first.find ('.', 4);
|
||||
if (period != std::string::npos)
|
||||
{
|
||||
std::string uda = name->first.substr (4, period - 4);
|
||||
std::string value = get (uda);
|
||||
std::string new_value = value;
|
||||
upgradeLegacyValue (new_value);
|
||||
|
||||
if (new_value != value)
|
||||
{
|
||||
set ("recur", new_value);
|
||||
context.debug (format ("Legacy upgrade: UDA {1}, {2} --> {3}", uda, value, new_value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Task::upgradeLegacyValue (std::string& value)
|
||||
{
|
||||
std::string::size_type len = value.length ();
|
||||
std::string::size_type p;
|
||||
|
||||
if (value == "-") value = "0s";
|
||||
else if ((p = value.find ("hr")) != std::string::npos && p == len - 2) value = value.substr (0, p) + "h";
|
||||
else if ((p = value.find ("hrs")) != std::string::npos && p == len - 3) value = value.substr (0, p) + "h";
|
||||
else if ((p = value.find ("mins")) != std::string::npos && p == len - 4) value = value.substr (0, p) + "min";
|
||||
else if ((p = value.find ("mnths")) != std::string::npos && p == len - 5) value = value.substr (0, p) + "mo";
|
||||
else if ((p = value.find ("mos")) != std::string::npos && p == len - 3) value = value.substr (0, p) + "mo";
|
||||
else if ((p = value.find ("mth")) != std::string::npos && p == len - 3) value = value.substr (0, p) + "mo";
|
||||
else if ((p = value.find ("mths")) != std::string::npos && p == len - 4) value = value.substr (0, p) + "mo";
|
||||
else if ((p = value.find ("qrtrs")) != std::string::npos && p == len - 5) value = value.substr (0, p) + "q";
|
||||
else if ((p = value.find ("qtr")) != std::string::npos && p == len - 3) value = value.substr (0, p) + "q";
|
||||
else if ((p = value.find ("qtrs")) != std::string::npos && p == len - 4) value = value.substr (0, p) + "q";
|
||||
else if ((p = value.find ("sec")) != std::string::npos && p == len - 3) value = value.substr (0, p) + "s";
|
||||
else if ((p = value.find ("secs")) != std::string::npos && p == len - 4) value = value.substr (0, p) + "s";
|
||||
else if ((p = value.find ("wk")) != std::string::npos && p == len - 2) value = value.substr (0, p) + "w";
|
||||
else if ((p = value.find ("wks")) != std::string::npos && p == len - 3) value = value.substr (0, p) + "w";
|
||||
else if ((p = value.find ("yr")) != std::string::npos && p == len - 2) value = value.substr (0, p) + "y";
|
||||
else if ((p = value.find ("yrs")) != std::string::npos && p == len - 3) value = value.substr (0, p) + "y";
|
||||
|
||||
// It is not an error to have a non-legacy value.
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -154,7 +154,6 @@ public:
|
||||
|
||||
enum modType {modReplace, modPrepend, modAppend, modAnnotate};
|
||||
void modify (modType, bool text_required = false);
|
||||
void upgradeLegacyValues ();
|
||||
|
||||
private:
|
||||
int determineVersion (const std::string&);
|
||||
@@ -163,7 +162,6 @@ private:
|
||||
void validate_before (const std::string&, const std::string&);
|
||||
const std::string encode (const std::string&) const;
|
||||
const std::string decode (const std::string&) const;
|
||||
void upgradeLegacyValue (std::string&);
|
||||
|
||||
public:
|
||||
float urgency_priority () const;
|
||||
|
||||
@@ -207,8 +207,6 @@ void ColumnDate::render (
|
||||
color.colorize (
|
||||
rightJustify (
|
||||
Duration (date - now).format (), width)));
|
||||
else
|
||||
lines.push_back (rightJustify ("", width));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,11 +62,16 @@ bool ColumnIMask::validate (std::string& value)
|
||||
// Set the minimum and maximum widths for the value.
|
||||
void ColumnIMask::measure (Task& task, unsigned int& minimum, unsigned int& maximum)
|
||||
{
|
||||
minimum = maximum = task.get ("imask").length ();
|
||||
minimum = maximum = 0;
|
||||
|
||||
if (_style != "default" &&
|
||||
_style != "number")
|
||||
throw format (STRING_COLUMN_BAD_FORMAT, _name, _style);
|
||||
if (task.has (_name))
|
||||
{
|
||||
minimum = maximum = task.get ("imask").length ();
|
||||
|
||||
if (_style != "default" &&
|
||||
_style != "number")
|
||||
throw format (STRING_COLUMN_BAD_FORMAT, _name, _style);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -76,7 +81,8 @@ void ColumnIMask::render (
|
||||
int width,
|
||||
Color& color)
|
||||
{
|
||||
lines.push_back (color.colorize (rightJustify (task.get ("imask"), width)));
|
||||
if (task.has (_name))
|
||||
lines.push_back (color.colorize (rightJustify (task.get ("imask"), width)));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -62,10 +62,14 @@ bool ColumnMask::validate (std::string& value)
|
||||
// Set the minimum and maximum widths for the value.
|
||||
void ColumnMask::measure (Task& task, unsigned int& minimum, unsigned int& maximum)
|
||||
{
|
||||
minimum = maximum = task.get ("mask").length ();
|
||||
minimum = maximum = 0;
|
||||
if (task.has (_name))
|
||||
{
|
||||
minimum = maximum = task.get ("mask").length ();
|
||||
|
||||
if (_style != "default")
|
||||
throw format (STRING_COLUMN_BAD_FORMAT, _name, _style);
|
||||
if (_style != "default")
|
||||
throw format (STRING_COLUMN_BAD_FORMAT, _name, _style);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -75,7 +79,8 @@ void ColumnMask::render (
|
||||
int width,
|
||||
Color& color)
|
||||
{
|
||||
lines.push_back (color.colorize (task.get ("mask")));
|
||||
if (task.has (_name))
|
||||
lines.push_back (color.colorize (task.get ("mask")));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -62,12 +62,17 @@ bool ColumnParent::validate (std::string& value)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Set the minimum and maximum widths for the value.
|
||||
void ColumnParent::measure (Task&, unsigned int& minimum, unsigned int& maximum)
|
||||
void ColumnParent::measure (Task& task, unsigned int& minimum, unsigned int& maximum)
|
||||
{
|
||||
if (_style == "default" || _style == "long") minimum = maximum = 36;
|
||||
else if (_style == "short") minimum = maximum = 8;
|
||||
else
|
||||
throw format (STRING_COLUMN_BAD_FORMAT, _name, _style);
|
||||
minimum = maximum = 0;
|
||||
|
||||
if (task.has (_name))
|
||||
{
|
||||
if (_style == "default" || _style == "long") minimum = maximum = 36;
|
||||
else if (_style == "short") minimum = maximum = 8;
|
||||
else
|
||||
throw format (STRING_COLUMN_BAD_FORMAT, _name, _style);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -77,20 +82,23 @@ void ColumnParent::render (
|
||||
int width,
|
||||
Color& color)
|
||||
{
|
||||
// f30cb9c3-3fc0-483f-bfb2-3bf134f00694 default
|
||||
// 34f00694 short
|
||||
if (_style == "default" ||
|
||||
_style == "long")
|
||||
if (task.has (_name))
|
||||
{
|
||||
lines.push_back (color.colorize (leftJustify (task.get (_name), width)));
|
||||
}
|
||||
// f30cb9c3-3fc0-483f-bfb2-3bf134f00694 default
|
||||
// 34f00694 short
|
||||
if (_style == "default" ||
|
||||
_style == "long")
|
||||
{
|
||||
lines.push_back (color.colorize (leftJustify (task.get (_name), width)));
|
||||
}
|
||||
|
||||
else if (_style == "short")
|
||||
{
|
||||
if (task.has (_name))
|
||||
lines.push_back (color.colorize (leftJustify (task.get (_name).substr (28), width)));
|
||||
else
|
||||
lines.push_back (color.colorize (leftJustify ("", width)));
|
||||
else if (_style == "short")
|
||||
{
|
||||
if (task.has (_name))
|
||||
lines.push_back (color.colorize (leftJustify (task.get (_name).substr (28), width)));
|
||||
else
|
||||
lines.push_back (color.colorize (leftJustify ("", width)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,17 +53,14 @@ ColumnPriority::~ColumnPriority ()
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Allow lower case, but implicitly convert.
|
||||
bool ColumnPriority::validate (std::string& value)
|
||||
{
|
||||
value = upperCase (value);
|
||||
if (value == "h") { value = "H"; return true; }
|
||||
else if (value == "m") { value = "M"; return true; }
|
||||
else if (value == "l") { value = "L"; return true; }
|
||||
|
||||
if (value == "H" ||
|
||||
value == "M" ||
|
||||
value == "L" ||
|
||||
value == "")
|
||||
return true;
|
||||
|
||||
return false;
|
||||
return value == "H" || value == "M" || value == "L" || value == "";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -81,22 +78,26 @@ void ColumnPriority::setStyle (const std::string& value)
|
||||
// Set the minimum and maximum widths for the value.
|
||||
void ColumnPriority::measure (Task& task, unsigned int& minimum, unsigned int& maximum)
|
||||
{
|
||||
std::string priority = task.get (_name);
|
||||
|
||||
if (priority == "")
|
||||
minimum = maximum = 0;
|
||||
else
|
||||
minimum = maximum = 1;
|
||||
|
||||
if (_style == "long")
|
||||
minimum = maximum = 0;
|
||||
if (task.has (_name))
|
||||
{
|
||||
if (priority == "H") minimum = maximum = 4;
|
||||
else if (priority == "M") minimum = maximum = 6;
|
||||
else if (priority == "L") minimum = maximum = 3;
|
||||
std::string priority = task.get (_name);
|
||||
|
||||
if (priority == "")
|
||||
minimum = maximum = 0;
|
||||
else
|
||||
minimum = maximum = 1;
|
||||
|
||||
if (_style == "long")
|
||||
{
|
||||
if (priority == "H") minimum = maximum = 4;
|
||||
else if (priority == "M") minimum = maximum = 6;
|
||||
else if (priority == "L") minimum = maximum = 3;
|
||||
}
|
||||
else if (_style != "default" &&
|
||||
_style != "short")
|
||||
throw format (STRING_COLUMN_BAD_FORMAT, "priority", _style);
|
||||
}
|
||||
else if (_style != "default" &&
|
||||
_style != "short")
|
||||
throw format (STRING_COLUMN_BAD_FORMAT, "priority", _style);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -106,21 +107,28 @@ void ColumnPriority::render (
|
||||
int width,
|
||||
Color& color)
|
||||
{
|
||||
std::string priority = task.get (_name);
|
||||
if (_style == "long")
|
||||
if (task.has (_name))
|
||||
{
|
||||
if (priority == "H") priority = "High";
|
||||
else if (priority == "M") priority = "Medium";
|
||||
else if (priority == "L") priority = "Low";
|
||||
}
|
||||
std::string priority = task.get (_name);
|
||||
if (_style == "long")
|
||||
{
|
||||
if (priority == "H") priority = "High";
|
||||
else if (priority == "M") priority = "Medium";
|
||||
else if (priority == "L") priority = "Low";
|
||||
}
|
||||
|
||||
lines.push_back (color.colorize (leftJustify (priority, width)));
|
||||
lines.push_back (color.colorize (leftJustify (priority, width)));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string ColumnPriority::modify (std::string& value)
|
||||
{
|
||||
return upperCase (value);
|
||||
if (value == "h") value = "H";
|
||||
else if (value == "m") value = "M";
|
||||
else if (value == "l") value = "L";
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -68,25 +68,30 @@ bool ColumnProject::validate (std::string& value)
|
||||
// Set the minimum and maximum widths for the value.
|
||||
void ColumnProject::measure (Task& task, unsigned int& minimum, unsigned int& maximum)
|
||||
{
|
||||
std::string project = task.get (_name);
|
||||
minimum = maximum = 0;
|
||||
|
||||
if (_style == "parent")
|
||||
if (task.has (_name))
|
||||
{
|
||||
std::string::size_type period = project.find ('.');
|
||||
if (period != std::string::npos)
|
||||
project = project.substr (0, period);
|
||||
}
|
||||
else if (_style == "indented")
|
||||
{
|
||||
project = indentProject (project, " ", '.');
|
||||
}
|
||||
else if (_style != "default" &&
|
||||
_style != "full" &&
|
||||
_style != "indented")
|
||||
throw format (STRING_COLUMN_BAD_FORMAT, _name, _style);
|
||||
std::string project = task.get (_name);
|
||||
|
||||
minimum = longestWord (project);
|
||||
maximum = utf8_width (project);
|
||||
if (_style == "parent")
|
||||
{
|
||||
std::string::size_type period = project.find ('.');
|
||||
if (period != std::string::npos)
|
||||
project = project.substr (0, period);
|
||||
}
|
||||
else if (_style == "indented")
|
||||
{
|
||||
project = indentProject (project, " ", '.');
|
||||
}
|
||||
else if (_style != "default" &&
|
||||
_style != "full" &&
|
||||
_style != "indented")
|
||||
throw format (STRING_COLUMN_BAD_FORMAT, _name, _style);
|
||||
|
||||
minimum = longestWord (project);
|
||||
maximum = utf8_width (project);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -96,24 +101,27 @@ void ColumnProject::render (
|
||||
int width,
|
||||
Color& color)
|
||||
{
|
||||
std::string project = task.get (_name);
|
||||
if (_style == "parent")
|
||||
if (task.has (_name))
|
||||
{
|
||||
std::string::size_type period = project.find ('.');
|
||||
if (period != std::string::npos)
|
||||
project = project.substr (0, period);
|
||||
}
|
||||
else if (_style == "indented")
|
||||
{
|
||||
project = indentProject (project, " ", '.');
|
||||
}
|
||||
std::string project = task.get (_name);
|
||||
if (_style == "parent")
|
||||
{
|
||||
std::string::size_type period = project.find ('.');
|
||||
if (period != std::string::npos)
|
||||
project = project.substr (0, period);
|
||||
}
|
||||
else if (_style == "indented")
|
||||
{
|
||||
project = indentProject (project, " ", '.');
|
||||
}
|
||||
|
||||
std::vector <std::string> raw;
|
||||
wrapText (raw, project, width, _hyphenate);
|
||||
std::vector <std::string> raw;
|
||||
wrapText (raw, project, width, _hyphenate);
|
||||
|
||||
std::vector <std::string>::iterator i;
|
||||
for (i = raw.begin (); i != raw.end (); ++i)
|
||||
lines.push_back (color.colorize (leftJustify (*i, width)));
|
||||
std::vector <std::string>::iterator i;
|
||||
for (i = raw.begin (); i != raw.end (); ++i)
|
||||
lines.push_back (color.colorize (leftJustify (*i, width)));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -79,18 +79,23 @@ void ColumnRecur::setStyle (const std::string& value)
|
||||
// Set the minimum and maximum widths for the value.
|
||||
void ColumnRecur::measure (Task& task, unsigned int& minimum, unsigned int& maximum)
|
||||
{
|
||||
if (_style == "default" ||
|
||||
_style == "duration")
|
||||
minimum = maximum = 0;
|
||||
|
||||
if (task.has (_name))
|
||||
{
|
||||
minimum = maximum = Duration (task.get ("recur")).formatISO ().length ();
|
||||
if (_style == "default" ||
|
||||
_style == "duration")
|
||||
{
|
||||
minimum = maximum = Duration (task.get ("recur")).formatISO ().length ();
|
||||
}
|
||||
else if (_style == "indicator")
|
||||
{
|
||||
if (task.has (_name))
|
||||
minimum = maximum = utf8_width (context.config.get ("recurrence.indicator"));
|
||||
}
|
||||
else
|
||||
throw format (STRING_COLUMN_BAD_FORMAT, _name, _style);
|
||||
}
|
||||
else if (_style == "indicator")
|
||||
{
|
||||
if (task.has (_name))
|
||||
minimum = maximum = utf8_width (context.config.get ("recurrence.indicator"));
|
||||
}
|
||||
else
|
||||
throw format (STRING_COLUMN_BAD_FORMAT, _name, _style);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -108,8 +113,7 @@ void ColumnRecur::render (
|
||||
lines.push_back (
|
||||
color.colorize (
|
||||
rightJustify (
|
||||
Duration (task.get ("recur")).formatISO (),
|
||||
width)));
|
||||
Duration (task.get ("recur")).formatISO (), width)));
|
||||
}
|
||||
else if (_style == "indicator")
|
||||
{
|
||||
|
||||
@@ -71,6 +71,8 @@ void ColumnString::setReport (const std::string& value)
|
||||
//
|
||||
void ColumnString::measure (const std::string& value, unsigned int& minimum, unsigned int& maximum)
|
||||
{
|
||||
minimum = maximum = 0;
|
||||
|
||||
if (_style == "left" ||
|
||||
_style == "right" ||
|
||||
_style == "default")
|
||||
|
||||
@@ -84,30 +84,34 @@ void ColumnTags::setStyle (const std::string& value)
|
||||
// Set the minimum and maximum widths for the value.
|
||||
void ColumnTags::measure (Task& task, unsigned int& minimum, unsigned int& maximum)
|
||||
{
|
||||
if (_style == "indicator") minimum = maximum = utf8_width (context.config.get ("tag.indicator"));
|
||||
else if (_style == "count") minimum = maximum = 3;
|
||||
else if (_style == "default" ||
|
||||
_style == "list")
|
||||
{
|
||||
std::string tags = task.get (_name);
|
||||
minimum = 0;
|
||||
maximum = utf8_width (tags);
|
||||
minimum = maximum = 0;
|
||||
|
||||
if (maximum)
|
||||
if (task.has (_name))
|
||||
{
|
||||
if (_style == "indicator") minimum = maximum = utf8_width (context.config.get ("tag.indicator"));
|
||||
else if (_style == "count") minimum = maximum = 3;
|
||||
else if (_style == "default" ||
|
||||
_style == "list")
|
||||
{
|
||||
std::vector <std::string> all;
|
||||
split (all, tags, ',');
|
||||
std::vector <std::string>::iterator i;
|
||||
for (i = all.begin (); i != all.end (); ++i)
|
||||
std::string tags = task.get (_name);
|
||||
maximum = utf8_width (tags);
|
||||
|
||||
if (maximum)
|
||||
{
|
||||
unsigned int length = utf8_width (*i);
|
||||
if (length > minimum)
|
||||
minimum = length;
|
||||
std::vector <std::string> all;
|
||||
split (all, tags, ',');
|
||||
std::vector <std::string>::iterator i;
|
||||
for (i = all.begin (); i != all.end (); ++i)
|
||||
{
|
||||
unsigned int length = utf8_width (*i);
|
||||
if (length > minimum)
|
||||
minimum = length;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
throw format (STRING_COLUMN_BAD_FORMAT, _name, _style);
|
||||
}
|
||||
else
|
||||
throw format (STRING_COLUMN_BAD_FORMAT, _name, _style);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -117,9 +121,9 @@ void ColumnTags::render (
|
||||
int width,
|
||||
Color& color)
|
||||
{
|
||||
std::string tags = task.get (_name);
|
||||
if (tags != "")
|
||||
if (task.has (_name))
|
||||
{
|
||||
std::string tags = task.get (_name);
|
||||
if (_style == "default" ||
|
||||
_style == "list")
|
||||
{
|
||||
|
||||
@@ -80,49 +80,52 @@ void ColumnUDA::measure (Task& task, unsigned int& minimum, unsigned int& maximu
|
||||
{
|
||||
minimum = maximum = 0;
|
||||
|
||||
if (_style == "default")
|
||||
if (task.has (_name))
|
||||
{
|
||||
std::string value = task.get (_name);
|
||||
if (value != "")
|
||||
if (_style == "default")
|
||||
{
|
||||
if (_type == "date")
|
||||
std::string value = task.get (_name);
|
||||
if (value != "")
|
||||
{
|
||||
// Determine the output date format, which uses a hierarchy of definitions.
|
||||
// rc.report.<report>.dateformat
|
||||
// rc.dateformat.report
|
||||
// rc.dateformat
|
||||
Date date ((time_t) strtol (value.c_str (), NULL, 10));
|
||||
std::string format = context.config.get ("report." + _report + ".dateformat");
|
||||
if (format == "")
|
||||
format = context.config.get ("dateformat.report");
|
||||
if (format == "")
|
||||
format = context.config.get ("dateformat");
|
||||
if (_type == "date")
|
||||
{
|
||||
// Determine the output date format, which uses a hierarchy of definitions.
|
||||
// rc.report.<report>.dateformat
|
||||
// rc.dateformat.report
|
||||
// rc.dateformat
|
||||
Date date ((time_t) strtol (value.c_str (), NULL, 10));
|
||||
std::string format = context.config.get ("report." + _report + ".dateformat");
|
||||
if (format == "")
|
||||
format = context.config.get ("dateformat.report");
|
||||
if (format == "")
|
||||
format = context.config.get ("dateformat");
|
||||
|
||||
minimum = maximum = Date::length (format);
|
||||
}
|
||||
else if (_type == "duration")
|
||||
{
|
||||
minimum = maximum = utf8_width (Duration (value).formatISO ());
|
||||
}
|
||||
else if (_type == "string")
|
||||
{
|
||||
std::string stripped = Color::strip (value);
|
||||
maximum = longestLine (stripped);
|
||||
minimum = longestWord (stripped);
|
||||
}
|
||||
else if (_type == "numeric")
|
||||
{
|
||||
minimum = maximum = utf8_width (value);
|
||||
minimum = maximum = Date::length (format);
|
||||
}
|
||||
else if (_type == "duration")
|
||||
{
|
||||
minimum = maximum = utf8_width (Duration (value).formatISO ());
|
||||
}
|
||||
else if (_type == "string")
|
||||
{
|
||||
std::string stripped = Color::strip (value);
|
||||
maximum = longestLine (stripped);
|
||||
minimum = longestWord (stripped);
|
||||
}
|
||||
else if (_type == "numeric")
|
||||
{
|
||||
minimum = maximum = utf8_width (value);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (_style == "indicator")
|
||||
{
|
||||
if (task.has (_name))
|
||||
minimum = maximum = utf8_width (context.config.get ("uda." + _name + ".indicator"));
|
||||
}
|
||||
else
|
||||
throw format (STRING_COLUMN_BAD_FORMAT, _name, _style);
|
||||
}
|
||||
else if (_style == "indicator")
|
||||
{
|
||||
if (task.has (_name))
|
||||
minimum = maximum = utf8_width (context.config.get ("uda." + _name + ".indicator"));
|
||||
}
|
||||
else
|
||||
throw format (STRING_COLUMN_BAD_FORMAT, _name, _style);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -132,11 +135,11 @@ void ColumnUDA::render (
|
||||
int width,
|
||||
Color& color)
|
||||
{
|
||||
if (_style == "default")
|
||||
if (task.has (_name))
|
||||
{
|
||||
std::string value = task.get (_name);
|
||||
if (value != "")
|
||||
if (_style == "default")
|
||||
{
|
||||
std::string value = task.get (_name);
|
||||
if (_type == "date")
|
||||
{
|
||||
// Determine the output date format, which uses a hierarchy of definitions.
|
||||
@@ -177,13 +180,13 @@ void ColumnUDA::render (
|
||||
lines.push_back (color.colorize (rightJustify (value, width)));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (_style == "indicator")
|
||||
{
|
||||
if (task.has (_name))
|
||||
lines.push_back (
|
||||
color.colorize (
|
||||
rightJustify (context.config.get ("uda." + _name + ".indicator"), width)));
|
||||
else if (_style == "indicator")
|
||||
{
|
||||
if (task.has (_name))
|
||||
lines.push_back (
|
||||
color.colorize (
|
||||
rightJustify (context.config.get ("uda." + _name + ".indicator"), width)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ set (commands_SRCS Command.cpp Command.h
|
||||
CmdColor.cpp CmdColor.h
|
||||
CmdColumns.cpp CmdColumns.h
|
||||
CmdConfig.cpp CmdConfig.h
|
||||
CmdContext.cpp CmdContext.h
|
||||
CmdCount.cpp CmdCount.h
|
||||
CmdCustom.cpp CmdCustom.h
|
||||
CmdDelete.cpp CmdDelete.h
|
||||
|
||||
@@ -46,6 +46,107 @@ CmdConfig::CmdConfig ()
|
||||
_displays_id = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool CmdConfig::setConfigVariable (std::string name, std::string value, bool confirmation /* = false */)
|
||||
{
|
||||
// Read .taskrc (or equivalent)
|
||||
std::vector <std::string> contents;
|
||||
File::read (context.config._original_file, contents);
|
||||
|
||||
bool found = false;
|
||||
bool change = false;
|
||||
|
||||
std::vector <std::string>::iterator line;
|
||||
for (line = contents.begin (); line != contents.end (); ++line)
|
||||
{
|
||||
// If there is a comment on the line, it must follow the pattern.
|
||||
std::string::size_type comment = line->find ("#");
|
||||
std::string::size_type pos = line->find (name + "=");
|
||||
|
||||
if (pos != std::string::npos &&
|
||||
(comment == std::string::npos ||
|
||||
comment > pos))
|
||||
{
|
||||
found = true;
|
||||
if (!confirmation ||
|
||||
confirm (format (STRING_CMD_CONFIG_CONFIRM, name, context.config.get (name), value)))
|
||||
{
|
||||
if (comment != std::string::npos)
|
||||
*line = name + "=" + json::encode (value) + " " + line->substr (comment);
|
||||
else
|
||||
*line = name + "=" + json::encode (value);
|
||||
|
||||
change = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Not found, so append instead.
|
||||
if (!found &&
|
||||
(!confirmation ||
|
||||
confirm (format (STRING_CMD_CONFIG_CONFIRM2, name, value))))
|
||||
{
|
||||
contents.push_back (name + "=" + json::encode (value));
|
||||
change = true;
|
||||
}
|
||||
|
||||
if (change)
|
||||
File::write (context.config._original_file, contents);
|
||||
|
||||
return change;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int CmdConfig::unsetConfigVariable (std::string name, bool confirmation /* = false */)
|
||||
{
|
||||
// Read .taskrc (or equivalent)
|
||||
std::vector <std::string> contents;
|
||||
File::read (context.config._original_file, contents);
|
||||
|
||||
bool found = false;
|
||||
bool change = false;
|
||||
|
||||
std::vector <std::string>::iterator line;
|
||||
for (line = contents.begin (); line != contents.end (); )
|
||||
{
|
||||
bool lineDeleted = false;
|
||||
|
||||
// If there is a comment on the line, it must follow the pattern.
|
||||
std::string::size_type comment = line->find ("#");
|
||||
std::string::size_type pos = line->find (name + "=");
|
||||
|
||||
if (pos != std::string::npos &&
|
||||
(comment == std::string::npos ||
|
||||
comment > pos))
|
||||
{
|
||||
found = true;
|
||||
|
||||
// Remove name
|
||||
if (!confirmation ||
|
||||
confirm (format (STRING_CMD_CONFIG_CONFIRM3, name)))
|
||||
{
|
||||
// vector::erase method returns a valid iterator to the next object
|
||||
line = contents.erase (line);
|
||||
lineDeleted = true;
|
||||
change = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (! lineDeleted)
|
||||
line++;
|
||||
}
|
||||
|
||||
if (change)
|
||||
File::write (context.config._original_file, contents);
|
||||
|
||||
if ( change && found )
|
||||
return 0;
|
||||
else if ( found )
|
||||
return 1;
|
||||
else
|
||||
return 2;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int CmdConfig::execute (std::string& output)
|
||||
{
|
||||
@@ -62,10 +163,13 @@ int CmdConfig::execute (std::string& output)
|
||||
if (words.size ())
|
||||
{
|
||||
bool confirmation = context.config.getBoolean ("confirmation");
|
||||
bool change = false;
|
||||
bool found = false;
|
||||
|
||||
std::string name = words[0];
|
||||
std::string value = "";
|
||||
|
||||
// Join the remaining words into config variable's value
|
||||
if (words.size () > 1)
|
||||
{
|
||||
for (unsigned int i = 1; i < words.size (); ++i)
|
||||
@@ -81,85 +185,30 @@ int CmdConfig::execute (std::string& output)
|
||||
{
|
||||
bool change = false;
|
||||
|
||||
// Read .taskrc (or equivalent)
|
||||
std::vector <std::string> contents;
|
||||
File::read (context.config._original_file, contents);
|
||||
|
||||
// task config name value
|
||||
// task config name ""
|
||||
if (words.size () > 1)
|
||||
{
|
||||
bool found = false;
|
||||
std::vector <std::string>::iterator line;
|
||||
for (line = contents.begin (); line != contents.end (); ++line)
|
||||
{
|
||||
// If there is a comment on the line, it must follow the pattern.
|
||||
std::string::size_type comment = line->find ("#");
|
||||
std::string::size_type pos = line->find (name + "=");
|
||||
|
||||
if (pos != std::string::npos &&
|
||||
(comment == std::string::npos ||
|
||||
comment > pos))
|
||||
{
|
||||
found = true;
|
||||
if (!confirmation ||
|
||||
confirm (format (STRING_CMD_CONFIG_CONFIRM, name, context.config.get (name), value)))
|
||||
{
|
||||
if (comment != std::string::npos)
|
||||
*line = name + "=" + json::encode (value) + " " + line->substr (comment);
|
||||
else
|
||||
*line = name + "=" + json::encode (value);
|
||||
|
||||
change = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Not found, so append instead.
|
||||
if (!found &&
|
||||
(!confirmation ||
|
||||
confirm (format (STRING_CMD_CONFIG_CONFIRM2, name, value))))
|
||||
{
|
||||
contents.push_back (name + "=" + json::encode (value));
|
||||
change = true;
|
||||
}
|
||||
}
|
||||
change = setConfigVariable(name, value, confirmation);
|
||||
|
||||
// task config name
|
||||
else
|
||||
{
|
||||
bool found = false;
|
||||
std::vector <std::string>::iterator line;
|
||||
for (line = contents.begin (); line != contents.end (); ++line)
|
||||
rc = unsetConfigVariable(name, confirmation);
|
||||
if (rc == 0)
|
||||
{
|
||||
// If there is a comment on the line, it must follow the pattern.
|
||||
std::string::size_type comment = line->find ("#");
|
||||
std::string::size_type pos = line->find (name + "=");
|
||||
|
||||
if (pos != std::string::npos &&
|
||||
(comment == std::string::npos ||
|
||||
comment > pos))
|
||||
{
|
||||
found = true;
|
||||
|
||||
// Remove name
|
||||
if (!confirmation ||
|
||||
confirm (format (STRING_CMD_CONFIG_CONFIRM3, name)))
|
||||
{
|
||||
*line = "";
|
||||
change = true;
|
||||
}
|
||||
}
|
||||
change = true;
|
||||
found = true;
|
||||
}
|
||||
else if (rc == 1)
|
||||
found = true;
|
||||
|
||||
if (!found)
|
||||
throw format (STRING_CMD_CONFIG_NO_ENTRY, name);
|
||||
}
|
||||
|
||||
// Write .taskrc (or equivalent)
|
||||
// Show feedback depending on whether .taskrc has been rewritten
|
||||
if (change)
|
||||
{
|
||||
File::write (context.config._original_file, contents);
|
||||
out << format (STRING_CMD_CONFIG_FILE_MOD,
|
||||
context.config._original_file._data)
|
||||
<< "\n";
|
||||
|
||||
@@ -34,6 +34,8 @@ class CmdConfig : public Command
|
||||
{
|
||||
public:
|
||||
CmdConfig ();
|
||||
static bool setConfigVariable (std::string name, std::string value, bool confirmation = false);
|
||||
static int unsetConfigVariable (std::string name, bool confirmation = false);
|
||||
int execute (std::string&);
|
||||
};
|
||||
|
||||
|
||||
379
src/commands/CmdContext.cpp
Normal file
379
src/commands/CmdContext.cpp
Normal file
@@ -0,0 +1,379 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// http://www.opensource.org/licenses/mit-license.php
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <cmake.h>
|
||||
#include <Context.h>
|
||||
#include <Filter.h>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <i18n.h>
|
||||
#include <util.h>
|
||||
#include <text.h>
|
||||
#include <CmdContext.h>
|
||||
#include <CmdConfig.h>
|
||||
|
||||
extern Context context;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CmdContext::CmdContext ()
|
||||
{
|
||||
_keyword = "context";
|
||||
_usage = "task context [<name> | subcommand]";
|
||||
_description = STRING_CMD_CONTEXT_USAGE;
|
||||
_read_only = true;
|
||||
_displays_id = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int CmdContext::execute (std::string& output)
|
||||
{
|
||||
int rc = 0;
|
||||
std::stringstream out;
|
||||
|
||||
// Get the non-attribute, non-fancy command line arguments.
|
||||
std::vector <std::string> words = context.cli.getWords ();
|
||||
|
||||
if (words.size () > 0)
|
||||
{
|
||||
std::string subcommand = words[0];
|
||||
|
||||
if (subcommand == "define")
|
||||
rc = defineContext (words, out);
|
||||
else if (subcommand == "delete")
|
||||
rc = deleteContext (words, out);
|
||||
else if (subcommand == "list")
|
||||
rc = listContexts (words, out);
|
||||
else if (subcommand == "none")
|
||||
rc = unsetContext (words, out);
|
||||
else if (subcommand == "show")
|
||||
rc = showContext (words, out);
|
||||
else
|
||||
rc = setContext (words, out);
|
||||
}
|
||||
|
||||
output = out.str ();
|
||||
return rc;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Joins all the words in the specified interval <from, to) to one string,
|
||||
// which is then returned.
|
||||
//
|
||||
// If to is specified as 0 (default value), all the remaining words will be joined.
|
||||
//
|
||||
std::string CmdContext::joinWords (std::vector <std::string>& words, unsigned int from, unsigned int to /* = 0 */)
|
||||
{
|
||||
std::string value = "";
|
||||
|
||||
if (to == 0)
|
||||
to = words.size();
|
||||
|
||||
for (unsigned int i = from; i < to; ++i)
|
||||
{
|
||||
if (i > from)
|
||||
value += " ";
|
||||
|
||||
value += words[i];
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Returns all user defined contexts.
|
||||
//
|
||||
std::vector <std::string> CmdContext::getContexts ()
|
||||
{
|
||||
std::vector <std::string> contexts;
|
||||
|
||||
Config::const_iterator name;
|
||||
for (name = context.config.begin (); name != context.config.end (); ++name)
|
||||
if (name->first.substr (0, 8) == "context.")
|
||||
contexts.push_back (name->first.substr (8));
|
||||
|
||||
return contexts;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Defines a new user-provided context.
|
||||
// - The context definition is written into .taskrc as a context.<name> variable.
|
||||
// - Deletion of the context requires confirmation if rc.confirmation=yes.
|
||||
//
|
||||
// Returns: 0 if the addition of the config variable was successful, 1 otherwise
|
||||
//
|
||||
// Invoked with: task context define <name> <filter>
|
||||
// Example: task context define home project:Home
|
||||
//
|
||||
int CmdContext::defineContext (std::vector <std::string>& words, std::stringstream& out)
|
||||
{
|
||||
int rc = 0;
|
||||
bool confirmation = context.config.getBoolean ("confirmation");
|
||||
|
||||
if (words.size () > 2)
|
||||
{
|
||||
std::string name = "context." + words[1];
|
||||
std::string value = joinWords (words, 2);
|
||||
|
||||
// Check if the value is a proper filter by filtering current pending.data
|
||||
Filter filter;
|
||||
std::vector <Task> filtered;
|
||||
const std::vector <Task>& pending = context.tdb2.pending.get_tasks ();
|
||||
|
||||
try
|
||||
{
|
||||
context.cli.addRawFilter ("( " + value + " )");
|
||||
filter.subset (pending, filtered);
|
||||
}
|
||||
catch (std::string exception)
|
||||
{
|
||||
throw format (STRING_CMD_CONTEXT_DEF_ABRT2, exception);
|
||||
}
|
||||
|
||||
// Make user explicitly confirm filters that are matching no pending tasks
|
||||
if (filtered.size () == 0)
|
||||
if (confirmation &&
|
||||
! confirm (format (STRING_CMD_CONTEXT_DEF_CONF, value)))
|
||||
throw std::string (STRING_CMD_CONTEXT_DEF_ABRT);
|
||||
|
||||
// Set context definition config variable
|
||||
bool success = CmdConfig::setConfigVariable (name, value, confirmation);
|
||||
|
||||
if (success)
|
||||
out << format (STRING_CMD_CONTEXT_DEF_SUCC, words[1]) << "\n";
|
||||
else
|
||||
{
|
||||
out << format (STRING_CMD_CONTEXT_DEF_FAIL, words[1]) << "\n";
|
||||
rc = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
out << STRING_CMD_CONTEXT_DEF_USAG << "\n";
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Deletes the specified context.
|
||||
// - If the deleted context is currently active, unset it.
|
||||
// - Deletion of the context requires confirmation if rc.confirmation=yes.
|
||||
//
|
||||
// Returns: 0 if the removal of the config variable was successful, 1 otherwise
|
||||
//
|
||||
// Invoked with: task context delete <name>
|
||||
// Example: task context delete home
|
||||
//
|
||||
int CmdContext::deleteContext (std::vector <std::string>& words, std::stringstream& out)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (words.size () > 1)
|
||||
{
|
||||
// Delete the specified context
|
||||
std::string name = "context." + words[1];
|
||||
|
||||
bool confirmation = context.config.getBoolean ("confirmation");
|
||||
rc = CmdConfig::unsetConfigVariable(name, confirmation);
|
||||
|
||||
// If the currently set context was deleted, unset it
|
||||
std::string currentContext = context.config.get ("context");
|
||||
|
||||
if (currentContext == words[1])
|
||||
CmdConfig::unsetConfigVariable("context", false);
|
||||
|
||||
// Output feedback
|
||||
if (rc == 0)
|
||||
out << format (STRING_CMD_CONTEXT_DEL_SUCC, words[1]) << "\n";
|
||||
else
|
||||
out << format (STRING_CMD_CONTEXT_DEL_FAIL, words[1]) << "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
out << STRING_CMD_CONTEXT_DEL_USAG << "\n";
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Render a list of context names and their definitions.
|
||||
//
|
||||
// Returns: 0 the resulting list is non-empty, 1 otherwise
|
||||
//
|
||||
// Invoked with: task context list
|
||||
// Example: task context list
|
||||
//
|
||||
int CmdContext::listContexts (std::vector <std::string>& words, std::stringstream& out)
|
||||
{
|
||||
int rc = 0;
|
||||
std::vector <std::string> contexts = getContexts();
|
||||
|
||||
if (contexts.size ())
|
||||
{
|
||||
std::sort (contexts.begin (), contexts.end ());
|
||||
|
||||
ViewText view;
|
||||
view.width (context.getWidth ());
|
||||
view.add (Column::factory ("string", "Name"));
|
||||
view.add (Column::factory ("string", "Definition"));
|
||||
|
||||
Color label (context.config.get ("color.label"));
|
||||
view.colorHeader (label);
|
||||
|
||||
std::vector <std::string>::iterator userContext;
|
||||
for (userContext = contexts.begin (); userContext != contexts.end (); ++userContext)
|
||||
{
|
||||
std::string definition = context.config.get ("context." + *userContext);
|
||||
|
||||
int row = view.addRow ();
|
||||
view.set (row, 0, *userContext);
|
||||
view.set (row, 1, definition);
|
||||
}
|
||||
|
||||
out << optionalBlankLine ()
|
||||
<< view.render ()
|
||||
<< optionalBlankLine ();
|
||||
}
|
||||
else
|
||||
{
|
||||
out << STRING_CMD_CONTEXT_LIST_EMPT << "\n";
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Sets the specified context as currently active.
|
||||
// - If some other context was active, the value of currently active context
|
||||
// is replaced, not added.
|
||||
// - Setting of the context does not require confirmation.
|
||||
//
|
||||
// Returns: 0 if the setting of the context was successful, 1 otherwise
|
||||
//
|
||||
// Invoked with: task context <name>
|
||||
// Example: task context home
|
||||
//
|
||||
int CmdContext::setContext (std::vector <std::string>& words, std::stringstream& out)
|
||||
{
|
||||
int rc = 0;
|
||||
std::string value = words[0];
|
||||
std::vector <std::string> contexts = getContexts ();
|
||||
|
||||
// Check that the specified context is defined
|
||||
if (std::find (contexts.begin (), contexts.end (), value) == contexts.end ())
|
||||
throw format (STRING_CMD_CONTEXT_SET_NFOU, value);
|
||||
|
||||
// Set the active context.
|
||||
// Should always succeed, as we do not require confirmation.
|
||||
bool success = CmdConfig::setConfigVariable ("context", value, false);
|
||||
|
||||
if (success)
|
||||
out << format (STRING_CMD_CONTEXT_SET_SUCC, value) << "\n";
|
||||
else
|
||||
{
|
||||
out << format (STRING_CMD_CONTEXT_SET_FAIL, value) << "\n";
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Shows the currently active context.
|
||||
//
|
||||
// Returns: Always returns 0.
|
||||
//
|
||||
// Invoked with: task context show
|
||||
// Example: task context show
|
||||
//
|
||||
int CmdContext::showContext (std::vector <std::string>& words, std::stringstream& out)
|
||||
{
|
||||
std::string currentContext = context.config.get ("context");
|
||||
|
||||
if (currentContext == "")
|
||||
out << STRING_CMD_CONTEXT_SHOW_EMPT << "\n";
|
||||
else
|
||||
{
|
||||
std::string currentFilter = context.config.get ("context." + currentContext);
|
||||
out << format (STRING_CMD_CONTEXT_SHOW, currentContext, currentFilter) << "\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Unsets the currently active context.
|
||||
// - Unsetting of the context does not require confirmation.
|
||||
//
|
||||
// Returns: 0 if the unsetting of the context was successful, 1 otherwise (also
|
||||
// returned if no context is currently active)
|
||||
//
|
||||
// Invoked with: task context none
|
||||
// Example: task context none
|
||||
//
|
||||
int CmdContext::unsetContext (std::vector <std::string>& words, std::stringstream& out)
|
||||
{
|
||||
int rc = 0;
|
||||
int status = CmdConfig::unsetConfigVariable ("context", false);
|
||||
|
||||
if (status == 0)
|
||||
out << STRING_CMD_CONTEXT_NON_SUCC << "\n";
|
||||
else
|
||||
{
|
||||
out << STRING_CMD_CONTEXT_NON_FAIL << "\n";
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CmdCompletionContext::CmdCompletionContext ()
|
||||
{
|
||||
_keyword = "_context";
|
||||
_usage = "task _context";
|
||||
_description = STRING_CMD_HCONTEXT_USAGE;
|
||||
_read_only = true;
|
||||
_displays_id = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int CmdCompletionContext::execute (std::string& output)
|
||||
{
|
||||
std::vector <std::string> userContexts = CmdContext::getContexts ();
|
||||
|
||||
std::vector <std::string>::iterator userContext;
|
||||
for (userContext = userContexts.begin (); userContext != userContexts.end (); ++userContext)
|
||||
output += *userContext + "\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -24,40 +24,33 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <cmake.h>
|
||||
#include <iostream>
|
||||
#include <stdlib.h>
|
||||
#include <text.h>
|
||||
#include <test.h>
|
||||
#ifndef INCLUDED_CMDCONTEXT
|
||||
#define INCLUDED_CMDCONTEXT
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int main (int argc, char** argv)
|
||||
#include <string>
|
||||
#include <Command.h>
|
||||
|
||||
class CmdContext : public Command
|
||||
{
|
||||
UnitTest t (16);
|
||||
public:
|
||||
CmdContext ();
|
||||
int execute (std::string&);
|
||||
std::string joinWords (std::vector <std::string>& words, unsigned int from, unsigned int to = 0);
|
||||
static std::vector <std::string> getContexts ();
|
||||
int defineContext (std::vector <std::string>& words, std::stringstream& out);
|
||||
int deleteContext (std::vector <std::string>& words, std::stringstream& out);
|
||||
int listContexts (std::vector <std::string>& words, std::stringstream& out);
|
||||
int setContext (std::vector <std::string>& words, std::stringstream& out);
|
||||
int showContext (std::vector <std::string>& words, std::stringstream& out);
|
||||
int unsetContext (std::vector <std::string>& words, std::stringstream& out);
|
||||
};
|
||||
|
||||
// Ensure environment has no influence.
|
||||
unsetenv ("TASKDATA");
|
||||
unsetenv ("TASKRC");
|
||||
|
||||
t.is (mk_wcwidth ('a'), 1, "U+0061 --> 1");
|
||||
|
||||
t.is (mk_wcwidth (0x5149), 2, "U+5149 --> 2");
|
||||
t.is (mk_wcwidth (0x9a8c), 2, "U+9a8c --> 2");
|
||||
t.is (mk_wcwidth (0x4e70), 2, "U+4e70 --> 2");
|
||||
t.is (mk_wcwidth (0x94b1), 2, "U+94b1 --> 2");
|
||||
t.is (mk_wcwidth (0x5305), 2, "U+5305 --> 2");
|
||||
t.is (mk_wcwidth (0x91cd), 2, "U+91cd --> 2");
|
||||
t.is (mk_wcwidth (0x65b0), 2, "U+65b0 --> 2");
|
||||
t.is (mk_wcwidth (0x8bbe), 2, "U+8bbe --> 2");
|
||||
t.is (mk_wcwidth (0x8ba1), 2, "U+8ba1 --> 2");
|
||||
t.is (mk_wcwidth (0x5411), 2, "U+5411 --> 2");
|
||||
t.is (mk_wcwidth (0x4e0a), 2, "U+4e0a --> 2");
|
||||
t.is (mk_wcwidth (0x4e0b), 2, "U+4e0b --> 2");
|
||||
t.is (mk_wcwidth (0x7bad), 2, "U+7bad --> 2");
|
||||
t.is (mk_wcwidth (0x5934), 2, "U+5934 --> 2");
|
||||
t.is (mk_wcwidth (0xff0c), 2, "U+ff0c --> 2"); // comma
|
||||
|
||||
return 0;
|
||||
}
|
||||
class CmdCompletionContext : public Command
|
||||
{
|
||||
public:
|
||||
CmdCompletionContext ();
|
||||
int execute (std::string&);
|
||||
};
|
||||
|
||||
#endif
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -82,15 +82,7 @@ int CmdCustom::execute (std::string& output)
|
||||
validateSortColumns (sortOrder);
|
||||
|
||||
// Prepend the argument list with those from the report filter.
|
||||
std::string lexeme;
|
||||
Lexer::Type type;
|
||||
Lexer lex (reportFilter);
|
||||
lex.ambiguity (false);
|
||||
while (lex.token (lexeme, type))
|
||||
context.cli.add (lexeme);
|
||||
|
||||
// Reparse after tree change.
|
||||
context.cli.analyze ();
|
||||
context.cli.addRawFilter(reportFilter);
|
||||
|
||||
// Apply filter.
|
||||
handleRecurrence ();
|
||||
|
||||
@@ -54,7 +54,7 @@ int CmdExport::execute (std::string& output)
|
||||
// Apply filter.
|
||||
Filter filter;
|
||||
std::vector <Task> filtered;
|
||||
filter.subset (filtered);
|
||||
filter.subset (filtered, false);
|
||||
|
||||
// Obey 'limit:N'.
|
||||
int rows = 0;
|
||||
|
||||
@@ -314,6 +314,40 @@ int CmdInfo::execute (std::string& output)
|
||||
view.set (row, 1, allTags);
|
||||
}
|
||||
|
||||
// Virtual tags.
|
||||
{
|
||||
// Note: This list must match that in Task::hasTag.
|
||||
std::string virtualTags = "";
|
||||
if (task->hasTag ("ACTIVE")) virtualTags += "ACTIVE ";
|
||||
if (task->hasTag ("ANNOTATED")) virtualTags += "ANNOTATED ";
|
||||
if (task->hasTag ("BLOCKED")) virtualTags += "BLOCKED ";
|
||||
if (task->hasTag ("BLOCKING")) virtualTags += "BLOCKING ";
|
||||
if (task->hasTag ("CHILD")) virtualTags += "CHILD ";
|
||||
if (task->hasTag ("COMPLETED")) virtualTags += "COMPLETED ";
|
||||
if (task->hasTag ("DELETED")) virtualTags += "DELETED ";
|
||||
if (task->hasTag ("DUE")) virtualTags += "DUE ";
|
||||
if (task->hasTag ("DUETODAY")) virtualTags += "DUETODAY ";
|
||||
if (task->hasTag ("MONTH")) virtualTags += "MONTH ";
|
||||
if (task->hasTag ("OVERDUE")) virtualTags += "OVERDUE ";
|
||||
if (task->hasTag ("PARENT")) virtualTags += "PARENT ";
|
||||
if (task->hasTag ("PENDING")) virtualTags += "PENDING ";
|
||||
if (task->hasTag ("READY")) virtualTags += "READY ";
|
||||
if (task->hasTag ("SCHEDULED")) virtualTags += "SCHEDULED ";
|
||||
if (task->hasTag ("TAGGED")) virtualTags += "TAGGED ";
|
||||
if (task->hasTag ("TODAY")) virtualTags += "TODAY ";
|
||||
if (task->hasTag ("TOMORROW")) virtualTags += "TOMORROW ";
|
||||
if (task->hasTag ("UNBLOCKED")) virtualTags += "UNBLOCKED ";
|
||||
if (task->hasTag ("UNTIL")) virtualTags += "UNTIL ";
|
||||
if (task->hasTag ("WAITING")) virtualTags += "WAITING ";
|
||||
if (task->hasTag ("WEEK")) virtualTags += "WEEK ";
|
||||
if (task->hasTag ("YEAR")) virtualTags += "YEAR ";
|
||||
if (task->hasTag ("YESTERDAY")) virtualTags += "YESTERDAY ";
|
||||
|
||||
row = view.addRow ();
|
||||
view.set (row, 0, STRING_CMD_INFO_VIRTUAL_TAGS);
|
||||
view.set (row, 1, virtualTags);
|
||||
}
|
||||
|
||||
// uuid
|
||||
row = view.addRow ();
|
||||
view.set (row, 0, STRING_COLUMN_LABEL_UUID);
|
||||
|
||||
@@ -53,6 +53,9 @@ int CmdProjects::execute (std::string& output)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
// Enforce the garbage collector to show correct task counts
|
||||
context.tdb2.gc ();
|
||||
|
||||
// Get all the tasks.
|
||||
handleRecurrence ();
|
||||
std::vector <Task> tasks = context.tdb2.pending.get_tasks ();
|
||||
@@ -89,8 +92,16 @@ int CmdProjects::execute (std::string& output)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Increase the count for the project the task belongs to and all
|
||||
// its super-projects
|
||||
project = task->get ("project");
|
||||
unique[project] += 1;
|
||||
|
||||
std::vector <std::string> projects = extractParents (project);
|
||||
projects.push_back (project);
|
||||
|
||||
std::vector <std::string>::const_iterator parent;
|
||||
for (parent = projects.begin (); parent != projects.end (); ++parent)
|
||||
unique[*parent] += 1;
|
||||
|
||||
if (project == "")
|
||||
no_project = true;
|
||||
|
||||
@@ -127,6 +127,7 @@ int CmdShow::execute (std::string& output)
|
||||
" column.padding"
|
||||
" complete.all.tags"
|
||||
" confirmation"
|
||||
" context"
|
||||
" data.location"
|
||||
" dateformat"
|
||||
" dateformat.annotation"
|
||||
@@ -230,6 +231,7 @@ int CmdShow::execute (std::string& output)
|
||||
i->first.substr (0, 14) != "color.project." &&
|
||||
i->first.substr (0, 10) != "color.tag." &&
|
||||
i->first.substr (0, 10) != "color.uda." &&
|
||||
i->first.substr (0, 8) != "context." &&
|
||||
i->first.substr (0, 8) != "holiday." &&
|
||||
i->first.substr (0, 7) != "report." &&
|
||||
i->first.substr (0, 6) != "alias." &&
|
||||
|
||||
@@ -92,27 +92,34 @@ int CmdSummary::execute (std::string& output)
|
||||
for (task = filtered.begin (); task != filtered.end (); ++task)
|
||||
{
|
||||
std::string project = task->get ("project");
|
||||
++counter[project];
|
||||
std::vector <std::string> projects = extractParents (project);
|
||||
projects.push_back (project);
|
||||
|
||||
std::vector <std::string>::const_iterator parent;
|
||||
for (parent = projects.begin (); parent != projects.end (); ++parent)
|
||||
++counter[*parent];
|
||||
|
||||
if (task->getStatus () == Task::pending ||
|
||||
task->getStatus () == Task::waiting)
|
||||
{
|
||||
++countPending[project];
|
||||
for (parent = projects.begin (); parent != projects.end (); ++parent)
|
||||
{
|
||||
++countPending[*parent];
|
||||
|
||||
time_t entry = strtol (task->get ("entry").c_str (), NULL, 10);
|
||||
if (entry)
|
||||
sumEntry[project] = sumEntry[project] + (double) (now - entry);
|
||||
}
|
||||
time_t entry = strtol (task->get ("entry").c_str (), NULL, 10);
|
||||
if (entry)
|
||||
sumEntry[*parent] = sumEntry[*parent] + (double) (now - entry);
|
||||
}
|
||||
|
||||
else if (task->getStatus () == Task::completed)
|
||||
{
|
||||
++countCompleted[project];
|
||||
for (parent = projects.begin (); parent != projects.end (); ++parent)
|
||||
{
|
||||
++countCompleted[*parent];
|
||||
|
||||
time_t entry = strtol (task->get ("entry").c_str (), NULL, 10);
|
||||
time_t end = strtol (task->get ("end").c_str (), NULL, 10);
|
||||
if (entry && end)
|
||||
sumEntry[project] = sumEntry[project] + (double) (end - entry);
|
||||
}
|
||||
time_t entry = strtol (task->get ("entry").c_str (), NULL, 10);
|
||||
time_t end = strtol (task->get ("end").c_str (), NULL, 10);
|
||||
if (entry && end)
|
||||
sumEntry[*parent] = sumEntry[*parent] + (double) (end - entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -135,7 +135,10 @@ CmdCompletionVersion::CmdCompletionVersion ()
|
||||
int CmdCompletionVersion::execute (std::string& output)
|
||||
{
|
||||
#ifdef HAVE_COMMIT
|
||||
output = COMMIT;
|
||||
output = std::string (VERSION)
|
||||
+ std::string (" (")
|
||||
+ std::string (COMMIT)
|
||||
+ std::string (")");
|
||||
#else
|
||||
output = VERSION;
|
||||
#endif
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include <CmdColumns.h>
|
||||
#include <CmdCommands.h>
|
||||
#include <CmdConfig.h>
|
||||
#include <CmdContext.h>
|
||||
#include <CmdCount.h>
|
||||
#include <CmdCustom.h>
|
||||
#include <CmdDelete.h>
|
||||
@@ -109,6 +110,7 @@ void Command::factory (std::map <std::string, Command*>& all)
|
||||
c = new CmdCompletionColumns (); all[c->keyword ()] = c;
|
||||
c = new CmdCompletionCommands (); all[c->keyword ()] = c;
|
||||
c = new CmdCompletionConfig (); all[c->keyword ()] = c;
|
||||
c = new CmdCompletionContext (); all[c->keyword ()] = c;
|
||||
c = new CmdCompletionIds (); all[c->keyword ()] = c;
|
||||
c = new CmdCompletionUDAs (); all[c->keyword ()] = c;
|
||||
c = new CmdCompletionUuids (); all[c->keyword ()] = c;
|
||||
@@ -116,6 +118,7 @@ void Command::factory (std::map <std::string, Command*>& all)
|
||||
c = new CmdCompletionTags (); all[c->keyword ()] = c;
|
||||
c = new CmdCompletionVersion (); all[c->keyword ()] = c;
|
||||
c = new CmdConfig (); all[c->keyword ()] = c;
|
||||
c = new CmdContext (); all[c->keyword ()] = c;
|
||||
c = new CmdCount (); all[c->keyword ()] = c;
|
||||
c = new CmdDelete (); all[c->keyword ()] = c;
|
||||
c = new CmdDenotate (); all[c->keyword ()] = c;
|
||||
|
||||
@@ -296,6 +296,7 @@
|
||||
#define STRING_CMD_INFO_UNTIL "Bis"
|
||||
#define STRING_CMD_INFO_MODIFICATION "Änderung"
|
||||
#define STRING_CMD_INFO_MODIFIED "Letzte Änderung"
|
||||
#define STRING_CMD_INFO_VIRTUAL_TAGS "Virtual tags"
|
||||
#define STRING_CMD_UNDO_USAGE "Macht die letzte Änderung an einer Aufgabe Rückgängig"
|
||||
#define STRING_CMD_UNDO_MODS "Der undo-Befehl erlaubt keine weitere Aufgaben-Änderung."
|
||||
#define STRING_CMD_STATS_USAGE "Zeigt Statistiken zur Aufgaben-Datenbank"
|
||||
@@ -561,6 +562,25 @@
|
||||
#define STRING_CMD_CONFIG_NO_CHANGE "Keine Änderungen durchgeführt."
|
||||
#define STRING_CMD_CONFIG_NO_NAME "Geben Sie den Wert der zu ändernden Option an."
|
||||
#define STRING_CMD_HCONFIG_USAGE "Zeigt alle unterstützten Konfigurations-Optionen zur AUtovervollständigung"
|
||||
#define STRING_CMD_CONTEXT_USAGE "Set and define contexts (default filters)"
|
||||
#define STRING_CMD_CONTEXT_DEF_SUCC "Context '{1}' defined."
|
||||
#define STRING_CMD_CONTEXT_DEF_FAIL "Context '{1}' not defined."
|
||||
#define STRING_CMD_CONTEXT_DEF_USAG "Both context name and its definition must be provided."
|
||||
#define STRING_CMD_CONTEXT_DEF_ABRT "Context definiton aborted."
|
||||
#define STRING_CMD_CONTEXT_DEF_ABRT2 "Filter validation failed: {1}"
|
||||
#define STRING_CMD_CONTEXT_DEF_CONF "The filter '{1}' matches 0 pending tasks. Do you wish to continue?"
|
||||
#define STRING_CMD_CONTEXT_DEL_SUCC "Context '{1}' deleted."
|
||||
#define STRING_CMD_CONTEXT_DEL_FAIL "Context '{1}' not deleted."
|
||||
#define STRING_CMD_CONTEXT_DEL_USAG "Context name needs to be specified."
|
||||
#define STRING_CMD_CONTEXT_LIST_EMPT "No contexts defined."
|
||||
#define STRING_CMD_CONTEXT_SET_NFOU "Context '{1}' not found."
|
||||
#define STRING_CMD_CONTEXT_SET_SUCC "Context '{1}' set. Use 'task context none' to remove."
|
||||
#define STRING_CMD_CONTEXT_SET_FAIL "Context '{1}' not applied."
|
||||
#define STRING_CMD_CONTEXT_SHOW_EMPT "No context is currently applied."
|
||||
#define STRING_CMD_CONTEXT_SHOW "Context '{1}' with filter '{2}' is currently applied."
|
||||
#define STRING_CMD_CONTEXT_NON_SUCC "Context unset."
|
||||
#define STRING_CMD_CONTEXT_NON_FAIL "Context not unset."
|
||||
#define STRING_CMD_HCONTEXT_USAGE "Lists all supported contexts, for completion purposes"
|
||||
#define STRING_CMD_CUSTOM_MISMATCH "Die Anzahl von Spalten und Beschriftungen für Report '{1}' unterscheidet sich."
|
||||
#define STRING_CMD_CUSTOM_SHOWN "{1} gezeigt"
|
||||
#define STRING_CMD_CUSTOM_COUNT "1 Aufgabe"
|
||||
@@ -881,10 +901,6 @@
|
||||
#define STRING_TDB2_UNDO_SYNCED "Kann Änderung nicht rückgängig machen, weil die Aufgabe bereits abgeglichen wurde. Aufgabe stattdessen löschen."
|
||||
#define STRING_TDB2_DIRTY_EXIT "Beende mit ungeschriebenen Änderungen auf {1}"
|
||||
|
||||
// utf8
|
||||
#define STRING_UTF8_INVALID_CP_REP "Ungültige Codepoint-Darstellung."
|
||||
#define STRING_UTF8_INVALID_CP "Ungültiger Unicode-Codepoint."
|
||||
|
||||
// View
|
||||
#define STRING_VIEW_TOO_SMALL "Dieser Report hat eine Mindestbreite von {1} und passt nicht in die Bildschirmbreite von {2}."
|
||||
|
||||
|
||||
@@ -296,6 +296,7 @@
|
||||
#define STRING_CMD_INFO_UNTIL "Until"
|
||||
#define STRING_CMD_INFO_MODIFICATION "Modification"
|
||||
#define STRING_CMD_INFO_MODIFIED "Last modified"
|
||||
#define STRING_CMD_INFO_VIRTUAL_TAGS "Virtual tags"
|
||||
#define STRING_CMD_UNDO_USAGE "Reverts the most recent change to a task"
|
||||
#define STRING_CMD_UNDO_MODS "The undo command does not allow further task modification."
|
||||
#define STRING_CMD_STATS_USAGE "Shows task database statistics"
|
||||
@@ -561,6 +562,25 @@
|
||||
#define STRING_CMD_CONFIG_NO_CHANGE "No changes made."
|
||||
#define STRING_CMD_CONFIG_NO_NAME "Specify the name of a config variable to modify."
|
||||
#define STRING_CMD_HCONFIG_USAGE "Lists all supported configuration variables, for completion purposes"
|
||||
#define STRING_CMD_CONTEXT_USAGE "Set and define contexts (default filters)"
|
||||
#define STRING_CMD_CONTEXT_DEF_SUCC "Context '{1}' defined."
|
||||
#define STRING_CMD_CONTEXT_DEF_FAIL "Context '{1}' not defined."
|
||||
#define STRING_CMD_CONTEXT_DEF_USAG "Both context name and its definition must be provided."
|
||||
#define STRING_CMD_CONTEXT_DEF_ABRT "Context definiton aborted."
|
||||
#define STRING_CMD_CONTEXT_DEF_ABRT2 "Filter validation failed: {1}"
|
||||
#define STRING_CMD_CONTEXT_DEF_CONF "The filter '{1}' matches 0 pending tasks. Do you wish to continue?"
|
||||
#define STRING_CMD_CONTEXT_DEL_SUCC "Context '{1}' deleted."
|
||||
#define STRING_CMD_CONTEXT_DEL_FAIL "Context '{1}' not deleted."
|
||||
#define STRING_CMD_CONTEXT_DEL_USAG "Context name needs to be specified."
|
||||
#define STRING_CMD_CONTEXT_LIST_EMPT "No contexts defined."
|
||||
#define STRING_CMD_CONTEXT_SET_NFOU "Context '{1}' not found."
|
||||
#define STRING_CMD_CONTEXT_SET_SUCC "Context '{1}' set. Use 'task context none' to remove."
|
||||
#define STRING_CMD_CONTEXT_SET_FAIL "Context '{1}' not applied."
|
||||
#define STRING_CMD_CONTEXT_SHOW_EMPT "No context is currently applied."
|
||||
#define STRING_CMD_CONTEXT_SHOW "Context '{1}' with filter '{2}' is currently applied."
|
||||
#define STRING_CMD_CONTEXT_NON_SUCC "Context unset."
|
||||
#define STRING_CMD_CONTEXT_NON_FAIL "Context not unset."
|
||||
#define STRING_CMD_HCONTEXT_USAGE "Lists all supported contexts, for completion purposes"
|
||||
#define STRING_CMD_CUSTOM_MISMATCH "There are different numbers of columns and labels for report '{1}'."
|
||||
#define STRING_CMD_CUSTOM_SHOWN "{1} shown"
|
||||
#define STRING_CMD_CUSTOM_COUNT "1 task"
|
||||
@@ -881,10 +901,6 @@
|
||||
#define STRING_TDB2_UNDO_SYNCED "Cannot undo change because the task was already synced. Modify the task instead."
|
||||
#define STRING_TDB2_DIRTY_EXIT "Exiting with unwritten changes to {1}"
|
||||
|
||||
// utf8
|
||||
#define STRING_UTF8_INVALID_CP_REP "Invalid codepoint representation."
|
||||
#define STRING_UTF8_INVALID_CP "Invalid Unicode codepoint."
|
||||
|
||||
// View
|
||||
#define STRING_VIEW_TOO_SMALL "The report has a minimum width of {1} and does not fit in the available width of {2}."
|
||||
|
||||
|
||||
@@ -296,6 +296,7 @@
|
||||
#define STRING_CMD_INFO_UNTIL "Ĝis"
|
||||
#define STRING_CMD_INFO_MODIFICATION "Modifado"
|
||||
#define STRING_CMD_INFO_MODIFIED "Modifado lasta"
|
||||
#define STRING_CMD_INFO_VIRTUAL_TAGS "Virtual tags"
|
||||
#define STRING_CMD_UNDO_USAGE "Malfaras la plej malfrua modifado al tasko"
|
||||
#define STRING_CMD_UNDO_MODS "La komando 'undo' ne permesos, ke oni pli modifus la taskojn."
|
||||
#define STRING_CMD_STATS_USAGE "Montras statistikon de la taska datumbazo"
|
||||
@@ -561,6 +562,25 @@
|
||||
#define STRING_CMD_CONFIG_NO_CHANGE "Ne ŝanĝis nenion."
|
||||
#define STRING_CMD_CONFIG_NO_NAME "Specifu la nomon de agordvariablo, kiun vi volas modifi."
|
||||
#define STRING_CMD_HCONFIG_USAGE "Listigas çiun subtenatan agordan variablon, por motivo memkompletada"
|
||||
#define STRING_CMD_CONTEXT_USAGE "Set and define contexts (default filters)"
|
||||
#define STRING_CMD_CONTEXT_DEF_SUCC "Context '{1}' defined."
|
||||
#define STRING_CMD_CONTEXT_DEF_FAIL "Context '{1}' not defined."
|
||||
#define STRING_CMD_CONTEXT_DEF_USAG "Both context name and its definition must be provided."
|
||||
#define STRING_CMD_CONTEXT_DEF_ABRT "Context definiton aborted."
|
||||
#define STRING_CMD_CONTEXT_DEF_ABRT2 "Filter validation failed: {1}"
|
||||
#define STRING_CMD_CONTEXT_DEF_CONF "The filter '{1}' matches 0 pending tasks. Do you wish to continue?"
|
||||
#define STRING_CMD_CONTEXT_DEL_SUCC "Context '{1}' deleted."
|
||||
#define STRING_CMD_CONTEXT_DEL_FAIL "Context '{1}' not deleted."
|
||||
#define STRING_CMD_CONTEXT_DEL_USAG "Context name needs to be specified."
|
||||
#define STRING_CMD_CONTEXT_LIST_EMPT "No contexts defined."
|
||||
#define STRING_CMD_CONTEXT_SET_NFOU "Context '{1}' not found."
|
||||
#define STRING_CMD_CONTEXT_SET_SUCC "Context '{1}' set. Use 'task context none' to remove."
|
||||
#define STRING_CMD_CONTEXT_SET_FAIL "Context '{1}' not applied."
|
||||
#define STRING_CMD_CONTEXT_SHOW_EMPT "No context is currently applied."
|
||||
#define STRING_CMD_CONTEXT_SHOW "Context '{1}' with filter '{2}' is currently applied."
|
||||
#define STRING_CMD_CONTEXT_NON_SUCC "Context unset."
|
||||
#define STRING_CMD_CONTEXT_NON_FAIL "Context not unset."
|
||||
#define STRING_CMD_HCONTEXT_USAGE "Lists all supported contexts, for completion purposes"
|
||||
#define STRING_CMD_CUSTOM_MISMATCH "La nombroj de kolumnoj kaj de siaj titoloj ne kongruas por raporto '{1}'."
|
||||
#define STRING_CMD_CUSTOM_SHOWN "{1} montritaj"
|
||||
#define STRING_CMD_CUSTOM_COUNT "1 tasko"
|
||||
@@ -881,10 +901,6 @@
|
||||
#define STRING_TDB2_UNDO_SYNCED "Ne povos malfari ŝanĝon ĉar la tasko estis jam sinkronigita. Modifu anstataŭe la taskon."
|
||||
#define STRING_TDB2_DIRTY_EXIT "Eliranta kun neskribitajn ŝanĝojn al {1}"
|
||||
|
||||
// utf8
|
||||
#define STRING_UTF8_INVALID_CP_REP "Nevalida kodpunkta nombro."
|
||||
#define STRING_UTF8_INVALID_CP "Nevalida unikoda kodpunkto."
|
||||
|
||||
// View
|
||||
#define STRING_VIEW_TOO_SMALL "La raporto havas larĝecminimumon {1}, al kio ne konformas la disponebla larĝeco {2}."
|
||||
|
||||
|
||||
@@ -298,6 +298,7 @@
|
||||
#define STRING_CMD_INFO_UNTIL "Hasta"
|
||||
#define STRING_CMD_INFO_MODIFICATION "Modificación"
|
||||
#define STRING_CMD_INFO_MODIFIED "Modificada por última vez"
|
||||
#define STRING_CMD_INFO_VIRTUAL_TAGS "Virtual tags"
|
||||
#define STRING_CMD_UNDO_USAGE "Revierte el cambio más reciente a una tarea"
|
||||
#define STRING_CMD_UNDO_MODS "El comando undo no permite más modificación a la tarea."
|
||||
#define STRING_CMD_STATS_USAGE "Muestra estadísticas de la base de datos de tareas"
|
||||
@@ -570,6 +571,25 @@
|
||||
#define STRING_CMD_CONFIG_NO_CHANGE "No se hicieron cambios."
|
||||
#define STRING_CMD_CONFIG_NO_NAME "Especifique el nombre de una variable de configuración a modificar."
|
||||
#define STRING_CMD_HCONFIG_USAGE "Lista todas las variables de configuración soportadas, a fines de completado"
|
||||
#define STRING_CMD_CONTEXT_USAGE "Set and define contexts (default filters)"
|
||||
#define STRING_CMD_CONTEXT_DEF_SUCC "Context '{1}' defined."
|
||||
#define STRING_CMD_CONTEXT_DEF_FAIL "Context '{1}' not defined."
|
||||
#define STRING_CMD_CONTEXT_DEF_USAG "Both context name and its definition must be provided."
|
||||
#define STRING_CMD_CONTEXT_DEF_ABRT "Context definiton aborted."
|
||||
#define STRING_CMD_CONTEXT_DEF_ABRT2 "Filter validation failed: {1}"
|
||||
#define STRING_CMD_CONTEXT_DEF_CONF "The filter '{1}' matches 0 pending tasks. Do you wish to continue?"
|
||||
#define STRING_CMD_CONTEXT_DEL_SUCC "Context '{1}' deleted."
|
||||
#define STRING_CMD_CONTEXT_DEL_FAIL "Context '{1}' not deleted."
|
||||
#define STRING_CMD_CONTEXT_DEL_USAG "Context name needs to be specified."
|
||||
#define STRING_CMD_CONTEXT_LIST_EMPT "No contexts defined."
|
||||
#define STRING_CMD_CONTEXT_SET_NFOU "Context '{1}' not found."
|
||||
#define STRING_CMD_CONTEXT_SET_SUCC "Context '{1}' set. Use 'task context none' to remove."
|
||||
#define STRING_CMD_CONTEXT_SET_FAIL "Context '{1}' not applied."
|
||||
#define STRING_CMD_CONTEXT_SHOW_EMPT "No context is currently applied."
|
||||
#define STRING_CMD_CONTEXT_SHOW "Context '{1}' with filter '{2}' is currently applied."
|
||||
#define STRING_CMD_CONTEXT_NON_SUCC "Context unset."
|
||||
#define STRING_CMD_CONTEXT_NON_FAIL "Context not unset."
|
||||
#define STRING_CMD_HCONTEXT_USAGE "Lists all supported contexts, for completion purposes"
|
||||
#define STRING_CMD_CUSTOM_MISMATCH "Hay diferente número de columnas y etiquetas para el informe '{1}'."
|
||||
#define STRING_CMD_CUSTOM_SHOWN "{1} mostrada(s)"
|
||||
#define STRING_CMD_CUSTOM_COUNT "1 tarea"
|
||||
@@ -891,10 +911,6 @@
|
||||
#define STRING_TDB2_UNDO_SYNCED "No se puede deshacer el cambio porque la tarea ya ha sido sincronizada. Como alternativa, modifique la tarea."
|
||||
#define STRING_TDB2_DIRTY_EXIT "Exiting with unwritten changes to {1}"
|
||||
|
||||
// utf8
|
||||
#define STRING_UTF8_INVALID_CP_REP "Representación de codepoint no válida."
|
||||
#define STRING_UTF8_INVALID_CP "Codepoint Unicode no válido."
|
||||
|
||||
// View
|
||||
#define STRING_VIEW_TOO_SMALL "El informe tiene una anchura mínima de {1} y no cabe en la disponible, que es {2}."
|
||||
|
||||
|
||||
@@ -296,6 +296,7 @@
|
||||
#define STRING_CMD_INFO_UNTIL "Jusqu'au"
|
||||
#define STRING_CMD_INFO_MODIFICATION "Modification"
|
||||
#define STRING_CMD_INFO_MODIFIED "Dernier modifié"
|
||||
#define STRING_CMD_INFO_VIRTUAL_TAGS "Virtual tags"
|
||||
#define STRING_CMD_UNDO_USAGE "Annule les changements les plus récents sur une tâche"
|
||||
#define STRING_CMD_UNDO_MODS "The undo command does not allow further task modification."
|
||||
#define STRING_CMD_STATS_USAGE "Affiche les statistiques de la base de donnée"
|
||||
@@ -561,6 +562,24 @@
|
||||
#define STRING_CMD_CONFIG_NO_CHANGE "No changes made."
|
||||
#define STRING_CMD_CONFIG_NO_NAME "Specify the name of a config variable to modify."
|
||||
#define STRING_CMD_HCONFIG_USAGE "Lists all supported configuration variables, for completion purposes"
|
||||
#define STRING_CMD_CONTEXT_USAGE "Set and define contexts (default filters)"
|
||||
#define STRING_CMD_CONTEXT_DEF_SUCC "Context '{1}' defined."
|
||||
#define STRING_CMD_CONTEXT_DEF_FAIL "Context '{1}' not defined."
|
||||
#define STRING_CMD_CONTEXT_DEF_USAG "Both context name and its definition must be provided."
|
||||
#define STRING_CMD_CONTEXT_DEF_ABRT "Context definiton aborted."
|
||||
#define STRING_CMD_CONTEXT_DEF_CONF "The filter '{1}' matches 0 pending tasks. Do you wish to continue?"
|
||||
#define STRING_CMD_CONTEXT_DEL_SUCC "Context '{1}' deleted."
|
||||
#define STRING_CMD_CONTEXT_DEL_FAIL "Context '{1}' not deleted."
|
||||
#define STRING_CMD_CONTEXT_DEL_USAG "Context name needs to be specified."
|
||||
#define STRING_CMD_CONTEXT_LIST_EMPT "No contexts defined."
|
||||
#define STRING_CMD_CONTEXT_SET_NFOU "Context '{1}' not found."
|
||||
#define STRING_CMD_CONTEXT_SET_SUCC "Context '{1}' set. Use 'task context none' to remove."
|
||||
#define STRING_CMD_CONTEXT_SET_FAIL "Context '{1}' not applied."
|
||||
#define STRING_CMD_CONTEXT_SHOW_EMPT "No context is currently applied."
|
||||
#define STRING_CMD_CONTEXT_SHOW "Context '{1}' with filter '{2}' is currently applied."
|
||||
#define STRING_CMD_CONTEXT_NON_SUCC "Context unset."
|
||||
#define STRING_CMD_CONTEXT_NON_FAIL "Context not unset."
|
||||
#define STRING_CMD_HCONTEXT_USAGE "Lists all supported contexts, for completion purposes"
|
||||
#define STRING_CMD_CUSTOM_MISMATCH "There are different numbers of columns and labels for report '{1}'."
|
||||
#define STRING_CMD_CUSTOM_SHOWN "{1} affichées"
|
||||
#define STRING_CMD_CUSTOM_COUNT "1 tâche"
|
||||
@@ -881,10 +900,6 @@
|
||||
#define STRING_TDB2_UNDO_SYNCED "Impossible d'annuler les changements car la tâche a déjà été synchronysée. Modifiez plutôt la tâche."
|
||||
#define STRING_TDB2_DIRTY_EXIT "Exiting with unwritten changes to {1}"
|
||||
|
||||
// utf8
|
||||
#define STRING_UTF8_INVALID_CP_REP "Invalid codepoint representation."
|
||||
#define STRING_UTF8_INVALID_CP "Invalid Unicode codepoint."
|
||||
|
||||
// View
|
||||
#define STRING_VIEW_TOO_SMALL "The report has a minimum width of {1} and does not fit in the available width of {2}."
|
||||
|
||||
|
||||
@@ -295,6 +295,7 @@
|
||||
#define STRING_CMD_INFO_UNTIL "Fino a"
|
||||
#define STRING_CMD_INFO_MODIFICATION "Modifica"
|
||||
#define STRING_CMD_INFO_MODIFIED "Ultima modifica"
|
||||
#define STRING_CMD_INFO_VIRTUAL_TAGS "Virtual tags"
|
||||
#define STRING_CMD_UNDO_USAGE "Ritorna alla più recente modifica di un task"
|
||||
#define STRING_CMD_UNDO_MODS "Il comando undo non ammette ulteriori modifiche al task."
|
||||
#define STRING_CMD_STATS_USAGE "Mostra le statistiche sul task"
|
||||
@@ -560,6 +561,25 @@
|
||||
#define STRING_CMD_CONFIG_NO_CHANGE "Nessuna modifica apportata."
|
||||
#define STRING_CMD_CONFIG_NO_NAME "Specificare il nome di una variabile di configurazione da modificare."
|
||||
#define STRING_CMD_HCONFIG_USAGE "Elenca le variabili di configurazione supportate, per autocompletamento"
|
||||
#define STRING_CMD_CONTEXT_USAGE "Set and define contexts (default filters)"
|
||||
#define STRING_CMD_CONTEXT_DEF_SUCC "Context '{1}' defined."
|
||||
#define STRING_CMD_CONTEXT_DEF_FAIL "Context '{1}' not defined."
|
||||
#define STRING_CMD_CONTEXT_DEF_USAG "Both context name and its definition must be provided."
|
||||
#define STRING_CMD_CONTEXT_DEF_ABRT "Context definiton aborted."
|
||||
#define STRING_CMD_CONTEXT_DEF_ABRT2 "Filter validation failed: {1}"
|
||||
#define STRING_CMD_CONTEXT_DEF_CONF "The filter '{1}' matches 0 pending tasks. Do you wish to continue?"
|
||||
#define STRING_CMD_CONTEXT_DEL_SUCC "Context '{1}' deleted."
|
||||
#define STRING_CMD_CONTEXT_DEL_FAIL "Context '{1}' not deleted."
|
||||
#define STRING_CMD_CONTEXT_DEL_USAG "Context name needs to be specified."
|
||||
#define STRING_CMD_CONTEXT_LIST_EMPT "No contexts defined."
|
||||
#define STRING_CMD_CONTEXT_SET_NFOU "Context '{1}' not found."
|
||||
#define STRING_CMD_CONTEXT_SET_SUCC "Context '{1}' set. Use 'task context none' to remove."
|
||||
#define STRING_CMD_CONTEXT_SET_FAIL "Context '{1}' not applied."
|
||||
#define STRING_CMD_CONTEXT_SHOW_EMPT "No context is currently applied."
|
||||
#define STRING_CMD_CONTEXT_SHOW "Context '{1}' with filter '{2}' is currently applied."
|
||||
#define STRING_CMD_CONTEXT_NON_SUCC "Context unset."
|
||||
#define STRING_CMD_CONTEXT_NON_FAIL "Context not unset."
|
||||
#define STRING_CMD_HCONTEXT_USAGE "Lists all supported contexts, for completion purposes"
|
||||
#define STRING_CMD_CUSTOM_MISMATCH "Differente numero di colonne ed etichette per il report '{1}'."
|
||||
#define STRING_CMD_CUSTOM_SHOWN "{1} mostrato"
|
||||
#define STRING_CMD_CUSTOM_COUNT "1 task"
|
||||
@@ -880,10 +900,6 @@
|
||||
#define STRING_TDB2_UNDO_SYNCED "Cannot undo change because the task was already synced. Modify the task instead."
|
||||
#define STRING_TDB2_DIRTY_EXIT "Exiting with unwritten changes to {1}"
|
||||
|
||||
// utf8
|
||||
#define STRING_UTF8_INVALID_CP_REP "Rappresentazione non valida del codepoint."
|
||||
#define STRING_UTF8_INVALID_CP "Codepoint Unicode non valido."
|
||||
|
||||
// View
|
||||
#define STRING_VIEW_TOO_SMALL "Il report ha larghezza minima di {1} e non entra nella larghezza disponibile di {2}."
|
||||
|
||||
|
||||
@@ -296,6 +296,7 @@
|
||||
#define STRING_CMD_INFO_UNTIL "Do"
|
||||
#define STRING_CMD_INFO_MODIFICATION "Modyfikacja"
|
||||
#define STRING_CMD_INFO_MODIFIED "Ostatnio zmodyfikowane"
|
||||
#define STRING_CMD_INFO_VIRTUAL_TAGS "Virtual tags"
|
||||
#define STRING_CMD_UNDO_USAGE "Odwraca ostatnią zmianę w zadaniu"
|
||||
#define STRING_CMD_UNDO_MODS "Polecenie cofnij nie pozwala na późniejsze modyfikacje zadania."
|
||||
#define STRING_CMD_STATS_USAGE "Pokazuje statystyki bazy danych zadań"
|
||||
@@ -561,6 +562,25 @@
|
||||
#define STRING_CMD_CONFIG_NO_CHANGE "Brak zmian."
|
||||
#define STRING_CMD_CONFIG_NO_NAME "Podaj nazwę zmiennej w konfiguracji do zmiany."
|
||||
#define STRING_CMD_HCONFIG_USAGE "Wylistuj wszystkie zmienne konfiguracji."
|
||||
#define STRING_CMD_CONTEXT_USAGE "Set and define contexts (default filters)"
|
||||
#define STRING_CMD_CONTEXT_DEF_SUCC "Context '{1}' defined."
|
||||
#define STRING_CMD_CONTEXT_DEF_FAIL "Context '{1}' not defined."
|
||||
#define STRING_CMD_CONTEXT_DEF_USAG "Both context name and its definition must be provided."
|
||||
#define STRING_CMD_CONTEXT_DEF_ABRT "Context definiton aborted."
|
||||
#define STRING_CMD_CONTEXT_DEF_ABRT2 "Filter validation failed: {1}"
|
||||
#define STRING_CMD_CONTEXT_DEF_CONF "The filter '{1}' matches 0 pending tasks. Do you wish to continue?"
|
||||
#define STRING_CMD_CONTEXT_DEL_SUCC "Context '{1}' deleted."
|
||||
#define STRING_CMD_CONTEXT_DEL_FAIL "Context '{1}' not deleted."
|
||||
#define STRING_CMD_CONTEXT_DEL_USAG "Context name needs to be specified."
|
||||
#define STRING_CMD_CONTEXT_LIST_EMPT "No contexts defined."
|
||||
#define STRING_CMD_CONTEXT_SET_NFOU "Context '{1}' not found."
|
||||
#define STRING_CMD_CONTEXT_SET_SUCC "Context '{1}' set. Use 'task context none' to remove."
|
||||
#define STRING_CMD_CONTEXT_SET_FAIL "Context '{1}' not applied."
|
||||
#define STRING_CMD_CONTEXT_SHOW_EMPT "No context is currently applied."
|
||||
#define STRING_CMD_CONTEXT_SHOW "Context '{1}' with filter '{2}' is currently applied."
|
||||
#define STRING_CMD_CONTEXT_NON_SUCC "Context unset."
|
||||
#define STRING_CMD_CONTEXT_NON_FAIL "Context not unset."
|
||||
#define STRING_CMD_HCONTEXT_USAGE "Lists all supported contexts, for completion purposes"
|
||||
#define STRING_CMD_CUSTOM_MISMATCH "Liczba kolumn i nagłówków nie zgadza się dla raportu '{1}'."
|
||||
#define STRING_CMD_CUSTOM_SHOWN "{1} pokazanych"
|
||||
#define STRING_CMD_CUSTOM_COUNT "1 zadanie"
|
||||
@@ -881,10 +901,6 @@
|
||||
#define STRING_TDB2_UNDO_SYNCED "Nie można cofnąć zmian ponieważ zadanie zostało zsynchronizowane. Zmodyfikuj zadanie."
|
||||
#define STRING_TDB2_DIRTY_EXIT "Zamykanie z niezapisanymi zmianami w {1}"
|
||||
|
||||
// utf8
|
||||
#define STRING_UTF8_INVALID_CP_REP "Niepoprawna reprezentacja znaku."
|
||||
#define STRING_UTF8_INVALID_CP "Niepoprawny znak Unicode."
|
||||
|
||||
// View
|
||||
#define STRING_VIEW_TOO_SMALL "Raport ma minimalną szerokość {1} i nie mieści się w dostępnej przestrzeni {2}."
|
||||
|
||||
|
||||
@@ -296,6 +296,7 @@
|
||||
#define STRING_CMD_INFO_UNTIL "Até"
|
||||
#define STRING_CMD_INFO_MODIFICATION "Modificação"
|
||||
#define STRING_CMD_INFO_MODIFIED "Última modificação"
|
||||
#define STRING_CMD_INFO_VIRTUAL_TAGS "Virtual tags"
|
||||
#define STRING_CMD_UNDO_USAGE "Reverte a mais recente modificação a uma tarefa"
|
||||
#define STRING_CMD_UNDO_MODS "O comando undo não permite outras modificações simultâneas."
|
||||
#define STRING_CMD_STATS_USAGE "Exibe estatísticas da base de dados de tarefas"
|
||||
@@ -561,6 +562,25 @@
|
||||
#define STRING_CMD_CONFIG_NO_CHANGE "Nenhuma alteração efectuada."
|
||||
#define STRING_CMD_CONFIG_NO_NAME "Especifique o nome da configuração a modificar."
|
||||
#define STRING_CMD_HCONFIG_USAGE "Lista todas as configurações suportadas, para fins de terminação automática"
|
||||
#define STRING_CMD_CONTEXT_USAGE "Set and define contexts (default filters)"
|
||||
#define STRING_CMD_CONTEXT_DEF_SUCC "Context '{1}' defined."
|
||||
#define STRING_CMD_CONTEXT_DEF_FAIL "Context '{1}' not defined."
|
||||
#define STRING_CMD_CONTEXT_DEF_USAG "Both context name and its definition must be provided."
|
||||
#define STRING_CMD_CONTEXT_DEF_ABRT "Context definiton aborted."
|
||||
#define STRING_CMD_CONTEXT_DEF_ABRT2 "Filter validation failed: {1}"
|
||||
#define STRING_CMD_CONTEXT_DEF_CONF "The filter '{1}' matches 0 pending tasks. Do you wish to continue?"
|
||||
#define STRING_CMD_CONTEXT_DEL_SUCC "Context '{1}' deleted."
|
||||
#define STRING_CMD_CONTEXT_DEL_FAIL "Context '{1}' not deleted."
|
||||
#define STRING_CMD_CONTEXT_DEL_USAG "Context name needs to be specified."
|
||||
#define STRING_CMD_CONTEXT_LIST_EMPT "No contexts defined."
|
||||
#define STRING_CMD_CONTEXT_SET_NFOU "Context '{1}' not found."
|
||||
#define STRING_CMD_CONTEXT_SET_SUCC "Context '{1}' set. Use 'task context none' to remove."
|
||||
#define STRING_CMD_CONTEXT_SET_FAIL "Context '{1}' not applied."
|
||||
#define STRING_CMD_CONTEXT_SHOW_EMPT "No context is currently applied."
|
||||
#define STRING_CMD_CONTEXT_SHOW "Context '{1}' with filter '{2}' is currently applied."
|
||||
#define STRING_CMD_CONTEXT_NON_SUCC "Context unset."
|
||||
#define STRING_CMD_CONTEXT_NON_FAIL "Context not unset."
|
||||
#define STRING_CMD_HCONTEXT_USAGE "Lists all supported contexts, for completion purposes"
|
||||
#define STRING_CMD_CUSTOM_MISMATCH "O número de colunas e de rótulos não é o mesmo no relatório '{1}'."
|
||||
#define STRING_CMD_CUSTOM_SHOWN "{1} visiveis"
|
||||
#define STRING_CMD_CUSTOM_COUNT "1 tarefa"
|
||||
@@ -881,10 +901,6 @@
|
||||
#define STRING_TDB2_UNDO_SYNCED "Não é possível reverter a alteração porque a tarefa já foi syncronizada. Em vez disso modifique a tarefa."
|
||||
#define STRING_TDB2_DIRTY_EXIT "Saindo com modificações por gravar de {1}"
|
||||
|
||||
// utf8
|
||||
#define STRING_UTF8_INVALID_CP_REP "Representação de 'codepoint' inválida."
|
||||
#define STRING_UTF8_INVALID_CP "'Codepoint' Unicode inválido."
|
||||
|
||||
// View
|
||||
#define STRING_VIEW_TOO_SMALL "O relatório tem uma largura mínima de {1} e não cabe na largura disponível {2}."
|
||||
|
||||
|
||||
@@ -160,54 +160,9 @@ std::string legacyCheckForDeprecatedColumns ()
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void legacyAttributeMap (std::string& name)
|
||||
{
|
||||
// TW-1274
|
||||
// TW-1274, 2.4.0
|
||||
if (name == "modification")
|
||||
name = "modified";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void legacyValueMap (const std::string& name, std::string& value)
|
||||
{
|
||||
// 2014-07-03: One-time initialization value mapping.
|
||||
static std::map <std::string, std::string> mapping;
|
||||
if (mapping.size () == 0)
|
||||
{
|
||||
mapping["hrs"] = "hours";
|
||||
mapping["hrs"] = "hours";
|
||||
mapping["hr"] = "hours";
|
||||
mapping["mins"] = "minutes";
|
||||
mapping["mnths"] = "months";
|
||||
mapping["mths"] = "months";
|
||||
mapping["mth"] = "months";
|
||||
mapping["mos"] = "months";
|
||||
mapping["m"] = "months";
|
||||
mapping["qrtrs"] = "quarters";
|
||||
mapping["qtrs"] = "quarters";
|
||||
mapping["qtr"] = "quarters";
|
||||
mapping["secs"] = "seconds";
|
||||
mapping["sec"] = "seconds";
|
||||
mapping["s"] = "seconds";
|
||||
mapping["wks"] = "weeks";
|
||||
mapping["wk"] = "weeks";
|
||||
mapping["yrs"] = "years";
|
||||
mapping["yr"] = "years";
|
||||
}
|
||||
|
||||
if (name == "recur")
|
||||
{
|
||||
std::size_t letter = value.find_first_not_of ("0123456789.");
|
||||
if (letter == std::string::npos)
|
||||
letter = 0;
|
||||
|
||||
std::map <std::string, std::string>::iterator i = mapping.find (value.substr (letter));
|
||||
if (i != mapping.end ())
|
||||
{
|
||||
if (letter)
|
||||
value = value.substr (0, letter) + i->second;
|
||||
else
|
||||
value = i->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -86,7 +86,6 @@ std::string legacyCheckForDeprecatedColor ();
|
||||
std::string legacyCheckForDeprecatedVariables ();
|
||||
std::string legacyCheckForDeprecatedColumns ();
|
||||
void legacyAttributeMap (std::string&);
|
||||
void legacyValueMap (const std::string&, std::string&);
|
||||
|
||||
// list template
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -424,14 +424,6 @@ std::string lowerCase (const std::string& input)
|
||||
return output;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string upperCase (const std::string& input)
|
||||
{
|
||||
std::string output = input;
|
||||
std::transform (output.begin (), output.end (), output.begin (), toupper);
|
||||
return output;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string ucFirst (const std::string& input)
|
||||
{
|
||||
|
||||
@@ -45,7 +45,6 @@ void join (std::string&, const std::string&, const std::vector<std::string>&);
|
||||
void join (std::string&, const std::string&, const std::vector<int>&);
|
||||
std::string commify (const std::string&);
|
||||
std::string lowerCase (const std::string&);
|
||||
std::string upperCase (const std::string&);
|
||||
std::string ucFirst (const std::string&);
|
||||
const std::string str_replace (std::string&, const std::string&, const std::string&);
|
||||
const std::string str_replace (const std::string&, const std::string&, const std::string&);
|
||||
|
||||
13
src/utf8.cpp
13
src/utf8.cpp
@@ -26,9 +26,7 @@
|
||||
|
||||
#include <cmake.h>
|
||||
#include <string>
|
||||
#include <text.h>
|
||||
#include <utf8.h>
|
||||
#include <i18n.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Converts '0' -> 0
|
||||
@@ -66,8 +64,6 @@ unsigned int utf8_codepoint (const std::string& input)
|
||||
XDIGIT (input[2]) << 4 |
|
||||
XDIGIT (input[3]);
|
||||
}
|
||||
else
|
||||
throw std::string (STRING_UTF8_INVALID_CP_REP);
|
||||
|
||||
return codepoint;
|
||||
}
|
||||
@@ -117,13 +113,12 @@ unsigned int utf8_next_char (const std::string& input, std::string::size_type& i
|
||||
// http://en.wikipedia.org/wiki/UTF-8
|
||||
std::string utf8_character (unsigned int codepoint)
|
||||
{
|
||||
char sequence[5];
|
||||
char sequence[5] = {0};
|
||||
|
||||
// 0xxxxxxx -> 0xxxxxxx
|
||||
if (codepoint < 0x80)
|
||||
{
|
||||
sequence[0] = codepoint;
|
||||
sequence[1] = 0;
|
||||
}
|
||||
|
||||
// 00000yyy yyxxxxxx -> 110yyyyy 10xxxxxx
|
||||
@@ -131,7 +126,6 @@ std::string utf8_character (unsigned int codepoint)
|
||||
{
|
||||
sequence[0] = 0xC0 | (codepoint & 0x7C0) >> 6;
|
||||
sequence[1] = 0x80 | (codepoint & 0x3F);
|
||||
sequence[2] = 0;
|
||||
}
|
||||
|
||||
// zzzzyyyy yyxxxxxx -> 1110zzzz 10yyyyyy 10xxxxxx
|
||||
@@ -140,7 +134,6 @@ std::string utf8_character (unsigned int codepoint)
|
||||
sequence[0] = 0xE0 | (codepoint & 0xF000) >> 12;
|
||||
sequence[1] = 0x80 | (codepoint & 0xFC0) >> 6;
|
||||
sequence[2] = 0x80 | (codepoint & 0x3F);
|
||||
sequence[3] = 0;
|
||||
}
|
||||
|
||||
// 000wwwzz zzzzyyyy yyxxxxxx -> 11110www 10zzzzzz 10yyyyyy 10xxxxxx
|
||||
@@ -150,12 +143,8 @@ std::string utf8_character (unsigned int codepoint)
|
||||
sequence[1] = 0x80 | (codepoint & 0x03F000) >> 12;
|
||||
sequence[2] = 0x80 | (codepoint & 0x0FC0) >> 6;
|
||||
sequence[3] = 0x80 | (codepoint & 0x3F);
|
||||
sequence[4] = 0;
|
||||
}
|
||||
else
|
||||
throw std::string (STRING_UTF8_INVALID_CP);
|
||||
|
||||
sequence[4] = '\0';
|
||||
return std::string (sequence);
|
||||
}
|
||||
|
||||
|
||||
@@ -299,9 +299,11 @@ int execute (
|
||||
|
||||
if (dup2 (pin[0], STDIN_FILENO) == -1)
|
||||
throw std::string (std::strerror (errno));
|
||||
close (pin[0]);
|
||||
|
||||
if (dup2 (pout[1], STDOUT_FILENO) == -1)
|
||||
throw std::string (std::strerror (errno));
|
||||
close (pout[1]);
|
||||
|
||||
char** argv = new char* [args.size () + 2];
|
||||
argv[0] = (char*) executable.c_str ();
|
||||
|
||||
1
test/.gitignore
vendored
1
test/.gitignore
vendored
@@ -53,7 +53,6 @@ variant_partial.t
|
||||
variant_subtract.t
|
||||
variant_xor.t
|
||||
view.t
|
||||
width.t
|
||||
|
||||
json_test
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ include_directories (${CMAKE_SOURCE_DIR}
|
||||
|
||||
set (test_SRCS autocomplete.t color.t config.t date.t directory.t dom.t
|
||||
file.t i18n.t json.t list.t msg.t nibbler.t path.t rx.t t.t t2.t
|
||||
t3.t tdb2.t text.t utf8.t util.t view.t width.t json_test
|
||||
iso8601d.t iso8601p.t duration.t lexer.t variant_add.t
|
||||
t3.t tdb2.t text.t utf8.t util.t view.t json_test lexer.t
|
||||
iso8601d.t iso8601p.t duration.t variant_add.t
|
||||
variant_and.t variant_cast.t variant_divide.t variant_equal.t
|
||||
variant_exp.t variant_gt.t variant_gte.t variant_inequal.t
|
||||
variant_lt.t variant_lte.t variant_match.t variant_math.t
|
||||
|
||||
126
test/alias.t
126
test/alias.t
@@ -1,68 +1,80 @@
|
||||
#! /usr/bin/env perl
|
||||
################################################################################
|
||||
##
|
||||
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
##
|
||||
## Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
## of this software and associated documentation files (the "Software"), to deal
|
||||
## in the Software without restriction, including without limitation the rights
|
||||
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
## copies of the Software, and to permit persons to whom the Software is
|
||||
## furnished to do so, subject to the following conditions:
|
||||
##
|
||||
## The above copyright notice and this permission notice shall be included
|
||||
## in all copies or substantial portions of the Software.
|
||||
##
|
||||
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
## SOFTWARE.
|
||||
##
|
||||
## http://www.opensource.org/licenses/mit-license.php
|
||||
##
|
||||
################################################################################
|
||||
#!/usr/bin/env python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
###############################################################################
|
||||
#
|
||||
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included
|
||||
# in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
# http://www.opensource.org/licenses/mit-license.php
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 5;
|
||||
import sys
|
||||
import os
|
||||
import unittest
|
||||
# Ensure python finds the local simpletap module
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
# Ensure environment has no influence.
|
||||
delete $ENV{'TASKDATA'};
|
||||
delete $ENV{'TASKRC'};
|
||||
from basetest import Task, TestCase
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'alias.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"alias.foo=_projects\n",
|
||||
"alias.bar=foo\n",
|
||||
"alias.baz=bar\n",
|
||||
"alias.qux=baz\n";
|
||||
close $fh;
|
||||
}
|
||||
|
||||
# Add a task with a certain project, then access that task via aliases.
|
||||
qx{../src/task rc:alias.rc add project:ALIAS foo 2>&1};
|
||||
class TestAlias(TestCase):
|
||||
def setUp(self):
|
||||
"""Executed before each test in the class"""
|
||||
# Used to initialize objects that should be re-initialized or
|
||||
# re-created for each individual test
|
||||
self.t = Task()
|
||||
|
||||
my $output = qx{../src/task rc:alias.rc _projects 2>&1};
|
||||
like ($output, qr/ALIAS/, 'task _projects -> ALIAS');
|
||||
self.t.config("alias.foo", "_projects")
|
||||
self.t.config("alias.bar", "foo")
|
||||
self.t.config("alias.baz", "bar")
|
||||
self.t.config("alias.qux", "baz")
|
||||
|
||||
$output = qx{../src/task rc:alias.rc qux 2>&1};
|
||||
like ($output, qr/ALIAS/, 'task foo -> _projects -> ALIAS');
|
||||
def test_alias_to_project(self):
|
||||
"""Access a project via aliases"""
|
||||
|
||||
$output = qx{../src/task rc:alias.rc bar 2>&1};
|
||||
like ($output, qr/ALIAS/, 'task bar -> foo -> _projects -> ALIAS');
|
||||
expected = "ALIAS"
|
||||
self.t(("add", "project:{0}".format(expected), "foo"))
|
||||
|
||||
$output = qx{../src/task rc:alias.rc baz 2>&1};
|
||||
like ($output, qr/ALIAS/, 'task baz -> bar -> foo -> _projects -> ALIAS');
|
||||
code, out, err = self.t(("_projects",))
|
||||
self.assertIn(expected, out,
|
||||
msg="task _projects -> ALIAS")
|
||||
|
||||
$output = qx{../src/task rc:alias.rc qux 2>&1};
|
||||
like ($output, qr/ALIAS/, 'task qux -> baz -> bar -> foo -> _projects -> ALIAS');
|
||||
code, out, err = self.t(("foo",))
|
||||
self.assertIn(expected, out,
|
||||
msg="task foo -> _projects > ALIAS")
|
||||
|
||||
# Cleanup.
|
||||
unlink qw(pending.data completed.data undo.data backlog.data alias.rc);
|
||||
exit 0;
|
||||
code, out, err = self.t(("bar",))
|
||||
self.assertIn(expected, out,
|
||||
msg="task bar -> foo > _projects > ALIAS")
|
||||
|
||||
code, out, err = self.t(("baz",))
|
||||
self.assertIn(expected, out,
|
||||
msg="task baz -> bar > foo > _projects > ALIAS")
|
||||
|
||||
code, out, err = self.t(("qux",))
|
||||
self.assertIn(expected, out,
|
||||
msg="task qux -> baz > bar > foo > _projects > ALIAS")
|
||||
|
||||
if __name__ == "__main__":
|
||||
from simpletap import TAPTestRunner
|
||||
unittest.main(testRunner=TAPTestRunner())
|
||||
|
||||
# vim: ai sts=4 et sw=4
|
||||
|
||||
244
test/annotate.t
244
test/annotate.t
@@ -1,121 +1,135 @@
|
||||
#! /usr/bin/env perl
|
||||
################################################################################
|
||||
##
|
||||
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
##
|
||||
## Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
## of this software and associated documentation files (the "Software"), to deal
|
||||
## in the Software without restriction, including without limitation the rights
|
||||
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
## copies of the Software, and to permit persons to whom the Software is
|
||||
## furnished to do so, subject to the following conditions:
|
||||
##
|
||||
## The above copyright notice and this permission notice shall be included
|
||||
## in all copies or substantial portions of the Software.
|
||||
##
|
||||
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
## SOFTWARE.
|
||||
##
|
||||
## http://www.opensource.org/licenses/mit-license.php
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 22;
|
||||
|
||||
# Ensure environment has no influence.
|
||||
delete $ENV{'TASKDATA'};
|
||||
delete $ENV{'TASKRC'};
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'annotate.rc')
|
||||
{
|
||||
# Note: Use 'rrr' to guarantee a unique report name. Using 'r' conflicts
|
||||
# with 'recurring'.
|
||||
print $fh "data.location=.\n",
|
||||
"confirmation=off\n",
|
||||
"report.rrr.description=rrr\n",
|
||||
"report.rrr.columns=id,description\n",
|
||||
"report.rrr.sort=id+\n",
|
||||
"color=off\n",
|
||||
"dateformat=m/d/Y\n";
|
||||
close $fh;
|
||||
}
|
||||
|
||||
# Add four tasks, annotate one three times, one twice, one just once and one none.
|
||||
qx{../src/task rc:annotate.rc add one 2>&1};
|
||||
qx{../src/task rc:annotate.rc add two 2>&1};
|
||||
qx{../src/task rc:annotate.rc add three 2>&1};
|
||||
qx{../src/task rc:annotate.rc add four 2>&1};
|
||||
qx{../src/task rc:annotate.rc 1 annotate foo1 2>&1};
|
||||
qx{../src/task rc:annotate.rc 1 annotate foo2 2>&1};
|
||||
qx{../src/task rc:annotate.rc 1 annotate foo3 2>&1};
|
||||
qx{../src/task rc:annotate.rc 2 annotate bar1 2>&1};
|
||||
qx{../src/task rc:annotate.rc 2 annotate bar2 2>&1};
|
||||
qx{../src/task rc:annotate.rc 3 annotate baz1 2>&1};
|
||||
|
||||
my $output = qx{../src/task rc:annotate.rc rrr 2>&1};
|
||||
|
||||
# ID Description
|
||||
# -- -------------------------------
|
||||
# 1 one
|
||||
# 3/24/2009 foo1
|
||||
# 3/24/2009 foo2
|
||||
# 3/24/2009 foo3
|
||||
# 2 two
|
||||
# 3/24/2009 bar1
|
||||
# 3/24/2009 bar2
|
||||
# 3 three
|
||||
# 3/24/2009 baz1
|
||||
# 4 four
|
||||
#!/usr/bin/env python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
###############################################################################
|
||||
#
|
||||
# 4 tasks
|
||||
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included
|
||||
# in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
# http://www.opensource.org/licenses/mit-license.php
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
like ($output, qr/1 one/, 'task 1'); # 2
|
||||
like ($output, qr/2 two/, 'task 2');
|
||||
like ($output, qr/3 three/, 'task 3');
|
||||
like ($output, qr/4 four/, 'task 4');
|
||||
like ($output, qr/one.+\d{1,2}\/\d{1,2}\/\d{4}\s+foo1/ms, 'full - first annotation task 1');
|
||||
like ($output, qr/foo1.+\d{1,2}\/\d{1,2}\/\d{4}\s+foo2/ms, 'full - second annotation task 1');
|
||||
like ($output, qr/foo2.+\d{1,2}\/\d{1,2}\/\d{4}\s+foo3/ms, 'full - third annotation task 1');
|
||||
like ($output, qr/two.+\d{1,2}\/\d{1,2}\/\d{4}\s+bar1/ms, 'full - first annotation task 2');
|
||||
like ($output, qr/bar1.+\d{1,2}\/\d{1,2}\/\d{4}\s+bar2/ms, 'full - second annotation task 2');
|
||||
like ($output, qr/three.+\d{1,2}\/\d{1,2}\/\d{4}\s+baz1/ms,'full - first annotation task 3');
|
||||
like ($output, qr/4 tasks/, 'count');
|
||||
import sys
|
||||
import os
|
||||
import unittest
|
||||
# Ensure python finds the local simpletap module
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
if (open my $fh, '>', 'annotate2.rc')
|
||||
{
|
||||
# Note: Use 'rrr' to guarantee a unique report name. Using 'r' conflicts
|
||||
# with 'recurring'.
|
||||
print $fh "data.location=.\n",
|
||||
"confirmation=off\n",
|
||||
"report.rrr.description=rrr\n",
|
||||
"report.rrr.columns=id,description\n",
|
||||
"report.rrr.sort=id+\n",
|
||||
"dateformat.annotation=yMD HNS\n";
|
||||
close $fh;
|
||||
}
|
||||
from basetest import Task, TestCase
|
||||
|
||||
$output = qx{../src/task rc:annotate2.rc rrr 2>&1};
|
||||
like ($output, qr/1 one/, 'task 1'); # 14
|
||||
like ($output, qr/2 two/, 'task 2');
|
||||
like ($output, qr/3 three/, 'task 3');
|
||||
like ($output, qr/4 four/, 'task 4');
|
||||
like ($output, qr/one.+\d{1,6}\s+\d{1,6}\s+foo1/ms, 'dateformat - first annotation task 1'); #18
|
||||
like ($output, qr/foo1.+\d{1,6}\s+\d{1,6}\s+foo2/ms, 'dateformat - second annotation task 1');
|
||||
like ($output, qr/foo2.+\d{1,6}\s+\d{1,6}\s+foo3/ms, 'dateformat - third annotation task 1');
|
||||
like ($output, qr/two.+\d{1,6}\s+\d{1,6}\s+bar1/ms, 'dateformat - first annotation task 2');
|
||||
like ($output, qr/bar1.+\d{1,6}\s+\d{1,6}\s+bar2/ms, 'dateformat - second annotation task 2');
|
||||
like ($output, qr/three.+\d{1,6}\s+\d{1,6}\s+baz1/ms,'dateformat - first annotation task 3');
|
||||
like ($output, qr/4 tasks/, 'count');
|
||||
|
||||
# Cleanup.
|
||||
unlink qw(pending.data completed.data undo.data backlog.data annotate.rc annotate2.rc);
|
||||
exit 0;
|
||||
class TestAnnotate(TestCase):
|
||||
def setUp(self):
|
||||
self.t = Task()
|
||||
|
||||
# ID Description
|
||||
# -- -------------------------------
|
||||
# 1 one
|
||||
# 3/24/2009 foo1
|
||||
# 3/24/2009 foo2
|
||||
# 3/24/2009 foo3
|
||||
# 2 two
|
||||
# 3/24/2009 bar1
|
||||
# 3/24/2009 bar2
|
||||
# 3 three
|
||||
# 3/24/2009 baz1
|
||||
# 4 four
|
||||
#
|
||||
# 4 tasks
|
||||
|
||||
self.t(("add", "one"))
|
||||
self.t(("add", "two"))
|
||||
self.t(("add", "three"))
|
||||
self.t(("add", "four"))
|
||||
self.t(("1", "annotate", "foo1"))
|
||||
self.t(("1", "annotate", "foo2"))
|
||||
self.t(("1", "annotate", "foo3"))
|
||||
self.t(("2", "annotate", "bar1"))
|
||||
self.t(("2", "annotate", "bar2"))
|
||||
self.t(("3", "annotate", "baz1"))
|
||||
|
||||
def assertTasksExist(self, out):
|
||||
self.assertIn("1 one", out)
|
||||
self.assertIn("2 two", out)
|
||||
self.assertIn("3 three", out)
|
||||
self.assertIn("4 four", out)
|
||||
self.assertIn("4 tasks", out)
|
||||
|
||||
def test_annotate(self):
|
||||
"""Testing annotations in reports"""
|
||||
|
||||
# NOTE: Use 'rrr' to guarantee a unique report name. Using 'r'
|
||||
# conflicts with 'recurring'.
|
||||
self.t.config("report.rrr.description", "rrr")
|
||||
self.t.config("report.rrr.columns", "id,description")
|
||||
self.t.config("report.rrr.sort", "id+")
|
||||
self.t.config("dateformat", "m/d/Y")
|
||||
self.t.config("color", "off")
|
||||
|
||||
code, out, err = self.t(("rrr",))
|
||||
|
||||
self.assertTasksExist(out)
|
||||
|
||||
self.assertRegexpMatches(out, "one\n.+\d{1,2}/\d{1,2}/\d{4}\s+foo1",
|
||||
msg='full - first annotation task 1')
|
||||
self.assertRegexpMatches(out, "foo1\n.+\d{1,2}/\d{1,2}/\d{4}\s+foo2",
|
||||
msg='full - first annotation task 1')
|
||||
self.assertRegexpMatches(out, "foo2\n.+\d{1,2}/\d{1,2}/\d{4}\s+foo3",
|
||||
msg='full - first annotation task 1')
|
||||
self.assertRegexpMatches(out, "two\n.+\d{1,2}/\d{1,2}/\d{4}\s+bar1",
|
||||
msg='full - first annotation task 1')
|
||||
self.assertRegexpMatches(out, "bar1\n.+\d{1,2}/\d{1,2}/\d{4}\s+bar2",
|
||||
msg='full - first annotation task 1')
|
||||
self.assertRegexpMatches(out, "three\n.+\d{1,2}/\d{1,2}/\d{4}\s+baz1",
|
||||
msg='full - first annotation task 1')
|
||||
|
||||
def test_annotate_dateformat(self):
|
||||
"""Testing annotations in reports using dateformat.annotation"""
|
||||
|
||||
# NOTE: Use 'rrr' to guarantee a unique report name. Using 'r'
|
||||
# conflicts with 'recurring'.
|
||||
self.t.config("report.rrr.description", "rrr")
|
||||
self.t.config("report.rrr.columns", "id,description")
|
||||
self.t.config("report.rrr.sort", "id+")
|
||||
self.t.config("dateformat.annotation", "yMD HNS")
|
||||
|
||||
code, out, err = self.t(("rrr",))
|
||||
|
||||
self.assertTasksExist(out)
|
||||
|
||||
self.assertRegexpMatches(out, "one\n.+\d{1,6}\s+\d{1,6}\s+foo1",
|
||||
msg="dateformat - first annotation task 1")
|
||||
self.assertRegexpMatches(out, "foo1\n.+\d{1,6}\s+\d{1,6}\s+foo2",
|
||||
msg="dateformat - second annotation task 1")
|
||||
self.assertRegexpMatches(out, "foo2\n.+\d{1,6}\s+\d{1,6}\s+foo3",
|
||||
msg="dateformat - third annotation task 1")
|
||||
self.assertRegexpMatches(out, "two\n.+\d{1,6}\s+\d{1,6}\s+bar1",
|
||||
msg="dateformat - first annotation task 2")
|
||||
self.assertRegexpMatches(out, "bar1\n.+\d{1,6}\s+\d{1,6}\s+bar2",
|
||||
msg="dateformat - second annotation task 2")
|
||||
self.assertRegexpMatches(out, "three\n.+\d{1,6}\s+\d{1,6}\s+baz1",
|
||||
msg="dateformat - first annotation task 3")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from simpletap import TAPTestRunner
|
||||
unittest.main(testRunner=TAPTestRunner())
|
||||
|
||||
# vim: ai sts=4 et sw=4
|
||||
|
||||
116
test/append.t
116
test/append.t
@@ -1,59 +1,71 @@
|
||||
#! /usr/bin/env perl
|
||||
################################################################################
|
||||
##
|
||||
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
##
|
||||
## Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
## of this software and associated documentation files (the "Software"), to deal
|
||||
## in the Software without restriction, including without limitation the rights
|
||||
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
## copies of the Software, and to permit persons to whom the Software is
|
||||
## furnished to do so, subject to the following conditions:
|
||||
##
|
||||
## The above copyright notice and this permission notice shall be included
|
||||
## in all copies or substantial portions of the Software.
|
||||
##
|
||||
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
## SOFTWARE.
|
||||
##
|
||||
## http://www.opensource.org/licenses/mit-license.php
|
||||
##
|
||||
################################################################################
|
||||
#!/usr/bin/env python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
###############################################################################
|
||||
#
|
||||
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included
|
||||
# in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
# http://www.opensource.org/licenses/mit-license.php
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 4;
|
||||
import sys
|
||||
import os
|
||||
import unittest
|
||||
# Ensure python finds the local simpletap module
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
# Ensure environment has no influence.
|
||||
delete $ENV{'TASKDATA'};
|
||||
delete $ENV{'TASKRC'};
|
||||
from basetest import Task, TestCase
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'append.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"confirmation=off\n";
|
||||
close $fh;
|
||||
}
|
||||
|
||||
# Add a task, then append more description.
|
||||
qx{../src/task rc:append.rc add foo 2>&1};
|
||||
my $output = qx{../src/task rc:append.rc 1 append bar 2>&1};
|
||||
like ($output, qr/^Appended 1 task.$/m, 'append worked');
|
||||
$output = qx{../src/task rc:append.rc info 1 2>&1};
|
||||
like ($output, qr/Description\s+foo\sbar\n/, 'append worked');
|
||||
class TestAppend(TestCase):
|
||||
def setUp(self):
|
||||
"""Executed before each test in the class"""
|
||||
self.t = Task()
|
||||
self.t(("add", "foo"))
|
||||
|
||||
# Should cause an error when nothing is appended.
|
||||
$output = qx{../src/task rc:append.rc 1 append 2>&1};
|
||||
like ($output, qr/^Additional text must be provided.$/m, 'blank append failed');
|
||||
unlike ($output, qr/^Appended 1 task.$/, 'blank append failed');
|
||||
def test_append(self):
|
||||
"""Add a task and then append more description"""
|
||||
code, out, err = self.t(("1", "append", "bar"))
|
||||
|
||||
# Cleanup.
|
||||
unlink qw(pending.data completed.data undo.data backlog.data append.rc);
|
||||
exit 0;
|
||||
expected = "Appended 1 task."
|
||||
self.assertIn(expected, out)
|
||||
|
||||
code, out, err = self.t(("info", "1"))
|
||||
|
||||
expected = "Description\s+foo\sbar\n"
|
||||
self.assertRegexpMatches(out, expected)
|
||||
|
||||
def test_append_error_on_empty(self):
|
||||
"""Should cause an error when nothing is appended"""
|
||||
code, out, err = self.t.runError(("1", "append"))
|
||||
|
||||
expected = "Additional text must be provided."
|
||||
self.assertIn(expected, err)
|
||||
|
||||
notexpected = "Appended 1 task."
|
||||
self.assertNotIn(notexpected, out)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from simpletap import TAPTestRunner
|
||||
unittest.main(testRunner=TAPTestRunner())
|
||||
|
||||
# vim: ai sts=4 et sw=4
|
||||
|
||||
125
test/args.1.t
125
test/args.1.t
@@ -1,72 +1,73 @@
|
||||
#! /usr/bin/env perl
|
||||
################################################################################
|
||||
##
|
||||
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
##
|
||||
## Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
## of this software and associated documentation files (the "Software"), to deal
|
||||
## in the Software without restriction, including without limitation the rights
|
||||
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
## copies of the Software, and to permit persons to whom the Software is
|
||||
## furnished to do so, subject to the following conditions:
|
||||
##
|
||||
## The above copyright notice and this permission notice shall be included
|
||||
## in all copies or substantial portions of the Software.
|
||||
##
|
||||
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
## SOFTWARE.
|
||||
##
|
||||
## http://www.opensource.org/licenses/mit-license.php
|
||||
##
|
||||
################################################################################
|
||||
#!/usr/bin/env python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
###############################################################################
|
||||
#
|
||||
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included
|
||||
# in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
# http://www.opensource.org/licenses/mit-license.php
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 8;
|
||||
import sys
|
||||
import os
|
||||
import unittest
|
||||
# Ensure python finds the local simpletap module
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
# Ensure environment has no influence.
|
||||
delete $ENV{'TASKDATA'};
|
||||
delete $ENV{'TASKRC'};
|
||||
from basetest import Task, TestCase
|
||||
|
||||
use File::Basename;
|
||||
my $ut = basename ($0);
|
||||
my $rc = $ut . '.rc';
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', $rc)
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"confirmation=off\n";
|
||||
close $fh;
|
||||
}
|
||||
class TestIDPosition(TestCase):
|
||||
def setUp(self):
|
||||
"""Executed before each test in the class"""
|
||||
self.t = Task()
|
||||
|
||||
# Test id before command, and id after command.
|
||||
qx{../src/task rc:$rc add one 2>&1};
|
||||
qx{../src/task rc:$rc add two 2>&1};
|
||||
qx{../src/task rc:$rc add three 2>&1};
|
||||
my $output = qx{../src/task rc:$rc list 2>&1};
|
||||
like ($output, qr/one/, "$ut: task 1 added");
|
||||
like ($output, qr/two/, "$ut: task 2 added");
|
||||
like ($output, qr/three/, "$ut: task 3 added");
|
||||
self.t(("add", "one"))
|
||||
self.t(("add", "two"))
|
||||
self.t(("add", "three"))
|
||||
|
||||
$output = qx{../src/task rc:$rc 1 done 2>&1};
|
||||
like ($output, qr/^Completed 1 task\.$/ms, "$ut: COMMAND after ID");
|
||||
def test_id(self):
|
||||
"""Test id before and after command"""
|
||||
code, out, err = self.t(("list",))
|
||||
|
||||
$output = qx{../src/task rc:$rc rc.allow.empty.filter:yes done 2 2>&1};
|
||||
like ($output, qr/^Command prevented from running.$/ms, "$ut: ID after COMMAND, allowing empty filter");
|
||||
unlike ($output, qr/^Completed 1 task\.$/ms, "$ut: ID after COMMAND, allowing empty filter");
|
||||
self.assertIn("one", out)
|
||||
self.assertIn("two", out)
|
||||
self.assertIn("three", out)
|
||||
|
||||
$output = qx{../src/task rc:$rc rc.allow.empty.filter:no done 2 2>&1};
|
||||
like ($output, qr/^You did not specify a filter, and with the 'allow\.empty\.filter' value, no action is taken\.$/ms,
|
||||
"$ut: ID after COMMAND, disallowing empty filter");
|
||||
unlike ($output, qr/^Completed 1 task\.$/ms, "$ut: ID after COMMAND, disallowing empty filter");
|
||||
code, out, err = self.t(("1", "done"))
|
||||
self.assertIn("Completed 1 task.", out)
|
||||
|
||||
# Cleanup.
|
||||
unlink qw(pending.data completed.data undo.data backlog.data), $rc;
|
||||
exit 0;
|
||||
filter = "rc.allow.empty.filter:yes"
|
||||
code, out, err = self.t.runError((filter, "done", "2"))
|
||||
self.assertIn("Command prevented from running.", err)
|
||||
self.assertNotIn("Completed 1 task.", out)
|
||||
|
||||
filter = "rc.allow.empty.filter:no"
|
||||
code, out, err = self.t.runError((filter, "done", "2"))
|
||||
self.assertIn("You did not specify a filter, and with the "
|
||||
"'allow.empty.filter' value, no action is taken.", err)
|
||||
self.assertNotIn("Completed 1 task.", out)
|
||||
|
||||
if __name__ == "__main__":
|
||||
from simpletap import TAPTestRunner
|
||||
unittest.main(testRunner=TAPTestRunner())
|
||||
|
||||
# vim: ai sts=4 et sw=4
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
#! /usr/bin/env perl
|
||||
################################################################################
|
||||
##
|
||||
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
##
|
||||
## Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
## of this software and associated documentation files (the "Software"), to deal
|
||||
## in the Software without restriction, including without limitation the rights
|
||||
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
## copies of the Software, and to permit persons to whom the Software is
|
||||
## furnished to do so, subject to the following conditions:
|
||||
##
|
||||
## The above copyright notice and this permission notice shall be included
|
||||
## in all copies or substantial portions of the Software.
|
||||
##
|
||||
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
## SOFTWARE.
|
||||
##
|
||||
## http://www.opensource.org/licenses/mit-license.php
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 5;
|
||||
|
||||
# Ensure environment has no influence.
|
||||
delete $ENV{'TASKDATA'};
|
||||
delete $ENV{'TASKRC'};
|
||||
|
||||
use File::Basename;
|
||||
my $ut = basename ($0);
|
||||
my $rc = $ut . '.rc';
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', $rc)
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"confirmation=off\n";
|
||||
close $fh;
|
||||
}
|
||||
|
||||
# Test 'done' with en-passant changes.
|
||||
qx{../src/task rc:$rc add one 2>&1};
|
||||
qx{../src/task rc:$rc add two 2>&1};
|
||||
qx{../src/task rc:$rc add three 2>&1};
|
||||
qx{../src/task rc:$rc add four 2>&1};
|
||||
qx{../src/task rc:$rc add five 2>&1};
|
||||
|
||||
qx{../src/task rc:$rc 1 done oneanno 2>&1};
|
||||
my $output = qx{../src/task rc:$rc 1 info 2>&1};
|
||||
like ($output, qr/oneanno/, "$ut: done enpassant anno");
|
||||
|
||||
qx{../src/task rc:$rc 2 done /two/TWO/ 2>&1};
|
||||
$output = qx{../src/task rc:$rc 2 info 2>&1};
|
||||
like ($output, qr/Description\s+TWO/, "$ut: done enpassant subst");
|
||||
|
||||
qx{../src/task rc:$rc 3 done +threetag 2>&1};
|
||||
$output = qx{../src/task rc:$rc 3 info 2>&1};
|
||||
like ($output, qr/Tags\s+threetag/, "$ut: done enpassant tag");
|
||||
|
||||
qx{../src/task rc:$rc 4 done pri:H 2>&1};
|
||||
$output = qx{../src/task rc:$rc 4 info 2>&1};
|
||||
like ($output, qr/Priority\s+H/, "$ut: done enpassant priority");
|
||||
|
||||
qx{../src/task rc:$rc 5 done pro:A 2>&1};
|
||||
$output = qx{../src/task rc:$rc 5 info 2>&1};
|
||||
like ($output, qr/Project\s+A/, "$ut: done enpassant project");
|
||||
|
||||
# Cleanup.
|
||||
unlink qw(pending.data completed.data undo.data backlog.data), $rc;
|
||||
exit 0;
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
#! /usr/bin/env perl
|
||||
################################################################################
|
||||
##
|
||||
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
##
|
||||
## Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
## of this software and associated documentation files (the "Software"), to deal
|
||||
## in the Software without restriction, including without limitation the rights
|
||||
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
## copies of the Software, and to permit persons to whom the Software is
|
||||
## furnished to do so, subject to the following conditions:
|
||||
##
|
||||
## The above copyright notice and this permission notice shall be included
|
||||
## in all copies or substantial portions of the Software.
|
||||
##
|
||||
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
## SOFTWARE.
|
||||
##
|
||||
## http://www.opensource.org/licenses/mit-license.php
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 5;
|
||||
|
||||
# Ensure environment has no influence.
|
||||
delete $ENV{'TASKDATA'};
|
||||
delete $ENV{'TASKRC'};
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'args.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"confirmation=off\n";
|
||||
close $fh;
|
||||
}
|
||||
|
||||
# Test 'delete' with en-passant changes.
|
||||
qx{../src/task rc:args.rc add one 2>&1};
|
||||
qx{../src/task rc:args.rc add two 2>&1};
|
||||
qx{../src/task rc:args.rc add three 2>&1};
|
||||
qx{../src/task rc:args.rc add four 2>&1};
|
||||
qx{../src/task rc:args.rc add five 2>&1};
|
||||
|
||||
qx{../src/task rc:args.rc 1 delete oneanno 2>&1};
|
||||
my $output = qx{../src/task rc:args.rc 1 info 2>&1};
|
||||
like ($output, qr/oneanno/, 'delete enpassant anno');
|
||||
|
||||
qx{../src/task rc:args.rc 2 delete /two/TWO/ 2>&1};
|
||||
$output = qx{../src/task rc:args.rc 2 info 2>&1};
|
||||
like ($output, qr/Description\s+TWO/, 'delete enpassant subst');
|
||||
|
||||
qx{../src/task rc:args.rc 3 delete +threetag 2>&1};
|
||||
$output = qx{../src/task rc:args.rc 3 info 2>&1};
|
||||
like ($output, qr/Tags\s+threetag/, 'delete enpassant tag');
|
||||
|
||||
qx{../src/task rc:args.rc 4 delete pri:H 2>&1};
|
||||
$output = qx{../src/task rc:args.rc 4 info 2>&1};
|
||||
like ($output, qr/Priority\s+H/, 'delete enpassant priority');
|
||||
|
||||
qx{../src/task rc:args.rc 5 delete pro:A 2>&1};
|
||||
$output = qx{../src/task rc:args.rc 5 info 2>&1};
|
||||
like ($output, qr/Project\s+A/, 'delete enpassant project');
|
||||
|
||||
# Cleanup.
|
||||
unlink qw(pending.data completed.data undo.data backlog.data args.rc);
|
||||
exit 0;
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
#! /usr/bin/env perl
|
||||
################################################################################
|
||||
##
|
||||
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
##
|
||||
## Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
## of this software and associated documentation files (the "Software"), to deal
|
||||
## in the Software without restriction, including without limitation the rights
|
||||
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
## copies of the Software, and to permit persons to whom the Software is
|
||||
## furnished to do so, subject to the following conditions:
|
||||
##
|
||||
## The above copyright notice and this permission notice shall be included
|
||||
## in all copies or substantial portions of the Software.
|
||||
##
|
||||
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
## SOFTWARE.
|
||||
##
|
||||
## http://www.opensource.org/licenses/mit-license.php
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 5;
|
||||
|
||||
# Ensure environment has no influence.
|
||||
delete $ENV{'TASKDATA'};
|
||||
delete $ENV{'TASKRC'};
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'args.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"confirmation=off\n";
|
||||
close $fh;
|
||||
}
|
||||
|
||||
# Test 'start' with en-passant changes.
|
||||
qx{../src/task rc:args.rc add one 2>&1};
|
||||
qx{../src/task rc:args.rc add two 2>&1};
|
||||
qx{../src/task rc:args.rc add three 2>&1};
|
||||
qx{../src/task rc:args.rc add four 2>&1};
|
||||
qx{../src/task rc:args.rc add five 2>&1};
|
||||
|
||||
qx{../src/task rc:args.rc 1 start oneanno 2>&1};
|
||||
my $output = qx{../src/task rc:args.rc 1 info 2>&1};
|
||||
like ($output, qr/oneanno/, 'start enpassant anno');
|
||||
|
||||
qx{../src/task rc:args.rc 2 start /two/TWO/ 2>&1};
|
||||
$output = qx{../src/task rc:args.rc 2 info 2>&1};
|
||||
like ($output, qr/Description\s+TWO/, 'start enpassant subst');
|
||||
|
||||
qx{../src/task rc:args.rc 3 start +threetag 2>&1};
|
||||
$output = qx{../src/task rc:args.rc 3 info 2>&1};
|
||||
like ($output, qr/Tags\s+threetag/, 'start enpassant tag');
|
||||
|
||||
qx{../src/task rc:args.rc 4 start pri:H 2>&1};
|
||||
$output = qx{../src/task rc:args.rc 4 info 2>&1};
|
||||
like ($output, qr/Priority\s+H/, 'start enpassant priority');
|
||||
|
||||
qx{../src/task rc:args.rc 5 start pro:A 2>&1};
|
||||
$output = qx{../src/task rc:args.rc 5 info 2>&1};
|
||||
like ($output, qr/Project\s+A/, 'start enpassant project');
|
||||
|
||||
# Cleanup.
|
||||
unlink qw(pending.data completed.data undo.data backlog.data args.rc);
|
||||
exit 0;
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
#! /usr/bin/env perl
|
||||
################################################################################
|
||||
##
|
||||
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
##
|
||||
## Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
## of this software and associated documentation files (the "Software"), to deal
|
||||
## in the Software without restriction, including without limitation the rights
|
||||
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
## copies of the Software, and to permit persons to whom the Software is
|
||||
## furnished to do so, subject to the following conditions:
|
||||
##
|
||||
## The above copyright notice and this permission notice shall be included
|
||||
## in all copies or substantial portions of the Software.
|
||||
##
|
||||
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
## SOFTWARE.
|
||||
##
|
||||
## http://www.opensource.org/licenses/mit-license.php
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 5;
|
||||
|
||||
# Ensure environment has no influence.
|
||||
delete $ENV{'TASKDATA'};
|
||||
delete $ENV{'TASKRC'};
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'args.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"confirmation=off\n";
|
||||
close $fh;
|
||||
}
|
||||
|
||||
# Test 'stop' with en-passant changes.
|
||||
qx{../src/task rc:args.rc add one 2>&1};
|
||||
qx{../src/task rc:args.rc add two 2>&1};
|
||||
qx{../src/task rc:args.rc add three 2>&1};
|
||||
qx{../src/task rc:args.rc add four 2>&1};
|
||||
qx{../src/task rc:args.rc add five 2>&1};
|
||||
|
||||
qx{../src/task rc:args.rc 1 start 2>&1};
|
||||
qx{../src/task rc:args.rc 2 start 2>&1};
|
||||
qx{../src/task rc:args.rc 3 start 2>&1};
|
||||
qx{../src/task rc:args.rc 4 start 2>&1};
|
||||
qx{../src/task rc:args.rc 5 start 2>&1};
|
||||
|
||||
qx{../src/task rc:args.rc 1 stop oneanno 2>&1};
|
||||
my $output = qx{../src/task rc:args.rc 1 info 2>&1};
|
||||
like ($output, qr/oneanno/, 'stop enpassant anno');
|
||||
|
||||
qx{../src/task rc:args.rc 2 stop /two/TWO/ 2>&1};
|
||||
$output = qx{../src/task rc:args.rc 2 info 2>&1};
|
||||
like ($output, qr/Description\s+TWO/, 'stop enpassant subst');
|
||||
|
||||
qx{../src/task rc:args.rc 3 stop +threetag 2>&1};
|
||||
$output = qx{../src/task rc:args.rc 3 info 2>&1};
|
||||
like ($output, qr/Tags\s+threetag/, 'stop enpassant tag');
|
||||
|
||||
qx{../src/task rc:args.rc 4 stop pri:H 2>&1};
|
||||
$output = qx{../src/task rc:args.rc 4 info 2>&1};
|
||||
like ($output, qr/Priority\s+H/, 'stop enpassant priority');
|
||||
|
||||
qx{../src/task rc:args.rc 5 stop pro:A 2>&1};
|
||||
$output = qx{../src/task rc:args.rc 5 info 2>&1};
|
||||
like ($output, qr/Project\s+A/, 'stop enpassant project');
|
||||
|
||||
# Cleanup.
|
||||
unlink qw(pending.data completed.data undo.data backlog.data args.rc);
|
||||
exit 0;
|
||||
|
||||
152
test/args.t
152
test/args.t
@@ -1,68 +1,104 @@
|
||||
#! /usr/bin/env perl
|
||||
################################################################################
|
||||
##
|
||||
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
##
|
||||
## Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
## of this software and associated documentation files (the "Software"), to deal
|
||||
## in the Software without restriction, including without limitation the rights
|
||||
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
## copies of the Software, and to permit persons to whom the Software is
|
||||
## furnished to do so, subject to the following conditions:
|
||||
##
|
||||
## The above copyright notice and this permission notice shall be included
|
||||
## in all copies or substantial portions of the Software.
|
||||
##
|
||||
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
## SOFTWARE.
|
||||
##
|
||||
## http://www.opensource.org/licenses/mit-license.php
|
||||
##
|
||||
################################################################################
|
||||
#!/usr/bin/env python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
###############################################################################
|
||||
#
|
||||
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included
|
||||
# in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
# http://www.opensource.org/licenses/mit-license.php
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 5;
|
||||
import sys
|
||||
import os
|
||||
import unittest
|
||||
# Ensure python finds the local simpletap module
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
# Ensure environment has no influence.
|
||||
delete $ENV{'TASKDATA'};
|
||||
delete $ENV{'TASKRC'};
|
||||
from basetest import Task, TestCase
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', 'args.rc')
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"confirmation=no\n";
|
||||
close $fh;
|
||||
}
|
||||
|
||||
# Test the -- argument.
|
||||
qx{../src/task rc:args.rc add project:p pri:H +tag foo 2>&1};
|
||||
my $output = qx{../src/task rc:args.rc info 1 2>&1};
|
||||
like ($output, qr/Description\s+foo\n/ms, 'task add project:p pri:H +tag foo');
|
||||
class TestArgs(TestCase):
|
||||
def setUp(self):
|
||||
"""Executed before each test in the class"""
|
||||
self.t = Task()
|
||||
|
||||
qx{../src/task rc:args.rc 1 modify project:p pri:H +tag -- foo 2>&1};
|
||||
$output = qx{../src/task rc:args.rc info 1 2>&1};
|
||||
like ($output, qr/Description\s+foo\n/ms, 'task 1 modify project:p pri:H +tag -- foo');
|
||||
def test_dash_dash_argument(self):
|
||||
"""Test the -- argument"""
|
||||
self.t(("add", "project:p", "pri:H", "+tag", "foo"))
|
||||
|
||||
qx{../src/task rc:args.rc 1 modify project:p pri:H -- +tag foo 2>&1};
|
||||
$output = qx{../src/task rc:args.rc info 1 2>&1};
|
||||
like ($output, qr/Description\s+\+tag\sfoo\n/ms, 'task 1 modify project:p pri:H -- +tag foo');
|
||||
code, out, err = self.t(("info", "1"))
|
||||
self.assertRegexpMatches(
|
||||
out,
|
||||
"Description\s+foo\n",
|
||||
msg='add project:p pri:H +tag foo',
|
||||
)
|
||||
|
||||
qx{../src/task rc:args.rc 1 modify project:p -- pri:H +tag foo 2>&1};
|
||||
$output = qx{../src/task rc:args.rc info 1 2>&1};
|
||||
like ($output, qr/Description\s+pri:H\s\+tag\sfoo\n/ms, 'task 1 modify project:p -- pri:H +tag foo');
|
||||
self.t(("1", "modify", "project:p", "pri:H", "+tag", "--", "foo"))
|
||||
|
||||
qx{../src/task rc:args.rc 1 modify -- project:p pri:H +tag foo 2>&1};
|
||||
$output = qx{../src/task rc:args.rc info 1 2>&1};
|
||||
like ($output, qr/Description\s+project:p\spri:H\s\+tag\sfoo\n/ms, 'task 1 modify -- project:p pri:H +tag foo');
|
||||
code, out, err = self.t(("info", "1"))
|
||||
self.assertRegexpMatches(
|
||||
out,
|
||||
"Description\s+foo\n",
|
||||
msg='1 modify project:p pri:H +tag -- foo',
|
||||
)
|
||||
|
||||
# Cleanup.
|
||||
unlink qw(pending.data completed.data undo.data backlog.data args.rc);
|
||||
exit 0;
|
||||
self.t(("1", "modify", "project:p", "pri:H", "--", "+tag", "foo"))
|
||||
|
||||
code, out, err = self.t(("info", "1"))
|
||||
self.assertRegexpMatches(
|
||||
out,
|
||||
"Description\s+\+tag\sfoo\n",
|
||||
msg='1 modify project:p pri:H -- +tag foo',
|
||||
)
|
||||
|
||||
self.t(("1", "modify", "project:p", "--", "pri:H", "+tag", "foo"))
|
||||
|
||||
code, out, err = self.t(("info", "1"))
|
||||
self.assertRegexpMatches(
|
||||
out,
|
||||
"Description\s+pri:H\s\+tag\sfoo\n",
|
||||
msg='1 modify project:p -- pri:H +tag foo',
|
||||
)
|
||||
|
||||
self.t(("1", "modify", "--", "project:p", "pri:H", "+tag", "foo"))
|
||||
|
||||
code, out, err = self.t(("info", "1"))
|
||||
self.assertRegexpMatches(
|
||||
out,
|
||||
"Description\s+project:p\spri:H\s\+tag\sfoo\n",
|
||||
msg='1 modify project:p -- pri:H +tag foo',
|
||||
)
|
||||
|
||||
self.t(("1", "modify", "--", "project:p", "pri:H", "+tag", "--"))
|
||||
|
||||
code, out, err = self.t(("info", "1"))
|
||||
self.assertRegexpMatches(
|
||||
out,
|
||||
"Description\s+project:p\spri:H\s\+tag\s--\n",
|
||||
msg='1 modify project:p -- pri:H +tag foo --',
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from simpletap import TAPTestRunner
|
||||
unittest.main(testRunner=TAPTestRunner())
|
||||
|
||||
# vim: ai sts=4 et sw=4
|
||||
|
||||
@@ -5,8 +5,8 @@ import tempfile
|
||||
import shutil
|
||||
import atexit
|
||||
import unittest
|
||||
from .utils import (run_cmd_wait, run_cmd_wait_nofail, which, binary_location,
|
||||
)
|
||||
from .utils import (run_cmd_wait, run_cmd_wait_nofail, which,
|
||||
task_binary_location)
|
||||
from .exceptions import CommandError
|
||||
from .hooks import Hooks
|
||||
|
||||
@@ -22,7 +22,7 @@ class Task(object):
|
||||
|
||||
A taskw client should not be used after being destroyed.
|
||||
"""
|
||||
DEFAULT_TASK = binary_location("task")
|
||||
DEFAULT_TASK = task_binary_location()
|
||||
|
||||
def __init__(self, taskd=None, taskw=DEFAULT_TASK):
|
||||
"""Initialize a Task warrior (client) that can interact with a taskd
|
||||
@@ -137,6 +137,15 @@ class Task(object):
|
||||
cmd = (self.taskw, "config", "--", var, value)
|
||||
return run_cmd_wait(cmd, env=self.env)
|
||||
|
||||
@property
|
||||
def taskrc_content(self):
|
||||
"""
|
||||
Returns the contents of the taskrc file.
|
||||
"""
|
||||
|
||||
with open(self.taskrc, "r") as f:
|
||||
return f.readlines()
|
||||
|
||||
def runSuccess(self, args=(), input=None, merge_streams=False,
|
||||
timeout=1):
|
||||
"""Invoke task with given arguments and fail if exit code != 0
|
||||
|
||||
@@ -8,7 +8,8 @@ import atexit
|
||||
from time import sleep
|
||||
from subprocess import Popen
|
||||
from .utils import (find_unused_port, release_port, port_used, run_cmd_wait,
|
||||
which, parse_datafile, DEFAULT_CERT_PATH, binary_location)
|
||||
which, parse_datafile, DEFAULT_CERT_PATH,
|
||||
taskd_binary_location)
|
||||
from .exceptions import CommandError
|
||||
|
||||
try:
|
||||
@@ -30,7 +31,7 @@ class Taskd(object):
|
||||
A server can be stopped and started multiple times, but should not be
|
||||
started or stopped after being destroyed.
|
||||
"""
|
||||
DEFAULT_TASKD = binary_location("taskd")
|
||||
DEFAULT_TASKD = taskd_binary_location()
|
||||
|
||||
def __init__(self, taskd=DEFAULT_TASKD, certpath=None,
|
||||
address="localhost"):
|
||||
|
||||
@@ -41,13 +41,28 @@ DEFAULT_HOOK_PATH = os.path.abspath(
|
||||
TASKW_SKIP = os.environ.get("TASKW_SKIP", False)
|
||||
TASKD_SKIP = os.environ.get("TASKD_SKIP", False)
|
||||
# Environment flags to control use of PATH or in-tree binaries
|
||||
USE_PATH = os.environ.get("USE_PATH", False)
|
||||
TASK_USE_PATH = os.environ.get("TASK_USE_PATH", False)
|
||||
TASKD_USE_PATH = os.environ.get("TASKD_USE_PATH", False)
|
||||
|
||||
UUID_regex = ("[0-9A-Fa-f]{8}-" + ("[0-9A-Fa-f]{4}-" * 3) + "[0-9A-Fa-f]{12}")
|
||||
|
||||
|
||||
def binary_location(cmd):
|
||||
"""If USE_PATH is set rely on PATH to look for task/taskd binaries.
|
||||
def task_binary_location(cmd="task"):
|
||||
"""If TASK_USE_PATH is set rely on PATH to look for task binaries.
|
||||
Otherwise ../src/ is used by default.
|
||||
"""
|
||||
return binary_location(cmd, TASK_USE_PATH)
|
||||
|
||||
|
||||
def taskd_binary_location(cmd="taskd"):
|
||||
"""If TASKD_USE_PATH is set rely on PATH to look for taskd binaries.
|
||||
Otherwise ../src/ is used by default.
|
||||
"""
|
||||
return binary_location(cmd, TASKD_USE_PATH)
|
||||
|
||||
|
||||
def binary_location(cmd, USE_PATH=False):
|
||||
"""If USE_PATH is True rely on PATH to look for taskd binaries.
|
||||
Otherwise ../src/ is used by default.
|
||||
"""
|
||||
if USE_PATH:
|
||||
@@ -108,14 +123,24 @@ def _queue_output(arguments, pidq, outputq):
|
||||
kwargs = arguments["process"]
|
||||
input = arguments["input"]
|
||||
|
||||
proc = Popen(**kwargs)
|
||||
try:
|
||||
proc = Popen(**kwargs)
|
||||
except OSError as e:
|
||||
# pid None is read by the main thread as a crash of the process
|
||||
pidq.put(None)
|
||||
|
||||
# NOTE If for whatever reason pid is None at the time of access, use the
|
||||
# following line instead
|
||||
# pid = wait_condition(lambda: proc.pid)
|
||||
pid = proc.pid
|
||||
# Put the PID in the queue for main process to know
|
||||
pidq.put(pid)
|
||||
outputq.put((
|
||||
"",
|
||||
("Unexpected exception caught during execution of taskw: '{0}' . "
|
||||
"If you are running out-of-tree tests set USE_PATH=1 in shell "
|
||||
"env before execution and add the location of the task binary to "
|
||||
"the PATH".format(e)),
|
||||
255)) # false exitcode
|
||||
|
||||
return
|
||||
|
||||
# Put the PID in the queue for main process to know.
|
||||
pidq.put(proc.pid)
|
||||
|
||||
# Send input and wait for finish
|
||||
out, err = proc.communicate(input)
|
||||
@@ -161,6 +186,10 @@ def _get_output(arguments, timeout=None):
|
||||
try:
|
||||
pid = pidq.get(timeout=timeout)
|
||||
except Empty:
|
||||
pid = None
|
||||
|
||||
# Process crashed or timed out for some reason
|
||||
if pid is None:
|
||||
return _retrieve_output(t, output_timeout, outputq,
|
||||
"TaskWarrior to start")
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user