diff -Nru task-2.4.4+dfsg/AUTHORS task-2.5.0+dfsg/AUTHORS --- task-2.4.4+dfsg/AUTHORS 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/AUTHORS 2015-10-21 21:18:14.000000000 +0000 @@ -117,6 +117,12 @@ Jens Erat Peter Rochen Oota Toshiya + ribbon + Daniel Shahaf + Johannes Wienke + Alan Young + Gordon Ball + Rafał Bolanowski Thanks to the following, who submitted detailed bug reports and excellent suggestions: @@ -213,7 +219,7 @@ Dmitriy Matrosov Michele Santullo Scott Kroll - Kosta H + Kosta Harlan Hector Arciga Jan Kunder jck @@ -251,3 +257,23 @@ Scott M Stefan Frühwirth Pierre Campet + Denis Kasak + David Brenner + Audrey Easterday + Stefan Betz + Blake Sweeney + Dylan Mikus + Andrea Rizzi + Florian Petry + Lars Beckers + Dustin J. Mitchell + James Cline + Ryan + Simon W. Jackson + Sebastien Badia + Michale Meier + Svetoslav Trochev + Marc Cornellà + Ander + Naga Kiran + David Badura diff -Nru task-2.4.4+dfsg/ChangeLog task-2.5.0+dfsg/ChangeLog --- task-2.4.4+dfsg/ChangeLog 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/ChangeLog 2015-10-21 21:18:14.000000000 +0000 @@ -1,4 +1,219 @@ -2.4.4 (2015-05-10) - +2.5.0 (2015-10-21) - + +- TW-20 Task edit loses annotation precision, causing journal updating code + to incorrectly indicate annotions are deleted and recreated (thanks + to Cory Donnelly). +- TW-32 Unable to change annotations via task edit (thanks to Peter De + Poorter). +- TW-46 Circular dependency detection broken for missing tasks. +- TW-50 Creation time is lost after editing (thanks to Ben Boeckel). +- TW-148 default.command options (thanks to David Patrick). +- TW-158 JSON export should model dependencies as array (thanks to Nicholas E. + Rabenau). +- TW-263 Unexpected zsh autocomplete behaviour (thanks to Leon Feng, Marc + Cornellà). +- TW-269 \t is not rendered correctly (thanks to Scott Kostyshak). +- TW-283 Process rc.* items when executing config (thanks to Ben Armstrong). +- TW-303 Ability for "import" to update existing tasks (thanks to Kosta + Harlan). +- TW-1285 relative dates combined with times (thanks to Adam Gibbins). +- TW-1319 UDA is NOT sorted corresponding to the order of UDA list entries + (thanks to Onion). +- TW-1344 Filter due:yyyy-mm-dd is failing to display daily recurring tasks if + there is deleted task in the series.(thanks to Svetoslav Trochev). +- TW-1375 Use of ^ in regex parsed as exponentiate operator (thanks to + lolilolicon). +- TW-1389 tw will import same UUID n-times if part of same import (thanks to + Markus Beppler). +- TW-1419 On add '-tag' is considered a tag removal, which makes no sense. +- TW-1426 Adding a date in 1963 (why not?) stores a negative epoch, which fails + to export (thanks to Black Ops Testing). +- TW-1430 Slashes in project names don't work (thanks to Richard Boß). +- TW-1432 start/stop can be issued on completed tasks (thanks to Renato Alves). +- TW-1440 "task import" from STDIN (thanks to Renato Alves). +- TW-1448 Add possibility to modify newest task (thanks to Jens Erat). +- TW-1452 The uuid: filter does not work (thanks to Tomas Babej). +- TW-1454 Redundant dependency should not stop modification (thanks to Tomas + Babej). +- TW-1455 Filter parser does not properly handle parentheses in attributes + (thanks to Tomas Babej). +- TW-1456 Filter parser does not always handle multiple arguments bundled into + one with apostrophes (thanks to Tomas Babej). +- TW-1466 UDA with type duration is stored as text/string (thanks to Thomas + Sullivan). +- TW-1472 Syntactic sugar morphs into regex expressions, even if turned off + (thanks to Richard Boß). +- TW-1475 task config expands values with unnecessary spaces (thanks to Tomas + Babej). +- TW-1478 due:easter sets the easter of the current year regardless of the date + (thanks to David Costa). +- TW-1479 Task arguments not properly parsed if they contain a space (thanks to + Tomas Babej). +- TW-1480 Weird behaviour on redundant filter beginning with number (thanks to + Tomas Babej). +- TW-1485 can't delete recurring tasks (except by workaround) (thanks to + Dustin J. Mitchell). +- TW-1488 You have more urgent tasks (thanks to Stefan Betz, Denis Kasak). +- TW-1496 Translation manuals are outdated/miss information (thanks to Jens + Erat). +- TW-1499 Invalid due date produces jump to beggining of the unix epoch (thanks + to Tomas Babej). +- TW-1511 Project titles not properly parsed if they contain hyphens (thanks to + Leon Feng, Blake Sweeney, Dylan Mikus). +- TW-1515 abbreviation.minimum does not apply to date recognition (thanks to + Lars Beckers). +- TW-1521 task project!=PROJECTNAME does not work (Regression) (thanks to + Florian Petry). +- TW-1527 Extra spaces added around slashes (thanks to Renato Alves). +- TW-1529 Parser incorrectly inserting spaces into task description (thanks to + David Brenner). +- TW-1533 dateformat confusion, regress tests (thanks to Peter Rochen). +- TW-1537 soww Synonym produces wrong date (thanks to Michael Meier). +- TW-1543 cmake complains "test" is not a valid target (on arch linux) (thanks + to Renato Alves). +- TW-1553 Setting defaultheight:0 makes burndown command hang (thanks to Tomas + Babej). +- TW-1555 Project Names Converted to Dates (thanks to Ryan). +- TW-1566 Context is applied on 'task export' (thanks to Tomas Babej). +- TW-1569 update wait: manpage entry (thanks to David Patrick). +- TW-1572 Better urgency inheritance (thanks to Jens Erat). +- TW-1575 `task log` mangles URLs when quoted (thanks to Luke Macken). +- TW-1592 Able to add duplicate tags using 'tags:' (thanks to Tomas + Babej). +- TW-1593 context and description substring (thanks to Peter Rochen). +- TW-1594 Filter "due.before" with relative dates stopped working (thanks to + Sebastien Badia). +- TW-1598 (Bulk) modification of tasks unintentionally overwrites description + if a context is active (thanks to Johannes Schlatow). +- TW-1600 Filtering "regressions"(?) in task-2.4.3, task-2.4.4 (thanks to Ralph + Bean). +- TW-1607 Theme Support for missing UDAs (thanks to Stefan Betz). +- TW-1609 In 'urgency<10', 10 is interpreted as an ID (thanks to Wim Schuermann). +- TW-1611 soww weirdness (thanks to Wim Schuermann). +- TW-1612 Spurious whitespace added in task descriptions around certain symbols + (thanks to Denis Kasak). +- TW-1615 Japanese translation for Taskwarrior(150513) (thanks to ribbon). +- TW-1616 Intermittent lengthy delay when starting or completing a task (thanks + to Jeremy John Reeder). +- TW-1617 Can't search for multi-word project (thanks to Audrey Easterday). +- TW-1619 fish completion contain backspaces in fish master version (thanks to + Johannes Wienke₎. +- TW-1620 Dateformat wrongly interpreted (thanks to Dirk Deimeke). +- TW-1621 Recurrent parent tasks shouldn't be counted in history (thanks to + Denis Kasak). +- TW-1622 Duration UDA can't take an algebraic expression (thanks to Jeremy John + Reeder). +- TW-1624 Report filters combine incorrectly with command line with terminator. +- TW-1626 Wrong wait date (thanks to Andrea Rizzi). +- TW-1627 'mon' is replaced with date in project field (thanks to James Cline). +- TW-1629 Descriptions often get overwritten with "( or )" (thanks to Jeremy + John Reeder). +- TW-1630 "Due" parsing behavior seems inconsistent (thanks to Jim B). +- TW-1632 Japanese translation for Taskwarrior(150713) (thanks to ribbon). +- TW-1634 due.not: excludes only tasks scheduled at mitnight (thanks to + Tomas Babej). +- TW-1635 Running "task anystringatall" does not filter anything (thanks to + Tomas Babej). +- TW-1636 UUID with numeric-only first segment is not parsed properly (thanks + to Tomas Babej). +- TW-1637 project name "mod" interpreted as date (thanks to Wim Schuermann). +- TW-1638 Undo doesn't work when a context is set (thanks to Jeremy John Reeder). +- TW-1640 '_get .start' for an inactive tasks returns a date formatted from + epoch 0. +- TW-1641 'edit' should process or reject arguments (thanks to Daniel + Shahaf). +- TW-1642 After "--", an apostrophe unexpectedly ends the task description + (thanks to Jeremy John Reeder). +- TW-1643 Batch modifying tasks under context sets description to '( )' + (thanks to Leon Feng). +- TW-1647 descriptions that are stringified ids (thanks to Daniel Shahaf). +- TW-1648 Typo in Documentation (thanks to Simon W. Jackson). +- TW-1649 'columns' colorizes output when stdout is a pipe (thanks to Daniel + Shahaf). +- TW-1651 Provide opt-out of filter parser's id treatment (thanks to Daniel + Shahaf). +- TW-1652 task rm misparsed (thanks to Daniel Shahaf). +- TW-1653 info report regression; shouldn't be context sensitive (thanks to + David Patrick). +- TW-1655 Inform "No changes made." when quitting early due to signal (thanks + to Daniel Shahaf). +- TW-1656 Implicitly parenthesize argv filter (thanks to Daniel Shahaf). +- TW-1660 Disabled sorting option (thanks to David Patrick). +- TW-1662 filter before add becomes description (thanks to Daniel + Shahaf). +- TW-1664 Notify of waiting→pending promotion (thanks to Daniel Shahaf). +- TW-1666 import should reject invalid data (thanks to Daniel Shahaf). +- TW-1670 Reversed ranges are parsed as a mathematician would expect (thanks to + Daniel Shahaf). +- TW-1671 task add: segfault with foo-bar:1 (thanks to Daniel Shahaf). +- TW-1675 project.not:something doesn't exclude project:something.subprojects + (thanks to Ander). +- TW-1678 segfault in ~ViewTask() (thanks to Daniel Shahaf). +- TW-1683 Dom reference for project not properly evaluated (thanks to Tomas + Babej). +- TW-1684 make no-date > has-date for all date attributes (thanks to David + Patrick). +- TW-1686 Sorting not working on udas (thanks to Naga Kiran). +- TW-1687 task add due:som appears to be interpreted as 'someday' (thanks to + Alan Young). +- TW-1688 task fails to import (thanks to Rainer Müller). +- TW-1692 '42//' segfaults (thanks to Daniel Shahaf). +- TW-1695 edit: Concurrent edits (thanks to Daniel Shahaf). +- TW-1699 Command interpretation displayed incorrectly (thanks to Tomas Babej). +- TW-1700 modify tags behavior changed (thanks to David Badura). +- TW-1701 Some generated UUIDs deemed invalid (thanks to Wim Schuermann). +- TW-1707 Context can leak into modifications (thanks to Tomas Babej). +- TW-1715 Dates misinterpreted when no dateformat active. +- TW-1716 on-modify hooks fail if `date.iso` is not set (thanks to Jens Erat). +- Prevent potential task duplication during import for non-pending tasks. +- Show the active context in "context list", if any is active. +- Fix "task edit" dropping annotation text after newlines. +- Removed obsolete script 'context'. +- Fix "project" verbosity info not showing without "footnote" being manually + enabled. +- Internal plumbing: Use variadic templates for format(), reducing code bloat + and enabling more flexible use of the function. +- Enable "task sync" support by default. "cmake -DENABLE_SYNC=OFF" allows + disabling it and building Taskwarrior without libgnutls available. +- An attempt to add or remove a virtual tag is now an error (thanks to Scott M). +- json.array now defaults to "on", making "export" output a JSON array that + can be parsed by most JSON libraries without changes. +- The '_ids', '_projects', '_tags', '_uuids' helper commands are deprecated, + and replaced by the new '_unique' helper command, which generates lists of + unique values for the specified attribute. +- "import" can now import JSON arrays, the new default "export" output. +- The '_tags' helper command now includes virtual tags (thanks to Daniel + Shahaf). +- When multiple tasks are 'edit'ed, a failure causes the editing to stop (thanks + to Daniel Shahaf). +- New 'UDA', 'ORPHAN', 'PROJECT', 'PRIORITY' and 'LATEST' virtual tags. +- Commands that do not accept filters or modifications now generate an error + when extra arguments are specified. +- Improved zsh support (thanks to Daniel Shahaf). +- Dependencies are exported as a JSON array by default, overridable using + 'rc.json.depends.array=off'. Both forms are imported. +- The 'commands' command shows the supported commands, with additional details + that determine some of their behavior. +- Improved feedback for tasks that do not have ID (thanks to Tomas Babej). +- Comma-separated lists of UUIDs can no longer be used as a filter. Use the + space character instead. +- New 'recur' verbosity token generates a notification message when a recurring + task is created. +- New 'unwait' verbosity token generates a notification message when a waiting + task becomes visible. +- New 'rule.color.merge=yes|no' configuration option, that can optionally + turn off color blending engine. +- The 'urgency.next.coefficient' configuration option is deprecated in favor + of 'urgency.user.tag.next.coefficient'. +- The long deprecated syntax of color values with underscores (i.e 'on_red') + is no longer supported. +- Correct a false-positive warning when a due date is removed and a wait is + added. +- When GC is turned off, disable the query shortcuts, which no longer apply. + +------ current release --------------------------- + +2.4.4 (2015-05-10) df49aaba126484b668c41d3ff9301f8d8ec49987 - TW-69 wait dates relative to due date (thanks to John Florian). - TW-1285 I'd like to use relative dates combined with times (thanks to Adam @@ -17,7 +232,7 @@ - The 'obfuscate' setting, if set to '1' will replace all text with 'xxx'. - POSIX file locking mechanism, eliminating platform-specific code. ------- current release --------------------------- +------ old releases ------------------------------ 2.4.3 (2015-04-19) 499044b9b6bdbc95338ea585204e949d80b24a09 @@ -531,8 +746,6 @@ - Fixed rc.nag documentation (thanks to Jeroen Budts). - Fixed bug where task edit incorrectly claimed duration UDA was modified. ------- old releases ------------------------------ - 2.2.0 (2013-04-07) 05f7948f7e70d7be3642bdc336faace52eaa9dfb Features diff -Nru task-2.4.4+dfsg/CMakeLists.txt task-2.5.0+dfsg/CMakeLists.txt --- task-2.4.4+dfsg/CMakeLists.txt 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/CMakeLists.txt 2015-10-21 21:18:14.000000000 +0000 @@ -1,8 +1,5 @@ cmake_minimum_required (VERSION 2.8) set(CMAKE_LEGACY_CYGWIN_WIN32 0) # Remove when CMake >= 2.8.4 is required -if(POLICY CMP0037) - cmake_policy(SET CMP0037 OLD) -endif() include (CheckFunctionExists) include (CheckStructHasMember) @@ -10,9 +7,16 @@ set (HAVE_CMAKE true) project (task) -set (PROJECT_VERSION "2.4.4") +set (PROJECT_VERSION "2.5.0") -OPTION(USE_GNUTLS "Build gnutls support." ON) +OPTION (ENABLE_SYNC "Enable 'task sync' support" ON) + +if (ENABLE_SYNC) + set (USE_GNUTLS ON CACHE BOOL "Build gnutls support." FORCE) +else (ENABLE_SYNC) + set (USE_GNUTLS OFF CACHE BOOL "Build gnutls support." FORCE) + message (WARNING "ENABLE_SYNC=OFF. Not building sync support.") +endif (ENABLE_SYNC) message ("CMAKE_SYSTEM_NAME ${CMAKE_SYSTEM_NAME}") @@ -116,6 +120,10 @@ endif (GNUTLS_FOUND) endif (USE_GNUTLS) +if (ENABLE_SYNC AND NOT GNUTLS_FOUND) + message (FATAL_ERROR "Cannot find GnuTLS. Use -DENABLE_SYNC=OFF to build Taskwarrior without sync support. See INSTALL for more information.") +endif (ENABLE_SYNC AND NOT GNUTLS_FOUND) + check_function_exists (timegm HAVE_TIMEGM) check_function_exists (get_current_dir_name HAVE_GET_CURRENT_DIR_NAME) check_function_exists (wordexp HAVE_WORDEXP) @@ -195,5 +203,5 @@ "_CPack_Packages" "cmake_install" "install_manifest" "Makefile$" "test" "package-config" "misc/*" "src/task$" "src/calc$" "performance" "src/libtask.a" "src/columns/libcolumns.a" "src/commands/libcommands.a" - "/\\.gitignore" "/\\.git/" "swp$") + "/\\\\.gitignore" "/\\\\.git/" "swp$" "src/lex$") include (CPack) diff -Nru task-2.4.4+dfsg/debian/changelog task-2.5.0+dfsg/debian/changelog --- task-2.4.4+dfsg/debian/changelog 2015-07-14 06:09:11.000000000 +0000 +++ task-2.5.0+dfsg/debian/changelog 2015-12-11 17:02:01.000000000 +0000 @@ -1,3 +1,9 @@ +task (2.5.0+dfsg-1) unstable; urgency=medium + + * New upstream release: 2.5.0 + + -- Sebastien Badia Wed, 21 Oct 2015 23:22:03 +0200 + task (2.4.4+dfsg-1) unstable; urgency=medium [ Gordon Ball ] diff -Nru task-2.4.4+dfsg/debian/contrib/NEWS task-2.5.0+dfsg/debian/contrib/NEWS --- task-2.4.4+dfsg/debian/contrib/NEWS 2015-07-14 06:09:11.000000000 +0000 +++ task-2.5.0+dfsg/debian/contrib/NEWS 2015-12-11 17:02:01.000000000 +0000 @@ -1,3 +1,58 @@ +# taskwarrior 2.5.0 + +New Features in Taskwarrior 2.5.0 + + - The active context, if one is set, is now identified in "task context list" + - It is an error to attempt adding or removing a virtual tag. + - New 'UDA', 'ORPHAN', 'PROJECT', 'PRIORITY' and 'LATEST' virtual tags. + +New Commands in Taskwarrior 2.5.0 + + - The '_unique' command shows a set of unique values for the specified + attribute + - The 'commands' command shows the supported commands, with additional + details that determine some of their behavior. + +New Configuration Options in Taskwarrior 2.5.0 + + - The 'json.depends.array' setting controls whether dependencies are exported + as a JSON array, of a comma-separated string. Default is 'on'. + Both variations are imported. + - The 'color.uda..none' is a color that is applied to tasks that do + not have a value for the UDA ''. + - A Cygwin fix means that now we can default 'search.case.sensitive' to 'yes', + and all platforms are again equal. + - The new 'recur' verbosity token generates a message when a recurring task is + generated. + - The new 'unwait' verbosity token generates a message when a waiting task + becomes visible. + - The new 'rule.color.merge' configuration option can disable merging of colors + produced by different color rules. Use if your color scheme produces + unpleasing foreground and background combinations. + +Newly Deprecated Features in Taskwarrior 2.5.0 + + - The '_ids', '_projects', '_tags', '_uuids' helper commands are deprecated, + and replaced by the new '_unique' helper command. + - Comma-separated ID lists are deprecated. + - The 'new-uuid' verbosity token is deprecated. Its functionality will + be merged with the 'new-id' verbosity token. + +Removed Features in 2.5.0 + + - The script 'context' was removed, now that context is a core feature. + - Non­extended forms of ISO-8601 date/time support is removed. This means + that 'YYYYMMDD' is no longer supported, but 'YYYY-MM-DD' is. For times, + 'hhmmss' is no longer supported, but 'hh:mm:ss' is. The non-extended + forms all contain sequences of digits that make the identification of + IDs, UUIDs, and various date/time formats ambiguous. + - Comma-separated UUID lists are no longer supported. + - DOM references may no longer be abbreviated. + - The 'urgency.next.coefficient' configuration option is deprecated in favor + of 'urgency.user.tag.next.coefficient'. + - The long deprecated syntax of color values with underscores (i.e 'on_red') + is no longer supported. + # taskwarrior 2.4.4 New Features in Taskwarrior 2.4.4 diff -Nru task-2.4.4+dfsg/debian/patches/001_default-editor.patch task-2.5.0+dfsg/debian/patches/001_default-editor.patch --- task-2.4.4+dfsg/debian/patches/001_default-editor.patch 2015-07-14 06:09:11.000000000 +0000 +++ task-2.5.0+dfsg/debian/patches/001_default-editor.patch 2015-12-11 17:02:01.000000000 +0000 @@ -24,7 +24,7 @@ .B reserved.lines=1 --- a/src/Config.cpp +++ b/src/Config.cpp -@@ -72,7 +72,7 @@ +@@ -71,7 +71,7 @@ "defaultheight=24 # Without detection, assumed height\n" "avoidlastcolumn=no # Fixes Cygwin width problem\n" "hyphenate=on # Hyphenates lines wrapped on non-word-breaks\n" @@ -35,7 +35,7 @@ "# Miscellaneous\n" --- a/src/commands/CmdEdit.cpp +++ b/src/commands/CmdEdit.cpp -@@ -765,13 +765,13 @@ +@@ -780,13 +780,13 @@ std::string before_orig = before; File::write (file.str (), before); diff -Nru task-2.4.4+dfsg/debian/patches/002_enable-warnings.patch task-2.5.0+dfsg/debian/patches/002_enable-warnings.patch --- task-2.4.4+dfsg/debian/patches/002_enable-warnings.patch 2015-07-14 06:09:11.000000000 +0000 +++ task-2.5.0+dfsg/debian/patches/002_enable-warnings.patch 2015-12-11 17:02:01.000000000 +0000 @@ -1,16 +1,16 @@ Description: enable warnings globally Author: Jakub Wilk Forwarded: no -Last-Update: 2015-02-17 +Last-Update: 2015-10-21 --- a/CMakeLists.txt +++ b/CMakeLists.txt -@@ -12,6 +12,8 @@ +@@ -9,6 +9,8 @@ project (task) - set (PROJECT_VERSION "2.4.4") - + set (PROJECT_VERSION "2.5.0") + +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") + - OPTION(USE_GNUTLS "Build gnutls support." ON) - - message ("CMAKE_SYSTEM_NAME ${CMAKE_SYSTEM_NAME}") + OPTION (ENABLE_SYNC "Enable 'task sync' support" ON) + + if (ENABLE_SYNC) diff -Nru task-2.4.4+dfsg/debian/patches/003_fix-groff-warnings.patch task-2.5.0+dfsg/debian/patches/003_fix-groff-warnings.patch --- task-2.4.4+dfsg/debian/patches/003_fix-groff-warnings.patch 2015-07-14 06:09:11.000000000 +0000 +++ task-2.5.0+dfsg/debian/patches/003_fix-groff-warnings.patch 2015-12-11 17:02:01.000000000 +0000 @@ -3,25 +3,9 @@ Forwarded: not-needed Last-Update: 2015-02-17 ---- a/doc/man/task-color.5.in -+++ b/doc/man/task-color.5.in -@@ -243,7 +243,13 @@ - The precedence for the color rules is determined by the configuration - variable 'rule.precedence.color', which by default contains: - -+.na -+.nh -+.cflags 4 , -    due.today,active,blocking,blocked,overdue,due,scheduled,keyword.,project.,tag.,uda.,recurring,pri.,tagged,completed,deleted -+.cflags 0 , -+.hy -+.ad - - These are just the color rules with the 'color.' prefix removed. The - rule 'color.due.today' is the highest precedence, and 'color.deleted' is the lowest. --- a/doc/man/taskrc.5.in +++ b/doc/man/taskrc.5.in -@@ -280,6 +280,9 @@ +@@ -285,6 +285,9 @@ Here are the shortcut equivalents: @@ -29,9 +13,9 @@ +.nh +.cflags 4 , verbose=on - verbose=blank,header,footnote,label,new-id,affected,edit,special,project,sync + verbose=blank,header,footnote,label,new-id,affected,edit,special,project,sync,filter,unwait -@@ -288,6 +291,9 @@ +@@ -293,6 +296,9 @@ verbose=nothing verbose= @@ -41,7 +25,7 @@ Those additional comments are sent to the standard error for header, footnote and project. The others are sent to standard output. -@@ -686,7 +692,7 @@ +@@ -701,7 +707,7 @@ .TP .B calendar.offset.value=-1 The offset value to apply to the first month in the calendar report. The default @@ -50,7 +34,7 @@ .TP .B calendar.holidays=full -@@ -1028,9 +1034,15 @@ +@@ -1064,9 +1070,15 @@ .RE .TP @@ -71,14 +55,30 @@ lowest. Note that the prefix 'color.' is omitted (for brevity), and that any --- a/doc/man/task.1.in +++ b/doc/man/task.1.in -@@ -657,8 +657,8 @@ - COMPLETED Matches if the task has completed status - DELETED Matches if the task has deleted status +@@ -698,8 +698,8 @@ + + .\" If you update the above list, update src/commands/CmdInfo.cpp and src/commands/CmdTags.cpp as well. -You can use +BLOCKED to filter blocked tasks, or -BLOCKED for unblocked tasks. --Similarly, -BLOCKED is equivalent to +UNBLOCKED. +-Similarly, -BLOCKED is equivalent to +UNBLOCKED. It is an error to attempt to +You can use +BLOCKED to filter blocked tasks, or \-BLOCKED for unblocked tasks. -+Similarly, \-BLOCKED is equivalent to +UNBLOCKED. ++Similarly, \-BLOCKED is equivalent to +UNBLOCKED. It is an error to attempt to + add or remove a virtual tag. .TP - .B project: +--- a/doc/man/task-color.5.in ++++ b/doc/man/task-color.5.in +@@ -246,7 +246,13 @@ + The precedence for the color rules is determined by the configuration + variable 'rule.precedence.color', which by default contains: + ++.na ++.nh ++.cflags 4 , + deleted,completed,active,keyword.,tag.,project.,overdue,scheduled,due.today,due,blocked,blocking,recurring,tagged,uda. ++.cflags 0 , ++.hy ++.ad + + These are just the color rules with the 'color.' prefix removed. The + rule 'color.due.today' is the highest precedence, and 'color.deleted' is the lowest. diff -Nru task-2.4.4+dfsg/debian/patches/005_tests-time-independent.patch task-2.5.0+dfsg/debian/patches/005_tests-time-independent.patch --- task-2.4.4+dfsg/debian/patches/005_tests-time-independent.patch 2015-07-14 06:09:11.000000000 +0000 +++ task-2.5.0+dfsg/debian/patches/005_tests-time-independent.patch 2015-12-11 17:02:01.000000000 +0000 @@ -6,7 +6,7 @@ --- a/test/version.t +++ b/test/version.t @@ -55,7 +55,7 @@ - code, out, err = self.t(("version",)) + code, out, err = self.t("version") expected = "Copyright \(C\) \d{4} - %d" % (datetime.now().year,) - self.assertRegexpMatches(out, expected) diff -Nru task-2.4.4+dfsg/debian/patches/006_update-basetest-prefix.patch task-2.5.0+dfsg/debian/patches/006_update-basetest-prefix.patch --- task-2.4.4+dfsg/debian/patches/006_update-basetest-prefix.patch 2015-07-14 06:09:11.000000000 +0000 +++ task-2.5.0+dfsg/debian/patches/006_update-basetest-prefix.patch 2015-12-11 17:02:01.000000000 +0000 @@ -7,7 +7,7 @@ --- a/test/basetest/utils.py +++ b/test/basetest/utils.py -@@ -23,7 +23,7 @@ +@@ -28,7 +28,7 @@ # Location of binary files (usually the src/ folder) BIN_PREFIX = os.path.abspath( diff -Nru task-2.4.4+dfsg/debian/patches/007_remove-date-time-from-source.diff task-2.5.0+dfsg/debian/patches/007_remove-date-time-from-source.diff --- task-2.4.4+dfsg/debian/patches/007_remove-date-time-from-source.diff 2015-07-14 06:09:11.000000000 +0000 +++ task-2.5.0+dfsg/debian/patches/007_remove-date-time-from-source.diff 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -Description: Remove binary timestamp (reproductible builds) -Author: Gordon Ball - ---- a/src/commands/CmdDiagnostics.cpp -+++ b/src/commands/CmdDiagnostics.cpp -@@ -155,8 +155,6 @@ - out << bold.colorize (STRING_CMD_DIAG_FEATURES) - << "\n" - -- // Build date. -- << " " << STRING_CMD_DIAG_BUILT << ": " << __DATE__ << " " << __TIME__ << "\n" - #ifdef HAVE_COMMIT - << " " << STRING_CMD_DIAG_COMMIT << ": " << COMMIT << "\n" - #endif diff -Nru task-2.4.4+dfsg/debian/patches/007_remove-date-time-from-source.patch task-2.5.0+dfsg/debian/patches/007_remove-date-time-from-source.patch --- task-2.4.4+dfsg/debian/patches/007_remove-date-time-from-source.patch 1970-01-01 00:00:00.000000000 +0000 +++ task-2.5.0+dfsg/debian/patches/007_remove-date-time-from-source.patch 2015-12-11 17:02:01.000000000 +0000 @@ -0,0 +1,14 @@ +Description: Remove binary timestamp (reproductible builds) +Author: Gordon Ball + +--- a/src/commands/CmdDiagnostics.cpp ++++ b/src/commands/CmdDiagnostics.cpp +@@ -161,8 +161,6 @@ + out << bold.colorize (STRING_CMD_DIAG_FEATURES) + << "\n" + +- // Build date. +- << " " << STRING_CMD_DIAG_BUILT << ": " << __DATE__ << " " << __TIME__ << "\n" + #ifdef HAVE_COMMIT + << " " << STRING_CMD_DIAG_COMMIT << ": " << COMMIT << "\n" + #endif diff -Nru task-2.4.4+dfsg/debian/patches/series task-2.5.0+dfsg/debian/patches/series --- task-2.4.4+dfsg/debian/patches/series 2015-07-14 06:09:11.000000000 +0000 +++ task-2.5.0+dfsg/debian/patches/series 2015-12-11 17:02:01.000000000 +0000 @@ -4,4 +4,4 @@ 004_no-task-ref.patch 005_tests-time-independent.patch 006_update-basetest-prefix.patch -007_remove-date-time-from-source.diff +007_remove-date-time-from-source.patch diff -Nru task-2.4.4+dfsg/DEVELOPER task-2.5.0+dfsg/DEVELOPER --- task-2.4.4+dfsg/DEVELOPER 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/DEVELOPER 2015-10-21 21:18:14.000000000 +0000 @@ -1,15 +1,16 @@ How to Build Taskwarrior Satisfy the Requirements: - - gcc 4.7 or later, clang 3.3 or later or equivalent. This is because 2.4.4 - will be utilizing C++11. + - gcc 4.7 or later, clang 3.3 or later or equivalent. This is because C++11 + is now used. - libuuid - gnutls (optional) + - python 2.7 or 3 (optional, for running the test suite) Obtain and build code: $ git clone https://git.tasktools.org/scm/tm/task.git task.git $ cd task.git - $ git checkout 2.4.4 # Latest dev branch + $ git checkout 2.5.0 # Latest dev branch $ cmake -DCMAKE_BUILD_TYPE=debug . # debug or release. Default: neither. $ make VERBOSE=1 # Shows details @@ -17,7 +18,6 @@ $ cd tests $ make VERBOSE=1 # Shows details $ ./run_all # Runs all tests silently > all.log - # Install 'vramsteg' for blinkenlights $ ./problems # Enumerate test failures in all.log Note that any development should be performed using a git clone, and the @@ -71,8 +71,7 @@ all, because they not only improve the quality of the code, but prevent future regressions, therefore maintaining quality of subsequent releases. Plus, broken tests are a great motivator for us to fix the causal defect. - You'll need Python skills, as we are migrating from Perl to Python for our - test suite. + You'll need Python skills. - Add a feature. Well, let's be very clear about this: adding a feature is not usually well-received, and if you add a feature and send a patch, it @@ -93,7 +92,7 @@ - Spread the word. Help others become more effective at managing tasks. - Encouragement. Tell us what works for you, and what doesn't. Tell us about - your methodology for managing tasks. It's all good. + your methodology for managing tasks. It's all useful information. - Request a feature. This not only tells us that you think something is missing from the software, but gives us insights into how you use it. @@ -101,27 +100,9 @@ Next are some specific areas that need attention. -Deprecated Code - This is code that is going to be phased out soon, and therefore is not worth - fixing or documenting. Don't waste your time. - - - Priorities in core. This will be migrated to become a UDA as soon as we - have the right support in place for custom sorting. - - - Nag feature. - - - Attribute modifiers. - New Code Needs This is code that needs to be written. - - Need export_viz.* script. Any language. This would have value as an example - or template script serving as a starting-point for anyone who needed this - format. - - Need new export_xxx.* scripts - the more the better. Any language. - - The JSON.{h,cpp} code is fast and efficient up to a point, but has a non- - linear performance curve, implying a slowdown due to fragmentation, but who - know? Find it, fix it. - Need an external script that can locate and correct duplicate UUIDs in the data file, as found by 'task diag'. This should check to see if there is a suitable UUID generator installed. This should also be careful to @@ -142,39 +123,28 @@ For example, dependencies.t runs through a long list of commands that test dependencies, but do so by using 'add', 'modify', 'done' and 'delete'. 2. Regression tests that ensure certain bugs are fixed and stay fixed. These - tests are named bug.NNN.t where NNN refers to the Redmine issue number. - While it is not worth creating tests for small fixes like typos, it is for - changes to the logic. + tests are named bug.NNN.t where NNN refers to the bug number. While it is + not worth creating tests for small fixes like typos, it is for changes to + the logic. 3. Small feature tests. When small features are added, we would like small, - low-level feature tests named feature.NNN.t, where NNN is the Redmine - issue number. + low-level feature tests named feature.t, with a descriptive name and + focused tests. 4. Code tests. These are tests written in C++ that exercise C++ objects, or function calls. These are the lowest level tests. It is important that these kind of tests be extensive and thorough, because the software depends on this code the most. - The tests are mainly written in Perl, and all use TAP. We want them all to be - eventually replaced by Python, so we are now only accepting new tests that use - the Python-based approach you can see in some of the existing tests. + The tests are written in Python, Bash and C++, and all use TAP. Tests needed: - Take a look at the bug database (https://bug.tasktools.org) and notice that many issues, open and closed, have the "needsTest" label. These are things that we would like to see in the test suite, as regression tests. - - The basic.t unit tests are a misnomer, and should be either removed or - renamed. We have long talked of 'basic functionality' that includes add, - delete, done, and list commands. We need unit tests that prove that basic - functionality is working, and the file containing them should be called - basic.t. - - Test propagation of modifications to recurring tasks. - Test regex support. - Need unit tests for each bug in the issue list that is marked with the 'needsTest' label. - Note that running the unit tests currently requires the Perl JSON module to - be installed. - Note that all new unit tests should follow the test/template.t standard. Work in Progress @@ -188,11 +158,11 @@ Current Codebase Condition 'master' branch: - - 2.4.3 Current release, locked. + - 2.4.4 Current release, locked. - '2.4.4' branch: + '2.5.0' branch: - Current development branch no plans yet. --- -2015-04-21 Updated for 2.4.4 +2015-09-07 Updated for 2.5.0 diff -Nru task-2.4.4+dfsg/doc/man/task.1.in task-2.5.0+dfsg/doc/man/task.1.in --- task-2.4.4+dfsg/doc/man/task.1.in 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/man/task.1.in 2015-10-21 21:18:14.000000000 +0000 @@ -1,4 +1,4 @@ -.TH task 1 2015-05-10 "${PACKAGE_STRING}" "User Manuals" +.TH task 1 2015-10-21 "${PACKAGE_STRING}" "User Manuals" .SH NAME task \- A command line todo manager. @@ -67,12 +67,12 @@ implicit report filter which would be combined with an implicit 'and'. A filter may target specific tasks using ID or UUID numbers. To specify -multiple tasks use one of these forms (comma or space-separated list of ID -numbers, UUID numbers or ID ranges): +multiple tasks use one of these forms (space-separated list of ID numbers, +UUID numbers or ID ranges): - task 1,2,3 delete + task 1 2 3 delete task 1-3 info - task 1,2-5,19 modify pri:H + task 1 2-5 19 modify pri:H task 4-7 ebeeab00-ccf8-464b-8b58-f7f2d606edfb info .SH MODIFICATIONS @@ -162,6 +162,10 @@ shown. .TP +.B task commands +Shows all the supported commands, with some details of each. + +.TP .B task completed Shows all tasks matching the filter that are completed. @@ -212,8 +216,8 @@ .TP .B task ids Applies the filter then extracts only the task IDs and presents them as -a range, for example: 1-4,12. This is useful as input to a task command, -to achieve this: +a space-separated list. This is useful as input to a task command, to achieve +this: task $(task project:Home ids) modify priority:H @@ -345,9 +349,17 @@ provided for exceptional circumstances. Use carefully. .TP -.B task import [ ...] -Imports tasks in the JSON format. The standard task release comes with a few -example scripts, such as: +.B task import [ ...] +Imports tasks in the JSON format. Can be used to add new tasks, or update +existing ones. Tasks are identified by their UUID. + +If no file or "-" is specified, import tasks from STDIN. + +Setting rc.recurrence.confirmation to an appropriate level is recommended +if import is to be used in automated workflows. See taskrc(5). + +For importing other file formats, the standard task release comes with a +few example scripts, such as: import-todo.sh.pl import-yaml.pl @@ -446,7 +458,7 @@ .TP .B task context none -Unsets the currently active context, if any was set. +Clears the currently active context, if any was set. .TP .B task context show @@ -496,9 +508,10 @@ .TP .B task tags -Show a list of all tags used. Any special tags used are highlighted. Note that +Show a list of all tags used. Any special tags used are highlighted. Note that virtual tags are not listed - they don't really exist, and are just a convenient -notation for other task metadata. +notation for other task metadata. It is an error to attempt to add or remove a +virtual tag. .TP .B task timesheet [weeks] @@ -537,6 +550,7 @@ .TP .B task _ids Shows only the IDs of matching tasks, in the form of a list. +Deprecated in favor of _unique. .TP .B task _show @@ -544,9 +558,17 @@ by third-party applications. .TP +.B task _unique +Reports a unique set of attribute values. For example, to see all the active +projects: + + task +PENDING _unique projects + +.TP .B task _uuids Shows only the UUIDs of matching tasks among all tasks (even deleted and completed tasks), in the form of a list. +Deprecated in favor of _unique. .TP .B task _udas @@ -555,10 +577,12 @@ .TP .B task _projects Shows only a list of all project names used. +Deprecated in favor of _unique. .TP .B task _tags Shows only a list of all tags used, for autocompletion purposes. +Deprecated in favor of _unique. .TP .B task _urgency @@ -601,6 +625,16 @@ Note that if the DOM reference is not valid, or the reference evaluates to a missing value, the command exits with 1. +Additionally, some components of the attributes of particular types may be +extracted by DOM references. + + $ task _get 2.due.year + 2015 + +For a full list of supported attribute-specific DOM references, consult +the online documentation at: + + .SH ATTRIBUTES AND METADATA .TP @@ -632,33 +666,41 @@ tags do not exist, but can be used to filter tasks. The supported virtual tags are: + ACTIVE Matches if the task is started + ANNOTATED Matches if the task has annotations BLOCKED Matches if the task is blocked - UNBLOCKED Matches if the task is not blocked BLOCKING Matches if the task is blocking - YESTERDAY Matches if the task was due sometime yesterday + CHILD Matches if the task has a parent + COMPLETED Matches if the task has completed status + DELETED Matches if the task has deleted status DUE Matches if the task is due DUETODAY Matches if the task is due today - TODAY Matches if the task is due today - TOMORROW Matches if the task is due sometime tomorrow - WEEK Matches if the task is due this week + LATEST Matches if the task is the newest added task MONTH Matches if the task is due this month - YEAR Matches if the task is due this year + ORPHAN Matches if the task has any orphaned UDA values OVERDUE Matches if the task is overdue - ACTIVE Matches if the task is started - SCHEDULED Matches if the task is scheduled - READY Matches if the task is actionable PARENT Matches if the task is a parent - CHILD Matches if the task has a parent + PENDING Matches if the task has pending status + PRIORITY Matches if the task has a priority + PROJECT Matches if the task has a project + READY Matches if the task is actionable + SCHEDULED Matches if the task is scheduled + TAGGED Matches if the task has tags + TODAY Matches if the task is due today + TOMORROW Matches if the task is due sometime tomorrow + UDA Matches if the task has any UDA values + UNBLOCKED Matches if the task is not blocked UNTIL Matches if the task expires WAITING Matches if the task is waiting - ANNOTATED Matches if the task has annotations - TAGGED Matches if the task has tags - PENDING Matches if the task has pending status - COMPLETED Matches if the task has completed status - DELETED Matches if the task has deleted status + WEEK Matches if the task is due this week + YEAR Matches if the task is due this year + YESTERDAY Matches if the task was due sometime yesterday + +.\" If you update the above list, update src/commands/CmdInfo.cpp and src/commands/CmdTags.cpp as well. You can use +BLOCKED to filter blocked tasks, or -BLOCKED for unblocked tasks. -Similarly, -BLOCKED is equivalent to +UNBLOCKED. +Similarly, -BLOCKED is equivalent to +UNBLOCKED. It is an error to attempt to +add or remove a virtual tag. .TP .B project: @@ -693,7 +735,9 @@ .TP .B wait: -Date until task becomes pending. +When a task is given a wait date, it is hidden from most reports by changing +its status to 'waiting'. When that date is passed, the status is changed back +to 'pending', and the task becomes visible. .TP .B depends: @@ -711,7 +755,7 @@ Attribute modifiers improve filters. Supported modifiers are: .RS -.B before (synonyms under, below) +.B before (synonyms under, below) .br .B after (synonyms over, above) .br @@ -829,14 +873,33 @@ You can use the following operators in filter expressions: - and or xor Logical operators - < <= = != >= > Relational operators - ( ) Precedence + and or xor ! Logical operators + < <= = == != !== >= > Relational operators + ( ) Precedence For example: task due.before:eom priority.not:L list - task '( due < eom or priority != L )' list + task '( due < eom or priority != L )' list + task '! ( project:Home or project:Garden )' list + +The +.I = +operator tests for approximate equality. Dates compare +equal if they are on the same day (hour and minutes are ignored). +Strings compare equal if the left operand starts with the right operand. +The +.I == +operator tests for exact equality. The +.I != +and +.I !== +operators are the negation of +.I = +and +.I == +respectively. The negation operator is +.IR ! . Note that the parentheses are required when using a logical operator other than the 'and' operator. The reason is that some reports contain filters that must @@ -897,7 +960,7 @@ .TP ISO-8601 -task ... due:20130314T223000Z +task ... due:2013-03-14T22:30:00Z .TP Relative wording diff -Nru task-2.4.4+dfsg/doc/man/task-color.5.in task-2.5.0+dfsg/doc/man/task-color.5.in --- task-2.4.4+dfsg/doc/man/task-color.5.in 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/man/task-color.5.in 2015-10-21 21:18:14.000000000 +0000 @@ -1,4 +1,4 @@ -.TH task-color 5 2015-05-10 "${PACKAGE_STRING}" "User Manuals" +.TH task-color 5 2015-10-21 "${PACKAGE_STRING}" "User Manuals" .SH NAME task-color \- A color tutorial for the Taskwarrior command line todo manager. @@ -240,10 +240,13 @@ those colors can be made subtle, and complementary, but without care, this can be a visual mess. Beware! +In such cases, consider using the 'rule.color.merge=no' option to disable the +color blending. + The precedence for the color rules is determined by the configuration variable 'rule.precedence.color', which by default contains: -    due.today,active,blocking,blocked,overdue,due,scheduled,keyword.,project.,tag.,uda.,recurring,pri.,tagged,completed,deleted + deleted,completed,active,keyword.,tag.,project.,overdue,scheduled,due.today,due,blocked,blocking,recurring,tagged,uda. These are just the color rules with the 'color.' prefix removed. The rule 'color.due.today' is the highest precedence, and 'color.deleted' is the lowest. diff -Nru task-2.4.4+dfsg/doc/man/taskrc.5.in task-2.5.0+dfsg/doc/man/taskrc.5.in --- task-2.4.4+dfsg/doc/man/taskrc.5.in 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/man/taskrc.5.in 2015-10-21 21:18:14.000000000 +0000 @@ -1,4 +1,4 @@ -.TH taskrc 5 2015-05-10 "${PACKAGE_STRING}" "User Manuals" +.TH taskrc 5 2015-10-21 "${PACKAGE_STRING}" "User Manuals" .SH NAME taskrc \- Configuration details for the task(1) command @@ -267,13 +267,18 @@ footnote Messages that appear after report output label Column labels on tabular reports new-id Provides feedback of any new task IDs - new-uuid Provides feedback of any new task UUIDs + new-uuid Provides feedback of any new task UUIDs. Deprecated, to be + merged with new-id. affected Reports 'N tasks affected' and similar edit Used the verbose template for the 'edit' command special Feedback when applying special tags project Feedback about project status changes sync Feedback about sync filter Shows the filter used in the command + unwait Notification when a task leaves the 'waiting' state + recur Notification when a new recurring task instance is created + +"affected", "new-id", "new-uuid" "project" and "unwait" imply "footnote". Note that the "on" setting is equivalent to all the tokens being specified, and the "nothing" setting is equivalent to none of the tokens being specified. @@ -281,7 +286,7 @@ Here are the shortcut equivalents: verbose=on - verbose=blank,header,footnote,label,new-id,affected,edit,special,project,sync + verbose=blank,header,footnote,label,new-id,affected,edit,special,project,sync,filter,unwait verbose=off verbose=blank,label,new-id,edit @@ -392,9 +397,18 @@ command line. Defaults to on. .TP -.B json.array=off -Determines whether the query command encloses the JSON output in '[...]' to -create a properly-formed JSON array. Defaults to off. +.B json.array=on +Determines whether the export command encloses the JSON output in '[...]' and +adds ',' after each exported task object to create a properly-formed JSON +array. +With json.array=off, export writes raw JSON objects to STDOUT, one per line. +Defaults to on. + +.TP +.B json.depends.array=on +Determines whether the export command encodes dependencies as an array of string +UUIDs, or one comma-separated string. +Defaults to on. .TP .B _forcecolor=no @@ -431,7 +445,7 @@ .TP .B recurrence=yes -Controls whether recurrence is enable, and whether recurring tasks continue to +Controls whether recurrence is enabled, and whether recurring tasks continue to generate new task instances. Defaults to 'yes'. .TP @@ -493,9 +507,10 @@ .TP .B debug.parser=0 -Controls the parser diagnostic level. Level 0 means no diagnostics. Level 1 -shows the parse tree. Level 2 shows expression evaluation details. Level 3 -shows parse trees from every phase of the parse. +Controls the parser diagnostic level. Level 0 shows no diagnostics. +Level 1 shows the final parse tree. +Level 2 shows the parse tree from all phases of the parse. +Level 3 shows expression evaluation details. .TP .B debug.tls=0 @@ -614,17 +629,17 @@ .RS .RS .br -a D b Y (V) would do an output as "Fri 24 Jul 2009 (30)" +a D b Y (V) would emit "Fri 24 Jul 2009 (30)" .br -A, B D, Y would do an output as "Friday, July 24, 2009" +A, B D, Y would emit "Friday, July 24, 2009" .br -wV a Y-M-D would do an output as "w30 Fri 2009-07-24" +wV a Y-M-D would emit "w30 Fri 2009-07-24" .br -yMD.HN would do an output as "110124.2342" +yMD.HN would emit "110124.2342" .br -m/d/Y H:N would do an output as "1/24/2011 10:42" +m/d/Y H:N would emit "1/24/2011 10:42" .br -a D b Y H:N:S would do an output as "Mon 24 Jan 2011 11:19:42" +a D b Y H:N:S would emit "Mon 24 Jan 2011 11:19:42" .RE .RE @@ -868,6 +883,22 @@ .RE .RE +.RS +By default, colors produced by rules blend. This has the advantage of +conveying additional information, by producing combinations that are not used +by any particular rule directly. + +However, color blending can produce highlighting combinations which are not +desired. In such cases, use the following option to disable this behaviour: +.RE + +.TP +.B rule.color.merge=yes +Can be "yes" or "no". When "no", disables merging of colors produced by +different color rules. Use if your color scheme produces unpleasing +foreground and background combinations. + + See the task-color(5) man pages for color details. .RE @@ -901,6 +932,11 @@ .RE .TP +.B color.uda.X.none=on green +Colors any task that does not have the user defined attribute X. +.RE + +.TP .B color.error=green Colors any of the error messages. .RE @@ -1050,10 +1086,6 @@ has a configurable coefficient. Those coefficients are: .TP -.B urgency.next.coefficient=15.0 -.RS -Urgency coefficient for 'next' special tag -.RE .B urgency.blocking.coefficient=8.0 .RS Urgency coefficient for blocking tasks @@ -1062,10 +1094,6 @@ .RS Urgency coefficient for blocked tasks .RE -.B urgency.inherit.coefficient=0.0 -.RS -Urgency inherited from dependency chain -.RE .B urgency.due.coefficient=12.0 .RS Urgency coefficient for due dates @@ -1106,6 +1134,10 @@ .RS Specific tag coefficient. .RE +.B urgency.user.tag.next.coefficient=15.0 +.RS +Urgency coefficient for tag 'next'. +.RE .B urgency.user.project..coefficient=... .RS Specific project coefficient. @@ -1127,6 +1159,16 @@ urgency calculation. These are default values, and may be modified to suit your preferences, but it is important that you carefully consider any modifications. +.B urgency.inherit=off +.RS +Not actually a coefficient. When enabled, blocking tasks inherit +the highest urgency value found in the tasks they block. This is +done recursively. +It is recommended to set urgency.blocking.coefficient and +urgency.blocked.coefficient to 0.0 in order for this setting to +be the most useful. +.RE + .SS DEFAULTS .TP @@ -1224,6 +1266,9 @@ project. A listing break is simply a blank line, which provides a visual grouping. +A special sort value of "none" indicates that no sorting is required, and tasks +will be presented in the order (if any) in which they are selected. + .TP .B report.X.filter This adds a filter to the report X so that only tasks matching the filter @@ -1240,9 +1285,11 @@ .TP .B report.X.annotations This adds the possibility to control the output of annotations for a task in a -report. See the -.B annotations -variable for details on the possible values. Deprecated. +report. Deprecated. Use the +.B description +column with a format (e.g., +\fBdescription.count\fP) +instead. .TP Taskwarrior comes with a number of predefined reports, which are: @@ -1376,9 +1423,9 @@ .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. +can be found in the task(1) man page. -The current context is stored in the taskrc file, along with definitions for +The current context is stored in the .taskrc file, along with definitions for all user provided contexts. .TP diff -Nru task-2.4.4+dfsg/doc/man/task-sync.5.in task-2.5.0+dfsg/doc/man/task-sync.5.in --- task-2.4.4+dfsg/doc/man/task-sync.5.in 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/man/task-sync.5.in 2015-10-21 21:18:14.000000000 +0000 @@ -1,4 +1,4 @@ -.TH task-sync 5 2015-05-10 "${PACKAGE_STRING}" "User Manuals" +.TH task-sync 5 2015-10-21 "${PACKAGE_STRING}" "User Manuals" .SH NAME task-sync \- A discussion and tutorial for the various task(1) data diff -Nru task-2.4.4+dfsg/doc/rc/holidays.be-BY.rc task-2.5.0+dfsg/doc/rc/holidays.be-BY.rc --- task-2.4.4+dfsg/doc/rc/holidays.be-BY.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.be-BY.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/be-BY/2014.json # http://holidata.net/be-BY/2015.json +# http://holidata.net/be-BY/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,62 +28,42 @@ ############################################################################### holiday.be-BY1.name=Новы Год -holiday.be-BY1.date=20140101 +holiday.be-BY1.date=20150101 holiday.be-BY2.name=Раство Хрыстова(праваслаўнае) -holiday.be-BY2.date=20140107 +holiday.be-BY2.date=20150107 holiday.be-BY3.name=Міжнародны жаночы дзень -holiday.be-BY3.date=20140803 +holiday.be-BY3.date=20150803 holiday.be-BY4.name=Пасха(праваслаўная) -holiday.be-BY4.date=20140420 +holiday.be-BY4.date=20150420 holiday.be-BY5.name=Радуніца -holiday.be-BY5.date=20140429 +holiday.be-BY5.date=20150421 holiday.be-BY6.name=Свята працы -holiday.be-BY6.date=20140501 +holiday.be-BY6.date=20150501 holiday.be-BY7.name=Дзень Перамогі -holiday.be-BY7.date=20140509 +holiday.be-BY7.date=20150509 holiday.be-BY8.name=Дзень незалежнаці -holiday.be-BY8.date=20140703 +holiday.be-BY8.date=20150703 holiday.be-BY9.name=Дзень Кастрычніцкай рэвалюцыі -holiday.be-BY9.date=20141107 +holiday.be-BY9.date=20151107 holiday.be-BY10.name=Раство Хрыстова(у заходніх хрысціян) -holiday.be-BY10.date=20141225 +holiday.be-BY10.date=20151225 holiday.be-BY11.name=Новы Год -holiday.be-BY11.date=20150101 +holiday.be-BY11.date=20160101 holiday.be-BY12.name=Раство Хрыстова(праваслаўнае) -holiday.be-BY12.date=20150107 +holiday.be-BY12.date=20160107 holiday.be-BY13.name=Міжнародны жаночы дзень -holiday.be-BY13.date=20150803 +holiday.be-BY13.date=20160803 holiday.be-BY14.name=Пасха(праваслаўная) -holiday.be-BY14.date=20150420 +holiday.be-BY14.date=20160327 holiday.be-BY15.name=Радуніца -holiday.be-BY15.date=20150421 +holiday.be-BY15.date=20160510 holiday.be-BY16.name=Свята працы -holiday.be-BY16.date=20150501 +holiday.be-BY16.date=20160501 holiday.be-BY17.name=Дзень Перамогі -holiday.be-BY17.date=20150509 +holiday.be-BY17.date=20160509 holiday.be-BY18.name=Дзень незалежнаці -holiday.be-BY18.date=20150703 +holiday.be-BY18.date=20160703 holiday.be-BY19.name=Дзень Кастрычніцкай рэвалюцыі -holiday.be-BY19.date=20151107 +holiday.be-BY19.date=20161107 holiday.be-BY20.name=Раство Хрыстова(у заходніх хрысціян) -holiday.be-BY20.date=20151225 -holiday.be-BY21.name=Новы Год -holiday.be-BY21.date=20160101 -holiday.be-BY22.name=Раство Хрыстова(праваслаўнае) -holiday.be-BY22.date=20160107 -holiday.be-BY23.name=Міжнародны жаночы дзень -holiday.be-BY23.date=20160803 -holiday.be-BY24.name=Пасха(праваслаўная) -holiday.be-BY24.date=20160327 -holiday.be-BY25.name=Радуніца -holiday.be-BY25.date=20160510 -holiday.be-BY26.name=Свята працы -holiday.be-BY26.date=20160501 -holiday.be-BY27.name=Дзень Перамогі -holiday.be-BY27.date=20160509 -holiday.be-BY28.name=Дзень незалежнаці -holiday.be-BY28.date=20160703 -holiday.be-BY29.name=Дзень Кастрычніцкай рэвалюцыі -holiday.be-BY29.date=20161107 -holiday.be-BY30.name=Раство Хрыстова(у заходніх хрысціян) -holiday.be-BY30.date=20161225 +holiday.be-BY20.date=20161225 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.cs-CZ.rc task-2.5.0+dfsg/doc/rc/holidays.cs-CZ.rc --- task-2.4.4+dfsg/doc/rc/holidays.cs-CZ.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.cs-CZ.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/cs-CZ/2014.json # http://holidata.net/cs-CZ/2015.json +# http://holidata.net/cs-CZ/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,80 +28,54 @@ ############################################################################### holiday.cs-CZ1.name=Nový rok -holiday.cs-CZ1.date=20140101 +holiday.cs-CZ1.date=20150101 holiday.cs-CZ2.name=Den obnovy samostatnosti českého státu -holiday.cs-CZ2.date=20140101 +holiday.cs-CZ2.date=20150101 holiday.cs-CZ3.name=Velikonoční pondělí -holiday.cs-CZ3.date=20140421 +holiday.cs-CZ3.date=20150406 holiday.cs-CZ4.name=Svátek práce -holiday.cs-CZ4.date=20140501 +holiday.cs-CZ4.date=20150501 holiday.cs-CZ5.name=Den vítězství -holiday.cs-CZ5.date=20140508 +holiday.cs-CZ5.date=20150508 holiday.cs-CZ6.name=Den slovanských věrozvěstů -holiday.cs-CZ6.date=20140705 +holiday.cs-CZ6.date=20150705 holiday.cs-CZ7.name=Den upálení mistra Jana Husa -holiday.cs-CZ7.date=20140706 +holiday.cs-CZ7.date=20150706 holiday.cs-CZ8.name=Den české státnosti -holiday.cs-CZ8.date=20140928 +holiday.cs-CZ8.date=20150928 holiday.cs-CZ9.name=Den vzniku samostatného československého státu -holiday.cs-CZ9.date=20141028 +holiday.cs-CZ9.date=20151028 holiday.cs-CZ10.name=Den boje za svobodu a demokracii -holiday.cs-CZ10.date=20141117 +holiday.cs-CZ10.date=20151117 holiday.cs-CZ11.name=Štědrý den -holiday.cs-CZ11.date=20141224 +holiday.cs-CZ11.date=20151224 holiday.cs-CZ12.name=1. svátek vánoční -holiday.cs-CZ12.date=20141225 +holiday.cs-CZ12.date=20151225 holiday.cs-CZ13.name=2. svátek vánoční -holiday.cs-CZ13.date=20141226 +holiday.cs-CZ13.date=20151226 holiday.cs-CZ14.name=Nový rok -holiday.cs-CZ14.date=20150101 +holiday.cs-CZ14.date=20160101 holiday.cs-CZ15.name=Den obnovy samostatnosti českého státu -holiday.cs-CZ15.date=20150101 +holiday.cs-CZ15.date=20160101 holiday.cs-CZ16.name=Velikonoční pondělí -holiday.cs-CZ16.date=20150406 +holiday.cs-CZ16.date=20160328 holiday.cs-CZ17.name=Svátek práce -holiday.cs-CZ17.date=20150501 +holiday.cs-CZ17.date=20160501 holiday.cs-CZ18.name=Den vítězství -holiday.cs-CZ18.date=20150508 +holiday.cs-CZ18.date=20160508 holiday.cs-CZ19.name=Den slovanských věrozvěstů -holiday.cs-CZ19.date=20150705 +holiday.cs-CZ19.date=20160705 holiday.cs-CZ20.name=Den upálení mistra Jana Husa -holiday.cs-CZ20.date=20150706 +holiday.cs-CZ20.date=20160706 holiday.cs-CZ21.name=Den české státnosti -holiday.cs-CZ21.date=20150928 +holiday.cs-CZ21.date=20160928 holiday.cs-CZ22.name=Den vzniku samostatného československého státu -holiday.cs-CZ22.date=20151028 +holiday.cs-CZ22.date=20161028 holiday.cs-CZ23.name=Den boje za svobodu a demokracii -holiday.cs-CZ23.date=20151117 +holiday.cs-CZ23.date=20161117 holiday.cs-CZ24.name=Štědrý den -holiday.cs-CZ24.date=20151224 +holiday.cs-CZ24.date=20161224 holiday.cs-CZ25.name=1. svátek vánoční -holiday.cs-CZ25.date=20151225 +holiday.cs-CZ25.date=20161225 holiday.cs-CZ26.name=2. svátek vánoční -holiday.cs-CZ26.date=20151226 -holiday.cs-CZ27.name=Nový rok -holiday.cs-CZ27.date=20160101 -holiday.cs-CZ28.name=Den obnovy samostatnosti českého státu -holiday.cs-CZ28.date=20160101 -holiday.cs-CZ29.name=Velikonoční pondělí -holiday.cs-CZ29.date=20160328 -holiday.cs-CZ30.name=Svátek práce -holiday.cs-CZ30.date=20160501 -holiday.cs-CZ31.name=Den vítězství -holiday.cs-CZ31.date=20160508 -holiday.cs-CZ32.name=Den slovanských věrozvěstů -holiday.cs-CZ32.date=20160705 -holiday.cs-CZ33.name=Den upálení mistra Jana Husa -holiday.cs-CZ33.date=20160706 -holiday.cs-CZ34.name=Den české státnosti -holiday.cs-CZ34.date=20160928 -holiday.cs-CZ35.name=Den vzniku samostatného československého státu -holiday.cs-CZ35.date=20161028 -holiday.cs-CZ36.name=Den boje za svobodu a demokracii -holiday.cs-CZ36.date=20161117 -holiday.cs-CZ37.name=Štědrý den -holiday.cs-CZ37.date=20161224 -holiday.cs-CZ38.name=1. svátek vánoční -holiday.cs-CZ38.date=20161225 -holiday.cs-CZ39.name=2. svátek vánoční -holiday.cs-CZ39.date=20161226 +holiday.cs-CZ26.date=20161226 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.da-DK.rc task-2.5.0+dfsg/doc/rc/holidays.da-DK.rc --- task-2.4.4+dfsg/doc/rc/holidays.da-DK.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.da-DK.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/da-DK/2014.json # http://holidata.net/da-DK/2015.json +# http://holidata.net/da-DK/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -27,69 +27,47 @@ # ############################################################################### -holiday.da-DK1.name=Grundlovsdag -holiday.da-DK1.date=20140605 -holiday.da-DK2.name=Nytårsdag -holiday.da-DK2.date=20140101 -holiday.da-DK3.name=Skærtorsdag -holiday.da-DK3.date=20140417 -holiday.da-DK4.name=Langfredag -holiday.da-DK4.date=20140418 -holiday.da-DK5.name=Påskedag -holiday.da-DK5.date=20140420 -holiday.da-DK6.name=Anden påskedag -holiday.da-DK6.date=20140421 -holiday.da-DK7.name=Kristi himmelfartsdag -holiday.da-DK7.date=20140529 -holiday.da-DK8.name=Pinsedag -holiday.da-DK8.date=20140608 -holiday.da-DK9.name=Anden pinsedag -holiday.da-DK9.date=20140609 +holiday.da-DK1.name=Nytårsdag +holiday.da-DK1.date=20150101 +holiday.da-DK2.name=Skærtorsdag +holiday.da-DK2.date=20150402 +holiday.da-DK3.name=Langfredag +holiday.da-DK3.date=20150403 +holiday.da-DK4.name=Påskedag +holiday.da-DK4.date=20150405 +holiday.da-DK5.name=Anden påskedag +holiday.da-DK5.date=20150406 +holiday.da-DK6.name=Kristi himmelfartsdag +holiday.da-DK6.date=20150514 +holiday.da-DK7.name=Pinsedag +holiday.da-DK7.date=20150524 +holiday.da-DK8.name=Anden pinsedag +holiday.da-DK8.date=20150525 +holiday.da-DK9.name=Grundlovsdag +holiday.da-DK9.date=20150605 holiday.da-DK10.name=Juledag -holiday.da-DK10.date=20141225 +holiday.da-DK10.date=20151225 holiday.da-DK11.name=Anden juledag -holiday.da-DK11.date=20141226 +holiday.da-DK11.date=20151226 holiday.da-DK12.name=Nytårsdag -holiday.da-DK12.date=20150101 +holiday.da-DK12.date=20160101 holiday.da-DK13.name=Skærtorsdag -holiday.da-DK13.date=20150402 +holiday.da-DK13.date=20160324 holiday.da-DK14.name=Langfredag -holiday.da-DK14.date=20150403 +holiday.da-DK14.date=20160325 holiday.da-DK15.name=Påskedag -holiday.da-DK15.date=20150405 +holiday.da-DK15.date=20160327 holiday.da-DK16.name=Anden påskedag -holiday.da-DK16.date=20150406 +holiday.da-DK16.date=20160328 holiday.da-DK17.name=Kristi himmelfartsdag -holiday.da-DK17.date=20150514 +holiday.da-DK17.date=20160505 holiday.da-DK18.name=Pinsedag -holiday.da-DK18.date=20150524 +holiday.da-DK18.date=20160515 holiday.da-DK19.name=Anden pinsedag -holiday.da-DK19.date=20150525 +holiday.da-DK19.date=20160516 holiday.da-DK20.name=Grundlovsdag -holiday.da-DK20.date=20150605 +holiday.da-DK20.date=20160605 holiday.da-DK21.name=Juledag -holiday.da-DK21.date=20151225 +holiday.da-DK21.date=20161225 holiday.da-DK22.name=Anden juledag -holiday.da-DK22.date=20151226 -holiday.da-DK23.name=Nytårsdag -holiday.da-DK23.date=20160101 -holiday.da-DK24.name=Skærtorsdag -holiday.da-DK24.date=20160324 -holiday.da-DK25.name=Langfredag -holiday.da-DK25.date=20160325 -holiday.da-DK26.name=Påskedag -holiday.da-DK26.date=20160327 -holiday.da-DK27.name=Anden påskedag -holiday.da-DK27.date=20160328 -holiday.da-DK28.name=Kristi himmelfartsdag -holiday.da-DK28.date=20160505 -holiday.da-DK29.name=Pinsedag -holiday.da-DK29.date=20160515 -holiday.da-DK30.name=Anden pinsedag -holiday.da-DK30.date=20160516 -holiday.da-DK31.name=Grundlovsdag -holiday.da-DK31.date=20160605 -holiday.da-DK32.name=Juledag -holiday.da-DK32.date=20161225 -holiday.da-DK33.name=Anden juledag -holiday.da-DK33.date=20161226 +holiday.da-DK22.date=20161226 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.de-AT.rc task-2.5.0+dfsg/doc/rc/holidays.de-AT.rc --- task-2.4.4+dfsg/doc/rc/holidays.de-AT.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.de-AT.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/de-AT/2014.json # http://holidata.net/de-AT/2015.json +# http://holidata.net/de-AT/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,140 +28,94 @@ ############################################################################### holiday.de-AT1.name=Neujahr -holiday.de-AT1.date=20140101 +holiday.de-AT1.date=20150101 holiday.de-AT2.name=Heilige drei Könige -holiday.de-AT2.date=20140106 +holiday.de-AT2.date=20150106 holiday.de-AT3.name=Josef (K, St, T, V) -holiday.de-AT3.date=20140319 +holiday.de-AT3.date=20150319 holiday.de-AT4.name=Karfreitag -holiday.de-AT4.date=20140418 +holiday.de-AT4.date=20150403 holiday.de-AT5.name=Ostersonntag -holiday.de-AT5.date=20140420 +holiday.de-AT5.date=20150405 holiday.de-AT6.name=Ostermontag -holiday.de-AT6.date=20140421 +holiday.de-AT6.date=20150406 holiday.de-AT7.name=Staatsfeiertag -holiday.de-AT7.date=20140501 +holiday.de-AT7.date=20150501 holiday.de-AT8.name=Florian (O) -holiday.de-AT8.date=20140504 +holiday.de-AT8.date=20150504 holiday.de-AT9.name=Christi Himmelfahrt -holiday.de-AT9.date=20140529 +holiday.de-AT9.date=20150514 holiday.de-AT10.name=Pfingstsonntag -holiday.de-AT10.date=20140608 +holiday.de-AT10.date=20150524 holiday.de-AT11.name=Pfingstmontag -holiday.de-AT11.date=20140609 +holiday.de-AT11.date=20150525 holiday.de-AT12.name=Fronleichnam -holiday.de-AT12.date=20140619 +holiday.de-AT12.date=20150604 holiday.de-AT13.name=Mariä Himmelfahrt -holiday.de-AT13.date=20140815 +holiday.de-AT13.date=20150815 holiday.de-AT14.name=Rupert (S) -holiday.de-AT14.date=20140924 +holiday.de-AT14.date=20150924 holiday.de-AT15.name=Tag der Volksabstimmung (K) -holiday.de-AT15.date=20141010 +holiday.de-AT15.date=20151010 holiday.de-AT16.name=Allerheiligen -holiday.de-AT16.date=20141101 +holiday.de-AT16.date=20151101 holiday.de-AT17.name=Martin (B) -holiday.de-AT17.date=20141111 +holiday.de-AT17.date=20151111 holiday.de-AT18.name=Leopold (W, N) -holiday.de-AT18.date=20141115 +holiday.de-AT18.date=20151115 holiday.de-AT19.name=Mariä Empfängnis -holiday.de-AT19.date=20141208 +holiday.de-AT19.date=20151208 holiday.de-AT20.name=Heiliger Abend -holiday.de-AT20.date=20141224 +holiday.de-AT20.date=20151224 holiday.de-AT21.name=Christtag -holiday.de-AT21.date=20141225 +holiday.de-AT21.date=20151225 holiday.de-AT22.name=Stefanitag -holiday.de-AT22.date=20141226 +holiday.de-AT22.date=20151226 holiday.de-AT23.name=Silvester -holiday.de-AT23.date=20141231 +holiday.de-AT23.date=20151231 holiday.de-AT24.name=Neujahr -holiday.de-AT24.date=20150101 +holiday.de-AT24.date=20160101 holiday.de-AT25.name=Heilige drei Könige -holiday.de-AT25.date=20150106 +holiday.de-AT25.date=20160106 holiday.de-AT26.name=Josef (K, St, T, V) -holiday.de-AT26.date=20150319 +holiday.de-AT26.date=20160319 holiday.de-AT27.name=Karfreitag -holiday.de-AT27.date=20150403 +holiday.de-AT27.date=20160325 holiday.de-AT28.name=Ostersonntag -holiday.de-AT28.date=20150405 +holiday.de-AT28.date=20160327 holiday.de-AT29.name=Ostermontag -holiday.de-AT29.date=20150406 +holiday.de-AT29.date=20160328 holiday.de-AT30.name=Staatsfeiertag -holiday.de-AT30.date=20150501 +holiday.de-AT30.date=20160501 holiday.de-AT31.name=Florian (O) -holiday.de-AT31.date=20150504 +holiday.de-AT31.date=20160504 holiday.de-AT32.name=Christi Himmelfahrt -holiday.de-AT32.date=20150514 +holiday.de-AT32.date=20160505 holiday.de-AT33.name=Pfingstsonntag -holiday.de-AT33.date=20150524 +holiday.de-AT33.date=20160515 holiday.de-AT34.name=Pfingstmontag -holiday.de-AT34.date=20150525 +holiday.de-AT34.date=20160516 holiday.de-AT35.name=Fronleichnam -holiday.de-AT35.date=20150604 +holiday.de-AT35.date=20160526 holiday.de-AT36.name=Mariä Himmelfahrt -holiday.de-AT36.date=20150815 +holiday.de-AT36.date=20160815 holiday.de-AT37.name=Rupert (S) -holiday.de-AT37.date=20150924 +holiday.de-AT37.date=20160924 holiday.de-AT38.name=Tag der Volksabstimmung (K) -holiday.de-AT38.date=20151010 +holiday.de-AT38.date=20161010 holiday.de-AT39.name=Allerheiligen -holiday.de-AT39.date=20151101 +holiday.de-AT39.date=20161101 holiday.de-AT40.name=Martin (B) -holiday.de-AT40.date=20151111 +holiday.de-AT40.date=20161111 holiday.de-AT41.name=Leopold (W, N) -holiday.de-AT41.date=20151115 +holiday.de-AT41.date=20161115 holiday.de-AT42.name=Mariä Empfängnis -holiday.de-AT42.date=20151208 +holiday.de-AT42.date=20161208 holiday.de-AT43.name=Heiliger Abend -holiday.de-AT43.date=20151224 +holiday.de-AT43.date=20161224 holiday.de-AT44.name=Christtag -holiday.de-AT44.date=20151225 +holiday.de-AT44.date=20161225 holiday.de-AT45.name=Stefanitag -holiday.de-AT45.date=20151226 +holiday.de-AT45.date=20161226 holiday.de-AT46.name=Silvester -holiday.de-AT46.date=20151231 -holiday.de-AT47.name=Neujahr -holiday.de-AT47.date=20160101 -holiday.de-AT48.name=Heilige drei Könige -holiday.de-AT48.date=20160106 -holiday.de-AT49.name=Josef (K, St, T, V) -holiday.de-AT49.date=20160319 -holiday.de-AT50.name=Karfreitag -holiday.de-AT50.date=20160325 -holiday.de-AT51.name=Ostersonntag -holiday.de-AT51.date=20160327 -holiday.de-AT52.name=Ostermontag -holiday.de-AT52.date=20160328 -holiday.de-AT53.name=Staatsfeiertag -holiday.de-AT53.date=20160501 -holiday.de-AT54.name=Florian (O) -holiday.de-AT54.date=20160504 -holiday.de-AT55.name=Christi Himmelfahrt -holiday.de-AT55.date=20160505 -holiday.de-AT56.name=Pfingstsonntag -holiday.de-AT56.date=20160515 -holiday.de-AT57.name=Pfingstmontag -holiday.de-AT57.date=20160516 -holiday.de-AT58.name=Fronleichnam -holiday.de-AT58.date=20160526 -holiday.de-AT59.name=Mariä Himmelfahrt -holiday.de-AT59.date=20160815 -holiday.de-AT60.name=Rupert (S) -holiday.de-AT60.date=20160924 -holiday.de-AT61.name=Tag der Volksabstimmung (K) -holiday.de-AT61.date=20161010 -holiday.de-AT62.name=Allerheiligen -holiday.de-AT62.date=20161101 -holiday.de-AT63.name=Martin (B) -holiday.de-AT63.date=20161111 -holiday.de-AT64.name=Leopold (W, N) -holiday.de-AT64.date=20161115 -holiday.de-AT65.name=Mariä Empfängnis -holiday.de-AT65.date=20161208 -holiday.de-AT66.name=Heiliger Abend -holiday.de-AT66.date=20161224 -holiday.de-AT67.name=Christtag -holiday.de-AT67.date=20161225 -holiday.de-AT68.name=Stefanitag -holiday.de-AT68.date=20161226 -holiday.de-AT69.name=Silvester -holiday.de-AT69.date=20161231 +holiday.de-AT46.date=20161231 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.de-BE.rc task-2.5.0+dfsg/doc/rc/holidays.de-BE.rc --- task-2.4.4+dfsg/doc/rc/holidays.de-BE.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.de-BE.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/de-BE/2014.json # http://holidata.net/de-BE/2015.json +# http://holidata.net/de-BE/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,74 +28,50 @@ ############################################################################### holiday.de-BE1.name=Neujahr -holiday.de-BE1.date=20140101 +holiday.de-BE1.date=20150101 holiday.de-BE2.name=Ostern -holiday.de-BE2.date=20140420 +holiday.de-BE2.date=20150405 holiday.de-BE3.name=Ostermontag -holiday.de-BE3.date=20140421 +holiday.de-BE3.date=20150406 holiday.de-BE4.name=Tag der Arbeit -holiday.de-BE4.date=20140501 +holiday.de-BE4.date=20150501 holiday.de-BE5.name=Christi Himmelfahrt -holiday.de-BE5.date=20140529 +holiday.de-BE5.date=20150514 holiday.de-BE6.name=Pfingsten -holiday.de-BE6.date=20140608 +holiday.de-BE6.date=20150524 holiday.de-BE7.name=Pfingstmontag -holiday.de-BE7.date=20140609 +holiday.de-BE7.date=20150525 holiday.de-BE8.name=Nationalfeiertag -holiday.de-BE8.date=20140721 +holiday.de-BE8.date=20150721 holiday.de-BE9.name=Mariä Himmelfahrt -holiday.de-BE9.date=20140815 +holiday.de-BE9.date=20150815 holiday.de-BE10.name=Allerheiligen -holiday.de-BE10.date=20141101 +holiday.de-BE10.date=20151101 holiday.de-BE11.name=Waffenstillstand -holiday.de-BE11.date=20141111 +holiday.de-BE11.date=20151111 holiday.de-BE12.name=Weihnacht -holiday.de-BE12.date=20141225 +holiday.de-BE12.date=20151225 holiday.de-BE13.name=Neujahr -holiday.de-BE13.date=20150101 +holiday.de-BE13.date=20160101 holiday.de-BE14.name=Ostern -holiday.de-BE14.date=20150405 +holiday.de-BE14.date=20160527 holiday.de-BE15.name=Ostermontag -holiday.de-BE15.date=20150406 +holiday.de-BE15.date=20160528 holiday.de-BE16.name=Tag der Arbeit -holiday.de-BE16.date=20150501 +holiday.de-BE16.date=20160501 holiday.de-BE17.name=Christi Himmelfahrt -holiday.de-BE17.date=20150514 +holiday.de-BE17.date=20160505 holiday.de-BE18.name=Pfingsten -holiday.de-BE18.date=20150524 +holiday.de-BE18.date=20160515 holiday.de-BE19.name=Pfingstmontag -holiday.de-BE19.date=20150525 +holiday.de-BE19.date=20160516 holiday.de-BE20.name=Nationalfeiertag -holiday.de-BE20.date=20150721 +holiday.de-BE20.date=20160721 holiday.de-BE21.name=Mariä Himmelfahrt -holiday.de-BE21.date=20150815 +holiday.de-BE21.date=20160815 holiday.de-BE22.name=Allerheiligen -holiday.de-BE22.date=20151101 +holiday.de-BE22.date=20161101 holiday.de-BE23.name=Waffenstillstand -holiday.de-BE23.date=20151111 +holiday.de-BE23.date=20161111 holiday.de-BE24.name=Weihnacht -holiday.de-BE24.date=20151225 -holiday.de-BE25.name=Neujahr -holiday.de-BE25.date=20160101 -holiday.de-BE26.name=Ostern -holiday.de-BE26.date=20160527 -holiday.de-BE27.name=Ostermontag -holiday.de-BE27.date=20160528 -holiday.de-BE28.name=Tag der Arbeit -holiday.de-BE28.date=20160501 -holiday.de-BE29.name=Christi Himmelfahrt -holiday.de-BE29.date=20160505 -holiday.de-BE30.name=Pfingsten -holiday.de-BE30.date=20160515 -holiday.de-BE31.name=Pfingstmontag -holiday.de-BE31.date=20160516 -holiday.de-BE32.name=Nationalfeiertag -holiday.de-BE32.date=20160721 -holiday.de-BE33.name=Mariä Himmelfahrt -holiday.de-BE33.date=20160815 -holiday.de-BE34.name=Allerheiligen -holiday.de-BE34.date=20161101 -holiday.de-BE35.name=Waffenstillstand -holiday.de-BE35.date=20161111 -holiday.de-BE36.name=Weihnacht -holiday.de-BE36.date=20161225 +holiday.de-BE24.date=20161225 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.de-CH.rc task-2.5.0+dfsg/doc/rc/holidays.de-CH.rc --- task-2.4.4+dfsg/doc/rc/holidays.de-CH.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.de-CH.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,9 +1,9 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/de-CH/2014.json # http://holidata.net/de-CH/2015.json +# http://holidata.net/de-CH/2016.json # -# Copyright 2006 - 2014, Paul Beckingham, Federico Hernandez. +# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -28,110 +28,74 @@ ############################################################################### holiday.de-CH1.name=Neujahrstag -holiday.de-CH1.date=20140101 +holiday.de-CH1.date=20150101 holiday.de-CH2.name=Berchtoldstag -holiday.de-CH2.date=20140102 +holiday.de-CH2.date=20150102 holiday.de-CH3.name=Heilige Drei Könige -holiday.de-CH3.date=20140106 +holiday.de-CH3.date=20150106 holiday.de-CH4.name=Josefstag -holiday.de-CH4.date=20140319 +holiday.de-CH4.date=20150319 holiday.de-CH5.name=Karfreitag -holiday.de-CH5.date=20140418 +holiday.de-CH5.date=20150403 holiday.de-CH6.name=Ostersonntag -holiday.de-CH6.date=20140420 +holiday.de-CH6.date=20150405 holiday.de-CH7.name=Ostermontag -holiday.de-CH7.date=20140421 +holiday.de-CH7.date=20150406 holiday.de-CH8.name=Tag der Arbeit -holiday.de-CH8.date=20140501 +holiday.de-CH8.date=20150501 holiday.de-CH9.name=Auffahrt -holiday.de-CH9.date=20140529 +holiday.de-CH9.date=20150514 holiday.de-CH10.name=Pfingstsonntag -holiday.de-CH10.date=20140608 +holiday.de-CH10.date=20150524 holiday.de-CH11.name=Pfingstmontag -holiday.de-CH11.date=20140609 +holiday.de-CH11.date=20150525 holiday.de-CH12.name=Fronleichnam -holiday.de-CH12.date=20140619 +holiday.de-CH12.date=20150604 holiday.de-CH13.name=Bundesfeier -holiday.de-CH13.date=20140801 +holiday.de-CH13.date=20150801 holiday.de-CH14.name=Mariä Himmelfahrt -holiday.de-CH14.date=20140815 +holiday.de-CH14.date=20150815 holiday.de-CH15.name=Allerheiligen -holiday.de-CH15.date=20141101 +holiday.de-CH15.date=20151101 holiday.de-CH16.name=Mariä Empfängnis -holiday.de-CH16.date=20141208 +holiday.de-CH16.date=20151208 holiday.de-CH17.name=Weihnachtstag -holiday.de-CH17.date=20141225 +holiday.de-CH17.date=20151225 holiday.de-CH18.name=Stephanstag -holiday.de-CH18.date=20141226 +holiday.de-CH18.date=20151226 holiday.de-CH19.name=Neujahrstag -holiday.de-CH19.date=20150101 +holiday.de-CH19.date=20160101 holiday.de-CH20.name=Berchtoldstag -holiday.de-CH20.date=20150102 +holiday.de-CH20.date=20160102 holiday.de-CH21.name=Heilige Drei Könige -holiday.de-CH21.date=20150106 +holiday.de-CH21.date=20160106 holiday.de-CH22.name=Josefstag -holiday.de-CH22.date=20150319 +holiday.de-CH22.date=20160319 holiday.de-CH23.name=Karfreitag -holiday.de-CH23.date=20150403 +holiday.de-CH23.date=20160325 holiday.de-CH24.name=Ostersonntag -holiday.de-CH24.date=20150405 +holiday.de-CH24.date=20160327 holiday.de-CH25.name=Ostermontag -holiday.de-CH25.date=20150406 +holiday.de-CH25.date=20160328 holiday.de-CH26.name=Tag der Arbeit -holiday.de-CH26.date=20150501 +holiday.de-CH26.date=20160501 holiday.de-CH27.name=Auffahrt -holiday.de-CH27.date=20150514 +holiday.de-CH27.date=20160505 holiday.de-CH28.name=Pfingstsonntag -holiday.de-CH28.date=20150524 +holiday.de-CH28.date=20160515 holiday.de-CH29.name=Pfingstmontag -holiday.de-CH29.date=20150525 +holiday.de-CH29.date=20160516 holiday.de-CH30.name=Fronleichnam -holiday.de-CH30.date=20150604 +holiday.de-CH30.date=20160526 holiday.de-CH31.name=Bundesfeier -holiday.de-CH31.date=20150801 +holiday.de-CH31.date=20160801 holiday.de-CH32.name=Mariä Himmelfahrt -holiday.de-CH32.date=20150815 +holiday.de-CH32.date=20160815 holiday.de-CH33.name=Allerheiligen -holiday.de-CH33.date=20151101 +holiday.de-CH33.date=20161101 holiday.de-CH34.name=Mariä Empfängnis -holiday.de-CH34.date=20151208 +holiday.de-CH34.date=20161208 holiday.de-CH35.name=Weihnachtstag -holiday.de-CH35.date=20151225 +holiday.de-CH35.date=20161225 holiday.de-CH36.name=Stephanstag -holiday.de-CH36.date=20151226 -holiday.de-CH37.name=Neujahrstag -holiday.de-CH37.date=20160101 -holiday.de-CH38.name=Berchtoldstag -holiday.de-CH38.date=20160102 -holiday.de-CH39.name=Heilige Drei Könige -holiday.de-CH39.date=20160106 -holiday.de-CH40.name=Josefstag -holiday.de-CH40.date=20160319 -holiday.de-CH41.name=Karfreitag -holiday.de-CH41.date=20160325 -holiday.de-CH42.name=Ostersonntag -holiday.de-CH42.date=20160327 -holiday.de-CH43.name=Ostermontag -holiday.de-CH43.date=20160328 -holiday.de-CH44.name=Tag der Arbeit -holiday.de-CH44.date=20160501 -holiday.de-CH45.name=Auffahrt -holiday.de-CH45.date=20160505 -holiday.de-CH46.name=Pfingstsonntag -holiday.de-CH46.date=20160515 -holiday.de-CH47.name=Pfingstmontag -holiday.de-CH47.date=20160516 -holiday.de-CH48.name=Fronleichnam -holiday.de-CH48.date=20160526 -holiday.de-CH49.name=Bundesfeier -holiday.de-CH49.date=20160801 -holiday.de-CH50.name=Mariä Himmelfahrt -holiday.de-CH50.date=20160815 -holiday.de-CH51.name=Allerheiligen -holiday.de-CH51.date=20161101 -holiday.de-CH52.name=Mariä Empfängnis -holiday.de-CH52.date=20161208 -holiday.de-CH53.name=Weihnachtstag -holiday.de-CH53.date=20161225 -holiday.de-CH54.name=Stephanstag -holiday.de-CH54.date=20161226 +holiday.de-CH36.date=20161226 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.de-DE.rc task-2.5.0+dfsg/doc/rc/holidays.de-DE.rc --- task-2.4.4+dfsg/doc/rc/holidays.de-DE.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.de-DE.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,9 +1,9 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/de-DE/2014.json # http://holidata.net/de-DE/2015.json +# http://holidata.net/de-DE/2016.json # -# Copyright 2006 - 2014, Paul Beckingham, Federico Hernandez. +# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -28,116 +28,78 @@ ############################################################################### holiday.de-DE1.name=Neujahr -holiday.de-DE1.date=20140101 +holiday.de-DE1.date=20150101 holiday.de-DE2.name=Heilige drei Könige -holiday.de-DE2.date=20140106 +holiday.de-DE2.date=20150106 holiday.de-DE3.name=Karfreitag -holiday.de-DE3.date=20140418 +holiday.de-DE3.date=20150403 holiday.de-DE4.name=Ostern -holiday.de-DE4.date=20140420 +holiday.de-DE4.date=20150405 holiday.de-DE5.name=Ostermontag -holiday.de-DE5.date=20140421 +holiday.de-DE5.date=20150406 holiday.de-DE6.name=Erster Maifeiertag -holiday.de-DE6.date=20140501 +holiday.de-DE6.date=20150501 holiday.de-DE7.name=Christi Himmelfahrt -holiday.de-DE7.date=20140529 +holiday.de-DE7.date=20150514 holiday.de-DE8.name=Pfingstsonntag -holiday.de-DE8.date=20140608 +holiday.de-DE8.date=20150524 holiday.de-DE9.name=Pfingstmontag -holiday.de-DE9.date=20140609 +holiday.de-DE9.date=20150525 holiday.de-DE10.name=Fronleichnam -holiday.de-DE10.date=20140619 +holiday.de-DE10.date=20150604 holiday.de-DE11.name=Mariä Himmelfahrt -holiday.de-DE11.date=20140815 +holiday.de-DE11.date=20150815 holiday.de-DE12.name=Tag der Deutschen Einheit -holiday.de-DE12.date=20141003 +holiday.de-DE12.date=20151003 holiday.de-DE13.name=Reformationstag -holiday.de-DE13.date=20141031 +holiday.de-DE13.date=20151031 holiday.de-DE14.name=Allerheiligen -holiday.de-DE14.date=20141101 +holiday.de-DE14.date=20151101 holiday.de-DE15.name=Buss und Bettag -holiday.de-DE15.date=20141119 +holiday.de-DE15.date=20151118 holiday.de-DE16.name=Heilig Abend -holiday.de-DE16.date=20141224 +holiday.de-DE16.date=20151224 holiday.de-DE17.name=Weihnachtstag -holiday.de-DE17.date=20141225 +holiday.de-DE17.date=20151225 holiday.de-DE18.name=Zweiter Weihnachtstag -holiday.de-DE18.date=20141226 +holiday.de-DE18.date=20151226 holiday.de-DE19.name=Sylvester -holiday.de-DE19.date=20141231 +holiday.de-DE19.date=20151231 holiday.de-DE20.name=Neujahr -holiday.de-DE20.date=20150101 +holiday.de-DE20.date=20160101 holiday.de-DE21.name=Heilige drei Könige -holiday.de-DE21.date=20150106 +holiday.de-DE21.date=20160106 holiday.de-DE22.name=Karfreitag -holiday.de-DE22.date=20150403 +holiday.de-DE22.date=20160325 holiday.de-DE23.name=Ostern -holiday.de-DE23.date=20150405 +holiday.de-DE23.date=20160327 holiday.de-DE24.name=Ostermontag -holiday.de-DE24.date=20150406 +holiday.de-DE24.date=20160328 holiday.de-DE25.name=Erster Maifeiertag -holiday.de-DE25.date=20150501 +holiday.de-DE25.date=20160501 holiday.de-DE26.name=Christi Himmelfahrt -holiday.de-DE26.date=20150514 +holiday.de-DE26.date=20160505 holiday.de-DE27.name=Pfingstsonntag -holiday.de-DE27.date=20150524 +holiday.de-DE27.date=20160515 holiday.de-DE28.name=Pfingstmontag -holiday.de-DE28.date=20150525 +holiday.de-DE28.date=20160516 holiday.de-DE29.name=Fronleichnam -holiday.de-DE29.date=20150604 +holiday.de-DE29.date=20160526 holiday.de-DE30.name=Mariä Himmelfahrt -holiday.de-DE30.date=20150815 +holiday.de-DE30.date=20160815 holiday.de-DE31.name=Tag der Deutschen Einheit -holiday.de-DE31.date=20151003 +holiday.de-DE31.date=20161003 holiday.de-DE32.name=Reformationstag -holiday.de-DE32.date=20151031 +holiday.de-DE32.date=20161031 holiday.de-DE33.name=Allerheiligen -holiday.de-DE33.date=20151101 +holiday.de-DE33.date=20161101 holiday.de-DE34.name=Buss und Bettag -holiday.de-DE34.date=20151118 +holiday.de-DE34.date=20161116 holiday.de-DE35.name=Heilig Abend -holiday.de-DE35.date=20151224 +holiday.de-DE35.date=20161224 holiday.de-DE36.name=Weihnachtstag -holiday.de-DE36.date=20151225 +holiday.de-DE36.date=20161225 holiday.de-DE37.name=Zweiter Weihnachtstag -holiday.de-DE37.date=20151226 +holiday.de-DE37.date=20161226 holiday.de-DE38.name=Sylvester -holiday.de-DE38.date=20151231 -holiday.de-DE39.name=Neujahr -holiday.de-DE39.date=20160101 -holiday.de-DE40.name=Heilige drei Könige -holiday.de-DE40.date=20160106 -holiday.de-DE41.name=Karfreitag -holiday.de-DE41.date=20160325 -holiday.de-DE42.name=Ostern -holiday.de-DE42.date=20160327 -holiday.de-DE43.name=Ostermontag -holiday.de-DE43.date=20160328 -holiday.de-DE44.name=Erster Maifeiertag -holiday.de-DE44.date=20160501 -holiday.de-DE45.name=Christi Himmelfahrt -holiday.de-DE45.date=20160505 -holiday.de-DE46.name=Pfingstsonntag -holiday.de-DE46.date=20160515 -holiday.de-DE47.name=Pfingstmontag -holiday.de-DE47.date=20160516 -holiday.de-DE48.name=Fronleichnam -holiday.de-DE48.date=20160526 -holiday.de-DE49.name=Mariä Himmelfahrt -holiday.de-DE49.date=20160815 -holiday.de-DE50.name=Tag der Deutschen Einheit -holiday.de-DE50.date=20161003 -holiday.de-DE51.name=Reformationstag -holiday.de-DE51.date=20161031 -holiday.de-DE52.name=Allerheiligen -holiday.de-DE52.date=20161101 -holiday.de-DE53.name=Buss und Bettag -holiday.de-DE53.date=20161116 -holiday.de-DE54.name=Heilig Abend -holiday.de-DE54.date=20161224 -holiday.de-DE55.name=Weihnachtstag -holiday.de-DE55.date=20161225 -holiday.de-DE56.name=Zweiter Weihnachtstag -holiday.de-DE56.date=20161226 -holiday.de-DE57.name=Sylvester -holiday.de-DE57.date=20161231 +holiday.de-DE38.date=20161231 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.el-GR.rc task-2.5.0+dfsg/doc/rc/holidays.el-GR.rc --- task-2.4.4+dfsg/doc/rc/holidays.el-GR.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.el-GR.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/el-GR/2014.json # http://holidata.net/el-GR/2015.json +# http://holidata.net/el-GR/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,86 +28,58 @@ ############################################################################### holiday.el-GR1.name=Πρωτοχρονιά -holiday.el-GR1.date=20140101 +holiday.el-GR1.date=20150101 holiday.el-GR2.name=Θεοφάνεια -holiday.el-GR2.date=20140106 +holiday.el-GR2.date=20150106 holiday.el-GR3.name=Καθαρά Δευτέρα -holiday.el-GR3.date=20140303 +holiday.el-GR3.date=20150223 holiday.el-GR4.name=Ευαγγελισμός της Θεοτόκου και Εθνική Ημέρα Ανεξαρτησίας της Ελλάδας -holiday.el-GR4.date=20140325 +holiday.el-GR4.date=20150325 holiday.el-GR5.name=Πρωτομαγιά -holiday.el-GR5.date=20140418 +holiday.el-GR5.date=20150418 holiday.el-GR6.name=Μεγάλη Παρασκευή -holiday.el-GR6.date=20140419 +holiday.el-GR6.date=20150410 holiday.el-GR7.name=Μεγάλο Σάββατο -holiday.el-GR7.date=20140420 +holiday.el-GR7.date=20150411 holiday.el-GR8.name=Πάσχα -holiday.el-GR8.date=20140421 +holiday.el-GR8.date=20150412 holiday.el-GR9.name=Δευτέρα του Πάσχα -holiday.el-GR9.date=20140422 +holiday.el-GR9.date=20150413 holiday.el-GR10.name=Δευτέρα του Αγίου Πνεύματος -holiday.el-GR10.date=20140609 +holiday.el-GR10.date=20150601 holiday.el-GR11.name=Κοίμηση της Θεοτόκου -holiday.el-GR11.date=20140815 +holiday.el-GR11.date=20150815 holiday.el-GR12.name=Ημέρα του ΌΧΙ -holiday.el-GR12.date=20141028 +holiday.el-GR12.date=20151028 holiday.el-GR13.name=Χριστούγεννα -holiday.el-GR13.date=20141225 +holiday.el-GR13.date=20151225 holiday.el-GR14.name=Επόμενη ημέρα Χριστουγέννων -holiday.el-GR14.date=20141226 +holiday.el-GR14.date=20151226 holiday.el-GR15.name=Πρωτοχρονιά -holiday.el-GR15.date=20150101 +holiday.el-GR15.date=20160101 holiday.el-GR16.name=Θεοφάνεια -holiday.el-GR16.date=20150106 +holiday.el-GR16.date=20160106 holiday.el-GR17.name=Καθαρά Δευτέρα -holiday.el-GR17.date=20150223 +holiday.el-GR17.date=20160314 holiday.el-GR18.name=Ευαγγελισμός της Θεοτόκου και Εθνική Ημέρα Ανεξαρτησίας της Ελλάδας -holiday.el-GR18.date=20150325 +holiday.el-GR18.date=20160325 holiday.el-GR19.name=Πρωτομαγιά -holiday.el-GR19.date=20150418 +holiday.el-GR19.date=20160418 holiday.el-GR20.name=Μεγάλη Παρασκευή -holiday.el-GR20.date=20150410 +holiday.el-GR20.date=20160429 holiday.el-GR21.name=Μεγάλο Σάββατο -holiday.el-GR21.date=20150411 +holiday.el-GR21.date=20160430 holiday.el-GR22.name=Πάσχα -holiday.el-GR22.date=20150412 +holiday.el-GR22.date=20160501 holiday.el-GR23.name=Δευτέρα του Πάσχα -holiday.el-GR23.date=20150413 +holiday.el-GR23.date=20160502 holiday.el-GR24.name=Δευτέρα του Αγίου Πνεύματος -holiday.el-GR24.date=20150601 +holiday.el-GR24.date=20160620 holiday.el-GR25.name=Κοίμηση της Θεοτόκου -holiday.el-GR25.date=20150815 +holiday.el-GR25.date=20160815 holiday.el-GR26.name=Ημέρα του ΌΧΙ -holiday.el-GR26.date=20151028 +holiday.el-GR26.date=20161028 holiday.el-GR27.name=Χριστούγεννα -holiday.el-GR27.date=20151225 +holiday.el-GR27.date=20161225 holiday.el-GR28.name=Επόμενη ημέρα Χριστουγέννων -holiday.el-GR28.date=20151226 -holiday.el-GR29.name=Πρωτοχρονιά -holiday.el-GR29.date=20160101 -holiday.el-GR30.name=Θεοφάνεια -holiday.el-GR30.date=20160106 -holiday.el-GR31.name=Καθαρά Δευτέρα -holiday.el-GR31.date=20160314 -holiday.el-GR32.name=Ευαγγελισμός της Θεοτόκου και Εθνική Ημέρα Ανεξαρτησίας της Ελλάδας -holiday.el-GR32.date=20160325 -holiday.el-GR33.name=Πρωτομαγιά -holiday.el-GR33.date=20160418 -holiday.el-GR34.name=Μεγάλη Παρασκευή -holiday.el-GR34.date=20160429 -holiday.el-GR35.name=Μεγάλο Σάββατο -holiday.el-GR35.date=20160430 -holiday.el-GR36.name=Πάσχα -holiday.el-GR36.date=20160501 -holiday.el-GR37.name=Δευτέρα του Πάσχα -holiday.el-GR37.date=20160502 -holiday.el-GR38.name=Δευτέρα του Αγίου Πνεύματος -holiday.el-GR38.date=20160620 -holiday.el-GR39.name=Κοίμηση της Θεοτόκου -holiday.el-GR39.date=20160815 -holiday.el-GR40.name=Ημέρα του ΌΧΙ -holiday.el-GR40.date=20161028 -holiday.el-GR41.name=Χριστούγεννα -holiday.el-GR41.date=20161225 -holiday.el-GR42.name=Επόμενη ημέρα Χριστουγέννων -holiday.el-GR42.date=20161226 +holiday.el-GR28.date=20161226 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.en-AU.rc task-2.5.0+dfsg/doc/rc/holidays.en-AU.rc --- task-2.4.4+dfsg/doc/rc/holidays.en-AU.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.en-AU.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/en-AU/2014.json # http://holidata.net/en-AU/2015.json +# http://holidata.net/en-AU/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,138 +28,92 @@ ############################################################################### holiday.en-AU1.name=New Year's Day -holiday.en-AU1.date=20140101 +holiday.en-AU1.date=20150101 holiday.en-AU2.name=Australia Day -holiday.en-AU2.date=20140126 +holiday.en-AU2.date=20150126 holiday.en-AU3.name=Royal Hobart Regatta -holiday.en-AU3.date=20140210 +holiday.en-AU3.date=20150209 holiday.en-AU4.name=Labour Day -holiday.en-AU4.date=20140303 +holiday.en-AU4.date=20150302 holiday.en-AU5.name=Labour Day -holiday.en-AU5.date=20140310 +holiday.en-AU5.date=20150309 holiday.en-AU6.name=Canberra Day -holiday.en-AU6.date=20140310 +holiday.en-AU6.date=20150309 holiday.en-AU7.name=Eight Hours Day -holiday.en-AU7.date=20140310 +holiday.en-AU7.date=20150309 holiday.en-AU8.name=Good Friday -holiday.en-AU8.date=20140418 +holiday.en-AU8.date=20150403 holiday.en-AU9.name=Easter Saturday -holiday.en-AU9.date=20140419 +holiday.en-AU9.date=20150404 holiday.en-AU10.name=Easter Sunday -holiday.en-AU10.date=20140420 +holiday.en-AU10.date=20150405 holiday.en-AU11.name=Easter Monday -holiday.en-AU11.date=20140421 +holiday.en-AU11.date=20150406 holiday.en-AU12.name=Anzac Day -holiday.en-AU12.date=20140425 +holiday.en-AU12.date=20150425 holiday.en-AU13.name=May Day -holiday.en-AU13.date=20140505 +holiday.en-AU13.date=20150504 holiday.en-AU14.name=Foundation Day -holiday.en-AU14.date=20140602 +holiday.en-AU14.date=20150601 holiday.en-AU15.name=Queen's Birthday -holiday.en-AU15.date=20140609 +holiday.en-AU15.date=20150608 holiday.en-AU16.name=Picnic Day -holiday.en-AU16.date=20140804 +holiday.en-AU16.date=20150803 holiday.en-AU17.name=Bank Holiday -holiday.en-AU17.date=20140804 +holiday.en-AU17.date=20150803 holiday.en-AU18.name=Queen's Birthday -holiday.en-AU18.date=20140929 +holiday.en-AU18.date=20150928 holiday.en-AU19.name=Labour Day -holiday.en-AU19.date=20141006 +holiday.en-AU19.date=20151005 holiday.en-AU20.name=Recreation Day -holiday.en-AU20.date=20141103 +holiday.en-AU20.date=20151102 holiday.en-AU21.name=Christmas Day -holiday.en-AU21.date=20141225 +holiday.en-AU21.date=20151225 holiday.en-AU22.name=Boxing Day -holiday.en-AU22.date=20141226 +holiday.en-AU22.date=20151226 holiday.en-AU23.name=Proclamation Day -holiday.en-AU23.date=20141226 +holiday.en-AU23.date=20151226 holiday.en-AU24.name=New Year's Day -holiday.en-AU24.date=20150101 +holiday.en-AU24.date=20160101 holiday.en-AU25.name=Australia Day -holiday.en-AU25.date=20150126 +holiday.en-AU25.date=20160126 holiday.en-AU26.name=Royal Hobart Regatta -holiday.en-AU26.date=20150209 +holiday.en-AU26.date=20160208 holiday.en-AU27.name=Labour Day -holiday.en-AU27.date=20150302 +holiday.en-AU27.date=20160307 holiday.en-AU28.name=Labour Day -holiday.en-AU28.date=20150309 +holiday.en-AU28.date=20160314 holiday.en-AU29.name=Canberra Day -holiday.en-AU29.date=20150309 +holiday.en-AU29.date=20160314 holiday.en-AU30.name=Eight Hours Day -holiday.en-AU30.date=20150309 +holiday.en-AU30.date=20160314 holiday.en-AU31.name=Good Friday -holiday.en-AU31.date=20150403 +holiday.en-AU31.date=20160325 holiday.en-AU32.name=Easter Saturday -holiday.en-AU32.date=20150404 -holiday.en-AU33.name=Easter Sunday -holiday.en-AU33.date=20150405 -holiday.en-AU34.name=Easter Monday -holiday.en-AU34.date=20150406 -holiday.en-AU35.name=Anzac Day -holiday.en-AU35.date=20150425 -holiday.en-AU36.name=May Day -holiday.en-AU36.date=20150504 -holiday.en-AU37.name=Foundation Day -holiday.en-AU37.date=20150601 -holiday.en-AU38.name=Queen's Birthday -holiday.en-AU38.date=20150608 -holiday.en-AU39.name=Picnic Day -holiday.en-AU39.date=20150803 -holiday.en-AU40.name=Bank Holiday -holiday.en-AU40.date=20150803 -holiday.en-AU41.name=Queen's Birthday -holiday.en-AU41.date=20150928 -holiday.en-AU42.name=Labour Day -holiday.en-AU42.date=20151005 -holiday.en-AU43.name=Recreation Day -holiday.en-AU43.date=20151102 -holiday.en-AU44.name=Christmas Day -holiday.en-AU44.date=20151225 -holiday.en-AU45.name=Boxing Day -holiday.en-AU45.date=20151226 -holiday.en-AU46.name=Proclamation Day -holiday.en-AU46.date=20151226 -holiday.en-AU47.name=New Year's Day -holiday.en-AU47.date=20160101 -holiday.en-AU48.name=Australia Day -holiday.en-AU48.date=20160126 -holiday.en-AU49.name=Royal Hobart Regatta -holiday.en-AU49.date=20160208 -holiday.en-AU50.name=Labour Day -holiday.en-AU50.date=20160307 -holiday.en-AU51.name=Labour Day -holiday.en-AU51.date=20160314 -holiday.en-AU52.name=Canberra Day -holiday.en-AU52.date=20160314 -holiday.en-AU53.name=Eight Hours Day -holiday.en-AU53.date=20160314 -holiday.en-AU54.name=Good Friday -holiday.en-AU54.date=20160325 -holiday.en-AU55.name=Easter Saturday -holiday.en-AU55.date=20160326 -holiday.en-AU56.name=Easter Monday -holiday.en-AU56.date=20160327 -holiday.en-AU57.name=Anzac Day -holiday.en-AU57.date=20160425 -holiday.en-AU58.name=May Day -holiday.en-AU58.date=20160502 -holiday.en-AU59.name=Foundation Day -holiday.en-AU59.date=20160603 -holiday.en-AU60.name=Queen's Birthday -holiday.en-AU60.date=20160613 -holiday.en-AU61.name=Picnic Day -holiday.en-AU61.date=20160801 -holiday.en-AU62.name=Bank Holiday -holiday.en-AU62.date=20160801 -holiday.en-AU63.name=Queen's Birthday -holiday.en-AU63.date=20160926 -holiday.en-AU64.name=Labour Day -holiday.en-AU64.date=20161003 -holiday.en-AU65.name=Recreation Day -holiday.en-AU65.date=20161107 -holiday.en-AU66.name=Christmas Day -holiday.en-AU66.date=20161225 -holiday.en-AU67.name=Boxing Day -holiday.en-AU67.date=20161226 -holiday.en-AU68.name=Proclamation Day -holiday.en-AU68.date=20161226 +holiday.en-AU32.date=20160326 +holiday.en-AU33.name=Easter Monday +holiday.en-AU33.date=20160327 +holiday.en-AU34.name=Anzac Day +holiday.en-AU34.date=20160425 +holiday.en-AU35.name=May Day +holiday.en-AU35.date=20160502 +holiday.en-AU36.name=Foundation Day +holiday.en-AU36.date=20160603 +holiday.en-AU37.name=Queen's Birthday +holiday.en-AU37.date=20160613 +holiday.en-AU38.name=Picnic Day +holiday.en-AU38.date=20160801 +holiday.en-AU39.name=Bank Holiday +holiday.en-AU39.date=20160801 +holiday.en-AU40.name=Queen's Birthday +holiday.en-AU40.date=20160926 +holiday.en-AU41.name=Labour Day +holiday.en-AU41.date=20161003 +holiday.en-AU42.name=Recreation Day +holiday.en-AU42.date=20161107 +holiday.en-AU43.name=Christmas Day +holiday.en-AU43.date=20161225 +holiday.en-AU44.name=Boxing Day +holiday.en-AU44.date=20161226 +holiday.en-AU45.name=Proclamation Day +holiday.en-AU45.date=20161226 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.en-CA.rc task-2.5.0+dfsg/doc/rc/holidays.en-CA.rc --- task-2.4.4+dfsg/doc/rc/holidays.en-CA.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.en-CA.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/en-CA/2014.json # http://holidata.net/en-CA/2015.json +# http://holidata.net/en-CA/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,74 +28,50 @@ ############################################################################### holiday.en-CA1.name=New Year's Day -holiday.en-CA1.date=20140101 +holiday.en-CA1.date=20150101 holiday.en-CA2.name=Family Day -holiday.en-CA2.date=20140210 +holiday.en-CA2.date=20150209 holiday.en-CA3.name=Good Friday -holiday.en-CA3.date=20140418 +holiday.en-CA3.date=20150403 holiday.en-CA4.name=Easter Monday -holiday.en-CA4.date=20140421 +holiday.en-CA4.date=20150406 holiday.en-CA5.name=Victoria Day -holiday.en-CA5.date=20140519 +holiday.en-CA5.date=20150518 holiday.en-CA6.name=Canada Day -holiday.en-CA6.date=20140701 +holiday.en-CA6.date=20150701 holiday.en-CA7.name=First Monday of August -holiday.en-CA7.date=20140804 +holiday.en-CA7.date=20150803 holiday.en-CA8.name=Labour Day -holiday.en-CA8.date=20140901 +holiday.en-CA8.date=20150907 holiday.en-CA9.name=Thanksgiving Day -holiday.en-CA9.date=20141013 +holiday.en-CA9.date=20151012 holiday.en-CA10.name=Remembrance Day -holiday.en-CA10.date=20141111 +holiday.en-CA10.date=20151111 holiday.en-CA11.name=Christmas Day -holiday.en-CA11.date=20141225 +holiday.en-CA11.date=20151225 holiday.en-CA12.name=Boxing Day -holiday.en-CA12.date=20141226 +holiday.en-CA12.date=20151226 holiday.en-CA13.name=New Year's Day -holiday.en-CA13.date=20150101 +holiday.en-CA13.date=20160101 holiday.en-CA14.name=Family Day -holiday.en-CA14.date=20150209 +holiday.en-CA14.date=20160208 holiday.en-CA15.name=Good Friday -holiday.en-CA15.date=20150403 +holiday.en-CA15.date=20160325 holiday.en-CA16.name=Easter Monday -holiday.en-CA16.date=20150406 +holiday.en-CA16.date=20160328 holiday.en-CA17.name=Victoria Day -holiday.en-CA17.date=20150518 +holiday.en-CA17.date=20160523 holiday.en-CA18.name=Canada Day -holiday.en-CA18.date=20150701 +holiday.en-CA18.date=20160701 holiday.en-CA19.name=First Monday of August -holiday.en-CA19.date=20150803 +holiday.en-CA19.date=20160801 holiday.en-CA20.name=Labour Day -holiday.en-CA20.date=20150907 +holiday.en-CA20.date=20160905 holiday.en-CA21.name=Thanksgiving Day -holiday.en-CA21.date=20151012 +holiday.en-CA21.date=20161010 holiday.en-CA22.name=Remembrance Day -holiday.en-CA22.date=20151111 +holiday.en-CA22.date=20161111 holiday.en-CA23.name=Christmas Day -holiday.en-CA23.date=20151225 +holiday.en-CA23.date=20161225 holiday.en-CA24.name=Boxing Day -holiday.en-CA24.date=20151226 -holiday.en-CA25.name=New Year's Day -holiday.en-CA25.date=20160101 -holiday.en-CA26.name=Family Day -holiday.en-CA26.date=20160208 -holiday.en-CA27.name=Good Friday -holiday.en-CA27.date=20160325 -holiday.en-CA28.name=Easter Monday -holiday.en-CA28.date=20160328 -holiday.en-CA29.name=Victoria Day -holiday.en-CA29.date=20160523 -holiday.en-CA30.name=Canada Day -holiday.en-CA30.date=20160701 -holiday.en-CA31.name=First Monday of August -holiday.en-CA31.date=20160801 -holiday.en-CA32.name=Labour Day -holiday.en-CA32.date=20160905 -holiday.en-CA33.name=Thanksgiving Day -holiday.en-CA33.date=20161010 -holiday.en-CA34.name=Remembrance Day -holiday.en-CA34.date=20161111 -holiday.en-CA35.name=Christmas Day -holiday.en-CA35.date=20161225 -holiday.en-CA36.name=Boxing Day -holiday.en-CA36.date=20161226 +holiday.en-CA24.date=20161226 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.en-GB.rc task-2.5.0+dfsg/doc/rc/holidays.en-GB.rc --- task-2.4.4+dfsg/doc/rc/holidays.en-GB.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.en-GB.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/en-GB/2014.json # http://holidata.net/en-GB/2015.json +# http://holidata.net/en-GB/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,50 +28,34 @@ ############################################################################### holiday.en-GB1.name=New Year's Day -holiday.en-GB1.date=20140101 +holiday.en-GB1.date=20150101 holiday.en-GB2.name=Good Friday -holiday.en-GB2.date=20140418 +holiday.en-GB2.date=20150403 holiday.en-GB3.name=Easter Monday -holiday.en-GB3.date=20140421 +holiday.en-GB3.date=20150406 holiday.en-GB4.name=Early May Bank Holiday -holiday.en-GB4.date=20140505 +holiday.en-GB4.date=20150504 holiday.en-GB5.name=Spring Bank Holiday -holiday.en-GB5.date=20140526 +holiday.en-GB5.date=20150525 holiday.en-GB6.name=August Bank Holiday -holiday.en-GB6.date=20140825 +holiday.en-GB6.date=20150831 holiday.en-GB7.name=Christmas Day -holiday.en-GB7.date=20141225 +holiday.en-GB7.date=20151225 holiday.en-GB8.name=Boxing Day -holiday.en-GB8.date=20141226 +holiday.en-GB8.date=20151226 holiday.en-GB9.name=New Year's Day -holiday.en-GB9.date=20150101 +holiday.en-GB9.date=20160101 holiday.en-GB10.name=Good Friday -holiday.en-GB10.date=20150403 +holiday.en-GB10.date=20160325 holiday.en-GB11.name=Easter Monday -holiday.en-GB11.date=20150406 +holiday.en-GB11.date=20160328 holiday.en-GB12.name=Early May Bank Holiday -holiday.en-GB12.date=20150504 +holiday.en-GB12.date=20160502 holiday.en-GB13.name=Spring Bank Holiday -holiday.en-GB13.date=20150525 +holiday.en-GB13.date=20160530 holiday.en-GB14.name=August Bank Holiday -holiday.en-GB14.date=20150831 +holiday.en-GB14.date=20160829 holiday.en-GB15.name=Christmas Day -holiday.en-GB15.date=20151225 +holiday.en-GB15.date=20161225 holiday.en-GB16.name=Boxing Day -holiday.en-GB16.date=20151226 -holiday.en-GB17.name=New Year's Day -holiday.en-GB17.date=20160101 -holiday.en-GB18.name=Good Friday -holiday.en-GB18.date=20160325 -holiday.en-GB19.name=Easter Monday -holiday.en-GB19.date=20160328 -holiday.en-GB20.name=Early May Bank Holiday -holiday.en-GB20.date=20160502 -holiday.en-GB21.name=Spring Bank Holiday -holiday.en-GB21.date=20160530 -holiday.en-GB22.name=August Bank Holiday -holiday.en-GB22.date=20160829 -holiday.en-GB23.name=Christmas Day -holiday.en-GB23.date=20161225 -holiday.en-GB24.name=Boxing Day -holiday.en-GB24.date=20161226 +holiday.en-GB16.date=20161226 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.en-GL.rc task-2.5.0+dfsg/doc/rc/holidays.en-GL.rc --- task-2.4.4+dfsg/doc/rc/holidays.en-GL.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.en-GL.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/en-GL/2014.json # http://holidata.net/en-GL/2015.json +# http://holidata.net/en-GL/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,80 +28,54 @@ ############################################################################### holiday.en-GL1.name=New Year's Day -holiday.en-GL1.date=20140101 +holiday.en-GL1.date=20150101 holiday.en-GL2.name=Epiphany -holiday.en-GL2.date=20140106 +holiday.en-GL2.date=20150106 holiday.en-GL3.name=Maundy Thursday -holiday.en-GL3.date=20140417 +holiday.en-GL3.date=20150402 holiday.en-GL4.name=Good Friday -holiday.en-GL4.date=20140318 +holiday.en-GL4.date=20150303 holiday.en-GL5.name=Easter Monday -holiday.en-GL5.date=20140421 +holiday.en-GL5.date=20150406 holiday.en-GL6.name=General Prayer Day -holiday.en-GL6.date=20140516 +holiday.en-GL6.date=20150501 holiday.en-GL7.name=Ascension -holiday.en-GL7.date=20140529 +holiday.en-GL7.date=20150514 holiday.en-GL8.name=Whit Monday -holiday.en-GL8.date=20140609 +holiday.en-GL8.date=20150525 holiday.en-GL9.name=Ullortuneq -holiday.en-GL9.date=20140621 +holiday.en-GL9.date=20150621 holiday.en-GL10.name=Christmas Eve -holiday.en-GL10.date=20141224 +holiday.en-GL10.date=20151224 holiday.en-GL11.name=Christmas Day -holiday.en-GL11.date=20141225 +holiday.en-GL11.date=20151225 holiday.en-GL12.name=St Stephen's Day -holiday.en-GL12.date=20141226 +holiday.en-GL12.date=20151226 holiday.en-GL13.name=New Year's Eve -holiday.en-GL13.date=20141231 +holiday.en-GL13.date=20151231 holiday.en-GL14.name=New Year's Day -holiday.en-GL14.date=20150101 +holiday.en-GL14.date=20160101 holiday.en-GL15.name=Epiphany -holiday.en-GL15.date=20150106 +holiday.en-GL15.date=20160106 holiday.en-GL16.name=Maundy Thursday -holiday.en-GL16.date=20150402 +holiday.en-GL16.date=20160324 holiday.en-GL17.name=Good Friday -holiday.en-GL17.date=20150303 +holiday.en-GL17.date=20160325 holiday.en-GL18.name=Easter Monday -holiday.en-GL18.date=20150406 +holiday.en-GL18.date=20160428 holiday.en-GL19.name=General Prayer Day -holiday.en-GL19.date=20150501 +holiday.en-GL19.date=20160422 holiday.en-GL20.name=Ascension -holiday.en-GL20.date=20150514 +holiday.en-GL20.date=20160505 holiday.en-GL21.name=Whit Monday -holiday.en-GL21.date=20150525 +holiday.en-GL21.date=20160516 holiday.en-GL22.name=Ullortuneq -holiday.en-GL22.date=20150621 +holiday.en-GL22.date=20160621 holiday.en-GL23.name=Christmas Eve -holiday.en-GL23.date=20151224 +holiday.en-GL23.date=20161224 holiday.en-GL24.name=Christmas Day -holiday.en-GL24.date=20151225 +holiday.en-GL24.date=20161225 holiday.en-GL25.name=St Stephen's Day -holiday.en-GL25.date=20151226 +holiday.en-GL25.date=20161226 holiday.en-GL26.name=New Year's Eve -holiday.en-GL26.date=20151231 -holiday.en-GL27.name=New Year's Day -holiday.en-GL27.date=20160101 -holiday.en-GL28.name=Epiphany -holiday.en-GL28.date=20160106 -holiday.en-GL29.name=Maundy Thursday -holiday.en-GL29.date=20160324 -holiday.en-GL30.name=Good Friday -holiday.en-GL30.date=20160325 -holiday.en-GL31.name=Easter Monday -holiday.en-GL31.date=20160428 -holiday.en-GL32.name=General Prayer Day -holiday.en-GL32.date=20160422 -holiday.en-GL33.name=Ascension -holiday.en-GL33.date=20160505 -holiday.en-GL34.name=Whit Monday -holiday.en-GL34.date=20160516 -holiday.en-GL35.name=Ullortuneq -holiday.en-GL35.date=20160621 -holiday.en-GL36.name=Christmas Eve -holiday.en-GL36.date=20161224 -holiday.en-GL37.name=Christmas Day -holiday.en-GL37.date=20161225 -holiday.en-GL38.name=St Stephen's Day -holiday.en-GL38.date=20161226 -holiday.en-GL39.name=New Year's Eve -holiday.en-GL39.date=20161231 +holiday.en-GL26.date=20161231 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.en-HK.rc task-2.5.0+dfsg/doc/rc/holidays.en-HK.rc --- task-2.4.4+dfsg/doc/rc/holidays.en-HK.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.en-HK.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/en-HK/2014.json # http://holidata.net/en-HK/2015.json +# http://holidata.net/en-HK/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,100 +28,68 @@ ############################################################################### holiday.en-HK1.name=The first day of January -holiday.en-HK1.date=20140101 -holiday.en-HK2.name=The second day of Lunar New Year -holiday.en-HK2.date=20140201 -holiday.en-HK3.name=The fourth day of Lunar New Year -holiday.en-HK3.date=20140203 -holiday.en-HK4.name=Good Friday -holiday.en-HK4.date=20140418 -holiday.en-HK5.name=The day following Good Friday -holiday.en-HK5.date=20140419 -holiday.en-HK6.name=Easter Monday -holiday.en-HK6.date=20140421 -holiday.en-HK7.name=Ching Ming Festival -holiday.en-HK7.date=20140405 -holiday.en-HK8.name=Labour Day -holiday.en-HK8.date=20140501 -holiday.en-HK9.name=The Birthday of the Buddha -holiday.en-HK9.date=20140506 -holiday.en-HK10.name=Tuen Ng Festival -holiday.en-HK10.date=20140602 -holiday.en-HK11.name=Hong Kong Special Administrative Region Establishment Day -holiday.en-HK11.date=20140701 -holiday.en-HK12.name=The day following the Chinese Mid-Autumn Festival -holiday.en-HK12.date=20140909 -holiday.en-HK13.name=National Day -holiday.en-HK13.date=20141001 -holiday.en-HK14.name=Chung Yeung Festival -holiday.en-HK14.date=20141002 -holiday.en-HK15.name=Christmas Day -holiday.en-HK15.date=20141225 -holiday.en-HK16.name=The first weekday after Christmas Day -holiday.en-HK16.date=20141226 -holiday.en-HK17.name=The first day of January -holiday.en-HK17.date=20150101 -holiday.en-HK18.name=Lunar New Year’s Day -holiday.en-HK18.date=20150219 -holiday.en-HK19.name=The second day of Lunar New Year -holiday.en-HK19.date=20150220 -holiday.en-HK20.name=The third day of Lunar New Year -holiday.en-HK20.date=20150221 -holiday.en-HK21.name=Good Friday -holiday.en-HK21.date=20150403 -holiday.en-HK22.name=The day following Good Friday -holiday.en-HK22.date=20150404 -holiday.en-HK23.name=The day following Ching Ming Festival -holiday.en-HK23.date=20150406 -holiday.en-HK24.name=The day following Easter Monday -holiday.en-HK24.date=20150407 +holiday.en-HK1.date=20150101 +holiday.en-HK2.name=Lunar New Year’s Day +holiday.en-HK2.date=20150219 +holiday.en-HK3.name=The second day of Lunar New Year +holiday.en-HK3.date=20150220 +holiday.en-HK4.name=The third day of Lunar New Year +holiday.en-HK4.date=20150221 +holiday.en-HK5.name=Good Friday +holiday.en-HK5.date=20150403 +holiday.en-HK6.name=The day following Good Friday +holiday.en-HK6.date=20150404 +holiday.en-HK7.name=The day following Ching Ming Festival +holiday.en-HK7.date=20150406 +holiday.en-HK8.name=The day following Easter Monday +holiday.en-HK8.date=20150407 +holiday.en-HK9.name=Labour Day +holiday.en-HK9.date=20150501 +holiday.en-HK10.name=The Birthday of the Buddha +holiday.en-HK10.date=20150525 +holiday.en-HK11.name=Tuen Ng Festival +holiday.en-HK11.date=20150620 +holiday.en-HK12.name=Hong Kong Special Administrative Region Establishment Day +holiday.en-HK12.date=20150701 +holiday.en-HK13.name=The day following the Chinese Mid-Autumn Festival +holiday.en-HK13.date=20150928 +holiday.en-HK14.name=National Day +holiday.en-HK14.date=20151001 +holiday.en-HK15.name=Chung Yeung Festival +holiday.en-HK15.date=20151021 +holiday.en-HK16.name=Christmas Day +holiday.en-HK16.date=20151225 +holiday.en-HK17.name=The first weekday after Christmas Day +holiday.en-HK17.date=20151226 +holiday.en-HK18.name=The first day of January +holiday.en-HK18.date=20160101 +holiday.en-HK19.name=Lunar New Year’s Day +holiday.en-HK19.date=20160208 +holiday.en-HK20.name=The second day of Lunar New Year +holiday.en-HK20.date=20160209 +holiday.en-HK21.name=The third day of Lunar New Year +holiday.en-HK21.date=20160210 +holiday.en-HK22.name=Good Friday +holiday.en-HK22.date=20160325 +holiday.en-HK23.name=The day following Good Friday +holiday.en-HK23.date=20160326 +holiday.en-HK24.name=Ching Ming Festival +holiday.en-HK24.date=20160404 holiday.en-HK25.name=Labour Day -holiday.en-HK25.date=20150501 +holiday.en-HK25.date=20160501 holiday.en-HK26.name=The Birthday of the Buddha -holiday.en-HK26.date=20150525 +holiday.en-HK26.date=20160514 holiday.en-HK27.name=Tuen Ng Festival -holiday.en-HK27.date=20150620 +holiday.en-HK27.date=20160609 holiday.en-HK28.name=Hong Kong Special Administrative Region Establishment Day -holiday.en-HK28.date=20150701 +holiday.en-HK28.date=20160701 holiday.en-HK29.name=The day following the Chinese Mid-Autumn Festival -holiday.en-HK29.date=20150928 +holiday.en-HK29.date=20160916 holiday.en-HK30.name=National Day -holiday.en-HK30.date=20151001 +holiday.en-HK30.date=20161001 holiday.en-HK31.name=Chung Yeung Festival -holiday.en-HK31.date=20151021 +holiday.en-HK31.date=20161010 holiday.en-HK32.name=Christmas Day -holiday.en-HK32.date=20151225 +holiday.en-HK32.date=20161225 holiday.en-HK33.name=The first weekday after Christmas Day -holiday.en-HK33.date=20151226 -holiday.en-HK34.name=The first day of January -holiday.en-HK34.date=20160101 -holiday.en-HK35.name=Lunar New Year’s Day -holiday.en-HK35.date=20160208 -holiday.en-HK36.name=The second day of Lunar New Year -holiday.en-HK36.date=20160209 -holiday.en-HK37.name=The third day of Lunar New Year -holiday.en-HK37.date=20160210 -holiday.en-HK38.name=Good Friday -holiday.en-HK38.date=20160325 -holiday.en-HK39.name=The day following Good Friday -holiday.en-HK39.date=20160326 -holiday.en-HK40.name=Ching Ming Festival -holiday.en-HK40.date=20160404 -holiday.en-HK41.name=Labour Day -holiday.en-HK41.date=20160501 -holiday.en-HK42.name=The Birthday of the Buddha -holiday.en-HK42.date=20160514 -holiday.en-HK43.name=Tuen Ng Festival -holiday.en-HK43.date=20160609 -holiday.en-HK44.name=Hong Kong Special Administrative Region Establishment Day -holiday.en-HK44.date=20160701 -holiday.en-HK45.name=The day following the Chinese Mid-Autumn Festival -holiday.en-HK45.date=20160916 -holiday.en-HK46.name=National Day -holiday.en-HK46.date=20161001 -holiday.en-HK47.name=Chung Yeung Festival -holiday.en-HK47.date=20161010 -holiday.en-HK48.name=Christmas Day -holiday.en-HK48.date=20161225 -holiday.en-HK49.name=The first weekday after Christmas Day -holiday.en-HK49.date=20161226 +holiday.en-HK33.date=20161226 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.en-NZ.rc task-2.5.0+dfsg/doc/rc/holidays.en-NZ.rc --- task-2.4.4+dfsg/doc/rc/holidays.en-NZ.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.en-NZ.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/en-NZ/2014.json # http://holidata.net/en-NZ/2015.json +# http://holidata.net/en-NZ/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,62 +28,42 @@ ############################################################################### holiday.en-NZ1.name=New Year's Day -holiday.en-NZ1.date=20140101 +holiday.en-NZ1.date=20150101 holiday.en-NZ2.name=Day after New Years Day -holiday.en-NZ2.date=20140102 +holiday.en-NZ2.date=20150102 holiday.en-NZ3.name=Waitangi Day -holiday.en-NZ3.date=20140206 +holiday.en-NZ3.date=20150206 holiday.en-NZ4.name=Good Friday -holiday.en-NZ4.date=20140418 +holiday.en-NZ4.date=20150403 holiday.en-NZ5.name=Easter Monday -holiday.en-NZ5.date=20140421 +holiday.en-NZ5.date=20150406 holiday.en-NZ6.name=ANZAC Day -holiday.en-NZ6.date=20140425 +holiday.en-NZ6.date=20150425 holiday.en-NZ7.name=Queen's Birthday -holiday.en-NZ7.date=20140602 +holiday.en-NZ7.date=20150601 holiday.en-NZ8.name=Labour Day -holiday.en-NZ8.date=20141027 +holiday.en-NZ8.date=20151026 holiday.en-NZ9.name=Christmas Day -holiday.en-NZ9.date=20141225 +holiday.en-NZ9.date=20151225 holiday.en-NZ10.name=Boxing Day -holiday.en-NZ10.date=20141226 +holiday.en-NZ10.date=20151226 holiday.en-NZ11.name=New Year's Day -holiday.en-NZ11.date=20150101 +holiday.en-NZ11.date=20160101 holiday.en-NZ12.name=Day after New Years Day -holiday.en-NZ12.date=20150102 +holiday.en-NZ12.date=20160104 holiday.en-NZ13.name=Waitangi Day -holiday.en-NZ13.date=20150206 +holiday.en-NZ13.date=20160206 holiday.en-NZ14.name=Good Friday -holiday.en-NZ14.date=20150403 +holiday.en-NZ14.date=20160325 holiday.en-NZ15.name=Easter Monday -holiday.en-NZ15.date=20150406 +holiday.en-NZ15.date=20160328 holiday.en-NZ16.name=ANZAC Day -holiday.en-NZ16.date=20150425 +holiday.en-NZ16.date=20160425 holiday.en-NZ17.name=Queen's Birthday -holiday.en-NZ17.date=20150601 +holiday.en-NZ17.date=20160606 holiday.en-NZ18.name=Labour Day -holiday.en-NZ18.date=20151026 +holiday.en-NZ18.date=20161024 holiday.en-NZ19.name=Christmas Day -holiday.en-NZ19.date=20151225 +holiday.en-NZ19.date=20161225 holiday.en-NZ20.name=Boxing Day -holiday.en-NZ20.date=20151226 -holiday.en-NZ21.name=New Year's Day -holiday.en-NZ21.date=20160101 -holiday.en-NZ22.name=Day after New Years Day -holiday.en-NZ22.date=20160104 -holiday.en-NZ23.name=Waitangi Day -holiday.en-NZ23.date=20160206 -holiday.en-NZ24.name=Good Friday -holiday.en-NZ24.date=20160325 -holiday.en-NZ25.name=Easter Monday -holiday.en-NZ25.date=20160328 -holiday.en-NZ26.name=ANZAC Day -holiday.en-NZ26.date=20160425 -holiday.en-NZ27.name=Queen's Birthday -holiday.en-NZ27.date=20160606 -holiday.en-NZ28.name=Labour Day -holiday.en-NZ28.date=20161024 -holiday.en-NZ29.name=Christmas Day -holiday.en-NZ29.date=20161225 -holiday.en-NZ30.name=Boxing Day -holiday.en-NZ30.date=20161226 +holiday.en-NZ20.date=20161226 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.en-US.rc task-2.5.0+dfsg/doc/rc/holidays.en-US.rc --- task-2.4.4+dfsg/doc/rc/holidays.en-US.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.en-US.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/en-US/2014.json # http://holidata.net/en-US/2015.json +# http://holidata.net/en-US/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,68 +28,46 @@ ############################################################################### holiday.en-US1.name=New Year's Day -holiday.en-US1.date=20140101 +holiday.en-US1.date=20150101 holiday.en-US2.name=Birthday of Martin Luther King, Jr. -holiday.en-US2.date=20140120 +holiday.en-US2.date=20150119 holiday.en-US3.name=Washington's Birthday -holiday.en-US3.date=20140217 +holiday.en-US3.date=20150216 holiday.en-US4.name=Patriots' Day -holiday.en-US4.date=20140421 +holiday.en-US4.date=20150420 holiday.en-US5.name=Memorial Day -holiday.en-US5.date=20140526 +holiday.en-US5.date=20150525 holiday.en-US6.name=Independence Day -holiday.en-US6.date=20140704 +holiday.en-US6.date=20150704 holiday.en-US7.name=Labor Day -holiday.en-US7.date=20140901 +holiday.en-US7.date=20150907 holiday.en-US8.name=Columbus Day -holiday.en-US8.date=20141013 +holiday.en-US8.date=20151012 holiday.en-US9.name=Veterans Day -holiday.en-US9.date=20141111 +holiday.en-US9.date=20151111 holiday.en-US10.name=Thanksgiving Day -holiday.en-US10.date=20141127 +holiday.en-US10.date=20151126 holiday.en-US11.name=Christmas Day -holiday.en-US11.date=20141225 +holiday.en-US11.date=20151225 holiday.en-US12.name=New Year's Day -holiday.en-US12.date=20150101 +holiday.en-US12.date=20160101 holiday.en-US13.name=Birthday of Martin Luther King, Jr. -holiday.en-US13.date=20150119 +holiday.en-US13.date=20160118 holiday.en-US14.name=Washington's Birthday -holiday.en-US14.date=20150216 +holiday.en-US14.date=20160215 holiday.en-US15.name=Patriots' Day -holiday.en-US15.date=20150420 +holiday.en-US15.date=20160418 holiday.en-US16.name=Memorial Day -holiday.en-US16.date=20150525 +holiday.en-US16.date=20160530 holiday.en-US17.name=Independence Day -holiday.en-US17.date=20150704 +holiday.en-US17.date=20160704 holiday.en-US18.name=Labor Day -holiday.en-US18.date=20150907 +holiday.en-US18.date=20160905 holiday.en-US19.name=Columbus Day -holiday.en-US19.date=20151012 +holiday.en-US19.date=20161010 holiday.en-US20.name=Veterans Day -holiday.en-US20.date=20151111 +holiday.en-US20.date=20161111 holiday.en-US21.name=Thanksgiving Day -holiday.en-US21.date=20151126 +holiday.en-US21.date=20161124 holiday.en-US22.name=Christmas Day -holiday.en-US22.date=20151225 -holiday.en-US23.name=New Year's Day -holiday.en-US23.date=20160101 -holiday.en-US24.name=Birthday of Martin Luther King, Jr. -holiday.en-US24.date=20160118 -holiday.en-US25.name=Washington's Birthday -holiday.en-US25.date=20160215 -holiday.en-US26.name=Patriots' Day -holiday.en-US26.date=20160418 -holiday.en-US27.name=Memorial Day -holiday.en-US27.date=20160530 -holiday.en-US28.name=Independence Day -holiday.en-US28.date=20160704 -holiday.en-US29.name=Labor Day -holiday.en-US29.date=20160905 -holiday.en-US30.name=Columbus Day -holiday.en-US30.date=20161010 -holiday.en-US31.name=Veterans Day -holiday.en-US31.date=20161111 -holiday.en-US32.name=Thanksgiving Day -holiday.en-US32.date=20161124 -holiday.en-US33.name=Christmas Day -holiday.en-US33.date=20161225 +holiday.en-US22.date=20161225 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.en-ZA.rc task-2.5.0+dfsg/doc/rc/holidays.en-ZA.rc --- task-2.4.4+dfsg/doc/rc/holidays.en-ZA.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.en-ZA.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/en-ZA/2014.json # http://holidata.net/en-ZA/2015.json +# http://holidata.net/en-ZA/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,74 +28,50 @@ ############################################################################### holiday.en-ZA1.name=New Year's Day -holiday.en-ZA1.date=20140101 +holiday.en-ZA1.date=20150101 holiday.en-ZA2.name=Human Rights Day -holiday.en-ZA2.date=20140321 +holiday.en-ZA2.date=20150321 holiday.en-ZA3.name=Good Friday -holiday.en-ZA3.date=20140418 +holiday.en-ZA3.date=20150403 holiday.en-ZA4.name=Family Day -holiday.en-ZA4.date=20140421 +holiday.en-ZA4.date=20150406 holiday.en-ZA5.name=Freedom Day -holiday.en-ZA5.date=20140427 +holiday.en-ZA5.date=20150427 holiday.en-ZA6.name=Workers' Day -holiday.en-ZA6.date=20140501 +holiday.en-ZA6.date=20150501 holiday.en-ZA7.name=Youth Day -holiday.en-ZA7.date=20140616 +holiday.en-ZA7.date=20150616 holiday.en-ZA8.name=National Women's Day -holiday.en-ZA8.date=20140809 +holiday.en-ZA8.date=20150809 holiday.en-ZA9.name=Heritage Day -holiday.en-ZA9.date=20140924 +holiday.en-ZA9.date=20150924 holiday.en-ZA10.name=Day of Reconciliation -holiday.en-ZA10.date=20141217 +holiday.en-ZA10.date=20151217 holiday.en-ZA11.name=Christmas Day -holiday.en-ZA11.date=20141225 +holiday.en-ZA11.date=20151225 holiday.en-ZA12.name=Day of Goodwill -holiday.en-ZA12.date=20141226 +holiday.en-ZA12.date=20151226 holiday.en-ZA13.name=New Year's Day -holiday.en-ZA13.date=20150101 +holiday.en-ZA13.date=20160101 holiday.en-ZA14.name=Human Rights Day -holiday.en-ZA14.date=20150321 +holiday.en-ZA14.date=20160321 holiday.en-ZA15.name=Good Friday -holiday.en-ZA15.date=20150403 +holiday.en-ZA15.date=20160325 holiday.en-ZA16.name=Family Day -holiday.en-ZA16.date=20150406 +holiday.en-ZA16.date=20160328 holiday.en-ZA17.name=Freedom Day -holiday.en-ZA17.date=20150427 +holiday.en-ZA17.date=20160427 holiday.en-ZA18.name=Workers' Day -holiday.en-ZA18.date=20150501 +holiday.en-ZA18.date=20160501 holiday.en-ZA19.name=Youth Day -holiday.en-ZA19.date=20150616 +holiday.en-ZA19.date=20160616 holiday.en-ZA20.name=National Women's Day -holiday.en-ZA20.date=20150809 +holiday.en-ZA20.date=20160809 holiday.en-ZA21.name=Heritage Day -holiday.en-ZA21.date=20150924 +holiday.en-ZA21.date=20160924 holiday.en-ZA22.name=Day of Reconciliation -holiday.en-ZA22.date=20151217 +holiday.en-ZA22.date=20161217 holiday.en-ZA23.name=Christmas Day -holiday.en-ZA23.date=20151225 +holiday.en-ZA23.date=20161225 holiday.en-ZA24.name=Day of Goodwill -holiday.en-ZA24.date=20151226 -holiday.en-ZA25.name=New Year's Day -holiday.en-ZA25.date=20160101 -holiday.en-ZA26.name=Human Rights Day -holiday.en-ZA26.date=20160321 -holiday.en-ZA27.name=Good Friday -holiday.en-ZA27.date=20160325 -holiday.en-ZA28.name=Family Day -holiday.en-ZA28.date=20160328 -holiday.en-ZA29.name=Freedom Day -holiday.en-ZA29.date=20160427 -holiday.en-ZA30.name=Workers' Day -holiday.en-ZA30.date=20160501 -holiday.en-ZA31.name=Youth Day -holiday.en-ZA31.date=20160616 -holiday.en-ZA32.name=National Women's Day -holiday.en-ZA32.date=20160809 -holiday.en-ZA33.name=Heritage Day -holiday.en-ZA33.date=20160924 -holiday.en-ZA34.name=Day of Reconciliation -holiday.en-ZA34.date=20161217 -holiday.en-ZA35.name=Christmas Day -holiday.en-ZA35.date=20161225 -holiday.en-ZA36.name=Day of Goodwill -holiday.en-ZA36.date=20161226 +holiday.en-ZA24.date=20161226 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.es-CO.rc task-2.5.0+dfsg/doc/rc/holidays.es-CO.rc --- task-2.4.4+dfsg/doc/rc/holidays.es-CO.rc 1970-01-01 00:00:00.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.es-CO.rc 2015-10-21 21:18:14.000000000 +0000 @@ -0,0 +1,105 @@ +############################################################################### +# International Holiday Data provided by Holidata.net +# http://holidata.net/es-CO/2015.json +# http://holidata.net/es-CO/2016.json +# +# 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 +# +############################################################################### + +holiday.es-CO1.name=Año Nuevo +holiday.es-CO1.date=20150101 +holiday.es-CO2.name=Día de los Reyes Magos +holiday.es-CO2.date=20150112 +holiday.es-CO3.name=Día de San José +holiday.es-CO3.date=20150323 +holiday.es-CO4.name=Jueves Santo +holiday.es-CO4.date=20150402 +holiday.es-CO5.name=Viernes Santo +holiday.es-CO5.date=20150403 +holiday.es-CO6.name=Domingo de Pascua +holiday.es-CO6.date=20150405 +holiday.es-CO7.name=Día del Trabajo +holiday.es-CO7.date=20150501 +holiday.es-CO8.name=La Ascensión del Señor +holiday.es-CO8.date=20150518 +holiday.es-CO9.name=Corpus Christi +holiday.es-CO9.date=20150608 +holiday.es-CO10.name=El Sagrado Corazón de Jesús +holiday.es-CO10.date=20150615 +holiday.es-CO11.name=San Pedro y San Pablo +holiday.es-CO11.date=20150629 +holiday.es-CO12.name=Grito de Independencia +holiday.es-CO12.date=20150720 +holiday.es-CO13.name=Batalla de Boyacá +holiday.es-CO13.date=20150807 +holiday.es-CO14.name=Asunción de la Virgen +holiday.es-CO14.date=20150817 +holiday.es-CO15.name=Día de la Raza +holiday.es-CO15.date=20151012 +holiday.es-CO16.name=Todos los Santos +holiday.es-CO16.date=20151102 +holiday.es-CO17.name=Independencia de Cartagena +holiday.es-CO17.date=20151116 +holiday.es-CO18.name=Inmaculada Concepción +holiday.es-CO18.date=20151208 +holiday.es-CO19.name=Navidad +holiday.es-CO19.date=20151225 +holiday.es-CO20.name=Año Nuevo +holiday.es-CO20.date=20160101 +holiday.es-CO21.name=Día de los Reyes Magos +holiday.es-CO21.date=20160111 +holiday.es-CO22.name=Día de San José +holiday.es-CO22.date=20160321 +holiday.es-CO23.name=Jueves Santo +holiday.es-CO23.date=20160324 +holiday.es-CO24.name=Viernes Santo +holiday.es-CO24.date=20160325 +holiday.es-CO25.name=Domingo de Pascua +holiday.es-CO25.date=20160326 +holiday.es-CO26.name=Día del Trabajo +holiday.es-CO26.date=20160501 +holiday.es-CO27.name=La Ascensión del Señor +holiday.es-CO27.date=20160509 +holiday.es-CO28.name=Corpus Christi +holiday.es-CO28.date=20160530 +holiday.es-CO29.name=El Sagrado Corazón de Jesús +holiday.es-CO29.date=20160606 +holiday.es-CO30.name=San Pedro y San Pablo +holiday.es-CO30.date=20160704 +holiday.es-CO31.name=Grito de Independencia +holiday.es-CO31.date=20160720 +holiday.es-CO32.name=Batalla de Boyacá +holiday.es-CO32.date=20160807 +holiday.es-CO33.name=Asunción de la Virgen +holiday.es-CO33.date=20160815 +holiday.es-CO34.name=Día de la Raza +holiday.es-CO34.date=20161017 +holiday.es-CO35.name=Todos los Santos +holiday.es-CO35.date=20161107 +holiday.es-CO36.name=Independencia de Cartagena +holiday.es-CO36.date=20161114 +holiday.es-CO37.name=Inmaculada Concepción +holiday.es-CO37.date=20161208 +holiday.es-CO38.name=Navidad +holiday.es-CO38.date=20161225 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.es-EC.rc task-2.5.0+dfsg/doc/rc/holidays.es-EC.rc --- task-2.4.4+dfsg/doc/rc/holidays.es-EC.rc 1970-01-01 00:00:00.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.es-EC.rc 2015-10-21 21:18:14.000000000 +0000 @@ -0,0 +1,75 @@ +############################################################################### +# International Holiday Data provided by Holidata.net +# http://holidata.net/es-EC/2015.json +# http://holidata.net/es-EC/2016.json +# +# 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 +# +############################################################################### + +holiday.es-EC1.name=Año Nuevo +holiday.es-EC1.date=20150101 +holiday.es-EC2.name=Año Nuevo +holiday.es-EC2.date=20150102 +holiday.es-EC3.name=Carnaval +holiday.es-EC3.date=20150216 +holiday.es-EC4.name=Carnaval +holiday.es-EC4.date=20150217 +holiday.es-EC5.name=Viernes Santo +holiday.es-EC5.date=20150403 +holiday.es-EC6.name=Día del Trabajo +holiday.es-EC6.date=20150501 +holiday.es-EC7.name=Batalla del Pichincha +holiday.es-EC7.date=20150524 +holiday.es-EC8.name=Primer Grito de Independencia +holiday.es-EC8.date=20150810 +holiday.es-EC9.name=Independencia de Guayaquil +holiday.es-EC9.date=20151009 +holiday.es-EC10.name=Día de Difuntos +holiday.es-EC10.date=20151102 +holiday.es-EC11.name=Independencia de Cuenca +holiday.es-EC11.date=20151103 +holiday.es-EC12.name=Navidad +holiday.es-EC12.date=20151225 +holiday.es-EC13.name=Año Nuevo +holiday.es-EC13.date=20160101 +holiday.es-EC14.name=Carnaval +holiday.es-EC14.date=20160208 +holiday.es-EC15.name=Carnaval +holiday.es-EC15.date=20160209 +holiday.es-EC16.name=Viernes Santo +holiday.es-EC16.date=20160325 +holiday.es-EC17.name=Día del Trabajo +holiday.es-EC17.date=20160501 +holiday.es-EC18.name=Batalla del Pichincha +holiday.es-EC18.date=20160524 +holiday.es-EC19.name=Primer Grito de Independencia +holiday.es-EC19.date=20160810 +holiday.es-EC20.name=Independencia de Guayaquil +holiday.es-EC20.date=20161009 +holiday.es-EC21.name=Día de Difuntos +holiday.es-EC21.date=20161102 +holiday.es-EC22.name=Independencia de Cuenca +holiday.es-EC22.date=20161103 +holiday.es-EC23.name=Navidad +holiday.es-EC23.date=20161225 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.es-ES.rc task-2.5.0+dfsg/doc/rc/holidays.es-ES.rc --- task-2.4.4+dfsg/doc/rc/holidays.es-ES.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.es-ES.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/es-ES/2014.json # http://holidata.net/es-ES/2015.json +# http://holidata.net/es-ES/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,80 +28,54 @@ ############################################################################### holiday.es-ES1.name=Año Nuevo -holiday.es-ES1.date=20140101 +holiday.es-ES1.date=20150101 holiday.es-ES2.name=Día de los Reyes -holiday.es-ES2.date=20140106 +holiday.es-ES2.date=20150106 holiday.es-ES3.name=Viernes Santo -holiday.es-ES3.date=20140418 +holiday.es-ES3.date=20150403 holiday.es-ES4.name=Pascua -holiday.es-ES4.date=20140420 +holiday.es-ES4.date=20150405 holiday.es-ES5.name=Fiesta del Trabajo -holiday.es-ES5.date=20140501 +holiday.es-ES5.date=20150501 holiday.es-ES6.name=Asunción de la Virgen -holiday.es-ES6.date=20140815 +holiday.es-ES6.date=20150815 holiday.es-ES7.name=Fiesta Nacional de España -holiday.es-ES7.date=20141012 +holiday.es-ES7.date=20151012 holiday.es-ES8.name=Dia de todos los Santos -holiday.es-ES8.date=20141101 +holiday.es-ES8.date=20151101 holiday.es-ES9.name=Dia de la Constitución -holiday.es-ES9.date=20141206 +holiday.es-ES9.date=20151206 holiday.es-ES10.name=Inmaculada Concepción -holiday.es-ES10.date=20141208 +holiday.es-ES10.date=20151208 holiday.es-ES11.name=Noche Buena -holiday.es-ES11.date=20141224 +holiday.es-ES11.date=20151224 holiday.es-ES12.name=Navidad -holiday.es-ES12.date=20141225 +holiday.es-ES12.date=20151225 holiday.es-ES13.name=Noche Vieja -holiday.es-ES13.date=20141231 +holiday.es-ES13.date=20151231 holiday.es-ES14.name=Año Nuevo -holiday.es-ES14.date=20150101 +holiday.es-ES14.date=20160101 holiday.es-ES15.name=Día de los Reyes -holiday.es-ES15.date=20150106 +holiday.es-ES15.date=20160106 holiday.es-ES16.name=Viernes Santo -holiday.es-ES16.date=20150403 +holiday.es-ES16.date=20160325 holiday.es-ES17.name=Pascua -holiday.es-ES17.date=20150405 +holiday.es-ES17.date=20160327 holiday.es-ES18.name=Fiesta del Trabajo -holiday.es-ES18.date=20150501 +holiday.es-ES18.date=20160501 holiday.es-ES19.name=Asunción de la Virgen -holiday.es-ES19.date=20150815 +holiday.es-ES19.date=20160815 holiday.es-ES20.name=Fiesta Nacional de España -holiday.es-ES20.date=20151012 +holiday.es-ES20.date=20161012 holiday.es-ES21.name=Dia de todos los Santos -holiday.es-ES21.date=20151101 +holiday.es-ES21.date=20161101 holiday.es-ES22.name=Dia de la Constitución -holiday.es-ES22.date=20151206 +holiday.es-ES22.date=20161206 holiday.es-ES23.name=Inmaculada Concepción -holiday.es-ES23.date=20151208 +holiday.es-ES23.date=20161208 holiday.es-ES24.name=Noche Buena -holiday.es-ES24.date=20151224 +holiday.es-ES24.date=20161224 holiday.es-ES25.name=Navidad -holiday.es-ES25.date=20151225 +holiday.es-ES25.date=20161225 holiday.es-ES26.name=Noche Vieja -holiday.es-ES26.date=20151231 -holiday.es-ES27.name=Año Nuevo -holiday.es-ES27.date=20160101 -holiday.es-ES28.name=Día de los Reyes -holiday.es-ES28.date=20160106 -holiday.es-ES29.name=Viernes Santo -holiday.es-ES29.date=20160325 -holiday.es-ES30.name=Pascua -holiday.es-ES30.date=20160327 -holiday.es-ES31.name=Fiesta del Trabajo -holiday.es-ES31.date=20160501 -holiday.es-ES32.name=Asunción de la Virgen -holiday.es-ES32.date=20160815 -holiday.es-ES33.name=Fiesta Nacional de España -holiday.es-ES33.date=20161012 -holiday.es-ES34.name=Dia de todos los Santos -holiday.es-ES34.date=20161101 -holiday.es-ES35.name=Dia de la Constitución -holiday.es-ES35.date=20161206 -holiday.es-ES36.name=Inmaculada Concepción -holiday.es-ES36.date=20161208 -holiday.es-ES37.name=Noche Buena -holiday.es-ES37.date=20161224 -holiday.es-ES38.name=Navidad -holiday.es-ES38.date=20161225 -holiday.es-ES39.name=Noche Vieja -holiday.es-ES39.date=20161231 +holiday.es-ES26.date=20161231 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.es-MX.rc task-2.5.0+dfsg/doc/rc/holidays.es-MX.rc --- task-2.4.4+dfsg/doc/rc/holidays.es-MX.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.es-MX.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/es-MX/2014.json # http://holidata.net/es-MX/2015.json +# http://holidata.net/es-MX/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,62 +28,42 @@ ############################################################################### holiday.es-MX1.name=Año Nuevo -holiday.es-MX1.date=20140101 +holiday.es-MX1.date=20150101 holiday.es-MX2.name=Día de la Constitución -holiday.es-MX2.date=20140203 +holiday.es-MX2.date=20150202 holiday.es-MX3.name=Natalicio de Benito Juárez -holiday.es-MX3.date=20140317 +holiday.es-MX3.date=20150316 holiday.es-MX4.name=Jueves Santo -holiday.es-MX4.date=20140417 +holiday.es-MX4.date=20150402 holiday.es-MX5.name=Viernes Santo -holiday.es-MX5.date=20140418 +holiday.es-MX5.date=20150403 holiday.es-MX6.name=Día del Trabajo -holiday.es-MX6.date=20140501 +holiday.es-MX6.date=20150501 holiday.es-MX7.name=Día de la Independencia -holiday.es-MX7.date=20140916 +holiday.es-MX7.date=20150916 holiday.es-MX8.name=Día de la Revolución -holiday.es-MX8.date=20141117 +holiday.es-MX8.date=20151116 holiday.es-MX9.name=Nuestra Señora de Guadalupe -holiday.es-MX9.date=20141212 +holiday.es-MX9.date=20151212 holiday.es-MX10.name=Navidad -holiday.es-MX10.date=20141225 +holiday.es-MX10.date=20151225 holiday.es-MX11.name=Año Nuevo -holiday.es-MX11.date=20150101 +holiday.es-MX11.date=20160101 holiday.es-MX12.name=Día de la Constitución -holiday.es-MX12.date=20150202 +holiday.es-MX12.date=20160201 holiday.es-MX13.name=Natalicio de Benito Juárez -holiday.es-MX13.date=20150316 +holiday.es-MX13.date=20160314 holiday.es-MX14.name=Jueves Santo -holiday.es-MX14.date=20150402 +holiday.es-MX14.date=20160324 holiday.es-MX15.name=Viernes Santo -holiday.es-MX15.date=20150403 +holiday.es-MX15.date=20160325 holiday.es-MX16.name=Día del Trabajo -holiday.es-MX16.date=20150501 +holiday.es-MX16.date=20160501 holiday.es-MX17.name=Día de la Independencia -holiday.es-MX17.date=20150916 +holiday.es-MX17.date=20160916 holiday.es-MX18.name=Día de la Revolución -holiday.es-MX18.date=20151116 +holiday.es-MX18.date=20161121 holiday.es-MX19.name=Nuestra Señora de Guadalupe -holiday.es-MX19.date=20151212 +holiday.es-MX19.date=20161212 holiday.es-MX20.name=Navidad -holiday.es-MX20.date=20151225 -holiday.es-MX21.name=Año Nuevo -holiday.es-MX21.date=20160101 -holiday.es-MX22.name=Día de la Constitución -holiday.es-MX22.date=20160201 -holiday.es-MX23.name=Natalicio de Benito Juárez -holiday.es-MX23.date=20160314 -holiday.es-MX24.name=Jueves Santo -holiday.es-MX24.date=20160324 -holiday.es-MX25.name=Viernes Santo -holiday.es-MX25.date=20160325 -holiday.es-MX26.name=Día del Trabajo -holiday.es-MX26.date=20160501 -holiday.es-MX27.name=Día de la Independencia -holiday.es-MX27.date=20160916 -holiday.es-MX28.name=Día de la Revolución -holiday.es-MX28.date=20161121 -holiday.es-MX29.name=Nuestra Señora de Guadalupe -holiday.es-MX29.date=20161212 -holiday.es-MX30.name=Navidad -holiday.es-MX30.date=20161225 +holiday.es-MX20.date=20161225 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.es-US.rc task-2.5.0+dfsg/doc/rc/holidays.es-US.rc --- task-2.4.4+dfsg/doc/rc/holidays.es-US.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.es-US.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/es-US/2014.json # http://holidata.net/es-US/2015.json +# http://holidata.net/es-US/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,68 +28,46 @@ ############################################################################### holiday.es-US1.name=Año Neuvo -holiday.es-US1.date=20140101 +holiday.es-US1.date=20150101 holiday.es-US2.name=Cumpleaños de Martin Luther King, Jr. -holiday.es-US2.date=20140120 +holiday.es-US2.date=20150119 holiday.es-US3.name=Día del Presidente -holiday.es-US3.date=20140217 +holiday.es-US3.date=20150216 holiday.es-US4.name=Día del Patriota -holiday.es-US4.date=20140421 +holiday.es-US4.date=20150420 holiday.es-US5.name=Día de los Caídos -holiday.es-US5.date=20140526 +holiday.es-US5.date=20150525 holiday.es-US6.name=Día de la Independiencia -holiday.es-US6.date=20140704 +holiday.es-US6.date=20150704 holiday.es-US7.name=Día del Trabajo -holiday.es-US7.date=20140901 +holiday.es-US7.date=20150907 holiday.es-US8.name=Día de Columbus -holiday.es-US8.date=20141013 +holiday.es-US8.date=20151012 holiday.es-US9.name=Día de los Veteranos -holiday.es-US9.date=20141111 +holiday.es-US9.date=20151111 holiday.es-US10.name=Día de Acción de Gracias -holiday.es-US10.date=20141127 +holiday.es-US10.date=20151126 holiday.es-US11.name=Navidad -holiday.es-US11.date=20141225 +holiday.es-US11.date=20151225 holiday.es-US12.name=Año Neuvo -holiday.es-US12.date=20150101 +holiday.es-US12.date=20160101 holiday.es-US13.name=Cumpleaños de Martin Luther King, Jr. -holiday.es-US13.date=20150119 +holiday.es-US13.date=20160118 holiday.es-US14.name=Día del Presidente -holiday.es-US14.date=20150216 +holiday.es-US14.date=20160215 holiday.es-US15.name=Día del Patriota -holiday.es-US15.date=20150420 +holiday.es-US15.date=20160418 holiday.es-US16.name=Día de los Caídos -holiday.es-US16.date=20150525 +holiday.es-US16.date=20160530 holiday.es-US17.name=Día de la Independiencia -holiday.es-US17.date=20150704 +holiday.es-US17.date=20160704 holiday.es-US18.name=Día del Trabajo -holiday.es-US18.date=20150907 +holiday.es-US18.date=20160905 holiday.es-US19.name=Día de Columbus -holiday.es-US19.date=20151012 +holiday.es-US19.date=20161010 holiday.es-US20.name=Día de los Veteranos -holiday.es-US20.date=20151111 +holiday.es-US20.date=20161111 holiday.es-US21.name=Día de Acción de Gracias -holiday.es-US21.date=20151126 +holiday.es-US21.date=20161124 holiday.es-US22.name=Navidad -holiday.es-US22.date=20151225 -holiday.es-US23.name=Año Neuvo -holiday.es-US23.date=20160101 -holiday.es-US24.name=Cumpleaños de Martin Luther King, Jr. -holiday.es-US24.date=20160118 -holiday.es-US25.name=Día del Presidente -holiday.es-US25.date=20160215 -holiday.es-US26.name=Día del Patriota -holiday.es-US26.date=20160418 -holiday.es-US27.name=Día de los Caídos -holiday.es-US27.date=20160530 -holiday.es-US28.name=Día de la Independiencia -holiday.es-US28.date=20160704 -holiday.es-US29.name=Día del Trabajo -holiday.es-US29.date=20160905 -holiday.es-US30.name=Día de Columbus -holiday.es-US30.date=20161010 -holiday.es-US31.name=Día de los Veteranos -holiday.es-US31.date=20161111 -holiday.es-US32.name=Día de Acción de Gracias -holiday.es-US32.date=20161124 -holiday.es-US33.name=Navidad -holiday.es-US33.date=20161225 +holiday.es-US22.date=20161225 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.et-EE.rc task-2.5.0+dfsg/doc/rc/holidays.et-EE.rc --- task-2.4.4+dfsg/doc/rc/holidays.et-EE.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.et-EE.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/et-EE/2014.json # http://holidata.net/et-EE/2015.json +# http://holidata.net/et-EE/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,74 +28,50 @@ ############################################################################### holiday.et-EE1.name=uusaasta -holiday.et-EE1.date=20140101 +holiday.et-EE1.date=20150101 holiday.et-EE2.name=iseseisvuspäev -holiday.et-EE2.date=20140224 +holiday.et-EE2.date=20150224 holiday.et-EE3.name=suur reede -holiday.et-EE3.date=20140418 +holiday.et-EE3.date=20150403 holiday.et-EE4.name=ülestõusmispühade 1. püha -holiday.et-EE4.date=20140420 +holiday.et-EE4.date=20150405 holiday.et-EE5.name=kevadpüha -holiday.et-EE5.date=20140501 +holiday.et-EE5.date=20150501 holiday.et-EE6.name=nelipühade 1. püha -holiday.et-EE6.date=20140608 +holiday.et-EE6.date=20150524 holiday.et-EE7.name=võidupüha -holiday.et-EE7.date=20140623 +holiday.et-EE7.date=20150623 holiday.et-EE8.name=jaanipäev -holiday.et-EE8.date=20140624 +holiday.et-EE8.date=20150624 holiday.et-EE9.name=taasiseseisvumispäev -holiday.et-EE9.date=20140820 +holiday.et-EE9.date=20150820 holiday.et-EE10.name=jõululaupäev -holiday.et-EE10.date=20141224 +holiday.et-EE10.date=20151224 holiday.et-EE11.name=esimene jõulupüha -holiday.et-EE11.date=20141225 +holiday.et-EE11.date=20151225 holiday.et-EE12.name=teine jõulupüha -holiday.et-EE12.date=20141226 +holiday.et-EE12.date=20151226 holiday.et-EE13.name=uusaasta -holiday.et-EE13.date=20150101 +holiday.et-EE13.date=20160101 holiday.et-EE14.name=iseseisvuspäev -holiday.et-EE14.date=20150224 +holiday.et-EE14.date=20160224 holiday.et-EE15.name=suur reede -holiday.et-EE15.date=20150403 +holiday.et-EE15.date=20160325 holiday.et-EE16.name=ülestõusmispühade 1. püha -holiday.et-EE16.date=20150405 +holiday.et-EE16.date=20160327 holiday.et-EE17.name=kevadpüha -holiday.et-EE17.date=20150501 +holiday.et-EE17.date=20160501 holiday.et-EE18.name=nelipühade 1. püha -holiday.et-EE18.date=20150524 +holiday.et-EE18.date=20160515 holiday.et-EE19.name=võidupüha -holiday.et-EE19.date=20150623 +holiday.et-EE19.date=20160623 holiday.et-EE20.name=jaanipäev -holiday.et-EE20.date=20150624 +holiday.et-EE20.date=20160624 holiday.et-EE21.name=taasiseseisvumispäev -holiday.et-EE21.date=20150820 +holiday.et-EE21.date=20160820 holiday.et-EE22.name=jõululaupäev -holiday.et-EE22.date=20151224 +holiday.et-EE22.date=20161224 holiday.et-EE23.name=esimene jõulupüha -holiday.et-EE23.date=20151225 +holiday.et-EE23.date=20161225 holiday.et-EE24.name=teine jõulupüha -holiday.et-EE24.date=20151226 -holiday.et-EE25.name=uusaasta -holiday.et-EE25.date=20160101 -holiday.et-EE26.name=iseseisvuspäev -holiday.et-EE26.date=20160224 -holiday.et-EE27.name=suur reede -holiday.et-EE27.date=20160325 -holiday.et-EE28.name=ülestõusmispühade 1. püha -holiday.et-EE28.date=20160327 -holiday.et-EE29.name=kevadpüha -holiday.et-EE29.date=20160501 -holiday.et-EE30.name=nelipühade 1. püha -holiday.et-EE30.date=20160515 -holiday.et-EE31.name=võidupüha -holiday.et-EE31.date=20160623 -holiday.et-EE32.name=jaanipäev -holiday.et-EE32.date=20160624 -holiday.et-EE33.name=taasiseseisvumispäev -holiday.et-EE33.date=20160820 -holiday.et-EE34.name=jõululaupäev -holiday.et-EE34.date=20161224 -holiday.et-EE35.name=esimene jõulupüha -holiday.et-EE35.date=20161225 -holiday.et-EE36.name=teine jõulupüha -holiday.et-EE36.date=20161226 +holiday.et-EE24.date=20161226 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.fi-FI.rc task-2.5.0+dfsg/doc/rc/holidays.fi-FI.rc --- task-2.4.4+dfsg/doc/rc/holidays.fi-FI.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.fi-FI.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/fi-FI/2014.json # http://holidata.net/fi-FI/2015.json +# http://holidata.net/fi-FI/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,92 +28,62 @@ ############################################################################### holiday.fi-FI1.name=Uudenvuodenpäivä -holiday.fi-FI1.date=20140101 +holiday.fi-FI1.date=20150101 holiday.fi-FI2.name=Loppiainen -holiday.fi-FI2.date=20140106 +holiday.fi-FI2.date=20150106 holiday.fi-FI3.name=Pitkäperjantai -holiday.fi-FI3.date=20140418 +holiday.fi-FI3.date=20150403 holiday.fi-FI4.name=Pääsiäispäivä -holiday.fi-FI4.date=20140420 +holiday.fi-FI4.date=20150405 holiday.fi-FI5.name=2. pääsiäispäivä -holiday.fi-FI5.date=20140421 +holiday.fi-FI5.date=20150406 holiday.fi-FI6.name=Vappu -holiday.fi-FI6.date=20140501 +holiday.fi-FI6.date=20150501 holiday.fi-FI7.name=Helatorstai -holiday.fi-FI7.date=20140529 +holiday.fi-FI7.date=20150514 holiday.fi-FI8.name=Helluntaipäivä -holiday.fi-FI8.date=20140608 +holiday.fi-FI8.date=20150524 holiday.fi-FI9.name=Juhannusaatto -holiday.fi-FI9.date=20140620 +holiday.fi-FI9.date=20150619 holiday.fi-FI10.name=Juhannuspäivä -holiday.fi-FI10.date=20140621 +holiday.fi-FI10.date=20150620 holiday.fi-FI11.name=Pyhäinpäivä -holiday.fi-FI11.date=20141101 +holiday.fi-FI11.date=20151031 holiday.fi-FI12.name=Itsenäisyyspäivä -holiday.fi-FI12.date=20141206 +holiday.fi-FI12.date=20151206 holiday.fi-FI13.name=Jouluaatto -holiday.fi-FI13.date=20141224 +holiday.fi-FI13.date=20151224 holiday.fi-FI14.name=Joulupäivä -holiday.fi-FI14.date=20141225 +holiday.fi-FI14.date=20151225 holiday.fi-FI15.name=2. joulupäivä -holiday.fi-FI15.date=20141226 +holiday.fi-FI15.date=20151226 holiday.fi-FI16.name=Uudenvuodenpäivä -holiday.fi-FI16.date=20150101 +holiday.fi-FI16.date=20160101 holiday.fi-FI17.name=Loppiainen -holiday.fi-FI17.date=20150106 +holiday.fi-FI17.date=20160106 holiday.fi-FI18.name=Pitkäperjantai -holiday.fi-FI18.date=20150403 +holiday.fi-FI18.date=20160325 holiday.fi-FI19.name=Pääsiäispäivä -holiday.fi-FI19.date=20150405 +holiday.fi-FI19.date=20160327 holiday.fi-FI20.name=2. pääsiäispäivä -holiday.fi-FI20.date=20150406 +holiday.fi-FI20.date=20160328 holiday.fi-FI21.name=Vappu -holiday.fi-FI21.date=20150501 +holiday.fi-FI21.date=20160501 holiday.fi-FI22.name=Helatorstai -holiday.fi-FI22.date=20150514 +holiday.fi-FI22.date=20160505 holiday.fi-FI23.name=Helluntaipäivä -holiday.fi-FI23.date=20150524 +holiday.fi-FI23.date=20160515 holiday.fi-FI24.name=Juhannusaatto -holiday.fi-FI24.date=20150619 +holiday.fi-FI24.date=20160624 holiday.fi-FI25.name=Juhannuspäivä -holiday.fi-FI25.date=20150620 +holiday.fi-FI25.date=20160625 holiday.fi-FI26.name=Pyhäinpäivä -holiday.fi-FI26.date=20151031 +holiday.fi-FI26.date=20161105 holiday.fi-FI27.name=Itsenäisyyspäivä -holiday.fi-FI27.date=20151206 +holiday.fi-FI27.date=20161206 holiday.fi-FI28.name=Jouluaatto -holiday.fi-FI28.date=20151224 +holiday.fi-FI28.date=20161224 holiday.fi-FI29.name=Joulupäivä -holiday.fi-FI29.date=20151225 +holiday.fi-FI29.date=20161225 holiday.fi-FI30.name=2. joulupäivä -holiday.fi-FI30.date=20151226 -holiday.fi-FI31.name=Uudenvuodenpäivä -holiday.fi-FI31.date=20160101 -holiday.fi-FI32.name=Loppiainen -holiday.fi-FI32.date=20160106 -holiday.fi-FI33.name=Pitkäperjantai -holiday.fi-FI33.date=20160325 -holiday.fi-FI34.name=Pääsiäispäivä -holiday.fi-FI34.date=20160327 -holiday.fi-FI35.name=2. pääsiäispäivä -holiday.fi-FI35.date=20160328 -holiday.fi-FI36.name=Vappu -holiday.fi-FI36.date=20160501 -holiday.fi-FI37.name=Helatorstai -holiday.fi-FI37.date=20160505 -holiday.fi-FI38.name=Helluntaipäivä -holiday.fi-FI38.date=20160515 -holiday.fi-FI39.name=Juhannusaatto -holiday.fi-FI39.date=20160624 -holiday.fi-FI40.name=Juhannuspäivä -holiday.fi-FI40.date=20160625 -holiday.fi-FI41.name=Pyhäinpäivä -holiday.fi-FI41.date=20161105 -holiday.fi-FI42.name=Itsenäisyyspäivä -holiday.fi-FI42.date=20161206 -holiday.fi-FI43.name=Jouluaatto -holiday.fi-FI43.date=20161224 -holiday.fi-FI44.name=Joulupäivä -holiday.fi-FI44.date=20161225 -holiday.fi-FI45.name=2. joulupäivä -holiday.fi-FI45.date=20161226 +holiday.fi-FI30.date=20161226 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.fr-BE.rc task-2.5.0+dfsg/doc/rc/holidays.fr-BE.rc --- task-2.4.4+dfsg/doc/rc/holidays.fr-BE.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.fr-BE.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/fr-BE/2014.json # http://holidata.net/fr-BE/2015.json +# http://holidata.net/fr-BE/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,74 +28,50 @@ ############################################################################### holiday.fr-BE1.name=Nouvel An -holiday.fr-BE1.date=20140101 +holiday.fr-BE1.date=20150101 holiday.fr-BE2.name=Pâques -holiday.fr-BE2.date=20140420 +holiday.fr-BE2.date=20150405 holiday.fr-BE3.name=Lundi de Pâques -holiday.fr-BE3.date=20140421 +holiday.fr-BE3.date=20150406 holiday.fr-BE4.name=Fête du Travail -holiday.fr-BE4.date=20140501 +holiday.fr-BE4.date=20150501 holiday.fr-BE5.name=Ascension -holiday.fr-BE5.date=20140529 +holiday.fr-BE5.date=20150514 holiday.fr-BE6.name=Pentecôte -holiday.fr-BE6.date=20140608 +holiday.fr-BE6.date=20150524 holiday.fr-BE7.name=Lundi de Pentecôte -holiday.fr-BE7.date=20140609 +holiday.fr-BE7.date=20150525 holiday.fr-BE8.name=Fête nationale -holiday.fr-BE8.date=20140721 +holiday.fr-BE8.date=20150721 holiday.fr-BE9.name=Assomption -holiday.fr-BE9.date=20140815 +holiday.fr-BE9.date=20150815 holiday.fr-BE10.name=Toussaint -holiday.fr-BE10.date=20141101 +holiday.fr-BE10.date=20151101 holiday.fr-BE11.name=Jour de l'armistice -holiday.fr-BE11.date=20141111 +holiday.fr-BE11.date=20151111 holiday.fr-BE12.name=Noël -holiday.fr-BE12.date=20141225 +holiday.fr-BE12.date=20151225 holiday.fr-BE13.name=Nouvel An -holiday.fr-BE13.date=20150101 +holiday.fr-BE13.date=20160101 holiday.fr-BE14.name=Pâques -holiday.fr-BE14.date=20150405 +holiday.fr-BE14.date=20160527 holiday.fr-BE15.name=Lundi de Pâques -holiday.fr-BE15.date=20150406 +holiday.fr-BE15.date=20160528 holiday.fr-BE16.name=Fête du Travail -holiday.fr-BE16.date=20150501 +holiday.fr-BE16.date=20160501 holiday.fr-BE17.name=Ascension -holiday.fr-BE17.date=20150514 +holiday.fr-BE17.date=20160505 holiday.fr-BE18.name=Pentecôte -holiday.fr-BE18.date=20150524 +holiday.fr-BE18.date=20160515 holiday.fr-BE19.name=Lundi de Pentecôte -holiday.fr-BE19.date=20150525 +holiday.fr-BE19.date=20160516 holiday.fr-BE20.name=Fête nationale -holiday.fr-BE20.date=20150721 +holiday.fr-BE20.date=20160721 holiday.fr-BE21.name=Assomption -holiday.fr-BE21.date=20150815 +holiday.fr-BE21.date=20160815 holiday.fr-BE22.name=Toussaint -holiday.fr-BE22.date=20151101 +holiday.fr-BE22.date=20161101 holiday.fr-BE23.name=Jour de l'armistice -holiday.fr-BE23.date=20151111 +holiday.fr-BE23.date=20161111 holiday.fr-BE24.name=Noël -holiday.fr-BE24.date=20151225 -holiday.fr-BE25.name=Nouvel An -holiday.fr-BE25.date=20160101 -holiday.fr-BE26.name=Pâques -holiday.fr-BE26.date=20160527 -holiday.fr-BE27.name=Lundi de Pâques -holiday.fr-BE27.date=20160528 -holiday.fr-BE28.name=Fête du Travail -holiday.fr-BE28.date=20160501 -holiday.fr-BE29.name=Ascension -holiday.fr-BE29.date=20160505 -holiday.fr-BE30.name=Pentecôte -holiday.fr-BE30.date=20160515 -holiday.fr-BE31.name=Lundi de Pentecôte -holiday.fr-BE31.date=20160516 -holiday.fr-BE32.name=Fête nationale -holiday.fr-BE32.date=20160721 -holiday.fr-BE33.name=Assomption -holiday.fr-BE33.date=20160815 -holiday.fr-BE34.name=Toussaint -holiday.fr-BE34.date=20161101 -holiday.fr-BE35.name=Jour de l'armistice -holiday.fr-BE35.date=20161111 -holiday.fr-BE36.name=Noël -holiday.fr-BE36.date=20161225 +holiday.fr-BE24.date=20161225 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.fr-FR.rc task-2.5.0+dfsg/doc/rc/holidays.fr-FR.rc --- task-2.4.4+dfsg/doc/rc/holidays.fr-FR.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.fr-FR.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/fr-FR/2014.json # http://holidata.net/fr-FR/2015.json +# http://holidata.net/fr-FR/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,68 +28,46 @@ ############################################################################### holiday.fr-FR1.name=Jour de l'an -holiday.fr-FR1.date=20140101 +holiday.fr-FR1.date=20150101 holiday.fr-FR2.name=Lundi de Pâques -holiday.fr-FR2.date=20140421 +holiday.fr-FR2.date=20150406 holiday.fr-FR3.name=Fête du premier mai -holiday.fr-FR3.date=20140501 +holiday.fr-FR3.date=20150501 holiday.fr-FR4.name=Armistice 1945 -holiday.fr-FR4.date=20140508 +holiday.fr-FR4.date=20150508 holiday.fr-FR5.name=Ascencion -holiday.fr-FR5.date=20140529 +holiday.fr-FR5.date=20150514 holiday.fr-FR6.name=Pentecôte -holiday.fr-FR6.date=20140608 +holiday.fr-FR6.date=20150524 holiday.fr-FR7.name=Fête nationale -holiday.fr-FR7.date=20140714 +holiday.fr-FR7.date=20150714 holiday.fr-FR8.name=Assomption -holiday.fr-FR8.date=20140815 +holiday.fr-FR8.date=20150815 holiday.fr-FR9.name=Toussaint -holiday.fr-FR9.date=20141101 +holiday.fr-FR9.date=20151101 holiday.fr-FR10.name=Armistice 1918 -holiday.fr-FR10.date=20141111 +holiday.fr-FR10.date=20151111 holiday.fr-FR11.name=Noël -holiday.fr-FR11.date=20141225 +holiday.fr-FR11.date=20151225 holiday.fr-FR12.name=Jour de l'an -holiday.fr-FR12.date=20150101 +holiday.fr-FR12.date=20160101 holiday.fr-FR13.name=Lundi de Pâques -holiday.fr-FR13.date=20150406 +holiday.fr-FR13.date=20160328 holiday.fr-FR14.name=Fête du premier mai -holiday.fr-FR14.date=20150501 +holiday.fr-FR14.date=20160501 holiday.fr-FR15.name=Armistice 1945 -holiday.fr-FR15.date=20150508 +holiday.fr-FR15.date=20160508 holiday.fr-FR16.name=Ascencion -holiday.fr-FR16.date=20150514 +holiday.fr-FR16.date=20160505 holiday.fr-FR17.name=Pentecôte -holiday.fr-FR17.date=20150524 +holiday.fr-FR17.date=20160515 holiday.fr-FR18.name=Fête nationale -holiday.fr-FR18.date=20150714 +holiday.fr-FR18.date=20160714 holiday.fr-FR19.name=Assomption -holiday.fr-FR19.date=20150815 +holiday.fr-FR19.date=20160815 holiday.fr-FR20.name=Toussaint -holiday.fr-FR20.date=20151101 +holiday.fr-FR20.date=20161101 holiday.fr-FR21.name=Armistice 1918 -holiday.fr-FR21.date=20151111 +holiday.fr-FR21.date=20161111 holiday.fr-FR22.name=Noël -holiday.fr-FR22.date=20151225 -holiday.fr-FR23.name=Jour de l'an -holiday.fr-FR23.date=20160101 -holiday.fr-FR24.name=Lundi de Pâques -holiday.fr-FR24.date=20160328 -holiday.fr-FR25.name=Fête du premier mai -holiday.fr-FR25.date=20160501 -holiday.fr-FR26.name=Armistice 1945 -holiday.fr-FR26.date=20160508 -holiday.fr-FR27.name=Ascencion -holiday.fr-FR27.date=20160505 -holiday.fr-FR28.name=Pentecôte -holiday.fr-FR28.date=20160515 -holiday.fr-FR29.name=Fête nationale -holiday.fr-FR29.date=20160714 -holiday.fr-FR30.name=Assomption -holiday.fr-FR30.date=20160815 -holiday.fr-FR31.name=Toussaint -holiday.fr-FR31.date=20161101 -holiday.fr-FR32.name=Armistice 1918 -holiday.fr-FR32.date=20161111 -holiday.fr-FR33.name=Noël -holiday.fr-FR33.date=20161225 +holiday.fr-FR22.date=20161225 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.ga-IE.rc task-2.5.0+dfsg/doc/rc/holidays.ga-IE.rc --- task-2.4.4+dfsg/doc/rc/holidays.ga-IE.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.ga-IE.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/ga-IE/2014.json # http://holidata.net/ga-IE/2015.json +# http://holidata.net/ga-IE/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,56 +28,38 @@ ############################################################################### holiday.ga-IE1.name=Lá Caille or Lá Bliana Nua -holiday.ga-IE1.date=20140101 +holiday.ga-IE1.date=20150101 holiday.ga-IE2.name=Lá Fhéile Pádraig -holiday.ga-IE2.date=20140317 +holiday.ga-IE2.date=20150317 holiday.ga-IE3.name=Luan Cásca -holiday.ga-IE3.date=20140421 +holiday.ga-IE3.date=20150406 holiday.ga-IE4.name=Lá an Lucht Oibre -holiday.ga-IE4.date=20140505 +holiday.ga-IE4.date=20150504 holiday.ga-IE5.name=Lá Saoire i mí Mheitheamh -holiday.ga-IE5.date=20140602 +holiday.ga-IE5.date=20150601 holiday.ga-IE6.name=Lá Saoire i mí Lúnasa -holiday.ga-IE6.date=20140804 +holiday.ga-IE6.date=20150803 holiday.ga-IE7.name=Lá Saoire i mí Dheireadh Fómhair -holiday.ga-IE7.date=20141027 +holiday.ga-IE7.date=20151026 holiday.ga-IE8.name=Lá Nollag -holiday.ga-IE8.date=20141225 +holiday.ga-IE8.date=20151225 holiday.ga-IE9.name=Lá Fhéile Stiofáin or Lá an Dreoilín -holiday.ga-IE9.date=20141226 +holiday.ga-IE9.date=20151226 holiday.ga-IE10.name=Lá Caille or Lá Bliana Nua -holiday.ga-IE10.date=20150101 +holiday.ga-IE10.date=20160101 holiday.ga-IE11.name=Lá Fhéile Pádraig -holiday.ga-IE11.date=20150317 +holiday.ga-IE11.date=20160317 holiday.ga-IE12.name=Luan Cásca -holiday.ga-IE12.date=20150406 +holiday.ga-IE12.date=20160328 holiday.ga-IE13.name=Lá an Lucht Oibre -holiday.ga-IE13.date=20150504 +holiday.ga-IE13.date=20160502 holiday.ga-IE14.name=Lá Saoire i mí Mheitheamh -holiday.ga-IE14.date=20150601 +holiday.ga-IE14.date=20160606 holiday.ga-IE15.name=Lá Saoire i mí Lúnasa -holiday.ga-IE15.date=20150803 +holiday.ga-IE15.date=20160801 holiday.ga-IE16.name=Lá Saoire i mí Dheireadh Fómhair -holiday.ga-IE16.date=20151026 +holiday.ga-IE16.date=20161031 holiday.ga-IE17.name=Lá Nollag -holiday.ga-IE17.date=20151225 +holiday.ga-IE17.date=20161225 holiday.ga-IE18.name=Lá Fhéile Stiofáin or Lá an Dreoilín -holiday.ga-IE18.date=20151226 -holiday.ga-IE19.name=Lá Caille or Lá Bliana Nua -holiday.ga-IE19.date=20160101 -holiday.ga-IE20.name=Lá Fhéile Pádraig -holiday.ga-IE20.date=20160317 -holiday.ga-IE21.name=Luan Cásca -holiday.ga-IE21.date=20160328 -holiday.ga-IE22.name=Lá an Lucht Oibre -holiday.ga-IE22.date=20160502 -holiday.ga-IE23.name=Lá Saoire i mí Mheitheamh -holiday.ga-IE23.date=20160606 -holiday.ga-IE24.name=Lá Saoire i mí Lúnasa -holiday.ga-IE24.date=20160801 -holiday.ga-IE25.name=Lá Saoire i mí Dheireadh Fómhair -holiday.ga-IE25.date=20161031 -holiday.ga-IE26.name=Lá Nollag -holiday.ga-IE26.date=20161225 -holiday.ga-IE27.name=Lá Fhéile Stiofáin or Lá an Dreoilín -holiday.ga-IE27.date=20161226 +holiday.ga-IE18.date=20161226 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.hr-HR.rc task-2.5.0+dfsg/doc/rc/holidays.hr-HR.rc --- task-2.4.4+dfsg/doc/rc/holidays.hr-HR.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.hr-HR.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/hr-HR/2014.json # http://holidata.net/hr-HR/2015.json +# http://holidata.net/hr-HR/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,86 +28,58 @@ ############################################################################### holiday.hr-HR1.name=Nova Godina -holiday.hr-HR1.date=20140101 +holiday.hr-HR1.date=20150101 holiday.hr-HR2.name=Bogojavljenje -holiday.hr-HR2.date=20140106 +holiday.hr-HR2.date=20150106 holiday.hr-HR3.name=Uskrs -holiday.hr-HR3.date=20140420 +holiday.hr-HR3.date=20150405 holiday.hr-HR4.name=Uskrsni ponedjeljak -holiday.hr-HR4.date=20140421 +holiday.hr-HR4.date=20150406 holiday.hr-HR5.name=Međunarodni praznik rada -holiday.hr-HR5.date=20140501 +holiday.hr-HR5.date=20150501 holiday.hr-HR6.name=Tijelovo -holiday.hr-HR6.date=20140619 +holiday.hr-HR6.date=20150604 holiday.hr-HR7.name=Dan antifašističke borbe -holiday.hr-HR7.date=20140622 +holiday.hr-HR7.date=20150622 holiday.hr-HR8.name=Dan državnosti -holiday.hr-HR8.date=20140625 +holiday.hr-HR8.date=20150625 holiday.hr-HR9.name=Dan pobjede -holiday.hr-HR9.date=20140805 +holiday.hr-HR9.date=20150805 holiday.hr-HR10.name=Velika Gospa -holiday.hr-HR10.date=20140815 +holiday.hr-HR10.date=20150815 holiday.hr-HR11.name=Dan neovisnosti -holiday.hr-HR11.date=20141008 +holiday.hr-HR11.date=20151008 holiday.hr-HR12.name=Dan svih svetih -holiday.hr-HR12.date=20141101 +holiday.hr-HR12.date=20151101 holiday.hr-HR13.name=Božić -holiday.hr-HR13.date=20141225 +holiday.hr-HR13.date=20151225 holiday.hr-HR14.name=Prvi dan po Božiću -holiday.hr-HR14.date=20141226 +holiday.hr-HR14.date=20151226 holiday.hr-HR15.name=Nova Godina -holiday.hr-HR15.date=20150101 +holiday.hr-HR15.date=20160101 holiday.hr-HR16.name=Bogojavljenje -holiday.hr-HR16.date=20150106 +holiday.hr-HR16.date=20160106 holiday.hr-HR17.name=Uskrs -holiday.hr-HR17.date=20150405 +holiday.hr-HR17.date=20160327 holiday.hr-HR18.name=Uskrsni ponedjeljak -holiday.hr-HR18.date=20150406 +holiday.hr-HR18.date=20160328 holiday.hr-HR19.name=Međunarodni praznik rada -holiday.hr-HR19.date=20150501 +holiday.hr-HR19.date=20160501 holiday.hr-HR20.name=Tijelovo -holiday.hr-HR20.date=20150604 +holiday.hr-HR20.date=20160526 holiday.hr-HR21.name=Dan antifašističke borbe -holiday.hr-HR21.date=20150622 +holiday.hr-HR21.date=20160622 holiday.hr-HR22.name=Dan državnosti -holiday.hr-HR22.date=20150625 +holiday.hr-HR22.date=20160625 holiday.hr-HR23.name=Dan pobjede -holiday.hr-HR23.date=20150805 +holiday.hr-HR23.date=20160805 holiday.hr-HR24.name=Velika Gospa -holiday.hr-HR24.date=20150815 +holiday.hr-HR24.date=20160815 holiday.hr-HR25.name=Dan neovisnosti -holiday.hr-HR25.date=20151008 +holiday.hr-HR25.date=20161008 holiday.hr-HR26.name=Dan svih svetih -holiday.hr-HR26.date=20151101 +holiday.hr-HR26.date=20161101 holiday.hr-HR27.name=Božić -holiday.hr-HR27.date=20151225 +holiday.hr-HR27.date=20161225 holiday.hr-HR28.name=Prvi dan po Božiću -holiday.hr-HR28.date=20151226 -holiday.hr-HR29.name=Nova Godina -holiday.hr-HR29.date=20160101 -holiday.hr-HR30.name=Bogojavljenje -holiday.hr-HR30.date=20160106 -holiday.hr-HR31.name=Uskrs -holiday.hr-HR31.date=20160327 -holiday.hr-HR32.name=Uskrsni ponedjeljak -holiday.hr-HR32.date=20160328 -holiday.hr-HR33.name=Međunarodni praznik rada -holiday.hr-HR33.date=20160501 -holiday.hr-HR34.name=Tijelovo -holiday.hr-HR34.date=20160526 -holiday.hr-HR35.name=Dan antifašističke borbe -holiday.hr-HR35.date=20160622 -holiday.hr-HR36.name=Dan državnosti -holiday.hr-HR36.date=20160625 -holiday.hr-HR37.name=Dan pobjede -holiday.hr-HR37.date=20160805 -holiday.hr-HR38.name=Velika Gospa -holiday.hr-HR38.date=20160815 -holiday.hr-HR39.name=Dan neovisnosti -holiday.hr-HR39.date=20161008 -holiday.hr-HR40.name=Dan svih svetih -holiday.hr-HR40.date=20161101 -holiday.hr-HR41.name=Božić -holiday.hr-HR41.date=20161225 -holiday.hr-HR42.name=Prvi dan po Božiću -holiday.hr-HR42.date=20161226 +holiday.hr-HR28.date=20161226 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.is-IS.rc task-2.5.0+dfsg/doc/rc/holidays.is-IS.rc --- task-2.4.4+dfsg/doc/rc/holidays.is-IS.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.is-IS.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/is-IS/2014.json # http://holidata.net/is-IS/2015.json +# http://holidata.net/is-IS/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,92 +28,62 @@ ############################################################################### holiday.is-IS1.name=Nýársdagur -holiday.is-IS1.date=20140101 +holiday.is-IS1.date=20150101 holiday.is-IS2.name=Skírdagur -holiday.is-IS2.date=20140417 +holiday.is-IS2.date=20150402 holiday.is-IS3.name=Föstudaginn langi -holiday.is-IS3.date=20140418 +holiday.is-IS3.date=20150403 holiday.is-IS4.name=Páskadagur -holiday.is-IS4.date=20140420 +holiday.is-IS4.date=20150405 holiday.is-IS5.name=Annar í páskum -holiday.is-IS5.date=20140421 +holiday.is-IS5.date=20150406 holiday.is-IS6.name=Sumardagurinn fyrsti -holiday.is-IS6.date=20140424 +holiday.is-IS6.date=20150423 holiday.is-IS7.name=Verkalýðsdagurinn -holiday.is-IS7.date=20140501 +holiday.is-IS7.date=20150501 holiday.is-IS8.name=Uppstigningardagur -holiday.is-IS8.date=20140529 +holiday.is-IS8.date=20150514 holiday.is-IS9.name=Annar í hvítasunnu -holiday.is-IS9.date=20140609 +holiday.is-IS9.date=20150525 holiday.is-IS10.name=Lýðveldisdagurinn -holiday.is-IS10.date=20140617 +holiday.is-IS10.date=20150617 holiday.is-IS11.name=Frídagur verslunarmanna -holiday.is-IS11.date=20140804 +holiday.is-IS11.date=20150803 holiday.is-IS12.name=Jól -holiday.is-IS12.date=20141224 +holiday.is-IS12.date=20151224 holiday.is-IS13.name=Jól -holiday.is-IS13.date=20141225 +holiday.is-IS13.date=20151225 holiday.is-IS14.name=Jól -holiday.is-IS14.date=20141226 +holiday.is-IS14.date=20151226 holiday.is-IS15.name=Gamlárskvöld -holiday.is-IS15.date=20141231 +holiday.is-IS15.date=20151231 holiday.is-IS16.name=Nýársdagur -holiday.is-IS16.date=20150101 +holiday.is-IS16.date=20160101 holiday.is-IS17.name=Skírdagur -holiday.is-IS17.date=20150402 +holiday.is-IS17.date=20160324 holiday.is-IS18.name=Föstudaginn langi -holiday.is-IS18.date=20150403 +holiday.is-IS18.date=20160325 holiday.is-IS19.name=Páskadagur -holiday.is-IS19.date=20150405 +holiday.is-IS19.date=20160327 holiday.is-IS20.name=Annar í páskum -holiday.is-IS20.date=20150406 +holiday.is-IS20.date=20160328 holiday.is-IS21.name=Sumardagurinn fyrsti -holiday.is-IS21.date=20150423 +holiday.is-IS21.date=20160421 holiday.is-IS22.name=Verkalýðsdagurinn -holiday.is-IS22.date=20150501 +holiday.is-IS22.date=20160501 holiday.is-IS23.name=Uppstigningardagur -holiday.is-IS23.date=20150514 +holiday.is-IS23.date=20160505 holiday.is-IS24.name=Annar í hvítasunnu -holiday.is-IS24.date=20150525 +holiday.is-IS24.date=20160516 holiday.is-IS25.name=Lýðveldisdagurinn -holiday.is-IS25.date=20150617 +holiday.is-IS25.date=20160617 holiday.is-IS26.name=Frídagur verslunarmanna -holiday.is-IS26.date=20150803 +holiday.is-IS26.date=20160801 holiday.is-IS27.name=Jól -holiday.is-IS27.date=20151224 +holiday.is-IS27.date=20161224 holiday.is-IS28.name=Jól -holiday.is-IS28.date=20151225 +holiday.is-IS28.date=20161225 holiday.is-IS29.name=Jól -holiday.is-IS29.date=20151226 +holiday.is-IS29.date=20161226 holiday.is-IS30.name=Gamlárskvöld -holiday.is-IS30.date=20151231 -holiday.is-IS31.name=Nýársdagur -holiday.is-IS31.date=20160101 -holiday.is-IS32.name=Skírdagur -holiday.is-IS32.date=20160324 -holiday.is-IS33.name=Föstudaginn langi -holiday.is-IS33.date=20160325 -holiday.is-IS34.name=Páskadagur -holiday.is-IS34.date=20160327 -holiday.is-IS35.name=Annar í páskum -holiday.is-IS35.date=20160328 -holiday.is-IS36.name=Sumardagurinn fyrsti -holiday.is-IS36.date=20160421 -holiday.is-IS37.name=Verkalýðsdagurinn -holiday.is-IS37.date=20160501 -holiday.is-IS38.name=Uppstigningardagur -holiday.is-IS38.date=20160505 -holiday.is-IS39.name=Annar í hvítasunnu -holiday.is-IS39.date=20160516 -holiday.is-IS40.name=Lýðveldisdagurinn -holiday.is-IS40.date=20160617 -holiday.is-IS41.name=Frídagur verslunarmanna -holiday.is-IS41.date=20160801 -holiday.is-IS42.name=Jól -holiday.is-IS42.date=20161224 -holiday.is-IS43.name=Jól -holiday.is-IS43.date=20161225 -holiday.is-IS44.name=Jól -holiday.is-IS44.date=20161226 -holiday.is-IS45.name=Gamlárskvöld -holiday.is-IS45.date=20161231 +holiday.is-IS30.date=20161231 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.it-IT.rc task-2.5.0+dfsg/doc/rc/holidays.it-IT.rc --- task-2.4.4+dfsg/doc/rc/holidays.it-IT.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.it-IT.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/it-IT/2014.json # http://holidata.net/it-IT/2015.json +# http://holidata.net/it-IT/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,74 +28,50 @@ ############################################################################### holiday.it-IT1.name=Capodanno -holiday.it-IT1.date=20140101 +holiday.it-IT1.date=20150101 holiday.it-IT2.name=Epifania -holiday.it-IT2.date=20140106 +holiday.it-IT2.date=20150106 holiday.it-IT3.name=Carnevale -holiday.it-IT3.date=20140304 +holiday.it-IT3.date=20150217 holiday.it-IT4.name=Pasqua -holiday.it-IT4.date=20140420 +holiday.it-IT4.date=20150405 holiday.it-IT5.name=Festa della liberazione -holiday.it-IT5.date=20140425 +holiday.it-IT5.date=20150425 holiday.it-IT6.name=Festa del lavoro -holiday.it-IT6.date=20140501 +holiday.it-IT6.date=20150501 holiday.it-IT7.name=Festa della repubblica -holiday.it-IT7.date=20140602 +holiday.it-IT7.date=20150602 holiday.it-IT8.name=Assunzione (ferragosto) -holiday.it-IT8.date=20140815 +holiday.it-IT8.date=20150815 holiday.it-IT9.name=Ognissanti -holiday.it-IT9.date=20141101 +holiday.it-IT9.date=20151101 holiday.it-IT10.name=Immacolata concezione -holiday.it-IT10.date=20141208 +holiday.it-IT10.date=20151208 holiday.it-IT11.name=Natale -holiday.it-IT11.date=20141225 +holiday.it-IT11.date=20151225 holiday.it-IT12.name=S.to Stefano -holiday.it-IT12.date=20141226 +holiday.it-IT12.date=20151226 holiday.it-IT13.name=Capodanno -holiday.it-IT13.date=20150101 +holiday.it-IT13.date=20160101 holiday.it-IT14.name=Epifania -holiday.it-IT14.date=20150106 +holiday.it-IT14.date=20160106 holiday.it-IT15.name=Carnevale -holiday.it-IT15.date=20150217 +holiday.it-IT15.date=20160209 holiday.it-IT16.name=Pasqua -holiday.it-IT16.date=20150405 +holiday.it-IT16.date=20160327 holiday.it-IT17.name=Festa della liberazione -holiday.it-IT17.date=20150425 +holiday.it-IT17.date=20160425 holiday.it-IT18.name=Festa del lavoro -holiday.it-IT18.date=20150501 +holiday.it-IT18.date=20160501 holiday.it-IT19.name=Festa della repubblica -holiday.it-IT19.date=20150602 +holiday.it-IT19.date=20160602 holiday.it-IT20.name=Assunzione (ferragosto) -holiday.it-IT20.date=20150815 +holiday.it-IT20.date=20160815 holiday.it-IT21.name=Ognissanti -holiday.it-IT21.date=20151101 +holiday.it-IT21.date=20161101 holiday.it-IT22.name=Immacolata concezione -holiday.it-IT22.date=20151208 +holiday.it-IT22.date=20161208 holiday.it-IT23.name=Natale -holiday.it-IT23.date=20151225 +holiday.it-IT23.date=20161225 holiday.it-IT24.name=S.to Stefano -holiday.it-IT24.date=20151226 -holiday.it-IT25.name=Capodanno -holiday.it-IT25.date=20160101 -holiday.it-IT26.name=Epifania -holiday.it-IT26.date=20160106 -holiday.it-IT27.name=Carnevale -holiday.it-IT27.date=20160209 -holiday.it-IT28.name=Pasqua -holiday.it-IT28.date=20160327 -holiday.it-IT29.name=Festa della liberazione -holiday.it-IT29.date=20160425 -holiday.it-IT30.name=Festa del lavoro -holiday.it-IT30.date=20160501 -holiday.it-IT31.name=Festa della repubblica -holiday.it-IT31.date=20160602 -holiday.it-IT32.name=Assunzione (ferragosto) -holiday.it-IT32.date=20160815 -holiday.it-IT33.name=Ognissanti -holiday.it-IT33.date=20161101 -holiday.it-IT34.name=Immacolata concezione -holiday.it-IT34.date=20161208 -holiday.it-IT35.name=Natale -holiday.it-IT35.date=20161225 -holiday.it-IT36.name=S.to Stefano -holiday.it-IT36.date=20161226 +holiday.it-IT24.date=20161226 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.jp-JP.rc task-2.5.0+dfsg/doc/rc/holidays.jp-JP.rc --- task-2.4.4+dfsg/doc/rc/holidays.jp-JP.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.jp-JP.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/jp-JP/2014.json # http://holidata.net/jp-JP/2015.json +# http://holidata.net/jp-JP/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,96 +28,64 @@ ############################################################################### holiday.jp-JP1.name=元日 -holiday.jp-JP1.date=20140101 +holiday.jp-JP1.date=20150101 holiday.jp-JP2.name=成人の日 -holiday.jp-JP2.date=20140113 +holiday.jp-JP2.date=20150112 holiday.jp-JP3.name=建国記念の日 -holiday.jp-JP3.date=20140211 +holiday.jp-JP3.date=20150211 holiday.jp-JP4.name=春分の日 -holiday.jp-JP4.date=20140321 +holiday.jp-JP4.date=20150321 holiday.jp-JP5.name=昭和の日 -holiday.jp-JP5.date=20140429 +holiday.jp-JP5.date=20150429 holiday.jp-JP6.name=憲法記念日 -holiday.jp-JP6.date=20140503 +holiday.jp-JP6.date=20150503 holiday.jp-JP7.name=みどりの日 -holiday.jp-JP7.date=20140504 +holiday.jp-JP7.date=20150504 holiday.jp-JP8.name=こどもの日 -holiday.jp-JP8.date=20140505 +holiday.jp-JP8.date=20150505 holiday.jp-JP9.name=振替休日 -holiday.jp-JP9.date=20140506 +holiday.jp-JP9.date=20150506 holiday.jp-JP10.name=海の日 -holiday.jp-JP10.date=20140721 +holiday.jp-JP10.date=20150720 holiday.jp-JP11.name=敬老の日 -holiday.jp-JP11.date=20140915 +holiday.jp-JP11.date=20150921 holiday.jp-JP12.name=秋分の日 -holiday.jp-JP12.date=20140923 +holiday.jp-JP12.date=20150923 holiday.jp-JP13.name=体育の日 -holiday.jp-JP13.date=20141013 +holiday.jp-JP13.date=20151012 holiday.jp-JP14.name=文化の日 -holiday.jp-JP14.date=20141103 +holiday.jp-JP14.date=20151103 holiday.jp-JP15.name=勤労感謝の日 -holiday.jp-JP15.date=20141124 +holiday.jp-JP15.date=20151123 holiday.jp-JP16.name=天皇誕生日 -holiday.jp-JP16.date=20141223 +holiday.jp-JP16.date=20151223 holiday.jp-JP17.name=元日 -holiday.jp-JP17.date=20150101 +holiday.jp-JP17.date=20160101 holiday.jp-JP18.name=成人の日 -holiday.jp-JP18.date=20150112 +holiday.jp-JP18.date=20160111 holiday.jp-JP19.name=建国記念の日 -holiday.jp-JP19.date=20150211 +holiday.jp-JP19.date=20160211 holiday.jp-JP20.name=春分の日 -holiday.jp-JP20.date=20150321 +holiday.jp-JP20.date=20160321 holiday.jp-JP21.name=昭和の日 -holiday.jp-JP21.date=20150429 +holiday.jp-JP21.date=20160429 holiday.jp-JP22.name=憲法記念日 -holiday.jp-JP22.date=20150503 +holiday.jp-JP22.date=20160503 holiday.jp-JP23.name=みどりの日 -holiday.jp-JP23.date=20150504 +holiday.jp-JP23.date=20160504 holiday.jp-JP24.name=こどもの日 -holiday.jp-JP24.date=20150505 -holiday.jp-JP25.name=振替休日 -holiday.jp-JP25.date=20150506 -holiday.jp-JP26.name=海の日 -holiday.jp-JP26.date=20150720 -holiday.jp-JP27.name=敬老の日 -holiday.jp-JP27.date=20150921 -holiday.jp-JP28.name=秋分の日 -holiday.jp-JP28.date=20150923 -holiday.jp-JP29.name=体育の日 -holiday.jp-JP29.date=20151012 -holiday.jp-JP30.name=文化の日 -holiday.jp-JP30.date=20151103 -holiday.jp-JP31.name=勤労感謝の日 -holiday.jp-JP31.date=20151123 -holiday.jp-JP32.name=天皇誕生日 -holiday.jp-JP32.date=20151223 -holiday.jp-JP33.name=元日 -holiday.jp-JP33.date=20160101 -holiday.jp-JP34.name=成人の日 -holiday.jp-JP34.date=20160111 -holiday.jp-JP35.name=建国記念の日 -holiday.jp-JP35.date=20160211 -holiday.jp-JP36.name=春分の日 -holiday.jp-JP36.date=20160321 -holiday.jp-JP37.name=昭和の日 -holiday.jp-JP37.date=20160429 -holiday.jp-JP38.name=憲法記念日 -holiday.jp-JP38.date=20160503 -holiday.jp-JP39.name=みどりの日 -holiday.jp-JP39.date=20160504 -holiday.jp-JP40.name=こどもの日 -holiday.jp-JP40.date=20160505 -holiday.jp-JP41.name=海の日 -holiday.jp-JP41.date=20160718 -holiday.jp-JP42.name=敬老の日 -holiday.jp-JP42.date=20160919 -holiday.jp-JP43.name=秋分の日 -holiday.jp-JP43.date=20160922 -holiday.jp-JP44.name=体育の日 -holiday.jp-JP44.date=20161010 -holiday.jp-JP45.name=文化の日 -holiday.jp-JP45.date=20161103 -holiday.jp-JP46.name=勤労感謝の日 -holiday.jp-JP46.date=20161123 -holiday.jp-JP47.name=天皇誕生日 -holiday.jp-JP47.date=20161223 +holiday.jp-JP24.date=20160505 +holiday.jp-JP25.name=海の日 +holiday.jp-JP25.date=20160718 +holiday.jp-JP26.name=敬老の日 +holiday.jp-JP26.date=20160919 +holiday.jp-JP27.name=秋分の日 +holiday.jp-JP27.date=20160922 +holiday.jp-JP28.name=体育の日 +holiday.jp-JP28.date=20161010 +holiday.jp-JP29.name=文化の日 +holiday.jp-JP29.date=20161103 +holiday.jp-JP30.name=勤労感謝の日 +holiday.jp-JP30.date=20161123 +holiday.jp-JP31.name=天皇誕生日 +holiday.jp-JP31.date=20161223 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.lt-LT.rc task-2.5.0+dfsg/doc/rc/holidays.lt-LT.rc --- task-2.4.4+dfsg/doc/rc/holidays.lt-LT.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.lt-LT.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/lt-LT/2014.json # http://holidata.net/lt-LT/2015.json +# http://holidata.net/lt-LT/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,80 +28,54 @@ ############################################################################### holiday.lt-LT1.name=Naujieji metai -holiday.lt-LT1.date=20140101 +holiday.lt-LT1.date=20150101 holiday.lt-LT2.name=Lietuvos valstybės atkūrimo diena -holiday.lt-LT2.date=20140216 +holiday.lt-LT2.date=20150216 holiday.lt-LT3.name=Lietuvos nepriklausomybės atkūrimo diena -holiday.lt-LT3.date=20140311 +holiday.lt-LT3.date=20150311 holiday.lt-LT4.name=Velykos -holiday.lt-LT4.date=20140420 +holiday.lt-LT4.date=20150405 holiday.lt-LT5.name=Velykos -holiday.lt-LT5.date=20140421 +holiday.lt-LT5.date=20150406 holiday.lt-LT6.name=Tarptautinė darbo diena -holiday.lt-LT6.date=20140501 +holiday.lt-LT6.date=20150501 holiday.lt-LT7.name=Joninės, Rasos -holiday.lt-LT7.date=20140624 +holiday.lt-LT7.date=20150624 holiday.lt-LT8.name=Valstybės diena -holiday.lt-LT8.date=20140706 +holiday.lt-LT8.date=20150706 holiday.lt-LT9.name=Žolinė -holiday.lt-LT9.date=20140815 +holiday.lt-LT9.date=20150815 holiday.lt-LT10.name=Visų šventųjų diena -holiday.lt-LT10.date=20142101 +holiday.lt-LT10.date=20152101 holiday.lt-LT11.name=Šv. Kalėdos -holiday.lt-LT11.date=20141224 +holiday.lt-LT11.date=20151224 holiday.lt-LT12.name=Šv. Kalėdos -holiday.lt-LT12.date=20141225 +holiday.lt-LT12.date=20151225 holiday.lt-LT13.name=Šv. Kalėdos -holiday.lt-LT13.date=20141226 +holiday.lt-LT13.date=20151226 holiday.lt-LT14.name=Naujieji metai -holiday.lt-LT14.date=20150101 +holiday.lt-LT14.date=20160101 holiday.lt-LT15.name=Lietuvos valstybės atkūrimo diena -holiday.lt-LT15.date=20150216 +holiday.lt-LT15.date=20160216 holiday.lt-LT16.name=Lietuvos nepriklausomybės atkūrimo diena -holiday.lt-LT16.date=20150311 +holiday.lt-LT16.date=20160311 holiday.lt-LT17.name=Velykos -holiday.lt-LT17.date=20150405 +holiday.lt-LT17.date=20160327 holiday.lt-LT18.name=Velykos -holiday.lt-LT18.date=20150406 +holiday.lt-LT18.date=20160328 holiday.lt-LT19.name=Tarptautinė darbo diena -holiday.lt-LT19.date=20150501 +holiday.lt-LT19.date=20160501 holiday.lt-LT20.name=Joninės, Rasos -holiday.lt-LT20.date=20150624 +holiday.lt-LT20.date=20160624 holiday.lt-LT21.name=Valstybės diena -holiday.lt-LT21.date=20150706 +holiday.lt-LT21.date=20160706 holiday.lt-LT22.name=Žolinė -holiday.lt-LT22.date=20150815 +holiday.lt-LT22.date=20160815 holiday.lt-LT23.name=Visų šventųjų diena -holiday.lt-LT23.date=20152101 +holiday.lt-LT23.date=20162101 holiday.lt-LT24.name=Šv. Kalėdos -holiday.lt-LT24.date=20151224 +holiday.lt-LT24.date=20161224 holiday.lt-LT25.name=Šv. Kalėdos -holiday.lt-LT25.date=20151225 +holiday.lt-LT25.date=20161225 holiday.lt-LT26.name=Šv. Kalėdos -holiday.lt-LT26.date=20151226 -holiday.lt-LT27.name=Naujieji metai -holiday.lt-LT27.date=20160101 -holiday.lt-LT28.name=Lietuvos valstybės atkūrimo diena -holiday.lt-LT28.date=20160216 -holiday.lt-LT29.name=Lietuvos nepriklausomybės atkūrimo diena -holiday.lt-LT29.date=20160311 -holiday.lt-LT30.name=Velykos -holiday.lt-LT30.date=20160327 -holiday.lt-LT31.name=Velykos -holiday.lt-LT31.date=20160328 -holiday.lt-LT32.name=Tarptautinė darbo diena -holiday.lt-LT32.date=20160501 -holiday.lt-LT33.name=Joninės, Rasos -holiday.lt-LT33.date=20160624 -holiday.lt-LT34.name=Valstybės diena -holiday.lt-LT34.date=20160706 -holiday.lt-LT35.name=Žolinė -holiday.lt-LT35.date=20160815 -holiday.lt-LT36.name=Visų šventųjų diena -holiday.lt-LT36.date=20162101 -holiday.lt-LT37.name=Šv. Kalėdos -holiday.lt-LT37.date=20161224 -holiday.lt-LT38.name=Šv. Kalėdos -holiday.lt-LT38.date=20161225 -holiday.lt-LT39.name=Šv. Kalėdos -holiday.lt-LT39.date=20161226 +holiday.lt-LT26.date=20161226 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.lv-LV.rc task-2.5.0+dfsg/doc/rc/holidays.lv-LV.rc --- task-2.4.4+dfsg/doc/rc/holidays.lv-LV.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.lv-LV.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/lv-LV/2014.json # http://holidata.net/lv-LV/2015.json +# http://holidata.net/lv-LV/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,74 +28,50 @@ ############################################################################### holiday.lv-LV1.name=Jaunais Gads -holiday.lv-LV1.date=20140101 +holiday.lv-LV1.date=20150101 holiday.lv-LV2.name=Lielā Piektdiena -holiday.lv-LV2.date=20140418 +holiday.lv-LV2.date=20150403 holiday.lv-LV3.name=Lieldienas -holiday.lv-LV3.date=20140420 +holiday.lv-LV3.date=20150405 holiday.lv-LV4.name=2. Lieldienas -holiday.lv-LV4.date=20140421 +holiday.lv-LV4.date=20150406 holiday.lv-LV5.name=Darba svētki -holiday.lv-LV5.date=20140501 +holiday.lv-LV5.date=20150501 holiday.lv-LV6.name=Latvijas Republikas Neatkarības atjaunošanas dienu -holiday.lv-LV6.date=20140505 +holiday.lv-LV6.date=20150505 holiday.lv-LV7.name=Jāņi -holiday.lv-LV7.date=20140624 +holiday.lv-LV7.date=20150624 holiday.lv-LV8.name=Latvijas Republikas proklamēšanas diena -holiday.lv-LV8.date=20141118 +holiday.lv-LV8.date=20151118 holiday.lv-LV9.name=Ziemassvētku vakars -holiday.lv-LV9.date=20141224 +holiday.lv-LV9.date=20151224 holiday.lv-LV10.name=Ziemassvētki -holiday.lv-LV10.date=20141225 +holiday.lv-LV10.date=20151225 holiday.lv-LV11.name=2. Ziemassvētki -holiday.lv-LV11.date=20141226 +holiday.lv-LV11.date=20151226 holiday.lv-LV12.name=Vecgada vakars -holiday.lv-LV12.date=20141231 +holiday.lv-LV12.date=20151231 holiday.lv-LV13.name=Jaunais Gads -holiday.lv-LV13.date=20150101 +holiday.lv-LV13.date=20160101 holiday.lv-LV14.name=Lielā Piektdiena -holiday.lv-LV14.date=20150403 +holiday.lv-LV14.date=20160325 holiday.lv-LV15.name=Lieldienas -holiday.lv-LV15.date=20150405 +holiday.lv-LV15.date=20160327 holiday.lv-LV16.name=2. Lieldienas -holiday.lv-LV16.date=20150406 +holiday.lv-LV16.date=20160327 holiday.lv-LV17.name=Darba svētki -holiday.lv-LV17.date=20150501 +holiday.lv-LV17.date=20160501 holiday.lv-LV18.name=Latvijas Republikas Neatkarības atjaunošanas dienu -holiday.lv-LV18.date=20150505 +holiday.lv-LV18.date=20160505 holiday.lv-LV19.name=Jāņi -holiday.lv-LV19.date=20150624 +holiday.lv-LV19.date=20160624 holiday.lv-LV20.name=Latvijas Republikas proklamēšanas diena -holiday.lv-LV20.date=20151118 +holiday.lv-LV20.date=20161118 holiday.lv-LV21.name=Ziemassvētku vakars -holiday.lv-LV21.date=20151224 +holiday.lv-LV21.date=20161224 holiday.lv-LV22.name=Ziemassvētki -holiday.lv-LV22.date=20151225 +holiday.lv-LV22.date=20161225 holiday.lv-LV23.name=2. Ziemassvētki -holiday.lv-LV23.date=20151226 +holiday.lv-LV23.date=20161226 holiday.lv-LV24.name=Vecgada vakars -holiday.lv-LV24.date=20151231 -holiday.lv-LV25.name=Jaunais Gads -holiday.lv-LV25.date=20160101 -holiday.lv-LV26.name=Lielā Piektdiena -holiday.lv-LV26.date=20160325 -holiday.lv-LV27.name=Lieldienas -holiday.lv-LV27.date=20160327 -holiday.lv-LV28.name=2. Lieldienas -holiday.lv-LV28.date=20160327 -holiday.lv-LV29.name=Darba svētki -holiday.lv-LV29.date=20160501 -holiday.lv-LV30.name=Latvijas Republikas Neatkarības atjaunošanas dienu -holiday.lv-LV30.date=20160505 -holiday.lv-LV31.name=Jāņi -holiday.lv-LV31.date=20160624 -holiday.lv-LV32.name=Latvijas Republikas proklamēšanas diena -holiday.lv-LV32.date=20161118 -holiday.lv-LV33.name=Ziemassvētku vakars -holiday.lv-LV33.date=20161224 -holiday.lv-LV34.name=Ziemassvētki -holiday.lv-LV34.date=20161225 -holiday.lv-LV35.name=2. Ziemassvētki -holiday.lv-LV35.date=20161226 -holiday.lv-LV36.name=Vecgada vakars -holiday.lv-LV36.date=20161231 +holiday.lv-LV24.date=20161231 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.nb-NO.rc task-2.5.0+dfsg/doc/rc/holidays.nb-NO.rc --- task-2.4.4+dfsg/doc/rc/holidays.nb-NO.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.nb-NO.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/nb-NO/2014.json # http://holidata.net/nb-NO/2015.json +# http://holidata.net/nb-NO/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,104 +28,70 @@ ############################################################################### holiday.nb-NO1.name=Nyttårsdag -holiday.nb-NO1.date=20140101 +holiday.nb-NO1.date=20150101 holiday.nb-NO2.name=Fastelavn -holiday.nb-NO2.date=20140302 +holiday.nb-NO2.date=20150215 holiday.nb-NO3.name=Palmesøndag -holiday.nb-NO3.date=20140413 +holiday.nb-NO3.date=20150329 holiday.nb-NO4.name=Skjærtorsdag -holiday.nb-NO4.date=20140417 +holiday.nb-NO4.date=20150402 holiday.nb-NO5.name=Langfredag -holiday.nb-NO5.date=20140418 +holiday.nb-NO5.date=20150403 holiday.nb-NO6.name=Påskedag -holiday.nb-NO6.date=20140420 +holiday.nb-NO6.date=20150405 holiday.nb-NO7.name=Påskedag -holiday.nb-NO7.date=20140421 +holiday.nb-NO7.date=20150406 holiday.nb-NO8.name=Offentlig Høytidsdag -holiday.nb-NO8.date=20140501 +holiday.nb-NO8.date=20150501 holiday.nb-NO9.name=Frigjøringsdag 1945 -holiday.nb-NO9.date=20140508 +holiday.nb-NO9.date=20150508 holiday.nb-NO10.name=Grunnlovsdag -holiday.nb-NO10.date=20140517 +holiday.nb-NO10.date=20150517 holiday.nb-NO11.name=Kristi Himmelfartsdag -holiday.nb-NO11.date=20140529 +holiday.nb-NO11.date=20150514 holiday.nb-NO12.name=Pinsedag -holiday.nb-NO12.date=20140608 +holiday.nb-NO12.date=20150524 holiday.nb-NO13.name=Pinsedag -holiday.nb-NO13.date=20140609 +holiday.nb-NO13.date=20150525 holiday.nb-NO14.name=Julaften -holiday.nb-NO14.date=20141224 +holiday.nb-NO14.date=20151224 holiday.nb-NO15.name=Juledag -holiday.nb-NO15.date=20141225 +holiday.nb-NO15.date=20151225 holiday.nb-NO16.name=Juledag -holiday.nb-NO16.date=20141226 +holiday.nb-NO16.date=20151226 holiday.nb-NO17.name=Nyttårsaften -holiday.nb-NO17.date=20141231 +holiday.nb-NO17.date=20151231 holiday.nb-NO18.name=Nyttårsdag -holiday.nb-NO18.date=20150101 +holiday.nb-NO18.date=20160101 holiday.nb-NO19.name=Fastelavn -holiday.nb-NO19.date=20150215 +holiday.nb-NO19.date=20160207 holiday.nb-NO20.name=Palmesøndag -holiday.nb-NO20.date=20150329 +holiday.nb-NO20.date=20160320 holiday.nb-NO21.name=Skjærtorsdag -holiday.nb-NO21.date=20150402 +holiday.nb-NO21.date=20160324 holiday.nb-NO22.name=Langfredag -holiday.nb-NO22.date=20150403 +holiday.nb-NO22.date=20160325 holiday.nb-NO23.name=Påskedag -holiday.nb-NO23.date=20150405 +holiday.nb-NO23.date=20160327 holiday.nb-NO24.name=Påskedag -holiday.nb-NO24.date=20150406 +holiday.nb-NO24.date=20160328 holiday.nb-NO25.name=Offentlig Høytidsdag -holiday.nb-NO25.date=20150501 +holiday.nb-NO25.date=20160501 holiday.nb-NO26.name=Frigjøringsdag 1945 -holiday.nb-NO26.date=20150508 +holiday.nb-NO26.date=20160508 holiday.nb-NO27.name=Grunnlovsdag -holiday.nb-NO27.date=20150517 +holiday.nb-NO27.date=20160517 holiday.nb-NO28.name=Kristi Himmelfartsdag -holiday.nb-NO28.date=20150514 +holiday.nb-NO28.date=20160505 holiday.nb-NO29.name=Pinsedag -holiday.nb-NO29.date=20150524 +holiday.nb-NO29.date=20160515 holiday.nb-NO30.name=Pinsedag -holiday.nb-NO30.date=20150525 +holiday.nb-NO30.date=20160516 holiday.nb-NO31.name=Julaften -holiday.nb-NO31.date=20151224 +holiday.nb-NO31.date=20161224 holiday.nb-NO32.name=Juledag -holiday.nb-NO32.date=20151225 +holiday.nb-NO32.date=20161225 holiday.nb-NO33.name=Juledag -holiday.nb-NO33.date=20151226 +holiday.nb-NO33.date=20161226 holiday.nb-NO34.name=Nyttårsaften -holiday.nb-NO34.date=20151231 -holiday.nb-NO35.name=Nyttårsdag -holiday.nb-NO35.date=20160101 -holiday.nb-NO36.name=Fastelavn -holiday.nb-NO36.date=20160207 -holiday.nb-NO37.name=Palmesøndag -holiday.nb-NO37.date=20160320 -holiday.nb-NO38.name=Skjærtorsdag -holiday.nb-NO38.date=20160324 -holiday.nb-NO39.name=Langfredag -holiday.nb-NO39.date=20160325 -holiday.nb-NO40.name=Påskedag -holiday.nb-NO40.date=20160327 -holiday.nb-NO41.name=Påskedag -holiday.nb-NO41.date=20160328 -holiday.nb-NO42.name=Offentlig Høytidsdag -holiday.nb-NO42.date=20160501 -holiday.nb-NO43.name=Frigjøringsdag 1945 -holiday.nb-NO43.date=20160508 -holiday.nb-NO44.name=Grunnlovsdag -holiday.nb-NO44.date=20160517 -holiday.nb-NO45.name=Kristi Himmelfartsdag -holiday.nb-NO45.date=20160505 -holiday.nb-NO46.name=Pinsedag -holiday.nb-NO46.date=20160515 -holiday.nb-NO47.name=Pinsedag -holiday.nb-NO47.date=20160516 -holiday.nb-NO48.name=Julaften -holiday.nb-NO48.date=20161224 -holiday.nb-NO49.name=Juledag -holiday.nb-NO49.date=20161225 -holiday.nb-NO50.name=Juledag -holiday.nb-NO50.date=20161226 -holiday.nb-NO51.name=Nyttårsaften -holiday.nb-NO51.date=20161231 +holiday.nb-NO34.date=20161231 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.nb-SJ.rc task-2.5.0+dfsg/doc/rc/holidays.nb-SJ.rc --- task-2.4.4+dfsg/doc/rc/holidays.nb-SJ.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.nb-SJ.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/nb-SJ/2014.json # http://holidata.net/nb-SJ/2015.json +# http://holidata.net/nb-SJ/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,104 +28,70 @@ ############################################################################### holiday.nb-SJ1.name=Nyttårsdag -holiday.nb-SJ1.date=20140101 +holiday.nb-SJ1.date=20150101 holiday.nb-SJ2.name=Fastelavn -holiday.nb-SJ2.date=20140302 +holiday.nb-SJ2.date=20150215 holiday.nb-SJ3.name=Palmesøndag -holiday.nb-SJ3.date=20140413 +holiday.nb-SJ3.date=20150329 holiday.nb-SJ4.name=Skjærtorsdag -holiday.nb-SJ4.date=20140417 +holiday.nb-SJ4.date=20150402 holiday.nb-SJ5.name=Langfredag -holiday.nb-SJ5.date=20140418 +holiday.nb-SJ5.date=20150403 holiday.nb-SJ6.name=Påskedag -holiday.nb-SJ6.date=20140420 +holiday.nb-SJ6.date=20150405 holiday.nb-SJ7.name=Påskedag -holiday.nb-SJ7.date=20140421 +holiday.nb-SJ7.date=20150406 holiday.nb-SJ8.name=Offentlig Høytidsdag -holiday.nb-SJ8.date=20140501 +holiday.nb-SJ8.date=20150501 holiday.nb-SJ9.name=Frigjøringsdag 1945 -holiday.nb-SJ9.date=20140508 +holiday.nb-SJ9.date=20150508 holiday.nb-SJ10.name=Grunnlovsdag -holiday.nb-SJ10.date=20140517 +holiday.nb-SJ10.date=20150517 holiday.nb-SJ11.name=Kristi Himmelfartsdag -holiday.nb-SJ11.date=20140529 +holiday.nb-SJ11.date=20150514 holiday.nb-SJ12.name=Pinsedag -holiday.nb-SJ12.date=20140608 +holiday.nb-SJ12.date=20150524 holiday.nb-SJ13.name=Pinsedag -holiday.nb-SJ13.date=20140609 +holiday.nb-SJ13.date=20150525 holiday.nb-SJ14.name=Julaften -holiday.nb-SJ14.date=20141224 +holiday.nb-SJ14.date=20151224 holiday.nb-SJ15.name=Juledag -holiday.nb-SJ15.date=20141225 +holiday.nb-SJ15.date=20151225 holiday.nb-SJ16.name=Juledag -holiday.nb-SJ16.date=20141226 +holiday.nb-SJ16.date=20151226 holiday.nb-SJ17.name=Nyttårsaften -holiday.nb-SJ17.date=20141231 +holiday.nb-SJ17.date=20151231 holiday.nb-SJ18.name=Nyttårsdag -holiday.nb-SJ18.date=20150101 +holiday.nb-SJ18.date=20160101 holiday.nb-SJ19.name=Fastelavn -holiday.nb-SJ19.date=20150215 +holiday.nb-SJ19.date=20160207 holiday.nb-SJ20.name=Palmesøndag -holiday.nb-SJ20.date=20150329 +holiday.nb-SJ20.date=20160320 holiday.nb-SJ21.name=Skjærtorsdag -holiday.nb-SJ21.date=20150402 +holiday.nb-SJ21.date=20160324 holiday.nb-SJ22.name=Langfredag -holiday.nb-SJ22.date=20150403 +holiday.nb-SJ22.date=20160325 holiday.nb-SJ23.name=Påskedag -holiday.nb-SJ23.date=20150405 +holiday.nb-SJ23.date=20160327 holiday.nb-SJ24.name=Påskedag -holiday.nb-SJ24.date=20150406 +holiday.nb-SJ24.date=20160328 holiday.nb-SJ25.name=Offentlig Høytidsdag -holiday.nb-SJ25.date=20150501 +holiday.nb-SJ25.date=20160501 holiday.nb-SJ26.name=Frigjøringsdag 1945 -holiday.nb-SJ26.date=20150508 +holiday.nb-SJ26.date=20160508 holiday.nb-SJ27.name=Grunnlovsdag -holiday.nb-SJ27.date=20150517 +holiday.nb-SJ27.date=20160517 holiday.nb-SJ28.name=Kristi Himmelfartsdag -holiday.nb-SJ28.date=20150514 +holiday.nb-SJ28.date=20160505 holiday.nb-SJ29.name=Pinsedag -holiday.nb-SJ29.date=20150524 +holiday.nb-SJ29.date=20160515 holiday.nb-SJ30.name=Pinsedag -holiday.nb-SJ30.date=20150525 +holiday.nb-SJ30.date=20160516 holiday.nb-SJ31.name=Julaften -holiday.nb-SJ31.date=20151224 +holiday.nb-SJ31.date=20161224 holiday.nb-SJ32.name=Juledag -holiday.nb-SJ32.date=20151225 +holiday.nb-SJ32.date=20161225 holiday.nb-SJ33.name=Juledag -holiday.nb-SJ33.date=20151226 +holiday.nb-SJ33.date=20161226 holiday.nb-SJ34.name=Nyttårsaften -holiday.nb-SJ34.date=20151231 -holiday.nb-SJ35.name=Nyttårsdag -holiday.nb-SJ35.date=20160101 -holiday.nb-SJ36.name=Fastelavn -holiday.nb-SJ36.date=20160207 -holiday.nb-SJ37.name=Palmesøndag -holiday.nb-SJ37.date=20160320 -holiday.nb-SJ38.name=Skjærtorsdag -holiday.nb-SJ38.date=20160324 -holiday.nb-SJ39.name=Langfredag -holiday.nb-SJ39.date=20160325 -holiday.nb-SJ40.name=Påskedag -holiday.nb-SJ40.date=20160327 -holiday.nb-SJ41.name=Påskedag -holiday.nb-SJ41.date=20160328 -holiday.nb-SJ42.name=Offentlig Høytidsdag -holiday.nb-SJ42.date=20160501 -holiday.nb-SJ43.name=Frigjøringsdag 1945 -holiday.nb-SJ43.date=20160508 -holiday.nb-SJ44.name=Grunnlovsdag -holiday.nb-SJ44.date=20160517 -holiday.nb-SJ45.name=Kristi Himmelfartsdag -holiday.nb-SJ45.date=20160505 -holiday.nb-SJ46.name=Pinsedag -holiday.nb-SJ46.date=20160515 -holiday.nb-SJ47.name=Pinsedag -holiday.nb-SJ47.date=20160516 -holiday.nb-SJ48.name=Julaften -holiday.nb-SJ48.date=20161224 -holiday.nb-SJ49.name=Juledag -holiday.nb-SJ49.date=20161225 -holiday.nb-SJ50.name=Juledag -holiday.nb-SJ50.date=20161226 -holiday.nb-SJ51.name=Nyttårsaften -holiday.nb-SJ51.date=20161231 +holiday.nb-SJ34.date=20161231 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.nl-BE.rc task-2.5.0+dfsg/doc/rc/holidays.nl-BE.rc --- task-2.4.4+dfsg/doc/rc/holidays.nl-BE.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.nl-BE.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/nl-BE/2014.json # http://holidata.net/nl-BE/2015.json +# http://holidata.net/nl-BE/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,74 +28,50 @@ ############################################################################### holiday.nl-BE1.name=Nieuwjaar -holiday.nl-BE1.date=20140101 +holiday.nl-BE1.date=20150101 holiday.nl-BE2.name=Pasen -holiday.nl-BE2.date=20140420 +holiday.nl-BE2.date=20150405 holiday.nl-BE3.name=Paasmaandag -holiday.nl-BE3.date=20140421 +holiday.nl-BE3.date=20150406 holiday.nl-BE4.name=Dag van de arbeid -holiday.nl-BE4.date=20140501 +holiday.nl-BE4.date=20150501 holiday.nl-BE5.name=Onze Lieve Heer hemelvaart -holiday.nl-BE5.date=20140529 +holiday.nl-BE5.date=20150514 holiday.nl-BE6.name=Pinksteren -holiday.nl-BE6.date=20140608 +holiday.nl-BE6.date=20150524 holiday.nl-BE7.name=Pinkstermaandag -holiday.nl-BE7.date=20140609 +holiday.nl-BE7.date=20150525 holiday.nl-BE8.name=Nationale feestdag -holiday.nl-BE8.date=20140721 +holiday.nl-BE8.date=20150721 holiday.nl-BE9.name=Onze Lieve Vrouw hemelvaart -holiday.nl-BE9.date=20140815 +holiday.nl-BE9.date=20150815 holiday.nl-BE10.name=Allerheiligen -holiday.nl-BE10.date=20141101 +holiday.nl-BE10.date=20151101 holiday.nl-BE11.name=Wapenstilstand -holiday.nl-BE11.date=20141111 +holiday.nl-BE11.date=20151111 holiday.nl-BE12.name=Kerstmis -holiday.nl-BE12.date=20141225 +holiday.nl-BE12.date=20151225 holiday.nl-BE13.name=Nieuwjaar -holiday.nl-BE13.date=20150101 +holiday.nl-BE13.date=20160101 holiday.nl-BE14.name=Pasen -holiday.nl-BE14.date=20150405 +holiday.nl-BE14.date=20160327 holiday.nl-BE15.name=Paasmaandag -holiday.nl-BE15.date=20150406 +holiday.nl-BE15.date=20160328 holiday.nl-BE16.name=Dag van de arbeid -holiday.nl-BE16.date=20150501 +holiday.nl-BE16.date=20160501 holiday.nl-BE17.name=Onze Lieve Heer hemelvaart -holiday.nl-BE17.date=20150514 +holiday.nl-BE17.date=20160505 holiday.nl-BE18.name=Pinksteren -holiday.nl-BE18.date=20150524 +holiday.nl-BE18.date=20160515 holiday.nl-BE19.name=Pinkstermaandag -holiday.nl-BE19.date=20150525 +holiday.nl-BE19.date=20160516 holiday.nl-BE20.name=Nationale feestdag -holiday.nl-BE20.date=20150721 +holiday.nl-BE20.date=20160721 holiday.nl-BE21.name=Onze Lieve Vrouw hemelvaart -holiday.nl-BE21.date=20150815 +holiday.nl-BE21.date=20160815 holiday.nl-BE22.name=Allerheiligen -holiday.nl-BE22.date=20151101 +holiday.nl-BE22.date=20161101 holiday.nl-BE23.name=Wapenstilstand -holiday.nl-BE23.date=20151111 +holiday.nl-BE23.date=20161111 holiday.nl-BE24.name=Kerstmis -holiday.nl-BE24.date=20151225 -holiday.nl-BE25.name=Nieuwjaar -holiday.nl-BE25.date=20160101 -holiday.nl-BE26.name=Pasen -holiday.nl-BE26.date=20160527 -holiday.nl-BE27.name=Paasmaandag -holiday.nl-BE27.date=20160528 -holiday.nl-BE28.name=Dag van de arbeid -holiday.nl-BE28.date=20160501 -holiday.nl-BE29.name=Onze Lieve Heer hemelvaart -holiday.nl-BE29.date=20160505 -holiday.nl-BE30.name=Pinksteren -holiday.nl-BE30.date=20160515 -holiday.nl-BE31.name=Pinkstermaandag -holiday.nl-BE31.date=20160516 -holiday.nl-BE32.name=Nationale feestdag -holiday.nl-BE32.date=20160721 -holiday.nl-BE33.name=Onze Lieve Vrouw hemelvaart -holiday.nl-BE33.date=20160815 -holiday.nl-BE34.name=Allerheiligen -holiday.nl-BE34.date=20161101 -holiday.nl-BE35.name=Wapenstilstand -holiday.nl-BE35.date=20161111 -holiday.nl-BE36.name=Kerstmis -holiday.nl-BE36.date=20161225 +holiday.nl-BE24.date=20161225 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.nl-NL.rc task-2.5.0+dfsg/doc/rc/holidays.nl-NL.rc --- task-2.4.4+dfsg/doc/rc/holidays.nl-NL.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.nl-NL.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/nl-NL/2014.json # http://holidata.net/nl-NL/2015.json +# http://holidata.net/nl-NL/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,78 +28,54 @@ ############################################################################### holiday.nl-NL1.name=Nieuwjaar -holiday.nl-NL1.date=20140101 +holiday.nl-NL1.date=20150101 holiday.nl-NL2.name=Goede Vrijdag -holiday.nl-NL2.date=20140418 +holiday.nl-NL2.date=20150403 holiday.nl-NL3.name=Pasen -holiday.nl-NL3.date=20140420 +holiday.nl-NL3.date=20150405 holiday.nl-NL4.name=Tweede Pasdag -holiday.nl-NL4.date=20140421 +holiday.nl-NL4.date=20150406 holiday.nl-NL5.name=Koninginnedag -holiday.nl-NL5.date=20140426 +holiday.nl-NL5.date=20150427 holiday.nl-NL6.name=Dodenherdenking -holiday.nl-NL6.date=20140504 -holiday.nl-NL7.name=Hemelvaartsdag -holiday.nl-NL7.date=20140529 -holiday.nl-NL8.name=Pinksteren -holiday.nl-NL8.date=20140608 -holiday.nl-NL9.name=Tweede Pinksterdag -holiday.nl-NL9.date=20140609 -holiday.nl-NL10.name=Sinterklaas -holiday.nl-NL10.date=20141205 -holiday.nl-NL11.name=Kerstmis -holiday.nl-NL11.date=20141225 -holiday.nl-NL12.name=Tweede Kerstdag -holiday.nl-NL12.date=20141226 -holiday.nl-NL13.name=Nieuwjaar -holiday.nl-NL13.date=20150101 -holiday.nl-NL14.name=Goede Vrijdag -holiday.nl-NL14.date=20150403 -holiday.nl-NL15.name=Pasen -holiday.nl-NL15.date=20150405 -holiday.nl-NL16.name=Tweede Pasdag -holiday.nl-NL16.date=20150406 -holiday.nl-NL17.name=Koninginnedag -holiday.nl-NL17.date=20150427 -holiday.nl-NL18.name=Dodenherdenking -holiday.nl-NL18.date=20150504 -holiday.nl-NL19.name=Bevrijdingsdag -holiday.nl-NL19.date=20150505 -holiday.nl-NL20.name=Hemelvaartsdag -holiday.nl-NL20.date=20150514 -holiday.nl-NL21.name=Pinksteren -holiday.nl-NL21.date=20150524 -holiday.nl-NL22.name=Tweede Pinksterdag -holiday.nl-NL22.date=20150525 -holiday.nl-NL23.name=Sinterklaas -holiday.nl-NL23.date=20151205 -holiday.nl-NL24.name=Kerstmis -holiday.nl-NL24.date=20151225 -holiday.nl-NL25.name=Tweede Kerstdag -holiday.nl-NL25.date=20151226 -holiday.nl-NL26.name=Nieuwjaar -holiday.nl-NL26.date=20160101 -holiday.nl-NL27.name=Goede Vrijdag -holiday.nl-NL27.date=20160325 -holiday.nl-NL28.name=Pasen -holiday.nl-NL28.date=20160327 -holiday.nl-NL29.name=Tweede Pasdag -holiday.nl-NL29.date=20160328 -holiday.nl-NL30.name=Koninginnedag -holiday.nl-NL30.date=20160427 -holiday.nl-NL31.name=Dodenherdenking -holiday.nl-NL31.date=20160504 -holiday.nl-NL32.name=Bevrijdingsdag -holiday.nl-NL32.date=20160505 -holiday.nl-NL33.name=Hemelvaartsdag -holiday.nl-NL33.date=20160505 -holiday.nl-NL34.name=Pinksteren -holiday.nl-NL34.date=20160515 -holiday.nl-NL35.name=Tweede Pinksterdag -holiday.nl-NL35.date=20160516 -holiday.nl-NL36.name=Sinterklaas -holiday.nl-NL36.date=20161205 -holiday.nl-NL37.name=Kerstmis -holiday.nl-NL37.date=20161225 -holiday.nl-NL38.name=Tweede Kerstdag -holiday.nl-NL38.date=20161226 +holiday.nl-NL6.date=20150504 +holiday.nl-NL7.name=Bevrijdingsdag +holiday.nl-NL7.date=20150505 +holiday.nl-NL8.name=Hemelvaartsdag +holiday.nl-NL8.date=20150514 +holiday.nl-NL9.name=Pinksteren +holiday.nl-NL9.date=20150524 +holiday.nl-NL10.name=Tweede Pinksterdag +holiday.nl-NL10.date=20150525 +holiday.nl-NL11.name=Sinterklaas +holiday.nl-NL11.date=20151205 +holiday.nl-NL12.name=Kerstmis +holiday.nl-NL12.date=20151225 +holiday.nl-NL13.name=Tweede Kerstdag +holiday.nl-NL13.date=20151226 +holiday.nl-NL14.name=Nieuwjaar +holiday.nl-NL14.date=20160101 +holiday.nl-NL15.name=Goede Vrijdag +holiday.nl-NL15.date=20160325 +holiday.nl-NL16.name=Pasen +holiday.nl-NL16.date=20160327 +holiday.nl-NL17.name=Tweede Pasdag +holiday.nl-NL17.date=20160328 +holiday.nl-NL18.name=Koninginnedag +holiday.nl-NL18.date=20160427 +holiday.nl-NL19.name=Dodenherdenking +holiday.nl-NL19.date=20160504 +holiday.nl-NL20.name=Bevrijdingsdag +holiday.nl-NL20.date=20160505 +holiday.nl-NL21.name=Hemelvaartsdag +holiday.nl-NL21.date=20160505 +holiday.nl-NL22.name=Pinksteren +holiday.nl-NL22.date=20160515 +holiday.nl-NL23.name=Tweede Pinksterdag +holiday.nl-NL23.date=20160516 +holiday.nl-NL24.name=Sinterklaas +holiday.nl-NL24.date=20161205 +holiday.nl-NL25.name=Kerstmis +holiday.nl-NL25.date=20161225 +holiday.nl-NL26.name=Tweede Kerstdag +holiday.nl-NL26.date=20161226 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.pl-PL.rc task-2.5.0+dfsg/doc/rc/holidays.pl-PL.rc --- task-2.4.4+dfsg/doc/rc/holidays.pl-PL.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.pl-PL.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/pl-PL/2014.json # http://holidata.net/pl-PL/2015.json +# http://holidata.net/pl-PL/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,86 +28,58 @@ ############################################################################### holiday.pl-PL1.name=Nowy Rok -holiday.pl-PL1.date=20140101 +holiday.pl-PL1.date=20150101 holiday.pl-PL2.name=Trzech Króli -holiday.pl-PL2.date=20140106 +holiday.pl-PL2.date=20150106 holiday.pl-PL3.name=Wielkanoc -holiday.pl-PL3.date=20140420 +holiday.pl-PL3.date=20150405 holiday.pl-PL4.name=Poniedziałek Wielkanocny -holiday.pl-PL4.date=20140421 +holiday.pl-PL4.date=20150406 holiday.pl-PL5.name=Święto Pracy -holiday.pl-PL5.date=20140501 +holiday.pl-PL5.date=20150501 holiday.pl-PL6.name=Święto Konstytucji Trzeciego Maja -holiday.pl-PL6.date=20140503 +holiday.pl-PL6.date=20150503 holiday.pl-PL7.name=Zielone Świątki -holiday.pl-PL7.date=20140608 +holiday.pl-PL7.date=20150524 holiday.pl-PL8.name=Boże Ciało -holiday.pl-PL8.date=20140619 +holiday.pl-PL8.date=20150604 holiday.pl-PL9.name=Święto Wojska Polskiego -holiday.pl-PL9.date=20140815 +holiday.pl-PL9.date=20150815 holiday.pl-PL10.name=Wniebowzięcia NMP -holiday.pl-PL10.date=20140815 +holiday.pl-PL10.date=20150815 holiday.pl-PL11.name=Wszystkich Świętych -holiday.pl-PL11.date=20141101 +holiday.pl-PL11.date=20151101 holiday.pl-PL12.name=Dzień Niepodległości -holiday.pl-PL12.date=20141111 +holiday.pl-PL12.date=20151111 holiday.pl-PL13.name=Boże Narodzenie (pierwszy dzień) -holiday.pl-PL13.date=20141225 +holiday.pl-PL13.date=20151225 holiday.pl-PL14.name=Boże Narodzenie (drugi dzień) -holiday.pl-PL14.date=20141226 +holiday.pl-PL14.date=20151226 holiday.pl-PL15.name=Nowy Rok -holiday.pl-PL15.date=20150101 +holiday.pl-PL15.date=20160101 holiday.pl-PL16.name=Trzech Króli -holiday.pl-PL16.date=20150106 +holiday.pl-PL16.date=20160106 holiday.pl-PL17.name=Wielkanoc -holiday.pl-PL17.date=20150405 +holiday.pl-PL17.date=20160327 holiday.pl-PL18.name=Poniedziałek Wielkanocny -holiday.pl-PL18.date=20150406 +holiday.pl-PL18.date=20160328 holiday.pl-PL19.name=Święto Pracy -holiday.pl-PL19.date=20150501 +holiday.pl-PL19.date=20160501 holiday.pl-PL20.name=Święto Konstytucji Trzeciego Maja -holiday.pl-PL20.date=20150503 +holiday.pl-PL20.date=20160503 holiday.pl-PL21.name=Zielone Świątki -holiday.pl-PL21.date=20150524 +holiday.pl-PL21.date=20160515 holiday.pl-PL22.name=Boże Ciało -holiday.pl-PL22.date=20150604 +holiday.pl-PL22.date=20160526 holiday.pl-PL23.name=Święto Wojska Polskiego -holiday.pl-PL23.date=20150815 +holiday.pl-PL23.date=20160815 holiday.pl-PL24.name=Wniebowzięcia NMP -holiday.pl-PL24.date=20150815 +holiday.pl-PL24.date=20160815 holiday.pl-PL25.name=Wszystkich Świętych -holiday.pl-PL25.date=20151101 +holiday.pl-PL25.date=20161101 holiday.pl-PL26.name=Dzień Niepodległości -holiday.pl-PL26.date=20151111 +holiday.pl-PL26.date=20161111 holiday.pl-PL27.name=Boże Narodzenie (pierwszy dzień) -holiday.pl-PL27.date=20151225 +holiday.pl-PL27.date=20161225 holiday.pl-PL28.name=Boże Narodzenie (drugi dzień) -holiday.pl-PL28.date=20151226 -holiday.pl-PL29.name=Nowy Rok -holiday.pl-PL29.date=20160101 -holiday.pl-PL30.name=Trzech Króli -holiday.pl-PL30.date=20160106 -holiday.pl-PL31.name=Wielkanoc -holiday.pl-PL31.date=20160327 -holiday.pl-PL32.name=Poniedziałek Wielkanocny -holiday.pl-PL32.date=20160328 -holiday.pl-PL33.name=Święto Pracy -holiday.pl-PL33.date=20160501 -holiday.pl-PL34.name=Święto Konstytucji Trzeciego Maja -holiday.pl-PL34.date=20160503 -holiday.pl-PL35.name=Zielone Świątki -holiday.pl-PL35.date=20160515 -holiday.pl-PL36.name=Boże Ciało -holiday.pl-PL36.date=20160526 -holiday.pl-PL37.name=Święto Wojska Polskiego -holiday.pl-PL37.date=20160815 -holiday.pl-PL38.name=Wniebowzięcia NMP -holiday.pl-PL38.date=20160815 -holiday.pl-PL39.name=Wszystkich Świętych -holiday.pl-PL39.date=20161101 -holiday.pl-PL40.name=Dzień Niepodległości -holiday.pl-PL40.date=20161111 -holiday.pl-PL41.name=Boże Narodzenie (pierwszy dzień) -holiday.pl-PL41.date=20161225 -holiday.pl-PL42.name=Boże Narodzenie (drugi dzień) -holiday.pl-PL42.date=20161226 +holiday.pl-PL28.date=20161226 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.por-PRT.rc task-2.5.0+dfsg/doc/rc/holidays.por-PRT.rc --- task-2.4.4+dfsg/doc/rc/holidays.por-PRT.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.por-PRT.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/pt-PT/2014.json # http://holidata.net/pt-PT/2015.json +# http://holidata.net/pt-PT/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,86 +28,58 @@ ############################################################################### holiday.pt-PT1.name=Ano Novo -holiday.pt-PT1.date=20140101 +holiday.pt-PT1.date=20150101 holiday.pt-PT2.name=Carnaval -holiday.pt-PT2.date=20140304 +holiday.pt-PT2.date=20150217 holiday.pt-PT3.name=Sexta-feira Santa -holiday.pt-PT3.date=20140418 +holiday.pt-PT3.date=20150403 holiday.pt-PT4.name=Páscoa -holiday.pt-PT4.date=20140420 +holiday.pt-PT4.date=20150405 holiday.pt-PT5.name=Dia da Liberdade -holiday.pt-PT5.date=20140425 +holiday.pt-PT5.date=20150425 holiday.pt-PT6.name=Dia do Trabalhador -holiday.pt-PT6.date=20140501 +holiday.pt-PT6.date=20150501 holiday.pt-PT7.name=Corpo de Deus -holiday.pt-PT7.date=20140619 +holiday.pt-PT7.date=20150604 holiday.pt-PT8.name=Dia de Portugal -holiday.pt-PT8.date=20140610 +holiday.pt-PT8.date=20150610 holiday.pt-PT9.name=Assunção de Nossa Senhora -holiday.pt-PT9.date=20140815 +holiday.pt-PT9.date=20150815 holiday.pt-PT10.name=Implantação da República -holiday.pt-PT10.date=20141005 +holiday.pt-PT10.date=20151005 holiday.pt-PT11.name=Todos os Santos -holiday.pt-PT11.date=20141101 +holiday.pt-PT11.date=20151101 holiday.pt-PT12.name=Restauração da Independência -holiday.pt-PT12.date=20141201 +holiday.pt-PT12.date=20151201 holiday.pt-PT13.name=Imaculada Conceição -holiday.pt-PT13.date=20141208 +holiday.pt-PT13.date=20151208 holiday.pt-PT14.name=Natal -holiday.pt-PT14.date=20141225 +holiday.pt-PT14.date=20151225 holiday.pt-PT15.name=Ano Novo -holiday.pt-PT15.date=20150101 +holiday.pt-PT15.date=20160101 holiday.pt-PT16.name=Carnaval -holiday.pt-PT16.date=20150217 +holiday.pt-PT16.date=20160209 holiday.pt-PT17.name=Sexta-feira Santa -holiday.pt-PT17.date=20150403 +holiday.pt-PT17.date=20160325 holiday.pt-PT18.name=Páscoa -holiday.pt-PT18.date=20150405 +holiday.pt-PT18.date=20160327 holiday.pt-PT19.name=Dia da Liberdade -holiday.pt-PT19.date=20150425 +holiday.pt-PT19.date=20160425 holiday.pt-PT20.name=Dia do Trabalhador -holiday.pt-PT20.date=20150501 +holiday.pt-PT20.date=20160501 holiday.pt-PT21.name=Corpo de Deus -holiday.pt-PT21.date=20150604 +holiday.pt-PT21.date=20160526 holiday.pt-PT22.name=Dia de Portugal -holiday.pt-PT22.date=20150610 +holiday.pt-PT22.date=20160610 holiday.pt-PT23.name=Assunção de Nossa Senhora -holiday.pt-PT23.date=20150815 +holiday.pt-PT23.date=20160815 holiday.pt-PT24.name=Implantação da República -holiday.pt-PT24.date=20151005 +holiday.pt-PT24.date=20161005 holiday.pt-PT25.name=Todos os Santos -holiday.pt-PT25.date=20151101 +holiday.pt-PT25.date=20161101 holiday.pt-PT26.name=Restauração da Independência -holiday.pt-PT26.date=20151201 +holiday.pt-PT26.date=20161201 holiday.pt-PT27.name=Imaculada Conceição -holiday.pt-PT27.date=20151208 +holiday.pt-PT27.date=20161208 holiday.pt-PT28.name=Natal -holiday.pt-PT28.date=20151225 -holiday.pt-PT29.name=Ano Novo -holiday.pt-PT29.date=20160101 -holiday.pt-PT30.name=Carnaval -holiday.pt-PT30.date=20160209 -holiday.pt-PT31.name=Sexta-feira Santa -holiday.pt-PT31.date=20160325 -holiday.pt-PT32.name=Páscoa -holiday.pt-PT32.date=20160327 -holiday.pt-PT33.name=Dia da Liberdade -holiday.pt-PT33.date=20160425 -holiday.pt-PT34.name=Dia do Trabalhador -holiday.pt-PT34.date=20160501 -holiday.pt-PT35.name=Corpo de Deus -holiday.pt-PT35.date=20160526 -holiday.pt-PT36.name=Dia de Portugal -holiday.pt-PT36.date=20160610 -holiday.pt-PT37.name=Assunção de Nossa Senhora -holiday.pt-PT37.date=20160815 -holiday.pt-PT38.name=Implantação da República -holiday.pt-PT38.date=20161005 -holiday.pt-PT39.name=Todos os Santos -holiday.pt-PT39.date=20161101 -holiday.pt-PT40.name=Restauração da Independência -holiday.pt-PT40.date=20161201 -holiday.pt-PT41.name=Imaculada Conceição -holiday.pt-PT41.date=20161208 -holiday.pt-PT42.name=Natal -holiday.pt-PT42.date=20161225 +holiday.pt-PT28.date=20161225 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.pt-BR.rc task-2.5.0+dfsg/doc/rc/holidays.pt-BR.rc --- task-2.4.4+dfsg/doc/rc/holidays.pt-BR.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.pt-BR.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/pt-BR/2014.json # http://holidata.net/pt-BR/2015.json +# http://holidata.net/pt-BR/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,80 +28,54 @@ ############################################################################### holiday.pt-BR1.name=Confraternização Universal -holiday.pt-BR1.date=20140101 +holiday.pt-BR1.date=20150101 holiday.pt-BR2.name=Carnaval -holiday.pt-BR2.date=20140303 +holiday.pt-BR2.date=20150216 holiday.pt-BR3.name=Carnaval -holiday.pt-BR3.date=20140304 +holiday.pt-BR3.date=20150217 holiday.pt-BR4.name=Sexta-feira Santa -holiday.pt-BR4.date=20140418 +holiday.pt-BR4.date=20150403 holiday.pt-BR5.name=Páscoa -holiday.pt-BR5.date=20140420 +holiday.pt-BR5.date=20150405 holiday.pt-BR6.name=Tiradentes -holiday.pt-BR6.date=20140421 +holiday.pt-BR6.date=20150421 holiday.pt-BR7.name=Dia do Trabalho -holiday.pt-BR7.date=20140501 +holiday.pt-BR7.date=20150501 holiday.pt-BR8.name=Corpus Christi -holiday.pt-BR8.date=20140619 +holiday.pt-BR8.date=20150604 holiday.pt-BR9.name=Independência do Brasil -holiday.pt-BR9.date=20140907 +holiday.pt-BR9.date=20150907 holiday.pt-BR10.name=Nossa Senhora Aparecida -holiday.pt-BR10.date=20141012 +holiday.pt-BR10.date=20151012 holiday.pt-BR11.name=Finados -holiday.pt-BR11.date=20141102 +holiday.pt-BR11.date=20151102 holiday.pt-BR12.name=Proclamação da República -holiday.pt-BR12.date=20141115 +holiday.pt-BR12.date=20151115 holiday.pt-BR13.name=Natal -holiday.pt-BR13.date=20141225 +holiday.pt-BR13.date=20151225 holiday.pt-BR14.name=Confraternização Universal -holiday.pt-BR14.date=20150101 +holiday.pt-BR14.date=20160101 holiday.pt-BR15.name=Carnaval -holiday.pt-BR15.date=20150216 +holiday.pt-BR15.date=20160208 holiday.pt-BR16.name=Carnaval -holiday.pt-BR16.date=20150217 +holiday.pt-BR16.date=20160209 holiday.pt-BR17.name=Sexta-feira Santa -holiday.pt-BR17.date=20150403 +holiday.pt-BR17.date=20160325 holiday.pt-BR18.name=Páscoa -holiday.pt-BR18.date=20150405 +holiday.pt-BR18.date=20160327 holiday.pt-BR19.name=Tiradentes -holiday.pt-BR19.date=20150421 +holiday.pt-BR19.date=20160421 holiday.pt-BR20.name=Dia do Trabalho -holiday.pt-BR20.date=20150501 +holiday.pt-BR20.date=20160501 holiday.pt-BR21.name=Corpus Christi -holiday.pt-BR21.date=20150604 +holiday.pt-BR21.date=20160526 holiday.pt-BR22.name=Independência do Brasil -holiday.pt-BR22.date=20150907 +holiday.pt-BR22.date=20160907 holiday.pt-BR23.name=Nossa Senhora Aparecida -holiday.pt-BR23.date=20151012 +holiday.pt-BR23.date=20161012 holiday.pt-BR24.name=Finados -holiday.pt-BR24.date=20151102 +holiday.pt-BR24.date=20161102 holiday.pt-BR25.name=Proclamação da República -holiday.pt-BR25.date=20151115 +holiday.pt-BR25.date=20161115 holiday.pt-BR26.name=Natal -holiday.pt-BR26.date=20151225 -holiday.pt-BR27.name=Confraternização Universal -holiday.pt-BR27.date=20160101 -holiday.pt-BR28.name=Carnaval -holiday.pt-BR28.date=20160208 -holiday.pt-BR29.name=Carnaval -holiday.pt-BR29.date=20160209 -holiday.pt-BR30.name=Sexta-feira Santa -holiday.pt-BR30.date=20160325 -holiday.pt-BR31.name=Páscoa -holiday.pt-BR31.date=20160327 -holiday.pt-BR32.name=Tiradentes -holiday.pt-BR32.date=20160421 -holiday.pt-BR33.name=Dia do Trabalho -holiday.pt-BR33.date=20160501 -holiday.pt-BR34.name=Corpus Christi -holiday.pt-BR34.date=20160526 -holiday.pt-BR35.name=Independência do Brasil -holiday.pt-BR35.date=20160907 -holiday.pt-BR36.name=Nossa Senhora Aparecida -holiday.pt-BR36.date=20161012 -holiday.pt-BR37.name=Finados -holiday.pt-BR37.date=20161102 -holiday.pt-BR38.name=Proclamação da República -holiday.pt-BR38.date=20161115 -holiday.pt-BR39.name=Natal -holiday.pt-BR39.date=20161225 +holiday.pt-BR26.date=20161225 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.pt-PT.rc task-2.5.0+dfsg/doc/rc/holidays.pt-PT.rc --- task-2.4.4+dfsg/doc/rc/holidays.pt-PT.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.pt-PT.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/pt-PT/2014.json # http://holidata.net/pt-PT/2015.json +# http://holidata.net/pt-PT/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,86 +28,58 @@ ############################################################################### holiday.pt-PT1.name=Ano Novo -holiday.pt-PT1.date=20140101 +holiday.pt-PT1.date=20150101 holiday.pt-PT2.name=Carnaval -holiday.pt-PT2.date=20140304 +holiday.pt-PT2.date=20150217 holiday.pt-PT3.name=Sexta-feira Santa -holiday.pt-PT3.date=20140418 +holiday.pt-PT3.date=20150403 holiday.pt-PT4.name=Páscoa -holiday.pt-PT4.date=20140420 +holiday.pt-PT4.date=20150405 holiday.pt-PT5.name=Dia da Liberdade -holiday.pt-PT5.date=20140425 +holiday.pt-PT5.date=20150425 holiday.pt-PT6.name=Dia do Trabalhador -holiday.pt-PT6.date=20140501 +holiday.pt-PT6.date=20150501 holiday.pt-PT7.name=Corpo de Deus -holiday.pt-PT7.date=20140619 +holiday.pt-PT7.date=20150604 holiday.pt-PT8.name=Dia de Portugal -holiday.pt-PT8.date=20140610 +holiday.pt-PT8.date=20150610 holiday.pt-PT9.name=Assunção de Nossa Senhora -holiday.pt-PT9.date=20140815 +holiday.pt-PT9.date=20150815 holiday.pt-PT10.name=Implantação da República -holiday.pt-PT10.date=20141005 +holiday.pt-PT10.date=20151005 holiday.pt-PT11.name=Todos os Santos -holiday.pt-PT11.date=20141101 +holiday.pt-PT11.date=20151101 holiday.pt-PT12.name=Restauração da Independência -holiday.pt-PT12.date=20141201 +holiday.pt-PT12.date=20151201 holiday.pt-PT13.name=Imaculada Conceição -holiday.pt-PT13.date=20141208 +holiday.pt-PT13.date=20151208 holiday.pt-PT14.name=Natal -holiday.pt-PT14.date=20141225 +holiday.pt-PT14.date=20151225 holiday.pt-PT15.name=Ano Novo -holiday.pt-PT15.date=20150101 +holiday.pt-PT15.date=20160101 holiday.pt-PT16.name=Carnaval -holiday.pt-PT16.date=20150217 +holiday.pt-PT16.date=20160209 holiday.pt-PT17.name=Sexta-feira Santa -holiday.pt-PT17.date=20150403 +holiday.pt-PT17.date=20160325 holiday.pt-PT18.name=Páscoa -holiday.pt-PT18.date=20150405 +holiday.pt-PT18.date=20160327 holiday.pt-PT19.name=Dia da Liberdade -holiday.pt-PT19.date=20150425 +holiday.pt-PT19.date=20160425 holiday.pt-PT20.name=Dia do Trabalhador -holiday.pt-PT20.date=20150501 +holiday.pt-PT20.date=20160501 holiday.pt-PT21.name=Corpo de Deus -holiday.pt-PT21.date=20150604 +holiday.pt-PT21.date=20160526 holiday.pt-PT22.name=Dia de Portugal -holiday.pt-PT22.date=20150610 +holiday.pt-PT22.date=20160610 holiday.pt-PT23.name=Assunção de Nossa Senhora -holiday.pt-PT23.date=20150815 +holiday.pt-PT23.date=20160815 holiday.pt-PT24.name=Implantação da República -holiday.pt-PT24.date=20151005 +holiday.pt-PT24.date=20161005 holiday.pt-PT25.name=Todos os Santos -holiday.pt-PT25.date=20151101 +holiday.pt-PT25.date=20161101 holiday.pt-PT26.name=Restauração da Independência -holiday.pt-PT26.date=20151201 +holiday.pt-PT26.date=20161201 holiday.pt-PT27.name=Imaculada Conceição -holiday.pt-PT27.date=20151208 +holiday.pt-PT27.date=20161208 holiday.pt-PT28.name=Natal -holiday.pt-PT28.date=20151225 -holiday.pt-PT29.name=Ano Novo -holiday.pt-PT29.date=20160101 -holiday.pt-PT30.name=Carnaval -holiday.pt-PT30.date=20160209 -holiday.pt-PT31.name=Sexta-feira Santa -holiday.pt-PT31.date=20160325 -holiday.pt-PT32.name=Páscoa -holiday.pt-PT32.date=20160327 -holiday.pt-PT33.name=Dia da Liberdade -holiday.pt-PT33.date=20160425 -holiday.pt-PT34.name=Dia do Trabalhador -holiday.pt-PT34.date=20160501 -holiday.pt-PT35.name=Corpo de Deus -holiday.pt-PT35.date=20160526 -holiday.pt-PT36.name=Dia de Portugal -holiday.pt-PT36.date=20160610 -holiday.pt-PT37.name=Assunção de Nossa Senhora -holiday.pt-PT37.date=20160815 -holiday.pt-PT38.name=Implantação da República -holiday.pt-PT38.date=20161005 -holiday.pt-PT39.name=Todos os Santos -holiday.pt-PT39.date=20161101 -holiday.pt-PT40.name=Restauração da Independência -holiday.pt-PT40.date=20161201 -holiday.pt-PT41.name=Imaculada Conceição -holiday.pt-PT41.date=20161208 -holiday.pt-PT42.name=Natal -holiday.pt-PT42.date=20161225 +holiday.pt-PT28.date=20161225 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.ru-RU.rc task-2.5.0+dfsg/doc/rc/holidays.ru-RU.rc --- task-2.4.4+dfsg/doc/rc/holidays.ru-RU.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.ru-RU.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/ru-RU/2014.json # http://holidata.net/ru-RU/2015.json +# http://holidata.net/ru-RU/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,56 +28,38 @@ ############################################################################### holiday.ru-RU1.name=Новый Год -holiday.ru-RU1.date=20140101 +holiday.ru-RU1.date=20150101 holiday.ru-RU2.name=Рождество Христово -holiday.ru-RU2.date=20140107 +holiday.ru-RU2.date=20150107 holiday.ru-RU3.name=День защитника Отечества -holiday.ru-RU3.date=20140223 +holiday.ru-RU3.date=20150223 holiday.ru-RU4.name=Международный женский день -holiday.ru-RU4.date=20140803 +holiday.ru-RU4.date=20150803 holiday.ru-RU5.name=Пасха -holiday.ru-RU5.date=20140420 +holiday.ru-RU5.date=20150412 holiday.ru-RU6.name=Праздник весны и труда -holiday.ru-RU6.date=20140501 +holiday.ru-RU6.date=20150501 holiday.ru-RU7.name=День Победы -holiday.ru-RU7.date=20140509 +holiday.ru-RU7.date=20150509 holiday.ru-RU8.name=День России -holiday.ru-RU8.date=20140612 +holiday.ru-RU8.date=20150612 holiday.ru-RU9.name=День народного единства -holiday.ru-RU9.date=20141104 +holiday.ru-RU9.date=20151104 holiday.ru-RU10.name=Новый Год -holiday.ru-RU10.date=20150101 +holiday.ru-RU10.date=20160101 holiday.ru-RU11.name=Рождество Христово -holiday.ru-RU11.date=20150107 +holiday.ru-RU11.date=20160107 holiday.ru-RU12.name=День защитника Отечества -holiday.ru-RU12.date=20150223 +holiday.ru-RU12.date=20160223 holiday.ru-RU13.name=Международный женский день -holiday.ru-RU13.date=20150803 +holiday.ru-RU13.date=20160803 holiday.ru-RU14.name=Пасха -holiday.ru-RU14.date=20150412 +holiday.ru-RU14.date=20160501 holiday.ru-RU15.name=Праздник весны и труда -holiday.ru-RU15.date=20150501 +holiday.ru-RU15.date=20160501 holiday.ru-RU16.name=День Победы -holiday.ru-RU16.date=20150509 +holiday.ru-RU16.date=20160509 holiday.ru-RU17.name=День России -holiday.ru-RU17.date=20150612 +holiday.ru-RU17.date=20160612 holiday.ru-RU18.name=День народного единства -holiday.ru-RU18.date=20151104 -holiday.ru-RU19.name=Новый Год -holiday.ru-RU19.date=20160101 -holiday.ru-RU20.name=Рождество Христово -holiday.ru-RU20.date=20160107 -holiday.ru-RU21.name=День защитника Отечества -holiday.ru-RU21.date=20160223 -holiday.ru-RU22.name=Международный женский день -holiday.ru-RU22.date=20160803 -holiday.ru-RU23.name=Пасха -holiday.ru-RU23.date=20160501 -holiday.ru-RU24.name=Праздник весны и труда -holiday.ru-RU24.date=20160501 -holiday.ru-RU25.name=День Победы -holiday.ru-RU25.date=20160509 -holiday.ru-RU26.name=День России -holiday.ru-RU26.date=20160612 -holiday.ru-RU27.name=День народного единства -holiday.ru-RU27.date=20161104 +holiday.ru-RU18.date=20161104 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.sv-SE.rc task-2.5.0+dfsg/doc/rc/holidays.sv-SE.rc --- task-2.4.4+dfsg/doc/rc/holidays.sv-SE.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.sv-SE.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/sv-SE/2014.json # http://holidata.net/sv-SE/2015.json +# http://holidata.net/sv-SE/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,104 +28,70 @@ ############################################################################### holiday.sv-SE1.name=Nyårsdagen -holiday.sv-SE1.date=20140101 +holiday.sv-SE1.date=20150101 holiday.sv-SE2.name=Trettondedag jul -holiday.sv-SE2.date=20140106 +holiday.sv-SE2.date=20150106 holiday.sv-SE3.name=Långfredagen -holiday.sv-SE3.date=20140418 +holiday.sv-SE3.date=20150403 holiday.sv-SE4.name=Påskdagen -holiday.sv-SE4.date=20140420 +holiday.sv-SE4.date=20150405 holiday.sv-SE5.name=Annandag påsk -holiday.sv-SE5.date=20140421 +holiday.sv-SE5.date=20150406 holiday.sv-SE6.name=Valborgmässoafton -holiday.sv-SE6.date=20140430 +holiday.sv-SE6.date=20150430 holiday.sv-SE7.name=Första maj -holiday.sv-SE7.date=20140501 +holiday.sv-SE7.date=20150501 holiday.sv-SE8.name=Kristi Himmelsfärdsdag -holiday.sv-SE8.date=20140529 +holiday.sv-SE8.date=20150514 holiday.sv-SE9.name=Pingstdagen -holiday.sv-SE9.date=20140608 +holiday.sv-SE9.date=20150524 holiday.sv-SE10.name=Nationaldagen -holiday.sv-SE10.date=20140606 +holiday.sv-SE10.date=20150606 holiday.sv-SE11.name=Midsommarafton -holiday.sv-SE11.date=20140620 +holiday.sv-SE11.date=20150619 holiday.sv-SE12.name=Midsommardagen -holiday.sv-SE12.date=20140621 +holiday.sv-SE12.date=20150620 holiday.sv-SE13.name=Alla Helgons Dag -holiday.sv-SE13.date=20141101 +holiday.sv-SE13.date=20151031 holiday.sv-SE14.name=Julafton -holiday.sv-SE14.date=20141224 +holiday.sv-SE14.date=20151224 holiday.sv-SE15.name=Juldagen -holiday.sv-SE15.date=20141225 +holiday.sv-SE15.date=20151225 holiday.sv-SE16.name=Annandag jul -holiday.sv-SE16.date=20141226 +holiday.sv-SE16.date=20151226 holiday.sv-SE17.name=Nyårsafton -holiday.sv-SE17.date=20141231 +holiday.sv-SE17.date=20151231 holiday.sv-SE18.name=Nyårsdagen -holiday.sv-SE18.date=20150101 +holiday.sv-SE18.date=20160101 holiday.sv-SE19.name=Trettondedag jul -holiday.sv-SE19.date=20150106 +holiday.sv-SE19.date=20160106 holiday.sv-SE20.name=Långfredagen -holiday.sv-SE20.date=20150403 +holiday.sv-SE20.date=20160325 holiday.sv-SE21.name=Påskdagen -holiday.sv-SE21.date=20150405 +holiday.sv-SE21.date=20160327 holiday.sv-SE22.name=Annandag påsk -holiday.sv-SE22.date=20150406 +holiday.sv-SE22.date=20160328 holiday.sv-SE23.name=Valborgmässoafton -holiday.sv-SE23.date=20150430 +holiday.sv-SE23.date=20160430 holiday.sv-SE24.name=Första maj -holiday.sv-SE24.date=20150501 +holiday.sv-SE24.date=20160501 holiday.sv-SE25.name=Kristi Himmelsfärdsdag -holiday.sv-SE25.date=20150514 +holiday.sv-SE25.date=20160505 holiday.sv-SE26.name=Pingstdagen -holiday.sv-SE26.date=20150524 +holiday.sv-SE26.date=20160515 holiday.sv-SE27.name=Nationaldagen -holiday.sv-SE27.date=20150606 +holiday.sv-SE27.date=20160606 holiday.sv-SE28.name=Midsommarafton -holiday.sv-SE28.date=20150619 +holiday.sv-SE28.date=20160624 holiday.sv-SE29.name=Midsommardagen -holiday.sv-SE29.date=20150620 +holiday.sv-SE29.date=20160625 holiday.sv-SE30.name=Alla Helgons Dag -holiday.sv-SE30.date=20151031 +holiday.sv-SE30.date=20161105 holiday.sv-SE31.name=Julafton -holiday.sv-SE31.date=20151224 +holiday.sv-SE31.date=20161224 holiday.sv-SE32.name=Juldagen -holiday.sv-SE32.date=20151225 +holiday.sv-SE32.date=20161225 holiday.sv-SE33.name=Annandag jul -holiday.sv-SE33.date=20151226 +holiday.sv-SE33.date=20161226 holiday.sv-SE34.name=Nyårsafton -holiday.sv-SE34.date=20151231 -holiday.sv-SE35.name=Nyårsdagen -holiday.sv-SE35.date=20160101 -holiday.sv-SE36.name=Trettondedag jul -holiday.sv-SE36.date=20160106 -holiday.sv-SE37.name=Långfredagen -holiday.sv-SE37.date=20160325 -holiday.sv-SE38.name=Påskdagen -holiday.sv-SE38.date=20160327 -holiday.sv-SE39.name=Annandag påsk -holiday.sv-SE39.date=20160328 -holiday.sv-SE40.name=Valborgmässoafton -holiday.sv-SE40.date=20160430 -holiday.sv-SE41.name=Första maj -holiday.sv-SE41.date=20160501 -holiday.sv-SE42.name=Kristi Himmelsfärdsdag -holiday.sv-SE42.date=20160505 -holiday.sv-SE43.name=Pingstdagen -holiday.sv-SE43.date=20160515 -holiday.sv-SE44.name=Nationaldagen -holiday.sv-SE44.date=20160606 -holiday.sv-SE45.name=Midsommarafton -holiday.sv-SE45.date=20160624 -holiday.sv-SE46.name=Midsommardagen -holiday.sv-SE46.date=20160625 -holiday.sv-SE47.name=Alla Helgons Dag -holiday.sv-SE47.date=20161105 -holiday.sv-SE48.name=Julafton -holiday.sv-SE48.date=20161224 -holiday.sv-SE49.name=Juldagen -holiday.sv-SE49.date=20161225 -holiday.sv-SE50.name=Annandag jul -holiday.sv-SE50.date=20161226 -holiday.sv-SE51.name=Nyårsafton -holiday.sv-SE51.date=20161231 +holiday.sv-SE34.date=20161231 diff -Nru task-2.4.4+dfsg/doc/rc/holidays.tr-TR.rc task-2.5.0+dfsg/doc/rc/holidays.tr-TR.rc --- task-2.4.4+dfsg/doc/rc/holidays.tr-TR.rc 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/doc/rc/holidays.tr-TR.rc 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,7 @@ ############################################################################### # International Holiday Data provided by Holidata.net -# http://holidata.net/tr-TR/2014.json # http://holidata.net/tr-TR/2015.json +# http://holidata.net/tr-TR/2016.json # # Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. # @@ -28,80 +28,54 @@ ############################################################################### holiday.tr-TR1.name=Yılbaşı -holiday.tr-TR1.date=20140101 +holiday.tr-TR1.date=20150101 holiday.tr-TR2.name=Ulusal Egemenlik ve Çocuk Bayramı -holiday.tr-TR2.date=20140423 +holiday.tr-TR2.date=20150423 holiday.tr-TR3.name=Emek ve Dayanışma Günü -holiday.tr-TR3.date=20140501 +holiday.tr-TR3.date=20150501 holiday.tr-TR4.name=Atatürk'ü Anma Gençlik ve Spor Bayramı -holiday.tr-TR4.date=20140519 +holiday.tr-TR4.date=20150519 holiday.tr-TR5.name=Zafer Bayramı -holiday.tr-TR5.date=20140830 +holiday.tr-TR5.date=20150830 holiday.tr-TR6.name=Cumhuriyet Bayramı -holiday.tr-TR6.date=20141029 +holiday.tr-TR6.date=20151029 holiday.tr-TR7.name=Ramazan Bayramı 1 -holiday.tr-TR7.date=20140728 +holiday.tr-TR7.date=20150717 holiday.tr-TR8.name=Ramazan Bayramı 2 -holiday.tr-TR8.date=20140729 +holiday.tr-TR8.date=20150718 holiday.tr-TR9.name=Ramazan Bayramı 3 -holiday.tr-TR9.date=20140730 +holiday.tr-TR9.date=20150719 holiday.tr-TR10.name=Kurban Bayramı 1 -holiday.tr-TR10.date=20141004 +holiday.tr-TR10.date=20150923 holiday.tr-TR11.name=Kurban Bayramı 2 -holiday.tr-TR11.date=20141005 +holiday.tr-TR11.date=20150924 holiday.tr-TR12.name=Kurban Bayramı 3 -holiday.tr-TR12.date=20141006 +holiday.tr-TR12.date=20150925 holiday.tr-TR13.name=Kurban Bayramı 4 -holiday.tr-TR13.date=20141007 +holiday.tr-TR13.date=20150926 holiday.tr-TR14.name=Yılbaşı -holiday.tr-TR14.date=20150101 +holiday.tr-TR14.date=20160101 holiday.tr-TR15.name=Ulusal Egemenlik ve Çocuk Bayramı -holiday.tr-TR15.date=20150423 +holiday.tr-TR15.date=20160423 holiday.tr-TR16.name=Emek ve Dayanışma Günü -holiday.tr-TR16.date=20150501 +holiday.tr-TR16.date=20160501 holiday.tr-TR17.name=Atatürk'ü Anma Gençlik ve Spor Bayramı -holiday.tr-TR17.date=20150519 +holiday.tr-TR17.date=20160519 holiday.tr-TR18.name=Zafer Bayramı -holiday.tr-TR18.date=20150830 +holiday.tr-TR18.date=20160830 holiday.tr-TR19.name=Cumhuriyet Bayramı -holiday.tr-TR19.date=20151029 +holiday.tr-TR19.date=20161029 holiday.tr-TR20.name=Ramazan Bayramı 1 -holiday.tr-TR20.date=20150717 +holiday.tr-TR20.date=20160705 holiday.tr-TR21.name=Ramazan Bayramı 2 -holiday.tr-TR21.date=20150718 +holiday.tr-TR21.date=20160706 holiday.tr-TR22.name=Ramazan Bayramı 3 -holiday.tr-TR22.date=20150719 +holiday.tr-TR22.date=20160707 holiday.tr-TR23.name=Kurban Bayramı 1 -holiday.tr-TR23.date=20150923 +holiday.tr-TR23.date=20160912 holiday.tr-TR24.name=Kurban Bayramı 2 -holiday.tr-TR24.date=20150924 +holiday.tr-TR24.date=20160913 holiday.tr-TR25.name=Kurban Bayramı 3 -holiday.tr-TR25.date=20150925 +holiday.tr-TR25.date=20160914 holiday.tr-TR26.name=Kurban Bayramı 4 -holiday.tr-TR26.date=20150926 -holiday.tr-TR27.name=Yılbaşı -holiday.tr-TR27.date=20160101 -holiday.tr-TR28.name=Ulusal Egemenlik ve Çocuk Bayramı -holiday.tr-TR28.date=20160423 -holiday.tr-TR29.name=Emek ve Dayanışma Günü -holiday.tr-TR29.date=20160501 -holiday.tr-TR30.name=Atatürk'ü Anma Gençlik ve Spor Bayramı -holiday.tr-TR30.date=20160519 -holiday.tr-TR31.name=Zafer Bayramı -holiday.tr-TR31.date=20160830 -holiday.tr-TR32.name=Cumhuriyet Bayramı -holiday.tr-TR32.date=20161029 -holiday.tr-TR33.name=Ramazan Bayramı 1 -holiday.tr-TR33.date=20160705 -holiday.tr-TR34.name=Ramazan Bayramı 2 -holiday.tr-TR34.date=20160706 -holiday.tr-TR35.name=Ramazan Bayramı 3 -holiday.tr-TR35.date=20160707 -holiday.tr-TR36.name=Kurban Bayramı 1 -holiday.tr-TR36.date=20160912 -holiday.tr-TR37.name=Kurban Bayramı 2 -holiday.tr-TR37.date=20160913 -holiday.tr-TR38.name=Kurban Bayramı 3 -holiday.tr-TR38.date=20160914 -holiday.tr-TR39.name=Kurban Bayramı 4 -holiday.tr-TR39.date=20160915 +holiday.tr-TR26.date=20160915 diff -Nru task-2.4.4+dfsg/EXPOSITION task-2.5.0+dfsg/EXPOSITION --- task-2.4.4+dfsg/EXPOSITION 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/EXPOSITION 2015-10-21 21:18:14.000000000 +0000 @@ -24,7 +24,7 @@ determines whether subsequent arguments are interpreted as part of a filter or set of modifications. - The CLI object is fed command line arguments, then through a succession of + The CLI2 object is fed command line arguments, then through a succession of calls builds and annotates a parse tree. To help with this, the Lexer is used to break up strings into tokens. @@ -151,16 +151,14 @@ A strong and diverse test suite is critical to the successful release of any software. With the complex command set and its myriad permutations, a test suite is the only way to ensure quality levels, and guarantee that big changes - are sound. + are robust. - It is intended that the test suite continues growing, mostly adding more - regression and feature tests. The test are mostly written in Perl, and utilize - the Test::More module to generate TAP output. This is changing though, and the - suite is slowly migrating to Python. Some tests are written in C++ and all - tets generate TAP output. + It is intended that the test suite continues growing, mostly feature tests. + The test are mostly written in Python. Some tests are written in C++ and all + tests generate TAP output. - There are currently about 8,000 unit tests, that take a minute or two to run - in total. + There are currently about 8,000 unit tests, that take only a few seconds to + run on a multi-core machine. Taskwarrior uses flod software to automate continuous integration across many platforms. Code changes are automatically detected, propagated, built and @@ -184,7 +182,7 @@ - TDB2 layer and I/O information. Additionally, there are other settings (see 'man taskrc' for full details) that - may also be helpful: 'rc.hooks=on|off', 'rc.debug.parser=0|1|2', + may also be helpful: 'rc.hooks=on|off', 'rc.debug.parser=0|1|2|3', 'rc.debug.hooks=0|1|2', 'rc.debug.tls=0|1|2|3...'. @@ -193,7 +191,8 @@ Jira issue, or send them to support@taskwarrior.org. A good patch: - Maintains the MIT license, and does not contain code lifted from other - sources. + sources. You will have written 100% of the code in the patch, otherwise + we cannot maintain the license. - Precisely addresses one issue only. - Doesn't break unit tests. - Doesn't introduce dependencies. @@ -202,9 +201,10 @@ - Conforms to the prevailing coding standards - in other words, it should fit right in with the existing code. - A patch may be rejected for not following the above guidelines, and more. + A patch may be rejected for violating any of the above rules, and more. Bad patches may be accepted and modified depending on work load and mood. It is possible that a patch may be rejected because it conflicts in some way with - plans or upcoming changes. + plans or upcoming changes. Check with us first, before sinking time and effort + into a patch. --- diff -Nru task-2.4.4+dfsg/INSTALL task-2.5.0+dfsg/INSTALL --- task-2.4.4+dfsg/INSTALL 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/INSTALL 2015-10-21 21:18:14.000000000 +0000 @@ -5,8 +5,8 @@ source. -Pre-requisites --------------- +Dependencies +------------ You will need the CMake build system installed in order to build Taskwarrior from source. More information on cmake can be obtained at http://cmake.org @@ -19,11 +19,8 @@ - clang 3.3 (released 2013-01-07) You will need the following libraries: - - libuuid - - gnutls (optional - for syncing) - -It is HIGHLY RECOMMENDED that you build with a library that provides uuid_* -functions, such as libuuid. + - libuuid (not needed for OSX) + - gnutls (can be optional - see '"sync" command' below) Basic Installation @@ -91,6 +88,20 @@ CMAKE_INSTALL_PREFIX/TASK_MAN5DIR /usr/local/share/man/man5 +"sync" command +-------------- + +By default, GnuTLS support is required, which enables the "sync" command. +For Debian based distributions, installing "libgnutls-dev" is sufficient. + +In order to build Taskwarrior without "sync" support, call cmake with the +"-DENABLE_SYNC=OFF" flag: + + $ cmake . -DENABLE_SYNC=OFF + +and proceed as described in "Basic Installation". + + Localizations ------------- diff -Nru task-2.4.4+dfsg/NEWS task-2.5.0+dfsg/NEWS --- task-2.4.4+dfsg/NEWS 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/NEWS 2015-10-21 21:18:14.000000000 +0000 @@ -1,26 +1,56 @@ -New Features in Taskwarrior 2.4.4 +New Features in Taskwarrior 2.5.0 - - Taskwarrior now requires GCC 4.7+ / Clang 3.3+, for full C++11 support. - - Taskwarrior now builds properly on 32-bit platforms. - - The beginnings of a Japaneѕe translation. - -New commands in Taskwarrior 2.4.4 - - - None - -New configuration options in Taskwarrior 2.4.4 - - - The 'obfuscate' setting, if set to '1' will replace all text with 'xxx'. - This is useful when sharing data for bug reporting purposes. - -Newly deprecated features in Taskwarrior 2.4.4 - - - None - -Removed features in 2.4.4 - - - None + - The active context, if one is set, is now identified in "task context list" + - It is an error to attempt adding or removing a virtual tag. + - New 'UDA', 'ORPHAN', 'PROJECT', 'PRIORITY' and 'LATEST' virtual tags. + +New Commands in Taskwarrior 2.5.0 + + - The '_unique' command shows a set of unique values for the specified + attribute + - The 'commands' command shows the supported commands, with additional + details that determine some of their behavior. + +New Configuration Options in Taskwarrior 2.5.0 + + - The 'json.depends.array' setting controls whether dependencies are exported + as a JSON array, of a comma-separated string. Default is 'on'. + Both variations are imported. + - The 'color.uda..none' is a color that is applied to tasks that do + not have a value for the UDA ''. + - A Cygwin fix means that now we can default 'search.case.sensitive' to 'yes', + and all platforms are again equal. + - The new 'recur' verbosity token generates a message when a recurring task is + generated. + - The new 'unwait' verbosity token generates a message when a waiting task + becomes visible. + - The new 'rule.color.merge' configuration option can disable merging of colors + produced by different color rules. Use if your color scheme produces + unpleasing foreground and background combinations. + +Newly Deprecated Features in Taskwarrior 2.5.0 + + - The '_ids', '_projects', '_tags', '_uuids' helper commands are deprecated, + and replaced by the new '_unique' helper command. + - Comma-separated ID lists are deprecated. + - The 'new-uuid' verbosity token is deprecated. Its functionality will + be merged with the 'new-id' verbosity token. + +Removed Features in 2.5.0 + + - The script 'context' was removed, now that context is a core feature. + - Non­extended forms of ISO-8601 date/time support is removed. This means + that 'YYYYMMDD' is no longer supported, but 'YYYY-MM-DD' is. For times, + 'hhmmss' is no longer supported, but 'hh:mm:ss' is. The non-extended + forms all contain sequences of digits that make the identification of + IDs, UUIDs, and various date/time formats ambiguous. + - Comma-separated UUID lists are no longer supported. + - DOM references may no longer be abbreviated. + - The 'urgency.next.coefficient' configuration option is deprecated in favor + of 'urgency.user.tag.next.coefficient'. + - The long deprecated syntax of color values with underscores (i.e 'on_red') + is no longer supported. Known Issues diff -Nru task-2.4.4+dfsg/performance/run_perf task-2.5.0+dfsg/performance/run_perf --- task-2.4.4+dfsg/performance/run_perf 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/performance/run_perf 2015-10-21 21:18:14.000000000 +0000 @@ -1,13 +1,20 @@ #! /bin/bash echo 'Performance: setup' -echo ' - This step will take several minutes' rm -f ./pending.data ./completed.data ./undo.data ./backlog.data perf.rc -./load +if [[ -e data/pending.data && -e data/completed.data ]] +then + echo ' - Using existing data' + cp data/* . +else + echo ' - This step will take several minutes' + ./load + mkdir -p data + cp *.data perf.rc data +fi -#TASK=/usr/local/bin/tw212 -#TASK=/usr/local/bin/tw220 -#TASK=/usr/local/bin/tw230 +#TASK=/usr/local/bin/tw244 +#TASK=/usr/local/bin/tw250b1 TASK=../src/task # Run benchmarks. diff -Nru task-2.4.4+dfsg/scripts/add-ons/export-csv.pl task-2.5.0+dfsg/scripts/add-ons/export-csv.pl --- task-2.4.4+dfsg/scripts/add-ons/export-csv.pl 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/scripts/add-ons/export-csv.pl 1970-01-01 00:00:00.000000000 +0000 @@ -1,85 +0,0 @@ -#! /usr/bin/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; - -# Give a nice error if the (non-standard) JSON module is not installed. -eval "use JSON"; -if ($@) -{ - print "Error: You need to install the JSON Perl module.\n"; - exit 1; -} - -# Use the taskwarrior 2.0+ export command to filter and return JSON -my $command = join (' ', ("env PATH=$ENV{PATH} task rc.verbose=nothing rc.json.array=no export", @ARGV)); -if ($command =~ /No matches/) -{ - printf STDERR $command; - exit 1; -} - -# Generate output. -print "'uuid','status','tags','entry','start','due','recur','end','project',", - "'priority','fg','bg','description'\n"; - -for my $task (split "\n", qx{$command}) -{ - my $data = from_json ($task); - - my $desc = $data->{'description'}; - $desc =~ s/'/\\'/g; - - print "'$data->{'uuid'}',", - "'$data->{'status'}',", - "'", (exists $data->{'tags'} ? join (' ', @{$data->{'tags'}}) : ''), "',", - "'$data->{'entry'}',", - "'", ($data->{'start'} || ''), "',", - "'", ($data->{'due'} || ''), "',", - "'", ($data->{'recur'} || ''), "',", - "'", ($data->{'end'} || ''), "',", - "'", ($data->{'project'} || ''), "',", - "'", ($data->{'priority'} || ''), "',", - "'", ($data->{'fg'} || ''), "',", - "'", ($data->{'bg'} || ''), "',", - "'$desc'", - "\n"; - - # Note that this format ignores: - # wait - # until - # annotations - # mask - # imask - # UDAs -} - -exit 0; - -################################################################################ - diff -Nru task-2.4.4+dfsg/scripts/add-ons/export-html.pl task-2.5.0+dfsg/scripts/add-ons/export-html.pl --- task-2.4.4+dfsg/scripts/add-ons/export-html.pl 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/scripts/add-ons/export-html.pl 1970-01-01 00:00:00.000000000 +0000 @@ -1,90 +0,0 @@ -#! /usr/bin/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; - -# Give a nice error if the (non-standard) JSON module is not installed. -eval "use JSON"; -if ($@) -{ - print "Error: You need to install the JSON Perl module.\n"; - exit 1; -} - -# Use the taskwarrior 2.0+ export command to filter and return JSON -my $command = join (' ', ("env PATH='$ENV{PATH}' task rc.verbose=nothing rc.json.array=no export", @ARGV)); -if ($command =~ /No matches/) -{ - printf STDERR $command; - exit 1; -} - -# Generate output. -print "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n"; - -my $count = 0; -for my $task (split "\n", qx{$command}) -{ - ++$count; - my $data = from_json ($task); - - print " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n"; -} - -print " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
IDPriDescriptionProjectDue
", ($data->{'id'} || ''), "", ($data->{'priority'} || ''), "", ($data->{'description'} || ''), "", ($data->{'project'} || ''), "", ($data->{'due'} || ''), "
", $count, " matching tasks
\n", - " \n", - "\n"; - -exit 0; - -################################################################################ - diff -Nru task-2.4.4+dfsg/scripts/add-ons/export-ical.pl task-2.5.0+dfsg/scripts/add-ons/export-ical.pl --- task-2.4.4+dfsg/scripts/add-ons/export-ical.pl 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/scripts/add-ons/export-ical.pl 1970-01-01 00:00:00.000000000 +0000 @@ -1,102 +0,0 @@ -#! /usr/bin/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; - -# Give a nice error if the (non-standard) JSON module is not installed. -eval "use JSON"; -if ($@) -{ - print "Error: You need to install the JSON Perl module.\n"; - exit 1; -} - -# Use the taskwarrior 2.0+ export command to filter and return JSON -my $command = join (' ', ("env PATH=$ENV{PATH} task rc.verbose=nothing rc.json.array=no export", @ARGV)); -if ($command =~ /No matches/) -{ - printf STDERR $command; - exit 1; -} - -# Generate output. -print "BEGIN:VCALENDAR\n", - "VERSION:2.0\n", - "PRODID:=//GBF/taskwarrior 1.9.4//EN\n"; - -for my $task (split "\n", qx{$command}) -{ - my $data = from_json ($task); - - print "BEGIN:VTODO\n"; - print "UID:$data->{'uuid'}\n"; - print "DTSTAMP:$data->{'entry'}\n"; - print "DTSTART:$data->{'start'}\n" if exists $data->{'start'}; - print "DUE:$data->{'due'}\n" if exists $data->{'due'}; - print "COMPLETED:$data->{'end'}\n" if exists $data->{'end'}; - print "SUMMARY:$data->{'description'}\n"; - print "CLASS:PRIVATE\n"; - print "CATEGORIES:", join (',', @{$data->{'tags'}}), "\n" if exists $data->{'tags'}; - - # Priorities map to a 1-9 scale. - if (exists $data->{'priority'}) - { - print "PRIORITY:", ($data->{'priority'} eq 'H' ? '1' : - $data->{'priority'} eq 'M' ? '5' : - '9'), "\n"; - } - - # Status maps differently. - my $status = $data->{'status'}; - if ($status eq 'pending' || $status eq 'waiting') - { - print "STATUS:", (exists $data->{'start'} ? 'IN-PROCESS' : 'NEEDS-ACTION'), "\n"; - } - elsif ($status eq 'completed') - { - print "STATUS:COMPLETED\n"; - } - elsif ($status eq 'deleted') - { - print "STATUS:CANCELLED\n"; - } - - # Annotations become comments. - if (exists $data->{'annotations'}) - { - print "COMMENT:$_->{'description'}\n" for @{$data->{'annotations'}}; - } - - print "END:VTODO\n"; -} - -print "END:VCALENDAR\n"; -exit 0; - -################################################################################ - diff -Nru task-2.4.4+dfsg/scripts/add-ons/export-sql.py task-2.5.0+dfsg/scripts/add-ons/export-sql.py --- task-2.4.4+dfsg/scripts/add-ons/export-sql.py 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/scripts/add-ons/export-sql.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,170 +0,0 @@ -#! /usr/bin/python -############################################################################### -# -# 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 -# -############################################################################### -""" -export-sql.py -- Export the taskwarrior database as a series of SQL commands. - -Example usage:: - - $ PYTHONIOENCODING=UTF-8 ./export-sql.py | sqlite3 mytasks.db - $ /usr/bin/sqlite3 mytasks.db "select * from annotations;" - -This script has only been tested with sqlite3, but in theory, it could be -easily modified to supported mysql, postgres or whatever you choose. - -Author: Ralph Bean -""" - -import sys -import commands -import json - -from datetime import datetime - -# Note that you may want to modify the field sizes to suit your usage. -table_definitions = """ -CREATE TABLE tasks ( - uuid VARCHAR(255) NOT NULL, - description VARCHAR(255) NOT NULL, - entry DATETIME NOT NULL, - end DATETIME, - priority VARCHAR(32), - project VARCHAR(32), - status VARCHAR(32), - PRIMARY KEY (uuid) -); - -CREATE TABLE annotations ( - uuid VARCHAR(255) NOT NULL, - description VARCHAR(255) NOT NULL, - entry DATETIME NOT NULL, - FOREIGN KEY(uuid) REFERENCES tasks(uuid) -); -""" - - -replacements = { - '"': '&dquot;', - "'": '"', - '[': '&open;', - ']': '&close;', - '/': '\\/', -} - - -def escape(s): - """ Escape a string in the taskwarrior style """ - - for unsafe, safe in replacements.iteritems(): - s = s.replace(unsafe, safe) - return s - - -# A lookup table for how to convert various values by type to SQL -conversion_lookup = { - # Tack on an extra set of quotes - unicode: lambda v: "'%s'" % escape(v), - # Do the same as for unicode - str: lambda v: convert(unicode(v)), - # Convert to ISO format and do the same as for unicode - datetime: lambda v: convert(v.isoformat(' ')), - # Replace python None with SQL NULL - type(None): lambda v: 'NULL', -} - -# Compose a value with its corresponding function in conversion_lookup -convert = lambda v: conversion_lookup.get(type(v), lambda v: v)(v) - - -def parse_datetime(task): - """ Parse the datetime strings given to us by `task export` """ - - for key in ['entry', 'end']: - if key in task: - task[key] = datetime.strptime(task[key], "%Y%m%dT%H%M%SZ") - return task - - -def to_sql(task): - """ Create a list of SQL INSERT statements out of a task python dict """ - - def make_annotation(annot): - """ Create a list of SQL INSERT statements for an annotation """ - - annot['uuid'] = task['uuid'] - template = "{uuid}, {description}, {entry}" - annot = dict(zip(annot.keys(), map(convert, annot.values()))) - values = template.format(**annot) - return "INSERT INTO \"annotations\" VALUES(%s)" % values - - template = u"{uuid}, {description}, {entry}, {end}, " + \ - u"{priority}, {project}, {status}" - - nullables = ['end', 'priority', 'project', 'status'] - defaults = dict([(key, None) for key in nullables]) - defaults['annotations'] = [] - defaults.update(task) - - defaults = dict(zip(defaults.keys(), map(convert, defaults.values()))) - - values = template.format(**defaults) - annotations = map(make_annotation, defaults['annotations']) - - return ["INSERT INTO \"tasks\" VALUES(%s)" % values] + annotations - - -def main(): - """ Return a list of SQL statements. """ - - # Use the taskwarrior 2.0+ export command to filter and return JSON - command = "task rc.verbose=nothing rc.json.array=yes " + " ".join(sys.argv[1:]) + " export" - - # Load each task from json to a python dict - tasks = json.loads(commands.getoutput(command)) - - # Mangle datetime strings into python datetime objects - tasks = map(parse_datetime, tasks) - - # Produce formatted SQL statements for each task - inserts = sum(map(to_sql, tasks), []) - - return inserts - - -if __name__ == '__main__': - # Get the INSERT statements - lines = main() - - # Combine them with semicolons - sql = table_definitions + ";\n".join(lines) + ';' - - # Print them out, decorated with sqlite3 trappings - print u""" -BEGIN TRANSACTION; -{sql} -COMMIT;""".format(sql=sql) - -############################################################################### diff -Nru task-2.4.4+dfsg/scripts/add-ons/export-tsv.pl task-2.5.0+dfsg/scripts/add-ons/export-tsv.pl --- task-2.4.4+dfsg/scripts/add-ons/export-tsv.pl 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/scripts/add-ons/export-tsv.pl 1970-01-01 00:00:00.000000000 +0000 @@ -1,82 +0,0 @@ -#! /usr/bin/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; - -# Give a nice error if the (non-standard) JSON module is not installed. -eval "use JSON"; -if ($@) -{ - print "Error: You need to install the JSON Perl module.\n"; - exit 1; -} - -# Use the taskwarrior 2.0+ export command to filter and return JSON -my $command = join (' ', ("env PATH=$ENV{PATH} task rc.verbose=nothing rc.json.array=no export", @ARGV)); -if ($command =~ /No matches/) -{ - printf STDERR $command; - exit 1; -} - -# Generate output. -print "uuid\tstatus\ttags\tentry\tstart\tdue\trecur\tend\tproject\t", - "priority\tfg\tbg\tdescription\n"; - -for my $task (split "\n", qx{$command}) -{ - my $data = from_json ($task); - - print "$data->{'uuid'}\t", - "$data->{'status'}\t", - (exists $data->{'tags'} ? join (' ', @{$data->{'tags'}}) : ''), "\t", - "$data->{'entry'}\t", - ($data->{'start'} || ''), "\t", - ($data->{'due'} || ''), "\t", - ($data->{'recur'} || ''), "\t", - ($data->{'end'} || ''), "\t", - ($data->{'project'} || ''), "\t", - ($data->{'priority'} || ''), "\t", - ($data->{'fg'} || ''), "\t", - ($data->{'bg'} || ''), "\t", - "$data->{'description'}", - "\n"; - - # Note that this format ignores: - # wait - # until - # annotations - # mask - # imask - # UDAs -} - -exit 0; - -################################################################################ - diff -Nru task-2.4.4+dfsg/scripts/add-ons/export-xml.pl task-2.5.0+dfsg/scripts/add-ons/export-xml.pl --- task-2.4.4+dfsg/scripts/add-ons/export-xml.pl 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/scripts/add-ons/export-xml.pl 1970-01-01 00:00:00.000000000 +0000 @@ -1,85 +0,0 @@ -#! /usr/bin/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; - -# Give a nice error if the (non-standard) JSON module is not installed. -eval "use JSON"; -if ($@) -{ - print "Error: You need to install the JSON Perl module.\n"; - exit 1; -} - -# Use the taskwarrior 2.0+ export command to filter and return JSON -my $command = join (' ', ("env PATH=$ENV{PATH} task rc.verbose=nothing rc.json.array=no export", @ARGV)); -if ($command =~ /No matches/) -{ - printf STDERR $command; - exit 1; -} - -# Generate output. -print "\n"; -for my $task (split "\n", qx{$command}) -{ - my $data = from_json ($task); - - print " \n"; - for my $key (keys %$data) - { - if ($key eq 'annotations') - { - print " \n"; - for my $anno (@{$data->{$key}}) - { - print " \n"; - print " <$_>$anno->{$_}\n" for keys %$anno; - print " \n"; - } - print " \n"; - } - elsif ($key eq 'tags') - { - print " \n"; - print " $_\n" for @{$data->{'tags'}}; - print " \n"; - } - else - { - print " <$key>$data->{$key}\n"; - } - } - print " \n"; -} - -print "\n"; -exit 0; - -################################################################################ - diff -Nru task-2.4.4+dfsg/scripts/add-ons/export-xml.py task-2.5.0+dfsg/scripts/add-ons/export-xml.py --- task-2.4.4+dfsg/scripts/add-ons/export-xml.py 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/scripts/add-ons/export-xml.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -#! /usr/bin/python -################################################################################ -## -## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. -## -## Permission is hereby granted, free of charge, to any person obtaining a copy -## of this software and associated documentation files (the "Software"), to deal -## in the Software without restriction, including without limitation the rights -## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -## copies of the Software, and to permit persons to whom the Software is -## furnished to do so, subject to the following conditions: -## -## The above copyright notice and this permission notice shall be included -## in all copies or substantial portions of the Software. -## -## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -## SOFTWARE. -## -## http://www.opensource.org/licenses/mit-license.php -## -################################################################################ - -import sys -import commands -import json - -# Use the taskwarrior 2.0+ export command to filter and return JSON -command = "/usr/local/bin/task rc.verbose=nothing rc.json.array=no export " + " ".join (sys.argv[1:]) - -# Generate output. -print "" -for task in commands.getoutput (command).split (",\n"): - data = json.loads (task) - print " " - for name,value in data.items (): - if name == "annotations": - print " " - for anno in value: - print " " - for name,value in anno.items (): - print " <{0}>{1}".format (name, value) - print " " - print " " - elif name == "tags": - print " " - for tag in value: - print " {0}".format (tag) - print " " - else: - print " <{0}>{1}".format (name, value) - print " " -print "" -sys.exit (0) - -################################################################################ - diff -Nru task-2.4.4+dfsg/scripts/add-ons/export-xml.rb task-2.5.0+dfsg/scripts/add-ons/export-xml.rb --- task-2.4.4+dfsg/scripts/add-ons/export-xml.rb 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/scripts/add-ons/export-xml.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ -#! /usr/bin/ruby -################################################################################ -## -## 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 -## -################################################################################ - -require 'rubygems' -require 'json' - -# Use the taskwarrior 2.0+ export command to filter and return JSON -lines = IO.popen("/usr/local/bin/task rc.verbose=nothing rc.json.array=no export " + ARGV.join(" ")).readlines - -# Generate output. -print "\n" -lines.each do |line| - data = JSON.parse(line) - print " \n" - data.each do |key,value| - if key == "annotations" - print " \n" - value.each do |anno| - print " \n" - anno.each do |key,value| - print " <#{key}>#{value}\n" - end - print " \n" - end - print " \n" - elsif key == "tags" - print " \n" - value.each do |tag| - print " #{tag}\n" - end - print " \n" - else - print " <#{key}>#{value}\n" - end - end - print " \n" -end -print "\n" -exit 0 - -################################################################################ - diff -Nru task-2.4.4+dfsg/scripts/add-ons/export-yad.pl task-2.5.0+dfsg/scripts/add-ons/export-yad.pl --- task-2.4.4+dfsg/scripts/add-ons/export-yad.pl 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/scripts/add-ons/export-yad.pl 1970-01-01 00:00:00.000000000 +0000 @@ -1,81 +0,0 @@ -#! /usr/bin/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; - -# Give a nice error if the (non-standard) JSON module is not installed. -eval "use JSON"; -if ($@) -{ - print "Error: You need to install the JSON Perl module.\n"; - exit 1; -} - -# Use the taskwarrior 2.0+ export command to filter and return JSON -my $command = join (' ', ("env PATH=$ENV{PATH} task rc.verbose=nothing rc.json.array=no export", @ARGV)); -if ($command =~ /No matches/) -{ - printf STDERR $command; - exit 1; -} - -# Generate output. -print "'uuid','status','tags','entry','start','due','recur','end','project',", - "'priority','fg','bg','description'\n"; - -for my $task (split "\n", qx{$command}) -{ - my $data = from_json ($task); - - print "'$data->{'uuid'}',", - "'$data->{'status'}',", - "'", (exists $data->{'tags'} ? join (' ', @{$data->{'tags'}}) : ''), "',", - "'$data->{'entry'}',", - "'", ($data->{'start'} || ''), "',", - "'", ($data->{'due'} || ''), "',", - "'", ($data->{'recur'} || ''), "',", - "'", ($data->{'end'} || ''), "',", - "'", ($data->{'project'} || ''), "',", - "'", ($data->{'priority'} || ''), "',", - "'", ($data->{'fg'} || ''), "',", - "'", ($data->{'bg'} || ''), "',", - "'$data->{'description'}'", - "\n"; - - # Note that this format ignores: - # wait - # until - # annotations - # mask - # imask -} - -exit 0; - -################################################################################ - diff -Nru task-2.4.4+dfsg/scripts/add-ons/export-yaml.pl task-2.5.0+dfsg/scripts/add-ons/export-yaml.pl --- task-2.4.4+dfsg/scripts/add-ons/export-yaml.pl 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/scripts/add-ons/export-yaml.pl 1970-01-01 00:00:00.000000000 +0000 @@ -1,79 +0,0 @@ -#! /usr/bin/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; - -# Give a nice error if the (non-standard) JSON module is not installed. -eval "use JSON"; -if ($@) -{ - print "Error: You need to install the JSON Perl module.\n"; - exit 1; -} - -# Generate output. -print "%YAML 1.1\n", - "---\n"; - -while (my $json = <>) -{ - $json =~ s/^\[//; - $json =~ s/\]$//; - $json =~ s/,$//; - next if $json eq ''; - - my $data = from_json ($json); - - print " task:\n"; - for my $key (sort keys %$data) - { - if ($key eq 'annotations') - { - print " annotations:\n"; - for my $anno (@{$data->{$key}}) - { - print " annotation:\n"; - print " $_: $anno->{$_}\n" for keys %$anno; - } - } - elsif ($key eq 'tags') - { - print " tags: ", join (',', @{$data->{'tags'}}), "\n"; - } - else - { - print " $key: $data->{$key}\n"; - } - } -} - -print "...\n"; -exit 0; - -################################################################################ - diff -Nru task-2.4.4+dfsg/scripts/add-ons/import-todo.sh.pl task-2.5.0+dfsg/scripts/add-ons/import-todo.sh.pl --- task-2.4.4+dfsg/scripts/add-ons/import-todo.sh.pl 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/scripts/add-ons/import-todo.sh.pl 1970-01-01 00:00:00.000000000 +0000 @@ -1,162 +0,0 @@ -#! /usr/bin/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 Time::Local; - -# Priority mappings. -my %priority_map = ( - 'a' => 'H', 'b' => 'M', 'c' => 'L', 'd' => 'L', 'e' => 'L', 'f' => 'L', - 'g' => 'L', 'h' => 'L', 'i' => 'L', 'j' => 'L', 'k' => 'L', 'l' => 'L', - 'm' => 'L', 'n' => 'L', 'o' => 'L', 'p' => 'L', 'q' => 'L', 'r' => 'L', - 's' => 'L', 't' => 'L', 'u' => 'L', 'v' => 'L', 'w' => 'L', 'x' => 'L', - 'y' => 'L', 'z' => 'L'); - -my @tasks; -while (my $todo = <>) -{ - my $status = 'pending'; - my $priority = ''; - my $entry = ''; - my $end = ''; - my @projects; - my @contexts; - my $description = ''; - my $due = ''; - - # pending + pri + entry - if ($todo =~ /^\(([A-Z])\)\s(\d{4}-\d{2}-\d{2})\s(.+)$/i) - { - ($status, $priority, $entry, $description) = ('pending', $1, epoch ($2), $3); - } - - # pending + pri - elsif ($todo =~ /^\(([A-Z])\)\s(.+)$/i) - { - ($status, $priority, $description) = ('pending', $1, $2); - } - - # pending + entry - elsif ($todo =~ /^(\d{4}-\d{2}-\d{2})\s(.+)$/i) - { - ($status, $entry, $description) = ('pending', epoch ($1), $2); - } - - # done + end + entry - elsif ($todo =~ /^x\s(\d{4}-\d{2}-\d{2})\s(\d{4}-\d{2}-\d{2})\s(.+)$/i) - { - ($status, $end, $entry, $description) = ('completed', epoch ($1), epoch ($2), $3); - } - - # done + end - elsif ($todo =~ /^x\s(\d{4}-\d{2}-\d{2})\s(.+)$/i) - { - ($status, $end, $description) = ('completed', epoch ($1), $2); - } - - # done - elsif ($todo =~ /^x\s(.+)$/i) - { - ($status, $description) = ('completed', $1); - } - - # pending - elsif ($todo =~ /^(.+)$/i) - { - ($status, $description) = ('pending', $1); - } - - # Project - @projects = $description =~ /\+(\S+)/ig; - - # Contexts - @contexts = $description =~ /\@(\S+)/ig; - - # Due - $due = epoch ($1) if $todo =~ /\sdue:(\d{4}-\d{2}-\d{2})/i; - - # Map priorities - $priority = $priority_map{lc $priority} if $priority ne ''; - - # Pick first project - my $first_project = shift @projects; - - # Compose the JSON - my $json = ''; - $json .= "{\"status\":\"${status}\""; - $json .= ",\"priority\":\"${priority}\"" if defined $priority && $priority ne ''; - $json .= ",\"project\":\"${first_project}\"" if defined $first_project && $first_project ne ''; - $json .= ",\"entry\":\"${entry}\"" if $entry ne ''; - $json .= ",\"end\":\"${end}\"" if $end ne ''; - $json .= ",\"due\":\"${due}\"" if $due ne ''; - - if (@contexts) - { - $json .= ",\"tags\":[" . join (',', map {"\"$_\""} @contexts) . "]"; - } - - $json .= ",\"description\":\"${description}\"}"; - - push @tasks, $json; -} - -print "[\n", join ("\n", @tasks), "\n]\n"; -exit 0; - -################################################################################ -sub epoch -{ - my ($input) = @_; - - my ($y, $m, $d) = $input =~ /(\d{4})-(\d{2})-(\d{2})/; - return timelocal (0, 0, 0, $d, $m-1, $y-1900); -} - -################################################################################ - -__DATA__ -(A) Thank Mom for the meatballs @phone -(B) Schedule Goodwill pickup +GarageSale @phone -Post signs around the neighborhood +GarageSale -@GroceryStore Eskimo pies -(A) Thank Mom for the meatballs @phone -(B) Schedule Goodwill pickup +GarageSale @phone -(B) Schedule Goodwill pickup +GarageSale @phone -Post signs around the neighborhood +GarageSale -Really gotta call Mom (A) @phone @someday -(b) Get back to the boss -(B)->Submit TPS report -2011-03-02 Document +TodoTxt task format -(A) 2011-03-02 Call Mom -(A) Call Mom 2011-03-02 -(A) Call Mom +Family +PeaceLoveAndHappiness @iphone @phone -x 2011-03-03 Call Mom -xylophone lesson -X 2012-01-01 Make resolutions -(A) x Find ticket prices -x 2011-03-02 2011-03-01 Review Tim's pull request +TodoTxtTouch @github diff -Nru task-2.4.4+dfsg/scripts/add-ons/import-yaml.pl task-2.5.0+dfsg/scripts/add-ons/import-yaml.pl --- task-2.4.4+dfsg/scripts/add-ons/import-yaml.pl 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/scripts/add-ons/import-yaml.pl 1970-01-01 00:00:00.000000000 +0000 @@ -1,141 +0,0 @@ -#! /usr/bin/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 Time::Local; - -my @tasks; - -my $status = ''; -my $uuid = ''; -my $priority = ''; -my $entry = ''; -my $end = ''; -my $project = ''; -my $tags = ''; -my $description = ''; -my $due = ''; - -my %annotations; -my $mid_anno = 0; -my $anno_entry = ''; -my $anno_desc = ''; - -while (my $yaml = <>) -{ - chomp $yaml; - next if $yaml =~ /\sid:/; - next if $yaml =~ /\sannotations:/; - - if ($yaml =~ /task:|\.\.\./ && $description ne '') - { - # Compose the JSON - my $json = "{\"status\":\"${status}\""; - $json .= ",\"uuid\":\"${uuid}\"" if $uuid ne ''; - $json .= ",\"priority\":\"${priority}\"" if $priority ne ''; - $json .= ",\"project\":\"${project}\"" if $project ne ''; - $json .= ",\"entry\":\"${entry}\"" if $entry ne ''; - $json .= ",\"end\":\"${end}\"" if $end ne ''; - $json .= ",\"due\":\"${due}\"" if $due ne ''; - if ($tags ne '') - { - $tags =~ s/,/","/g; - $json .= ",\"tags\":[\"${tags}\"]"; - } - if (%annotations) - { - $json .= ",\"annotations\":["; - my $pre = ""; - for my $key (sort keys %annotations) { - $json .= "${pre}{\"entry\":\"${key}\",\"description\":\"${annotations{$key}}\"}"; - $pre = ","; - } - $json .= "]"; - } - $json .= ",\"description\":\"${description}\"}"; - - push @tasks, $json; - - $status = $uuid = $priority = $entry = $end = $project = $tags = - $description = $due = $anno_entry = $anno_desc = ''; - $mid_anno = 0; - %annotations = (); - $yaml = ''; - } - else - { - $mid_anno = 1 if $yaml =~ /annotation:/; - $anno_entry = $1 if $mid_anno && $yaml =~ /entry:\s*(\S+)/; - if ($mid_anno) - { - if ($yaml =~ /description:\s*(.+)/) - { - $anno_desc = $1; - $mid_anno = 0; - - $annotations{$anno_entry} = $anno_desc; - } - } - else - { - $entry = $1 if $yaml =~ /entry:\s*(\S+)/; - $description = $1 if $yaml =~ /description:\s*(.+)/; - } - - $status = $1 if $yaml =~ /status:\s*(\S+)/; - $uuid = $1 if $yaml =~ /uuid:\s*(\S+)/; - $priority = $1 if $yaml =~ /priority:\s*(\S+)/; - $project = $1 if $yaml =~ /project:\s*(\S+)/; - $end = $1 if $yaml =~ /end:\s*(\S+)/; - $due = $1 if $yaml =~ /due:\s*(\S+)/; - $tags = $1 if $yaml =~ /tags:\s*(\S+)/; - } -} - -print "[\n", join ("\n", @tasks), "\n]\n"; -exit 0; - -################################################################################ - -__DATA__ -%YAML 1.1 ---- - task: - annotations: - annotation: - entry: 20100706T025311Z - description: Also needs to ignore control codes - description: text.cpp/extractLines needs to calculate string length in a way that supports UTF8 - entry: 20090319T151633Z - id: 9 - project: task-2.0 - status: pending - tags: bug,utf8,next - uuid: 0c4cf066-9413-4862-9dc8-0793f158a649 -... - diff -Nru task-2.4.4+dfsg/scripts/add-ons/README task-2.5.0+dfsg/scripts/add-ons/README --- task-2.4.4+dfsg/scripts/add-ons/README 1970-01-01 00:00:00.000000000 +0000 +++ task-2.5.0+dfsg/scripts/add-ons/README 2015-10-21 21:18:14.000000000 +0000 @@ -0,0 +1,3 @@ +The import/export add-on scripts have been relocated online. Please see: + +https://taskwarrior.org/tools/#exts diff -Nru task-2.4.4+dfsg/scripts/bash/context task-2.5.0+dfsg/scripts/bash/context --- task-2.4.4+dfsg/scripts/bash/context 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/scripts/bash/context 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -#!/bin/bash -# - These filters not modified, as their purpose is for special review -# not dependent on context or focus: -# - report.all.filter -# - report.completed.filter status:completed -# - What is this -FILTER about in my filters? -# - In each filter, we negate a non-existent virtual tag -FILTER that -# doesn't change what the filter matches but does add a recognizable -# marker. This is used later to substitute the filter with a new one when -# it changes. -# - CAUTION: do not add any additional (i.e. non-context, non-focus) material -# after -FILTER in the report filter variables or else it will be lost next -# time the context or focus is changed. -script_path=$(dirname ${0}) -. "${script_path}/task_functions.sh" - -filter_type=$(basename ${0}) -task_config "${filter_type}.current" "${@}" -context=$(task_get context.current) -focus=$(task_get focus.current) -colored_context="$(task_color 'white on red' ${context})" -colored_focus="$(task_color 'white on blue' ${focus})" -filter="${context} ${focus}" - -filter_vars=$(task_vars filter) -filter_vars=${filter_vars/report.all.filter/} -filter_vars=${filter_vars/report.completed.filter/} -for var in ${filter_vars}; do - old_value=$(task_get ${var}) - old_value=${old_value/%-FILTER*/} - task_config ${var} ${old_value} -FILTER ${filter} -done - -task_config "shell.prompt" "${colored_context}:${colored_focus}>" - -echo "Filter applied to reports and add: ${filter}" diff -Nru task-2.4.4+dfsg/scripts/bash/focus task-2.5.0+dfsg/scripts/bash/focus --- task-2.4.4+dfsg/scripts/bash/focus 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/scripts/bash/focus 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -#!/bin/bash -# - These filters not modified, as their purpose is for special review -# not dependent on context or focus: -# - report.all.filter -# - report.completed.filter status:completed -# - What is this -FILTER about in my filters? -# - In each filter, we negate a non-existent virtual tag -FILTER that -# doesn't change what the filter matches but does add a recognizable -# marker. This is used later to substitute the filter with a new one when -# it changes. -# - CAUTION: do not add any additional (i.e. non-context, non-focus) material -# after -FILTER in the report filter variables or else it will be lost next -# time the context or focus is changed. -script_path=$(dirname ${0}) -. "${script_path}/task_functions.sh" - -filter_type=$(basename ${0}) -task_config "${filter_type}.current" "${@}" -context=$(task_get context.current) -focus=$(task_get focus.current) -colored_context="$(task_color 'white on red' ${context})" -colored_focus="$(task_color 'white on blue' ${focus})" -filter="${context} ${focus}" - -filter_vars=$(task_vars filter) -filter_vars=${filter_vars/report.all.filter/} -filter_vars=${filter_vars/report.completed.filter/} -for var in ${filter_vars}; do - old_value=$(task_get ${var}) - old_value=${old_value/%-FILTER*/} - task_config ${var} ${old_value} -FILTER ${filter} -done - -task_config "shell.prompt" "${colored_context}:${colored_focus}>" - -echo "Filter applied to reports and add: ${filter}" diff -Nru task-2.4.4+dfsg/scripts/fish/task.fish task-2.5.0+dfsg/scripts/fish/task.fish --- task-2.4.4+dfsg/scripts/fish/task.fish 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/scripts/fish/task.fish 2015-10-21 21:18:14.000000000 +0000 @@ -55,6 +55,8 @@ # # http://www.opensource.org/licenses/mit-license.php +# NOTE: remember that sed on OS X is different in some aspects. E.g. it does +# not understand \t for tabs. # convinience functions @@ -74,7 +76,7 @@ function __fish.task.zsh set -q argv[2]; and set task_argv $argv[2..-1] - task _zsh$argv[1] $task_argv | sed 's/:/\t/' + task _zsh$argv[1] $task_argv | sed 's/:/ /' end @@ -141,7 +143,7 @@ end function __fish.task.list.attr_name - task _columns | sed 's/$/:\tattribute/g' + task _columns | sed 's/$/: attribute/g' # BUG: doesn't support file completion echo rc end @@ -149,7 +151,7 @@ function __fish.task.list.attr_value set token (commandline -ct | cut -d ':' -f 1 | cut -d '.' -f 1 | __fish.task.token_clean) if test -n $token - set attr_names (__fish.task.list.attr_name | sed 's/:\t/\t/g' | grep '^'$token | cut -d ' ' -f 1) + set attr_names (__fish.task.list.attr_name | sed 's/: / /g' | grep '^'$token | cut -d ' ' -f 1) for attr_name in $attr_names if test -n $attr_name __fish.task.list.attr_value_by_name $attr_name @@ -250,7 +252,7 @@ end function __fish.task.list.task - __fish.task.zsh ids | sed -E 's/^(.*)\t(.*)$/\2\ttask [id = \1]/g' + __fish.task.zsh ids | sed -E 's/^(.*) (.*)$/\2 task [id = \1]/g' end function __fish.task.list diff -Nru task-2.4.4+dfsg/scripts/hooks/on-exit task-2.5.0+dfsg/scripts/hooks/on-exit --- task-2.4.4+dfsg/scripts/hooks/on-exit 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/scripts/hooks/on-exit 2015-10-21 21:18:14.000000000 +0000 @@ -1,7 +1,10 @@ #!/bin/sh # The on-exit event is triggered once, after all processing is complete. -# This hooks script has no effect on processing. +# This hook script has no effect on processing. + +# Input: +# - line of JSON for each modified task # Output: # - Optional feedback/error. diff -Nru task-2.4.4+dfsg/scripts/vim/syntax/taskrc.vim task-2.5.0+dfsg/scripts/vim/syntax/taskrc.vim --- task-2.4.4+dfsg/scripts/vim/syntax/taskrc.vim 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/scripts/vim/syntax/taskrc.vim 2015-10-21 21:18:14.000000000 +0000 @@ -151,7 +151,6 @@ syn match taskrcGoodKey '^\s*\Vurgency.blocked.coefficient='he=e-1 syn match taskrcGoodKey '^\s*\Vurgency.blocking.coefficient='he=e-1 syn match taskrcGoodKey '^\s*\Vurgency.due.coefficient='he=e-1 -syn match taskrcGoodKey '^\s*\Vurgency.inherit.coefficient='he=e-1 syn match taskrcGoodKey '^\s*\Vurgency.next.coefficient='he=e-1 syn match taskrcGoodKey '^\s*\Vurgency.uda.priority.H.coefficient='he=e-1 syn match taskrcGoodKey '^\s*\Vurgency.uda.priority.M.coefficient='he=e-1 @@ -161,6 +160,7 @@ syn match taskrcGoodKey '^\s*\Vurgency.tags.coefficient='he=e-1 syn match taskrcGoodKey '^\s*\Vurgency.uda.\S\{-}.coefficient='he=e-1 syn match taskrcGoodKey '^\s*\Vurgency.waiting.coefficient='he=e-1 +syn match taskrcGoodKey '^\s*\Vurgency.inherit='he=e-1 syn match taskrcGoodKey '^\s*\Vverbose='he=e-1 syn match taskrcGoodKey '^\s*\Vweekstart='he=e-1 syn match taskrcGoodKey '^\s*\Vxterm.title='he=e-1 diff -Nru task-2.4.4+dfsg/scripts/zsh/_task task-2.5.0+dfsg/scripts/zsh/_task --- task-2.4.4+dfsg/scripts/zsh/_task 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/scripts/zsh/_task 2015-10-21 21:18:14.000000000 +0000 @@ -31,34 +31,34 @@ _task_config=($(task _config)) _task_columns=($(task _columns)) _task_modifiers=( - 'before' \ - 'after' \ - 'none' \ - 'any' \ - 'is' \ - 'isnt' \ - 'has' \ - 'hasnt' \ - 'startswith' \ - 'endswith' \ - 'word' \ - 'noword' + 'before' \ + 'after' \ + 'none' \ + 'any' \ + 'is' \ + 'isnt' \ + 'has' \ + 'hasnt' \ + 'startswith' \ + 'endswith' \ + 'word' \ + 'noword' ) _task_conjunctions=( - 'and' \ - 'or' \ - 'xor' \ - '\)' \ - '\(' \ - '<' \ - '<=' \ - '=' \ - '!=' \ - '>=' \ - '>' + 'and' \ + 'or' \ + 'xor' \ + '\)' \ + '\(' \ + '<' \ + '<=' \ + '=' \ + '!=' \ + '>=' \ + '>' ) _task_cmds=($(task _commands; task _aliases)) -_task_zshcmds=( ${(f)"$(task _zshcommands)"} ) +_task_zshcmds=( ${(f)"$(task _zshcommands)"} sentinel:sentinel:sentinel ) _task_aliases=($(task _aliases)) @@ -74,42 +74,42 @@ # priorities local -a task_priorities _regex_words values 'task priorities' \ - 'H:High' \ - 'M:Middle' \ - 'L:Low' + 'H:High' \ + 'M:Middle' \ + 'L:Low' task_priorities=("$reply[@]") # projects local -a task_projects task_projects=( - /"$word"/ - ":values:task projects:compadd -a _task_projects" + /"$word"/ + ":values:task projects:compadd -a _task_projects" ) local -a _task_dates _regex_words values 'task dates' \ - 'tod*ay:Today' \ - 'yes*terday:Yesterday' \ - 'tom*orrow:Tomorrow' \ - 'sow:Start of week' \ - 'soww:Start of work week' \ - 'socw:Start of calendar week' \ - 'som:Start of month' \ - 'soq:Start of quarter' \ - 'soy:Start of year' \ - 'eow:End of week' \ - 'eoww:End of work week' \ - 'eocw:End of calendar week' \ - 'eom:End of month' \ - 'eoq:End of quarter' \ - 'eoy:End of year' \ - 'mon:Monday' \ - 'tue:Tuesday'\ - 'wed:Wednesday' \ - 'thu:Thursday' \ - 'fri:Friday' \ - 'sat:Saturday' \ - 'sun:Sunday' \ + 'tod*ay:Today' \ + 'yes*terday:Yesterday' \ + 'tom*orrow:Tomorrow' \ + 'sow:Start of week' \ + 'soww:Start of work week' \ + 'socw:Start of calendar week' \ + 'som:Start of month' \ + 'soq:Start of quarter' \ + 'soy:Start of year' \ + 'eow:End of week' \ + 'eoww:End of work week' \ + 'eocw:End of calendar week' \ + 'eom:End of month' \ + 'eoq:End of quarter' \ + 'eoy:End of year' \ + 'mon:Monday' \ + 'tue:Tuesday'\ + 'wed:Wednesday' \ + 'thu:Thursday' \ + 'fri:Friday' \ + 'sat:Saturday' \ + 'sun:Sunday' \ 'good*friday:Good Friday' \ 'easter:Easter' \ 'eastermonday:Easter Monday' \ @@ -123,19 +123,19 @@ local -a _task_reldates _regex_words values 'task reldates' \ - 'hrs:n hours' \ - 'day:n days' \ - '1st:first' \ - '2nd:second' \ - '3rd:third' \ - 'th:4th, 5th, etc.' \ - 'wks:weeks' + 'hrs:n hours' \ + 'day:n days' \ + '1st:first' \ + '2nd:second' \ + '3rd:third' \ + 'th:4th, 5th, etc.' \ + 'wks:weeks' _task_reldates=("$reply[@]") task_dates=( - \( "$_task_dates[@]" \| + \( "$_task_dates[@]" \| \( /$'[0-9][0-9]#'/- \( "$_task_reldates[@]" \) \) - \) + \) ) local -a task_zshids @@ -143,61 +143,61 @@ task_zshids=("$reply[@]") _regex_words values 'task frequencies' \ - 'daily:Every day' \ - 'day:Every day' \ - 'weekdays:Every day skipping weekend days' \ - 'weekly:Every week' \ - 'biweekly:Every two weeks' \ - 'fortnight:Every two weeks' \ + 'daily:Every day' \ + 'day:Every day' \ + 'weekdays:Every day skipping weekend days' \ + 'weekly:Every week' \ + 'biweekly:Every two weeks' \ + 'fortnight:Every two weeks' \ 'monthly:Every month' \ - 'quarterly:Every three months' \ - 'semiannual:Every six months' \ - 'annual:Every year' \ - 'yearly:Every year' \ - 'biannual:Every two years' \ - 'biyearly:Every two years' + 'quarterly:Every three months' \ + 'semiannual:Every six months' \ + 'annual:Every year' \ + 'yearly:Every year' \ + 'biannual:Every two years' \ + 'biyearly:Every two years' _task_freqs=("$reply[@]") local -a _task_frequencies _regex_words values 'task frequencies' \ - 'd:days' \ - 'w:weeks' \ - 'q:quarters' \ - 'y:years' + 'd:days' \ + 'w:weeks' \ + 'q:quarters' \ + 'y:years' _task_frequencies=("$reply[@]") task_freqs=( - \( "$_task_freqs[@]" \| + \( "$_task_freqs[@]" \| \( /$'[0-9][0-9]#'/- \( "$_task_frequencies[@]" \) \) - \) + \) ) # attributes local -a task_attributes _regex_words -t ':' default 'task attributes' \ - 'des*cription:Task description text' \ - 'status:Status of task - pending, completed, deleted, waiting' \ - 'pro*ject:Project name:$task_projects' \ - 'pri*ority:priority:$task_priorities' \ - 'du*e:Due date:$task_dates' \ - 're*cur:Recurrence frequency:$task_freqs' \ - 'un*til:Expiration date:$task_dates' \ - 'li*mit:Desired number of rows in report' \ - 'wa*it:Date until task becomes pending:$task_dates' \ - 'ent*ry:Date task was created:$task_dates' \ - 'end:Date task was completed/deleted:$task_dates' \ - 'st*art:Date task was started:$task_dates' \ - 'sc*heduled:Date task is scheduled to start:$task_dates' \ - 'dep*ends:Other tasks that this task depends upon:$task_zshids' + 'des*cription:Task description text' \ + 'status:Status of task - pending, completed, deleted, waiting' \ + 'pro*ject:Project name:$task_projects' \ + 'pri*ority:priority:$task_priorities' \ + 'du*e:Due date:$task_dates' \ + 're*cur:Recurrence frequency:$task_freqs' \ + 'un*til:Expiration date:$task_dates' \ + 'li*mit:Desired number of rows in report' \ + 'wa*it:Date until task becomes pending:$task_dates' \ + 'ent*ry:Date task was created:$task_dates' \ + 'end:Date task was completed/deleted:$task_dates' \ + 'st*art:Date task was started:$task_dates' \ + 'sc*heduled:Date task is scheduled to start:$task_dates' \ + 'dep*ends:Other tasks that this task depends upon:$task_zshids' task_attributes=("$reply[@]") args=( - \( "$task_attributes[@]" \| - \( /'(project|description|status|entry|end|start|scheduled|depends|due|wait|recur|priority|until|limit).'/- \( /$'[^:]#:'/ ":default:modifiers:compadd -S ':' -a _task_modifiers" \) \) \| - \( /'(rc).'/- \( /$'[^:]#:'/ ":arguments:config:compadd -S ':' -a _task_config" \) \) \| - \( /'(+|-)'/- \( /"$word"/ ":values:remove tag:compadd -a _task_tags" \) \) \| - \( /"$word"/ \) - \) \# + \( "$task_attributes[@]" \| + \( /'(project|description|status|entry|end|start|scheduled|depends|due|wait|recur|priority|until|limit).'/- \( /$'[^:]#:'/ ":default:modifiers:compadd -S ':' -a _task_modifiers" \) \) \| + \( /'(rc).'/- \( /$'[^:]#:'/ ":arguments:config:compadd -S ':' -a _task_config" \) \) \| + \( /'(+|-)'/- \( /"$word"/ ":values:remove tag:compadd -a _task_tags" \) \) \| + \( /"$word"/ \) + \) \# ) _regex_arguments _task_attributes "${args[@]}" @@ -206,22 +206,50 @@ # filter completion (( $+functions[_task_filter] )) || _task_filter() { - _task_attributes "$@" + _task_attributes "$@" - # TODO complete conjunctions only if the previous word is a filter expression, i.e. attribute, ID, any non-command - _describe -t default 'task conjunctions' _task_conjunctions + # TODO complete conjunctions only if the previous word is a filter expression, i.e. attribute, ID, any non-command + _describe -t default 'task conjunctions' _task_conjunctions } # execute completion (( $+functions[_task_execute] )) || _task_execute() { - _files + _files } # id-only completion (( $+functions[_task_id] )) || _task_id() { - _describe -t values 'task IDs' _task_zshids + _describe -t values 'task IDs' _task_zshids +} + +# subcommand-only function +(( $+functions[_task_subcommands] )) || +_task_subcommands() { + local -a subcommands + local _zshcmd + local cmd category desc + local lastcategory='' + # The list is sorted by category, in the right order. + for _zshcmd in "$_task_zshcmds[@]"; do + # Parse out the three fields + cmd=${_zshcmd%%:*} + category=${${_zshcmd#*:}%%:*} + desc=${_zshcmd#*:*:} + + # Present each category as soon as the first entry in the *next* category + # is seen. + if [[ $category != $lastcategory && -n $lastcategory ]]; then + _describe -t ${lastcategory}-commands "task ${lastcategory} command" subcommands + subcommands=() + fi + + # Log the subcommand; we will process it in some future iteration. + subcommands+=( "$cmd:$desc" ) + + lastcategory=$category + done } ## first level completion => task sub-command completion @@ -229,26 +257,28 @@ _task_default() { local cmd ret=1 - integer i=1 - while (( i < $#words )) - do - cmd="${_task_cmds[(r)$words[$i]]}" - if (( $#cmd )); then - _call_function ret _task_${cmd} || - _call_function ret _task_filter || - _message "No command remaining." - return ret - fi - (( i++ )) - done - - # update IDs - _task_zshids=( ${(f)"$(task _zshids)"} ) - - _describe -t commands 'task command' _task_zshcmds - _describe -t values 'task IDs' _task_zshids - _describe -t aliases 'task aliases' _task_aliases - _call_function ret _task_filter + integer i=1 + while (( i < $#words )) + do + cmd="${_task_cmds[(r)$words[$i]]}" + if (( $#cmd )); then + _call_function ret _task_${cmd} || + _call_function ret _task_filter || + _message "No command remaining." + return ret + fi + (( i++ )) + done + + # update IDs + _task_zshids=( ${(f)"$(task _zshids)"} ) + + _task_subcommands + _describe -t tasks 'task IDs' _task_zshids + _describe -t aliases 'task aliases' _task_aliases + _call_function ret _task_filter - return ret + return ret } + +_task "$@" diff -Nru task-2.4.4+dfsg/src/args.cpp task-2.5.0+dfsg/src/args.cpp --- task-2.4.4+dfsg/src/args.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/args.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,223 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// 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 -#include -#include - -Context context; - -//////////////////////////////////////////////////////////////////////////////// -int main (int argc, const char** argv) -{ - try - { - CLI cli; - cli.initialize (argc, argv); - cli.findOverrides (); - - // Read-only commands. - cli.entity ("cmd", "active"); cli.entity ("readcmd", "active"); - cli.entity ("cmd", "all"); cli.entity ("readcmd", "all"); - cli.entity ("cmd", "blocked"); cli.entity ("readcmd", "blocked"); - cli.entity ("cmd", "blocking"); cli.entity ("readcmd", "blocking"); - cli.entity ("cmd", "burndown.daily"); cli.entity ("readcmd", "burndown.daily"); - cli.entity ("cmd", "burndown.monthly"); cli.entity ("readcmd", "burndown.monthly"); - cli.entity ("cmd", "burndown.weekly"); cli.entity ("readcmd", "burndown.weekly"); - cli.entity ("cmd", "calc"); cli.entity ("readcmd", "calc"); - cli.entity ("cmd", "calendar"); cli.entity ("readcmd", "calendar"); - cli.entity ("cmd", "colors"); cli.entity ("readcmd", "colors"); - cli.entity ("cmd", "columns"); cli.entity ("readcmd", "columns"); - cli.entity ("cmd", "completed"); cli.entity ("readcmd", "completed"); - cli.entity ("cmd", "config"); cli.entity ("readcmd", "config"); - cli.entity ("cmd", "count"); cli.entity ("readcmd", "count"); - cli.entity ("cmd", "diagnostics"); cli.entity ("readcmd", "diagnostics"); - cli.entity ("cmd", "execute"); cli.entity ("readcmd", "execute"); - cli.entity ("cmd", "export"); cli.entity ("readcmd", "export"); - cli.entity ("cmd", "ghistory.annual"); cli.entity ("readcmd", "ghistory.annual"); - cli.entity ("cmd", "ghistory.monthly"); cli.entity ("readcmd", "ghistory.monthly"); - cli.entity ("cmd", "help"); cli.entity ("readcmd", "help"); - cli.entity ("cmd", "history.annual"); cli.entity ("readcmd", "history.annual"); - cli.entity ("cmd", "history.monthly"); cli.entity ("readcmd", "history.monthly"); - cli.entity ("cmd", "ids"); cli.entity ("readcmd", "ids"); - cli.entity ("cmd", "information"); cli.entity ("readcmd", "information"); - cli.entity ("cmd", "list"); cli.entity ("readcmd", "list"); - cli.entity ("cmd", "logo"); cli.entity ("readcmd", "logo"); - cli.entity ("cmd", "long"); cli.entity ("readcmd", "long"); - cli.entity ("cmd", "ls"); cli.entity ("readcmd", "ls"); - cli.entity ("cmd", "minimal"); cli.entity ("readcmd", "minimal"); - cli.entity ("cmd", "newest"); cli.entity ("readcmd", "newest"); - cli.entity ("cmd", "next"); cli.entity ("readcmd", "next"); - cli.entity ("cmd", "oldest"); cli.entity ("readcmd", "oldest"); - cli.entity ("cmd", "overdue"); cli.entity ("readcmd", "overdue"); - cli.entity ("cmd", "projects"); cli.entity ("readcmd", "projects"); - cli.entity ("cmd", "ready"); cli.entity ("readcmd", "ready"); - cli.entity ("cmd", "recurring"); cli.entity ("readcmd", "recurring"); - cli.entity ("cmd", "reports"); cli.entity ("readcmd", "reports"); - cli.entity ("cmd", "show"); cli.entity ("readcmd", "show"); - cli.entity ("cmd", "stats"); cli.entity ("readcmd", "stats"); - cli.entity ("cmd", "summary"); cli.entity ("readcmd", "summary"); - cli.entity ("cmd", "tags"); cli.entity ("readcmd", "tags"); - cli.entity ("cmd", "timesheet"); cli.entity ("readcmd", "timesheet"); - cli.entity ("cmd", "udas"); cli.entity ("readcmd", "udas"); - cli.entity ("cmd", "unblocked"); cli.entity ("readcmd", "unblocked"); - cli.entity ("cmd", "uuids"); cli.entity ("readcmd", "uuids"); - cli.entity ("cmd", "version"); cli.entity ("readcmd", "version"); - cli.entity ("cmd", "waiting"); cli.entity ("readcmd", "waiting"); - - // Write commands. - cli.entity ("cmd", "add"); cli.entity ("writecmd", "add"); - cli.entity ("cmd", "annotate"); cli.entity ("writecmd", "annotate"); - cli.entity ("cmd", "append"); cli.entity ("writecmd", "append"); - cli.entity ("cmd", "delete"); cli.entity ("writecmd", "delete"); - cli.entity ("cmd", "denotate"); cli.entity ("writecmd", "denotate"); - cli.entity ("cmd", "done"); cli.entity ("writecmd", "done"); - cli.entity ("cmd", "duplicate"); cli.entity ("writecmd", "duplicate"); - cli.entity ("cmd", "edit"); cli.entity ("writecmd", "edit"); - cli.entity ("cmd", "import"); cli.entity ("writecmd", "import"); - cli.entity ("cmd", "log"); cli.entity ("writecmd", "log"); - cli.entity ("cmd", "modify"); cli.entity ("writecmd", "modify"); - cli.entity ("cmd", "prepend"); cli.entity ("writecmd", "prepend"); - cli.entity ("cmd", "start"); cli.entity ("writecmd", "start"); - cli.entity ("cmd", "stop"); cli.entity ("writecmd", "stop"); - cli.entity ("cmd", "synchronize"); cli.entity ("writecmd", "synchronize"); - cli.entity ("cmd", "undo"); cli.entity ("writecmd", "undo"); - - // Helper commands. - cli.entity ("cmd", "_aliases"); cli.entity ("readcmd", "_aliases"); cli.entity ("helper", "_aliases"); - cli.entity ("cmd", "_columns"); cli.entity ("readcmd", "_columns"); cli.entity ("helper", "_columns"); - cli.entity ("cmd", "_commands"); cli.entity ("readcmd", "_commands"); cli.entity ("helper", "_commands"); - cli.entity ("cmd", "_config"); cli.entity ("readcmd", "_config"); cli.entity ("helper", "_config"); - cli.entity ("cmd", "_get"); cli.entity ("readcmd", "_get"); cli.entity ("helper", "_get"); - cli.entity ("cmd", "_ids"); cli.entity ("readcmd", "_ids"); cli.entity ("helper", "_ids"); - cli.entity ("cmd", "_projects"); cli.entity ("readcmd", "_projects"); cli.entity ("helper", "_projects"); - cli.entity ("cmd", "_show"); cli.entity ("readcmd", "_show"); cli.entity ("helper", "_show"); - cli.entity ("cmd", "_tags"); cli.entity ("readcmd", "_tags"); cli.entity ("helper", "_tags"); - cli.entity ("cmd", "_udas"); cli.entity ("readcmd", "_udas"); cli.entity ("helper", "_udas"); - cli.entity ("cmd", "_urgency"); cli.entity ("readcmd", "_urgency"); cli.entity ("helper", "_urgency"); - cli.entity ("cmd", "_uuids"); cli.entity ("readcmd", "_uuids"); cli.entity ("helper", "_uuids"); - cli.entity ("cmd", "_version"); cli.entity ("readcmd", "_version"); cli.entity ("helper", "_version"); - cli.entity ("cmd", "_zshcommands"); cli.entity ("readcmd", "_zshcommands"); cli.entity ("helper", "_zshcommands"); - cli.entity ("cmd", "_zshids"); cli.entity ("readcmd", "_zshids"); cli.entity ("helper", "_zshids"); - cli.entity ("cmd", "_zshuuids"); cli.entity ("readcmd", "_zshuuids"); cli.entity ("helper", "_zshuuids"); - - // Attributes (columns). - cli.entity ("attribute", "depends"); - cli.entity ("attribute", "description"); - cli.entity ("attribute", "due"); - cli.entity ("attribute", "end"); - cli.entity ("attribute", "entry"); - cli.entity ("attribute", "id"); - cli.entity ("attribute", "imask"); - cli.entity ("attribute", "mask"); - cli.entity ("attribute", "modified"); - cli.entity ("attribute", "parent"); - cli.entity ("attribute", "project"); - cli.entity ("attribute", "recur"); - cli.entity ("attribute", "scheduled"); - cli.entity ("attribute", "start"); - cli.entity ("attribute", "status"); - cli.entity ("attribute", "tags"); - cli.entity ("attribute", "until"); - cli.entity ("attribute", "urgency"); - cli.entity ("attribute", "uuid"); - cli.entity ("attribute", "wait"); - - // Pseudo-attributes. - cli.entity ("pseudo", "limit"); - - // UDAs. - cli.entity ("attribute", "duration"); - cli.entity ("uda", "duration"); - - // Modifiers. - cli.entity ("modifier", "above"); - cli.entity ("modifier", "after"); - cli.entity ("modifier", "any"); - cli.entity ("modifier", "before"); - cli.entity ("modifier", "below"); - cli.entity ("modifier", "contains"); - cli.entity ("modifier", "endswith"); - cli.entity ("modifier", "equals"); - cli.entity ("modifier", "has"); - cli.entity ("modifier", "hasnt"); - cli.entity ("modifier", "is"); - cli.entity ("modifier", "isnt"); - cli.entity ("modifier", "left"); - cli.entity ("modifier", "none"); - cli.entity ("modifier", "not"); - cli.entity ("modifier", "noword"); - cli.entity ("modifier", "over"); - cli.entity ("modifier", "right"); - cli.entity ("modifier", "startswith"); - cli.entity ("modifier", "under"); - cli.entity ("modifier", "word"); - - // Operators. - cli.entity ("operator", "^"); - cli.entity ("operator", "!"); - cli.entity ("operator", "_neg_"); - cli.entity ("operator", "_pos_"); - cli.entity ("operator", "_hastag_"); - cli.entity ("operator", "_notag_"); - cli.entity ("operator", "*"); - cli.entity ("operator", "/"); - cli.entity ("operator", "%"); - cli.entity ("operator", "+"); - cli.entity ("operator", "-"); - cli.entity ("operator", "<="); - cli.entity ("operator", ">="); - cli.entity ("operator", ">"); - cli.entity ("operator", "<"); - cli.entity ("operator", "="); - cli.entity ("operator", "=="); - cli.entity ("operator", "!="); - cli.entity ("operator", "~"); - cli.entity ("operator", "!~"); - cli.entity ("operator", "and"); - cli.entity ("operator", "or"); - cli.entity ("operator", "xor"); - cli.entity ("operator", "("); - cli.entity ("operator", ")"); - - cli.analyze (); - - std::cout << cli.dump () - << "\n" - << " \033[1;37;42mFILTER\033[0m " - << cli.getFilter () - << "\n"; - } - - catch (const std::string& error) - { - std::cout << "Error: " << error << std::endl; - } - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/calc.cpp task-2.5.0+dfsg/src/calc.cpp --- task-2.4.4+dfsg/src/calc.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/calc.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -39,7 +39,7 @@ //////////////////////////////////////////////////////////////////////////////// // Constants. -bool get (const std::string& name, Variant& value) +bool get (const std::string&, Variant&) { /* // An example, although a bad one because this is supported by default. @@ -57,7 +57,6 @@ try { bool infix = true; - bool ambiguous = false; // Add a source for constants. Eval e; @@ -77,8 +76,6 @@ << " -d|--debug Debug mode\n" << " -i|--infix Infix expression (default)\n" << " -p|--postfix Postfix expression\n" - << " -a|--ambiguous Choose dates over numbers when ambiguous\n" - << " -n|--noambiguous Choose numbers over dates when ambiguous (default)\n" << "\n"; exit (1); } @@ -125,15 +122,9 @@ infix = true; else if (!strcmp (argv[i], "-p") || !strcmp (argv[i], "--postfix")) infix = false; - else if (!strcmp (argv[i], "-a") || !strcmp (argv[i], "--ambiguous")) - ambiguous = true; - else if (!strcmp (argv[i], "-n") || !strcmp (argv[i], "--noambiguous")) - ambiguous = false; else expression += std::string (argv[i]) + " "; - e.ambiguity (ambiguous); - Variant result; if (infix) e.evaluateInfixExpression (expression, result); @@ -141,9 +132,8 @@ e.evaluatePostfixExpression (expression, result); // Show any debug output. - std::vector ::iterator i; - for (i = context.debugMessages.begin (); i != context.debugMessages.end (); ++i) - std::cout << *i << "\n"; + for (auto& i : context.debugMessages) + std::cout << i << "\n"; // Show the result in string form. std::cout << (std::string) result diff -Nru task-2.4.4+dfsg/src/CLI2.cpp task-2.5.0+dfsg/src/CLI2.cpp --- task-2.4.4+dfsg/src/CLI2.cpp 1970-01-01 00:00:00.000000000 +0000 +++ task-2.5.0+dfsg/src/CLI2.cpp 2015-10-21 21:18:14.000000000 +0000 @@ -0,0 +1,2163 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern Context context; + +// Overridden by rc.abbreviation.minimum. +int CLI2::minimumMatchLength = 3; + +// Alias expansion limit. Any more indicates some kind of error. +static int safetyValveDefault = 10; + +//////////////////////////////////////////////////////////////////////////////// +A2::A2 (const std::string& raw, Lexer::Type lextype) +{ + _lextype = lextype; + attribute ("raw", raw); +} + +//////////////////////////////////////////////////////////////////////////////// +A2::~A2 () +{ +} + +//////////////////////////////////////////////////////////////////////////////// +A2::A2 (const A2& other) +: _lextype (other._lextype) +, _tags (other._tags) +, _attributes (other._attributes) +{ +} + +//////////////////////////////////////////////////////////////////////////////// +A2& A2::operator= (const A2& other) +{ + if (this != &other) + { + _lextype = other._lextype; + _tags = other._tags; + _attributes = other._attributes; + } + + return *this; +} + +//////////////////////////////////////////////////////////////////////////////// +bool A2::hasTag (const std::string& tag) const +{ + if (std::find (_tags.begin (), _tags.end (), tag) != _tags.end ()) + return true; + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +void A2::tag (const std::string& tag) +{ + if (! hasTag (tag)) + _tags.push_back (tag); +} + +//////////////////////////////////////////////////////////////////////////////// +void A2::unTag (const std::string& tag) +{ + for (auto i = _tags.begin (); i != _tags.end (); ++i) + { + if (*i == tag) + { + _tags.erase (i); + break; + } + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Accessor for attributes. +void A2::attribute (const std::string& name, const std::string& value) +{ + _attributes[name] = value; + + if (name == "raw") + decompose (); +} + +//////////////////////////////////////////////////////////////////////////////// +// Accessor for attributes. +const std::string A2::attribute (const std::string& name) const +{ + // Prevent autovivification. + auto i = _attributes.find (name); + if (i != _attributes.end ()) + return i->second; + + return ""; +} + +//////////////////////////////////////////////////////////////////////////////// +const std::string A2::getToken () const +{ + auto i = _attributes.find ("canonical"); + if (i == _attributes.end ()) + i = _attributes.find ("raw"); + + return i->second; +} + +//////////////////////////////////////////////////////////////////////////////// +void A2::decompose () +{ + if (_lextype == Lexer::Type::tag) + { + std::string raw = _attributes["raw"]; + attribute ("name", raw.substr (1)); + attribute ("sign", raw.substr (0, 1)); + } + + else if (_lextype == Lexer::Type::substitution) + { + //if (Directory (raw).exists ()) + // return; + + std::string from; + std::string to; + std::string flags; + if (Lexer::decomposeSubstitution (_attributes["raw"], from, to, flags)) + { + attribute ("from", from); + attribute ("to", to); + attribute ("flags", flags); + } + } + + else if (_lextype == Lexer::Type::pair) + { + std::string name; + std::string mod; + std::string sep; + std::string value; + if (Lexer::decomposePair (_attributes["raw"], name, mod, sep, value)) + { + attribute ("name", name); + attribute ("modifier", mod); + attribute ("separator", sep); + attribute ("value", value); + + if (name == "rc") + { + if (mod != "") + tag ("CONFIG"); + else + tag ("RC"); + } + } + } + + else if (_lextype == Lexer::Type::pattern) + { + //if (Directory (raw).exists ()) + // return; + + std::string pattern; + std::string flags; + if (Lexer::decomposePattern (_attributes["raw"], pattern, flags)) + { + attribute ("pattern", pattern); + attribute ("flags", flags); + } + } +} + +//////////////////////////////////////////////////////////////////////////////// +const std::string A2::dump () const +{ + std::string output = Lexer::typeToString (_lextype); + + // Dump attributes. + std::string atts; + for (auto a = _attributes.begin (); a != _attributes.end (); ++a) + { + if (a != _attributes.begin ()) + atts += " "; + + atts += a->first + "='\033[33m" + a->second + "\033[0m'"; + } + + if (atts.length ()) + output += " " + atts; + + // Dump tags. + std::string tags; + for (auto& tag : _tags) + { + if (tags.length ()) + tags += ' '; + + if (tag == "BINARY") tags += "\033[1;37;44m" + tag + "\033[0m"; + else if (tag == "CMD") tags += "\033[1;37;46m" + tag + "\033[0m"; + else if (tag == "FILTER") tags += "\033[1;37;42m" + tag + "\033[0m"; + else if (tag == "MODIFICATION") tags += "\033[1;37;43m" + tag + "\033[0m"; + else if (tag == "MISCELLANEOUS") tags += "\033[1;37;45m" + tag + "\033[0m"; + else if (tag == "RC") tags += "\033[1;37;41m" + tag + "\033[0m"; + else if (tag == "CONFIG") tags += "\033[1;37;101m" + tag + "\033[0m"; + else if (tag == "?") tags += "\033[38;5;255;48;5;232m" + tag + "\033[0m"; + else tags += "\033[32m" + tag + "\033[0m"; + } + + if (tags.length ()) + output += ' ' + tags; + + return output; +} + +//////////////////////////////////////////////////////////////////////////////// +// Static method. +void CLI2::getOverride (int argc, const char** argv, std::string& home, File& rc) +{ + for (int i = 0; i < argc; ++i) + { + std::string raw = argv[i]; + if (raw == "--") + return; + + if (raw.length () > 3 && + raw.substr (0, 3) == "rc:") + { + rc = raw.substr (3); + + home = "."; + auto last_slash = rc._data.rfind ("/"); + if (last_slash != std::string::npos) + home = rc.parent (); + + context.header (format (STRING_PARSER_ALTERNATE_RC, rc._data)); + + // Keep looping, because if there are multiple rc:file arguments, the last + // one should dominate. + } + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Look for CONFIG data.location and initialize a Path object. +// Static method. +void CLI2::getDataLocation (int argc, const char** argv, Path& data) +{ + std::string location = context.config.get ("data.location"); + if (location != "") + data = location; + + for (int i = 0; i < argc; ++i) + { + std::string raw = argv[i]; + if (raw == "--") + break; + + if (raw.length () > 17 && + raw.substr (0, 16) == "rc.data.location") + { + data = Directory (raw.substr (17)); + context.header (format (STRING_PARSER_ALTERNATE_DATA, (std::string) data)); + + // Keep looping, because if there are multiple rc:file arguments, the last + // one should dominate. + } + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Static method. +void CLI2::applyOverrides (int argc, const char** argv) +{ + for (int i = 0; i < argc; ++i) + { + std::string raw = argv[i]; + if (raw == "--") + break; + + if (raw.length () > 3 && + raw.substr (0, 3) == "rc.") + { + auto sep = raw.find ('=', 3); + if (sep == std::string::npos) + sep = raw.find (':', 3); + if (sep != std::string::npos) + { + std::string name = raw.substr (3, sep - 3); + std::string value = raw.substr (sep + 1); + context.config.set (name, value); + context.footnote (format (STRING_PARSER_OVERRIDE_RC, name, value)); + } + } + } +} + +//////////////////////////////////////////////////////////////////////////////// +CLI2::CLI2 () +: _context_filter_added (false) +{ +} + +//////////////////////////////////////////////////////////////////////////////// +CLI2::~CLI2 () +{ +} + +//////////////////////////////////////////////////////////////////////////////// +void CLI2::alias (const std::string& name, const std::string& value) +{ + _aliases.insert (std::pair (name, value)); +} + +//////////////////////////////////////////////////////////////////////////////// +void CLI2::entity (const std::string& category, const std::string& name) +{ + // Walk the list of entities for category. + auto c = _entities.equal_range (category); + for (auto e = c.first; e != c.second; ++e) + if (e->second == name) + return; + + // The category/name pair was not found, therefore add it. + _entities.insert (std::pair (category, name)); +} + +//////////////////////////////////////////////////////////////////////////////// +// Capture a single argument. +void CLI2::add (const std::string& argument) +{ + A2 arg (trim (argument), Lexer::Type::word); + arg.tag ("ORIGINAL"); + _original_args.push_back (arg); + + // Adding a new argument invalidates prior analysis. + _args.clear (); +} + +//////////////////////////////////////////////////////////////////////////////// +// Capture a set of arguments, inserted immediately after the binary. +void CLI2::add (const std::vector & arguments) +{ + std::vector replacement; + replacement.push_back (_original_args[0]); + + for (auto& arg : arguments) + replacement.push_back (A2 (arg, Lexer::Type::word)); + + for (unsigned int i = 1; i < _original_args.size (); ++i) + replacement.push_back (_original_args[i]); + + _original_args = replacement; + + // Adding a new argument invalidates prior analysis. + _args.clear (); +} + +//////////////////////////////////////////////////////////////////////////////// +// Arg0 is the first argument, which is the name and potentially a relative or +// absolute path to the invoked binary. +// +// The binary name is 'task', but if the binary is reported as 'cal' or +// 'calendar' then it was invoked via symbolic link, in which case capture the +// first argument as 'calendar'. +void CLI2::handleArg0 () +{ + // Capture arg0 separately, because it is the command that was run, and could + // need special handling. + std::string raw = _original_args[0].attribute ("raw"); + A2 a (raw, Lexer::Type::word); + a.tag ("BINARY"); + + std::string basename = "task"; + auto slash = raw.rfind ('/'); + if (slash != std::string::npos) + basename = raw.substr (slash + 1); + + a.attribute ("basename", basename); + if (basename == "cal" || + basename == "calendar") + { + _args.push_back (a); + + A2 cal ("calendar", Lexer::Type::word); + _args.push_back (cal); + } + else if (basename == "task" || + basename == "tw" || + basename == "t") + { + _args.push_back (a); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// All arguments must be individually and wholly recognized by the Lexer. Any +// argument not recognized is considered a Lexer::Type::word. +// +// As a side effect, tags all arguments after a terminator ('--') with +// TERMINATED. +void CLI2::lexArguments () +{ + // Note: Starts iterating at index 1, because ::handleArg0 has already + // processed it. + bool terminated = false; + for (unsigned int i = 1; i < _original_args.size (); ++i) + { + bool quoted = Lexer::wasQuoted (_original_args[i].attribute ("raw")); + + std::string lexeme; + Lexer::Type type; + Lexer lex (_original_args[i].attribute ("raw")); + if (lex.token (lexeme, type) && + (lex.isEOS () || // Token goes to EOS + (quoted && type == Lexer::Type::pair)) // Quoted pairs automatically go to EOS + ) + { + if (! terminated && type == Lexer::Type::separator) + terminated = true; + else if (terminated) + type = Lexer::Type::word; + + A2 a (_original_args[i].attribute ("raw"), type); + if (terminated) + a.tag ("TERMINATED"); + if (quoted) + a.tag ("QUOTED"); + + if (_original_args[i].hasTag ("ORIGINAL")) + a.tag ("ORIGINAL"); + + _args.push_back (a); + } + else + { + std::string quote = "'"; + std::string escaped = _original_args[i].attribute ("raw"); + str_replace (escaped, quote, "\\'"); + + std::string::size_type cursor = 0; + std::string word; + if (Lexer::readWord (quote + escaped + quote, quote, cursor, word)) + { + Lexer::dequote (word); + A2 unknown (word, Lexer::Type::word); + if (lex.wasQuoted (_original_args[i].attribute ("raw"))) + unknown.tag ("QUOTED"); + + if (_original_args[i].hasTag ("ORIGINAL")) + unknown.tag ("ORIGINAL"); + + _args.push_back (unknown); + } + + // This branch may have no use-case. + else + { + A2 unknown (_original_args[i].attribute ("raw"), Lexer::Type::word); + unknown.tag ("UNKNOWN"); + + if (lex.wasQuoted (_original_args[i].attribute ("raw"))) + unknown.tag ("QUOTED"); + + if (_original_args[i].hasTag ("ORIGINAL")) + unknown.tag ("ORIGINAL"); + + _args.push_back (unknown); + } + } + } + + if (context.config.getInteger ("debug.parser") >= 2) + context.debug (dump ("CLI2::analyze lexArguments")); +} + +//////////////////////////////////////////////////////////////////////////////// +// [1] Scan all args for the 'add' and 'log' commands, and demote any +// Lexer::Type::Tag args with sign '-' to Lexer::Type::word. +// [2] Convert any pseudo args name:value into config settings, and erase. +void CLI2::demotion () +{ + bool changes = false; + std::vector replacement; + + std::string canonical; + for (auto& a : _args) + { + if (a._lextype == Lexer::Type::tag && + a.attribute ("sign") == "-") + { + std::string command = getCommand (); + if (command == "add" || + command == "log") + { + a._lextype = Lexer::Type::word; + changes = true; + } + } + + else if (a._lextype == Lexer::Type::pair && + canonicalize (canonical, "pseudo", a.attribute ("name"))) + { + context.config.set (canonical, a.attribute ("value")); + changes = true; + + // Equivalent to erasing 'a'. + continue; + } + + replacement.push_back (a); + } + + if (changes && + context.config.getInteger ("debug.parser") >= 2) + context.debug (dump ("CLI2::analyze demotion")); +} + +//////////////////////////////////////////////////////////////////////////////// +// Intended to be called after ::add() to perform the final analysis. +void CLI2::analyze () +{ + if (context.config.getInteger ("debug.parser") >= 2) + context.debug (dump ("CLI2::analyze")); + + // Process _original_args. + _args.clear (); + handleArg0 (); + lexArguments (); + + // Process _args. + aliasExpansion (); + if (! findCommand ()) + { + defaultCommand (); + if (! findCommand ()) + throw std::string (STRING_TRIVIAL_INPUT); + } + + demotion (); + canonicalizeNames (); + + // Determine arg types: FILTER, MODIFICATION, MISCELLANEOUS. + categorizeArgs (); + parenthesizeOriginalFilter (); +} + +//////////////////////////////////////////////////////////////////////////////// +// Process raw string. +void CLI2::addFilter (const std::string& arg) +{ + if (arg.length ()) + { + std::vector filter; + filter.push_back ("("); + + std::string lexeme; + Lexer::Type type; + Lexer lex (arg); + + while (lex.token (lexeme, type)) + filter.push_back (lexeme); + + filter.push_back (")"); + add (filter); + analyze (); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// There are situations where a context filter is applied. This method +// determines whether one applies, and if so, applies it. Disqualifiers include: +// - filter contains ID or UUID +void CLI2::addContextFilter () +{ + // Recursion block. + if (_context_filter_added) + return; + + // Detect if any context is set, and bail out if not + std::string contextName = context.config.get ("context"); + if (contextName == "") + { + context.debug ("No context."); + return; + } + + // Detect if UUID or ID is set, and bail out + for (auto& a : _args) + { + if (a._lextype == Lexer::Type::uuid || + a._lextype == Lexer::Type::number || + a._lextype == Lexer::Type::set) + { + context.debug (format ("UUID/ID argument 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 + { + _context_filter_added = true; + addFilter (contextFilter); + if (context.verbose ("context")) + context.footnote (format ("Context '{1}' set. Use 'task context none' to remove.", contextName)); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Parse the command line, identifiying filter components, expanding syntactic +// sugar as necessary. +void CLI2::prepareFilter () +{ + // Clear and re-populate. + _id_ranges.clear (); + _uuid_list.clear (); + _context_filter_added = false; + + // Remove all the syntactic sugar for FILTERs. + lexFilterArgs (); + findIDs (); + findUUIDs (); + insertIDExpr (); + desugarFilterPlainArgs (); + findStrayModifications (); + desugarFilterTags (); + desugarFilterAttributes (); + desugarFilterPatterns (); + insertJunctions (); // Deliberately after all desugar calls. + + if (context.verbose ("filter")) + { + std::string combined; + for (auto& a : _args) + { + if (a.hasTag ("FILTER")) + { + if (combined != "") + combined += " "; + + combined += a.attribute ("raw"); + } + } + + if (combined.size ()) + context.footnote (std::string (STRING_COLUMN_LABEL_FILTER) + ": " + combined); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Return all the MISCELLANEOUS args. +const std::vector CLI2::getWords () +{ + std::vector words; + for (auto& a : _args) + if (a.hasTag ("MISCELLANEOUS")) + words.push_back (a.attribute ("raw")); + + if (context.config.getInteger ("debug.parser") >= 2) + { + Color colorOrigArgs ("gray10 on gray4"); + std::string message = " "; + for (auto& word : words) + message += colorOrigArgs.colorize (word) + " "; + context.debug ("CLI2::getWords" + message); + } + + return words; +} + +//////////////////////////////////////////////////////////////////////////////// +// Search for 'value' in _entities category, return canonicalized value. +bool CLI2::canonicalize ( + std::string& canonicalized, + const std::string& category, + const std::string& value) const +{ + // Extract a list of entities for category. + std::vector options; + auto c = _entities.equal_range (category); + for (auto e = c.first; e != c.second; ++e) + { + // Shortcut: if an exact match is found, success. + if (value == e->second) + { + canonicalized = value; + return true; + } + + options.push_back (e->second); + } + + // Match against the options, throw away results. + std::vector matches; + if (autoComplete (value, options, matches, minimumMatchLength) == 1) + { + canonicalized = matches[0]; + return true; + } + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +std::string CLI2::getBinary () const +{ + if (_args.size ()) + return _args[0].attribute ("raw"); + + return ""; +} + +//////////////////////////////////////////////////////////////////////////////// +std::string CLI2::getCommand (bool canonical) const +{ + for (auto& a : _args) + if (a.hasTag ("CMD")) + return a.attribute (canonical ? "canonical" : "raw"); + + return ""; +} + +//////////////////////////////////////////////////////////////////////////////// +const std::string CLI2::dump (const std::string& title) const +{ + std::stringstream out; + + out << "\033[1m" << title << "\033[0m\n" + << " _original_args\n "; + + Color colorArgs ("gray10 on gray4"); + Color colorFilter ("black on rgb311"); + for (auto i = _original_args.begin (); i != _original_args.end (); ++i) + { + if (i != _original_args.begin ()) + out << ' '; + + if (i->hasTag ("ORIGINAL")) + out << colorArgs.colorize (i->attribute ("raw")); + else + out << colorFilter.colorize (i->attribute ("raw")); + } + out << "\n"; + + if (_args.size ()) + { + out << " _args\n"; + for (auto& a : _args) + out << " " << a.dump () << "\n"; + } + + if (_id_ranges.size ()) + { + out << " _id_ranges\n "; + for (auto& range : _id_ranges) + { + if (range.first != range.second) + out << colorArgs.colorize (range.first + "-" + range.second) << " "; + else + out << colorArgs.colorize (range.first) << " "; + } + + out << "\n"; + } + + if (_uuid_list.size ()) + { + out << " _uuid_list\n "; + for (auto& uuid : _uuid_list) + out << colorArgs.colorize (uuid) << " "; + + out << "\n"; + } + + return out.str (); +} + +//////////////////////////////////////////////////////////////////////////////// +// If any aliases are found in un-TERMINATED arguments, replace the alias with +// a set of Lexed tokens from the configuration. +void CLI2::aliasExpansion () +{ + bool changes = false; + bool action; + int counter = 0; + do + { + action = false; + std::vector reconstructed; + + std::string raw; + for (auto& i : _args) + { + raw = i.attribute ("raw"); + if (i.hasTag ("TERMINATED")) + { + reconstructed.push_back (i); + } + else if (_aliases.find (raw) != _aliases.end ()) + { + std::string lexeme; + Lexer::Type type; + Lexer lex (_aliases[raw]); + while (lex.token (lexeme, type)) + reconstructed.push_back (A2 (lexeme, type)); + + action = true; + changes = true; + } + else + { + reconstructed.push_back (i); + } + } + + _args = reconstructed; + + std::vector reconstructedOriginals; + bool terminated = false; + for (auto& i : _original_args) + { + if (i.attribute ("raw") == "--") + terminated = true; + + if (terminated) + { + reconstructedOriginals.push_back (i); + } + else if (_aliases.find (i.attribute ("raw")) != _aliases.end ()) + { + std::string lexeme; + Lexer::Type type; + Lexer lex (_aliases[i.attribute ("raw")]); + while (lex.token (lexeme, type)) + reconstructedOriginals.push_back (A2 (lexeme, type)); + + action = true; + changes = true; + } + else + { + reconstructedOriginals.push_back (i); + } + } + + _original_args = reconstructedOriginals; + } + while (action && counter++ < safetyValveDefault); + + if (counter >= safetyValveDefault) + context.debug (format (STRING_PARSER_ALIAS_NEST, safetyValveDefault)); + + if (changes && + context.config.getInteger ("debug.parser") >= 2) + context.debug (dump ("CLI2::analyze aliasExpansion")); +} + +//////////////////////////////////////////////////////////////////////////////// +// Scan all arguments and canonicalize names that need it. +void CLI2::canonicalizeNames () +{ + bool changes = false; + for (auto& a : _args) + { + if (a._lextype == Lexer::Type::pair) + { + std::string raw = a.attribute ("raw"); + if (raw.substr (0, 3) != "rc:" && + raw.substr (0, 3) != "rc.") + { + std::string name = a.attribute ("name"); + std::string canonical; + if (canonicalize (canonical, "pseudo", name) || + canonicalize (canonical, "attribute", name)) + { + a.attribute ("canonical", canonical); + } + else + { + a._lextype = Lexer::Type::word; + } + + changes = true; + } + } + } + + if (changes && + context.config.getInteger ("debug.parser") >= 2) + context.debug (dump ("CLI2::analyze canonicalizeNames")); +} + +//////////////////////////////////////////////////////////////////////////////// +// Categorize FILTER, MODIFICATION and MISCELLANEOUS args, based on CMD DNA. +void CLI2::categorizeArgs () +{ + // Context is only applied for commands that request it. + std::string command = getCommand (); + Command* cmd = context.commands[command]; + if (cmd && cmd->uses_context ()) + addContextFilter (); + + bool changes = false; + bool afterCommand = false; + for (auto& a : _args) + { + if (a._lextype == Lexer::Type::separator) + continue; + + // Record that the command has been found, it affects behavior. + if (a.hasTag ("CMD")) + { + afterCommand = true; + } + + // Skip admin args. + else if (a.hasTag ("BINARY") || + a.hasTag ("RC") || + a.hasTag ("CONFIG")) + { + // NOP. + } + + // All combinations, with all 8 cases handled below.: + // + // -- -- -- Error: found an arg, but none expected + // -- -- Mi task [Mi] [Mi] + // -- Mo -- task [Mo] [Mo] + // -- Mo Mi Internally inconsistent + // Fi -- -- task [Fi] [Fi] + // Fi -- Mi task [Fi] [Mi] + // Fi Mo -- task [Fi] [Mo] + // Fi Mo Mi Internally inconsistent + // + else if (cmd && + ! cmd->accepts_filter () && + ! cmd->accepts_modifications () && + ! cmd->accepts_miscellaneous ()) + { + // No commands were expected --> error. + throw format (STRING_PARSER_UNEXPECTED_ARG, command, a.attribute ("raw")); + } + else if (cmd && + ! cmd->accepts_filter () && + ! cmd->accepts_modifications () && + cmd->accepts_miscellaneous ()) + { + a.tag ("MISCELLANEOUS"); + changes = true; + } + else if (cmd && + ! cmd->accepts_filter () && + cmd->accepts_modifications () && + ! cmd->accepts_miscellaneous ()) + { + a.tag ("MODIFICATION"); + changes = true; + } + else if (cmd && + ! cmd->accepts_filter () && + cmd->accepts_modifications () && + cmd->accepts_miscellaneous ()) + { + // Error: internally inconsistent. + throw std::string (STRING_UNKNOWN_ERROR); + } + else if (cmd && + cmd->accepts_filter () && + ! cmd->accepts_modifications () && + ! cmd->accepts_miscellaneous ()) + { + a.tag ("FILTER"); + changes = true; + } + else if (cmd && + cmd->accepts_filter () && + ! cmd->accepts_modifications () && + cmd->accepts_miscellaneous ()) + { + if (!afterCommand) + a.tag ("FILTER"); + else + a.tag ("MISCELLANEOUS"); + + changes = true; + } + else if (cmd && + cmd->accepts_filter () && + cmd->accepts_modifications () && + ! cmd->accepts_miscellaneous ()) + { + if (!afterCommand) + a.tag ("FILTER"); + else + a.tag ("MODIFICATION"); + + changes = true; + } + else if (cmd && + cmd->accepts_filter () && + cmd->accepts_modifications () && + cmd->accepts_miscellaneous ()) + { + // Error: internally inconsistent. + throw std::string (STRING_UNKNOWN_ERROR); + } + } + + if (changes && + context.config.getInteger ("debug.parser") >= 2) + context.debug (dump ("CLI2::analyze categorizeArgs")); +} + +//////////////////////////////////////////////////////////////////////////////// +// The following command: +// +// task +home or +work list +// +// Is reasonable, and does not work unless the filter is parenthesized. Ignoring +// context, the 'list' report has a filter, which is inserted at the beginning +// like this: +// +// task ( status:pending ) +home or +work list +// +// Parenthesizing the user-provided (original) filter yields this: +// +// task ( status:pending ) ( +home or +work ) list +// +// And when the conjunction is added: +// +// task ( status:pending ) and ( +home or +work ) list +// +// the query is correct. +void CLI2::parenthesizeOriginalFilter () +{ + // Locate the first and last ORIGINAL FILTER args. + unsigned int firstOriginalFilter = 0; + unsigned int lastOriginalFilter = 0; + for (unsigned int i = 1; i < _args.size (); ++i) + { + if (_args[i].hasTag ("FILTER") && + _args[i].hasTag ("ORIGINAL")) + { + if (firstOriginalFilter == 0) + firstOriginalFilter = i; + + lastOriginalFilter = i; + } + } + + // If found, parenthesize the arg list accordingly. + if (firstOriginalFilter && + lastOriginalFilter) + { + std::vector reconstructed; + for (unsigned int i = 0; i < _args.size (); ++i) + { + if (i == firstOriginalFilter) + { + A2 openParen ("(", Lexer::Type::op); + openParen.tag ("ORIGINAL"); + openParen.tag ("FILTER"); + reconstructed.push_back (openParen); + } + + reconstructed.push_back (_args[i]); + + if (i == lastOriginalFilter) + { + A2 closeParen (")", Lexer::Type::op); + closeParen.tag ("ORIGINAL"); + closeParen.tag ("FILTER"); + reconstructed.push_back (closeParen); + } + } + + _args = reconstructed; + + if (context.config.getInteger ("debug.parser") >= 2) + context.debug (dump ("CLI2::analyze parenthesizeOriginalFilter")); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Scan all arguments and if any are an exact match for a command name, then +// tag as CMD. If an argument is an exact match for an attribute, despite being +// an inexact match for a command, then it is not a command. +bool CLI2::findCommand () +{ + for (auto& a : _args) + { + std::string raw = a.attribute ("raw"); + std::string canonical; + + // If the arg canonicalized to a 'cmd', but is also not an exact match + // for an 'attribute', proceed. Example: + // task project=foo list + // ^cmd ^cmd + // ^attribute + if (exactMatch ("cmd", raw)) + canonical = raw; + else if (exactMatch ("attribute", raw)) + continue; + else if (! canonicalize (canonical, "cmd", raw)) + continue; + + a.attribute ("canonical", canonical); + a.tag ("CMD"); + + // Apply command DNA as tags. + Command* command = context.commands[canonical]; + if (command->read_only ()) a.tag ("READONLY"); + if (command->displays_id ()) a.tag ("SHOWSID"); + if (command->needs_gc ()) a.tag ("RUNSGC"); + if (command->uses_context ()) a.tag ("USESCONTEXT"); + if (command->accepts_filter ()) a.tag ("ALLOWSFILTER"); + if (command->accepts_modifications ()) a.tag ("ALLOWSMODIFICATIONS"); + if (command->accepts_miscellaneous ()) a.tag ("ALLOWSMISC"); + + if (context.config.getInteger ("debug.parser") >= 2) + context.debug (dump ("CLI2::analyze findCommand")); + + // Stop and indicate command found. + return true; + } + + // Indicate command not found. + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +// Search for exact 'value' in _entities category. +bool CLI2::exactMatch ( + const std::string& category, + const std::string& value) const +{ + // Extract a list of entities for category. + auto c = _entities.equal_range (category); + for (auto e = c.first; e != c.second; ++e) + if (value == e->second) + return true; + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +// +tag --> tags _hastag_ tag +// -tag --> tags _notag_ tag +void CLI2::desugarFilterTags () +{ + bool changes = false; + std::vector reconstructed; + for (auto& a : _args) + { + if (a._lextype == Lexer::Type::tag && + a.hasTag ("FILTER")) + { + changes = true; + + A2 left ("tags", Lexer::Type::dom); + left.tag ("FILTER"); + reconstructed.push_back (left); + + std::string raw = a.attribute ("raw"); + + A2 op (raw[0] == '+' ? "_hastag_" : "_notag_", Lexer::Type::op); + op.tag ("FILTER"); + reconstructed.push_back (op); + + A2 right ("" + raw.substr (1) + "", Lexer::Type::string); + right.tag ("FILTER"); + reconstructed.push_back (right); + } + else + reconstructed.push_back (a); + } + + if (changes) + { + _args = reconstructed; + + if (context.config.getInteger ("debug.parser") >= 2) + context.debug (dump ("CLI2::prepareFilter desugarFilterTags")); + } +} + +//////////////////////////////////////////////////////////////////////////////// +void CLI2::findStrayModifications () +{ + bool changes = false; + + std::string command = getCommand (); + if (command == "add" || + command == "log") + { + for (auto& a : _args) + { + if (a.hasTag ("FILTER")) + { + a.unTag ("FILTER"); + a.tag ("MODIFICATION"); + changes = true; + } + } + } + + if (changes) + if (context.config.getInteger ("debug.parser") >= 2) + context.debug (dump ("CLI2::prepareFilter findStrayModifications")); +} + +//////////////////////////////////////////////////////////////////////////////// +// [.]:['"][]['"] --> name value +void CLI2::desugarFilterAttributes () +{ + bool changes = false; + std::vector reconstructed; + for (auto& a : _args) + { + if (a._lextype == Lexer::Type::pair && + a.hasTag ("FILTER")) + { + std::string raw = a.attribute ("raw"); + std::string name = a.attribute ("name"); + std::string mod = a.attribute ("modifier"); + std::string sep = a.attribute ("separator"); + std::string value = a.attribute ("value"); + + // An unquoted string, while equivalent to an empty string, doesn't cause + // an operand shortage in eval. + if (value == "") + value = "''"; + + // Some values are expressions, which need to be lexed. The best way to + // determine whether an expression is either a single value, or needs to + // be lexed, is to lex it and count the tokens. For example: + // now+1d + // This should be lexed and surrounded by parentheses: + // ( + // now + // + + // 1d + // ) + // Use this sequence in place of a single value. + std::vector values = lexExpression (value); + if (context.config.getInteger ("debug.parser") >= 2) + { + context.debug ("CLI2::lexExpression " + name + ":" + value); + for (auto& v : values) + context.debug (" " + v.dump ()); + context.debug (" "); + } + + bool found = false; + std::string canonical; + if (canonicalize (canonical, "attribute", name)) + { + // Certain attribute types do not suport math. + // string --> no + // numeric --> yes + // date --> yes + // duration --> yes + bool evalSupported = true; + Column* col = context.columns[canonical]; + if (col && col->type () == "string") + evalSupported = false; + + A2 lhs (name, Lexer::Type::dom); + lhs.tag ("FILTER"); + lhs.attribute ("canonical", canonical); + lhs.attribute ("modifier", mod); + + A2 op ("", Lexer::Type::op); + op.tag ("FILTER"); + + A2 rhs ("", Lexer::Type::string); + rhs.tag ("FILTER"); + + // Special case for ':'. + if (mod == "") + { + op.attribute ("raw", "="); + rhs.attribute ("raw", value); + } + else if (mod == "before" || mod == "under" || mod == "below") + { + op.attribute ("raw", "<"); + rhs.attribute ("raw", value); + } + else if (mod == "after" || mod == "over" || mod == "above") + { + op.attribute ("raw", ">"); + rhs.attribute ("raw", value); + } + else if (mod == "none") + { + op.attribute ("raw", "=="); + rhs.attribute ("raw", "''"); + } + else if (mod == "any") + { + op.attribute ("raw", "!=="); + rhs.attribute ("raw", "''"); + } + else if (mod == "is" || mod == "equals") + { + op.attribute ("raw", "=="); + rhs.attribute ("raw", value); + } + else if (mod == "not") + { + op.attribute ("raw", "!="); + rhs.attribute ("raw", value); + } + else if (mod == "isnt") + { + op.attribute ("raw", "!=="); + rhs.attribute ("raw", value); + } + else if (mod == "has" || mod == "contains") + { + op.attribute ("raw", "~"); + rhs.attribute ("raw", value); + } + else if (mod == "hasnt") + { + op.attribute ("raw", "!~"); + rhs.attribute ("raw", value); + } + else if (mod == "startswith" || mod == "left") + { + op.attribute ("raw", "~"); + rhs.attribute ("raw", "^" + value); + } + else if (mod == "endswith" || mod == "right") + { + op.attribute ("raw", "~"); + rhs.attribute ("raw", value + "$"); + } + else if (mod == "word") + { + op.attribute ("raw", "~"); +#if defined (DARWIN) + rhs.attribute ("raw", value); +#elif defined (SOLARIS) + rhs.attribute ("raw", "\\<" + value + "\\>"); +#else + rhs.attribute ("raw", "\\b" + value + "\\b"); +#endif + } + else if (mod == "noword") + { + op.attribute ("raw", "!~"); +#if defined (DARWIN) + rhs.attribute ("raw", value); +#elif defined (SOLARIS) + rhs.attribute ("raw", "\\<" + value + "\\>"); +#else + rhs.attribute ("raw", "\\b" + value + "\\b"); +#endif + } + else + throw format (STRING_PARSER_UNKNOWN_ATTMOD, mod); + + reconstructed.push_back (lhs); + reconstructed.push_back (op); + + // Do not modify this construct without full understanding. + if (values.size () == 1 || ! evalSupported) + { + if (Lexer::isDOM (rhs.attribute ("raw"))) + rhs._lextype = Lexer::Type::dom; + + reconstructed.push_back (rhs); + } + else + for (auto& v : values) + reconstructed.push_back (v); + + found = true; + } + + // If the name does not canonicalize to either an attribute or a UDA + // then it is not a recognized Lexer::Type::pair, so downgrade it to + // Lexer::Type::word. + else + { + a._lextype = Lexer::Type::word; + } + + if (found) + changes = true; + else + reconstructed.push_back (a); + } + // Not a FILTER pair. + else + reconstructed.push_back (a); + } + + if (changes) + { + _args = reconstructed; + + if (context.config.getInteger ("debug.parser") >= 2) + context.debug (dump ("CLI2::prepareFilter desugarFilterAttributes")); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// /pattern/ --> description ~ 'pattern' +void CLI2::desugarFilterPatterns () +{ + bool changes = false; + std::vector reconstructed; + for (auto& a : _args) + { + if (a._lextype == Lexer::Type::pattern && + a.hasTag ("FILTER")) + { + changes = true; + + A2 lhs ("description", Lexer::Type::dom); + lhs.tag ("FILTER"); + reconstructed.push_back (lhs); + + A2 op ("~", Lexer::Type::op); + op.tag ("FILTER"); + reconstructed.push_back (op); + + A2 rhs (a.attribute ("pattern"), Lexer::Type::string); + rhs.attribute ("flags", a.attribute ("flags")); + rhs.tag ("FILTER"); + reconstructed.push_back (rhs); + } + else + reconstructed.push_back (a); + } + + if (changes) + { + _args = reconstructed; + + if (context.config.getInteger ("debug.parser") >= 2) + context.debug (dump ("CLI2::prepareFilter desugarFilterPatterns")); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// An ID sequence can be: +// +// a single ID: 1 +// a list of IDs: 1,3,5 +// a list of IDs: 1 3 5 +// a range: 5-10 +// or a combination: 1,3,5-10 12 +// +void CLI2::findIDs () +{ + bool changes = false; + + if (context.config.getBoolean ("sugar")) + { + bool previousFilterArgWasAnOperator = false; + int filterCount = 0; + + for (auto& a : _args) + { + if (a.hasTag ("FILTER")) + { + ++filterCount; + + if (a._lextype == Lexer::Type::number) + { + // Skip any number that was preceded by an operator. + if (! previousFilterArgWasAnOperator) + { + changes = true; + std::string number = a.attribute ("raw"); + _id_ranges.push_back (std::pair (number, number)); + } + } + else if (a._lextype == Lexer::Type::set) + { + // Split the ID list into elements. + std::vector elements; + split (elements, a.attribute ("raw"), ','); + + for (auto& element : elements) + { + changes = true; + auto hyphen = element.find ("-"); + if (hyphen != std::string::npos) + { + _id_ranges.push_back (std::pair (element.substr (0, hyphen), element.substr (hyphen + 1))); + } + else + { + _id_ranges.push_back (std::pair (element, element)); + } + } + } + + std::string raw = a.attribute ("raw"); + previousFilterArgWasAnOperator = (a._lextype == Lexer::Type::op && + raw != "(" && + raw != ")") + ? true + : false; + } + } + + // If no IDs were found, and no filter was specified, look for number/set + // listed as a MODIFICATION. + std::string command = getCommand (); + + if (! _id_ranges.size () && + filterCount == 0 && + command != "add" && + command != "log") + { + for (auto& a : _args) + { + if (a.hasTag ("MODIFICATION")) + { + std::string raw = a.attribute ("raw"); + + // For a number to be an ID, it must not contain any sign or floating + // point elements. + if (a._lextype == Lexer::Type::number && + raw.find ('.') == std::string::npos && + raw.find ('e') == std::string::npos && + raw.find ('-') == std::string::npos) + { + changes = true; + a.unTag ("MODIFICATION"); + a.tag ("FILTER"); + _id_ranges.push_back (std::pair (raw, raw)); + } + else if (a._lextype == Lexer::Type::set) + { + a.unTag ("MODIFICATION"); + a.tag ("FILTER"); + + // Split the ID list into elements. + std::vector elements; + split (elements, raw, ','); + + for (auto& element : elements) + { + changes = true; + auto hyphen = element.find ("-"); + if (hyphen != std::string::npos) + { + _id_ranges.push_back (std::pair (element.substr (0, hyphen), element.substr (hyphen + 1))); + } + else + { + _id_ranges.push_back (std::pair (element, element)); + } + } + } + } + } + } + } + + // Sugar-free. + else + { + std::vector reconstructed; + for (auto& a : _args) + { + if (a.hasTag ("FILTER") && + a._lextype == Lexer::Type::number) + { + changes = true; + A2 pair ("id:" + a.attribute ("raw"), Lexer::Type::pair); + pair.tag ("FILTER"); + pair.decompose (); + reconstructed.push_back (pair); + } + else + reconstructed.push_back (a); + } + + if (changes) + _args = reconstructed; + } + + if (changes) + if (context.config.getInteger ("debug.parser") >= 2) + context.debug (dump ("CLI2::prepareFilter findIDs")); +} + +//////////////////////////////////////////////////////////////////////////////// +void CLI2::findUUIDs () +{ + bool changes = false; + + if (context.config.getBoolean ("sugar")) + { + for (auto& a : _args) + { + if (a._lextype == Lexer::Type::uuid && + a.hasTag ("FILTER")) + { + changes = true; + _uuid_list.push_back (a.attribute ("raw")); + } + } + + if (! _uuid_list.size ()) + { + for (auto& a : _args) + { + if (a._lextype == Lexer::Type::uuid && + a.hasTag ("MODIFICATION")) + { + changes = true; + a.unTag ("MODIFICATION"); + a.tag ("FILTER"); + _uuid_list.push_back (a.attribute ("raw")); + } + } + } + } + + // Sugar-free. + else + { + std::vector reconstructed; + for (auto& a : _args) + { + if (a.hasTag ("FILTER") && + a._lextype == Lexer::Type::uuid) + { + changes = true; + A2 pair ("uuid:" + a.attribute ("raw"), Lexer::Type::pair); + pair.tag ("FILTER"); + pair.decompose (); + reconstructed.push_back (pair); + } + else + reconstructed.push_back (a); + } + + if (changes) + _args = reconstructed; + } + + if (changes) + if (context.config.getInteger ("debug.parser") >= 2) + context.debug (dump ("CLI2::prepareFilter findUUIDs")); +} + +//////////////////////////////////////////////////////////////////////////////// +void CLI2::insertIDExpr () +{ + // Skip completely if no ID/UUID was found. This is because below, '(' and ')' + // are inserted regardless of list size. + if (! _id_ranges.size () && + ! _uuid_list.size ()) + return; + + // Find the *first* occurence of lexer type set/number/uuid, and replace it + // with a synthesized expression. All other occurences are eaten. + bool changes = false; + bool foundID = false; + std::vector reconstructed; + for (auto& a : _args) + { + if ((a._lextype == Lexer::Type::set || + a._lextype == Lexer::Type::number || + a._lextype == Lexer::Type::uuid) && + a.hasTag ("FILTER")) + { + if (! foundID) + { + foundID = true; + changes = true; + + // Construct a single sequence that represents all _id_ranges and + // _uuid_list in one clause. This is essentially converting this: + // + // 1,2-3 uuid,uuid uuid 4 + // + // into: + // + // ( + // ( id == 1 ) + // or ( ( id >= 2 ) and ( id <= 3 ) ) + // or ( id == 4 ) + // or ( uuid = $UUID ) + // or ( uuid = $UUID ) + // ) + + // Building block operators. + A2 openParen ("(", Lexer::Type::op); openParen.tag ("FILTER"); + A2 closeParen (")", Lexer::Type::op); closeParen.tag ("FILTER"); + A2 opOr ("or", Lexer::Type::op); opOr.tag ("FILTER"); + A2 opAnd ("and", Lexer::Type::op); opAnd.tag ("FILTER"); + A2 opSimilar ("=", Lexer::Type::op); opSimilar.tag ("FILTER"); + A2 opEqual ("==", Lexer::Type::op); opEqual.tag ("FILTER"); + A2 opGTE (">=", Lexer::Type::op); opGTE.tag ("FILTER"); + A2 opLTE ("<=", Lexer::Type::op); opLTE.tag ("FILTER"); + + // Building block attributes. + A2 argID ("id", Lexer::Type::dom); + argID.tag ("FILTER"); + + A2 argUUID ("uuid", Lexer::Type::dom); + argUUID.tag ("FILTER"); + + reconstructed.push_back (openParen); + + // Add all ID ranges. + for (auto r = _id_ranges.begin (); r != _id_ranges.end (); ++r) + { + if (r != _id_ranges.begin ()) + reconstructed.push_back (opOr); + + if (r->first == r->second) + { + reconstructed.push_back (openParen); + reconstructed.push_back (argID); + reconstructed.push_back (opEqual); + + A2 value (r->first, Lexer::Type::number); + value.tag ("FILTER"); + reconstructed.push_back (value); + + reconstructed.push_back (closeParen); + } + else + { + bool ascending = true; + int low = strtol (r->first.c_str (), NULL, 10); + int high = strtol (r->second.c_str (), NULL, 10); + if (low <= high) + ascending = true; + else + ascending = false; + + reconstructed.push_back (openParen); + reconstructed.push_back (argID); + reconstructed.push_back (opGTE); + + A2 startValue ((ascending ? r->first : r->second), Lexer::Type::number); + startValue.tag ("FILTER"); + reconstructed.push_back (startValue); + + reconstructed.push_back (opAnd); + reconstructed.push_back (argID); + reconstructed.push_back (opLTE); + + A2 endValue ((ascending ? r->second : r->first), Lexer::Type::number); + endValue.tag ("FILTER"); + reconstructed.push_back (endValue); + + reconstructed.push_back (closeParen); + } + } + + // Combine the ID and UUID sections with 'or'. + if (_id_ranges.size () && + _uuid_list.size ()) + reconstructed.push_back (opOr); + + // Add all UUID list items. + for (auto u = _uuid_list.begin (); u != _uuid_list.end (); ++u) + { + if (u != _uuid_list.begin ()) + reconstructed.push_back (opOr); + + reconstructed.push_back (openParen); + reconstructed.push_back (argUUID); + reconstructed.push_back (opSimilar); + + A2 value (*u, Lexer::Type::string); + value.tag ("FILTER"); + reconstructed.push_back (value); + + reconstructed.push_back (closeParen); + } + + reconstructed.push_back (closeParen); + } + + // No 'else' because all set/number/uuid args but the first are removed. + } + else + reconstructed.push_back (a); + } + + if (changes) + { + _args = reconstructed; + + if (context.config.getInteger ("debug.parser") >= 2) + context.debug (dump ("CLI2::prepareFilter insertIDExpr")); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// FILTER Lexer::Type::word args will become part of an expression, and so they +// need to be Lexed. +void CLI2::lexFilterArgs () +{ + bool changes = false; + std::vector reconstructed; + for (auto& a : _args) + { + if (a._lextype == Lexer::Type::word && + a.hasTag ("FILTER")) + { + changes = true; + + std::string lexeme; + Lexer::Type type; + Lexer lex (a.attribute ("raw")); + while (lex.token (lexeme, type)) + { + A2 extra (lexeme, type); + extra.tag ("FILTER"); + reconstructed.push_back (extra); + } + } + else + reconstructed.push_back (a); + } + + if (changes) + { + _args = reconstructed; + + if (context.config.getInteger ("debug.parser") >= 2) + context.debug (dump ("CLI2::prepareFilter lexFilterArgs")); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// FILTER, Lexer::Type::word args are treated as search terms. +// +// Algorithm: +// Given: +// - task ... argX candidate argY +// Where: +// - neither argX nor argY are an operator, except (, ), and, or, xor +// - candidate is Lexer::Type::word +// +void CLI2::desugarFilterPlainArgs () +{ + // First walk the arg list looking for plain words that are not part of an + // existing expression. + auto prevprev = &_args[0]; + auto prev = &_args[0]; + for (auto& a : _args) + { + auto raw = a.attribute ("raw"); + auto praw = prev->attribute ("raw"); + auto ppraw = prevprev->attribute ("raw"); + + if ((prevprev->_lextype != Lexer::Type::op || // argX + ppraw == "(" || + ppraw == ")" || + ppraw == "and" || + ppraw == "or" || + ppraw == "xor") && + + (prev->_lextype == Lexer::Type::identifier || // candidate + prev->_lextype == Lexer::Type::word) && // candidate + + prev->hasTag ("FILTER") && // candidate + + (a._lextype != Lexer::Type::op || // argY + raw == "(" || + raw == ")" || + raw == "and" || + raw == "or" || + raw == "xor")) + { + prev->tag ("PLAIN"); + } + + prevprev = prev; + prev = &a; + } + + // Cover the case where the *last* argument is a plain arg. + auto& penultimate = _args[_args.size () - 2]; + auto praw = penultimate.attribute ("raw"); + auto& last = _args[_args.size () - 1]; + if ((penultimate._lextype != Lexer::Type::op || // argX + praw == "(" || + praw == ")" || + praw == "and" || + praw == "or" || + praw == "xor") && + + (last._lextype == Lexer::Type::identifier || // candidate + last._lextype == Lexer::Type::word) && // candidate + + last.hasTag ("FILTER")) // candidate + { + last.tag ("PLAIN"); + } + + + // Walk the list again, upgrading PLAIN args. + bool changes = false; + std::vector reconstructed; + for (auto& a : _args) + { + if (a.hasTag ("PLAIN")) + { + changes = true; + + A2 lhs ("description", Lexer::Type::dom); + lhs.attribute ("canonical", "description"); + lhs.tag ("FILTER"); + lhs.tag ("PLAIN"); + reconstructed.push_back (lhs); + + A2 op ("~", Lexer::Type::op); + op.tag ("FILTER"); + op.tag ("PLAIN"); + reconstructed.push_back (op); + + std::string word = a.attribute ("raw"); + Lexer::dequote (word); + A2 rhs (word, Lexer::Type::string); + rhs.tag ("FILTER"); + rhs.tag ("PLAIN"); + reconstructed.push_back (rhs); + } + else + reconstructed.push_back (a); + } + + if (changes) + { + _args = reconstructed; + + if (context.config.getInteger ("debug.parser") >= 2) + context.debug (dump ("CLI2::prepareFilter desugarFilterPlainArgs")); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Two consecutive FILTER, non-OP arguments that are not "(" or ")" need an +// "and" operator inserted between them. +// +// ) --> ) and +// ( --> ( +// ) ( --> ) and ( +// --> and +// +void CLI2::insertJunctions () +{ + bool changes = false; + std::vector reconstructed; + auto prev = _args.begin (); + + for (auto a = _args.begin (); a != _args.end (); ++a) + { + if (a->hasTag ("FILTER")) + { + // The prev iterator should be the first FILTER arg. + if (prev == _args.begin ()) + prev = a; + + // Insert AND between terms. + else if (a != prev) + { + if ((prev->_lextype != Lexer::Type::op && a->attribute ("raw") == "(") || + (prev->_lextype != Lexer::Type::op && a->_lextype != Lexer::Type::op) || + (prev->attribute ("raw") == ")" && a->_lextype != Lexer::Type::op) || + (prev->attribute ("raw") == ")" && a->attribute ("raw") == "(")) + { + A2 opOr ("and", Lexer::Type::op); + opOr.tag ("FILTER"); + reconstructed.push_back (opOr); + changes = true; + } + } + + // Previous FILTER arg. + prev = a; + } + + reconstructed.push_back (*a); + } + + if (changes) + { + _args = reconstructed; + + if (context.config.getInteger ("debug.parser") >= 2) + context.debug (dump ("CLI2::prepareFilter insertJunctions")); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Look for situations that require defaults: +// +// 1. If no command was found, and no ID/UUID, and if rc.default.command is +// configured, inject the lexed tokens from rc.default.command. +// +// 2. If no command was found, but an ID/UUID was found, then assume a command +// of 'information'. +// +void CLI2::defaultCommand () +{ + // Scan the top-level branches for evidence of ID, UUID, overrides and other + // arguments. + bool changes = false; + bool found_command = false; + bool found_sequence = false; + + for (auto& a : _args) + { + std::string raw = a.attribute ("raw"); + + if (a.hasTag ("CMD")) + found_command = true; + + if (a._lextype == Lexer::Type::uuid || + a._lextype == Lexer::Type::number) + found_sequence = true; + } + + // If no command was specified, then a command will be inserted. + if (! found_command) + { + // Default command. + if (! found_sequence) + { + // Apply overrides, if any. + std::string defaultCommand = context.config.get ("default.command"); + if (defaultCommand != "") + { + // Modify _args, _original_args to be: + // [ ...] [...] + + std::vector reconstructedOriginals {_original_args[0]}; + std::vector reconstructed {_args[0]}; + + std::string lexeme; + Lexer::Type type; + Lexer lex (defaultCommand); + + while (lex.token (lexeme, type)) + { + reconstructedOriginals.push_back (A2 (lexeme, type)); + + A2 cmd (lexeme, type); + cmd.tag ("DEFAULT"); + reconstructed.push_back (cmd); + } + + for (unsigned int i = 1; i < _original_args.size (); ++i) + reconstructedOriginals.push_back (_original_args[i]); + + for (unsigned int i = 1; i < _args.size (); ++i) + reconstructed.push_back (_args[i]); + + _original_args = reconstructedOriginals; + _args = reconstructed; + changes = true; + } + } + else + { + A2 info ("information", Lexer::Type::word); + info.tag ("ASSUMED"); + _args.push_back (info); + changes = true; + } + } + + if (changes && + context.config.getInteger ("debug.parser") >= 2) + context.debug (dump ("CLI2::analyze defaultCommand")); +} + +//////////////////////////////////////////////////////////////////////////////// +// Some values are expressions, which need to be lexed. The best way to +// determine whether an expression is either a single value, or needs to be +// lexed, is to lex it and count the tokens. For example: +// now+1d +// This should be lexed and surrounded by parentheses: +// ( +// now +// + +// 1d +// ) +std::vector CLI2::lexExpression (const std::string& expression) +{ + std::vector lexed; + std::string lexeme; + Lexer::Type type; + Lexer lex (expression); + while (lex.token (lexeme, type)) + { + A2 token (lexeme, type); + token.tag ("FILTER"); + lexed.push_back (token); + } + + // If there were multiple tokens, parenthesize, because this expression will + // be used as a value. + if (lexed.size () > 1) + { + A2 openParen ("(", Lexer::Type::op); + openParen.tag ("FILTER"); + A2 closeParen (")", Lexer::Type::op); + closeParen.tag ("FILTER"); + + lexed.insert (lexed.begin (), openParen); + lexed.push_back (closeParen); + } + + return lexed; +} + +//////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/CLI2.h task-2.5.0+dfsg/src/CLI2.h --- task-2.4.4+dfsg/src/CLI2.h 1970-01-01 00:00:00.000000000 +0000 +++ task-2.5.0+dfsg/src/CLI2.h 2015-10-21 21:18:14.000000000 +0000 @@ -0,0 +1,121 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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 +// +//////////////////////////////////////////////////////////////////////////////// +#ifndef INCLUDED_CLI2 +#define INCLUDED_CLI2 + +#include +#include +#include +#include +#include + +// Represents a single argument. +class A2 +{ +public: + A2 (const std::string&, Lexer::Type); + ~A2 (); + A2 (const A2&); + A2& operator= (const A2&); + bool hasTag (const std::string&) const; + void tag (const std::string&); + void unTag (const std::string&); + void attribute (const std::string&, const std::string&); + const std::string attribute (const std::string&) const; + const std::string getToken () const; + const std::string dump () const; + void decompose (); + +public: + Lexer::Type _lextype; + std::vector _tags; + std::map _attributes; +}; + +// Represents the command line. +class CLI2 +{ +public: + static int minimumMatchLength; + + static void getOverride (int, const char**, std::string&, File&); + static void getDataLocation (int, const char**, Path&); + static void applyOverrides (int, const char**); + +public: + CLI2 (); + ~CLI2 (); + void alias (const std::string&, const std::string&); + void entity (const std::string&, const std::string&); + + void add (const std::string&); + void add (const std::vector &); + void analyze (); + void addFilter (const std::string& arg); + void addContextFilter (); + void prepareFilter (); + const std::vector getWords (); + bool canonicalize (std::string&, const std::string&, const std::string&) const; + std::string getBinary () const; + std::string getCommand (bool canonical = true) const; + const std::string dump (const std::string& title = "CLI2 Parser") const; + +private: + void handleArg0 (); + void lexArguments (); + void demotion (); + void aliasExpansion (); + void canonicalizeNames (); + void categorizeArgs (); + void parenthesizeOriginalFilter (); + bool findCommand (); + bool exactMatch (const std::string&, const std::string&) const; + void desugarFilterTags (); + void findStrayModifications (); + void desugarFilterAttributes (); + void desugarFilterPatterns (); + void findIDs (); + void findUUIDs (); + void insertIDExpr (); + void lexFilterArgs (); + void desugarFilterPlainArgs (); + void insertJunctions (); + void defaultCommand (); + std::vector lexExpression (const std::string&); + +public: + std::multimap _entities; + std::map _aliases; + std::vector _original_args; + std::vector _args; + + std::vector > _id_ranges; + std::vector _uuid_list; + bool _context_filter_added; +}; + +#endif + diff -Nru task-2.4.4+dfsg/src/CLI.cpp task-2.5.0+dfsg/src/CLI.cpp --- task-2.4.4+dfsg/src/CLI.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/CLI.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,2469 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern Context context; - -// Overridden by rc.abbreviation.minimum. -int CLI::minimumMatchLength = 3; - -// Alias expansion limit. Any more indicates some kind of error. -static int safetyValveDefault = 10; - -//////////////////////////////////////////////////////////////////////////////// -A::A () -: _name ("") -{ -} - -//////////////////////////////////////////////////////////////////////////////// -A::A (const std::string& name, const std::string& raw) -{ - _name = name; - attribute ("raw", raw); -} - -//////////////////////////////////////////////////////////////////////////////// -A::A (const std::string& name, const int raw) -{ - _name = name; - attribute ("raw", raw); -} - -//////////////////////////////////////////////////////////////////////////////// -A::A (const std::string& name, const double raw) -{ - _name = name; - attribute ("raw", raw); -} - -//////////////////////////////////////////////////////////////////////////////// -A::~A () -{ -} - -//////////////////////////////////////////////////////////////////////////////// -A::A (const A& other) -: _name (other._name) -, _tags (other._tags) -, _attributes (other._attributes) -{ -} - -//////////////////////////////////////////////////////////////////////////////// -A& A::operator= (const A& other) -{ - if (this != &other) - { - _name = other._name; - _tags = other._tags; - _attributes = other._attributes; - } - - return *this; -} - -//////////////////////////////////////////////////////////////////////////////// -bool A::hasTag (const std::string& tag) const -{ - if (std::find (_tags.begin (), _tags.end (), tag) != _tags.end ()) - return true; - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -void A::tag (const std::string& tag) -{ - if (! hasTag (tag)) - _tags.push_back (tag); -} - -//////////////////////////////////////////////////////////////////////////////// -void A::unTag (const std::string& tag) -{ - std::vector ::iterator i; - for (i = _tags.begin (); i != _tags.end (); ++i) - { - if (*i == tag) - { - _tags.erase (i); - break; - } - } -} - -//////////////////////////////////////////////////////////////////////////////// -void A::unTagAll () -{ - _tags.clear (); -} - -//////////////////////////////////////////////////////////////////////////////// -// Accessor for attributes. -void A::attribute (const std::string& name, const std::string& value) -{ - _attributes[name] = value; -} - -//////////////////////////////////////////////////////////////////////////////// -// Accessor for attributes. -void A::attribute (const std::string& name, const int value) -{ - _attributes[name] = format (value); -} - -//////////////////////////////////////////////////////////////////////////////// -// Accessor for attributes. -void A::attribute (const std::string& name, const double value) -{ - _attributes[name] = format (value, 1, 8); -} - -//////////////////////////////////////////////////////////////////////////////// -// Accessor for attributes. -const std::string A::attribute (const std::string& name) const -{ - // Prevent autovivification. - std::map::const_iterator i = _attributes.find (name); - if (i != _attributes.end ()) - return i->second; - - return ""; -} - -//////////////////////////////////////////////////////////////////////////////// -void A::removeAttribute (const std::string& name) -{ - _attributes.erase (name); -} - -//////////////////////////////////////////////////////////////////////////////// -const std::string A::dump () const -{ - std::string output = _name; - - // Dump attributes. - std::string atts; - std::map ::const_iterator a; - for (a = _attributes.begin (); a != _attributes.end (); ++a) - { - if (a != _attributes.begin ()) - atts += " "; - - atts += a->first + "='\033[33m" + a->second + "\033[0m'"; - } - - if (atts.length ()) - output += " " + atts; - - // Dump tags. - std::string tags; - std::vector ::const_iterator tag; - for (tag = _tags.begin (); tag != _tags.end (); ++tag) - { - if (tags.length ()) - tags += ' '; - - if (*tag == "BINARY") tags += "\033[1;37;44m" + *tag + "\033[0m"; - else if (*tag == "CMD") tags += "\033[1;37;46m" + *tag + "\033[0m"; - else if (*tag == "FILTER") tags += "\033[1;37;42m" + *tag + "\033[0m"; - else if (*tag == "MODIFICATION") tags += "\033[1;37;43m" + *tag + "\033[0m"; - else if (*tag == "RC") tags += "\033[1;37;41m" + *tag + "\033[0m"; - else if (*tag == "CONFIG") tags += "\033[1;37;101m" + *tag + "\033[0m"; - else if (*tag == "PSEUDO") tags += "\033[1;37;45m" + *tag + "\033[0m"; - else if (*tag == "?") tags += "\033[38;5;255;48;5;232m" + *tag + "\033[0m"; - else tags += "\033[32m" + *tag + "\033[0m"; - } - - if (tags.length ()) - output += ' ' + tags; - - return output; -} - -//////////////////////////////////////////////////////////////////////////////// -// Static method. -void CLI::getOverride (int argc, const char** argv, std::string& home, File& rc) -{ - for (int i = 0; i < argc; ++i) - { - std::string raw = argv[i]; - - if (raw == "--") - return; - - if (raw.length () > 3 && - raw.substr (0, 3) == "rc:") - { - rc = raw.substr (3); - - home = "."; - std::string::size_type last_slash = rc._data.rfind ("/"); - if (last_slash != std::string::npos) - home = rc.parent (); - - context.header (format (STRING_PARSER_ALTERNATE_RC, rc._data)); - - // Keep looping, because if there are multiple rc:file arguments, the last - // one should dominate. - } - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Look for CONFIG data.location and initialize a Path object. -void CLI::getDataLocation (int argc, const char** argv, Path& data) -{ - std::string location = context.config.get ("data.location"); - if (location != "") - data = location; - - bool terminated = false; - for (int i = 0; i < argc; ++i) - { - std::string raw = argv[i]; - - if (raw == "--") - terminated = true; - - if (! terminated && - raw.length () > 17 && - raw.substr (0, 16) == "rc.data.location") - { - data = Directory (raw.substr (17)); - context.header (format (STRING_PARSER_ALTERNATE_DATA, (std::string) data)); - - // Keep looping, because if there are multiple rc:file arguments, the last - // one should dominate. - } - } -} - -//////////////////////////////////////////////////////////////////////////////// -void CLI::applyOverrides (int argc, const char** argv) -{ - bool terminated = false; - for (int i = 0; i < argc; ++i) - { - std::string raw = argv[i]; - - if (raw == "--") - terminated = true; - - if (! terminated && - raw.length () > 3 && - raw.substr (0, 3) == "rc.") - { - std::string::size_type sep = raw.find ('=', 3); - if (sep == std::string::npos) - sep = raw.find (':', 3); - if (sep != std::string::npos) - { - std::string name = raw.substr (3, sep - 3); - std::string value = raw.substr (sep + 1); - context.config.set (name, value); - context.footnote (format (STRING_PARSER_OVERRIDE_RC, name, value)); - } - } - } -} - -//////////////////////////////////////////////////////////////////////////////// -CLI::CLI () -: _strict (false) -, _terminated (false) -{ -} - -//////////////////////////////////////////////////////////////////////////////// -CLI::~CLI () -{ -} - -//////////////////////////////////////////////////////////////////////////////// -void CLI::alias (const std::string& name, const std::string& value) -{ - _aliases.insert (std::pair (name, value)); -} - -//////////////////////////////////////////////////////////////////////////////// -void CLI::entity (const std::string& category, const std::string& name) -{ - // Find the category. - std::pair ::const_iterator, std::multimap ::const_iterator> c; - c = _entities.equal_range (category); - - // Walk the list of entities for category. - std::multimap ::const_iterator e; - for (e = c.first; e != c.second; ++e) - if (e->second == name) - return; - - // The category/name pair was not found, therefore add it. - _entities.insert (std::pair (category, name)); -} - -//////////////////////////////////////////////////////////////////////////////// -// Capture the original, intact command line arguments. -void CLI::initialize (int argc, const char** argv) -{ - // Clean what needs to be cleaned. Everything in this case. - _original_args.clear (); - _id_ranges.clear (); - _uuid_list.clear (); - _terminated = false; - - _original_args.push_back (argv[0]); - for (int i = 1; i < argc; ++i) - { - if (isTerminator (argv[i])) - _terminated = true; - addArg (argv[i]); - } - - analyze (); -} - -//////////////////////////////////////////////////////////////////////////////// -// Capture a single argument, and recalc everything. -void CLI::add (const std::string& arg) -{ - // Clean the ID/UUID lists, because they will be rebuilt. - _id_ranges.clear (); - _uuid_list.clear (); - - addArg (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 ::const_iterator a; - for (a = _args.begin (); a != _args.end (); ++a) - { - // TODO This looks wrong. - 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 -// is a need to extract overrides early, before entities are proviedd. -void CLI::analyze (bool parse /* = true */, bool strict /* = false */) -{ - // Clean what needs to be cleaned. Most in this case. - _args.clear (); - _id_ranges.clear (); - _uuid_list.clear (); - - // For propagation. - _strict = strict; - - for (unsigned int i = 0; i < _original_args.size (); ++i) - { - std::string raw = _original_args[i]; - A a ("arg", raw); - a.tag ("ORIGINAL"); - - if (i == 0) - { - a.tag ("BINARY"); - - std::string basename = "task"; - std::string::size_type slash = raw.rfind ('/'); - if (slash != std::string::npos) - basename = raw.substr (slash + 1); - - a.attribute ("basename", basename); - if (basename == "cal" || basename == "calendar") - a.tag ("CALENDAR"); - else if (basename == "task" || basename == "tw" || basename == "t") - a.tag ("TW"); - } - - _args.push_back (a); - - if (a.hasTag ("CALENDAR")) - { - A cal ("argCal", "calendar"); - _args.push_back (cal); - } - } - - if (context.config.getInteger ("debug.parser") >= 3) - context.debug (context.cli.dump ("CLI::analyze start")); - - // Find argument types. - aliasExpansion (); - findOverrides (); - applyOverrides (); - injectDefaults (); - categorize (); - - if (parse) - { - // Remove all the syntactic sugar for FILTERs. - findIDs (); - findUUIDs (); - insertIDExpr (); - desugarFilterTags (); - findStrayModifications (); - desugarFilterAttributes (); - desugarFilterAttributeModifiers (); - desugarFilterPatterns (); - findOperators (); - findAttributes (); - desugarFilterPlainArgs (); - insertJunctions (); // Deliberately after all desugar calls. - - // Decompose the elements for MODIFICATIONs. - decomposeModAttributes (); - decomposeModAttributeModifiers (); - decomposeModTags (); - decomposeModSubstitutions (); - } - - if (context.config.getInteger ("debug.parser") >= 3) - context.debug ("CLI::analyze end"); -} - -//////////////////////////////////////////////////////////////////////////////// -void CLI::applyOverrides () -{ - std::vector ::const_iterator a; - for (a = _args.begin (); a != _args.end (); ++a) - { - if (a->hasTag ("CONFIG")) - { - std::string name = a->attribute ("name"); - std::string value = a->attribute ("value"); - context.config.set (name, value); - context.footnote (format (STRING_PARSER_OVERRIDE_RC, name, value)); - } - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Extract all the FILTER-tagged items. -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 ()) - { - std::vector ::const_iterator a; - for (a = _args.begin (); a != _args.end (); ++a) - { - if (a->hasTag ("FILTER")) - { - if (filter != "") - filter += ' '; - - std::string term = a->attribute ("name"); - if (term == "") - term = a->attribute ("raw"); - - filter += term; - } - } - - // Only apply parentheses for non-trivial filters. - if (filter != "") - filter = "( " + filter + " )"; - } - - context.debug("Derived filter: '" + filter + "'"); - return filter; -} - -//////////////////////////////////////////////////////////////////////////////// -const std::vector CLI::getWords () -{ - // Re-analyze the arguments, but do not de-sugar or decompose any. Analysis - // only. - analyze (false); - - std::vector words; - std::vector ::const_iterator a; - for (a = _args.begin (); a != _args.end (); ++a) - { - if (! a->hasTag ("BINARY") && - ! a->hasTag ("RC") && - ! a->hasTag ("CONFIG") && - ! a->hasTag ("CMD") && - ! a->hasTag ("TERMINATOR")) - { - words.push_back (a->attribute ("raw")); - } - } - - return words; -} - -//////////////////////////////////////////////////////////////////////////////// -// Search for 'value' in _entities category, return canonicalized value. -bool CLI::canonicalize ( - std::string& canonicalized, - const std::string& category, - const std::string& value) const -{ - // Find the category. - std::pair ::const_iterator, std::multimap ::const_iterator> c; - c = _entities.equal_range (category); - - // Extract a list of entities for category. - std::vector options; - std::multimap ::const_iterator e; - for (e = c.first; e != c.second; ++e) - { - // Shortcut: if an exact match is found, success. - if (value == e->second) - { - canonicalized = value; - return true; - } - - options.push_back (e->second); - } - - // Match against the options, throw away results. - std::vector matches; - if (autoComplete (value, options, matches, minimumMatchLength) == 1) - { - canonicalized = matches[0]; - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -std::string CLI::getBinary () const -{ - if (_args.size ()) - return _args[0].attribute ("raw"); - - return ""; -} - -//////////////////////////////////////////////////////////////////////////////// -std::string CLI::getCommand () const -{ - std::vector ::const_iterator a; - for (a = _args.begin (); a != _args.end (); ++a) - if (a->hasTag ("CMD")) - return a->attribute ("canonical"); - - return ""; -} - -//////////////////////////////////////////////////////////////////////////////// -std::string CLI::getLimit () const -{ - std::vector ::const_iterator a; - for (a = _args.begin (); a != _args.end (); ++a) - if (a->hasTag ("PSEUDO") && - a->attribute ("canonical") == "limit") - return a->attribute ("value"); - - return "0"; -} - -//////////////////////////////////////////////////////////////////////////////// -const std::string CLI::dump (const std::string& title /* = "CLI Parser" */) const -{ - std::stringstream out; - - out << "\033[1m" << title << "\033[0m\n" - << " _original_args\n "; - Color colorOrigArgs ("gray10 on gray4"); - std::vector ::const_iterator i; - for (i = _original_args.begin (); i != _original_args.end (); ++i) - { - if (i != _original_args.begin ()) - out << ' '; - out << colorOrigArgs.colorize (*i); - } - out << "\n"; - - out << " _args\n"; - std::vector ::const_iterator a; - for (a = _args.begin (); a != _args.end (); ++a) - out << " " << a->dump () << "\n"; - - return out.str (); -} - -//////////////////////////////////////////////////////////////////////////////// -// Note: This seems silly - it's essentially performing a low-quality parse. But -// that is really all that is needed - to separate the args that need to -// be lexed from those that need to be left alone. -// -// Either the arg is appended to _original_args intact, or the lexemes are. -void CLI::addArg (const std::string& arg, Lexer::Type type /* = Lexer::Type::word */) -{ - std::string raw = trim (arg); - - // Do not lex these constructs. - if (isTerminator (raw)) // -- - _terminated = true; - - // This is the case where the argument should not be lexed. - if (_terminated || - isRCOverride (raw) || // rc: - isConfigOverride (raw) || // rc.: - isCommand (raw) || // - isTag (raw) || // [+-] - isUUIDList (raw) || // ,[uuid ...] - isUUID (raw) || // - isIDSequence (raw) || // [-][,[-] ...] - isID (raw) || // - isPattern (raw) || // ///[g] - isAttribute (raw) || // [.[~]]: - isOperator (raw)) // - { - _original_args.push_back (raw); - } - - // The argument may require lexing. Lex anyway, and analyze before comitting - // to that. - else - { - // Lex each remaining argument. The apply a series of disqualifying tests - // that cause the lexemes to be ignored, and the original arugment used - // intact. - std::string lexeme; - Lexer::Type type; - Lexer lex (raw); - lex.ambiguity (false); - - std::vector > lexemes; - while (lex.token (lexeme, type)) - lexemes.push_back (std::pair (lexeme, type)); - - if (disqualifyInsufficientTerms (lexemes) || - disqualifyNoOps (lexemes) || - disqualifyOnlyParenOps (lexemes) || - disqualifyFirstLastBinary (lexemes) || - disqualifySugarFree (lexemes)) - { - _original_args.push_back (raw); - } - else - { - // How often have I said to you that when you have eliminated the - // impossible, whatever remains, however improbable, must be the truth? - std::vector >::iterator l; - for (l = lexemes.begin (); l != lexemes.end (); ++l) - _original_args.push_back (l->first); - } - } -} - -//////////////////////////////////////////////////////////////////////////////// -void CLI::aliasExpansion () -{ - bool changes = false; - bool action; - int counter = 0; - do - { - action = false; - std::vector reconstructed; - - bool terminated = false; - std::string raw; - std::vector ::iterator i; - for (i = _args.begin (); i != _args.end (); ++i) - { - raw = i->attribute ("raw"); - - if (raw == "--") - terminated = true; - - if (! terminated) - { - if (_aliases.find (raw) != _aliases.end ()) - { - std::vector lexed = Lexer::split (_aliases[raw]); - std::vector ::iterator l; - for (l = lexed.begin (); l != lexed.end (); ++l) - { - A a ("argLex", *l); - a.tag ("ALIAS"); - a.tag ("LEX"); - reconstructed.push_back (a); - } - - action = true; - changes = true; - } - else - reconstructed.push_back (*i); - } - else - reconstructed.push_back (*i); - } - - _args = reconstructed; - } - while (action && counter++ < safetyValveDefault); - - if (counter >= safetyValveDefault) - context.debug (format (STRING_PARSER_ALIAS_NEST, safetyValveDefault)); - - if (changes && - context.config.getInteger ("debug.parser") >= 3) - context.debug (context.cli.dump ("CLI::analyze aliasExpansion")); -} - -//////////////////////////////////////////////////////////////////////////////// -void CLI::findOverrides () -{ - bool changes = false; - std::string raw; - bool terminated = false; - std::vector ::iterator a; - for (a = _args.begin (); a != _args.end (); ++a) - { - raw = a->attribute ("raw"); - - if (raw == "--") - terminated = true; - - if (terminated) - continue; - - if (isRCOverride (raw)) - { - a->tag ("RC"); - a->attribute ("file", raw.substr (3)); - changes = true; - } - else if (isConfigOverride (raw)) - { - std::string::size_type sep = raw.find ('=', 3); - if (sep == std::string::npos) - sep = raw.find (':', 3); - if (sep != std::string::npos) - { - a->tag ("CONFIG"); - a->attribute ("name", raw.substr (3, sep - 3)); - a->attribute ("value", raw.substr (sep + 1)); - changes = true; - } - } - } - - if (changes && - context.config.getInteger ("debug.parser") >= 3) - context.debug (context.cli.dump ("CLI::analyze findOverrides")); -} - -//////////////////////////////////////////////////////////////////////////////// -void CLI::categorize () -{ - bool changes = false; - bool foundCommand = false; - bool readOnly = false; - bool terminated = false; - - std::vector ::iterator a; - for (a = _args.begin (); a != _args.end (); ++a) - { - std::string raw = a->attribute ("raw"); - - if (! terminated && raw == "--") - { - a->tag ("ORIGINAL"); - a->tag ("TERMINATOR"); - terminated = true; - changes = true; - continue; - } - - else if (terminated) - { - a->tag ("ORIGINAL"); - a->tag ("TERMINATED"); - a->tag ("WORD"); - changes = true; - } - - if (raw.find (' ') != std::string::npos) - { - a->tag ("QUOTED"); - changes = true; - } - - std::string canonical; - if (! terminated && - ! foundCommand && - canonicalize (canonical, "cmd", raw)) - { - readOnly = ! exactMatch ("writecmd", canonical); - - a->tag ("CMD"); - a->tag (readOnly ? "READCMD" : "WRITECMD"); - a->attribute ("canonical", canonical); - foundCommand = true; - changes = true; - } - else if (a->hasTag ("TERMINATOR") || - a->hasTag ("BINARY") || - a->hasTag ("CONFIG") || - a->hasTag ("RC")) - { - // NOP - } - else if (foundCommand && ! readOnly) - { - a->tag ("MODIFICATION"); - - // If the argument contains a space, it was quoted. Record that. - if (! Lexer::isOneWord (raw)) - a->tag ("QUOTED"); - - changes = true; - } - else if (!foundCommand || (foundCommand && readOnly)) - { - a->tag ("FILTER"); - - // If the argument contains a space, it was quoted. Record that. - if (! Lexer::isOneWord (raw)) - a->tag ("QUOTED"); - - changes = true; - } - } - - if (changes && - context.config.getInteger ("debug.parser") >= 3) - context.debug (context.cli.dump ("CLI::analyze categorize")); -} - -//////////////////////////////////////////////////////////////////////////////// -// Search for exact 'value' in _entities category. -bool CLI::exactMatch ( - const std::string& category, - const std::string& value) const -{ - // Find the category. - std::pair ::const_iterator, std::multimap ::const_iterator> c; - c = _entities.equal_range (category); - - // Extract a list of entities for category. - std::vector options; - std::multimap ::const_iterator e; - for (e = c.first; e != c.second; ++e) - { - // Shortcut: if an exact match is found, success. - if (value == e->second) - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// +tag --> tags _hastag_ tag -// -tag --> tags _notag_ tag -void CLI::desugarFilterTags () -{ - bool changes = false; - std::vector reconstructed; - std::vector ::iterator a; - for (a = _args.begin (); a != _args.end (); ++a) - { - if (a->hasTag ("FILTER")) - { - Nibbler n (a->attribute ("raw")); - std::string tag; - std::string sign; - - if (n.getN (1, sign) && - (sign == "+" || sign == "-") && - n.getUntilEOS (tag) && - tag.find (' ') == std::string::npos) - { - A left ("argTag", "tags"); - left.tag ("ATTRIBUTE"); - left.tag ("FILTER"); - reconstructed.push_back (left); - - A op ("argTag", sign == "+" ? "_hastag_" : "_notag_"); - op.tag ("OP"); - op.tag ("FILTER"); - reconstructed.push_back (op); - - A right ("argTag", "'" + tag + "'"); - right.tag ("LITERAL"); - right.tag ("FILTER"); - reconstructed.push_back (right); - - changes = true; - } - else - reconstructed.push_back (*a); - } - else - reconstructed.push_back (*a); - } - - if (changes) - { - _args = reconstructed; - - if (context.config.getInteger ("debug.parser") >= 3) - context.debug (context.cli.dump ("CLI::analyze desugarFilterTags")); - } -} - -//////////////////////////////////////////////////////////////////////////////// -void CLI::findStrayModifications () -{ - bool changes = false; - - std::string command = getCommand (); - if (command == "add" || - command == "log") - { - std::vector ::iterator a; - for (a = _args.begin (); a != _args.end (); ++a) - { - if (a->hasTag ("FILTER")) - { - a->unTag ("FILTER"); - a->tag ("MODIFICATION"); - changes = true; - } - } - } - - if (changes) - if (context.config.getInteger ("debug.parser") >= 3) - context.debug (context.cli.dump ("CLI::analyze findStrayModifications")); -} - -//////////////////////////////////////////////////////////////////////////////// -// :['"][]['"] --> name = value -void CLI::desugarFilterAttributes () -{ - bool changes = false; - std::vector reconstructed; - std::vector ::iterator a; - for (a = _args.begin (); a != _args.end (); ++a) - { - if (a->hasTag ("FILTER")) - { - // Look for a valid attribute name. - bool found = false; - Nibbler n (a->attribute ("raw")); - std::string name; - if (n.getName (name) && - name.length ()) - { - if (n.skip (':') || - n.skip ('=')) - { - std::string value; - if (n.getQuoted ('"', value) || - n.getQuoted ('\'', value) || - n.getUntilEOS (value) || - n.depleted ()) - { - if (value == "") - value = "''"; - - std::string canonical; - if (canonicalize (canonical, "uda", name)) - { - A lhs ("argUDA", name); - lhs.attribute ("name", canonical); - lhs.tag ("UDA"); - lhs.tag ("ATTRIBUTE"); - lhs.tag ("FILTER"); - - A op ("argUDA", "="); - op.tag ("OP"); - op.tag ("FILTER"); - - A rhs ("argUDA", value); - rhs.tag ("LITERAL"); - rhs.tag ("FILTER"); - - reconstructed.push_back (lhs); - reconstructed.push_back (op); - reconstructed.push_back (rhs); - found = true; - } - - else if (canonicalize (canonical, "pseudo", name)) - { - A lhs ("argPseudo", a->attribute ("raw")); - lhs.attribute ("canonical", canonical); - lhs.attribute ("value", value); - lhs.tag ("PSEUDO"); - reconstructed.push_back (lhs); - found = true; - } - - else if (canonicalize (canonical, "attribute", name)) - { - A lhs ("argAtt", name); - lhs.attribute ("name", canonical); - lhs.tag ("ATTRIBUTE"); - lhs.tag ("FILTER"); - - std::string operatorLiteral = "="; - if (canonical == "status") - operatorLiteral = "=="; - - A op ("argAtt", operatorLiteral); - op.tag ("OP"); - op.tag ("FILTER"); - - A rhs ("argAtt", value); - rhs.tag ("LITERAL"); - rhs.tag ("FILTER"); - - reconstructed.push_back (lhs); - reconstructed.push_back (op); - reconstructed.push_back (rhs); - found = true; - } - } - } - } - - if (found) - changes = true; - else - reconstructed.push_back (*a); - } - else - reconstructed.push_back (*a); - } - - if (changes) - { - _args = reconstructed; - - if (context.config.getInteger ("debug.parser") >= 3) - context.debug (context.cli.dump ("CLI::analyze desugarFilterAttributes")); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// .[~][:=]['"]['"] --> name value -void CLI::desugarFilterAttributeModifiers () -{ - bool changes = false; - std::vector reconstructed; - std::vector ::iterator a; - for (a = _args.begin (); a != _args.end (); ++a) - { - if (a->hasTag ("FILTER")) - { - // Look for a valid attribute name. - bool found = false; - Nibbler n (a->attribute ("raw")); - std::string name; - if (n.getUntil (".", name) && - name.length ()) - { - std::string canonical; - if (canonicalize (canonical, "attribute", name) || - canonicalize (canonical, "uda", name)) - { - if (n.skip ('.')) - { - std::string sense = "+"; - if (n.skip ('~')) - sense = "-"; - - std::string modifier; - n.getUntilOneOf (":=", modifier); - - if (n.skip (':') || - n.skip ('=')) - { - std::string value; - if (n.getQuoted ('"', value) || - n.getQuoted ('\'', value) || - n.getUntilEOS (value) || - n.depleted ()) - { - if (value == "") - value = "''"; - - A lhs ("argAttMod", name); - lhs.tag ("ATTMOD"); - lhs.tag ("FILTER"); - - lhs.attribute ("name", canonical); - lhs.attribute ("modifier", modifier); - lhs.attribute ("sense", sense); - - A op ("argAttmod", ""); - op.tag ("FILTER"); - op.tag ("OP"); - - A rhs ("argAttMod", ""); - rhs.tag ("FILTER"); - - if (modifier == "before" || modifier == "under" || modifier == "below") - { - op.attribute ("raw", "<"); - rhs.attribute ("raw", value); - rhs.tag ("LITERAL"); - } - else if (modifier == "after" || modifier == "over" || modifier == "above") - { - op.attribute ("raw", ">"); - rhs.attribute ("raw", value); - rhs.tag ("LITERAL"); - } - else if (modifier == "none") - { - op.attribute ("raw", "=="); - rhs.attribute ("raw", "''"); - rhs.tag ("LITERAL"); - } - else if (modifier == "any") - { - op.attribute ("raw", "!="); - rhs.attribute ("raw", "''"); - rhs.tag ("LITERAL"); - } - else if (modifier == "is" || modifier == "equals") - { - op.attribute ("raw", "=="); - rhs.attribute ("raw", "'" + value + "'"); - rhs.tag ("LITERAL"); - } - else if (modifier == "isnt" || modifier == "not") - { - op.attribute ("raw", "!=="); - rhs.attribute ("raw", "'" + value + "'"); - rhs.tag ("LITERAL"); - } - else if (modifier == "has" || modifier == "contains") - { - op.attribute ("raw", "~"); - rhs.attribute ("raw", "'" + value + "'"); - rhs.tag ("LITERAL"); - } - else if (modifier == "hasnt") - { - op.attribute ("raw", "!~"); - rhs.attribute ("raw", "'" + value + "'"); - rhs.tag ("LITERAL"); - } - else if (modifier == "startswith" || modifier == "left") - { - op.attribute ("raw", "~"); - rhs.attribute ("raw", "'^" + value + "'"); - rhs.tag ("REGEX"); - } - else if (modifier == "endswith" || modifier == "right") - { - op.attribute ("raw", "~"); - rhs.attribute ("raw", "'" + value + "$'"); - rhs.tag ("REGEX"); - } - else if (modifier == "word") - { - op.attribute ("raw", "~"); -#if defined (DARWIN) - rhs.attribute ("raw", value); -#elif defined (SOLARIS) - rhs.attribute ("raw", "'\\<" + value + "\\>'"); -#else - rhs.attribute ("raw", "'\\b" + value + "\\b'"); -#endif - rhs.tag ("REGEX"); - } - else if (modifier == "noword") - { - op.attribute ("raw", "!~"); -#if defined (DARWIN) - rhs.attribute ("raw", value); -#elif defined (SOLARIS) - rhs.attribute ("raw", "'\\<" + value + "\\>'"); -#else - rhs.attribute ("raw", "'\\b" + value + "\\b'"); -#endif - rhs.tag ("REGEX"); - } - else - throw format (STRING_PARSER_UNKNOWN_ATTMOD, modifier); - - reconstructed.push_back (lhs); - reconstructed.push_back (op); - reconstructed.push_back (rhs); - found = true; - } - } - } - } - } - - if (found) - changes = true; - else - reconstructed.push_back (*a); - } - else - reconstructed.push_back (*a); - } - - if (changes) - { - _args = reconstructed; - - if (context.config.getInteger ("debug.parser") >= 3) - context.debug (context.cli.dump ("CLI::analyze desugarFilterAttributeModifiers")); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// /pattern/ --> description ~ 'pattern' -void CLI::desugarFilterPatterns () -{ - bool changes = false; - std::vector reconstructed; - std::vector ::iterator a; - for (a = _args.begin (); a != _args.end (); ++a) - { - if (a->hasTag ("FILTER")) - { - Nibbler n (a->attribute ("raw")); - std::string pattern; - - if (n.getQuoted ('/', pattern) && - n.depleted () && - pattern.length () > 0) - { - A lhs ("argPattern", "description"); - lhs.tag ("ATTRIBUTE"); - lhs.tag ("FILTER"); - reconstructed.push_back (lhs); - - A op ("argPattern", "~"); - op.tag ("OP"); - op.tag ("FILTER"); - reconstructed.push_back (op); - - A rhs ("argPattern", "'" + pattern + "'"); - rhs.tag ("LITERAL"); - rhs.tag ("FILTER"); - reconstructed.push_back (rhs); - changes = true; - } - else - reconstructed.push_back (*a); - } - else - reconstructed.push_back (*a); - } - - if (changes) - { - _args = reconstructed; - - if (context.config.getInteger ("debug.parser") >= 3) - context.debug (context.cli.dump ("CLI::analyze desugarFilterPatterns")); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// An ID sequence can be: -// -// a single ID: 1 -// a list of IDs: 1,3,5 -// a list of IDs: 1 3 5 -// a range: 5-10 -// or a combination: 1,3,5-10 12 -// -void CLI::findIDs () -{ - std::vector ::iterator a; - for (a = _args.begin (); a != _args.end (); ++a) - { - if (a->hasTag ("FILTER")) - { - // IDs have a limited character set. - std::string raw = a->attribute ("raw"); - if (raw.find_first_not_of ("0123456789,-") == std::string::npos) - { - // Container for min/max ID ranges. - std::vector > ranges; - - // Split the ID list into elements. - std::vector elements; - split (elements, raw, ','); - - bool is_an_id = true; - std::vector ::iterator e; - for (e = elements.begin (); e != elements.end (); ++e) - { - // Split the ID range into min/max. - std::vector terms; - split (terms, *e, '-'); - - if (terms.size () == 1) - { - if (! Lexer::isAllDigits (terms[0])) - { - is_an_id = false; - break; - } - - Nibbler n (terms[0]); - int id; - if (n.getUnsignedInt (id) && - n.depleted ()) - { - ranges.push_back (std::pair (id, id)); - } - else - { - is_an_id = false; - break; - } - } - else if (terms.size () == 2) - { - if (! Lexer::isAllDigits (terms[0]) || - ! Lexer::isAllDigits (terms[1])) - { - is_an_id = false; - break; - } - - Nibbler n_min (terms[0]); - Nibbler n_max (terms[1]); - int id_min; - int id_max; - if (n_min.getUnsignedInt (id_min) && - n_min.depleted () && - n_max.getUnsignedInt (id_max) && - n_max.depleted ()) - { - if (id_min > id_max) - { - is_an_id = false; - break; - } - - ranges.push_back (std::pair (id_min, id_max)); - } - else - { - is_an_id = false; - break; - } - } - else - { - is_an_id = false; - break; - } - } - - if (is_an_id) - { - a->tag ("ID"); - - // Save the ranges. - std::vector >::iterator r; - for (r = ranges.begin (); r != ranges.end (); ++r) - _id_ranges.push_back (*r); - } - } - } - } -} - -//////////////////////////////////////////////////////////////////////////////// -void CLI::findUUIDs () -{ - std::vector ::iterator a; - for (a = _args.begin (); a != _args.end (); ++a) - { - if (a->hasTag ("FILTER")) - { - // UUIDs have a limited character set. - std::string raw = a->attribute ("raw"); - if (raw.find_first_not_of ("0123456789abcdefABCDEF-,") == std::string::npos) - { - Nibbler n (raw); - std::vector uuidList; - std::string uuid; - if (n.getUUID (uuid) || - n.getPartialUUID (uuid)) - { - uuidList.push_back (uuid); - - while (n.skip (',')) - { - if (! n.getUUID (uuid) && - ! n.getPartialUUID (uuid)) - throw std::string (STRING_PARSER_UUID_AFTER_COMMA); - - uuidList.push_back (uuid); - } - - if (n.depleted ()) - { - a->tag ("UUID"); - - // Save the list. - std::vector ::iterator u; - for (u = uuidList.begin (); u != uuidList.end (); ++u) - _uuid_list.push_back (*u); - } - } - } - } - } -} - -//////////////////////////////////////////////////////////////////////////////// -void CLI::insertIDExpr () -{ - // Iterate over all args. The first ID/UUID arg found will be replaced by - // the combined ID clause. All other ID/UUID args are removed. - bool changes = false; - bool foundID = false; - std::vector reconstructed; - std::vector ::iterator a; - for (a = _args.begin (); a != _args.end (); ++a) - { - if (a->hasTag ("FILTER") && - (a->hasTag ("ID") || - a->hasTag ("UUID"))) - { - if (! foundID) - { - foundID = true; - - // Construct a single sequence that represents all _id_ranges and - // _uuid_list in one clause. This is essentially converting this: - // - // 1,2-3 uuid,uuid uuid 4 - // - // into: - // - // ( - // ( id == 1 ) - // or ( ( id >= 2 ) and ( id <= 3 ) ) - // or ( id == 4 ) - // or ( uuid = $UUID ) - // or ( uuid = $UUID ) - // ) - - // Building block operators. - A openParen ("argSeq", "("); openParen.tag ("FILTER"); openParen.tag ("OP"); - A closeParen ("argSeq", ")"); closeParen.tag ("FILTER"); closeParen.tag ("OP"); - A opOr ("argSeq", "or"); opOr.tag ("FILTER"); opOr.tag ("OP"); - A opAnd ("argSeq", "and"); opAnd.tag ("FILTER"); opAnd.tag ("OP"); - A opSimilar ("argSeq", "="); opSimilar.tag ("FILTER"); opSimilar.tag ("OP"); - A opEqual ("argSeq", "=="); opEqual.tag ("FILTER"); opEqual.tag ("OP"); - A opGTE ("argSeq", ">="); opGTE.tag ("FILTER"); opGTE.tag ("OP"); - A opLTE ("argSeq", "<="); opLTE.tag ("FILTER"); opLTE.tag ("OP"); - - // Building block attributes. - A argID ("argSeq", "id"); - argID.tag ("FILTER"); - argID.tag ("ATTRIBUTE"); - - A argUUID ("argSeq", "uuid"); - argUUID.tag ("FILTER"); - argUUID.tag ("ATTRIBUTE"); - - reconstructed.push_back (openParen); - - // Add all ID ranges. - std::vector >::iterator r; - for (r = _id_ranges.begin (); r != _id_ranges.end (); ++r) - { - if (r != _id_ranges.begin ()) - reconstructed.push_back (opOr); - - if (r->first == r->second) - { - reconstructed.push_back (openParen); - reconstructed.push_back (argID); - reconstructed.push_back (opEqual); - - A value ("argSeq", r->first); - value.tag ("FILTER"); - value.tag ("LITERAL"); - value.tag ("NUMBER"); - reconstructed.push_back (value); - - reconstructed.push_back (closeParen); - } - else - { - reconstructed.push_back (openParen); - reconstructed.push_back (argID); - reconstructed.push_back (opGTE); - - A startValue ("argSeq", r->first); - startValue.tag ("FILTER"); - startValue.tag ("LITERAL"); - startValue.tag ("NUMBER"); - reconstructed.push_back (startValue); - - reconstructed.push_back (opAnd); - reconstructed.push_back (argID); - reconstructed.push_back (opLTE); - - A endValue ("argSeq", r->second); - endValue.tag ("FILTER"); - endValue.tag ("LITERAL"); - endValue.tag ("NUMBER"); - reconstructed.push_back (endValue); - - reconstructed.push_back (closeParen); - } - } - - // Combine the ID and UUID sections with 'or'. - if (_id_ranges.size () && - _uuid_list.size ()) - reconstructed.push_back (opOr); - - // Add all UUID list items. - std::vector ::iterator u; - for (u = _uuid_list.begin (); u != _uuid_list.end (); ++u) - { - if (u != _uuid_list.begin ()) - reconstructed.push_back (opOr); - - reconstructed.push_back (openParen); - reconstructed.push_back (argUUID); - reconstructed.push_back (opSimilar); - - A value ("argSeq", "'" + *u + "'"); - value.tag ("FILTER"); - value.tag ("LITERAL"); - value.tag ("STRING"); - reconstructed.push_back (value); - - reconstructed.push_back (closeParen); - } - - reconstructed.push_back (closeParen); - changes = true; - } - - // No 'else' which cause all other ID/UUID args to be eaten. - } - else - reconstructed.push_back (*a); - } - - if (changes) - { - _args = reconstructed; - - if (context.config.getInteger ("debug.parser") >= 3) - context.debug (context.cli.dump ("CLI::analyze insertIDExpr")); - } -} - -//////////////////////////////////////////////////////////////////////////////// -void CLI::desugarFilterPlainArgs () -{ - bool changes = false; - std::vector reconstructed; - std::vector ::iterator a; - std::vector ::iterator prev = _args.begin (); - for (a = _args.begin (); a != _args.end (); ++a) - { - if (a != prev && // Not the first arg. - ! prev->hasTag ("OP") && // An OP before protects the arg. - a->hasTag ("FILTER") && - ! a->hasTag ("ATTRIBUTE") && - ! a->hasTag ("ATTMOD") && - ! a->hasTag ("OP") && - ! a->hasTag ("REGEX") && - ! a->hasTag ("LITERAL")) - { - A lhs ("argPattern", "description"); - lhs.tag ("ATTRIBUTE"); - lhs.tag ("FILTER"); - reconstructed.push_back (lhs); - - A op ("argPattern", "~"); - op.tag ("OP"); - op.tag ("FILTER"); - reconstructed.push_back (op); - - std::string pattern = a->attribute ("raw"); - Lexer::dequote (pattern); - A rhs ("argPattern", "'" + pattern + "'"); - rhs.tag ("LITERAL"); - rhs.tag ("FILTER"); - reconstructed.push_back (rhs); - changes = true; - } - else - reconstructed.push_back (*a); - - prev = a; - } - - if (changes) - { - _args = reconstructed; - - if (context.config.getInteger ("debug.parser") >= 3) - context.debug (context.cli.dump ("CLI::analyze desugarFilterPlainArgs")); - } -} - -//////////////////////////////////////////////////////////////////////////////// -void CLI::findOperators () -{ - // Find the category. - std::pair ::const_iterator, std::multimap ::const_iterator> c; - c = _entities.equal_range ("operator"); - - // Extract a list of entities for category. - std::vector options; - std::multimap ::const_iterator e; - for (e = c.first; e != c.second; ++e) - options.push_back (e->second); - - // Walk the arguments and tag as OP. - bool changes = false; - std::vector ::iterator a; - for (a = _args.begin (); a != _args.end (); ++a) - if (a->hasTag ("FILTER")) - if (std::find (options.begin (), options.end (), a->attribute ("raw")) != options.end ()) - if (! a->hasTag ("OP")) - { - a->tag ("OP"); - changes = true; - } - - if (changes && - context.config.getInteger ("debug.parser") >= 3) - context.debug (context.cli.dump ("CLI::analyze findOperators")); -} - -//////////////////////////////////////////////////////////////////////////////// -void CLI::findAttributes () -{ - // Find the category. - std::pair ::const_iterator, std::multimap ::const_iterator> c; - c = _entities.equal_range ("attribute"); - - // Extract a list of entities for category. - std::vector options; - std::multimap ::const_iterator e; - for (e = c.first; e != c.second; ++e) - options.push_back (e->second); - - // Walk the arguments and tag as OP. - bool changes = false; - std::vector ::iterator a; - for (a = _args.begin (); a != _args.end (); ++a) - if (a->hasTag ("FILTER")) - if (std::find (options.begin (), options.end (), a->attribute ("raw")) != options.end ()) - if (! a->hasTag ("ATTRIBUTE")) - { - a->tag ("ATTRIBUTE"); - changes = true; - } - - if (changes && - context.config.getInteger ("debug.parser") >= 3) - context.debug (context.cli.dump ("CLI::analyze findAttributes")); -} - -//////////////////////////////////////////////////////////////////////////////// -// Two consecutive FILTER, non-OP arguments that are not "(" or ")" need an -// "and" operator inserted between them. -// -// ) --> ) and -// ( --> ( -// ) ( --> ) and ( -// --> and -// -void CLI::insertJunctions () -{ - bool changes = false; - std::vector reconstructed; - std::vector ::iterator prev = _args.begin (); - std::vector ::iterator a; - for (a = _args.begin (); a != _args.end (); ++a) - { - if (a->hasTag ("FILTER")) - { - // The prev iterator should be the first FILTER arg. - if (prev == _args.begin ()) - prev = a; - - // Insert AND between terms. - else if (a != prev) - { - if ((! prev->hasTag ("OP") && a->attribute ("raw") == "(") || - (! prev->hasTag ("OP") && ! a->hasTag ("OP")) || - (prev->attribute ("raw") == ")" && ! a->hasTag ("OP")) || - (prev->attribute ("raw") == ")" && a->attribute ("raw") == "(")) - { - A opOr ("argOp", "and"); - opOr.tag ("FILTER"); - opOr.tag ("OP"); - reconstructed.push_back (opOr); - changes = true; - } - } - - // Previous FILTER arg. - prev = a; - } - - reconstructed.push_back (*a); - } - - if (changes) - { - _args = reconstructed; - - if (context.config.getInteger ("debug.parser") >= 3) - context.debug (context.cli.dump ("CLI::analyze insertJunctions")); - } -} - -//////////////////////////////////////////////////////////////////////////////// -void CLI::injectDefaults () -{ - // Scan the top-level branches for evidence of ID, UUID, overrides and other - // arguments. - bool changes = false; - bool found_command = false; - bool found_sequence = false; - bool found_terminator = false; - - std::vector ::iterator a; - for (a = _args.begin (); a != _args.end (); ++a) - { - std::string raw = a->attribute ("raw"); - if (isTerminator (raw)) - found_terminator = true; - - if (! found_terminator && isCommand (raw)) - found_command = true; - - else if (! found_terminator && - (isUUIDList (raw) || - isUUID (raw) || - isIDSequence (raw) || - isID (raw))) - found_sequence = true; - } - - // If no command was specified, then a command will be inserted. - if (! found_command) - { - // Default command. - if (! found_sequence) - { - // Apply overrides, if any. - std::string defaultCommand = context.config.get ("default.command"); - if (defaultCommand != "") - { - // Split the defaultCommand into separate args. - std::vector tokens = Lexer::split (defaultCommand); - - // Modify _args to be: [ ...] [...] - std::vector reconstructed; - for (a = _args.begin (); a != _args.end (); ++a) - { - reconstructed.push_back (*a); - - if (a == _args.begin ()) - { - std::vector ::iterator t; - for (t = tokens.begin (); t != tokens.end (); ++t) - { - A arg ("argDefault", *t); - arg.tag ("DEFAULT"); - reconstructed.push_back (arg); - } - } - } - - _args = reconstructed; - } - - // Only an error in strict mode. - else if (_strict) - { - throw std::string (STRING_TRIVIAL_INPUT); - } - } - else - { - A info ("argDefault", "information"); - info.tag ("ASSUMED"); - _args.push_back (info); - } - } - - if (changes && - context.config.getInteger ("debug.parser") >= 3) - context.debug (context.cli.dump ("CLI::analyze injectDefaults")); -} - -//////////////////////////////////////////////////////////////////////////////// -void CLI::decomposeModAttributes () -{ - bool changes = false; - std::vector ::iterator a; - for (a = _args.begin (); a != _args.end (); ++a) - { - if (a->hasTag ("TERMINATOR")) - break; - - if (a->hasTag ("MODIFICATION")) - { - // Look for a valid attribute name. - Nibbler n (a->attribute ("raw")); - std::string name; - if (n.getName (name) && - name.length ()) - { - if (n.skip (':')) - { - std::string value; - if (n.getQuoted ('"', value) || - n.getQuoted ('\'', value) || - n.getUntilEOS (value) || - n.depleted ()) - { - if (value == "") - value = "''"; - - std::string canonical; - if (canonicalize (canonical, "uda", name)) - { - a->attribute ("name", canonical); - a->attribute ("value", value); - a->tag ("UDA"); - a->tag ("MODIFIABLE"); - changes = true; - } - - else if (canonicalize (canonical, "attribute", name)) - { - a->attribute ("name", canonical); - a->attribute ("value", value); - a->tag ("ATTRIBUTE"); - - std::map ::const_iterator col; - col = context.columns.find (canonical); - if (col != context.columns.end () && - col->second->modifiable ()) - { - a->tag ("MODIFIABLE"); - } - - changes = true; - } - } - } - } - } - } - - if (changes && - context.config.getInteger ("debug.parser") >= 3) - context.debug (context.cli.dump ("CLI::analyze decomposeModAttributes")); -} - -//////////////////////////////////////////////////////////////////////////////// -void CLI::decomposeModAttributeModifiers () -{ - bool changes = false; - std::vector ::iterator a; - for (a = _args.begin (); a != _args.end (); ++a) - { - if (a->hasTag ("TERMINATOR")) - break; - - if (a->hasTag ("MODIFICATION")) - { - // Look for a valid attribute name. - Nibbler n (a->attribute ("raw")); - std::string name; - if (n.getUntil (".", name) && - name.length ()) - { - std::string canonical; - if (canonicalize (canonical, "attribute", name) || - canonicalize (canonical, "uda", name)) - { - if (n.skip ('.')) - { - std::string sense = "+"; - if (n.skip ('~')) - sense = "-"; - - std::string modifier; - n.getUntilOneOf (":=", modifier); - - if (n.skip (':') || - n.skip ('=')) - { - std::string value; - if (n.getQuoted ('"', value) || - n.getQuoted ('\'', value) || - n.getUntilEOS (value) || - n.depleted ()) - { - if (value == "") - value = "''"; - - std::string canonical; - if (canonicalize (canonical, "uda", name)) - { - a->attribute ("name", canonical); - a->attribute ("modifier", modifier); - a->attribute ("sense", sense); - a->attribute ("value", value); - a->tag ("UDA"); - a->tag ("MODIFIABLE"); - changes = true; - } - - else if (canonicalize (canonical, "attribute", name)) - { - a->attribute ("name", canonical); - a->attribute ("modifier", modifier); - a->attribute ("sense", sense); - a->attribute ("value", value); - a->tag ("ATTMOD"); - - std::map ::const_iterator col; - col = context.columns.find (canonical); - if (col != context.columns.end () && - col->second->modifiable ()) - { - a->tag ("MODIFIABLE"); - } - - changes = true; - } - } - } - } - } - } - } - } - - if (changes && - context.config.getInteger ("debug.parser") >= 3) - context.debug (context.cli.dump ("CLI::analyze decomposeModAttributeModifiers")); -} - -//////////////////////////////////////////////////////////////////////////////// -void CLI::decomposeModTags () -{ - bool changes = false; - std::vector ::iterator a; - for (a = _args.begin (); a != _args.end (); ++a) - { - if (a->hasTag ("TERMINATOR")) - break; - - if (a->hasTag ("MODIFICATION")) - { - Nibbler n (a->attribute ("raw")); - std::string tag; - std::string sign; - - if (n.getN (1, sign) && - (sign == "+" || sign == "-") && - n.getUntilEOS (tag) && - tag.find (' ') == std::string::npos) - { - a->attribute ("name", tag); - a->attribute ("sign", sign); - a->tag ("TAG"); - changes = true; - } - } - } - - if (changes && - context.config.getInteger ("debug.parser") >= 3) - context.debug (context.cli.dump ("CLI::analyze decomposeModTags")); -} - -//////////////////////////////////////////////////////////////////////////////// -void CLI::decomposeModSubstitutions () -{ - bool changes = false; - std::vector ::iterator a; - for (a = _args.begin (); a != _args.end (); ++a) - { - if (a->hasTag ("TERMINATOR")) - break; - - if (a->hasTag ("MODIFICATION")) - { - std::string raw = a->attribute ("raw"); - Nibbler n (raw); - std::string from; - std::string to; - bool global = false; - if (n.getQuoted ('/', from) && - n.backN () && - n.getQuoted ('/', to)) - { - if (n.skip ('g')) - global = true; - - if (n.depleted () && - ! Directory (raw).exists ()) - { - a->tag ("SUBSTITUTION"); - a->attribute ("from", from); - a->attribute ("to", to); - a->attribute ("global", global ? 1 : 0); - changes = true; - } - } - } - } - - if (changes && - context.config.getInteger ("debug.parser") >= 3) - context.debug (context.cli.dump ("CLI::analyze decomposeModSubstitutions")); -} - -//////////////////////////////////////////////////////////////////////////////// -bool CLI::isTerminator (const std::string& raw) const -{ - return (raw == "--"); -} - -//////////////////////////////////////////////////////////////////////////////// -bool CLI::isRCOverride (const std::string& raw) const -{ - if (raw.length () > 3 && raw.substr (0, 3) == "rc:") - return true; - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool CLI::isConfigOverride (const std::string& raw) const -{ - if (raw.length () > 3 && raw.substr (0, 3) == "rc.") - return true; - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool CLI::isCommand (const std::string& raw) const -{ - std::string canonical; - return canonicalize (canonical, "cmd", raw); -} - -//////////////////////////////////////////////////////////////////////////////// -// Valid tag -// - Length > 1 -// - Starts with +/- -// - The rest matches ::isName -bool CLI::isTag (const std::string& raw) const -{ - if (raw.size () >= 2 && - (raw[0] == '+' || raw[0] == '-') && - isName (raw.substr (1)) && - raw.find (' ') == std::string::npos) - return true; - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool CLI::isUUIDList (const std::string& raw) const -{ - // UUIDs have a limited character set. - if (raw.find_first_not_of ("0123456789abcdefABCDEF-,") == std::string::npos) - { - Nibbler n (raw); - std::string token; - if (n.getUUID (token) || - n.getPartialUUID (token)) - { - while (n.skip (',')) - if (! n.getUUID (token) && - ! n.getPartialUUID (token)) - return false; - - if (n.depleted ()) - return true; - } - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool CLI::isUUID (const std::string& raw) const -{ - // UUIDs have a limited character set. - if (raw.find_first_not_of ("0123456789abcdefABCDEF-") == std::string::npos) - { - Nibbler n (raw); - std::string token; - if (n.getUUID (token) || n.getPartialUUID (token)) - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool CLI::isIDSequence (const std::string& raw) const -{ - if (raw.find_first_not_of ("0123456789,-") == std::string::npos) - { - // Split the ID list into elements. - std::vector elements; - split (elements, raw, ','); - - std::vector ::iterator e; - for (e = elements.begin (); e != elements.end (); ++e) - { - // Split the ID range into min/max. - std::vector terms; - split (terms, *e, '-'); - - if (terms.size () == 1 && - ! isID (terms[0])) - return false; - - else if (terms.size () == 2 && - (! isID (terms[0]) || - ! isID (terms[1]))) - return false; - - else if (terms.size () > 2) - return false; - } - - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool CLI::isID (const std::string& raw) const -{ - return Lexer::isAllDigits (raw); -} - -//////////////////////////////////////////////////////////////////////////////// -bool CLI::isPattern (const std::string& raw) const -{ - if (raw.length () > 2 && - raw[0] == '/' && - raw[raw.length () - 1] == '/') - return true; - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// The non-g case is caught by ::isPattern, but not categorized, so it doesn't -// matter. -bool CLI::isSubstitution (const std::string& raw) const -{ - if (raw.length () > 3 && // /x// = length 4 - raw[0] == '/' && - raw[raw.length () - 2] == '/' && - raw[raw.length () - 1] == 'g') - return true; - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// Covers attribute and attribute modifiers. -// .[~][:=]... -bool CLI::isAttribute (const std::string& raw) const -{ - std::string::size_type colon = raw.find (":"); - std::string::size_type equal = raw.find ("="); - - std::string attr = ""; - if (colon != std::string::npos) - attr = raw.substr (0, colon); - else if (equal != std::string::npos) - attr = raw.substr (0, equal); - else - return false; - - // No spaces in name. - if (! isName (attr)) - return false; - - std::string::size_type dot = attr.find ("."); - std::string mod = ""; - if (dot != std::string::npos) - { - mod = attr.substr (dot + 1); - attr = attr.substr (0, dot); - - if (mod[0] == '~') - mod = mod.substr (1); - - if (! canonicalize (mod, "modifier", mod)) - return false; - } - -/* - TODO Entities are not loaded yet. Hmm. - - if (! canonicalize (attr, "attribute", attr)) - return false; -*/ - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -bool CLI::isOperator (const std::string& raw) const -{ - // Find the category. - std::pair ::const_iterator, std::multimap ::const_iterator> c; - c = _entities.equal_range ("operator"); - - // Walk the list of entities for category. - std::vector options; - std::multimap ::const_iterator e; - for (e = c.first; e != c.second; ++e) - if (raw == e->second) - return true; - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool CLI::isName (const std::string& raw) const -{ - if (raw != "") - { - for (unsigned int i = 0; i < raw.length (); ++i) - { - if (i == 0 && ! Lexer::isIdentifierStart (raw[i])) - return false; - else if (! Lexer::isIdentifierNext (raw[i])) - return false; - } - - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool CLI::disqualifyInsufficientTerms ( - const std::vector >& lexemes) const -{ - return lexemes.size () < 3 ? true : false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool CLI::disqualifyNoOps ( - const std::vector >& lexemes) const -{ - bool foundOP = false; - std::vector >::const_iterator l; - for (l = lexemes.begin (); l != lexemes.end (); ++l) - if (l->second == Lexer::Type::op) - foundOP = true; - - return ! foundOP; -} - -//////////////////////////////////////////////////////////////////////////////// -bool CLI::disqualifyOnlyParenOps ( - const std::vector >& lexemes) const -{ - int opCount = 0; - int opSugarCount = 0; - int opParenCount = 0; - - std::vector >::const_iterator l; - for (l = lexemes.begin (); l != lexemes.end (); ++l) - { - if (l->second == Lexer::Type::op) - { - ++opCount; - - if (l->first == "(" || - l->first == ")") - ++opParenCount; - } - - else if (isTag (l->first) || - isUUIDList (l->first) || - isUUID (l->first) || - isIDSequence (l->first) || - isID (l->first) || - isPattern (l->first) || - isAttribute (l->first)) - ++opSugarCount; - } - - return opCount == opParenCount && ! opSugarCount; -} - -//////////////////////////////////////////////////////////////////////////////// -// Disqualify terms when there are are binary operators at either end, as long -// as there are no operators in between, which includes syntactic sugar that -// hides operators. -bool CLI::disqualifyFirstLastBinary ( - const std::vector >& lexemes) const -{ - bool firstBinary = false; - bool lastBinary = false; - - std::string dummy; - if (canonicalize (dummy, "binary_operator", lexemes[0].first)) - firstBinary = true; - - if (lexemes.size () > 1 && - canonicalize (dummy, "binary_operator", lexemes[lexemes.size () - 1].first)) - lastBinary = true; - - return firstBinary || lastBinary; -} - -//////////////////////////////////////////////////////////////////////////////// -// Disqualify terms when there operators hidden by syntactic sugar. -bool CLI::disqualifySugarFree ( - const std::vector >& lexemes) const -{ - bool sugared = true; - for (unsigned int i = 1; i < lexemes.size () - 1; ++i) - if (isTag (lexemes[i].first) || - isUUIDList (lexemes[i].first) || - isUUID (lexemes[i].first) || - isIDSequence (lexemes[i].first) || - isID (lexemes[i].first) || - isPattern (lexemes[i].first) || - isAttribute (lexemes[i].first)) - sugared = true; - - return ! sugared; -} - -//////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/CLI.h task-2.5.0+dfsg/src/CLI.h --- task-2.4.4+dfsg/src/CLI.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/CLI.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,150 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// 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 -// -//////////////////////////////////////////////////////////////////////////////// -#ifndef INCLUDED_CLI -#define INCLUDED_CLI - -#include -#include -#include -#include -#include -#include - -// Represents a single argument. -class A -{ -public: - A (); - A (const std::string&, const std::string&); - A (const std::string&, const int); - A (const std::string&, const double); - ~A (); - A (const A&); - A& operator= (const A&); - bool hasTag (const std::string&) const; - void tag (const std::string&); - void unTag (const std::string&); - void unTagAll (); - void attribute (const std::string&, const std::string&); - void attribute (const std::string&, const int); - void attribute (const std::string&, const double); - const std::string attribute (const std::string&) const; - void removeAttribute (const std::string&); - const std::string dump () const; - -public: - std::string _name; - std::vector _tags; - std::map _attributes; -}; - -// Represents the command line. -class CLI -{ -public: - static int minimumMatchLength; - static void getOverride (int, const char**, std::string&, File&); - static void getDataLocation (int, const char**, Path&); - static void applyOverrides (int, const char**); - -public: - CLI (); - ~CLI (); - void alias (const std::string&, const std::string&); - 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 (bool applyContext = true); - const std::vector getWords (); - bool canonicalize (std::string&, const std::string&, const std::string&) const; - std::string getBinary () const; - std::string getCommand () const; - std::string getLimit () const; - const std::string dump (const std::string& title = "CLI Parser") const; - -private: - void addArg (const std::string&, Lexer::Type type = Lexer::Type::word); - void aliasExpansion (); - void findOverrides (); - void categorize (); - bool exactMatch (const std::string&, const std::string&) const; - void desugarFilterTags (); - void findStrayModifications (); - void desugarFilterAttributes (); - void desugarFilterAttributeModifiers (); - void desugarFilterPatterns (); - void findIDs (); - void findUUIDs (); - void insertIDExpr (); - void desugarFilterPlainArgs (); - void findOperators (); - void findAttributes (); - void insertJunctions (); - void injectDefaults (); - void decomposeModAttributes (); - void decomposeModAttributeModifiers (); - void decomposeModTags (); - void decomposeModSubstitutions (); - - bool isTerminator (const std::string&) const; - bool isRCOverride (const std::string&) const; - bool isConfigOverride (const std::string&) const; - bool isCommand (const std::string&) const; - bool isTag (const std::string&) const; - bool isUUIDList (const std::string&) const; - bool isUUID (const std::string&) const; - bool isIDSequence (const std::string&) const; - bool isID (const std::string&) const; - bool isPattern (const std::string&) const; - bool isSubstitution (const std::string&) const; - bool isAttribute (const std::string&) const; - bool isOperator (const std::string&) const; - bool isName (const std::string&) const; - - bool disqualifyInsufficientTerms (const std::vector >&) const; - bool disqualifyNoOps (const std::vector >&) const; - bool disqualifyOnlyParenOps (const std::vector >&) const; - bool disqualifyFirstLastBinary (const std::vector >&) const; - bool disqualifySugarFree (const std::vector >&) const; - -public: - std::multimap _entities; - std::map _aliases; - std::vector _original_args; - std::vector _args; - - std::vector > _id_ranges; - std::vector _uuid_list; - bool _strict; - bool _terminated; -}; - -#endif - diff -Nru task-2.4.4+dfsg/src/CMakeLists.txt task-2.5.0+dfsg/src/CMakeLists.txt --- task-2.4.4+dfsg/src/CMakeLists.txt 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/CMakeLists.txt 2015-10-21 21:18:14.000000000 +0000 @@ -5,25 +5,21 @@ ${CMAKE_SOURCE_DIR}/src/columns ${TASK_INCLUDE_DIRS}) -set (task_SRCS CLI.cpp CLI.h +set (task_SRCS CLI2.cpp CLI2.h Color.cpp Color.h Config.cpp Config.h Context.cpp Context.h DOM.cpp DOM.h - Date.cpp Date.h Dates.cpp Dates.h - Directory.cpp Directory.h - Duration.cpp Duration.h Eval.cpp Eval.h - File.cpp File.h Filter.cpp Filter.h + FS.cpp FS.h Hooks.cpp Hooks.h ISO8601.cpp ISO8601.h JSON.cpp JSON.h Lexer.cpp Lexer.h Msg.cpp Msg.h Nibbler.cpp Nibbler.h - Path.cpp Path.h RX.cpp RX.h TDB2.cpp TDB2.h Task.cpp Task.h diff -Nru task-2.4.4+dfsg/src/Color.cpp task-2.5.0+dfsg/src/Color.cpp --- task-2.4.4+dfsg/src/Color.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/Color.cpp 2015-10-21 21:18:14.000000000 +0000 @@ -74,14 +74,12 @@ Color::Color (unsigned int c) : _value (0) { -#ifdef FEATURE_COLOR if (!(c & _COLOR_HASFG)) _value &= ~_COLOR_FG; if (!(c & _COLOR_HASBG)) _value &= ~_COLOR_BG; _value = c & (_COLOR_256 | _COLOR_HASBG | _COLOR_HASFG |_COLOR_UNDERLINE | _COLOR_INVERSE | _COLOR_BOLD | _COLOR_BRIGHT | _COLOR_BG | _COLOR_FG); -#endif } //////////////////////////////////////////////////////////////////////////////// @@ -99,16 +97,9 @@ Color::Color (const std::string& spec) : _value (0) { -#ifdef FEATURE_COLOR - // By converting underscores to spaces, we inherently support the old "on_red" - // style of specifying background colors. We consider underscores to be - // deprecated. - std::string modifiable_spec = spec; - std::replace (modifiable_spec.begin (), modifiable_spec.end (), '_', ' '); - // Split spec into words. std::vector words; - split (words, modifiable_spec, ' '); + split (words, spec, ' '); // Construct the color as two separate colors, then blend them later. This // make it possible to declare a color such as "color1 on black", and have @@ -119,10 +110,9 @@ bool bg = false; int index; std::string word; - std::vector ::iterator it; - for (it = words.begin (); it != words.end (); ++it) + for (auto& it : words) { - word = lowerCase (trim (*it)); + word = lowerCase (trim (it)); if (word == "bold") fg_value |= _COLOR_BOLD; else if (word == "bright") bg_value |= _COLOR_BRIGHT; @@ -154,7 +144,7 @@ { index = atoi (word.substr (4).c_str ()); if (index < 0 || index > 23) - throw format (STRING_COLOR_UNRECOGNIZED, *it); + throw format (STRING_COLOR_UNRECOGNIZED, it); if (bg) { @@ -176,7 +166,7 @@ index = atoi (word.substr (3).c_str ()); if (word.length () != 6 || index < 0 || index > 555) - throw format (STRING_COLOR_UNRECOGNIZED, *it); + throw format (STRING_COLOR_UNRECOGNIZED, it); int r = atoi (word.substr (3, 1).c_str ()); int g = atoi (word.substr (4, 1).c_str ()); @@ -184,7 +174,7 @@ if (r < 0 || r > 5 || g < 0 || g > 5 || b < 0 || b > 5) - throw format (STRING_COLOR_UNRECOGNIZED, *it); + throw format (STRING_COLOR_UNRECOGNIZED, it); index = 16 + r*36 + g*6 + b; @@ -207,7 +197,7 @@ { index = atoi (word.substr (5).c_str ()); if (index < 0 || index > 255) - throw format (STRING_COLOR_UNRECOGNIZED, *it); + throw format (STRING_COLOR_UNRECOGNIZED, it); upgrade (); @@ -225,33 +215,29 @@ } } else if (word != "") - throw format (STRING_COLOR_UNRECOGNIZED, *it); + throw format (STRING_COLOR_UNRECOGNIZED, it); } // Now combine the fg and bg into a single color. _value = fg_value; blend (Color (bg_value)); -#endif } //////////////////////////////////////////////////////////////////////////////// Color::Color (color_id fg) : _value (0) { -#ifdef FEATURE_COLOR if (fg != Color::nocolor) { _value |= _COLOR_HASFG; _value |= fg; } -#endif } //////////////////////////////////////////////////////////////////////////////// Color::Color (color_id fg, color_id bg) : _value (0) { -#ifdef FEATURE_COLOR if (bg != Color::nocolor) { _value |= _COLOR_HASBG; @@ -263,14 +249,12 @@ _value |= _COLOR_HASFG; _value |= fg; } -#endif } //////////////////////////////////////////////////////////////////////////////// Color::Color (color_id fg, color_id bg, bool underline, bool bold, bool bright) : _value (0) { -#ifdef FEATURE_COLOR _value |= ((underline ? 1 : 0) << 18) | ((bold ? 1 : 0) << 17) | ((bright ? 1 : 0) << 16); @@ -286,7 +270,6 @@ _value |= _COLOR_HASFG; _value |= fg; } -#endif } //////////////////////////////////////////////////////////////////////////////// @@ -307,7 +290,6 @@ Color::operator std::string () const { std::string description; -#ifdef FEATURE_COLOR if (_value & _COLOR_BOLD) description += "bold"; if (_value & _COLOR_UNDERLINE) @@ -328,7 +310,6 @@ description += " " + bg (); } -#endif return description; } @@ -344,7 +325,6 @@ // other take precedence. void Color::blend (const Color& other) { -#ifdef FEATURE_COLOR if (!other.nontrivial ()) return; @@ -396,13 +376,11 @@ _value |= (c._value & _COLOR_BG); // Apply other color. } } -#endif } //////////////////////////////////////////////////////////////////////////////// void Color::upgrade () { -#ifdef FEATURE_COLOR if (!(_value & _COLOR_256)) { if (_value & _COLOR_HASFG) @@ -425,7 +403,6 @@ _value |= _COLOR_256; } -#endif } //////////////////////////////////////////////////////////////////////////////// @@ -442,7 +419,6 @@ // 256 bg \033[48;5;Nm std::string Color::colorize (const std::string& input) { -#ifdef FEATURE_COLOR if (!nontrivial ()) return input; @@ -452,35 +428,19 @@ // 256 color if (_value & _COLOR_256) { - bool needTerminator = false; - if (_value & _COLOR_UNDERLINE) - { result << "\033[4m"; - needTerminator = true; - } if (_value & _COLOR_INVERSE) - { result << "\033[7m"; - needTerminator = true; - } if (_value & _COLOR_HASFG) - { result << "\033[38;5;" << (_value & _COLOR_FG) << "m"; - needTerminator = true; - } if (_value & _COLOR_HASBG) - { result << "\033[48;5;" << ((_value & _COLOR_BG) >> 8) << "m"; - needTerminator = true; - } - result << input; - if (needTerminator) - result << "\033[0m"; + result << input << "\033[0m"; return result.str (); } @@ -523,7 +483,6 @@ result << "m" << input << "\033[0m"; return result.str (); } -#endif return input; } @@ -532,7 +491,6 @@ // Remove color codes from a string. std::string Color::strip (const std::string& input) { -#ifdef FEATURE_COLOR int length = input.length (); bool inside = false; std::string output; @@ -553,20 +511,13 @@ } return output; -#else - return input; -#endif } //////////////////////////////////////////////////////////////////////////////// std::string Color::colorize (const std::string& input, const std::string& spec) { -#ifdef FEATURE_COLOR Color c (spec); return c.colorize (input); -#else - return input; -#endif } //////////////////////////////////////////////////////////////////////////////// @@ -588,7 +539,6 @@ //////////////////////////////////////////////////////////////////////////////// std::string Color::fg () const { -#ifdef FEATURE_COLOR int index = _value & _COLOR_FG; if (_value & _COLOR_256) @@ -606,7 +556,6 @@ if (allColors[i].index == index) return allColors[i].english_name; } -#endif return ""; } @@ -614,7 +563,6 @@ //////////////////////////////////////////////////////////////////////////////// std::string Color::bg () const { -#ifdef FEATURE_COLOR int index = (_value & _COLOR_BG) >> 8; if (_value & _COLOR_256) @@ -632,7 +580,6 @@ if (allColors[i].index == index) return allColors[i].english_name; } -#endif return ""; } diff -Nru task-2.4.4+dfsg/src/Color.h task-2.5.0+dfsg/src/Color.h --- task-2.4.4+dfsg/src/Color.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/Color.h 2015-10-21 21:18:14.000000000 +0000 @@ -29,8 +29,6 @@ #include -#define FEATURE_COLOR 1 - //////////////////////////////////////////////////////////////////////////////// #define _COLOR_INVERSE 0x00400000 // Inverse attribute. #define _COLOR_256 0x00200000 // 256-color mode. diff -Nru task-2.4.4+dfsg/src/columns/ColDate.cpp task-2.5.0+dfsg/src/columns/ColDate.cpp --- task-2.4.4+dfsg/src/columns/ColDate.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColDate.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -28,8 +28,7 @@ #include #include #include -#include -#include +#include #include #include @@ -42,24 +41,23 @@ _type = "date"; _style = "formatted"; _label = ""; + _styles = {"formatted", + "julian", + "epoch", + "iso", + "age", + "remaining", + "countdown"}; - _styles.push_back ("formatted"); - _styles.push_back ("julian"); - _styles.push_back ("epoch"); - _styles.push_back ("iso"); - _styles.push_back ("age"); - _styles.push_back ("remaining"); - _styles.push_back ("countdown"); - - Date now; + ISO8601d now; now -= 125; // So that "age" is non-zero. - _examples.push_back (now.toString (context.config.get ("dateformat"))); - _examples.push_back (format (now.toJulian (), 13, 12)); - _examples.push_back (now.toEpochString ()); - _examples.push_back (now.toISO ()); - _examples.push_back (Duration (Date () - now).formatCompact ()); - _examples.push_back (""); - _examples.push_back (Duration (Date () - now).format ()); + _examples = {now.toString (context.config.get ("dateformat")), + format (now.toJulian (), 13, 12), + now.toEpochString (), + now.toISO (), + ISO8601p (ISO8601d () - now).formatVague (), + "", + ISO8601p (ISO8601d () - now).format ()}; } //////////////////////////////////////////////////////////////////////////////// @@ -68,12 +66,6 @@ } //////////////////////////////////////////////////////////////////////////////// -bool ColumnDate::validate (std::string& value) -{ - return true; -} - -//////////////////////////////////////////////////////////////////////////////// // Set the minimum and maximum widths for the value. void ColumnDate::measure (Task& task, unsigned int& minimum, unsigned int& maximum) { @@ -81,7 +73,7 @@ if (task.has (_name)) { - Date date (task.get_date (_name)); + ISO8601d date (task.get_date (_name)); if (_style == "default" || _style == "formatted") @@ -96,12 +88,12 @@ if (format == "") format = context.config.get ("dateformat"); - minimum = maximum = Date::length (format); + minimum = maximum = ISO8601d::length (format); } else if (_style == "countdown") { - Date now; - minimum = maximum = Duration (now - date).format ().length (); + ISO8601d now; + minimum = maximum = ISO8601p (now - date).formatVague ().length (); } else if (_style == "julian") { @@ -117,14 +109,14 @@ } else if (_style == "age") { - Date now; - minimum = maximum = Duration (now - date).formatCompact ().length (); + ISO8601d now; + minimum = maximum = ISO8601p (now - date).formatVague ().length (); } else if (_style == "remaining") { - Date now; + ISO8601d now; if (date > now) - minimum = maximum = Duration (date - now).format ().length (); + minimum = maximum = ISO8601p (date - now).formatVague ().length (); } else throw format (STRING_COLUMN_BAD_FORMAT, _name, _style); @@ -140,7 +132,7 @@ { if (task.has (_name)) { - Date date (task.get_date (_name)); + ISO8601d date (task.get_date (_name)); if (_style == "default" || _style == "formatted") @@ -162,12 +154,12 @@ } else if (_style == "countdown") { - Date now; + ISO8601d now; lines.push_back ( color.colorize ( rightJustify ( - Duration (now - date).format (), width))); + ISO8601p (now - date).formatVague (), width))); } else if (_style == "julian") { @@ -192,21 +184,21 @@ } else if (_style == "age") { - Date now; + ISO8601d now; lines.push_back ( color.colorize ( leftJustify ( - Duration (now - date).formatCompact (), width))); + ISO8601p (now - date).formatVague (), width))); } else if (_style == "remaining") { - Date now; + ISO8601d now; if (date > now) lines.push_back ( color.colorize ( rightJustify ( - Duration (date - now).format (), width))); + ISO8601p (date - now).formatVague (), width))); } } } diff -Nru task-2.4.4+dfsg/src/columns/ColDate.h task-2.5.0+dfsg/src/columns/ColDate.h --- task-2.4.4+dfsg/src/columns/ColDate.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColDate.h 2015-10-21 21:18:15.000000000 +0000 @@ -39,7 +39,6 @@ ColumnDate (); virtual ~ColumnDate (); - virtual bool validate (std::string&); virtual void measure (Task&, unsigned int&, unsigned int&); virtual void render (std::vector &, Task&, int, Color&); }; diff -Nru task-2.4.4+dfsg/src/columns/ColDepends.cpp task-2.5.0+dfsg/src/columns/ColDepends.cpp --- task-2.4.4+dfsg/src/columns/ColDepends.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColDepends.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -38,18 +38,16 @@ //////////////////////////////////////////////////////////////////////////////// ColumnDepends::ColumnDepends () { - _name = "depends"; - _type = "string"; - _style = "list"; - _label = STRING_COLUMN_LABEL_DEP; - - _styles.push_back ("list"); - _styles.push_back ("count"); - _styles.push_back ("indicator"); - - _examples.push_back ("1 2 10"); - _examples.push_back ("[3]"); - _examples.push_back (context.config.get ("dependency.indicator")); + _name = "depends"; + _type = "string"; + _style = "list"; + _label = STRING_COLUMN_LABEL_DEP; + _styles = {"list", + "count", + "indicator"}; + _examples = {"1 2 10", + "[3]", + context.config.get ("dependency.indicator")}; _hyphenate = context.config.getBoolean ("hyphenate"); } @@ -60,12 +58,6 @@ } //////////////////////////////////////////////////////////////////////////////// -bool ColumnDepends::validate (std::string& value) -{ - return true; -} - -//////////////////////////////////////////////////////////////////////////////// // Overriden so that style <----> label are linked. // Note that you can not determine which gets called first. void ColumnDepends::setStyle (const std::string& value) @@ -85,8 +77,10 @@ if (_style == "indicator") { - minimum = maximum = utf8_width (context.config.get ("dependency.indicator")); - _fixed_width = true; + if (task.has ("depends")) + minimum = maximum = utf8_width (context.config.get ("dependency.indicator")); + else + minimum = maximum = 0; } else if (_style == "count") { @@ -99,18 +93,17 @@ if (task.has ("depends")) { std::vector blocking_ids; - std::vector ::iterator i; - for (i = blocking.begin (); i != blocking.end (); ++i) - blocking_ids.push_back (i->id); + for (auto& i : blocking) + blocking_ids.push_back (i.id); std::string all; join (all, " ", blocking_ids); maximum = all.length (); unsigned int length; - for (i = blocking.begin (); i != blocking.end (); ++i) + for (auto& i : blocking) { - length = format (i->id).length (); + length = format (i.id).length (); if (length > minimum) minimum = length; } @@ -150,9 +143,8 @@ _style == "list") { std::vector blocking_ids; - std::vector ::iterator t; - for (t = blocking.begin (); t != blocking.end (); ++t) - blocking_ids.push_back (t->id); + for (auto& t : blocking) + blocking_ids.push_back (t.id); std::string combined; join (combined, " ", blocking_ids); @@ -160,9 +152,8 @@ std::vector all; wrapText (all, combined, width, _hyphenate); - std::vector ::iterator i; - for (i = all.begin (); i != all.end (); ++i) - lines.push_back (color.colorize (leftJustify (*i, width))); + for (auto& i : all) + lines.push_back (color.colorize (leftJustify (i, width))); } } } diff -Nru task-2.4.4+dfsg/src/columns/ColDepends.h task-2.5.0+dfsg/src/columns/ColDepends.h --- task-2.4.4+dfsg/src/columns/ColDepends.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColDepends.h 2015-10-21 21:18:15.000000000 +0000 @@ -39,7 +39,6 @@ ColumnDepends (); ~ColumnDepends (); - bool validate (std::string&); void setStyle (const std::string&); void measure (Task&, unsigned int&, unsigned int&); void render (std::vector &, Task&, int, Color&); diff -Nru task-2.4.4+dfsg/src/columns/ColDescription.cpp task-2.5.0+dfsg/src/columns/ColDescription.cpp --- task-2.4.4+dfsg/src/columns/ColDescription.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColDescription.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -44,38 +44,36 @@ _style = "combined"; _label = STRING_COLUMN_LABEL_DESC; - _styles.push_back ("combined"); - _styles.push_back ("desc"); - _styles.push_back ("oneline"); - _styles.push_back ("truncated"); - _styles.push_back ("count"); - _styles.push_back ("truncated_count"); + _styles = {"combined", + "desc", + "oneline", + "truncated", + "count", + "truncated_count"}; _dateformat = context.config.get ("dateformat.annotation"); if (_dateformat == "") _dateformat = context.config.get ("dateformat"); - std::string t = Date ().toString (_dateformat); + std::string t = ISO8601d ().toString (_dateformat); std::string d = STRING_COLUMN_EXAMPLES_DESC; std::string a1 = STRING_COLUMN_EXAMPLES_ANNO1; std::string a2 = STRING_COLUMN_EXAMPLES_ANNO2; std::string a3 = STRING_COLUMN_EXAMPLES_ANNO3; std::string a4 = STRING_COLUMN_EXAMPLES_ANNO4; - _examples.push_back (d - + "\n " + t + " " + a1 - + "\n " + t + " " + a2 - + "\n " + t + " " + a3 - + "\n " + t + " " + a4); - _examples.push_back (d); - _examples.push_back (d - + " " + t + " " + a1 - + " " + t + " " + a2 - + " " + t + " " + a3 - + " " + t + " " + a4); - _examples.push_back (d.substr (0, 20) + "..."); - _examples.push_back (d + " [4]"); - _examples.push_back (d.substr (0, 20) + "... [4]"); + _examples = {d + "\n " + t + " " + a1 + + "\n " + t + " " + a2 + + "\n " + t + " " + a3 + + "\n " + t + " " + a4, + d, + d + " " + t + " " + a1 + + " " + t + " " + a2 + + " " + t + " " + a3 + + " " + t + " " + a4, + d.substr (0, 20) + "...", + d + " [4]", + d.substr (0, 20) + "... [4]"}; _hyphenate = context.config.getBoolean ("hyphenate"); @@ -88,12 +86,6 @@ } //////////////////////////////////////////////////////////////////////////////// -bool ColumnDescription::validate (std::string& value) -{ - return true; -} - -//////////////////////////////////////////////////////////////////////////////// // Set the minimum and maximum widths for the value. void ColumnDescription::measure (Task& task, unsigned int& minimum, unsigned int& maximum) { @@ -110,16 +102,15 @@ if (task.annotation_count) { - unsigned int min_anno = _indent + Date::length (_dateformat); + unsigned int min_anno = _indent + ISO8601d::length (_dateformat); if (min_anno > minimum) minimum = min_anno; std::map annos; task.getAnnotations (annos); - std::map ::iterator i; - for (i = annos.begin (); i != annos.end (); i++) + for (auto& i : annos) { - unsigned int len = min_anno + 1 + utf8_width (i->second); + unsigned int len = min_anno + 1 + utf8_width (i.second); if (len > maximum) maximum = len; } @@ -141,12 +132,11 @@ if (task.annotation_count) { - unsigned int min_anno = Date::length (_dateformat); + auto min_anno = ISO8601d::length (_dateformat); std::map annos; task.getAnnotations (annos); - std::map ::iterator i; - for (i = annos.begin (); i != annos.end (); i++) - maximum += min_anno + 1 + utf8_width (i->second); + for (auto& i : annos) + maximum += min_anno + 1 + utf8_width (i.second); } } @@ -195,20 +185,18 @@ task.getAnnotations (annos); if (annos.size ()) { - std::map ::iterator i; - for (i = annos.begin (); i != annos.end (); i++) + for (auto& i : annos) { - Date dt (strtol (i->first.substr (11).c_str (), NULL, 10)); - description += "\n" + std::string (_indent, ' ') + dt.toString (_dateformat) + " " + i->second; + ISO8601d dt (strtol (i.first.substr (11).c_str (), NULL, 10)); + description += "\n" + std::string (_indent, ' ') + dt.toString (_dateformat) + " " + i.second; } } std::vector raw; wrapText (raw, description, width, _hyphenate); - std::vector ::iterator i; - for (i = raw.begin (); i != raw.end (); ++i) - lines.push_back (color.colorize (leftJustify (*i, width))); + for (auto& i : raw) + lines.push_back (color.colorize (leftJustify (i, width))); } // This is a description @@ -217,9 +205,8 @@ std::vector raw; wrapText (raw, description, width, _hyphenate); - std::vector ::iterator i; - for (i = raw.begin (); i != raw.end (); ++i) - lines.push_back (color.colorize (leftJustify (*i, width))); + for (auto& i : raw) + lines.push_back (color.colorize (leftJustify (i, width))); } // This is a description ... @@ -229,20 +216,18 @@ task.getAnnotations (annos); if (annos.size ()) { - std::map ::iterator i; - for (i = annos.begin (); i != annos.end (); i++) + for (auto& i : annos) { - Date dt (atoi (i->first.substr (11).c_str ())); - description += " " + dt.toString (_dateformat) + " " + i->second; + ISO8601d dt (strtol (i.first.substr (11).c_str (), NULL, 10)); + description += " " + dt.toString (_dateformat) + " " + i.second; } } std::vector raw; wrapText (raw, description, width, _hyphenate); - std::vector ::iterator i; - for (i = raw.begin (); i != raw.end (); ++i) - lines.push_back (color.colorize (leftJustify (*i, width))); + for (auto& i : raw) + lines.push_back (color.colorize (leftJustify (i, width))); } // This is a des... @@ -267,9 +252,8 @@ std::vector raw; wrapText (raw, description, width, _hyphenate); - std::vector ::iterator i; - for (i = raw.begin (); i != raw.end (); ++i) - lines.push_back (color.colorize (leftJustify (*i, width))); + for (auto& i : raw) + lines.push_back (color.colorize (leftJustify (i, width))); } // This is a des... [2] @@ -292,7 +276,6 @@ lines.push_back (color.colorize (description.substr (0, width - len_annos - 3) + "..." + annos_count)); else lines.push_back (color.colorize (leftJustify (description + annos_count, width))); - } } diff -Nru task-2.4.4+dfsg/src/columns/ColDescription.h task-2.5.0+dfsg/src/columns/ColDescription.h --- task-2.4.4+dfsg/src/columns/ColDescription.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColDescription.h 2015-10-21 21:18:15.000000000 +0000 @@ -39,7 +39,6 @@ ColumnDescription (); ~ColumnDescription (); - bool validate (std::string&); void measure (Task&, unsigned int&, unsigned int&); void render (std::vector &, Task&, int, Color&); diff -Nru task-2.4.4+dfsg/src/columns/ColDue.cpp task-2.5.0+dfsg/src/columns/ColDue.cpp --- task-2.4.4+dfsg/src/columns/ColDue.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColDue.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -28,8 +28,6 @@ #include #include #include -#include -#include #include #include @@ -40,10 +38,6 @@ { _name = "due"; _label = STRING_COLUMN_LABEL_DUE; - - Date now; - now += 125; - _examples.push_back (Duration (now - Date ()).formatCompact ()); } //////////////////////////////////////////////////////////////////////////////// @@ -52,17 +46,11 @@ } //////////////////////////////////////////////////////////////////////////////// -bool ColumnDue::validate (std::string& value) -{ - return ColumnDate::validate (value); -} - -//////////////////////////////////////////////////////////////////////////////// // Overriden so that style <----> label are linked. // Note that you can not determine which gets called first. void ColumnDue::setStyle (const std::string& value) { - _style = value; + Column::setStyle (value); if (_style == "countdown" && _label == STRING_COLUMN_LABEL_DUE) _label = STRING_COLUMN_LABEL_COUNT; diff -Nru task-2.4.4+dfsg/src/columns/ColDue.h task-2.5.0+dfsg/src/columns/ColDue.h --- task-2.4.4+dfsg/src/columns/ColDue.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColDue.h 2015-10-21 21:18:15.000000000 +0000 @@ -35,7 +35,6 @@ ColumnDue (); ~ColumnDue (); - bool validate (std::string&); void setStyle (const std::string&); }; diff -Nru task-2.4.4+dfsg/src/columns/ColEnd.cpp task-2.5.0+dfsg/src/columns/ColEnd.cpp --- task-2.4.4+dfsg/src/columns/ColEnd.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColEnd.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -41,9 +41,3 @@ } //////////////////////////////////////////////////////////////////////////////// -bool ColumnEnd::validate (std::string& value) -{ - return ColumnDate::validate (value); -} - -//////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/columns/ColEnd.h task-2.5.0+dfsg/src/columns/ColEnd.h --- task-2.4.4+dfsg/src/columns/ColEnd.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColEnd.h 2015-10-21 21:18:15.000000000 +0000 @@ -34,8 +34,6 @@ public: ColumnEnd (); ~ColumnEnd (); - - bool validate (std::string&); }; #endif diff -Nru task-2.4.4+dfsg/src/columns/ColEntry.cpp task-2.5.0+dfsg/src/columns/ColEntry.cpp --- task-2.4.4+dfsg/src/columns/ColEntry.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColEntry.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -41,12 +41,6 @@ } //////////////////////////////////////////////////////////////////////////////// -bool ColumnEntry::validate (std::string& value) -{ - return ColumnDate::validate (value); -} - -//////////////////////////////////////////////////////////////////////////////// // Overriden so that style <----> label are linked. // Note that you can not determine which gets called first. void ColumnEntry::setStyle (const std::string& value) diff -Nru task-2.4.4+dfsg/src/columns/ColEntry.h task-2.5.0+dfsg/src/columns/ColEntry.h --- task-2.4.4+dfsg/src/columns/ColEntry.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColEntry.h 2015-10-21 21:18:15.000000000 +0000 @@ -35,7 +35,6 @@ ColumnEntry (); ~ColumnEntry (); - bool validate (std::string&); void setStyle (const std::string&); }; diff -Nru task-2.4.4+dfsg/src/columns/ColID.cpp task-2.5.0+dfsg/src/columns/ColID.cpp --- task-2.4.4+dfsg/src/columns/ColID.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColID.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -41,10 +41,8 @@ _style = "number"; _label = STRING_COLUMN_LABEL_ID; _modifiable = false; - - _styles.push_back ("number"); - - _examples.push_back ("123"); + _styles = {"number"}; + _examples = {"123"}; } //////////////////////////////////////////////////////////////////////////////// @@ -53,22 +51,17 @@ } //////////////////////////////////////////////////////////////////////////////// -bool ColumnID::validate (std::string& value) -{ - return true; -} - -//////////////////////////////////////////////////////////////////////////////// // Set the minimum and maximum widths for the value. void ColumnID::measure (Task& task, unsigned int& minimum, unsigned int& maximum) { int length; - if (task.id < 10) length = 1; // Fast - else if (task.id < 100) length = 2; // Fast - else if (task.id < 1000) length = 3; // Fast - else if (task.id < 10000) length = 4; // Fast - else length = (int) log10 ((double) task.id); // Slow + if (task.id < 10) length = 1; // Fast + else if (task.id < 100) length = 2; // Fast + else if (task.id < 1000) length = 3; // Fast + else if (task.id < 10000) length = 4; // Fast + else if (task.id < 100000) length = 5; // Fast + else length = 1 + (int) log10 ((double) task.id); // Slow minimum = maximum = length; diff -Nru task-2.4.4+dfsg/src/columns/ColID.h task-2.5.0+dfsg/src/columns/ColID.h --- task-2.4.4+dfsg/src/columns/ColID.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColID.h 2015-10-21 21:18:15.000000000 +0000 @@ -39,7 +39,6 @@ ColumnID (); ~ColumnID (); - bool validate (std::string&); void measure (Task&, unsigned int&, unsigned int&); void render (std::vector &, Task&, int, Color&); diff -Nru task-2.4.4+dfsg/src/columns/ColIMask.cpp task-2.5.0+dfsg/src/columns/ColIMask.cpp --- task-2.4.4+dfsg/src/columns/ColIMask.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColIMask.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -41,10 +41,8 @@ _style = "number"; _label = STRING_COLUMN_LABEL_MASK_IDX; _modifiable = false; - - _styles.push_back ("number"); - - _examples.push_back ("12"); + _styles = {"number"}; + _examples = {"12"}; } //////////////////////////////////////////////////////////////////////////////// @@ -53,12 +51,6 @@ } //////////////////////////////////////////////////////////////////////////////// -bool ColumnIMask::validate (std::string& value) -{ - return true; -} - -//////////////////////////////////////////////////////////////////////////////// // Set the minimum and maximum widths for the value. void ColumnIMask::measure (Task& task, unsigned int& minimum, unsigned int& maximum) { diff -Nru task-2.4.4+dfsg/src/columns/ColIMask.h task-2.5.0+dfsg/src/columns/ColIMask.h --- task-2.4.4+dfsg/src/columns/ColIMask.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColIMask.h 2015-10-21 21:18:15.000000000 +0000 @@ -39,7 +39,6 @@ ColumnIMask (); ~ColumnIMask (); - bool validate (std::string&); void measure (Task&, unsigned int&, unsigned int&); void render (std::vector &, Task&, int, Color&); diff -Nru task-2.4.4+dfsg/src/columns/ColMask.cpp task-2.5.0+dfsg/src/columns/ColMask.cpp --- task-2.4.4+dfsg/src/columns/ColMask.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColMask.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -41,10 +41,8 @@ _style = "default"; _label = STRING_COLUMN_LABEL_MASK; _modifiable = false; - - _styles.push_back ("default"); - - _examples.push_back ("++++---"); + _styles = {"default"}; + _examples = {"++++---"}; } //////////////////////////////////////////////////////////////////////////////// @@ -53,12 +51,6 @@ } //////////////////////////////////////////////////////////////////////////////// -bool ColumnMask::validate (std::string& value) -{ - return true; -} - -//////////////////////////////////////////////////////////////////////////////// // Set the minimum and maximum widths for the value. void ColumnMask::measure (Task& task, unsigned int& minimum, unsigned int& maximum) { @@ -76,7 +68,7 @@ void ColumnMask::render ( std::vector & lines, Task& task, - int width, + int, Color& color) { if (task.has (_name)) diff -Nru task-2.4.4+dfsg/src/columns/ColMask.h task-2.5.0+dfsg/src/columns/ColMask.h --- task-2.4.4+dfsg/src/columns/ColMask.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColMask.h 2015-10-21 21:18:15.000000000 +0000 @@ -39,7 +39,6 @@ ColumnMask (); ~ColumnMask (); - bool validate (std::string&); void measure (Task&, unsigned int&, unsigned int&); void render (std::vector &, Task&, int, Color&); diff -Nru task-2.4.4+dfsg/src/columns/ColModified.cpp task-2.5.0+dfsg/src/columns/ColModified.cpp --- task-2.4.4+dfsg/src/columns/ColModified.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColModified.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -41,9 +41,3 @@ } //////////////////////////////////////////////////////////////////////////////// -bool ColumnModified::validate (std::string& value) -{ - return ColumnDate::validate (value); -} - -//////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/columns/ColModified.h task-2.5.0+dfsg/src/columns/ColModified.h --- task-2.4.4+dfsg/src/columns/ColModified.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColModified.h 2015-10-21 21:18:15.000000000 +0000 @@ -34,8 +34,6 @@ public: ColumnModified (); ~ColumnModified (); - - bool validate (std::string&); }; #endif diff -Nru task-2.4.4+dfsg/src/columns/ColParent.cpp task-2.5.0+dfsg/src/columns/ColParent.cpp --- task-2.4.4+dfsg/src/columns/ColParent.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColParent.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -41,12 +41,8 @@ _style = "long"; _label = STRING_COLUMN_LABEL_PARENT; _modifiable = false; - - _styles.push_back ("long"); - _styles.push_back ("short"); - - _examples.push_back ("f30cb9c3-3fc0-483f-bfb2-3bf134f00694"); - _examples.push_back ("34f00694"); + _styles = {"long", "short"}; + _examples = {"f30cb9c3-3fc0-483f-bfb2-3bf134f00694", "34f00694"}; } //////////////////////////////////////////////////////////////////////////////// @@ -55,12 +51,6 @@ } //////////////////////////////////////////////////////////////////////////////// -bool ColumnParent::validate (std::string& value) -{ - return true; -} - -//////////////////////////////////////////////////////////////////////////////// // Set the minimum and maximum widths for the value. void ColumnParent::measure (Task& task, unsigned int& minimum, unsigned int& maximum) { diff -Nru task-2.4.4+dfsg/src/columns/ColParent.h task-2.5.0+dfsg/src/columns/ColParent.h --- task-2.4.4+dfsg/src/columns/ColParent.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColParent.h 2015-10-21 21:18:15.000000000 +0000 @@ -39,7 +39,6 @@ ColumnParent (); ~ColumnParent (); - bool validate (std::string&); void measure (Task&, unsigned int&, unsigned int&); void render (std::vector &, Task&, int, Color&); diff -Nru task-2.4.4+dfsg/src/columns/ColProject.cpp task-2.5.0+dfsg/src/columns/ColProject.cpp --- task-2.4.4+dfsg/src/columns/ColProject.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColProject.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -37,19 +37,14 @@ //////////////////////////////////////////////////////////////////////////////// ColumnProject::ColumnProject () { - _name = "project"; - _type = "string"; - _style = "full"; - _label = STRING_COLUMN_LABEL_PROJECT; - - _styles.push_back ("full"); - _styles.push_back ("parent"); - _styles.push_back ("indented"); - - _examples.push_back (STRING_COLUMN_EXAMPLES_PROJ); - _examples.push_back (STRING_COLUMN_EXAMPLES_PAR); - _examples.push_back (STRING_COLUMN_EXAMPLES_IND); - + _name = "project"; + _type = "string"; + _style = "full"; + _label = STRING_COLUMN_LABEL_PROJECT; + _styles = {"full", "parent", "indented"}; + _examples = {STRING_COLUMN_EXAMPLES_PROJ, + STRING_COLUMN_EXAMPLES_PAR, + STRING_COLUMN_EXAMPLES_IND}; _hyphenate = context.config.getBoolean ("hyphenate"); } @@ -59,12 +54,6 @@ } //////////////////////////////////////////////////////////////////////////////// -bool ColumnProject::validate (std::string& value) -{ - return true; -} - -//////////////////////////////////////////////////////////////////////////////// // Set the minimum and maximum widths for the value. void ColumnProject::measure (Task& task, unsigned int& minimum, unsigned int& maximum) { @@ -76,7 +65,7 @@ if (_style == "parent") { - std::string::size_type period = project.find ('.'); + auto period = project.find ('.'); if (period != std::string::npos) project = project.substr (0, period); } @@ -106,7 +95,7 @@ std::string project = task.get (_name); if (_style == "parent") { - std::string::size_type period = project.find ('.'); + auto period = project.find ('.'); if (period != std::string::npos) project = project.substr (0, period); } @@ -118,9 +107,8 @@ std::vector raw; wrapText (raw, project, width, _hyphenate); - std::vector ::iterator i; - for (i = raw.begin (); i != raw.end (); ++i) - lines.push_back (color.colorize (leftJustify (*i, width))); + for (auto& i : raw) + lines.push_back (color.colorize (leftJustify (i, width))); } } diff -Nru task-2.4.4+dfsg/src/columns/ColProject.h task-2.5.0+dfsg/src/columns/ColProject.h --- task-2.4.4+dfsg/src/columns/ColProject.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColProject.h 2015-10-21 21:18:15.000000000 +0000 @@ -39,7 +39,6 @@ ColumnProject (); ~ColumnProject (); - bool validate (std::string&); void measure (Task&, unsigned int&, unsigned int&); void render (std::vector &, Task&, int, Color&); diff -Nru task-2.4.4+dfsg/src/columns/ColRecur.cpp task-2.5.0+dfsg/src/columns/ColRecur.cpp --- task-2.4.4+dfsg/src/columns/ColRecur.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColRecur.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -26,7 +26,7 @@ #include #include -#include +#include #include #include #include @@ -37,20 +37,16 @@ //////////////////////////////////////////////////////////////////////////////// ColumnRecur::ColumnRecur () { - _name = "recur"; + _name = "recur"; // This is 'string', and not 'duration' to force the value to be stored as a // raw duration, so that it can be reevaluated every time. - _type = "string"; + _type = "string"; - _style = "duration"; - _label = STRING_COLUMN_LABEL_RECUR; - - _styles.push_back ("duration"); - _styles.push_back ("indicator"); - - _examples.push_back ("weekly"); - _examples.push_back (context.config.get ("recurrence.indicator")); + _style = "duration"; + _label = STRING_COLUMN_LABEL_RECUR; + _styles = {"duration", "indicator"}; + _examples = {"weekly", context.config.get ("recurrence.indicator")}; } //////////////////////////////////////////////////////////////////////////////// @@ -59,12 +55,6 @@ } //////////////////////////////////////////////////////////////////////////////// -bool ColumnRecur::validate (std::string& value) -{ - return true; -} - -//////////////////////////////////////////////////////////////////////////////// // Overriden so that style <----> label are linked. // Note that you can not determine which gets called first. void ColumnRecur::setStyle (const std::string& value) @@ -86,12 +76,14 @@ if (_style == "default" || _style == "duration") { - minimum = maximum = Duration (task.get ("recur")).formatISO ().length (); + minimum = maximum = ISO8601p (task.get ("recur")).format ().length (); } else if (_style == "indicator") { - minimum = maximum = utf8_width (context.config.get ("recurrence.indicator")); - _fixed_width = true; + if (task.has ("recur")) + minimum = maximum = utf8_width (context.config.get ("recurrence.indicator")); + else + minimum = maximum = 0; } else throw format (STRING_COLUMN_BAD_FORMAT, _name, _style); @@ -113,7 +105,7 @@ lines.push_back ( color.colorize ( rightJustify ( - Duration (task.get ("recur")).formatISO (), width))); + ISO8601p (task.get ("recur")).format (), width))); } else if (_style == "indicator") { diff -Nru task-2.4.4+dfsg/src/columns/ColRecur.h task-2.5.0+dfsg/src/columns/ColRecur.h --- task-2.4.4+dfsg/src/columns/ColRecur.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColRecur.h 2015-10-21 21:18:15.000000000 +0000 @@ -39,7 +39,6 @@ ColumnRecur (); ~ColumnRecur (); - bool validate (std::string&); void setStyle (const std::string&); void measure (Task&, unsigned int&, unsigned int&); void render (std::vector &, Task&, int, Color&); diff -Nru task-2.4.4+dfsg/src/columns/ColScheduled.cpp task-2.5.0+dfsg/src/columns/ColScheduled.cpp --- task-2.4.4+dfsg/src/columns/ColScheduled.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColScheduled.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -28,8 +28,6 @@ #include #include #include -#include -#include #include #include @@ -38,14 +36,8 @@ //////////////////////////////////////////////////////////////////////////////// ColumnScheduled::ColumnScheduled () { - _name = "scheduled"; - _label = STRING_COLUMN_LABEL_SCHED; - - _styles.push_back ("countdown"); - - Date now; - now += 125; - _examples.push_back (Duration (now - Date ()).formatCompact ()); + _name = "scheduled"; + _label = STRING_COLUMN_LABEL_SCHED; } //////////////////////////////////////////////////////////////////////////////// @@ -54,12 +46,6 @@ } //////////////////////////////////////////////////////////////////////////////// -bool ColumnScheduled::validate (std::string& value) -{ - return ColumnDate::validate (value); -} - -//////////////////////////////////////////////////////////////////////////////// // Overriden so that style <----> label are linked. // Note that you can not determine which gets called first. void ColumnScheduled::setStyle (const std::string& value) diff -Nru task-2.4.4+dfsg/src/columns/ColScheduled.h task-2.5.0+dfsg/src/columns/ColScheduled.h --- task-2.4.4+dfsg/src/columns/ColScheduled.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColScheduled.h 2015-10-21 21:18:15.000000000 +0000 @@ -35,7 +35,6 @@ ColumnScheduled (); ~ColumnScheduled (); - bool validate (std::string&); void setStyle (const std::string&); }; diff -Nru task-2.4.4+dfsg/src/columns/ColStart.cpp task-2.5.0+dfsg/src/columns/ColStart.cpp --- task-2.4.4+dfsg/src/columns/ColStart.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColStart.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -40,7 +40,6 @@ _label = STRING_COLUMN_LABEL_STARTED; _styles.push_back ("active"); - _examples.push_back (context.config.get ("active.indicator")); } @@ -50,12 +49,6 @@ } //////////////////////////////////////////////////////////////////////////////// -bool ColumnStart::validate (std::string& value) -{ - return ColumnDate::validate (value); -} - -//////////////////////////////////////////////////////////////////////////////// // Overriden so that style <----> label are linked. // Note that you can not determine which gets called first. void ColumnStart::setStyle (const std::string& value) @@ -76,8 +69,10 @@ { if (_style == "active") { - minimum = maximum = utf8_width (context.config.get ("active.indicator")); - _fixed_width = true; + if (task.has ("start")) + minimum = maximum = utf8_width (context.config.get ("active.indicator")); + else + minimum = maximum = 0; } else ColumnDate::measure (task, minimum, maximum); diff -Nru task-2.4.4+dfsg/src/columns/ColStart.h task-2.5.0+dfsg/src/columns/ColStart.h --- task-2.4.4+dfsg/src/columns/ColStart.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColStart.h 2015-10-21 21:18:15.000000000 +0000 @@ -35,7 +35,6 @@ ColumnStart (); ~ColumnStart (); - bool validate (std::string&); void setStyle (const std::string&); void measure (Task&, unsigned int&, unsigned int&); void render (std::vector &, Task&, int, Color&); diff -Nru task-2.4.4+dfsg/src/columns/ColStatus.cpp task-2.5.0+dfsg/src/columns/ColStatus.cpp --- task-2.4.4+dfsg/src/columns/ColStatus.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColStatus.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -36,16 +36,13 @@ //////////////////////////////////////////////////////////////////////////////// ColumnStatus::ColumnStatus () { - _name = "status"; - _type = "string"; - _style = "long"; - _label = STRING_COLUMN_LABEL_STATUS; - - _styles.push_back ("long"); - _styles.push_back ("short"); - - _examples.push_back (STRING_COLUMN_LABEL_STAT_PE); - _examples.push_back (STRING_COLUMN_LABEL_STAT_P); + _name = "status"; + _type = "string"; + _style = "long"; + _label = STRING_COLUMN_LABEL_STATUS; + _styles = {"long", "short"}; + _examples = {STRING_COLUMN_LABEL_STAT_PE, + STRING_COLUMN_LABEL_STAT_P}; } //////////////////////////////////////////////////////////////////////////////// @@ -54,12 +51,6 @@ } //////////////////////////////////////////////////////////////////////////////// -bool ColumnStatus::validate (std::string& value) -{ - return true; -} - -//////////////////////////////////////////////////////////////////////////////// // Overriden so that style <----> label are linked. // Note that you can not determine which gets called first. void ColumnStatus::setStyle (const std::string& value) diff -Nru task-2.4.4+dfsg/src/columns/ColStatus.h task-2.5.0+dfsg/src/columns/ColStatus.h --- task-2.4.4+dfsg/src/columns/ColStatus.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColStatus.h 2015-10-21 21:18:15.000000000 +0000 @@ -39,7 +39,6 @@ ColumnStatus (); ~ColumnStatus (); - bool validate (std::string&); void setStyle (const std::string&); void measure (Task&, unsigned int&, unsigned int&); void render (std::vector &, Task&, int, Color&); diff -Nru task-2.4.4+dfsg/src/columns/ColString.cpp task-2.5.0+dfsg/src/columns/ColString.cpp --- task-2.4.4+dfsg/src/columns/ColString.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColString.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -35,21 +35,18 @@ //////////////////////////////////////////////////////////////////////////////// ColumnString::ColumnString () { - _name = "string"; - _type = "string"; - _style = "left"; - _label = ""; - - _styles.push_back ("left"); - _styles.push_back ("right"); - _styles.push_back ("left_fixed"); - _styles.push_back ("right_fixed"); - - _styles.push_back ("Hello (wrapped) "); - _styles.push_back (" Hello (wrapped)"); - _styles.push_back ("Hello (no-wrap) "); - _styles.push_back (" Hello (no-wrap)"); - + _name = "string"; + _type = "string"; + _style = "left"; + _label = ""; + _styles = {"left", + "right", + "left_fixed", + "right_fixed"}; + _examples = {"Hello (wrapped) ", + " Hello (wrapped)", + "Hello (no-wrap) ", + " Hello (no-wrap)"}; _hyphenate = context.config.getBoolean ("hyphenate"); } @@ -100,18 +97,16 @@ std::vector raw; wrapText (raw, value, width, _hyphenate); - std::vector ::iterator i; - for (i = raw.begin (); i != raw.end (); ++i) - lines.push_back (color.colorize (leftJustify (*i, width))); + for (auto& i : raw) + lines.push_back (color.colorize (leftJustify (i, width))); } else if (_style == "right") { std::vector raw; wrapText (raw, value, width, _hyphenate); - std::vector ::iterator i; - for (i = raw.begin (); i != raw.end (); ++i) - lines.push_back (color.colorize (rightJustify (*i, width))); + for (auto& i : raw) + lines.push_back (color.colorize (rightJustify (i, width))); } else if (_style == "left_fixed") { diff -Nru task-2.4.4+dfsg/src/columns/ColTags.cpp task-2.5.0+dfsg/src/columns/ColTags.cpp --- task-2.4.4+dfsg/src/columns/ColTags.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColTags.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -37,19 +37,14 @@ //////////////////////////////////////////////////////////////////////////////// ColumnTags::ColumnTags () { - _name = "tags"; - _type = "string"; - _style = "list"; - _label = STRING_COLUMN_LABEL_TAGS; - - _styles.push_back ("list"); - _styles.push_back ("indicator"); - _styles.push_back ("count"); - - _examples.push_back (STRING_COLUMN_EXAMPLES_TAGS); - _examples.push_back (context.config.get ("tag.indicator")); - _examples.push_back ("[2]"); - + _name = "tags"; + _type = "string"; + _style = "list"; + _label = STRING_COLUMN_LABEL_TAGS; + _styles = {"list", "indicator", "count"}; + _examples = {STRING_COLUMN_EXAMPLES_TAGS, + context.config.get ("tag.indicator"), + "[2]"}; _hyphenate = context.config.getBoolean ("hyphenate"); } @@ -59,12 +54,6 @@ } //////////////////////////////////////////////////////////////////////////////// -bool ColumnTags::validate (std::string& value) -{ - return true; -} - -//////////////////////////////////////////////////////////////////////////////// // Overriden so that style <----> label are linked. // Note that you can not determine which gets called first. void ColumnTags::setStyle (const std::string& value) @@ -90,8 +79,10 @@ { if (_style == "indicator") { - minimum = maximum = utf8_width (context.config.get ("tag.indicator")); - _fixed_width = true; + if (task.has ("tags")) + minimum = maximum = utf8_width (context.config.get ("tag.indicator")); + else + minimum = maximum = 0; } else if (_style == "count") { @@ -107,10 +98,9 @@ { std::vector all; split (all, tags, ','); - std::vector ::iterator i; - for (i = all.begin (); i != all.end (); ++i) + for (auto& i : all) { - unsigned int length = utf8_width (*i); + unsigned int length = utf8_width (i); if (length > minimum) minimum = length; } @@ -145,9 +135,8 @@ std::vector all; wrapText (all, tags, width, _hyphenate); - std::vector ::iterator i; - for (i = all.begin (); i != all.end (); ++i) - lines.push_back (color.colorize (leftJustify (*i, width))); + for (auto& i : all) + lines.push_back (color.colorize (leftJustify (i, width))); } else if (_style == "indicator") { diff -Nru task-2.4.4+dfsg/src/columns/ColTags.h task-2.5.0+dfsg/src/columns/ColTags.h --- task-2.4.4+dfsg/src/columns/ColTags.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColTags.h 2015-10-21 21:18:15.000000000 +0000 @@ -39,7 +39,6 @@ ColumnTags (); ~ColumnTags (); - bool validate (std::string&); void setStyle (const std::string&); void measure (Task&, unsigned int&, unsigned int&); void render (std::vector &, Task&, int, Color&); diff -Nru task-2.4.4+dfsg/src/columns/ColUDA.cpp task-2.5.0+dfsg/src/columns/ColUDA.cpp --- task-2.4.4+dfsg/src/columns/ColUDA.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColUDA.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -26,8 +26,7 @@ #include #include -#include -#include +#include #include #include #include @@ -39,16 +38,13 @@ //////////////////////////////////////////////////////////////////////////////// ColumnUDA::ColumnUDA () { - _name = ""; - _type = "string"; - _style = "default"; - _label = ""; - _uda = true; - + _name = ""; + _type = "string"; + _style = "default"; + _label = ""; + _uda = true; _hyphenate = (_type == "string") ? true : false; - - _styles.push_back (_style); - _styles.push_back ("indicator"); + _styles = {_style, "indicator"}; } //////////////////////////////////////////////////////////////////////////////// @@ -64,9 +60,8 @@ return true; // Look for exact match value. - std::vector ::iterator i; - for (i = _values.begin (); i != _values.end (); ++i) - if (*i == value) + for (auto& i : _values) + if (i == value) return true; // Fail if not found. @@ -93,18 +88,18 @@ // rc.report..dateformat // rc.dateformat.report // rc.dateformat - Date date ((time_t) strtol (value.c_str (), NULL, 10)); + ISO8601d 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); + minimum = maximum = ISO8601d::length (format); } else if (_type == "duration") { - minimum = maximum = utf8_width (Duration (value).formatISO ()); + minimum = maximum = utf8_width (ISO8601p (value).format ()); } else if (_type == "string") { @@ -120,8 +115,10 @@ } else if (_style == "indicator") { - minimum = maximum = utf8_width (context.config.get ("uda." + _name + ".indicator")); - _fixed_width = true; + if (task.has (_name)) + minimum = maximum = utf8_width (context.config.get ("uda." + _name + ".indicator")); + else + minimum = maximum = 0; } else throw format (STRING_COLUMN_BAD_FORMAT, _name, _style); @@ -155,15 +152,14 @@ lines.push_back ( color.colorize ( leftJustify ( - Date ((time_t) strtol (value.c_str (), NULL, 10)) - .toString (format), width))); + ISO8601d ((time_t) strtol (value.c_str (), NULL, 10)).toString (format), width))); } else if (_type == "duration") { lines.push_back ( color.colorize ( rightJustify ( - Duration (value).formatISO (), + ISO8601p (value).format (), width))); } else if (_type == "string") @@ -171,9 +167,8 @@ std::vector raw; wrapText (raw, value, width, _hyphenate); - std::vector ::iterator i; - for (i = raw.begin (); i != raw.end (); ++i) - lines.push_back (color.colorize (leftJustify (*i, width))); + for (auto& i : raw) + lines.push_back (color.colorize (leftJustify (i, width))); } else if (_type == "numeric") { diff -Nru task-2.4.4+dfsg/src/columns/Column.cpp task-2.5.0+dfsg/src/columns/Column.cpp --- task-2.4.4+dfsg/src/columns/Column.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/Column.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -25,6 +25,7 @@ //////////////////////////////////////////////////////////////////////////////// #include +#include #include #include #include @@ -62,7 +63,7 @@ Column* Column::factory (const std::string& name, const std::string& report) { // Decompose name into type and style. - std::string::size_type dot = name.find ('.'); + auto dot = name.find ('.'); std::string column_name; std::string column_style; if (dot != std::string::npos) @@ -149,24 +150,22 @@ // For each UDA, instantiate and initialize ColumnUDA(). std::map udas; - Config::const_iterator i; - for (i = context.config.begin (); i != context.config.end (); ++i) + for (auto& i : context.config) { - if (i->first.substr (0, 4) == "uda.") + if (i.first.substr (0, 4) == "uda.") { std::string::size_type period = 4; - if ((period = i->first.find ('.', period)) != std::string::npos) - udas[i->first.substr (4, period - 4)] = 0; + if ((period = i.first.find ('.', period)) != std::string::npos) + udas[i.first.substr (4, period - 4)] = 0; } } - std::map ::iterator uda; - for (uda = udas.begin (); uda != udas.end (); ++uda) + for (auto& uda : udas) { - if (all.find (uda->first) != all.end ()) - throw format (STRING_UDA_COLLISION, uda->first); + if (all.find (uda.first) != all.end ()) + throw format (STRING_UDA_COLLISION, uda.first); - Column* c = Column::uda (uda->first); + Column* c = Column::uda (uda.first); all[c->_name] = c; } } @@ -213,49 +212,6 @@ } //////////////////////////////////////////////////////////////////////////////// -Column::Column (const Column& other) -{ - _name = other._name; - _type = other._type; - _style = other._style; - _label = other._label; - _label = other._report; - _modifiable = other._modifiable; - _uda = other._uda; - _fixed_width = other._fixed_width; -} - -//////////////////////////////////////////////////////////////////////////////// -Column& Column::operator= (const Column& other) -{ - if (this != &other) - { - _name = other._name; - _type = other._type; - _style = other._style; - _label = other._label; - _report = other._report; - _modifiable = other._modifiable; - _uda = other._uda; - _fixed_width = other._fixed_width; - } - - return *this; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Column::operator== (const Column& other) const -{ - return _name == other._name && - _type == other._type && - _style == other._style && - _label == other._label && - _report == other._report && - _modifiable == other._modifiable && - _uda == other._uda; -} - -//////////////////////////////////////////////////////////////////////////////// Column::~Column () { } @@ -293,37 +249,19 @@ } //////////////////////////////////////////////////////////////////////////////// -bool Column::validate (std::string& input) +void Column::setStyle (const std::string& style) { - return input.length () ? true : false; -} + if (style != "default" && + std::find (_styles.begin (), _styles.end (), style) == _styles.end ()) + throw format (STRING_COLUMN_BAD_FORMAT, _name, style); -//////////////////////////////////////////////////////////////////////////////// -// No L10N. -void Column::measure (const std::string&, unsigned int&, unsigned int&) -{ - throw std::string ("Virtual method Column::measure not overridden."); -} - -//////////////////////////////////////////////////////////////////////////////// -// No L10N. -void Column::measure (Task&, unsigned int&, unsigned int&) -{ - throw std::string ("Virtual method Column::measure not overridden."); + _style = style; } //////////////////////////////////////////////////////////////////////////////// -// No L10N. -void Column::render (std::vector &, const std::string&, int, Color&) -{ - throw std::string ("Virtual method Column::render not overridden."); -} - -//////////////////////////////////////////////////////////////////////////////// -// No L10N. -void Column::render (std::vector &, Task&, int, Color&) +bool Column::validate (std::string& input) { - throw std::string ("Virtual method Column::render not overridden."); + return input.length () ? true : false; } //////////////////////////////////////////////////////////////////////////////// @@ -334,10 +272,3 @@ } //////////////////////////////////////////////////////////////////////////////// -// No L10N. -std::string Column::modify (std::string& value) -{ - throw std::string ("Virtual method Column::modify not overridden."); -} - -//////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/columns/Column.h task-2.5.0+dfsg/src/columns/Column.h --- task-2.4.4+dfsg/src/columns/Column.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/Column.h 2015-10-21 21:18:15.000000000 +0000 @@ -41,33 +41,30 @@ static Column* uda (const std::string&); Column (); - Column (const Column&); - Column& operator= (const Column&); - bool operator== (const Column&) const; // TODO Is this necessary? virtual ~Column (); - const std::string& name () const { return _name; } - const std::string& style () const { return _style; } - const std::string& label () const { return _label; } - const std::string& type () const { return _type; } - bool modifiable () const { return _modifiable; } - bool is_uda () const { return _uda; } - bool is_fixed_width () const { return _fixed_width;} - std::vector styles () const { return _styles; } - std::vector examples () const { return _examples; } + const std::string& name () const { return _name; } + const std::string& style () const { return _style; } + const std::string& label () const { return _label; } + const std::string& type () const { return _type; } + bool modifiable () const { return _modifiable; } + bool is_uda () const { return _uda; } + bool is_fixed_width () const { return _fixed_width; } + std::vector styles () const { return _styles; } + std::vector examples () const { return _examples; } - virtual void setStyle (const std::string& value) { _style = value; } + virtual void setStyle (const std::string&); virtual void setLabel (const std::string& value) { _label = value; } virtual void setReport (const std::string& value) { _report = value; } virtual bool validate (std::string&); - virtual void measure (const std::string&, unsigned int&, unsigned int&); - virtual void measure (Task&, unsigned int&, unsigned int&); + virtual void measure (const std::string&, unsigned int&, unsigned int&) {}; + virtual void measure (Task&, unsigned int&, unsigned int&) {}; virtual void renderHeader (std::vector &, int, Color&); - virtual void render (std::vector &, const std::string&, int, Color&); - virtual void render (std::vector &, Task&, int, Color&); + virtual void render (std::vector &, const std::string&, int, Color&) {}; + virtual void render (std::vector &, Task&, int, Color&) {}; virtual bool can_modify (); - virtual std::string modify (std::string&); + virtual std::string modify (std::string& input) { return input; }; protected: std::string _name; diff -Nru task-2.4.4+dfsg/src/columns/ColUntil.cpp task-2.5.0+dfsg/src/columns/ColUntil.cpp --- task-2.4.4+dfsg/src/columns/ColUntil.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColUntil.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -41,9 +41,3 @@ } //////////////////////////////////////////////////////////////////////////////// -bool ColumnUntil::validate (std::string& value) -{ - return ColumnDate::validate (value); -} - -//////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/columns/ColUntil.h task-2.5.0+dfsg/src/columns/ColUntil.h --- task-2.4.4+dfsg/src/columns/ColUntil.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColUntil.h 2015-10-21 21:18:15.000000000 +0000 @@ -34,8 +34,6 @@ public: ColumnUntil (); ~ColumnUntil (); - - bool validate (std::string&); }; #endif diff -Nru task-2.4.4+dfsg/src/columns/ColUrgency.cpp task-2.5.0+dfsg/src/columns/ColUrgency.cpp --- task-2.4.4+dfsg/src/columns/ColUrgency.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColUrgency.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -35,16 +35,12 @@ //////////////////////////////////////////////////////////////////////////////// ColumnUrgency::ColumnUrgency () { - _name = "urgency"; - _type = "numeric"; - _style = "real"; - _label = STRING_COLUMN_LABEL_URGENCY; - - _styles.push_back ("real"); - _styles.push_back ("integer"); - - _examples.push_back ("4.6"); - _examples.push_back ("4"); + _name = "urgency"; + _type = "numeric"; + _style = "real"; + _label = STRING_COLUMN_LABEL_URGENCY; + _styles = {"real", "integer"}; + _examples = {"4.6", "4"}; } //////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/columns/ColUUID.cpp task-2.5.0+dfsg/src/columns/ColUUID.cpp --- task-2.4.4+dfsg/src/columns/ColUUID.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColUUID.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -41,12 +41,8 @@ _style = "long"; _label = STRING_COLUMN_LABEL_UUID; _modifiable = false; - - _styles.push_back ("long"); - _styles.push_back ("short"); - - _examples.push_back ("f30cb9c3-3fc0-483f-bfb2-3bf134f00694"); - _examples.push_back ("f30cb9c3"); + _styles = {"long", "short"}; + _examples = {"f30cb9c3-3fc0-483f-bfb2-3bf134f00694", "f30cb9c3"}; } //////////////////////////////////////////////////////////////////////////////// @@ -55,12 +51,6 @@ } //////////////////////////////////////////////////////////////////////////////// -bool ColumnUUID::validate (std::string& value) -{ - return true; -} - -//////////////////////////////////////////////////////////////////////////////// // Set the minimum and maximum widths for the value. void ColumnUUID::measure (Task&, unsigned int& minimum, unsigned int& maximum) { diff -Nru task-2.4.4+dfsg/src/columns/ColUUID.h task-2.5.0+dfsg/src/columns/ColUUID.h --- task-2.4.4+dfsg/src/columns/ColUUID.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColUUID.h 2015-10-21 21:18:15.000000000 +0000 @@ -39,7 +39,6 @@ ColumnUUID (); ~ColumnUUID (); - bool validate (std::string&); void measure (Task&, unsigned int&, unsigned int&); void render (std::vector &, Task&, int, Color&); diff -Nru task-2.4.4+dfsg/src/columns/ColWait.cpp task-2.5.0+dfsg/src/columns/ColWait.cpp --- task-2.4.4+dfsg/src/columns/ColWait.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColWait.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -41,9 +41,3 @@ } //////////////////////////////////////////////////////////////////////////////// -bool ColumnWait::validate (std::string& value) -{ - return ColumnDate::validate (value); -} - -//////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/columns/ColWait.h task-2.5.0+dfsg/src/columns/ColWait.h --- task-2.4.4+dfsg/src/columns/ColWait.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/columns/ColWait.h 2015-10-21 21:18:15.000000000 +0000 @@ -34,8 +34,6 @@ public: ColumnWait (); ~ColumnWait (); - - bool validate (std::string&); }; #endif diff -Nru task-2.4.4+dfsg/src/commands/CMakeLists.txt task-2.5.0+dfsg/src/commands/CMakeLists.txt --- task-2.4.4+dfsg/src/commands/CMakeLists.txt 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CMakeLists.txt 2015-10-21 21:18:15.000000000 +0000 @@ -51,6 +51,7 @@ CmdTimesheet.cpp CmdTimesheet.h CmdUDAs.cpp CmdUDAs.h CmdUndo.cpp CmdUndo.h + CmdUnique.cpp CmdUnique.h CmdUrgency.cpp CmdUrgency.h CmdVersion.cpp CmdVersion.h) diff -Nru task-2.4.4+dfsg/src/commands/CmdAdd.cpp task-2.5.0+dfsg/src/commands/CmdAdd.cpp --- task-2.4.4+dfsg/src/commands/CmdAdd.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdAdd.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -37,11 +37,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdAdd::CmdAdd () { - _keyword = "add"; - _usage = "task add "; - _description = STRING_CMD_ADD_USAGE; - _read_only = false; - _displays_id = false; + _keyword = "add"; + _usage = "task add "; + _description = STRING_CMD_ADD_USAGE; + _read_only = false; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = false; + _accepts_modifications = true; + _accepts_miscellaneous = false; + _category = Command::Category::operation; } //////////////////////////////////////////////////////////////////////////////// @@ -52,7 +58,8 @@ task.modify (Task::modReplace, true); context.tdb2.add (task); - if (context.verbose ("new-id")) + // Do not display ID 0, users cannot query by that + if (context.verbose ("new-id") && task.id != 0) output += format (STRING_CMD_ADD_FEEDBACK, task.id) + "\n"; else if (context.verbose ("new-uuid")) output += format (STRING_CMD_ADD_FEEDBACK, task.get ("uuid")) + "\n"; diff -Nru task-2.4.4+dfsg/src/commands/CmdAliases.cpp task-2.5.0+dfsg/src/commands/CmdAliases.cpp --- task-2.4.4+dfsg/src/commands/CmdAliases.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdAliases.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -35,20 +35,25 @@ //////////////////////////////////////////////////////////////////////////////// CmdCompletionAliases::CmdCompletionAliases () { - _keyword = "_aliases"; - _usage = "task _aliases"; - _description = STRING_CMD_ALIASES_USAGE; - _read_only = true; - _displays_id = false; + _keyword = "_aliases"; + _usage = "task _aliases"; + _description = STRING_CMD_ALIASES_USAGE; + _read_only = true; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = false; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::internal; } //////////////////////////////////////////////////////////////////////////////// int CmdCompletionAliases::execute (std::string& output) { - std::map ::iterator alias; - for (alias = context.config.begin (); alias != context.config.end (); ++alias) - if (alias->first.substr (0, 6) == "alias.") - output += alias->first.substr (6) + "\n"; + for (auto& alias : context.config) + if (alias.first.substr (0, 6) == "alias.") + output += alias.first.substr (6) + "\n"; return 0; } diff -Nru task-2.4.4+dfsg/src/commands/CmdAnnotate.cpp task-2.5.0+dfsg/src/commands/CmdAnnotate.cpp --- task-2.4.4+dfsg/src/commands/CmdAnnotate.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdAnnotate.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -39,15 +39,21 @@ //////////////////////////////////////////////////////////////////////////////// CmdAnnotate::CmdAnnotate () { - _keyword = "annotate"; - _usage = "task annotate "; - _description = STRING_CMD_ANNO_USAGE; - _read_only = false; - _displays_id = false; + _keyword = "annotate"; + _usage = "task annotate "; + _description = STRING_CMD_ANNO_USAGE; + _read_only = false; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = true; + _accepts_modifications = true; + _accepts_miscellaneous = false; + _category = Command::Category::operation; } //////////////////////////////////////////////////////////////////////////////// -int CmdAnnotate::execute (std::string& output) +int CmdAnnotate::execute (std::string&) { int rc = 0; int count = 0; @@ -67,46 +73,44 @@ // Accumulated project change notifications. std::map projectChanges; - std::vector ::iterator task; - for (task = filtered.begin (); task != filtered.end (); ++task) + for (auto& task : filtered) { - Task before (*task); + Task before (task); // Annotate the specified task. std::string question = format (STRING_CMD_ANNO_CONFIRM, - task->id, - task->get ("description")); + task.id, + task.get ("description")); - task->modify (Task::modAnnotate, true); + task.modify (Task::modAnnotate, true); - if (permission (*task, taskDifferences (before, *task) + question, filtered.size ())) + if (permission (taskDifferences (before, task) + question, filtered.size ())) { - context.tdb2.modify (*task); + context.tdb2.modify (task); ++count; - feedback_affected (STRING_CMD_ANNO_TASK, *task); + feedback_affected (STRING_CMD_ANNO_TASK, task); if (context.verbose ("project")) - projectChanges[task->get ("project")] = onProjectChange (*task, false); + projectChanges[task.get ("project")] = onProjectChange (task, false); // Annotate siblings. - if (task->has ("parent")) + if (task.has ("parent")) { if ((context.config.get ("recurrence.confirmation") == "prompt" && confirm (STRING_CMD_ANNO_CONFIRM_R)) || context.config.getBoolean ("recurrence.confirmation")) { - std::vector siblings = context.tdb2.siblings (*task); - std::vector ::iterator sibling; - for (sibling = siblings.begin (); sibling != siblings.end (); ++sibling) + std::vector siblings = context.tdb2.siblings (task); + for (auto& sibling : siblings) { - sibling->modify (Task::modAnnotate, true); - context.tdb2.modify (*sibling); + sibling.modify (Task::modAnnotate, true); + context.tdb2.modify (sibling); ++count; - feedback_affected (STRING_CMD_ANNO_TASK_R, *sibling); + feedback_affected (STRING_CMD_ANNO_TASK_R, sibling); } // Annotate the parent Task parent; - context.tdb2.get (task->get ("parent"), parent); + context.tdb2.get (task.get ("parent"), parent); parent.modify (Task::modAnnotate, true); context.tdb2.modify (parent); } @@ -122,10 +126,9 @@ } // Now list the project changes. - std::map ::iterator i; - for (i = projectChanges.begin (); i != projectChanges.end (); ++i) - if (i->first != "") - context.footnote (i->second); + for (auto& change : projectChanges) + if (change.first != "") + context.footnote (change.second); feedback_affected (count == 1 ? STRING_CMD_ANNO_1 : STRING_CMD_ANNO_N, count); return rc; diff -Nru task-2.4.4+dfsg/src/commands/CmdAppend.cpp task-2.5.0+dfsg/src/commands/CmdAppend.cpp --- task-2.4.4+dfsg/src/commands/CmdAppend.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdAppend.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -39,15 +39,21 @@ //////////////////////////////////////////////////////////////////////////////// CmdAppend::CmdAppend () { - _keyword = "append"; - _usage = "task append "; - _description = STRING_CMD_APPEND_USAGE; - _read_only = false; - _displays_id = false; + _keyword = "append"; + _usage = "task append "; + _description = STRING_CMD_APPEND_USAGE; + _read_only = false; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = true; + _accepts_modifications = true; + _accepts_miscellaneous = false; + _category = Command::Category::operation; } //////////////////////////////////////////////////////////////////////////////// -int CmdAppend::execute (std::string& output) +int CmdAppend::execute (std::string&) { int rc = 0; int count = 0; @@ -67,46 +73,44 @@ // Accumulated project change notifications. std::map projectChanges; - std::vector ::iterator task; - for (task = filtered.begin (); task != filtered.end (); ++task) + for (auto& task : filtered) { - Task before (*task); + Task before (task); // Append to the specified task. std::string question = format (STRING_CMD_APPEND_CONFIRM, - task->id, - task->get ("description")); + task.id, + task.get ("description")); - task->modify (Task::modAppend, true); + task.modify (Task::modAppend, true); - if (permission (*task, taskDifferences (before, *task) + question, filtered.size ())) + if (permission (taskDifferences (before, task) + question, filtered.size ())) { - context.tdb2.modify (*task); + context.tdb2.modify (task); ++count; - feedback_affected (STRING_CMD_APPEND_TASK, *task); + feedback_affected (STRING_CMD_APPEND_TASK, task); if (context.verbose ("project")) - projectChanges[task->get ("project")] = onProjectChange (*task, false); + projectChanges[task.get ("project")] = onProjectChange (task, false); // Append to siblings. - if (task->has ("parent")) + if (task.has ("parent")) { if ((context.config.get ("recurrence.confirmation") == "prompt" && confirm (STRING_CMD_APPEND_CONFIRM_R)) || context.config.getBoolean ("recurrence.confirmation")) { - std::vector siblings = context.tdb2.siblings (*task); - std::vector ::iterator sibling; - for (sibling = siblings.begin (); sibling != siblings.end (); ++sibling) + std::vector siblings = context.tdb2.siblings (task); + for (auto& sibling : siblings) { - sibling->modify (Task::modAppend, true); - context.tdb2.modify (*sibling); + sibling.modify (Task::modAppend, true); + context.tdb2.modify (sibling); ++count; - feedback_affected (STRING_CMD_APPEND_TASK_R, *sibling); + feedback_affected (STRING_CMD_APPEND_TASK_R, sibling); } // Append to the parent Task parent; - context.tdb2.get (task->get ("parent"), parent); + context.tdb2.get (task.get ("parent"), parent); parent.modify (Task::modAppend, true); context.tdb2.modify (parent); } @@ -122,10 +126,9 @@ } // Now list the project changes. - std::map ::iterator i; - for (i = projectChanges.begin (); i != projectChanges.end (); ++i) - if (i->first != "") - context.footnote (i->second); + for (auto& change : projectChanges) + if (change.first != "") + context.footnote (change.second); feedback_affected (count == 1 ? STRING_CMD_APPEND_1 : STRING_CMD_APPEND_N, count); return rc; diff -Nru task-2.4.4+dfsg/src/commands/CmdAttributes.cpp task-2.5.0+dfsg/src/commands/CmdAttributes.cpp --- task-2.4.4+dfsg/src/commands/CmdAttributes.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdAttributes.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -38,26 +38,29 @@ //////////////////////////////////////////////////////////////////////////////// CmdZshAttributes::CmdZshAttributes () { - _keyword = "_zshattributes"; - _usage = "task _zshattributes"; - _description = STRING_CMD_ZSHATTS_USAGE; - _read_only = true; - _displays_id = false; + _keyword = "_zshattributes"; + _usage = "task _zshattributes"; + _description = STRING_CMD_ZSHATTS_USAGE; + _read_only = true; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = false; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::internal; } //////////////////////////////////////////////////////////////////////////////// int CmdZshAttributes::execute (std::string& output) { - // Get a list of all columns. + // Get a list of all columns, sort them. std::vector columns = context.getColumns (); - - // Sort alphabetically. std::sort (columns.begin (), columns.end ()); std::stringstream out; - std::vector ::iterator c; - for (c = columns.begin (); c != columns.end (); ++c) - out << *c << ":" << *c << "\n"; + for (auto& col : columns) + out << col << ":" << col << "\n"; output = out.str (); return 0; diff -Nru task-2.4.4+dfsg/src/commands/CmdBurndown.cpp task-2.5.0+dfsg/src/commands/CmdBurndown.cpp --- task-2.4.4+dfsg/src/commands/CmdBurndown.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdBurndown.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -32,8 +32,7 @@ #include #include #include -#include -#include +#include #include #include #include @@ -152,10 +151,10 @@ private: void generateBars (); void optimizeGrid (); - Date quantize (const Date&); + ISO8601d quantize (const ISO8601d&); - Date increment (const Date&); - Date decrement (const Date&); + ISO8601d increment (const ISO8601d&); + ISO8601d decrement (const ISO8601d&); void maxima (); void yLabels (std::vector &); void calculateRates (std::vector &); @@ -173,7 +172,7 @@ int _estimated_bars; // Estimated bar count int _actual_bars; // Calculated bar count std::map _bars; // Epoch-indexed set of bars - Date _earliest; // Date of earliest estimated bar + ISO8601d _earliest; // Date of earliest estimated bar int _carryover_done; // Number of 'done' tasks prior to chart range char _period; // D, W, M std::string _title; // Additional description @@ -209,7 +208,7 @@ _fix_rate = 0.0; // Set the title. - std::vector words = context.cli.getWords (); + std::vector words = context.cli2.getWords (); std::string filter; join (filter, " ", words); _title = "(" + filter + ")"; @@ -226,14 +225,13 @@ generateBars (); // Not quantized, so that "while (xxx < now)" is inclusive. - Date now; + ISO8601d now; time_t epoch; - std::vector ::iterator task; - for (task = tasks.begin (); task != tasks.end (); ++task) + for (auto& task : tasks) { // The entry date is when the counting starts. - Date from = quantize (Date (task->get_date ("entry"))); + ISO8601d from = quantize (ISO8601d (task.get_date ("entry"))); epoch = from.toEpoch (); if (_bars.find (epoch) != _bars.end ()) @@ -241,24 +239,26 @@ // e--> e--s--> // ppp> pppsss> - Task::status status = task->getStatus (); + Task::status status = task.getStatus (); if (status == Task::pending || status == Task::waiting) { - if (task->has ("start")) + if (task.has ("start")) { - Date start = quantize (Date (task->get_date ("start"))); + ISO8601d start = quantize (ISO8601d (task.get_date ("start"))); while (from < start) { epoch = from.toEpoch (); - if (_bars.find (epoch) != _bars.end ()) ++_bars[epoch]._pending; + if (_bars.find (epoch) != _bars.end ()) + ++_bars[epoch]._pending; from = increment (from); } while (from < now) { epoch = from.toEpoch (); - if (_bars.find (epoch) != _bars.end ()) ++_bars[epoch]._started; + if (_bars.find (epoch) != _bars.end ()) + ++_bars[epoch]._started; from = increment (from); } } @@ -267,7 +267,8 @@ while (from < now) { epoch = from.toEpoch (); - if (_bars.find (epoch) != _bars.end ()) ++_bars[epoch]._pending; + if (_bars.find (epoch) != _bars.end ()) + ++_bars[epoch]._pending; from = increment (from); } } @@ -278,7 +279,7 @@ else if (status == Task::completed) { // Truncate history so it starts at 'earliest' for completed tasks. - Date end = quantize (Date (task->get_date ("end"))); + ISO8601d end = quantize (ISO8601d (task.get_date ("end"))); epoch = end.toEpoch (); if (_bars.find (epoch) != _bars.end ()) @@ -292,44 +293,49 @@ continue; } - if (task->has ("start")) + if (task.has ("start")) { - Date start = quantize (Date (task->get_date ("start"))); + ISO8601d start = quantize (ISO8601d (task.get_date ("start"))); while (from < start) { epoch = from.toEpoch (); - if (_bars.find (epoch) != _bars.end ()) ++_bars[epoch]._pending; + if (_bars.find (epoch) != _bars.end ()) + ++_bars[epoch]._pending; from = increment (from); } while (from < end) { epoch = from.toEpoch (); - if (_bars.find (epoch) != _bars.end ()) ++_bars[epoch]._started; + if (_bars.find (epoch) != _bars.end ()) + ++_bars[epoch]._started; from = increment (from); } while (from < now) { epoch = from.toEpoch (); - if (_bars.find (epoch) != _bars.end ()) ++_bars[epoch]._done; + if (_bars.find (epoch) != _bars.end ()) + ++_bars[epoch]._done; from = increment (from); } } else { - Date end = quantize (Date (task->get_date ("end"))); + ISO8601d end = quantize (ISO8601d (task.get_date ("end"))); while (from < end) { epoch = from.toEpoch (); - if (_bars.find (epoch) != _bars.end ()) ++_bars[epoch]._pending; + if (_bars.find (epoch) != _bars.end ()) + ++_bars[epoch]._pending; from = increment (from); } while (from < now) { epoch = from.toEpoch (); - if (_bars.find (epoch) != _bars.end ()) ++_bars[epoch]._done; + if (_bars.find (epoch) != _bars.end ()) + ++_bars[epoch]._done; from = increment (from); } } @@ -340,7 +346,7 @@ else if (status == Task::deleted) { // Skip old deleted tasks. - Date end = quantize (Date (task->get_date ("end"))); + ISO8601d end = quantize (ISO8601d (task.get_date ("end"))); epoch = end.toEpoch (); if (_bars.find (epoch) != _bars.end ()) ++_bars[epoch]._removed; @@ -348,30 +354,33 @@ if (end < _earliest) continue; - if (task->has ("start")) + if (task.has ("start")) { - Date start = quantize (Date (task->get_date ("start"))); + ISO8601d start = quantize (ISO8601d (task.get_date ("start"))); while (from < start) { epoch = from.toEpoch (); - if (_bars.find (epoch) != _bars.end ()) ++_bars[epoch]._pending; + if (_bars.find (epoch) != _bars.end ()) + ++_bars[epoch]._pending; from = increment (from); } while (from < end) { epoch = from.toEpoch (); - if (_bars.find (epoch) != _bars.end ()) ++_bars[epoch]._started; + if (_bars.find (epoch) != _bars.end ()) + ++_bars[epoch]._started; from = increment (from); } } else { - Date end = quantize (Date (task->get_date ("end"))); + ISO8601d end = quantize (ISO8601d (task.get_date ("end"))); while (from < end) { epoch = from.toEpoch (); - if (_bars.find (epoch) != _bars.end ()) ++_bars[epoch]._pending; + if (_bars.find (epoch) != _bars.end ()) + ++_bars[epoch]._pending; from = increment (from); } } @@ -409,6 +418,12 @@ return std::string (STRING_CMD_BURN_TOO_SMALL) + "\n"; } + else if (_graph_height > 1000 || // each line is a string allloc + _graph_width > 1000) + { + return std::string (STRING_CMD_BURN_TOO_LARGE) + "\n"; + } + if (_max_value == 0) context.footnote (STRING_FEEDBACK_NO_MATCH); @@ -474,16 +489,14 @@ // Draw x-axis labels. std::vector bars_in_sequence; - std::map ::iterator it; - for (it = _bars.begin (); it != _bars.end (); ++it) - bars_in_sequence.push_back (it->first); + for (auto& bar : _bars) + bars_in_sequence.push_back (bar.first); std::sort (bars_in_sequence.begin (), bars_in_sequence.end ()); - std::vector ::iterator seq; std::string _major_label; - for (seq = bars_in_sequence.begin (); seq != bars_in_sequence.end (); ++seq) + for (auto& seq : bars_in_sequence) { - Bar bar = _bars[*seq]; + Bar bar = _bars[seq]; // If it fits within the allowed space. if (bar._offset < _actual_bars) @@ -498,15 +511,15 @@ } // Draw bars. - for (seq = bars_in_sequence.begin (); seq != bars_in_sequence.end (); ++seq) + for (auto& seq : bars_in_sequence) { - Bar bar = _bars[*seq]; + Bar bar = _bars[seq]; // If it fits within the allowed space. if (bar._offset < _actual_bars) { - int pending = ( bar._pending * _graph_height) / _labels[2]; - int started = ((bar._pending + bar._started) * _graph_height) / _labels[2]; + int pending = ( bar._pending * _graph_height) / _labels[2]; + int started = ((bar._pending + bar._started) * _graph_height) / _labels[2]; int done = ((bar._pending + bar._started + bar._done + _carryover_done) * _graph_height) / _labels[2]; for (int b = 0; b < pending; ++b) @@ -585,7 +598,7 @@ std::string::size_type ws; while ((ws = _grid.find (" \n")) != std::string::npos) { - std::string::size_type non_ws = ws; + auto non_ws = ws; while (_grid[non_ws] == ' ') --non_ws; @@ -594,7 +607,7 @@ } //////////////////////////////////////////////////////////////////////////////// -Date Chart::quantize (const Date& input) +ISO8601d Chart::quantize (const ISO8601d& input) { if (_period == 'D') return input.startOfDay (); if (_period == 'W') return input.startOfWeek (); @@ -604,7 +617,7 @@ } //////////////////////////////////////////////////////////////////////////////// -Date Chart::increment (const Date& input) +ISO8601d Chart::increment (const ISO8601d& input) { // Move to the next period. int d = input.day (); @@ -616,7 +629,7 @@ switch (_period) { case 'D': - if (++d > Date::daysInMonth (m, y)) + if (++d > ISO8601d::daysInMonth (m, y)) { d = 1; @@ -630,7 +643,7 @@ case 'W': d += 7; - days = Date::daysInMonth (m, y); + days = ISO8601d::daysInMonth (m, y); if (d > days) { d -= days; @@ -653,11 +666,11 @@ break; } - return Date (m, d, y, 0, 0, 0); + return ISO8601d (m, d, y, 0, 0, 0); } //////////////////////////////////////////////////////////////////////////////// -Date Chart::decrement (const Date& input) +ISO8601d Chart::decrement (const ISO8601d& input) { // Move to the previous period. int d = input.day (); @@ -675,7 +688,7 @@ --y; } - d = Date::daysInMonth (m, y); + d = ISO8601d::daysInMonth (m, y); } break; @@ -689,7 +702,7 @@ y--; } - d += Date::daysInMonth (m, y); + d += ISO8601d::daysInMonth (m, y); } break; @@ -703,7 +716,7 @@ break; } - return Date (m, d, y, 0, 0, 0); + return ISO8601d (m, d, y, 0, 0, 0); } //////////////////////////////////////////////////////////////////////////////// @@ -713,12 +726,12 @@ Bar bar; // Determine the last bar date. - Date cursor; + ISO8601d cursor; switch (_period) { - case 'D': cursor = Date ().startOfDay (); break; - case 'W': cursor = Date ().startOfWeek (); break; - case 'M': cursor = Date ().startOfMonth (); break; + case 'D': cursor = ISO8601d ().startOfDay (); break; + case 'W': cursor = ISO8601d ().startOfWeek (); break; + case 'M': cursor = ISO8601d ().startOfMonth (); break; } // Iterate and determine all the other bar dates. @@ -730,7 +743,7 @@ { case 'D': // month/day { - std::string month = Date::monthName (cursor.month ()); + std::string month = ISO8601d::monthName (cursor.month ()); bar._major_label = month.substr (0, 3); sprintf (str, "%02d", cursor.day ()); @@ -772,13 +785,12 @@ _max_value = 0; _max_label = 1; - std::map ::iterator it; - for (it = _bars.begin (); it != _bars.end (); it++) + for (auto& bar : _bars) { // Determine _max_label. - int total = it->second._pending + - it->second._started + - it->second._done + + int total = bar.second._pending + + bar.second._started + + bar.second._done + _carryover_done; // Determine _max_value. @@ -921,8 +933,8 @@ int current_pending = _bars[sequence.back ()]._pending; int remaining_days = (int) (current_pending / (_fix_rate - _find_rate)); - Date now; - Duration delta (remaining_days * 86400); + ISO8601d now; + ISO8601p delta (remaining_days * 86400); now += delta; // Prefer dateformat.report over dateformat. @@ -1001,11 +1013,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdBurndownMonthly::CmdBurndownMonthly () { - _keyword = "burndown.monthly"; - _usage = "task burndown.monthly"; - _description = STRING_CMD_BURN_USAGE_M; - _read_only = true; - _displays_id = false; + _keyword = "burndown.monthly"; + _usage = "task burndown.monthly"; + _description = STRING_CMD_BURN_USAGE_M; + _read_only = true; + _displays_id = false; + _needs_gc = true; + _uses_context = true; + _accepts_filter = true; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::graphs; } //////////////////////////////////////////////////////////////////////////////// @@ -1029,11 +1047,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdBurndownWeekly::CmdBurndownWeekly () { - _keyword = "burndown.weekly"; - _usage = "task burndown.weekly"; - _description = STRING_CMD_BURN_USAGE_W; - _read_only = true; - _displays_id = false; + _keyword = "burndown.weekly"; + _usage = "task burndown.weekly"; + _description = STRING_CMD_BURN_USAGE_W; + _read_only = true; + _displays_id = false; + _needs_gc = true; + _uses_context = true; + _accepts_filter = true; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::graphs; } //////////////////////////////////////////////////////////////////////////////// @@ -1057,11 +1081,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdBurndownDaily::CmdBurndownDaily () { - _keyword = "burndown.daily"; - _usage = "task burndown.daily"; - _description = STRING_CMD_BURN_USAGE_D; - _read_only = true; - _displays_id = false; + _keyword = "burndown.daily"; + _usage = "task burndown.daily"; + _description = STRING_CMD_BURN_USAGE_D; + _read_only = true; + _displays_id = false; + _needs_gc = true; + _uses_context = true; + _accepts_filter = true; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::graphs; } //////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/commands/CmdCalc.cpp task-2.5.0+dfsg/src/commands/CmdCalc.cpp --- task-2.4.4+dfsg/src/commands/CmdCalc.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdCalc.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -37,11 +37,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdCalc::CmdCalc () { - _keyword = "calc"; - _usage = "task calc "; - _description = STRING_CMD_CALC_USAGE; - _read_only = true; - _displays_id = false; + _keyword = "calc"; + _usage = "task calc "; + _description = STRING_CMD_CALC_USAGE; + _read_only = true; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = false; + _accepts_modifications = false; + _accepts_miscellaneous = true; + _category = Command::Category::misc; } //////////////////////////////////////////////////////////////////////////////// @@ -58,15 +64,12 @@ Eval e; e.addSource (domSource); e.addSource (namedDates); - e.ambiguity (false); // TODO Configurable? e.debug (context.config.getBoolean ("debug")); // Compile all the args into one expression. std::string expression; - std::vector words = context.cli.getWords (); - std::vector ::iterator word; - for (word = words.begin (); word != words.end (); ++word) - expression += *word + " "; + for (auto& word : context.cli2.getWords ()) + expression += word + " "; // Evaluate according to preference. Variant result; diff -Nru task-2.4.4+dfsg/src/commands/CmdCalendar.cpp task-2.5.0+dfsg/src/commands/CmdCalendar.cpp --- task-2.4.4+dfsg/src/commands/CmdCalendar.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdCalendar.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -42,11 +42,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdCalendar::CmdCalendar () { - _keyword = "calendar"; - _usage = "task calendar [due| |] [y]"; - _description = STRING_CMD_CAL_USAGE; - _read_only = true; - _displays_id = true; + _keyword = "calendar"; + _usage = "task calendar [due| |] [y]"; + _description = STRING_CMD_CAL_USAGE; + _read_only = true; + _displays_id = true; + _needs_gc = true; + _uses_context = true; + _accepts_filter = false; + _accepts_modifications = false; + _accepts_miscellaneous = true; + _category = Command::Category::graphs; } //////////////////////////////////////////////////////////////////////////////// @@ -66,9 +72,9 @@ // Load the pending tasks. handleRecurrence (); - std::vector tasks = context.tdb2.pending.get_tasks (); + auto tasks = context.tdb2.pending.get_tasks (); - Date today; + ISO8601d today; bool getpendingdate = false; int monthsToDisplay = 1; int mFrom = today.month (); @@ -92,7 +98,7 @@ // Set up a vector of months, for autoComplete. std::vector monthNames; for (int i = 1; i <= 12; ++i) - monthNames.push_back (lowerCase (Date::monthName (i))); + monthNames.push_back (lowerCase (ISO8601d::monthName (i))); // For autoComplete results. std::vector matches; @@ -102,45 +108,44 @@ int argYear = 0; bool argWholeYear = false; - std::vector words = context.cli.getWords (); + std::vector words = context.cli2.getWords (); - std::vector ::iterator arg; - for (arg = words.begin (); arg != words.end (); ++arg) + for (auto& arg : words) { // Some version of "calendar". - if (autoComplete (lowerCase (*arg), commandNames, matches, context.config.getInteger ("abbreviation.minimum")) == 1) + if (autoComplete (lowerCase (arg), commandNames, matches, context.config.getInteger ("abbreviation.minimum")) == 1) continue; // "due". - else if (autoComplete (lowerCase (*arg), keywordNames, matches, context.config.getInteger ("abbreviation.minimum")) == 1) + else if (autoComplete (lowerCase (arg), keywordNames, matches, context.config.getInteger ("abbreviation.minimum")) == 1) getpendingdate = true; // "y". - else if (lowerCase (*arg) == "y") + else if (lowerCase (arg) == "y") argWholeYear = true; // YYYY. - else if (Lexer::isAllDigits (*arg) && arg->length () == 4) - argYear = strtol (arg->c_str (), NULL, 10); + else if (Lexer::isAllDigits (arg) && arg.length () == 4) + argYear = strtol (arg.c_str (), NULL, 10); // MM. - else if (Lexer::isAllDigits (*arg) && arg->length () <= 2) + else if (Lexer::isAllDigits (arg) && arg.length () <= 2) { - argMonth = strtol (arg->c_str (), NULL, 10); + argMonth = strtol (arg.c_str (), NULL, 10); if (argMonth < 1 || argMonth > 12) - throw format (STRING_CMD_CAL_BAD_MONTH, *arg); + throw format (STRING_CMD_CAL_BAD_MONTH, arg); } // "January" etc. - else if (autoComplete (lowerCase (*arg), monthNames, matches, context.config.getInteger ("abbreviation.minimum")) == 1) + else if (autoComplete (lowerCase (arg), monthNames, matches, context.config.getInteger ("abbreviation.minimum")) == 1) { - argMonth = Date::monthOfYear (matches[0]); + argMonth = ISO8601d::monthOfYear (matches[0]); if (argMonth == -1) - throw format (STRING_CMD_CAL_BAD_MONTH, *arg); + throw format (STRING_CMD_CAL_BAD_MONTH, arg); } else - throw format (STRING_CMD_CAL_BAD_ARG, *arg); + throw format (STRING_CMD_CAL_BAD_ARG, arg); } // Supported combinations: @@ -171,17 +176,16 @@ if (getpendingdate == true) { // Find the oldest pending due date. - Date oldest (12, 31, 2037); - std::vector ::iterator task; - for (task = tasks.begin (); task != tasks.end (); ++task) + ISO8601d oldest (12, 31, 2037); + for (auto& task : tasks) { - if (task->getStatus () == Task::pending) + if (task.getStatus () == Task::pending) { - if (task->has ("due") && - !task->hasTag ("nocal")) + if (task.has ("due") && + !task.hasTag ("nocal")) { ++countDueDates; - Date d (task->get ("due")); + ISO8601d d (task.get ("due")); if (d < oldest) oldest = d; } } @@ -230,7 +234,7 @@ // Print month headers (cheating on the width settings, yes) for (int i = 0 ; i < monthsPerLine ; i++) { - std::string month = Date::monthName (nextM); + std::string month = ISO8601d::monthName (nextM); // 12345678901234567890123456 = 26 chars wide // ^^ = center @@ -313,7 +317,7 @@ details_mFrom = 12; --details_yFrom; } - int details_dFrom = Date::daysInMonth (details_mFrom, details_yFrom); + int details_dFrom = ISO8601d::daysInMonth (details_mFrom, details_yFrom); ++mTo; if (mTo == 13) @@ -322,10 +326,10 @@ ++yTo; } - Date date_after (details_mFrom, details_dFrom, details_yFrom); + ISO8601d date_after (details_mFrom, details_dFrom, details_yFrom); std::string after = date_after.toString (context.config.get ("dateformat")); - Date date_before (mTo, 1, yTo); + ISO8601d date_before (mTo, 1, yTo); std::string before = date_before.toString (context.config.get ("dateformat")); // Table with due date information @@ -336,9 +340,12 @@ if (context.commands.find (report) == context.commands.end ()) throw std::string (STRING_ERROR_DETAILS); + // TODO Fix this: cal --> task + // calendar --> taskendar + // If the executable was "cal" or equivalent, replace it with "task". - std::string executable = context.cli._args[0].attribute ("raw"); - std::string::size_type cal = executable.find ("cal"); + std::string executable = context.cli2._original_args[0].attribute ("raw"); + auto cal = executable.find ("cal"); if (cal != std::string::npos) executable = executable.substr (0, cal) + PACKAGE; @@ -365,20 +372,17 @@ holTable.add (Column::factory ("string", STRING_CMD_CAL_LABEL_HOL)); holTable.colorHeader (color_label); - Config::const_iterator it; std::map > hm; // we need to store multiple holidays per day - for (it = context.config.begin (); it != context.config.end (); ++it) - if (it->first.substr (0, 8) == "holiday.") - if (it->first.substr (it->first.size () - 4) == "name") + for (auto& it : context.config) + if (it.first.substr (0, 8) == "holiday.") + if (it.first.substr (it.first.size () - 4) == "name") { - std::string holName = context.config.get ("holiday." + it->first.substr (8, it->first.size () - 13) + ".name"); - std::string holDate = context.config.get ("holiday." + it->first.substr (8, it->first.size () - 13) + ".date"); - Date hDate (holDate.c_str (), context.config.get ("dateformat.holiday")); + std::string holName = context.config.get ("holiday." + it.first.substr (8, it.first.size () - 13) + ".name"); + std::string holDate = context.config.get ("holiday." + it.first.substr (8, it.first.size () - 13) + ".date"); + ISO8601d hDate (holDate.c_str (), context.config.get ("dateformat.holiday")); if (date_after < hDate && hDate < date_before) - { hm[hDate.toEpoch()].push_back(holName); - } } std::string format = context.config.get ("report." + @@ -389,11 +393,10 @@ if (format == "") format = context.config.get ("dateformat"); - std::map >::iterator hm_it; - for (hm_it = hm.begin(); hm_it != hm.end(); ++hm_it) + for (auto& hm_it : hm) { - std::vector v = hm_it->second; - Date hDate (hm_it->first); + std::vector v = hm_it.second; + ISO8601d hDate (hm_it.first); std::string d = hDate.toString (format); for (size_t i = 0; i < v.size(); i++) { @@ -417,12 +420,12 @@ std::string CmdCalendar::renderMonths ( int firstMonth, int firstYear, - const Date& today, + const ISO8601d& today, std::vector & all, int monthsPerLine) { // What day of the week does the user consider the first? - int weekStart = Date::dayOfWeek (context.config.get ("weekstart")); + int weekStart = ISO8601d::dayOfWeek (context.config.get ("weekstart")); if (weekStart != 0 && weekStart != 1) throw std::string (STRING_CMD_CAL_SUN_MON); @@ -437,24 +440,24 @@ if (weekStart == 1) { view.add (Column::factory ("string.right", " ")); - view.add (Column::factory ("string.right", utf8_substr (Date::dayName (1), 0, 2))); - view.add (Column::factory ("string.right", utf8_substr (Date::dayName (2), 0, 2))); - view.add (Column::factory ("string.right", utf8_substr (Date::dayName (3), 0, 2))); - view.add (Column::factory ("string.right", utf8_substr (Date::dayName (4), 0, 2))); - view.add (Column::factory ("string.right", utf8_substr (Date::dayName (5), 0, 2))); - view.add (Column::factory ("string.right", utf8_substr (Date::dayName (6), 0, 2))); - view.add (Column::factory ("string.right", utf8_substr (Date::dayName (0), 0, 2))); + view.add (Column::factory ("string.right", utf8_substr (ISO8601d::dayName (1), 0, 2))); + view.add (Column::factory ("string.right", utf8_substr (ISO8601d::dayName (2), 0, 2))); + view.add (Column::factory ("string.right", utf8_substr (ISO8601d::dayName (3), 0, 2))); + view.add (Column::factory ("string.right", utf8_substr (ISO8601d::dayName (4), 0, 2))); + view.add (Column::factory ("string.right", utf8_substr (ISO8601d::dayName (5), 0, 2))); + view.add (Column::factory ("string.right", utf8_substr (ISO8601d::dayName (6), 0, 2))); + view.add (Column::factory ("string.right", utf8_substr (ISO8601d::dayName (0), 0, 2))); } else { view.add (Column::factory ("string.right", " ")); - view.add (Column::factory ("string.right", utf8_substr (Date::dayName (0), 0, 2))); - view.add (Column::factory ("string.right", utf8_substr (Date::dayName (1), 0, 2))); - view.add (Column::factory ("string.right", utf8_substr (Date::dayName (2), 0, 2))); - view.add (Column::factory ("string.right", utf8_substr (Date::dayName (3), 0, 2))); - view.add (Column::factory ("string.right", utf8_substr (Date::dayName (4), 0, 2))); - view.add (Column::factory ("string.right", utf8_substr (Date::dayName (5), 0, 2))); - view.add (Column::factory ("string.right", utf8_substr (Date::dayName (6), 0, 2))); + view.add (Column::factory ("string.right", utf8_substr (ISO8601d::dayName (0), 0, 2))); + view.add (Column::factory ("string.right", utf8_substr (ISO8601d::dayName (1), 0, 2))); + view.add (Column::factory ("string.right", utf8_substr (ISO8601d::dayName (2), 0, 2))); + view.add (Column::factory ("string.right", utf8_substr (ISO8601d::dayName (3), 0, 2))); + view.add (Column::factory ("string.right", utf8_substr (ISO8601d::dayName (4), 0, 2))); + view.add (Column::factory ("string.right", utf8_substr (ISO8601d::dayName (5), 0, 2))); + view.add (Column::factory ("string.right", utf8_substr (ISO8601d::dayName (6), 0, 2))); } } @@ -484,7 +487,7 @@ years.push_back (++thisYear); } months.push_back (thisMonth); - daysInMonth.push_back (Date::daysInMonth (thisMonth++, thisYear)); + daysInMonth.push_back (ISO8601d::daysInMonth (thisMonth++, thisYear)); } int row = 0; @@ -507,7 +510,7 @@ // Loop through days in month and add to table. for (int d = 1; d <= daysInMonth[mpl]; ++d) { - Date temp (months[mpl], d, years[mpl]); + ISO8601d temp (months[mpl], d, years[mpl]); int dow = temp.dayOfWeek (); int woy = temp.weekOfYear (weekStart); @@ -535,13 +538,12 @@ // colorize holidays if (context.config.get ("calendar.holidays") != "none") { - Config::const_iterator hol; - for (hol = context.config.begin (); hol != context.config.end (); ++hol) - if (hol->first.substr (0, 8) == "holiday.") - if (hol->first.substr (hol->first.size () - 4) == "date") + for (auto& hol : context.config) + if (hol.first.substr (0, 8) == "holiday.") + if (hol.first.substr (hol.first.size () - 4) == "date") { - std::string value = hol->second; - Date holDate (value.c_str (), context.config.get ("dateformat.holiday")); + std::string value = hol.second; + ISO8601d holDate (value.c_str (), context.config.get ("dateformat.holiday")); if (holDate.day () == d && holDate.month () == months[mpl] && holDate.year () == years[mpl]) @@ -559,21 +561,20 @@ if (context.config.get ("calendar.details") != "none") { context.config.set ("due", 0); - std::vector ::iterator task; - for (task = all.begin (); task != all.end (); ++task) + for (auto& task : all) { - if (task->getStatus () == Task::pending && - !task->hasTag ("nocal") && - task->has ("due")) + if (task.getStatus () == Task::pending && + !task.hasTag ("nocal") && + task.has ("due")) { - std::string due = task->get ("due"); - Date duedmy (strtol (due.c_str(), NULL, 10)); + std::string due = task.get ("due"); + ISO8601d duedmy (strtol (due.c_str(), NULL, 10)); if (duedmy.day () == d && duedmy.month () == months[mpl] && duedmy.year () == years[mpl]) { - switch (task->getDateState ("due")) + switch (task.getDateState ("due")) { case Task::dateNotDue: break; diff -Nru task-2.4.4+dfsg/src/commands/CmdCalendar.h task-2.5.0+dfsg/src/commands/CmdCalendar.h --- task-2.4.4+dfsg/src/commands/CmdCalendar.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdCalendar.h 2015-10-21 21:18:15.000000000 +0000 @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include @@ -40,7 +40,7 @@ int execute (std::string&); private: - std::string renderMonths (int, int, const Date&, std::vector &, int); + std::string renderMonths (int, int, const ISO8601d&, std::vector &, int); }; #endif diff -Nru task-2.4.4+dfsg/src/commands/CmdColor.cpp task-2.5.0+dfsg/src/commands/CmdColor.cpp --- task-2.4.4+dfsg/src/commands/CmdColor.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdColor.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -39,11 +39,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdColor::CmdColor () { - _keyword = "colors"; - _usage = "task colors [sample | legend]"; - _description = STRING_CMD_COLOR_USAGE; - _read_only = true; - _displays_id = false; + _keyword = "colors"; + _usage = "task colors [sample | legend]"; + _description = STRING_CMD_COLOR_USAGE; + _read_only = true; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = false; + _accepts_modifications = false; + _accepts_miscellaneous = true; + _category = Command::Category::misc; } //////////////////////////////////////////////////////////////////////////////// @@ -51,13 +57,11 @@ { int rc = 0; -#ifdef FEATURE_COLOR // Get the non-attribute, non-fancy command line arguments. bool legend = false; - std::vector words = context.cli.getWords (); - std::vector ::iterator word; - for (word = words.begin (); word != words.end (); ++word) - if (closeEnough ("legend", *word)) + std::vector words = context.cli2.getWords (); + for (auto& word : words) + if (closeEnough ("legend", word)) legend = true; std::stringstream out; @@ -74,19 +78,18 @@ view.add (Column::factory ("string", STRING_CMD_COLOR_COLOR)); view.add (Column::factory ("string", STRING_CMD_COLOR_DEFINITION)); - Config::const_iterator item; - for (item = context.config.begin (); item != context.config.end (); ++item) + for (auto& item : context.config) { // Skip items with 'color' in their name, that are not referring to // actual colors. - if (item->first != "_forcecolor" && - item->first != "color" && - item->first.find ("color") == 0) + if (item.first != "_forcecolor" && + item.first != "color" && + item.first.find ("color") == 0) { - Color color (context.config.get (item->first)); + Color color (context.config.get (item.first)); int row = view.addRow (); - view.set (row, 0, item->first, color); - view.set (row, 1, item->second, color); + view.set (row, 0, item.first, color); + view.set (row, 1, item.second, color); } } @@ -106,7 +109,7 @@ Color six ("red on color173"); std::string swatch; - for (word = words.begin (); word != words.end (); ++word) + for (auto word = words.begin (); word != words.end (); ++word) { if (word != words.begin ()) swatch += " "; @@ -259,10 +262,6 @@ } output = out.str (); -#else - output = "Color not supported.\n"; -#endif - return rc; } diff -Nru task-2.4.4+dfsg/src/commands/CmdColumns.cpp task-2.5.0+dfsg/src/commands/CmdColumns.cpp --- task-2.4.4+dfsg/src/commands/CmdColumns.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdColumns.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -39,11 +39,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdColumns::CmdColumns () { - _keyword = "columns"; - _usage = "task columns [substring]"; - _description = STRING_CMD_COLUMNS_USAGE; - _read_only = true; - _displays_id = false; + _keyword = "columns"; + _usage = "task columns [substring]"; + _description = STRING_CMD_COLUMNS_USAGE; + _read_only = true; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = false; + _accepts_modifications = false; + _accepts_miscellaneous = true; + _category = Command::Category::config; } //////////////////////////////////////////////////////////////////////////////// @@ -51,15 +57,14 @@ { // Obtain the arguments from the description. That way, things like '--' // have already been handled. - std::vector words = context.cli.getWords (); + std::vector words = context.cli2.getWords (); if (words.size () > 1) throw std::string (STRING_CMD_COLUMNS_ARGS); // Include all columns in the table. std::vector names; - std::map ::const_iterator col; - for (col = context.columns.begin (); col != context.columns.end (); ++col) - names.push_back (col->first); + for (auto& col : context.columns) + names.push_back (col.first); std::sort (names.begin (), names.end ()); @@ -67,35 +72,48 @@ ViewText formats; formats.width (context.getWidth ()); formats.add (Column::factory ("string", STRING_COLUMN_LABEL_COLUMN)); + formats.add (Column::factory ("string", STRING_COLUMN_LABEL_TYPE)); formats.add (Column::factory ("string", STRING_COLUMN_LABEL_STYLES)); formats.add (Column::factory ("string", STRING_COLUMN_LABEL_EXAMPLES)); - Color label (context.config.get ("color.label")); - formats.colorHeader (label); + if (context.color ()) + { + Color label (context.config.get ("color.label")); + formats.colorHeader (label); - Color alternate (context.config.get ("color.alternate")); - formats.colorOdd (alternate); - formats.intraColorOdd (alternate); + Color alternate (context.config.get ("color.alternate")); + formats.colorOdd (alternate); + formats.intraColorOdd (alternate); + } - std::vector ::iterator name; - for (name = names.begin (); name != names.end (); ++name) + for (auto& name : names) { if (words.size () == 0 || - find (*name, words[0], false) != std::string::npos) + find (name, words[0], false) != std::string::npos) { - const std::vector styles = context.columns[*name]->styles (); - const std::vector examples = context.columns[*name]->examples (); + const std::vector styles = context.columns[name]->styles (); + const std::vector examples = context.columns[name]->examples (); for (unsigned int i = 0; i < styles.size (); ++i) { int row = formats.addRow (); - formats.set (row, 0, i == 0 ? *name : ""); - formats.set (row, 1, styles[i] + (i == 0 ? "*" : "")); - formats.set (row, 2, i < examples.size () ? examples[i] : ""); + formats.set (row, 0, i == 0 ? name : ""); + formats.set (row, 1, i == 0 ? context.columns[name]->type () : ""); + formats.set (row, 2, styles[i] + (i == 0 ? "*" : "")); + formats.set (row, 3, i < examples.size () ? examples[i] : ""); } } } + int row = formats.addRow (); + formats.set (row, 0, ""); + formats.set (row, 1, ""); + formats.set (row, 2, "default*"); + + row = formats.addRow (); + formats.set (row, 0, ""); + formats.set (row, 2, "indicator"); + output = optionalBlankLine () + formats.render () + "\n" @@ -108,11 +126,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdCompletionColumns::CmdCompletionColumns () { - _keyword = "_columns"; - _usage = "task _columns"; - _description = STRING_CMD_COLUMNS_USAGE2; - _read_only = true; - _displays_id = false; + _keyword = "_columns"; + _usage = "task _columns"; + _description = STRING_CMD_COLUMNS_USAGE2; + _read_only = true; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = false; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::internal; } //////////////////////////////////////////////////////////////////////////////// @@ -120,16 +144,14 @@ { // Include all columns. std::vector names; - std::map ::const_iterator col; - for (col = context.columns.begin (); col != context.columns.end (); ++col) - names.push_back (col->first); + for (auto& col : context.columns) + names.push_back (col.first); std::sort (names.begin (), names.end ()); // Render only the column names. - std::vector ::iterator name; - for (name = names.begin (); name != names.end (); ++name) - output += *name + "\n"; + for (auto& name : names) + output += name + "\n"; return 0; } diff -Nru task-2.4.4+dfsg/src/commands/CmdCommands.cpp task-2.5.0+dfsg/src/commands/CmdCommands.cpp --- task-2.4.4+dfsg/src/commands/CmdCommands.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdCommands.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -29,20 +29,115 @@ #include #include #include +#include #include #include +#include +#include #include extern Context context; //////////////////////////////////////////////////////////////////////////////// +CmdCommands::CmdCommands () +{ + _keyword = "commands"; + _usage = "task commands"; + _description = STRING_CMD_COMMANDS_USAGE; + _read_only = true; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = false; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::metadata; +} + +//////////////////////////////////////////////////////////////////////////////// +int CmdCommands::execute (std::string& output) +{ + ViewText view; + view.width (context.getWidth ()); + view.add (Column::factory ("string", STRING_COLUMN_LABEL_COMMAND)); + view.add (Column::factory ("string", STRING_COLUMN_LABEL_CATEGORY)); + view.add (Column::factory ("string.right", STRING_COLUMN_LABEL_RO)); + view.add (Column::factory ("string.right", STRING_COLUMN_LABEL_SHOWS_ID)); + view.add (Column::factory ("string.right", STRING_COLUMN_LABEL_GC)); + view.add (Column::factory ("string.right", STRING_COLUMN_LABEL_CONTEXT)); + view.add (Column::factory ("string.right", STRING_COLUMN_LABEL_FILTER)); + view.add (Column::factory ("string.right", STRING_COLUMN_LABEL_MODS)); + view.add (Column::factory ("string.right", STRING_COLUMN_LABEL_MISC)); + view.add (Column::factory ("string.left", STRING_COLUMN_LABEL_DESC)); + + if (context.color ()) + { + Color label (context.config.get ("color.label")); + view.colorHeader (label); + + Color alternate (context.config.get ("color.alternate")); + view.colorOdd (alternate); + view.intraColorOdd (alternate); + } + + view.leftMargin (context.config.getInteger ("indent.report")); + view.extraPadding (context.config.getInteger ("row.padding")); + view.intraPadding (context.config.getInteger ("column.padding")); + + for (auto& command : context.commands) + { + int row = view.addRow (); + view.set (row, 0, command.first); + view.set (row, 1, Command::categoryNames.at (command.second->category ())); + + if (command.second->read_only ()) + view.set (row, 2, "RO"); + else + view.set (row, 2, "RW"); + + if (command.second->displays_id ()) + view.set (row, 3, "ID"); + + if (command.second->needs_gc ()) + view.set (row, 4, "GC"); + + if (command.second->uses_context ()) + view.set (row, 5, "Ctxt"); + + if (command.second->accepts_filter ()) + view.set (row, 6, "Filt"); + + if (command.second->accepts_modifications ()) + view.set (row, 7, "Mods"); + + if (command.second->accepts_miscellaneous ()) + view.set (row, 8, "Misc"); + + view.set (row, 9, command.second->description ()); + } + + output = optionalBlankLine () + + view.render () + + optionalBlankLine () + + "\n"; + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// CmdCompletionCommands::CmdCompletionCommands () { - _keyword = "_commands"; - _usage = "task _commands"; - _description = STRING_CMD_HCOMMANDS_USAGE; - _read_only = true; - _displays_id = false; + _keyword = "_commands"; + _usage = "task _commands"; + _description = STRING_CMD_HCOMMANDS_USAGE; + _read_only = true; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = false; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::internal; } //////////////////////////////////////////////////////////////////////////////// @@ -51,21 +146,15 @@ // Get a list of all commands. std::vector commands; - std::map ::iterator command; - for (command = context.commands.begin (); - command != context.commands.end (); - ++command) - { - commands.push_back (command->first); - } + for (auto& command : context.commands) + commands.push_back (command.first); // Sort alphabetically. std::sort (commands.begin (), commands.end ()); std::stringstream out; - std::vector ::iterator c; - for (c = commands.begin (); c != commands.end (); ++c) - out << *c << "\n"; + for (auto& c : commands) + out << c << "\n"; output = out.str (); return 0; @@ -74,34 +163,70 @@ //////////////////////////////////////////////////////////////////////////////// CmdZshCommands::CmdZshCommands () { - _keyword = "_zshcommands"; - _usage = "task _zshcommands"; - _description = STRING_CMD_ZSHCOMMANDS_USAGE; - _read_only = true; - _displays_id = false; + _keyword = "_zshcommands"; + _usage = "task _zshcommands"; + _description = STRING_CMD_ZSHCOMMANDS_USAGE; + _read_only = true; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = false; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::internal; +} + +//////////////////////////////////////////////////////////////////////////////// +struct ZshCommand +{ + bool operator< (const struct ZshCommand&) const; + Command::Category _category; + std::string _command; + std::string _description; +}; + +//////////////////////////////////////////////////////////////////////////////// +bool ZshCommand::operator< (const struct ZshCommand& other) const +{ + // Lexicographical comparison. + if (_category != other._category) + return (_category < other._category); + + if (_command != other._command) + return (_command < other._command); + + if (_description != other._description) + return (_description < other._description); + + return false; } //////////////////////////////////////////////////////////////////////////////// int CmdZshCommands::execute (std::string& output) { - // Get a list of all commands. - std::vector commands; + // Get a list of all command descriptions, sorted by category and then + // alphabetically by command name. - std::map ::iterator command; - for (command = context.commands.begin (); - command != context.commands.end (); - ++command) + // Since not all supported compilers support tuples, we use a least common + // denominator alternative: a custom struct type. + + std::vector commands; + for (auto& command : context.commands) { - commands.push_back (command->first); + ZshCommand zshCommand {command.second->category (), + command.first, + command.second->description ()}; + commands.push_back (zshCommand); } - // Sort alphabetically. std::sort (commands.begin (), commands.end ()); + // Emit the commands in order. std::stringstream out; - std::vector ::iterator c; - for (c = commands.begin (); c != commands.end (); ++c) - out << *c << ":" << context.commands[*c]->description () << "\n"; + for (auto& zc : commands) + out << zc._command << ":" + << Command::categoryNames.at (zc._category) << ":" + << zc._description << "\n"; output = out.str (); return 0; diff -Nru task-2.4.4+dfsg/src/commands/CmdCommands.h task-2.5.0+dfsg/src/commands/CmdCommands.h --- task-2.4.4+dfsg/src/commands/CmdCommands.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdCommands.h 2015-10-21 21:18:15.000000000 +0000 @@ -30,6 +30,13 @@ #include #include +class CmdCommands : public Command +{ +public: + CmdCommands (); + int execute (std::string&); +}; + class CmdCompletionCommands : public Command { public: diff -Nru task-2.4.4+dfsg/src/commands/CmdConfig.cpp task-2.5.0+dfsg/src/commands/CmdConfig.cpp --- task-2.4.4+dfsg/src/commands/CmdConfig.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdConfig.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -39,11 +39,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdConfig::CmdConfig () { - _keyword = "config"; - _usage = "task config [name [value | '']]"; - _description = STRING_CMD_CONFIG_USAGE; - _read_only = true; - _displays_id = false; + _keyword = "config"; + _usage = "task config [name [value | '']]"; + _description = STRING_CMD_CONFIG_USAGE; + _read_only = true; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = false; + _accepts_modifications = false; + _accepts_miscellaneous = true; + _category = Command::Category::config; } //////////////////////////////////////////////////////////////////////////////// @@ -56,12 +62,11 @@ bool found = false; bool change = false; - std::vector ::iterator line; - for (line = contents.begin (); line != contents.end (); ++line) + for (auto& line : contents) { // 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 + "="); + auto comment = line.find ("#"); + auto pos = line.find (name + "="); if (pos != std::string::npos && (comment == std::string::npos || @@ -72,9 +77,9 @@ 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); + line = name + "=" + json::encode (value) + " " + line.substr (comment); else - *line = name + "=" + json::encode (value); + line = name + "=" + json::encode (value); change = true; } @@ -106,14 +111,13 @@ bool found = false; bool change = false; - std::vector ::iterator line; - for (line = contents.begin (); line != contents.end (); ) + for (auto 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 + "="); + auto comment = line->find ("#"); + auto pos = line->find (name + "="); if (pos != std::string::npos && (comment == std::string::npos || @@ -154,7 +158,7 @@ std::stringstream out; // Get the non-attribute, non-fancy command line arguments. - std::vector words = context.cli.getWords (); + std::vector words = context.cli2.getWords (); // Support: // task config name value # set name to value @@ -229,11 +233,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdCompletionConfig::CmdCompletionConfig () { - _keyword = "_config"; - _usage = "task _config"; - _description = STRING_CMD_HCONFIG_USAGE; - _read_only = true; - _displays_id = false; + _keyword = "_config"; + _usage = "task _config"; + _description = STRING_CMD_HCONFIG_USAGE; + _read_only = true; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = false; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::internal; } //////////////////////////////////////////////////////////////////////////////// @@ -243,9 +253,8 @@ context.config.all (configs); std::sort (configs.begin (), configs.end ()); - std::vector ::iterator config; - for (config = configs.begin (); config != configs.end (); ++config) - output += *config + "\n"; + for (auto& config : configs) + output += config + "\n"; return 0; } diff -Nru task-2.4.4+dfsg/src/commands/CmdContext.cpp task-2.5.0+dfsg/src/commands/CmdContext.cpp --- task-2.4.4+dfsg/src/commands/CmdContext.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdContext.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -40,11 +40,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdContext::CmdContext () { - _keyword = "context"; - _usage = "task context [ | subcommand]"; - _description = STRING_CMD_CONTEXT_USAGE; - _read_only = true; - _displays_id = false; + _keyword = "context"; + _usage = "task context [ | ]"; + _description = STRING_CMD_CONTEXT_USAGE; + _read_only = true; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = false; + _accepts_modifications = false; + _accepts_miscellaneous = true; + _category = Command::Category::context; } //////////////////////////////////////////////////////////////////////////////// @@ -54,24 +60,18 @@ std::stringstream out; // Get the non-attribute, non-fancy command line arguments. - std::vector words = context.cli.getWords (); + std::vector words = context.cli2.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); + if (subcommand == "define") rc = defineContext (words, out); + else if (subcommand == "delete") rc = deleteContext (words, out); + else if (subcommand == "list") rc = listContexts (out); + else if (subcommand == "none") rc = unsetContext (out); + else if (subcommand == "show") rc = showContext (out); + else rc = setContext (words, out); } output = out.str (); @@ -84,7 +84,7 @@ // // If to is specified as 0 (default value), all the remaining words will be joined. // -std::string CmdContext::joinWords (std::vector & words, unsigned int from, unsigned int to /* = 0 */) +std::string CmdContext::joinWords (const std::vector & words, unsigned int from, unsigned int to /* = 0 */) { std::string value = ""; @@ -109,10 +109,9 @@ { std::vector 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)); + for (auto& name : context.config) + if (name.first.substr (0, 8) == "context.") + contexts.push_back (name.first.substr (8)); return contexts; } @@ -127,7 +126,7 @@ // Invoked with: task context define // Example: task context define home project:Home // -int CmdContext::defineContext (std::vector & words, std::stringstream& out) +int CmdContext::defineContext (const std::vector & words, std::stringstream& out) { int rc = 0; bool confirmation = context.config.getBoolean ("confirmation"); @@ -140,11 +139,12 @@ // Check if the value is a proper filter by filtering current pending.data Filter filter; std::vector filtered; - const std::vector & pending = context.tdb2.pending.get_tasks (); + auto pending = context.tdb2.pending.get_tasks (); try { - context.cli.addRawFilter ("( " + value + " )"); + // This result is not used, and is just to check validity. + context.cli2.addFilter (value); filter.subset (pending, filtered); } catch (std::string exception) @@ -188,7 +188,7 @@ // Invoked with: task context delete // Example: task context delete home // -int CmdContext::deleteContext (std::vector & words, std::stringstream& out) +int CmdContext::deleteContext (const std::vector & words, std::stringstream& out) { int rc = 0; @@ -229,7 +229,7 @@ // Invoked with: task context list // Example: task context list // -int CmdContext::listContexts (std::vector & words, std::stringstream& out) +int CmdContext::listContexts (std::stringstream& out) { int rc = 0; std::vector contexts = getContexts(); @@ -242,18 +242,26 @@ view.width (context.getWidth ()); view.add (Column::factory ("string", "Name")); view.add (Column::factory ("string", "Definition")); + view.add (Column::factory ("string", "Active")); Color label (context.config.get ("color.label")); view.colorHeader (label); - std::vector ::iterator userContext; - for (userContext = contexts.begin (); userContext != contexts.end (); ++userContext) + std::string activeContext = context.config.get ("context"); + + for (auto& userContext : contexts) { - std::string definition = context.config.get ("context." + *userContext); + std::string definition = context.config.get ("context." + userContext); + + std::string active = "no"; + + if (userContext == activeContext) + active = "yes"; int row = view.addRow (); - view.set (row, 0, *userContext); + view.set (row, 0, userContext); view.set (row, 1, definition); + view.set (row, 2, active); } out << optionalBlankLine () @@ -280,7 +288,7 @@ // Invoked with: task context // Example: task context home // -int CmdContext::setContext (std::vector & words, std::stringstream& out) +int CmdContext::setContext (const std::vector & words, std::stringstream& out) { int rc = 0; std::string value = words[0]; @@ -313,7 +321,7 @@ // Invoked with: task context show // Example: task context show // -int CmdContext::showContext (std::vector & words, std::stringstream& out) +int CmdContext::showContext (std::stringstream& out) { std::string currentContext = context.config.get ("context"); @@ -338,7 +346,7 @@ // Invoked with: task context none // Example: task context none // -int CmdContext::unsetContext (std::vector & words, std::stringstream& out) +int CmdContext::unsetContext (std::stringstream& out) { int rc = 0; int status = CmdConfig::unsetConfigVariable ("context", false); @@ -357,11 +365,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdCompletionContext::CmdCompletionContext () { - _keyword = "_context"; - _usage = "task _context"; - _description = STRING_CMD_HCONTEXT_USAGE; - _read_only = true; - _displays_id = false; + _keyword = "_context"; + _usage = "task _context"; + _description = STRING_CMD_HCONTEXT_USAGE; + _read_only = true; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = false; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::internal; } //////////////////////////////////////////////////////////////////////////////// @@ -369,9 +383,8 @@ { std::vector userContexts = CmdContext::getContexts (); - std::vector ::iterator userContext; - for (userContext = userContexts.begin (); userContext != userContexts.end (); ++userContext) - output += *userContext + "\n"; + for (auto& userContext : userContexts) + output += userContext + "\n"; return 0; } diff -Nru task-2.4.4+dfsg/src/commands/CmdContext.h task-2.5.0+dfsg/src/commands/CmdContext.h --- task-2.4.4+dfsg/src/commands/CmdContext.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdContext.h 2015-10-21 21:18:15.000000000 +0000 @@ -35,14 +35,14 @@ public: CmdContext (); int execute (std::string&); - std::string joinWords (std::vector & words, unsigned int from, unsigned int to = 0); + std::string joinWords (const std::vector &, unsigned int, unsigned int = 0); static std::vector getContexts (); - int defineContext (std::vector & words, std::stringstream& out); - int deleteContext (std::vector & words, std::stringstream& out); - int listContexts (std::vector & words, std::stringstream& out); - int setContext (std::vector & words, std::stringstream& out); - int showContext (std::vector & words, std::stringstream& out); - int unsetContext (std::vector & words, std::stringstream& out); + int defineContext (const std::vector &, std::stringstream&); + int deleteContext (const std::vector &, std::stringstream&); + int listContexts (std::stringstream&); + int setContext (const std::vector &, std::stringstream&); + int showContext (std::stringstream&); + int unsetContext (std::stringstream&); }; class CmdCompletionContext : public Command diff -Nru task-2.4.4+dfsg/src/commands/CmdCount.cpp task-2.5.0+dfsg/src/commands/CmdCount.cpp --- task-2.4.4+dfsg/src/commands/CmdCount.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdCount.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -37,11 +37,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdCount::CmdCount () { - _keyword = "count"; - _usage = "task count"; - _description = STRING_CMD_COUNT_USAGE; - _read_only = true; - _displays_id = false; + _keyword = "count"; + _usage = "task count"; + _description = STRING_CMD_COUNT_USAGE; + _read_only = true; + _displays_id = false; + _needs_gc = true; + _uses_context = true; + _accepts_filter = true; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::metadata; } //////////////////////////////////////////////////////////////////////////////// @@ -55,9 +61,8 @@ // Find number of matching tasks. Skip recurring parent tasks. int count = 0; - std::vector ::iterator it; - for (it = filtered.begin (); it != filtered.end (); ++it) - if (it->getStatus () != Task::recurring) + for (auto& task : filtered) + if (task.getStatus () != Task::recurring) ++count; output = format (count) + "\n"; diff -Nru task-2.4.4+dfsg/src/commands/CmdCustom.cpp task-2.5.0+dfsg/src/commands/CmdCustom.cpp --- task-2.4.4+dfsg/src/commands/CmdCustom.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdCustom.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -43,15 +43,21 @@ //////////////////////////////////////////////////////////////////////////////// CmdCustom::CmdCustom ( - const std::string& k, - const std::string& u, - const std::string& d) + const std::string& keyword, + const std::string& usage, + const std::string& description) { - _keyword = k; - _usage = u; - _description = d; - _read_only = true; - _displays_id = true; + _keyword = keyword; + _usage = usage; + _description = description; + _read_only = true; + _displays_id = true; + _needs_gc = true; + _uses_context = true; + _accepts_filter = true; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Category::report; } //////////////////////////////////////////////////////////////////////////////// @@ -64,8 +70,6 @@ std::string reportLabels = context.config.get ("report." + _keyword + ".labels"); std::string reportSort = context.config.get ("report." + _keyword + ".sort"); std::string reportFilter = context.config.get ("report." + _keyword + ".filter"); - if (reportFilter != "") - reportFilter = "( " + reportFilter + " )"; std::vector columns; split (columns, reportColumns, ','); @@ -79,10 +83,13 @@ std::vector sortOrder; split (sortOrder, reportSort, ','); - validateSortColumns (sortOrder); + if (sortOrder.size () != 0 && + sortOrder[0] != "none") + validateSortColumns (sortOrder); - // Prepend the argument list with those from the report filter. - context.cli.addRawFilter (reportFilter); + // Add the report filter to any existing filter. + if (reportFilter != "") + context.cli2.addFilter (reportFilter); // Apply filter. handleRecurrence (); @@ -90,12 +97,30 @@ std::vector filtered; filter.subset (filtered); - // Sort the tasks. std::vector sequence; - for (unsigned int i = 0; i < filtered.size (); ++i) - sequence.push_back (i); - - sort_tasks (filtered, sequence, reportSort); + if (sortOrder.size () && + sortOrder[0] == "none") + { + // Assemble a sequence vector that represents the tasks listed in + // context.cli2._uuid_ranges, in the order in which they appear. This + // equates to no sorting, just a specified order. + sortOrder.clear (); + for (auto& i : context.cli2._uuid_list) + for (unsigned int t = 0; t < filtered.size (); ++t) + if (filtered[t].get ("uuid") == i) + sequence.push_back (t); + } + else + { + // There is a sortOrder, so sorting will take place, which means the initial + // order of sequence is ascending. + for (unsigned int i = 0; i < filtered.size (); ++i) + sequence.push_back (i); + + // Sort the tasks. + if (sortOrder.size ()) + sort_tasks (filtered, sequence, reportSort); + } // Configure the view. ViewTask view; @@ -104,27 +129,33 @@ view.extraPadding (context.config.getInteger ("row.padding")); view.intraPadding (context.config.getInteger ("column.padding")); - Color label (context.config.get ("color.label")); - view.colorHeader (label); + if (context.color ()) + { + Color label (context.config.get ("color.label")); + view.colorHeader (label); - Color label_sort (context.config.get ("color.label.sort")); - view.colorSortHeader (label_sort); + Color label_sort (context.config.get ("color.label.sort")); + view.colorSortHeader (label_sort); - Color alternate (context.config.get ("color.alternate")); - view.colorOdd (alternate); - view.intraColorOdd (alternate); + // If an alternating row color is specified, notify the table. + Color alternate (context.config.get ("color.alternate")); + if (alternate.nontrivial ()) + { + view.colorOdd (alternate); + view.intraColorOdd (alternate); + } + } // Capture columns that are sorted. std::vector sortColumns; // Add the break columns, if any. - std::vector ::iterator so; - for (so = sortOrder.begin (); so != sortOrder.end (); ++so) + for (auto& so : sortOrder) { std::string name; bool ascending; bool breakIndicator; - context.decomposeSortField (*so, name, ascending, breakIndicator); + context.decomposeSortField (so, name, ascending, breakIndicator); if (breakIndicator) view.addBreak (name); @@ -211,17 +242,15 @@ //////////////////////////////////////////////////////////////////////////////// void CmdCustom::validateReportColumns (std::vector & columns) { - std::vector ::iterator i; - for (i = columns.begin (); i != columns.end (); ++i) - legacyColumnMap (*i); + for (auto& col : columns) + legacyColumnMap (col); } //////////////////////////////////////////////////////////////////////////////// void CmdCustom::validateSortColumns (std::vector & columns) { - std::vector ::iterator i; - for (i = columns.begin (); i != columns.end (); ++i) - legacySortColumnMap (*i); + for (auto& col : columns) + legacySortColumnMap (col); } //////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/commands/CmdDelete.cpp task-2.5.0+dfsg/src/commands/CmdDelete.cpp --- task-2.4.4+dfsg/src/commands/CmdDelete.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdDelete.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -39,16 +39,22 @@ //////////////////////////////////////////////////////////////////////////////// CmdDelete::CmdDelete () { - _keyword = "delete"; - _usage = "task delete "; - _description = STRING_CMD_DELETE_USAGE; - _read_only = false; - _displays_id = false; - _needs_confirm = true; + _keyword = "delete"; + _usage = "task delete "; + _description = STRING_CMD_DELETE_USAGE; + _read_only = false; + _displays_id = false; + _needs_confirm = true; + _needs_gc = false; + _uses_context = true; + _accepts_filter = true; + _accepts_modifications = true; + _accepts_miscellaneous = false; + _category = Command::Category::operation; } //////////////////////////////////////////////////////////////////////////////// -int CmdDelete::execute (std::string& output) +int CmdDelete::execute (std::string&) { int rc = 0; int count = 0; @@ -66,66 +72,64 @@ // Accumulated project change notifications. std::map projectChanges; - std::vector ::iterator task; - for (task = filtered.begin (); task != filtered.end (); ++task) + for (auto& task : filtered) { - Task before (*task); + Task before (task); - if (task->getStatus () != Task::deleted) + if (task.getStatus () != Task::deleted) { // Delete the specified task. std::string question; - if (task->id) + if (task.id) question = format (STRING_CMD_DELETE_CONFIRM, - task->id, - task->get ("description")); + task.id, + task.get ("description")); else question = format (STRING_CMD_DELETE_CONFIRM, - task->get ("uuid"), - task->get ("description")); + task.get ("uuid"), + task.get ("description")); - task->modify (Task::modAnnotate); - task->setStatus (Task::deleted); - if (! task->has ("end")) - task->setAsNow ("end"); + task.modify (Task::modAnnotate); + task.setStatus (Task::deleted); + if (! task.has ("end")) + task.setAsNow ("end"); - if (permission (*task, question, filtered.size ())) + if (permission (question, filtered.size ())) { - updateRecurrenceMask (*task); + updateRecurrenceMask (task); ++count; - context.tdb2.modify (*task); - feedback_affected (STRING_CMD_DELETE_TASK, *task); - feedback_unblocked (*task); - dependencyChainOnComplete (*task); + context.tdb2.modify (task); + feedback_affected (STRING_CMD_DELETE_TASK, task); + feedback_unblocked (task); + dependencyChainOnComplete (task); if (context.verbose ("project")) - projectChanges[task->get ("project")] = onProjectChange (*task); + projectChanges[task.get ("project")] = onProjectChange (task); // Delete siblings. - if (task->has ("parent")) + if (task.has ("parent")) { if ((context.config.get ("recurrence.confirmation") == "prompt" && confirm (STRING_CMD_DELETE_CONFIRM_R)) || context.config.getBoolean ("recurrence.confirmation")) { - std::vector siblings = context.tdb2.siblings (*task); - std::vector ::iterator sibling; - for (sibling = siblings.begin (); sibling != siblings.end (); ++sibling) + std::vector siblings = context.tdb2.siblings (task); + for (auto& sibling : siblings) { - sibling->modify (Task::modAnnotate); - sibling->setStatus (Task::deleted); - if (! sibling->has ("end")) - sibling->setAsNow ("end"); - - updateRecurrenceMask (*sibling); - context.tdb2.modify (*sibling); - feedback_affected (STRING_CMD_DELETE_TASK_R, *sibling); - feedback_unblocked (*sibling); + sibling.modify (Task::modAnnotate); + sibling.setStatus (Task::deleted); + if (! sibling.has ("end")) + sibling.setAsNow ("end"); + + updateRecurrenceMask (sibling); + context.tdb2.modify (sibling); + feedback_affected (STRING_CMD_DELETE_TASK_R, sibling); + feedback_unblocked (sibling); ++count; } // Delete the parent Task parent; - context.tdb2.get (task->get ("parent"), parent); + context.tdb2.get (task.get ("parent"), parent); parent.setStatus (Task::deleted); if (! parent.has ("end")) parent.setAsNow ("end"); @@ -137,23 +141,22 @@ // Task potentially has child tasks - optionally delete them. else { - std::vector children = context.tdb2.children (*task); + std::vector children = context.tdb2.children (task); if (children.size () && (context.config.getBoolean ("recurrence.confirmation") || confirm (STRING_CMD_DELETE_CONFIRM_R))) { - std::vector ::iterator child; - for (child = children.begin (); child != children.end (); ++child) + for (auto& child : children) { - child->modify (Task::modAnnotate); - child->setStatus (Task::deleted); - if (! child->has ("end")) - child->setAsNow ("end"); - - updateRecurrenceMask (*child); - context.tdb2.modify (*child); - feedback_affected (STRING_CMD_DELETE_TASK_R, *child); - feedback_unblocked (*child); + child.modify (Task::modAnnotate); + child.setStatus (Task::deleted); + if (! child.has ("end")) + child.setAsNow ("end"); + + updateRecurrenceMask (child); + context.tdb2.modify (child); + feedback_affected (STRING_CMD_DELETE_TASK_R, child); + feedback_unblocked (child); ++count; } } @@ -170,18 +173,17 @@ else { std::cout << format (STRING_CMD_DELETE_NOT_DEL, - task->id, - task->get ("description")) + task.id, + task.get ("description")) << "\n"; rc = 1; } } // Now list the project changes. - std::map ::iterator i; - for (i = projectChanges.begin (); i != projectChanges.end (); ++i) - if (i->first != "") - context.footnote (i->second); + for (auto& change : projectChanges) + if (change.first != "") + context.footnote (change.second); feedback_affected (count == 1 ? STRING_CMD_DELETE_1 : STRING_CMD_DELETE_N, count); return rc; diff -Nru task-2.4.4+dfsg/src/commands/CmdDenotate.cpp task-2.5.0+dfsg/src/commands/CmdDenotate.cpp --- task-2.4.4+dfsg/src/commands/CmdDenotate.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdDenotate.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -39,15 +39,21 @@ //////////////////////////////////////////////////////////////////////////////// CmdDenotate::CmdDenotate () { - _keyword = "denotate"; - _usage = "task denotate "; - _description = STRING_CMD_DENO_USAGE; - _read_only = false; - _displays_id = false; + _keyword = "denotate"; + _usage = "task denotate "; + _description = STRING_CMD_DENO_USAGE; + _read_only = false; + _displays_id = false; + _needs_gc = false; + _uses_context = true; + _accepts_filter = true; + _accepts_modifications = false; + _accepts_miscellaneous = true; + _category = Command::Category::operation; } //////////////////////////////////////////////////////////////////////////////// -int CmdDenotate::execute (std::string& output) +int CmdDenotate::execute (std::string&) { int rc = 0; int count = 0; @@ -65,75 +71,72 @@ // Extract all the ORIGINAL MODIFICATION args as simple text patterns. std::string pattern = ""; - std::vector ::iterator a; - for (a = context.cli._args.begin (); a != context.cli._args.end (); ++a) + for (auto& a : context.cli2._args) { - if (a->hasTag ("ORIGINAL") && - a->hasTag ("MODIFICATION")) + if (a.hasTag ("MISCELLANEOUS")) { if (pattern != "") pattern += ' '; - pattern += a->attribute ("raw"); + pattern += a.attribute ("raw"); } } // Accumulated project change notifications. std::map projectChanges; - std::vector ::iterator task; - for (task = filtered.begin (); task != filtered.end (); ++task) + for (auto& task : filtered) { - Task before (*task); + Task before (task); std::map annotations; - task->getAnnotations (annotations); + task.getAnnotations (annotations); if (annotations.size () == 0) throw std::string (STRING_CMD_DENO_NONE); - std::map ::iterator i; std::string anno; bool match = false; - for (i = annotations.begin (); i != annotations.end (); ++i) + for (auto i = annotations.begin (); i != annotations.end (); ++i) { if (i->second == pattern) { match = true; anno = i->second; annotations.erase (i); - task->setAnnotations (annotations); + task.setAnnotations (annotations); break; } } + if (! match) { - for (i = annotations.begin (); i != annotations.end (); ++i) + for (auto i = annotations.begin (); i != annotations.end (); ++i) { - std::string::size_type loc = find (i->second, pattern, sensitive); + auto loc = find (i->second, pattern, sensitive); if (loc != std::string::npos) { anno = i->second; annotations.erase (i); - task->setAnnotations (annotations); + task.setAnnotations (annotations); break; } } } - if (taskDiff (before, *task)) + if (before != task) { std::string question = format (STRING_CMD_DENO_CONFIRM, - task->id, - task->get ("description")); + task.id, + task.get ("description")); - if (permission (*task, taskDifferences (before, *task) + question, filtered.size ())) + if (permission (taskDifferences (before, task) + question, filtered.size ())) { ++count; - context.tdb2.modify (*task); + context.tdb2.modify (task); feedback_affected (format (STRING_CMD_DENO_FOUND, anno)); if (context.verbose ("project")) - projectChanges[task->get ("project")] = onProjectChange (*task, false); + projectChanges[task.get ("project")] = onProjectChange (task, false); } else { @@ -151,10 +154,9 @@ } // Now list the project changes. - std::map ::iterator i; - for (i = projectChanges.begin (); i != projectChanges.end (); ++i) - if (i->first != "") - context.footnote (i->second); + for (auto& change : projectChanges) + if (change.first != "") + context.footnote (change.second); feedback_affected (count == 1 ? STRING_CMD_DENO_1 : STRING_CMD_DENO_N, count); return rc; diff -Nru task-2.4.4+dfsg/src/commands/CmdDiagnostics.cpp task-2.5.0+dfsg/src/commands/CmdDiagnostics.cpp --- task-2.4.4+dfsg/src/commands/CmdDiagnostics.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdDiagnostics.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -50,11 +50,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdDiagnostics::CmdDiagnostics () { - _keyword = "diagnostics"; - _usage = "task diagnostics"; - _description = STRING_CMD_DIAG_USAGE; - _read_only = true; - _displays_id = false; + _keyword = "diagnostics"; + _usage = "task diagnostics"; + _description = STRING_CMD_DIAG_USAGE; + _read_only = true; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = false; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::misc; } //////////////////////////////////////////////////////////////////////////////// @@ -256,8 +262,9 @@ out << " CA: " << context.config.get ("taskd.ca") << (File (context.config.get ("taskd.ca")).readable () - ? " (readable)" : " (not readable)") - << "\n"; + ? ", readable, " : ", not readable, ") + << File (context.config.get ("taskd.ca")).size () + << " bytes\n"; std::string trust_value = context.config.get ("taskd.trust"); if (trust_value == "strict" || @@ -270,14 +277,16 @@ out << "Certificate: " << context.config.get ("taskd.certificate") << (File (context.config.get ("taskd.certificate")).readable () - ? " (readable)" : " (not readable)") - << "\n"; + ? ", readable, " : ", not readable, ") + << File (context.config.get ("taskd.certificate")).size () + << " bytes\n"; out << " Key: " << context.config.get ("taskd.key") << (File (context.config.get ("taskd.key")).readable () - ? " (readable)" : " (not readable)") - << "\n"; + ? ", readable, " : ", not readable, ") + << File (context.config.get ("taskd.key")).size () + << " bytes\n"; out << " Ciphers: " << context.config.get ("taskd.ciphers") @@ -285,7 +294,7 @@ // Get credentials, but mask out the key. std::string credentials = context.config.get ("taskd.credentials"); - std::string::size_type last_slash = credentials.rfind ('/'); + auto last_slash = credentials.rfind ('/'); if (last_slash != std::string::npos) credentials = credentials.substr (0, last_slash) + "/" @@ -305,13 +314,12 @@ std::vector hooks = context.hooks.list (); if (hooks.size ()) { - std::vector ::iterator h; - for (h = hooks.begin (); h != hooks.end (); ++h) + for (auto& hook : hooks) { - Path p (*h); + Path p (hook); std::string name = p.name (); out << " " - << *h + << hook << (p.executable () ? format (" ({1})", STRING_CMD_DIAG_HOOK_EXEC) : format (" ({1})", STRING_CMD_DIAG_HOOK_NO_EXEC)) << (p.is_link () ? format (" ({1})", STRING_CMD_DIAG_HOOK_SYMLINK) : "") << ((name.substr (0, 6) == "on-add" || @@ -345,10 +353,9 @@ std::map seen; std::vector dups; std::string uuid; - std::vector ::iterator i; - for (i = all.begin (); i != all.end (); ++i) + for (auto& i : all) { - uuid = i->get ("uuid"); + uuid = i.get ("uuid"); if (seen.find (uuid) != seen.end ()) dups.push_back (uuid); else @@ -361,9 +368,8 @@ if (dups.size ()) { - std::vector ::iterator d; - for (d = dups.begin (); d != dups.end (); ++d) - out << " " << format (STRING_CMD_DIAG_UUID_DUP, *d) << "\n"; + for (auto& d : dups) + out << " " << format (STRING_CMD_DIAG_UUID_DUP, d) << "\n"; } else { diff -Nru task-2.4.4+dfsg/src/commands/CmdDone.cpp task-2.5.0+dfsg/src/commands/CmdDone.cpp --- task-2.4.4+dfsg/src/commands/CmdDone.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdDone.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -39,15 +39,21 @@ //////////////////////////////////////////////////////////////////////////////// CmdDone::CmdDone () { - _keyword = "done"; - _usage = "task done "; - _description = STRING_CMD_DONE_USAGE; - _read_only = false; - _displays_id = false; + _keyword = "done"; + _usage = "task done "; + _description = STRING_CMD_DONE_USAGE; + _read_only = false; + _displays_id = false; + _needs_gc = false; + _uses_context = true; + _accepts_filter = true; + _accepts_modifications = true; + _accepts_miscellaneous = false; + _category = Command::Category::operation; } //////////////////////////////////////////////////////////////////////////////// -int CmdDone::execute (std::string& output) +int CmdDone::execute (std::string&) { int rc = 0; int count = 0; @@ -66,44 +72,43 @@ std::map projectChanges; bool nagged = false; - std::vector ::iterator task; - for (task = filtered.begin (); task != filtered.end (); ++task) + for (auto& task : filtered) { - Task before (*task); + Task before (task); - if (task->getStatus () == Task::pending || - task->getStatus () == Task::waiting) + if (task.getStatus () == Task::pending || + task.getStatus () == Task::waiting) { // Complete the specified task. std::string question = format (STRING_CMD_DONE_CONFIRM, - task->id, - task->get ("description")); + task.id, + task.get ("description")); - task->modify (Task::modAnnotate); - task->setStatus (Task::completed); - if (! task->has ("end")) - task->setAsNow ("end"); + task.modify (Task::modAnnotate); + task.setStatus (Task::completed); + if (! task.has ("end")) + task.setAsNow ("end"); // Stop the task, if started. - if (task->has ("start")) + if (task.has ("start")) { - task->remove ("start"); + task.remove ("start"); if (context.config.getBoolean ("journal.time")) - task->addAnnotation (context.config.get ("journal.time.stop.annotation")); + task.addAnnotation (context.config.get ("journal.time.stop.annotation")); } - if (permission (*task, taskDifferences (before, *task) + question, filtered.size ())) + if (permission (taskDifferences (before, task) + question, filtered.size ())) { - updateRecurrenceMask (*task); - context.tdb2.modify (*task); + updateRecurrenceMask (task); + context.tdb2.modify (task); ++count; - feedback_affected (STRING_CMD_DONE_TASK, *task); - feedback_unblocked (*task); + feedback_affected (STRING_CMD_DONE_TASK, task); + feedback_unblocked (task); if (!nagged) - nagged = nag (*task); - dependencyChainOnComplete (*task); + nagged = nag (task); + dependencyChainOnComplete (task); if (context.verbose ("project")) - projectChanges[task->get ("project")] = onProjectChange (*task); + projectChanges[task.get ("project")] = onProjectChange (task); } else { @@ -116,18 +121,17 @@ else { std::cout << format (STRING_CMD_DONE_NOTPEND, - task->id, - task->get ("description")) + task.id, + task.get ("description")) << "\n"; rc = 1; } } // Now list the project changes. - std::map ::iterator i; - for (i = projectChanges.begin (); i != projectChanges.end (); ++i) - if (i->first != "") - context.footnote (i->second); + for (auto& change : projectChanges) + if (change.first != "") + context.footnote (change.second); feedback_affected (count == 1 ? STRING_CMD_DONE_1 : STRING_CMD_DONE_N, count); return rc; diff -Nru task-2.4.4+dfsg/src/commands/CmdDuplicate.cpp task-2.5.0+dfsg/src/commands/CmdDuplicate.cpp --- task-2.4.4+dfsg/src/commands/CmdDuplicate.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdDuplicate.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -39,15 +39,21 @@ //////////////////////////////////////////////////////////////////////////////// CmdDuplicate::CmdDuplicate () { - _keyword = "duplicate"; - _usage = "task duplicate "; - _description = STRING_CMD_DUPLICATE_USAGE; - _read_only = false; - _displays_id = false; + _keyword = "duplicate"; + _usage = "task duplicate "; + _description = STRING_CMD_DUPLICATE_USAGE; + _read_only = false; + _displays_id = false; + _needs_gc = false; + _uses_context = true; + _accepts_filter = true; + _accepts_modifications = true; + _accepts_miscellaneous = false; + _category = Command::Category::operation; } //////////////////////////////////////////////////////////////////////////////// -int CmdDuplicate::execute (std::string& output) +int CmdDuplicate::execute (std::string&) { int rc = 0; int count = 0; @@ -65,11 +71,10 @@ // Accumulated project change notifications. std::map projectChanges; - std::vector ::iterator task; - for (task = filtered.begin (); task != filtered.end (); ++task) + for (auto& task : filtered) { // Duplicate the specified task. - Task dup (*task); + Task dup (task); dup.id = 0; // Reset, and TDB2::add will set. dup.set ("uuid", uuid ()); // Needs a new UUID. dup.remove ("start"); // Does not inherit start date. @@ -83,7 +88,7 @@ dup.remove ("recur"); dup.remove ("until"); dup.remove ("imask"); - std::cout << format (STRING_CMD_DUPLICATE_NON_REC, task->id) + std::cout << format (STRING_CMD_DUPLICATE_NON_REC, task.id) << "\n"; } @@ -91,7 +96,7 @@ else if (dup.getStatus () == Task::recurring) { dup.remove ("mask"); - std::cout << format (STRING_CMD_DUPLICATE_REC, task->id) + std::cout << format (STRING_CMD_DUPLICATE_REC, task.id) << "\n"; } @@ -100,15 +105,14 @@ dup.modify (Task::modAnnotate); - if (permission (dup, - format (STRING_CMD_DUPLICATE_CONFIRM, - task->id, - task->get ("description")), + if (permission (format (STRING_CMD_DUPLICATE_CONFIRM, + task.id, + task.get ("description")), filtered.size ())) { context.tdb2.add (dup); ++count; - feedback_affected (STRING_CMD_DUPLICATE_TASK, *task); + feedback_affected (STRING_CMD_DUPLICATE_TASK, task); if (context.verbose ("new-id")) std::cout << format (STRING_CMD_ADD_FEEDBACK, dup.id) + "\n"; @@ -116,7 +120,7 @@ std::cout << format (STRING_CMD_ADD_FEEDBACK, dup.get ("uuid")) + "\n"; if (context.verbose ("project")) - projectChanges[task->get ("project")] = onProjectChange (*task); + projectChanges[task.get ("project")] = onProjectChange (task); } else { @@ -128,10 +132,9 @@ } // Now list the project changes. - std::map ::iterator i; - for (i = projectChanges.begin (); i != projectChanges.end (); ++i) - if (i->first != "") - context.footnote (i->second); + for (auto& change : projectChanges) + if (change.first != "") + context.footnote (change.second); feedback_affected (count == 1 ? STRING_CMD_DUPLICATE_1 : STRING_CMD_DUPLICATE_N, count); return rc; diff -Nru task-2.4.4+dfsg/src/commands/CmdEdit.cpp task-2.5.0+dfsg/src/commands/CmdEdit.cpp --- task-2.4.4+dfsg/src/commands/CmdEdit.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdEdit.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -28,9 +28,10 @@ #include #include #include +#include #include #include -#include +#include #include #include #include @@ -40,24 +41,31 @@ #include #include #include +#include extern Context context; //////////////////////////////////////////////////////////////////////////////// CmdEdit::CmdEdit () { - _keyword = "edit"; - _usage = "task edit"; - _description = STRING_CMD_EDIT_USAGE; - _read_only = false; - _displays_id = false; + _keyword = "edit"; + _usage = "task edit"; + _description = STRING_CMD_EDIT_USAGE; + _read_only = false; + _displays_id = false; + _needs_gc = false; + _uses_context = true; + _accepts_filter = true; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::operation; } //////////////////////////////////////////////////////////////////////////////// // Introducing the Silver Bullet. This feature is the catch-all fixative for // various other ills. This is like opening up the hood and going in with a // wrench. To be used sparingly. -int CmdEdit::execute (std::string& output) +int CmdEdit::execute (std::string&) { // Filter the tasks. handleRecurrence (); @@ -66,10 +74,14 @@ filter.subset (filtered); // Find number of matching tasks. - std::vector ::iterator task; - for (task = filtered.begin (); task != filtered.end (); ++task) - if (editFile (*task)) - context.tdb2.modify (*task); + for (auto& task : filtered) + { + CmdEdit::editResult result = editFile (task); + if (result == CmdEdit::editResult::error) + break; + else if (result == CmdEdit::editResult::changes) + context.tdb2.modify (task); + } return 0; } @@ -79,10 +91,10 @@ const std::string& text, const std::string& name) { - std::string::size_type found = text.find (name); + auto found = text.find (name); if (found != std::string::npos) { - std::string::size_type eol = text.find ("\n", found + 1); + auto eol = text.find ("\n", found + 1); if (eol != std::string::npos) { std::string value = text.substr ( @@ -102,10 +114,10 @@ const std::string& startMarker, const std::string& endMarker) { - std::string::size_type start = text.find (startMarker); + auto start = text.find (startMarker); if (start != std::string::npos) { - std::string::size_type end = text.find (endMarker, start); + auto end = text.find (endMarker, start); if (end != std::string::npos) { std::string value = text.substr (start + startMarker.length (), @@ -129,7 +141,7 @@ found = text.find (name, found + 1); if (found != std::string::npos) { - std::string::size_type eol = text.find ("\n", found + 1); + auto eol = text.find ("\n", found + 1); if (eol != std::string::npos) { std::string value = text.substr ( @@ -154,7 +166,7 @@ std::string value = task.get (attribute); if (value.length ()) { - Date dt (value); + ISO8601d dt (value); value = dt.toString (dateformat); } @@ -169,8 +181,8 @@ std::string value = task.get (attribute); if (value.length ()) { - Duration dur (value); - value = dur.formatSeconds (); + ISO8601p dur (value); + value = dur.format (); } return value; @@ -236,15 +248,14 @@ std::map annotations; task.getAnnotations (annotations); - std::map ::iterator anno; - for (anno = annotations.begin (); anno != annotations.end (); ++anno) + for (auto& anno : annotations) { - Date dt (strtol (anno->first.substr (11).c_str (), NULL, 10)); + ISO8601d dt (strtol (anno.first.substr (11).c_str (), NULL, 10)); before << " Annotation: " << dt.toString (dateformat) - << " -- " << anno->second << "\n"; + << " -- " << json::encode (anno.second) << "\n"; } - Date now; + ISO8601d now; before << " Annotation: " << now.toString (dateformat) << " -- \n"; // Add dependencies here. @@ -272,30 +283,28 @@ // UDAs std::vector udas; - std::map ::iterator col; - for (col = context.columns.begin (); col != context.columns.end (); ++col) - if (context.config.get ("uda." + col->first + ".type") != "") - udas.push_back (col->first); + for (auto& col : context.columns) + if (context.config.get ("uda." + col.first + ".type") != "") + udas.push_back (col.first); if (udas.size ()) { before << "# " << STRING_EDIT_UDA_SEP << "\n"; std::sort (udas.begin (), udas.end ()); - std::vector ::iterator uda; - for (uda = udas.begin (); uda != udas.end (); ++uda) + for (auto& uda : udas) { - int pad = 13 - uda->length (); + int pad = 13 - uda.length (); std::string padding = ""; if (pad > 0) padding = std::string (pad, ' '); - std::string type = context.config.get ("uda." + *uda + ".type"); + std::string type = context.config.get ("uda." + uda + ".type"); if (type == "string" || type == "numeric") - before << " UDA " << *uda << ": " << padding << task.get (*uda) << "\n"; + before << " UDA " << uda << ": " << padding << task.get (uda) << "\n"; else if (type == "date") - before << " UDA " << *uda << ": " << padding << formatDate (task, *uda, dateformat) << "\n"; + before << " UDA " << uda << ": " << padding << formatDate (task, uda, dateformat) << "\n"; else if (type == "duration") - before << " UDA " << *uda << ": " << padding << formatDuration (task, *uda) << "\n"; + before << " UDA " << uda << ": " << padding << formatDuration (task, uda) << "\n"; } } @@ -307,15 +316,14 @@ { before << "# " << STRING_EDIT_UDA_ORPHAN_SEP << "\n"; std::sort (orphans.begin (), orphans.end ()); - std::vector ::iterator orphan; - for (orphan = orphans.begin (); orphan != orphans.end (); ++orphan) + for (auto& orphan : orphans) { - int pad = 6 - orphan->length (); + int pad = 6 - orphan.length (); std::string padding = ""; if (pad > 0) padding = std::string (pad, ' '); - before << " UDA Orphan " << *orphan << ": " << padding << task.get (*orphan) << "\n"; + before << " UDA Orphan " << orphan << ": " << padding << task.get (orphan) << "\n"; } } @@ -371,7 +379,7 @@ if (formatted != value) { context.footnote (STRING_EDIT_ENTRY_MOD); - task.set ("entry", Date(value, dateformat).toEpochString ()); + task.set ("entry", ISO8601d (value, dateformat).toEpochString ()); } } else @@ -388,13 +396,13 @@ if (formatted != value) { context.footnote (STRING_EDIT_START_MOD); - task.set ("start", Date(value, dateformat).toEpochString ()); + task.set ("start", ISO8601d (value, dateformat).toEpochString ()); } } else { context.footnote (STRING_EDIT_START_MOD); - task.set ("start", Date(value, dateformat).toEpochString ()); + task.set ("start", ISO8601d (value, dateformat).toEpochString ()); } } else @@ -417,7 +425,7 @@ if (formatted != value) { context.footnote (STRING_EDIT_END_MOD); - task.set ("end", Date(value, dateformat).toEpochString ()); + task.set ("end", ISO8601d (value, dateformat).toEpochString ()); } } else if (task.getStatus () != Task::deleted) @@ -444,13 +452,13 @@ if (formatted != value) { context.footnote (STRING_EDIT_SCHED_MOD); - task.set ("scheduled", Date(value, dateformat).toEpochString ()); + task.set ("scheduled", ISO8601d (value, dateformat).toEpochString ()); } } else { context.footnote (STRING_EDIT_SCHED_MOD); - task.set ("scheduled", Date(value, dateformat).toEpochString ()); + task.set ("scheduled", ISO8601d (value, dateformat).toEpochString ()); } } else @@ -474,13 +482,13 @@ if (formatted != value) { context.footnote (STRING_EDIT_DUE_MOD); - task.set ("due", Date(value, dateformat).toEpochString ()); + task.set ("due", ISO8601d (value, dateformat).toEpochString ()); } } else { context.footnote (STRING_EDIT_DUE_MOD); - task.set ("due", Date(value, dateformat).toEpochString ()); + task.set ("due", ISO8601d (value, dateformat).toEpochString ()); } } else @@ -511,13 +519,13 @@ if (formatted != value) { context.footnote (STRING_EDIT_UNTIL_MOD); - task.set ("until", Date(value, dateformat).toEpochString ()); + task.set ("until", ISO8601d (value, dateformat).toEpochString ()); } } else { context.footnote (STRING_EDIT_UNTIL_MOD); - task.set ("until", Date(value, dateformat).toEpochString ()); + task.set ("until", ISO8601d (value, dateformat).toEpochString ()); } } else @@ -535,9 +543,9 @@ { if (value != "") { - Duration d; + ISO8601p p; std::string::size_type idx = 0; - if (d.parse (value, idx)) + if (p.parse (value, idx)) { context.footnote (STRING_EDIT_RECUR_MOD); if (task.get ("due") != "") @@ -573,14 +581,14 @@ if (formatted != value) { context.footnote (STRING_EDIT_WAIT_MOD); - task.set ("wait", Date(value, dateformat).toEpochString ()); + task.set ("wait", ISO8601d (value, dateformat).toEpochString ()); task.setStatus (Task::waiting); } } else { context.footnote (STRING_EDIT_WAIT_MOD); - task.set ("wait", Date(value, dateformat).toEpochString ()); + task.set ("wait", ISO8601d (value, dateformat).toEpochString ()); task.setStatus (Task::waiting); } } @@ -617,14 +625,14 @@ { found += 14; // Length of "\n Annotation:". - std::string::size_type eol = after.find ("\n", found + 1); + auto eol = after.find ("\n", found + 1); if (eol != std::string::npos) { std::string value = trim (after.substr ( found, eol - found), "\t "); - std::string::size_type gap = value.find (" -- "); + auto gap = value.find (" -- "); if (gap != std::string::npos) { // TODO keeping the initial dates even if dateformat approximates them @@ -634,17 +642,24 @@ // for each line: if the annotation is the same, then it is copied; if // the annotation is modified, then its original date may be kept; and // if there is no corresponding id, then a new unique date is created). - Date when (value.substr (0, gap), dateformat); + ISO8601d when (value.substr (0, gap), dateformat); - // This guarantees that if more than one annotation has the same date, - // that the seconds will be different, thus unique, thus not squashed. - // Bug #249 - when += (const int) annotations.size (); + // If the map already contains a annotation for a given timestamp + // we need to increment until we find an unused key + int timestamp = (int) when.toEpoch (); std::stringstream name; - name << "annotation_" << when.toEpoch (); + + do + { + name.str (""); // Clear + name << "annotation_" << timestamp; + timestamp++; + } + while (annotations.find (name.str ()) != annotations.end ()); + std::string text = trim (value.substr (gap + 4), "\t "); - annotations.insert (std::make_pair (name.str (), text)); + annotations.insert (std::make_pair (name.str (), json::decode (text))); } } } @@ -657,35 +672,33 @@ split (dependencies, value, ","); task.remove ("depends"); - std::vector ::iterator dep; - for (dep = dependencies.begin (); dep != dependencies.end (); ++dep) + for (auto& dep : dependencies) { - if (dep->length () >= 7) - task.addDependency (*dep); + if (dep.length () >= 7) + task.addDependency (dep); else - task.addDependency ((int) strtol (dep->c_str (), NULL, 10)); + task.addDependency ((int) strtol (dep.c_str (), NULL, 10)); } // UDAs - std::map ::iterator col; - for (col = context.columns.begin (); col != context.columns.end (); ++col) + for (auto& col : context.columns) { - std::string type = context.config.get ("uda." + col->first + ".type"); + std::string type = context.config.get ("uda." + col.first + ".type"); if (type != "") { - std::string value = findValue (after, "\n UDA " + col->first + ":"); - if ((task.get (col->first) != value) && (type != "date" || - (task.get (col->first) != Date (value, dateformat).toEpochString ())) && + std::string value = findValue (after, "\n UDA " + col.first + ":"); + if ((task.get (col.first) != value) && (type != "date" || + (task.get (col.first) != ISO8601d (value, dateformat).toEpochString ())) && (type != "duration" || - (task.get (col->first) != (std::string) Duration (value) ))) + (task.get (col.first) != (std::string) ISO8601p (value)))) { if (value != "") { - context.footnote (format (STRING_EDIT_UDA_MOD, col->first)); + context.footnote (format (STRING_EDIT_UDA_MOD, col.first)); if (type == "string") { - task.set (col->first, value); + task.set (col.first, value); } else if (type == "numeric") { @@ -693,25 +706,23 @@ double d; if (n.getNumber (d) && n.depleted ()) - task.set (col->first, value); + task.set (col.first, value); else throw format (STRING_UDA_NUMERIC, value); } else if (type == "date") { - Date d (value, dateformat); - task.set (col->first, d.toEpochString ()); + task.set (col.first, ISO8601d (value, dateformat).toEpochString ()); } else if (type == "duration") { - Duration d (value); - task.set (col->first, (time_t) d); + task.set (col.first, (time_t) ISO8601p (value)); } } else { - context.footnote (format (STRING_EDIT_UDA_DEL, col->first)); - task.remove (col->first); + context.footnote (format (STRING_EDIT_UDA_DEL, col.first)); + task.remove (col.first); } } } @@ -719,14 +730,13 @@ // UDA orphans std::vector orphanValues = findValues (after, "\n UDA Orphan "); - std::vector ::iterator orphan; - for (orphan = orphanValues.begin (); orphan != orphanValues.end (); ++orphan) + for (auto& orphan : orphanValues) { - std::string::size_type colon = orphan->find (':'); + auto colon = orphan.find (':'); if (colon != std::string::npos) { - std::string name = trim (orphan->substr (0, colon), "\t "); - std::string value = trim (orphan->substr (colon + 1), "\t "); + std::string name = trim (orphan.substr (0, colon), "\t "); + std::string value = trim (orphan.substr (colon + 1), "\t "); if (value != "") task.set (name, value); @@ -737,7 +747,7 @@ } //////////////////////////////////////////////////////////////////////////////// -bool CmdEdit::editFile (Task& task) +CmdEdit::editResult CmdEdit::editFile (Task& task) { // Check for file permissions. Directory location (context.config.get ("data.location")); @@ -746,7 +756,7 @@ // Create a temp file name in data.location. std::stringstream file; - file << "task." << getpid () << "." << task.id << ".task"; + file << "task." << task.get ("uuid").substr (0, 8) << ".task"; // Determine the output date format, which uses a hierarchy of definitions. // rc.dateformat.edit @@ -760,6 +770,11 @@ int ignored = chdir (location._data.c_str ()); ++ignored; // Keep compiler quiet. + // Check if the file already exists, if so, bail out + Path filepath = Path (file.str ()); + if (filepath.exists ()) + throw std::string (STRING_EDIT_IN_PROGRESS); + // Format the contents, T -> text, write to a file. std::string before = formatTask (task, dateformat); std::string before_orig = before; @@ -782,10 +797,16 @@ // Launch the editor. std::cout << format (STRING_EDIT_LAUNCHING, editor) << "\n"; - if (-1 == system (editor.c_str ())) - std::cout << STRING_EDIT_NO_EDITS << "\n"; - else + int exitcode = system (editor.c_str ()); + if (0 == exitcode) std::cout << STRING_EDIT_COMPLETE << "\n"; + else + { + std::cout << format (STRING_EDIT_FAILED, exitcode) << "\n"; + if (-1 == exitcode) + std::cout << std::strerror (errno) << "\n"; + return CmdEdit::editResult::error; + } // Slurp file. std::string after; @@ -833,7 +854,9 @@ // Cleanup. File::remove (file.str ()); ignored = chdir (current_dir.c_str ()); - return changes; + return changes + ? CmdEdit::editResult::changes + : CmdEdit::editResult::nochanges; } //////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/commands/CmdEdit.h task-2.5.0+dfsg/src/commands/CmdEdit.h --- task-2.4.4+dfsg/src/commands/CmdEdit.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdEdit.h 2015-10-21 21:18:15.000000000 +0000 @@ -45,7 +45,8 @@ std::string formatDuration (Task&, const std::string&); std::string formatTask (Task, const std::string&); void parseTask (Task&, const std::string&, const std::string&); - bool editFile (Task&); + enum class editResult { error, changes, nochanges }; + editResult editFile (Task&); }; #endif diff -Nru task-2.4.4+dfsg/src/commands/CmdExec.cpp task-2.5.0+dfsg/src/commands/CmdExec.cpp --- task-2.4.4+dfsg/src/commands/CmdExec.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdExec.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -36,18 +36,24 @@ //////////////////////////////////////////////////////////////////////////////// CmdExec::CmdExec () { - _keyword = "execute"; - _usage = "task execute "; - _description = STRING_CMD_EXEC_USAGE; - _read_only = true; - _displays_id = false; + _keyword = "execute"; + _usage = "task execute "; + _description = STRING_CMD_EXEC_USAGE; + _read_only = true; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = false; + _accepts_modifications = false; + _accepts_miscellaneous = true; + _category = Command::Category::misc; } //////////////////////////////////////////////////////////////////////////////// -int CmdExec::execute (std::string& output) +int CmdExec::execute (std::string&) { std::string command_line; - join (command_line, " ", context.cli.getWords ()); + join (command_line, " ", context.cli2.getWords ()); return system (command_line.c_str ()); } diff -Nru task-2.4.4+dfsg/src/commands/CmdExport.cpp task-2.5.0+dfsg/src/commands/CmdExport.cpp --- task-2.4.4+dfsg/src/commands/CmdExport.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdExport.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -36,11 +36,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdExport::CmdExport () { - _keyword = "export"; - _usage = "task export"; - _description = STRING_CMD_EXPORT_USAGE; - _read_only = true; - _displays_id = true; + _keyword = "export"; + _usage = "task export"; + _description = STRING_CMD_EXPORT_USAGE; + _read_only = true; + _displays_id = true; + _needs_gc = true; + _uses_context = false; + _accepts_filter = true; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::migration; } //////////////////////////////////////////////////////////////////////////////// @@ -54,7 +60,10 @@ // Apply filter. Filter filter; std::vector filtered; - filter.subset (filtered, false); + filter.subset (filtered); + + // Export == render. + context.timer_render.start (); // Obey 'limit:N'. int rows = 0; @@ -70,8 +79,7 @@ output += "[\n"; int counter = 0; - std::vector ::iterator task; - for (task = filtered.begin (); task != filtered.end (); ++task) + for (auto task = filtered.begin (); task != filtered.end (); ++task) { if (task != filtered.begin ()) { @@ -92,6 +100,7 @@ if (json_array) output += "]\n"; + context.timer_render.stop (); return rc; } diff -Nru task-2.4.4+dfsg/src/commands/CmdGet.cpp task-2.5.0+dfsg/src/commands/CmdGet.cpp --- task-2.4.4+dfsg/src/commands/CmdGet.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdGet.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -37,39 +37,61 @@ //////////////////////////////////////////////////////////////////////////////// CmdGet::CmdGet () { - _keyword = "_get"; - _usage = "task _get [ ...]"; - _description = STRING_CMD_GET_USAGE; - _read_only = true; - _displays_id = false; + _keyword = "_get"; + _usage = "task _get [ ...]"; + _description = STRING_CMD_GET_USAGE; + _read_only = true; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = false; + _accepts_modifications = false; + _accepts_miscellaneous = true; + _category = Command::Category::internal; } //////////////////////////////////////////////////////////////////////////////// +// Rely on the Lexer to correctly identify DOM references, then jsut iterate +// over those. +// +// It is an error to specify no DOM references. +// It is not an error for a DOM reference to resolve to a blank value. int CmdGet::execute (std::string& output) { - // Obtain the arguments from the description. That way, things like '--' - // have already been handled. - std::vector words = context.cli.getWords (); - if (words.size () == 0) - throw std::string (STRING_CMD_GET_NO_DOM); - - bool found = false; std::vector results; - std::vector ::iterator word; - for (word = words.begin (); word != words.end (); ++word) + for (auto& arg : context.cli2._args) { - Task t; - Variant result; - if (context.dom.get (*word, t, result)) + switch (arg._lextype) { - results.push_back ((std::string) result); - found = true; + case Lexer::Type::dom: + { + Task t; + Variant result; + if (context.dom.get (arg.attribute ("raw"), t, result)) + results.push_back ((std::string) result); + else + results.push_back (""); + } + break; + + // Look for non-refs to complain about. + case Lexer::Type::word: + case Lexer::Type::identifier: + if (! arg.hasTag ("BINARY") && + ! arg.hasTag ("CMD")) + throw format (STRING_CMD_GET_BAD_REF, arg.attribute ("raw")); + + default: + break; } } + if (results.size () == 0) + throw std::string (STRING_CMD_GET_NO_DOM); + join (output, " ", results); output += "\n"; - return found ? 0 : 1; + return 0; } //////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/commands/CmdHelp.cpp task-2.5.0+dfsg/src/commands/CmdHelp.cpp --- task-2.4.4+dfsg/src/commands/CmdHelp.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdHelp.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -38,11 +38,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdHelp::CmdHelp () { - _keyword = "help"; - _usage = "task help"; - _description = STRING_CMD_HELP_USAGE; - _read_only = true; - _displays_id = false; + _keyword = "help"; + _usage = "task help"; + _description = STRING_CMD_HELP_USAGE; + _read_only = true; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = false; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::misc; } //////////////////////////////////////////////////////////////////////////////// @@ -62,33 +68,31 @@ // Obsolete method of getting a list of all commands. std::vector all; - std::map ::iterator i; - for (i = context.commands.begin (); i != context.commands.end (); ++i) - all.push_back (i->first); + for (auto& cmd : context.commands) + all.push_back (cmd.first); // Sort alphabetically by usage. std::sort (all.begin (), all.end ()); // Add the regular commands. - std::vector ::iterator name; - for (name = all.begin (); name != all.end (); ++name) + for (auto& name : all) { - if ((*name)[0] != '_') + if (name[0] != '_') { row = view.addRow (); - view.set (row, 1, context.commands[*name]->usage ()); - view.set (row, 2, context.commands[*name]->description ()); + view.set (row, 1, context.commands[name]->usage ()); + view.set (row, 2, context.commands[name]->description ()); } } // Add the helper commands. - for (name = all.begin (); name != all.end (); ++name) + for (auto& name : all) { - if ((*name)[0] == '_') + if (name[0] == '_') { row = view.addRow (); - view.set (row, 1, context.commands[*name]->usage ()); - view.set (row, 2, context.commands[*name]->description ()); + view.set (row, 1, context.commands[name]->usage ()); + view.set (row, 2, context.commands[name]->description ()); } } @@ -96,14 +100,13 @@ row = view.addRow (); view.set (row, 1, " "); - std::map ::iterator alias; - for (alias = context.config.begin (); alias != context.config.end (); ++alias) + for (auto& alias : context.config) { - if (alias->first.substr (0, 6) == "alias.") + if (alias.first.substr (0, 6) == "alias.") { row = view.addRow (); - view.set (row, 1, alias->first.substr (6)); - view.set (row, 2, format (STRING_CMD_HELP_ALIASED, alias->second)); + view.set (row, 1, alias.first.substr (6)); + view.set (row, 2, format (STRING_CMD_HELP_ALIASED, alias.second)); } } diff -Nru task-2.4.4+dfsg/src/commands/CmdHistory.cpp task-2.5.0+dfsg/src/commands/CmdHistory.cpp --- task-2.4.4+dfsg/src/commands/CmdHistory.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdHistory.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -32,6 +32,7 @@ #include #include #include +#include #include extern Context context; @@ -39,11 +40,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdHistoryMonthly::CmdHistoryMonthly () { - _keyword = "history.monthly"; - _usage = "task history.monthly"; - _description = STRING_CMD_HISTORY_USAGE_M; - _read_only = true; - _displays_id = false; + _keyword = "history.monthly"; + _usage = "task history.monthly"; + _description = STRING_CMD_HISTORY_USAGE_M; + _read_only = true; + _displays_id = false; + _needs_gc = false; + _uses_context = true; + _accepts_filter = true; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::graphs; } //////////////////////////////////////////////////////////////////////////////// @@ -62,23 +69,23 @@ std::vector filtered; filter.subset (filtered); - std::vector ::iterator task; - for (task = filtered.begin (); task != filtered.end (); ++task) + for (auto& task : filtered) { - Date entry (task->get_date ("entry")); + ISO8601d entry (task.get_date ("entry")); - Date end; - if (task->has ("end")) - end = Date (task->get_date ("end")); + ISO8601d end; + if (task.has ("end")) + end = ISO8601d (task.get_date ("end")); time_t epoch = entry.startOfMonth ().toEpoch (); groups[epoch] = 0; - // Every task has an entry date. - ++addedGroup[epoch]; + // Every task has an entry date, but exclude templates. + if (task.getStatus () != Task::recurring) + ++addedGroup[epoch]; // All deleted tasks have an end date. - if (task->getStatus () == Task::deleted) + if (task.getStatus () == Task::deleted) { epoch = end.startOfMonth ().toEpoch (); groups[epoch] = 0; @@ -86,7 +93,7 @@ } // All completed tasks have an end date. - else if (task->getStatus () == Task::completed) + else if (task.getStatus () == Task::completed) { epoch = end.startOfMonth ().toEpoch (); groups[epoch] = 0; @@ -113,16 +120,15 @@ int priorYear = 0; int row = 0; - std::map ::iterator i; - for (i = groups.begin (); i != groups.end (); ++i) + for (auto& i : groups) { row = view.addRow (); - totalAdded += addedGroup [i->first]; - totalCompleted += completedGroup [i->first]; - totalDeleted += deletedGroup [i->first]; + totalAdded += addedGroup [i.first]; + totalCompleted += completedGroup [i.first]; + totalDeleted += deletedGroup [i.first]; - Date dt (i->first); + ISO8601d dt (i.first); int m, d, y; dt.toMDY (m, d, y); @@ -131,26 +137,26 @@ view.set (row, 0, y); priorYear = y; } - view.set (row, 1, Date::monthName(m)); + view.set (row, 1, ISO8601d::monthName(m)); int net = 0; - if (addedGroup.find (i->first) != addedGroup.end ()) + if (addedGroup.find (i.first) != addedGroup.end ()) { - view.set (row, 2, addedGroup[i->first]); - net +=addedGroup[i->first]; + view.set (row, 2, addedGroup[i.first]); + net +=addedGroup[i.first]; } - if (completedGroup.find (i->first) != completedGroup.end ()) + if (completedGroup.find (i.first) != completedGroup.end ()) { - view.set (row, 3, completedGroup[i->first]); - net -= completedGroup[i->first]; + view.set (row, 3, completedGroup[i.first]); + net -= completedGroup[i.first]; } - if (deletedGroup.find (i->first) != deletedGroup.end ()) + if (deletedGroup.find (i.first) != deletedGroup.end ()) { - view.set (row, 4, deletedGroup[i->first]); - net -= deletedGroup[i->first]; + view.set (row, 4, deletedGroup[i.first]); + net -= deletedGroup[i.first]; } Color net_color; @@ -197,11 +203,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdHistoryAnnual::CmdHistoryAnnual () { - _keyword = "history.annual"; - _usage = "task history.annual"; - _description = STRING_CMD_HISTORY_USAGE_A; - _read_only = true; - _displays_id = false; + _keyword = "history.annual"; + _usage = "task history.annual"; + _description = STRING_CMD_HISTORY_USAGE_A; + _read_only = true; + _displays_id = false; + _needs_gc = false; + _uses_context = true; + _accepts_filter = true; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::graphs; } //////////////////////////////////////////////////////////////////////////////// @@ -219,23 +231,23 @@ std::vector filtered; filter.subset (filtered); - std::vector ::iterator task; - for (task = filtered.begin (); task != filtered.end (); ++task) + for (auto& task : filtered) { - Date entry (task->get_date ("entry")); + ISO8601d entry (task.get_date ("entry")); - Date end; - if (task->has ("end")) - end = Date (task->get_date ("end")); + ISO8601d end; + if (task.has ("end")) + end = ISO8601d (task.get_date ("end")); time_t epoch = entry.startOfYear ().toEpoch (); groups[epoch] = 0; - // Every task has an entry date. - ++addedGroup[epoch]; + // Every task has an entry date, but exclude templates. + if (task.getStatus () != Task::recurring) + ++addedGroup[epoch]; // All deleted tasks have an end date. - if (task->getStatus () == Task::deleted) + if (task.getStatus () == Task::deleted) { epoch = end.startOfYear ().toEpoch (); groups[epoch] = 0; @@ -243,7 +255,7 @@ } // All completed tasks have an end date. - else if (task->getStatus () == Task::completed) + else if (task.getStatus () == Task::completed) { epoch = end.startOfYear ().toEpoch (); groups[epoch] = 0; @@ -269,16 +281,15 @@ int priorYear = 0; int row = 0; - std::map ::iterator i; - for (i = groups.begin (); i != groups.end (); ++i) + for (auto& i : groups) { row = view.addRow (); - totalAdded += addedGroup [i->first]; - totalCompleted += completedGroup [i->first]; - totalDeleted += deletedGroup [i->first]; + totalAdded += addedGroup [i.first]; + totalCompleted += completedGroup [i.first]; + totalDeleted += deletedGroup [i.first]; - Date dt (i->first); + ISO8601d dt (i.first); int m, d, y; dt.toMDY (m, d, y); @@ -290,22 +301,22 @@ int net = 0; - if (addedGroup.find (i->first) != addedGroup.end ()) + if (addedGroup.find (i.first) != addedGroup.end ()) { - view.set (row, 1, addedGroup[i->first]); - net +=addedGroup[i->first]; + view.set (row, 1, addedGroup[i.first]); + net +=addedGroup[i.first]; } - if (completedGroup.find (i->first) != completedGroup.end ()) + if (completedGroup.find (i.first) != completedGroup.end ()) { - view.set (row, 2, completedGroup[i->first]); - net -= completedGroup[i->first]; + view.set (row, 2, completedGroup[i.first]); + net -= completedGroup[i.first]; } - if (deletedGroup.find (i->first) != deletedGroup.end ()) + if (deletedGroup.find (i.first) != deletedGroup.end ()) { - view.set (row, 3, deletedGroup[i->first]); - net -= deletedGroup[i->first]; + view.set (row, 3, deletedGroup[i.first]); + net -= deletedGroup[i.first]; } Color net_color; @@ -351,11 +362,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdGHistoryMonthly::CmdGHistoryMonthly () { - _keyword = "ghistory.monthly"; - _usage = "task ghistory.monthly"; - _description = STRING_CMD_GHISTORY_USAGE_M; - _read_only = true; - _displays_id = false; + _keyword = "ghistory.monthly"; + _usage = "task ghistory.monthly"; + _description = STRING_CMD_GHISTORY_USAGE_M; + _read_only = true; + _displays_id = false; + _needs_gc = false; + _uses_context = true; + _accepts_filter = true; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::graphs; } //////////////////////////////////////////////////////////////////////////////// @@ -373,23 +390,23 @@ std::vector filtered; filter.subset (filtered); - std::vector ::iterator task; - for (task = filtered.begin (); task != filtered.end (); ++task) + for (auto& task : filtered) { - Date entry (task->get_date ("entry")); + ISO8601d entry (task.get_date ("entry")); - Date end; - if (task->has ("end")) - end = Date (task->get_date ("end")); + ISO8601d end; + if (task.has ("end")) + end = ISO8601d (task.get_date ("end")); time_t epoch = entry.startOfMonth ().toEpoch (); groups[epoch] = 0; - // Every task has an entry date. - ++addedGroup[epoch]; + // Every task has an entry date, but exclude templates. + if (task.getStatus () != Task::recurring) + ++addedGroup[epoch]; // All deleted tasks have an end date. - if (task->getStatus () == Task::deleted) + if (task.getStatus () == Task::deleted) { epoch = end.startOfMonth ().toEpoch (); groups[epoch] = 0; @@ -397,7 +414,7 @@ } // All completed tasks have an end date. - else if (task->getStatus () == Task::completed) + else if (task.getStatus () == Task::completed) { epoch = end.startOfMonth ().toEpoch (); groups[epoch] = 0; @@ -424,14 +441,13 @@ // Determine the longest line, and the longest "added" line. int maxAddedLine = 0; int maxRemovedLine = 0; - std::map ::iterator i; - for (i = groups.begin (); i != groups.end (); ++i) + for (auto& i : groups) { - if (completedGroup[i->first] + deletedGroup[i->first] > maxRemovedLine) - maxRemovedLine = completedGroup[i->first] + deletedGroup[i->first]; + if (completedGroup[i.first] + deletedGroup[i.first] > maxRemovedLine) + maxRemovedLine = completedGroup[i.first] + deletedGroup[i.first]; - if (addedGroup[i->first] > maxAddedLine) - maxAddedLine = addedGroup[i->first]; + if (addedGroup[i.first] > maxAddedLine) + maxAddedLine = addedGroup[i.first]; } int maxLine = maxAddedLine + maxRemovedLine; @@ -445,16 +461,15 @@ int priorYear = 0; int row = 0; - std::map ::iterator i; - for (i = groups.begin (); i != groups.end (); ++i) + for (auto& i : groups) { row = view.addRow (); - totalAdded += addedGroup[i->first]; - totalCompleted += completedGroup[i->first]; - totalDeleted += deletedGroup[i->first]; + totalAdded += addedGroup[i.first]; + totalCompleted += completedGroup[i.first]; + totalDeleted += deletedGroup[i.first]; - Date dt (i->first); + ISO8601d dt (i.first); int m, d, y; dt.toMDY (m, d, y); @@ -463,35 +478,35 @@ view.set (row, 0, y); priorYear = y; } - view.set (row, 1, Date::monthName(m)); + view.set (row, 1, ISO8601d::monthName(m)); - unsigned int addedBar = (widthOfBar * addedGroup[i->first]) / maxLine; - unsigned int completedBar = (widthOfBar * completedGroup[i->first]) / maxLine; - unsigned int deletedBar = (widthOfBar * deletedGroup[i->first]) / maxLine; + unsigned int addedBar = (widthOfBar * addedGroup[i.first]) / maxLine; + unsigned int completedBar = (widthOfBar * completedGroup[i.first]) / maxLine; + unsigned int deletedBar = (widthOfBar * deletedGroup[i.first]) / maxLine; std::string bar = ""; if (context.color ()) { std::string aBar = ""; - if (addedGroup[i->first]) + if (addedGroup[i.first]) { - aBar = format (addedGroup[i->first]); + aBar = format (addedGroup[i.first]); while (aBar.length () < addedBar) aBar = " " + aBar; } std::string cBar = ""; - if (completedGroup[i->first]) + if (completedGroup[i.first]) { - cBar = format (completedGroup[i->first]); + cBar = format (completedGroup[i.first]); while (cBar.length () < completedBar) cBar = " " + cBar; } std::string dBar = ""; - if (deletedGroup[i->first]) + if (deletedGroup[i.first]) { - dBar = format (deletedGroup[i->first]); + dBar = format (deletedGroup[i.first]); while (dBar.length () < deletedBar) dBar = " " + dBar; } @@ -547,11 +562,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdGHistoryAnnual::CmdGHistoryAnnual () { - _keyword = "ghistory.annual"; - _usage = "task ghistory.annual"; - _description = STRING_CMD_GHISTORY_USAGE_A; - _read_only = true; - _displays_id = false; + _keyword = "ghistory.annual"; + _usage = "task ghistory.annual"; + _description = STRING_CMD_GHISTORY_USAGE_A; + _read_only = true; + _displays_id = false; + _needs_gc = false; + _uses_context = true; + _accepts_filter = true; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::graphs; } //////////////////////////////////////////////////////////////////////////////// @@ -569,23 +590,23 @@ std::vector filtered; filter.subset (filtered); - std::vector ::iterator task; - for (task = filtered.begin (); task != filtered.end (); ++task) + for (auto& task : filtered) { - Date entry (task->get_date ("entry")); + ISO8601d entry (task.get_date ("entry")); - Date end; - if (task->has ("end")) - end = Date (task->get_date ("end")); + ISO8601d end; + if (task.has ("end")) + end = ISO8601d (task.get_date ("end")); time_t epoch = entry.startOfYear ().toEpoch (); groups[epoch] = 0; - // Every task has an entry date. - ++addedGroup[epoch]; + // Every task has an entry date, but exclude templates. + if (task.getStatus () != Task::recurring) + ++addedGroup[epoch]; // All deleted tasks have an end date. - if (task->getStatus () == Task::deleted) + if (task.getStatus () == Task::deleted) { epoch = end.startOfYear ().toEpoch (); groups[epoch] = 0; @@ -593,7 +614,7 @@ } // All completed tasks have an end date. - else if (task->getStatus () == Task::completed) + else if (task.getStatus () == Task::completed) { epoch = end.startOfYear ().toEpoch (); groups[epoch] = 0; @@ -619,14 +640,13 @@ // Determine the longest line, and the longest "added" line. int maxAddedLine = 0; int maxRemovedLine = 0; - std::map ::iterator i; - for (i = groups.begin (); i != groups.end (); ++i) + for (auto& i : groups) { - if (completedGroup[i->first] + deletedGroup[i->first] > maxRemovedLine) - maxRemovedLine = completedGroup[i->first] + deletedGroup[i->first]; + if (completedGroup[i.first] + deletedGroup[i.first] > maxRemovedLine) + maxRemovedLine = completedGroup[i.first] + deletedGroup[i.first]; - if (addedGroup[i->first] > maxAddedLine) - maxAddedLine = addedGroup[i->first]; + if (addedGroup[i.first] > maxAddedLine) + maxAddedLine = addedGroup[i.first]; } int maxLine = maxAddedLine + maxRemovedLine; @@ -640,16 +660,15 @@ int priorYear = 0; int row = 0; - std::map ::iterator i; - for (i = groups.begin (); i != groups.end (); ++i) + for (auto& i : groups) { row = view.addRow (); - totalAdded += addedGroup[i->first]; - totalCompleted += completedGroup[i->first]; - totalDeleted += deletedGroup[i->first]; + totalAdded += addedGroup[i.first]; + totalCompleted += completedGroup[i.first]; + totalDeleted += deletedGroup[i.first]; - Date dt (i->first); + ISO8601d dt (i.first); int m, d, y; dt.toMDY (m, d, y); @@ -659,33 +678,33 @@ priorYear = y; } - unsigned int addedBar = (widthOfBar * addedGroup[i->first]) / maxLine; - unsigned int completedBar = (widthOfBar * completedGroup[i->first]) / maxLine; - unsigned int deletedBar = (widthOfBar * deletedGroup[i->first]) / maxLine; + unsigned int addedBar = (widthOfBar * addedGroup[i.first]) / maxLine; + unsigned int completedBar = (widthOfBar * completedGroup[i.first]) / maxLine; + unsigned int deletedBar = (widthOfBar * deletedGroup[i.first]) / maxLine; std::string bar = ""; if (context.color ()) { std::string aBar = ""; - if (addedGroup[i->first]) + if (addedGroup[i.first]) { - aBar = format (addedGroup[i->first]); + aBar = format (addedGroup[i.first]); while (aBar.length () < addedBar) aBar = " " + aBar; } std::string cBar = ""; - if (completedGroup[i->first]) + if (completedGroup[i.first]) { - cBar = format (completedGroup[i->first]); + cBar = format (completedGroup[i.first]); while (cBar.length () < completedBar) cBar = " " + cBar; } std::string dBar = ""; - if (deletedGroup[i->first]) + if (deletedGroup[i.first]) { - dBar = format (deletedGroup[i->first]); + dBar = format (deletedGroup[i.first]); while (dBar.length () < deletedBar) dBar = " " + dBar; } diff -Nru task-2.4.4+dfsg/src/commands/CmdIDs.cpp task-2.5.0+dfsg/src/commands/CmdIDs.cpp --- task-2.4.4+dfsg/src/commands/CmdIDs.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdIDs.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -41,11 +41,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdIDs::CmdIDs () { - _keyword = "ids"; - _usage = "task ids"; - _description = STRING_CMD_IDS_USAGE_RANGE; - _read_only = true; - _displays_id = true; + _keyword = "ids"; + _usage = "task ids"; + _description = STRING_CMD_IDS_USAGE_RANGE; + _read_only = true; + _displays_id = true; + _needs_gc = true; + _uses_context = false; + _accepts_filter = true; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::metadata; } //////////////////////////////////////////////////////////////////////////////// @@ -59,10 +65,9 @@ // Find number of matching tasks. std::vector ids; - std::vector ::iterator task; - for (task = filtered.begin (); task != filtered.end (); ++task) - if (task->id) - ids.push_back (task->id); + for (auto& task : filtered) + if (task.id) + ids.push_back (task.id); std::sort (ids.begin (), ids.end ()); output = compressIds (ids) + "\n"; @@ -95,7 +100,7 @@ if (i + 1 == ids.size ()) { if (result.str ().length ()) - result << ","; + result << " "; if (range_start < range_end) result << ids[range_start] << "-" << ids[range_end]; @@ -111,7 +116,7 @@ else { if (result.str ().length ()) - result << ","; + result << " "; if (range_start < range_end) result << ids[range_start] << "-" << ids[range_end]; @@ -129,11 +134,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdCompletionIds::CmdCompletionIds () { - _keyword = "_ids"; - _usage = "task _ids"; - _description = STRING_CMD_IDS_USAGE_LIST; - _read_only = true; - _displays_id = true; + _keyword = "_ids"; + _usage = "task _ids"; + _description = STRING_CMD_IDS_USAGE_LIST; + _read_only = true; + _displays_id = true; + _needs_gc = true; + _uses_context = false; + _accepts_filter = true; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::internal; } //////////////////////////////////////////////////////////////////////////////// @@ -146,11 +157,10 @@ filter.subset (filtered); std::vector ids; - std::vector ::iterator task; - for (task = filtered.begin (); task != filtered.end (); ++task) - if (task->getStatus () != Task::deleted && - task->getStatus () != Task::completed) - ids.push_back (task->id); + for (auto& task : filtered) + if (task.getStatus () != Task::deleted && + task.getStatus () != Task::completed) + ids.push_back (task.id); std::sort (ids.begin (), ids.end ()); join (output, "\n", ids); @@ -163,11 +173,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdZshCompletionIds::CmdZshCompletionIds () { - _keyword = "_zshids"; - _usage = "task _zshids"; - _description = STRING_CMD_IDS_USAGE_ZSH; - _read_only = true; - _displays_id = true; + _keyword = "_zshids"; + _usage = "task _zshids"; + _description = STRING_CMD_IDS_USAGE_ZSH; + _read_only = true; + _displays_id = true; + _needs_gc = true; + _uses_context = false; + _accepts_filter = true; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::internal; } //////////////////////////////////////////////////////////////////////////////// @@ -180,13 +196,12 @@ filter.subset (filtered); std::stringstream out; - std::vector ::iterator task; - for (task = filtered.begin (); task != filtered.end (); ++task) - if (task->getStatus () != Task::deleted && - task->getStatus () != Task::completed) - out << task->id + for (auto& task : filtered) + if (task.getStatus () != Task::deleted && + task.getStatus () != Task::completed) + out << task.id << ":" - << str_replace(task->get ("description"), ":", zshColonReplacement) + << str_replace(task.get ("description"), ":", zshColonReplacement) << "\n"; output = out.str (); @@ -198,11 +213,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdUUIDs::CmdUUIDs () { - _keyword = "uuids"; - _usage = "task uuids"; - _description = STRING_CMD_UUIDS_USAGE_RANGE; - _read_only = true; - _displays_id = false; + _keyword = "uuids"; + _usage = "task uuids"; + _description = STRING_CMD_UUIDS_USAGE_RANGE; + _read_only = true; + _displays_id = false; + _needs_gc = true; + _uses_context = false; + _accepts_filter = true; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::metadata; } //////////////////////////////////////////////////////////////////////////////// @@ -215,12 +236,11 @@ filter.subset (filtered); std::vector uuids; - std::vector ::iterator task; - for (task = filtered.begin (); task != filtered.end (); ++task) - uuids.push_back (task->get ("uuid")); + for (auto& task : filtered) + uuids.push_back (task.get ("uuid")); std::sort (uuids.begin (), uuids.end ()); - join (output, ",", uuids); + join (output, " ", uuids); output += "\n"; context.headers.clear (); @@ -230,11 +250,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdCompletionUuids::CmdCompletionUuids () { - _keyword = "_uuids"; - _usage = "task _uuids"; - _description = STRING_CMD_UUIDS_USAGE_LIST; - _read_only = true; - _displays_id = false; + _keyword = "_uuids"; + _usage = "task _uuids"; + _description = STRING_CMD_UUIDS_USAGE_LIST; + _read_only = true; + _displays_id = false; + _needs_gc = true; + _uses_context = false; + _accepts_filter = true; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::internal; } //////////////////////////////////////////////////////////////////////////////// @@ -247,9 +273,8 @@ filter.subset (filtered); std::vector uuids; - std::vector ::iterator task; - for (task = filtered.begin (); task != filtered.end (); ++task) - uuids.push_back (task->get ("uuid")); + for (auto& task : filtered) + uuids.push_back (task.get ("uuid")); std::sort (uuids.begin (), uuids.end ()); join (output, "\n", uuids); @@ -262,11 +287,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdZshCompletionUuids::CmdZshCompletionUuids () { - _keyword = "_zshuuids"; - _usage = "task _zshuuids"; - _description = STRING_CMD_UUIDS_USAGE_ZSH; - _read_only = true; - _displays_id = false; + _keyword = "_zshuuids"; + _usage = "task _zshuuids"; + _description = STRING_CMD_UUIDS_USAGE_ZSH; + _read_only = true; + _displays_id = false; + _needs_gc = true; + _uses_context = true; + _accepts_filter = true; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::internal; } //////////////////////////////////////////////////////////////////////////////// @@ -279,11 +310,10 @@ filter.subset (filtered); std::stringstream out; - std::vector ::iterator task; - for (task = filtered.begin (); task != filtered.end (); ++task) - out << task->get ("uuid") + for (auto& task : filtered) + out << task.get ("uuid") << ":" - << str_replace (task->get ("description"), ":", zshColonReplacement) + << str_replace (task.get ("description"), ":", zshColonReplacement) << "\n"; output = out.str (); diff -Nru task-2.4.4+dfsg/src/commands/CmdImport.cpp task-2.5.0+dfsg/src/commands/CmdImport.cpp --- task-2.4.4+dfsg/src/commands/CmdImport.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdImport.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -28,76 +28,209 @@ #include #include #include -#include +#include #include #include #include #include #include +#include extern Context context; //////////////////////////////////////////////////////////////////////////////// CmdImport::CmdImport () { - _keyword = "import"; - _usage = "task import [ ...]"; - _description = STRING_CMD_IMPORT_USAGE; - _read_only = false; - _displays_id = false; + _keyword = "import"; + _usage = "task import [ ...]"; + _description = STRING_CMD_IMPORT_USAGE; + _read_only = false; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = false; + _accepts_modifications = false; + _accepts_miscellaneous = true; + _category = Command::Category::migration; } //////////////////////////////////////////////////////////////////////////////// -int CmdImport::execute (std::string& output) +int CmdImport::execute (std::string&) { int rc = 0; int count = 0; - // Use the description as a file name. - std::vector words = context.cli.getWords (); - if (! words.size ()) - throw std::string (STRING_CMD_IMPORT_NOFILE); + Filter filter; + if (filter.hasFilter ()) + throw std::string (STRING_ERROR_NO_FILTER); + + // Get filenames from command line arguments. + std::vector words = context.cli2.getWords (); + if (! words.size () || (words.size () == 1 && words[0] == "-")) + { + std::cout << format (STRING_CMD_IMPORT_FILE, "STDIN") << "\n"; + + std::string json; + std::string line; + while (std::getline (std::cin, line)) + json += line + "\n"; + + if (nontrivial (json)) + count = import (json); + } + else + { + // Import tasks from all specified files. + for (auto& word : words) + { + File incoming (word); + if (! incoming.exists ()) + throw format (STRING_CMD_IMPORT_MISSING, word); + + std::cout << format (STRING_CMD_IMPORT_FILE, word) << "\n"; + + // Load the file. + std::string json; + incoming.read (json); + if (nontrivial (json)) + count += import (json); + } + } + + context.footnote (format (STRING_CMD_IMPORT_SUMMARY, count)); + return rc; +} - std::vector ::iterator word; - for (word = words.begin (); word != words.end (); ++word) +//////////////////////////////////////////////////////////////////////////////// +int CmdImport::import (const std::string& input) +{ + int count = 0; + try { - File incoming (*word); - if (! incoming.exists ()) - throw format (STRING_CMD_IMPORT_MISSING, *word); + json::value* root = json::parse (input); + if (root) + { + // Single object parse. Input looks like: + // { ... } + if (root->type () == json::j_object) + { + // For each object element... + json::object* root_obj = (json::object*)root; + importSingleTask (root_obj); + ++count; + } + + // Multiple object array. Input looks like: + // [ { ... } , { ... } ] + else if (root->type () == json::j_array) + { + json::array* root_arr = (json::array*)root; + + // For each object element... + for (auto& element : root_arr->_data) + { + // For each object element... + json::object* root_obj = (json::object*)element; + importSingleTask (root_obj); + ++count; + } + } - std::cout << format (STRING_CMD_IMPORT_FILE, *word) << "\n"; + delete root; + } + } - // Load the file. + // If an exception is caught, then it is because the free-form JSON + // objects/array above failed to parse. This is an indication that the input + // is an old-style line-by-line set of JSON objects, because both an array of + // objects, and a single object have failed to parse.. + // + // Input looks like: + // { ... } + // { ... } + catch (std::string& e) + { std::vector lines; - incoming.read (lines); + split (lines, input, '\n'); - std::vector ::iterator line; - for (line = lines.begin (); line != lines.end (); ++line) + for (auto& line : lines) { - std::string object = trimLeft ( - trimRight ( - trim (*line), - "]"), - "["); - // Skip blanks. May be caused by the trim calls above. - if (! object.length ()) - continue; - - // Parse the whole thing. - Task task (object); - - context.tdb2.add (task); - ++count; - std::cout << " " - << task.get ("uuid") - << " " - << task.get ("description") - << "\n"; + if (line.length ()) + { + json::value* root = json::parse (line); + if (root) + { + importSingleTask ((json::object*) root); + ++count; + delete root; + } + } } } - context.footnote (format (STRING_CMD_IMPORT_SUMMARY, count)); - return rc; + return count; +} + +//////////////////////////////////////////////////////////////////////////////// +void CmdImport::importSingleTask (json::object* obj) +{ + // Parse the whole thing, validate the data. + Task task (obj); + + bool hasGeneratedEntry = not task.has ("entry"); + bool hasExplicitEnd = task.has ("end"); + + task.validate (); + + bool hasGeneratedEnd = not hasExplicitEnd and task.has ("end"); + + // Check whether the imported task is new or a modified existing task. + Task before; + if (context.tdb2.get (task.get ("uuid"), before)) + { + // We need to neglect updates from attributes with dynamic defaults + // unless they have been explicitly specified on import. + // + // There are three attributes with dynamic defaults, besides uuid: + // - modified: Ignored in any case. + // - entry: Ignored if generated. + // - end: Ignored if generated. + + // The 'modified' attribute is ignored in any case, since if it + // were the only difference between the tasks, it would have been + // neglected anyway, since it is bumped on each modification. + task.set ("modified", before.get ("modified")); + + // Other generated values are replaced by values from existing task, + // so that they are ignored on comparison. + if (hasGeneratedEntry) + task.set ("entry", before.get ("entry")); + + if (hasGeneratedEnd) + task.set ("end", before.get ("end")); + + if (before != task) + { + CmdModify modHelper; + modHelper.checkConsistency (before, task); + modHelper.modifyAndUpdate (before, task); + std::cout << " mod "; + } + else + { + std::cout << " skip "; + } + } + else + { + context.tdb2.add (task); + std::cout << " add "; + } + + std::cout << task.get ("uuid") + << " " + << task.get ("description") + << "\n"; } //////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/commands/CmdImport.h task-2.5.0+dfsg/src/commands/CmdImport.h --- task-2.4.4+dfsg/src/commands/CmdImport.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdImport.h 2015-10-21 21:18:15.000000000 +0000 @@ -29,47 +29,18 @@ #include #include +#include class CmdImport : public Command { public: CmdImport (); int execute (std::string&); -}; - -/* -class CmdImport : public Command -{ -public: - CmdImport (); - int execute (std::string&); private: - enum fileType - { - type_not_a_clue, - type_task_1_4_3, - type_task_1_5_0, - type_task_1_6_0, - type_task_cmd_line, - type_todo_sh_2_0, - type_csv, - type_yaml, - type_text - }; - - fileType determineFileType (const std::vector &); - void decorateTask (Task&); - std::string task_1_4_3 (const std::vector &); - std::string task_1_5_0 (const std::vector &); - std::string task_1_6_0 (const std::vector &); - std::string taskCmdLine (const std::vector &); - std::string todoSh_2_0 (const std::vector &); - std::string text (const std::vector &); - std::string CSV (const std::vector &); - std::string YAML (const std::vector &); + int import (const std::string&); + void importSingleTask (json::object*); }; -*/ #endif //////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/commands/CmdInfo.cpp task-2.5.0+dfsg/src/commands/CmdInfo.cpp --- task-2.4.4+dfsg/src/commands/CmdInfo.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdInfo.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -30,8 +30,7 @@ #include #include #include -#include -#include +#include #include #include #include @@ -42,17 +41,23 @@ //////////////////////////////////////////////////////////////////////////////// CmdInfo::CmdInfo () { - _keyword = "information"; - _usage = "task information"; - _description = STRING_CMD_INFO_USAGE; - _read_only = true; + _keyword = "information"; + _usage = "task information"; + _description = STRING_CMD_INFO_USAGE; + _read_only = true; // This is inaccurate, but it does prevent a GC. While this doesn't make a // lot of sense, given that the info command shows the ID, it does mimic the // behavior of versions prior to 2.0, which the test suite relies upon. // // Once the test suite is completely modified, this can be corrected. - _displays_id = false; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = true; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::metadata; } //////////////////////////////////////////////////////////////////////////////// @@ -89,8 +94,7 @@ // Render each task. std::stringstream out; - std::vector ::iterator task; - for (task = filtered.begin (); task != filtered.end (); ++task) + for (auto& task : filtered) { ViewText view; view.width (context.getWidth ()); @@ -108,30 +112,29 @@ view.colorHeader (label); } - Date now; + ISO8601d now; // id int row = view.addRow (); view.set (row, 0, STRING_COLUMN_LABEL_ID); - view.set (row, 1, (task->id ? format (task->id) : "-")); + view.set (row, 1, (task.id ? format (task.id) : "-")); - std::string status = ucFirst (Task::statusToText (task->getStatus ())); // L10N safe ucFirst. + std::string status = ucFirst (Task::statusToText (task.getStatus ())); // L10N safe ucFirst. // description Color c; - autoColorize (*task, c); - std::string description = task->get ("description"); + autoColorize (task, c); + std::string description = task.get ("description"); int indent = context.config.getInteger ("indent.annotation"); std::map annotations; - task->getAnnotations (annotations); - std::map ::iterator ann; - for (ann = annotations.begin (); ann != annotations.end (); ++ann) + task.getAnnotations (annotations); + for (auto& anno : annotations) description += "\n" + std::string (indent, ' ') - + Date (ann->first.substr (11)).toString (dateformatanno) + + ISO8601d (anno.first.substr (11)).toString (dateformatanno) + " " - + ann->second; + + anno.second; row = view.addRow (); view.set (row, 0, STRING_COLUMN_LABEL_DESC); @@ -143,23 +146,22 @@ view.set (row, 1, status); // project - if (task->has ("project")) + if (task.has ("project")) { row = view.addRow (); view.set (row, 0, STRING_COLUMN_LABEL_PROJECT); - view.set (row, 1, task->get ("project")); + view.set (row, 1, task.get ("project")); } // dependencies: blocked { std::vector blocked; - dependencyGetBlocking (*task, blocked); + dependencyGetBlocking (task, blocked); if (blocked.size ()) { std::stringstream message; - std::vector ::const_iterator it; - for (it = blocked.begin (); it != blocked.end (); ++it) - message << it->id << " " << it->get ("description") << "\n"; + for (auto& block : blocked) + message << block.id << " " << block.get ("description") << "\n"; row = view.addRow (); view.set (row, 0, STRING_CMD_INFO_BLOCKED); @@ -170,13 +172,12 @@ // dependencies: blocking { std::vector blocking; - dependencyGetBlocked (*task, blocking); + dependencyGetBlocked (task, blocking); if (blocking.size ()) { std::stringstream message; - std::vector ::const_iterator it; - for (it = blocking.begin (); it != blocking.end (); ++it) - message << it->id << " " << it->get ("description") << "\n"; + for (auto& block : blocking) + message << block.id << " " << block.get ("description") << "\n"; row = view.addRow (); view.set (row, 0, STRING_CMD_INFO_BLOCKING); @@ -185,115 +186,115 @@ } // recur - if (task->has ("recur")) + if (task.has ("recur")) { row = view.addRow (); view.set (row, 0, STRING_COLUMN_LABEL_RECUR_L); - view.set (row, 1, task->get ("recur")); + view.set (row, 1, task.get ("recur")); } // parent - if (task->has ("parent")) + if (task.has ("parent")) { row = view.addRow (); view.set (row, 0, STRING_COLUMN_LABEL_PARENT); - view.set (row, 1, task->get ("parent")); + view.set (row, 1, task.get ("parent")); } // mask - if (task->has ("mask")) + if (task.has ("mask")) { row = view.addRow (); view.set (row, 0, STRING_COLUMN_LABEL_MASK); - view.set (row, 1, task->get ("mask")); + view.set (row, 1, task.get ("mask")); } // imask - if (task->has ("imask")) + if (task.has ("imask")) { row = view.addRow (); view.set (row, 0, STRING_COLUMN_LABEL_MASK_IDX); - view.set (row, 1, task->get ("imask")); + view.set (row, 1, task.get ("imask")); } // entry row = view.addRow (); view.set (row, 0, STRING_COLUMN_LABEL_ENTERED); - Date dt (task->get_date ("entry")); + ISO8601d dt (task.get_date ("entry")); std::string entry = dt.toString (dateformat); std::string age; - std::string created = task->get ("entry"); + std::string created = task.get ("entry"); if (created.length ()) { - Date dt (strtol (created.c_str (), NULL, 10)); - age = Duration (now - dt).format (); + ISO8601d dt (strtol (created.c_str (), NULL, 10)); + age = ISO8601p (now - dt).formatVague (); } view.set (row, 1, entry + " (" + age + ")"); // wait - if (task->has ("wait")) + if (task.has ("wait")) { row = view.addRow (); view.set (row, 0, STRING_COLUMN_LABEL_WAITING); - view.set (row, 1, Date (task->get_date ("wait")).toString (dateformat)); + view.set (row, 1, ISO8601d (task.get_date ("wait")).toString (dateformat)); } // scheduled - if (task->has ("scheduled")) + if (task.has ("scheduled")) { row = view.addRow (); view.set (row, 0, STRING_COLUMN_LABEL_SCHED); - view.set (row, 1, Date (task->get_date ("scheduled")).toString (dateformat)); + view.set (row, 1, ISO8601d (task.get_date ("scheduled")).toString (dateformat)); } // start - if (task->has ("start")) + if (task.has ("start")) { row = view.addRow (); view.set (row, 0, STRING_COLUMN_LABEL_START); - view.set (row, 1, Date (task->get_date ("start")).toString (dateformat)); + view.set (row, 1, ISO8601d (task.get_date ("start")).toString (dateformat)); } // due (colored) - if (task->has ("due")) + if (task.has ("due")) { row = view.addRow (); view.set (row, 0, STRING_COLUMN_LABEL_DUE); - view.set (row, 1, Date (task->get_date ("due")).toString (dateformat)); + view.set (row, 1, ISO8601d (task.get_date ("due")).toString (dateformat)); } // end - if (task->has ("end")) + if (task.has ("end")) { row = view.addRow (); view.set (row, 0, STRING_COLUMN_LABEL_END); - view.set (row, 1, Date (task->get_date ("end")).toString (dateformat)); + view.set (row, 1, ISO8601d (task.get_date ("end")).toString (dateformat)); } // until - if (task->has ("until")) + if (task.has ("until")) { row = view.addRow (); view.set (row, 0, STRING_CMD_INFO_UNTIL); - view.set (row, 1, Date (task->get_date ("until")).toString (dateformat)); + view.set (row, 1, ISO8601d (task.get_date ("until")).toString (dateformat)); } // modified - if (task->has ("modified")) + if (task.has ("modified")) { row = view.addRow (); view.set (row, 0, STRING_CMD_INFO_MODIFIED); - Date mod (task->get_date ("modified")); - std::string age = Duration (now - mod).format (); + ISO8601d mod (task.get_date ("modified")); + std::string age = ISO8601p (now - mod).formatVague (); view.set (row, 1, mod.toString (dateformat) + " (" + age + ")"); } // tags ... std::vector tags; - task->getTags (tags); + task.getTags (tags); if (tags.size ()) { std::string allTags; @@ -307,31 +308,38 @@ // Virtual tags. { // Note: This list must match that in Task::hasTag. + // Note: This list must match that in ::feedback_reserved_tags. 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 "; + 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 ("ORPHAN")) virtualTags += "ORPHAN "; + 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 ("UDA")) virtualTags += "UDA "; + 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 "; + if (task.hasTag ("LATEST")) virtualTags += "LATEST "; + if (task.hasTag ("PROJECT")) virtualTags += "PROJECT "; + if (task.hasTag ("PRIORITY")) virtualTags += "PRIORITY "; + // If you update the above list, update src/commands/CmdInfo.cpp and src/commands/CmdTags.cpp as well. row = view.addRow (); view.set (row, 0, STRING_CMD_INFO_VIRTUAL_TAGS); @@ -341,59 +349,61 @@ // uuid row = view.addRow (); view.set (row, 0, STRING_COLUMN_LABEL_UUID); - std::string uuid = task->get ("uuid"); + std::string uuid = task.get ("uuid"); view.set (row, 1, uuid); // Task::urgency row = view.addRow (); view.set (row, 0, STRING_COLUMN_LABEL_URGENCY); - view.set (row, 1, format (task->urgency (), 4, 4)); + view.set (row, 1, format (task.urgency (), 4, 4)); // Show any UDAs - std::vector all = task->all (); - std::vector ::iterator att; + std::vector all = task.all (); std::string type; - for (att = all.begin (); att != all.end (); ++att) + for (auto& att: all) { - type = context.config.get ("uda." + *att + ".type"); - if (type != "") + Column* col = context.columns[att]; + if (col && col->is_uda ()) { - Column* col = context.columns[*att]; - if (col) + std::string value = task.get (att); + if (value != "") { - std::string value = task->get (*att); - if (value != "") - { - row = view.addRow (); - view.set (row, 0, col->label ()); - - if (type == "date") - value = Date (value).toString (dateformat); - else if (type == "duration") - value = Duration (value).formatCompact (); + row = view.addRow (); + view.set (row, 0, col->label ()); - view.set (row, 1, value); + if (type == "date") + value = ISO8601d (value).toString (dateformat); + else if (type == "duration") + { + ISO8601p iso; + std::string::size_type cursor = 0; + if (iso.parse (value, cursor)) + value = (std::string) Variant ((time_t) iso, Variant::type_duration); + else + value = "PT0S"; } + + view.set (row, 1, value); } } } // Show any orphaned UDAs, which are identified by not being represented in // the context.columns map. - for (att = all.begin (); att != all.end (); ++att) + for (auto& att : all) { - if (att->substr (0, 11) != "annotation_" && - context.columns.find (*att) == context.columns.end ()) + if (att.substr (0, 11) != "annotation_" && + ! context.columns[att]) { row = view.addRow (); - view.set (row, 0, "[" + *att); - view.set (row, 1, task->get (*att) + "]"); + view.set (row, 0, "[" + att); + view.set (row, 1, task.get (att) + "]"); } } // Create a second table, containing urgency details, if necessary. ViewText urgencyDetails; - if (task->urgency () != 0.0) + if (task.urgency () != 0.0) { if (context.color ()) { @@ -413,74 +423,72 @@ urgencyDetails.add (Column::factory ("string", "")); // = urgencyDetails.add (Column::factory ("string", "")); // Result - urgencyTerm (urgencyDetails, "project", task->urgency_project (), Task::urgencyProjectCoefficient); - urgencyTerm (urgencyDetails, "active", task->urgency_active (), Task::urgencyActiveCoefficient); - urgencyTerm (urgencyDetails, "scheduled", task->urgency_scheduled (), Task::urgencyScheduledCoefficient); - urgencyTerm (urgencyDetails, "waiting", task->urgency_waiting (), Task::urgencyWaitingCoefficient); - urgencyTerm (urgencyDetails, "blocked", task->urgency_blocked (), Task::urgencyBlockedCoefficient); - urgencyTerm (urgencyDetails, "blocking", task->urgency_blocking (), Task::urgencyBlockingCoefficient); - urgencyTerm (urgencyDetails, "annotations", task->urgency_annotations (), Task::urgencyAnnotationsCoefficient); - urgencyTerm (urgencyDetails, "tags", task->urgency_tags (), Task::urgencyTagsCoefficient); - urgencyTerm (urgencyDetails, "next", task->urgency_next (), Task::urgencyNextCoefficient); - urgencyTerm (urgencyDetails, "due", task->urgency_due (), Task::urgencyDueCoefficient); - urgencyTerm (urgencyDetails, "age", task->urgency_age (), Task::urgencyAgeCoefficient); + urgencyTerm (urgencyDetails, "project", task.urgency_project (), Task::urgencyProjectCoefficient); + urgencyTerm (urgencyDetails, "active", task.urgency_active (), Task::urgencyActiveCoefficient); + urgencyTerm (urgencyDetails, "scheduled", task.urgency_scheduled (), Task::urgencyScheduledCoefficient); + urgencyTerm (urgencyDetails, "waiting", task.urgency_waiting (), Task::urgencyWaitingCoefficient); + urgencyTerm (urgencyDetails, "blocked", task.urgency_blocked (), Task::urgencyBlockedCoefficient); + urgencyTerm (urgencyDetails, "blocking", task.urgency_blocking (), Task::urgencyBlockingCoefficient); + urgencyTerm (urgencyDetails, "annotations", task.urgency_annotations (), Task::urgencyAnnotationsCoefficient); + urgencyTerm (urgencyDetails, "tags", task.urgency_tags (), Task::urgencyTagsCoefficient); + urgencyTerm (urgencyDetails, "due", task.urgency_due (), Task::urgencyDueCoefficient); + urgencyTerm (urgencyDetails, "age", task.urgency_age (), Task::urgencyAgeCoefficient); // Tag, Project- and UDA-specific coefficients. - std::map ::iterator var; - for (var = Task::coefficients.begin (); var != Task::coefficients.end (); ++var) + for (auto& var : Task::coefficients) { - if (var->first.substr (0, 13) == "urgency.user.") + if (var.first.substr (0, 13) == "urgency.user.") { // urgency.user.project..coefficient - std::string::size_type end = std::string::npos; - if (var->first.substr (13, 8) == "project." && - (end = var->first.find (".coefficient")) != std::string::npos) + auto end = std::string::npos; + if (var.first.substr (13, 8) == "project." && + (end = var.first.find (".coefficient")) != std::string::npos) { - std::string project = var->first.substr (21, end - 21); - if (task->get ("project").find (project) == 0) - urgencyTerm (urgencyDetails, "PROJECT " + project, 1.0, var->second); + std::string project = var.first.substr (21, end - 21); + if (task.get ("project").find (project) == 0) + urgencyTerm (urgencyDetails, "PROJECT " + project, 1.0, var.second); } // urgency.user.tag..coefficient - if (var->first.substr (13, 4) == "tag." && - (end = var->first.find (".coefficient")) != std::string::npos) + if (var.first.substr (13, 4) == "tag." && + (end = var.first.find (".coefficient")) != std::string::npos) { - std::string name = var->first.substr (17, end - 17); - if (task->hasTag (name)) - urgencyTerm (urgencyDetails, "TAG " + name, 1.0, var->second); + std::string name = var.first.substr (17, end - 17); + if (task.hasTag (name)) + urgencyTerm (urgencyDetails, "TAG " + name, 1.0, var.second); } // urgency.user.keyword..coefficient - if (var->first.substr (13, 8) == "keyword." && - (end = var->first.find (".coefficient")) != std::string::npos) + if (var.first.substr (13, 8) == "keyword." && + (end = var.first.find (".coefficient")) != std::string::npos) { - std::string keyword = var->first.substr (21, end - 21); - if (task->get ("description").find (keyword) != std::string::npos) - urgencyTerm (urgencyDetails, "KEYWORD " + keyword, 1.0, var->second); + std::string keyword = var.first.substr (21, end - 21); + if (task.get ("description").find (keyword) != std::string::npos) + urgencyTerm (urgencyDetails, "KEYWORD " + keyword, 1.0, var.second); } } // urgency.uda..coefficient - else if (var->first.substr (0, 12) == "urgency.uda.") + else if (var.first.substr (0, 12) == "urgency.uda.") { // urgency.uda..coefficient // urgency.uda...coefficient - std::string::size_type end = var->first.find (".coefficient"); + auto end = var.first.find (".coefficient"); if (end != std::string::npos) { - const std::string uda = var->first.substr (12, end - 12); - std::string::size_type dot = uda.find ("."); + const std::string uda = var.first.substr (12, end - 12); + auto dot = uda.find ("."); if (dot == std::string::npos) { // urgency.uda..coefficient - if (task->has (uda)) - urgencyTerm (urgencyDetails, std::string ("UDA ") + uda, 1.0, var->second); + if (task.has (uda)) + urgencyTerm (urgencyDetails, std::string ("UDA ") + uda, 1.0, var.second); } else { // urgency.uda...coefficient - if (task->get (uda.substr(0, dot)) == uda.substr(dot+1)) - urgencyTerm (urgencyDetails, std::string ("UDA ") + uda, 1.0, var->second); + if (task.get (uda.substr(0, dot)) == uda.substr(dot+1)) + urgencyTerm (urgencyDetails, std::string ("UDA ") + uda, 1.0, var.second); } } } @@ -489,7 +497,7 @@ row = urgencyDetails.addRow (); urgencyDetails.set (row, 5, rightJustify ("------", 6)); row = urgencyDetails.addRow (); - urgencyDetails.set (row, 5, rightJustify (format (task->urgency (), 4, 4), 6)); + urgencyDetails.set (row, 5, rightJustify (format (task.urgency (), 4, 4), 6)); } // Create a third table, containing undo log change details. @@ -535,7 +543,7 @@ { int row = journal.addRow (); - Date timestamp (strtol (when.substr (5).c_str (), NULL, 10)); + ISO8601d timestamp (strtol (when.substr (5).c_str (), NULL, 10)); journal.set (row, 0, timestamp.toString (dateformat)); Task before (previous.substr (4)); diff -Nru task-2.4.4+dfsg/src/commands/CmdInstall.cpp task-2.5.0+dfsg/src/commands/CmdInstall.cpp --- task-2.4.4+dfsg/src/commands/CmdInstall.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdInstall.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,56 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// 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 -#include -#include -#include -#include - -extern Context context; - -//////////////////////////////////////////////////////////////////////////////// -CmdInstall::CmdInstall () -{ - _keyword = "install"; - _usage = "task install [ ...]"; - _description = STRING_CMD_INSTALL_USAGE; - _read_only = true; - _displays_id = false; -} - -//////////////////////////////////////////////////////////////////////////////// -// Algorithm: -// Copy file rc.data.location/extensions -// Generate UUID -// Call the "install" function once, store results in rc: -// extension.= -int CmdInstall::execute (std::string&) -{ - return 1; -} - -//////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/commands/CmdInstall.h task-2.5.0+dfsg/src/commands/CmdInstall.h --- task-2.4.4+dfsg/src/commands/CmdInstall.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdInstall.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// 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 -// -//////////////////////////////////////////////////////////////////////////////// - -#ifndef INCLUDED_CMDINSTALL -#define INCLUDED_CMDINSTALL - -#include -#include - -class CmdInstall : public Command -{ -public: - CmdInstall (); - int execute (std::string&); -}; - -#endif -//////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/commands/CmdLog.cpp task-2.5.0+dfsg/src/commands/CmdLog.cpp --- task-2.4.4+dfsg/src/commands/CmdLog.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdLog.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -37,38 +37,44 @@ //////////////////////////////////////////////////////////////////////////////// CmdLog::CmdLog () { - _keyword = "log"; - _usage = "task log "; - _description = STRING_CMD_LOG_USAGE; - _read_only = false; - _displays_id = false; + _keyword = "log"; + _usage = "task log "; + _description = STRING_CMD_LOG_USAGE; + _read_only = false; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = false; + _accepts_modifications = true; + _accepts_miscellaneous = false; + _category = Command::Category::operation; } //////////////////////////////////////////////////////////////////////////////// int CmdLog::execute (std::string& output) { - int rc = 0; - // Apply the command line modifications to the new task. Task task; task.modify (Task::modReplace, true); task.setStatus (Task::completed); - // Recurring tasks get a special status. + // Cannot log recurring tasks. if (task.has ("recur")) throw std::string (STRING_CMD_LOG_NO_RECUR); + // Cannot log waiting tasks. if (task.has ("wait")) throw std::string (STRING_CMD_LOG_NO_WAITING); context.tdb2.add (task); + if (context.verbose ("project")) context.footnote (onProjectChange (task)); - if (context.verbose ("affected")) - output = std::string (STRING_CMD_LOG_LOGGED) + "\n"; + if (context.verbose ("new-uuid")) + output = format (STRING_CMD_LOG_LOGGED, task.get ("uuid")) + "\n"; - return rc; + return 0; } //////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/commands/CmdLogo.cpp task-2.5.0+dfsg/src/commands/CmdLogo.cpp --- task-2.4.4+dfsg/src/commands/CmdLogo.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdLogo.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -35,11 +35,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdLogo::CmdLogo () { - _keyword = "logo"; - _usage = "task logo"; - _description = STRING_CMD_LOGO_USAGE; - _read_only = true; - _displays_id = false; + _keyword = "logo"; + _usage = "task logo"; + _description = STRING_CMD_LOGO_USAGE; + _read_only = true; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = false; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::misc; } //////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/commands/CmdModify.cpp task-2.5.0+dfsg/src/commands/CmdModify.cpp --- task-2.4.4+dfsg/src/commands/CmdModify.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdModify.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -39,15 +39,21 @@ //////////////////////////////////////////////////////////////////////////////// CmdModify::CmdModify () { - _keyword = "modify"; - _usage = "task modify "; - _description = STRING_CMD_MODIFY_USAGE1; - _read_only = false; - _displays_id = false; + _keyword = "modify"; + _usage = "task modify "; + _description = STRING_CMD_MODIFY_USAGE1; + _read_only = false; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = true; + _accepts_modifications = true; + _accepts_miscellaneous = false; + _category = Command::Category::operation; } //////////////////////////////////////////////////////////////////////////////// -int CmdModify::execute (std::string& output) +int CmdModify::execute (std::string&) { int rc = 0; int count = 0; @@ -62,112 +68,32 @@ return 1; } - // TODO Complain when no modifications are specified. - // Accumulated project change notifications. std::map projectChanges; - std::vector ::iterator task; - for (task = filtered.begin (); task != filtered.end (); ++task) + for (auto& task : filtered) { - Task before (*task); - task->modify (Task::modReplace); + Task before (task); + task.modify (Task::modReplace); - if (taskDiff (before, *task)) + if (before != task) { - // Perform some logical consistency checks. - if (task->has ("recur") && - !task->has ("due") && - !before.has ("due")) - throw std::string (STRING_CMD_MODIFY_NO_DUE); - - if (before.has ("recur") && - before.has ("due") && - (!task->has ("due") || - task->get ("due") == "")) - throw std::string (STRING_CMD_MODIFY_REM_DUE); - - if (before.has ("recur") && - (!task->has ("recur") || - task->get ("recur") == "")) - throw std::string (STRING_CMD_MODIFY_REC_ALWAYS); + // Abort if change introduces inconsistencies. + checkConsistency(before, task); - // Delete the specified task. std::string question; - if (task->id != 0) + if (task.id != 0) question = format (STRING_CMD_MODIFY_CONFIRM, - task->id, - task->get ("description")); + task.id, + task.get ("description")); else question = format (STRING_CMD_MODIFY_CONFIRM, - task->get ("uuid"), - task->get ("description")); + task.get ("uuid"), + task.get ("description")); - if (permission (*task, taskDifferences (before, *task) + question, filtered.size ())) + if (permission (taskDifferences (before, task) + question, filtered.size ())) { - updateRecurrenceMask (*task); - dependencyChainOnModify (before, *task); - ++count; - feedback_affected (STRING_CMD_MODIFY_TASK, *task); - feedback_unblocked (*task); - context.tdb2.modify (*task); - if (context.verbose ("project")) - projectChanges[task->get ("project")] = onProjectChange (before, *task); - - // Task potentially has siblings - modify them. - if (task->has ("parent")) - { - if ((context.config.get ("recurrence.confirmation") == "prompt" - && confirm (STRING_CMD_MODIFY_RECUR)) || - context.config.getBoolean ("recurrence.confirmation")) - { - std::vector siblings = context.tdb2.siblings (*task); - std::vector ::iterator sibling; - for (sibling = siblings.begin (); sibling != siblings.end (); ++sibling) - { - Task alternate (*sibling); - sibling->modify (Task::modReplace); - updateRecurrenceMask (*sibling); - dependencyChainOnModify (alternate, *sibling); - ++count; - feedback_affected (STRING_CMD_MODIFY_TASK_R, *sibling); - feedback_unblocked (*sibling); - context.tdb2.modify (*sibling); - if (context.verbose ("project")) - projectChanges[sibling->get ("project")] = onProjectChange (alternate, *sibling); - } - - // Modify the parent - Task parent; - context.tdb2.get (task->get ("parent"), parent); - parent.modify (Task::modReplace); - context.tdb2.modify (parent); - } - } - - // Task potentially has child tasks - modify them. - else if (task->get ("status") == "recurring") - { - std::vector children = context.tdb2.children (*task); - if (children.size () && - (! context.config.getBoolean ("recurrence.confirmation") || - confirm (STRING_CMD_MODIFY_RECUR))) - { - std::vector ::iterator child; - for (child = children.begin (); child != children.end (); ++child) - { - Task alternate (*child); - child->modify (Task::modReplace); - updateRecurrenceMask (*child); - context.tdb2.modify (*child); - dependencyChainOnModify (alternate, *child); - if (context.verbose ("project")) - projectChanges[child->get ("project")] = onProjectChange (alternate, *child); - ++count; - feedback_affected (STRING_CMD_MODIFY_TASK_R, *child); - } - } - } + count += modifyAndUpdate (before, task, &projectChanges); } else { @@ -180,13 +106,126 @@ } // Now list the project changes. - std::map ::iterator i; - for (i = projectChanges.begin (); i != projectChanges.end (); ++i) - if (i->first != "") - context.footnote (i->second); + for (auto& change : projectChanges) + if (change.first != "") + context.footnote (change.second); feedback_affected (count == 1 ? STRING_CMD_MODIFY_1 : STRING_CMD_MODIFY_N, count); return rc; } //////////////////////////////////////////////////////////////////////////////// +void CmdModify::checkConsistency (Task &before, Task &after) +{ + // Perform some logical consistency checks. + if (after.has ("recur") && + !after.has ("due") && + !before.has ("due")) + throw std::string (STRING_CMD_MODIFY_NO_DUE); + + if (before.has ("recur") && + before.has ("due") && + (!after.has ("due") || + after.get ("due") == "")) + throw std::string (STRING_CMD_MODIFY_REM_DUE); + + if (before.has ("recur") && + (!after.has ("recur") || + after.get ("recur") == "")) + throw std::string (STRING_CMD_MODIFY_REC_ALWAYS); +} + +//////////////////////////////////////////////////////////////////////////////// +int CmdModify::modifyAndUpdate ( + Task &before, Task &after, + std::map *projectChanges /* = NULL */) +{ + int count = 0; + + updateRecurrenceMask (after); + ++count; + feedback_affected (STRING_CMD_MODIFY_TASK, after); + feedback_unblocked (after); + context.tdb2.modify (after); + if (context.verbose ("project") && projectChanges) + (*projectChanges)[after.get ("project")] = onProjectChange (before, after); + + if (after.has ("parent")) + { + // Task has siblings - modify them. + count += modifyRecurrenceSiblings (after, projectChanges); + } + else if (after.get ("status") == "recurring") + { + // Task has child tasks - modify them. + count += modifyRecurrenceParent (after, projectChanges); + } + + return count; +} + +//////////////////////////////////////////////////////////////////////////////// +int CmdModify::modifyRecurrenceSiblings ( + Task &task, + std::map *projectChanges /* = NULL */) +{ + int count = 0; + + if ((context.config.get ("recurrence.confirmation") == "prompt" + && confirm (STRING_CMD_MODIFY_RECUR)) || + context.config.getBoolean ("recurrence.confirmation")) + { + std::vector siblings = context.tdb2.siblings (task); + for (auto& sibling : siblings) + { + Task alternate (sibling); + sibling.modify (Task::modReplace); + updateRecurrenceMask (sibling); + ++count; + feedback_affected (STRING_CMD_MODIFY_TASK_R, sibling); + feedback_unblocked (sibling); + context.tdb2.modify (sibling); + if (context.verbose ("project") && projectChanges) + (*projectChanges)[sibling.get ("project")] = onProjectChange (alternate, sibling); + } + + // Modify the parent + Task parent; + context.tdb2.get (task.get ("parent"), parent); + parent.modify (Task::modReplace); + context.tdb2.modify (parent); + } + + return count; +} + +//////////////////////////////////////////////////////////////////////////////// +int CmdModify::modifyRecurrenceParent ( + Task &task, + std::map *projectChanges /* = NULL */) +{ + int count = 0; + + std::vector children = context.tdb2.children (task); + if (children.size () && + (! context.config.getBoolean ("recurrence.confirmation") || + confirm (STRING_CMD_MODIFY_RECUR))) + { + for (auto& child : children) + { + Task alternate (child); + child.modify (Task::modReplace); + updateRecurrenceMask (child); + context.tdb2.modify (child); + if (context.verbose ("project") && projectChanges) + (*projectChanges)[child.get ("project")] = onProjectChange (alternate, child); + ++count; + feedback_affected (STRING_CMD_MODIFY_TASK_R, child); + } + } + + return count; +} + +//////////////////////////////////////////////////////////////////////////////// + diff -Nru task-2.4.4+dfsg/src/commands/CmdModify.h task-2.5.0+dfsg/src/commands/CmdModify.h --- task-2.4.4+dfsg/src/commands/CmdModify.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdModify.h 2015-10-21 21:18:15.000000000 +0000 @@ -35,6 +35,13 @@ public: CmdModify (); int execute (std::string&); + void checkConsistency (Task &before, Task &after); + int modifyAndUpdate (Task &before, Task &after, + std::map *projectChanges = NULL); + int modifyRecurrenceSiblings (Task &task, + std::map *projectChanges = NULL); + int modifyRecurrenceParent (Task &task, + std::map *projectChanges = NULL); }; #endif diff -Nru task-2.4.4+dfsg/src/commands/CmdPrepend.cpp task-2.5.0+dfsg/src/commands/CmdPrepend.cpp --- task-2.4.4+dfsg/src/commands/CmdPrepend.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdPrepend.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -39,15 +39,21 @@ //////////////////////////////////////////////////////////////////////////////// CmdPrepend::CmdPrepend () { - _keyword = "prepend"; - _usage = "task prepend "; - _description = STRING_CMD_PREPEND_USAGE; - _read_only = false; - _displays_id = false; + _keyword = "prepend"; + _usage = "task prepend "; + _description = STRING_CMD_PREPEND_USAGE; + _read_only = false; + _displays_id = false; + _needs_gc = false; + _uses_context = true; + _accepts_filter = true; + _accepts_modifications = true; + _accepts_miscellaneous = false; + _category = Command::Category::operation; } //////////////////////////////////////////////////////////////////////////////// -int CmdPrepend::execute (std::string& output) +int CmdPrepend::execute (std::string&) { int rc = 0; int count = 0; @@ -67,46 +73,44 @@ // Accumulated project change notifications. std::map projectChanges; - std::vector ::iterator task; - for (task = filtered.begin (); task != filtered.end (); ++task) + for (auto& task : filtered) { - Task before (*task); + Task before (task); // Prepend to the specified task. std::string question = format (STRING_CMD_PREPEND_CONFIRM, - task->id, - task->get ("description")); + task.id, + task.get ("description")); - task->modify (Task::modPrepend, true); + task.modify (Task::modPrepend, true); - if (permission (*task, taskDifferences (before, *task) + question, filtered.size ())) + if (permission (taskDifferences (before, task) + question, filtered.size ())) { - context.tdb2.modify (*task); + context.tdb2.modify (task); ++count; - feedback_affected (STRING_CMD_PREPEND_TASK, *task); + feedback_affected (STRING_CMD_PREPEND_TASK, task); if (context.verbose ("project")) - projectChanges[task->get ("project")] = onProjectChange (*task, false); + projectChanges[task.get ("project")] = onProjectChange (task, false); // Prepend to siblings. - if (task->has ("parent")) + if (task.has ("parent")) { if ((context.config.get ("recurrence.confirmation") == "prompt" && confirm (STRING_CMD_PREPEND_CONFIRM_R)) || context.config.getBoolean ("recurrence.confirmation")) { - std::vector siblings = context.tdb2.siblings (*task); - std::vector ::iterator sibling; - for (sibling = siblings.begin (); sibling != siblings.end (); ++sibling) + std::vector siblings = context.tdb2.siblings (task); + for (auto& sibling : siblings) { - sibling->modify (Task::modPrepend, true); - context.tdb2.modify (*sibling); + sibling.modify (Task::modPrepend, true); + context.tdb2.modify (sibling); ++count; - feedback_affected (STRING_CMD_PREPEND_TASK_R, *sibling); + feedback_affected (STRING_CMD_PREPEND_TASK_R, sibling); } // Prepend to the parent Task parent; - context.tdb2.get (task->get ("parent"), parent); + context.tdb2.get (task.get ("parent"), parent); parent.modify (Task::modPrepend, true); context.tdb2.modify (parent); } @@ -122,10 +126,9 @@ } // Now list the project changes. - std::map ::iterator i; - for (i = projectChanges.begin (); i != projectChanges.end (); ++i) - if (i->first != "") - context.footnote (i->second); + for (auto& change : projectChanges) + if (change.first != "") + context.footnote (change.second); feedback_affected (count == 1 ? STRING_CMD_PREPEND_1 : STRING_CMD_PREPEND_N, count); return rc; diff -Nru task-2.4.4+dfsg/src/commands/CmdProjects.cpp task-2.5.0+dfsg/src/commands/CmdProjects.cpp --- task-2.4.4+dfsg/src/commands/CmdProjects.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdProjects.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -41,11 +41,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdProjects::CmdProjects () { - _keyword = "projects"; - _usage = "task projects"; - _description = STRING_CMD_PROJECTS_USAGE; - _read_only = true; - _displays_id = false; + _keyword = "projects"; + _usage = "task projects"; + _description = STRING_CMD_PROJECTS_USAGE; + _read_only = true; + _displays_id = false; + _needs_gc = true; + _uses_context = true; + _accepts_filter = true; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::metadata; } //////////////////////////////////////////////////////////////////////////////// @@ -53,26 +59,18 @@ { int rc = 0; - // Enforce the garbage collector to show correct task counts - context.tdb2.gc (); - // Get all the tasks. handleRecurrence (); - std::vector tasks = context.tdb2.pending.get_tasks (); + auto tasks = context.tdb2.pending.get_tasks (); if (context.config.getBoolean ("list.all.projects")) - { - std::vector extra = context.tdb2.completed.get_tasks (); - std::vector ::iterator task; - for (task = extra.begin (); task != extra.end (); ++task) - tasks.push_back (*task); - } + for (auto& task : context.tdb2.completed.get_tasks ()) + tasks.push_back (task); // Apply the filter. Filter filter; std::vector filtered; filter.subset (tasks, filtered); - int quantity = filtered.size (); std::stringstream out; @@ -82,10 +80,9 @@ std::map unique; bool no_project = false; std::string project; - std::vector ::iterator task; - for (task = filtered.begin (); task != filtered.end (); ++task) + for (auto& task : filtered) { - if (task->getStatus () == Task::deleted) + if (task.getStatus () == Task::deleted) { --quantity; continue; @@ -93,14 +90,13 @@ // Increase the count for the project the task belongs to and all // its super-projects - project = task->get ("project"); + project = task.get ("project"); std::vector projects = extractParents (project); projects.push_back (project); - std::vector ::const_iterator parent; - for (parent = projects.begin (); parent != projects.end (); ++parent) - unique[*parent] += 1; + for (auto& parent : projects) + unique[parent] += 1; if (project == "") no_project = true; @@ -118,27 +114,24 @@ view.colorHeader (label); std::vector processed; - std::map ::iterator project; - for (project = unique.begin (); project != unique.end (); ++project) + for (auto& project : unique) { - const std::vector parents = extractParents (project->first); - std::vector ::const_iterator parent; - for (parent = parents.begin (); parent != parents.end (); parent++) + const std::vector parents = extractParents (project.first); + for (auto& parent : parents) { - if (std::find (processed.begin (), processed.end (), *parent) - == processed.end ()) + if (std::find (processed.begin (), processed.end (), parent) == processed.end ()) { int row = view.addRow (); - view.set (row, 0, indentProject (*parent)); - processed.push_back (*parent); + view.set (row, 0, indentProject (parent)); + processed.push_back (parent); } } int row = view.addRow (); - view.set (row, 0, (project->first == "" + view.set (row, 0, (project.first == "" ? STRING_CMD_PROJECTS_NONE - : indentProject (project->first, " ", '.'))); - view.set (row, 1, project->second); - processed.push_back (project->first); + : indentProject (project.first, " ", '.'))); + view.set (row, 1, project.second); + processed.push_back (project.first); } int number_projects = unique.size (); @@ -170,11 +163,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdCompletionProjects::CmdCompletionProjects () { - _keyword = "_projects"; - _usage = "task _projects"; - _description = STRING_CMD_PROJECTS_USAGE_2; - _read_only = true; - _displays_id = false; + _keyword = "_projects"; + _usage = "task _projects"; + _description = STRING_CMD_PROJECTS_USAGE_2; + _read_only = true; + _displays_id = false; + _needs_gc = true; + _uses_context = false; + _accepts_filter = true; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::internal; } //////////////////////////////////////////////////////////////////////////////// @@ -182,15 +181,11 @@ { // Get all the tasks. handleRecurrence (); - std::vector tasks = context.tdb2.pending.get_tasks (); + auto tasks = context.tdb2.pending.get_tasks (); if (context.config.getBoolean ("list.all.projects")) - { - std::vector extra = context.tdb2.completed.get_tasks (); - std::vector ::iterator task; - for (task = extra.begin (); task != extra.end (); ++task) - tasks.push_back (*task); - } + for (auto& task : context.tdb2.completed.get_tasks ()) + tasks.push_back (task); // Apply the filter. Filter filter; @@ -200,14 +195,12 @@ // Scan all the tasks for their project name, building a map using project // names as keys. std::map unique; - std::vector ::iterator task; - for (task = filtered.begin (); task != filtered.end (); ++task) - unique[task->get ("project")] = 0; - - std::map ::iterator project; - for (project = unique.begin (); project != unique.end (); ++project) - if (project->first.length ()) - output += project->first + "\n"; + for (auto& task : filtered) + unique[task.get ("project")] = 0; + + for (auto& project : unique) + if (project.first.length ()) + output += project.first + "\n"; return 0; } diff -Nru task-2.4.4+dfsg/src/commands/CmdReports.cpp task-2.5.0+dfsg/src/commands/CmdReports.cpp --- task-2.4.4+dfsg/src/commands/CmdReports.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdReports.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -38,11 +38,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdReports::CmdReports () { - _keyword = "reports"; - _usage = "task reports"; - _description = STRING_CMD_REPORTS_USAGE; - _read_only = true; - _displays_id = false; + _keyword = "reports"; + _usage = "task reports"; + _description = STRING_CMD_REPORTS_USAGE; + _read_only = true; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = false; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::config; } //////////////////////////////////////////////////////////////////////////////// @@ -51,13 +57,12 @@ std::vector reports; // Add custom reports. - Config::const_iterator i; - for (i = context.config.begin (); i != context.config.end (); ++i) + for (auto& i : context.config) { - if (i->first.substr (0, 7) == "report.") + if (i.first.substr (0, 7) == "report.") { - std::string report = i->first.substr (7); - std::string::size_type columns = report.find (".columns"); + std::string report = i.first.substr (7); + auto columns = report.find (".columns"); if (columns != std::string::npos) reports.push_back (report.substr (0, columns)); } @@ -96,12 +101,11 @@ view.intraColorOdd (alternate); } - std::vector ::iterator report; - for (report = reports.begin (); report != reports.end (); ++report) + for (auto& report : reports) { int row = view.addRow (); - view.set (row, 0, *report); - view.set (row, 1, context.commands[*report]->description ()); + view.set (row, 0, report); + view.set (row, 1, context.commands[report]->description ()); } out << optionalBlankLine () diff -Nru task-2.4.4+dfsg/src/commands/CmdShow.cpp task-2.5.0+dfsg/src/commands/CmdShow.cpp --- task-2.4.4+dfsg/src/commands/CmdShow.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdShow.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include @@ -41,11 +41,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdShow::CmdShow () { - _keyword = "show"; - _usage = "task show [all | substring]"; - _description = STRING_CMD_SHOW; - _read_only = true; - _displays_id = false; + _keyword = "show"; + _usage = "task show [all | substring]"; + _description = STRING_CMD_SHOW; + _read_only = true; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = false; + _accepts_modifications = false; + _accepts_miscellaneous = true; + _category = Command::Category::config; } //////////////////////////////////////////////////////////////////////////////// @@ -56,7 +62,7 @@ // Obtain the arguments from the description. That way, things like '--' // have already been handled. - std::vector words = context.cli.getWords (); + std::vector words = context.cli2.getWords (); if (words.size () > 1) throw std::string (STRING_CMD_SHOW_ARGS); @@ -162,6 +168,7 @@ " journal.time.start.annotation" " journal.time.stop.annotation" " json.array" + " json.depends.array" " list.all.projects" " list.all.tags" " locking" @@ -176,9 +183,11 @@ " regex" " reserved.lines" " row.padding" + " rule.color.merge" " rule.precedence.color" " search.case.sensitive" " shell.prompt" + " sugar" " summary.all.projects" " tag.indicator" " taskd.server" @@ -194,14 +203,13 @@ " urgency.annotations.coefficient" " urgency.blocked.coefficient" " urgency.blocking.coefficient" - " urgency.inherit.coefficient" " urgency.due.coefficient" - " urgency.next.coefficient" " urgency.project.coefficient" " urgency.tags.coefficient" " urgency.waiting.coefficient" " urgency.age.coefficient" " urgency.age.max" + " urgency.inherit" " verbose" " weekstart" " xterm.title" @@ -213,33 +221,32 @@ recognized += "_forcecolor "; std::vector unrecognized; - Config::const_iterator i; - for (i = context.config.begin (); i != context.config.end (); ++i) + for (auto& i : context.config) { // Disallow partial matches by tacking a leading and trailing space on each // variable name. - std::string pattern = " " + i->first + " "; + std::string pattern = " " + i.first + " "; if (recognized.find (pattern) == std::string::npos) { // These are special configuration variables, because their name is // dynamic. - if (i->first.substr (0, 14) != "color.keyword." && - 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." && - i->first.substr (0, 5) != "hook." && - i->first.substr (0, 4) != "uda." && - i->first.substr (0, 8) != "default." && - i->first.substr (0, 21) != "urgency.user.project." && - i->first.substr (0, 17) != "urgency.user.tag." && - i->first.substr (0, 21) != "urgency.user.keyword." && - i->first.substr (0, 12) != "urgency.uda.") + if (i.first.substr (0, 14) != "color.keyword." && + 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." && + i.first.substr (0, 5) != "hook." && + i.first.substr (0, 4) != "uda." && + i.first.substr (0, 8) != "default." && + i.first.substr (0, 21) != "urgency.user.project." && + i.first.substr (0, 17) != "urgency.user.tag." && + i.first.substr (0, 21) != "urgency.user.keyword." && + i.first.substr (0, 12) != "urgency.uda.") { - unrecognized.push_back (i->first); + unrecognized.push_back (i.first); } } } @@ -249,9 +256,9 @@ Config default_config; default_config.setDefaults (); - for (i = context.config.begin (); i != context.config.end (); ++i) - if (i->second != default_config.get (i->first)) - default_values.push_back (i->first); + for (auto& i : context.config) + if (i.second != default_config.get (i.first)) + default_values.push_back (i.first); // Create output view. ViewText view; @@ -278,35 +285,35 @@ section = ""; std::string::size_type loc; - for (i = context.config.begin (); i != context.config.end (); ++i) + for (auto& i : context.config) { - loc = i->first.find (section, 0); + loc = i.first.find (section, 0); if (loc != std::string::npos) { // Look for unrecognized. Color color; - if (std::find (unrecognized.begin (), unrecognized.end (), i->first) != unrecognized.end ()) + if (std::find (unrecognized.begin (), unrecognized.end (), i.first) != unrecognized.end ()) { issue_error = true; color = error; } - else if (std::find (default_values.begin (), default_values.end (), i->first) != default_values.end ()) + else if (std::find (default_values.begin (), default_values.end (), i.first) != default_values.end ()) { issue_warning = true; color = warning; } - std::string value = i->second; + std::string value = i.second; int row = view.addRow (); - view.set (row, 0, i->first, color); + view.set (row, 0, i.first, color); view.set (row, 1, value, color); - if (default_config[i->first] != value && - default_config[i->first] != "") + if (default_config[i.first] != value && + default_config[i.first] != "") { row = view.addRow (); view.set (row, 0, std::string (" ") + STRING_CMD_SHOW_CONF_DEFAULT, color); - view.set (row, 1, default_config[i->first], color); + view.set (row, 1, default_config[i.first], color); } } } @@ -318,7 +325,7 @@ if (issue_warning) { - out << STRING_CMD_SHOW_DIFFER; + out << STRING_CMD_SHOW_DIFFER << "\n"; if (context.color ()) out << " " @@ -331,9 +338,8 @@ { out << STRING_CMD_SHOW_UNREC << "\n"; - std::vector ::iterator i; - for (i = unrecognized.begin (); i != unrecognized.end (); ++i) - out << " " << *i << "\n"; + for (auto& i : unrecognized) + out << " " << i << "\n"; if (context.color ()) out << "\n" << format (STRING_CMD_SHOW_DIFFER_COLOR, error.colorize ("color")); @@ -342,7 +348,6 @@ } out << legacyCheckForDeprecatedVariables (); - out << legacyCheckForDeprecatedColor (); out << legacyCheckForDeprecatedColumns (); // TODO Check for referenced but missing theme files. @@ -395,6 +400,7 @@ _description = STRING_CMD_SHOWRAW; _read_only = true; _displays_id = false; + _category = Command::Category::internal; } //////////////////////////////////////////////////////////////////////////////// @@ -408,10 +414,9 @@ std::sort (all.begin (), all.end ()); // Display them all. - std::vector ::iterator i; std::stringstream out; - for (i = all.begin (); i != all.end (); ++i) - out << *i << '=' << context.config.get (*i) << "\n"; + for (auto& i : all) + out << i << '=' << context.config.get (i) << "\n"; output = out.str (); return 0; diff -Nru task-2.4.4+dfsg/src/commands/CmdStart.cpp task-2.5.0+dfsg/src/commands/CmdStart.cpp --- task-2.4.4+dfsg/src/commands/CmdStart.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdStart.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -39,15 +39,21 @@ //////////////////////////////////////////////////////////////////////////////// CmdStart::CmdStart () { - _keyword = "start"; - _usage = "task start "; - _description = STRING_CMD_START_USAGE; - _read_only = false; - _displays_id = false; + _keyword = "start"; + _usage = "task start "; + _description = STRING_CMD_START_USAGE; + _read_only = false; + _displays_id = false; + _needs_gc = false; + _uses_context = true; + _accepts_filter = true; + _accepts_modifications = true; + _accepts_miscellaneous = false; + _category = Command::Category::operation; } //////////////////////////////////////////////////////////////////////////////// -int CmdStart::execute (std::string& output) +int CmdStart::execute (std::string&) { int rc = 0; int count = 0; @@ -66,34 +72,40 @@ std::map projectChanges; bool nagged = false; - std::vector ::iterator task; - for (task = filtered.begin (); task != filtered.end (); ++task) + for (auto& task : filtered) { - if (! task->has ("start")) + if (! task.has ("start")) { - Task before (*task); + Task before (task); // Start the specified task. std::string question = format (STRING_CMD_START_CONFIRM, - task->id, - task->get ("description")); - task->modify (Task::modAnnotate); - task->setAsNow ("start"); + task.id, + task.get ("description")); + task.modify (Task::modAnnotate); + task.setAsNow ("start"); + + Task::status status = task.getStatus (); + if (status == Task::completed || status == Task::deleted) + { + // "waiting" handled by Task::validate(), no special care needed here. + task.setStatus (Task::pending); + } if (context.config.getBoolean ("journal.time")) - task->addAnnotation (context.config.get ("journal.time.start.annotation")); + task.addAnnotation (context.config.get ("journal.time.start.annotation")); - if (permission (*task, taskDifferences (before, *task) + question, filtered.size ())) + if (permission (taskDifferences (before, task) + question, filtered.size ())) { - updateRecurrenceMask (*task); - context.tdb2.modify (*task); + updateRecurrenceMask (task); + context.tdb2.modify (task); ++count; - feedback_affected (STRING_CMD_START_TASK, *task); + feedback_affected (STRING_CMD_START_TASK, task); if (!nagged) - nagged = nag (*task); - dependencyChainOnStart (*task); + nagged = nag (task); + dependencyChainOnStart (task); if (context.verbose ("project")) - projectChanges[task->get ("project")] = onProjectChange (*task, false); + projectChanges[task.get ("project")] = onProjectChange (task, false); } else { @@ -106,18 +118,17 @@ else { std::cout << format (STRING_CMD_START_ALREADY, - task->id, - task->get ("description")) + task.id, + task.get ("description")) << "\n"; rc = 1; } } // Now list the project changes. - std::map ::iterator i; - for (i = projectChanges.begin (); i != projectChanges.end (); ++i) - if (i->first != "") - context.footnote (i->second); + for (auto& change : projectChanges) + if (change.first != "") + context.footnote (change.second); feedback_affected (count == 1 ? STRING_CMD_START_1 : STRING_CMD_START_N, count); return rc; diff -Nru task-2.4.4+dfsg/src/commands/CmdStats.cpp task-2.5.0+dfsg/src/commands/CmdStats.cpp --- task-2.4.4+dfsg/src/commands/CmdStats.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdStats.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include @@ -43,11 +43,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdStats::CmdStats () { - _keyword = "stats"; - _usage = "task stats"; - _description = STRING_CMD_STATS_USAGE; - _read_only = true; - _displays_id = false; + _keyword = "stats"; + _usage = "task stats"; + _description = STRING_CMD_STATS_USAGE; + _read_only = true; + _displays_id = false; + _needs_gc = true; + _uses_context = true; + _accepts_filter = true; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::metadata; } //////////////////////////////////////////////////////////////////////////////// @@ -67,16 +73,15 @@ // Count the undo transactions. std::vector undoTxns = context.tdb2.undo.get_lines (); int undoCount = 0; - std::vector ::iterator tx; - for (tx = undoTxns.begin (); tx != undoTxns.end (); ++tx) - if (*tx == "---") + for (auto& tx : undoTxns) + if (tx == "---") ++undoCount; // Count the backlog transactions. std::vector backlogTxns = context.tdb2.backlog.get_lines (); int backlogCount = 0; - for (tx = backlogTxns.begin (); tx != backlogTxns.end (); ++tx) - if ((*tx)[0] == '{') + for (auto& tx : backlogTxns) + if (tx[0] == '{') ++backlogCount; // Get all the tasks. @@ -85,7 +90,7 @@ std::vector filtered; filter.subset (all, filtered); - Date now; + ISO8601d now; time_t earliest = time (NULL); time_t latest = 1; int totalT = 0; @@ -103,12 +108,11 @@ std::map allTags; std::map allProjects; - std::vector ::iterator task; - for (task = filtered.begin (); task != filtered.end (); ++task) + for (auto& task : filtered) { ++totalT; - Task::status status = task->getStatus (); + Task::status status = task.getStatus (); switch (status) { case Task::deleted: ++deletedT; break; @@ -118,37 +122,37 @@ case Task::waiting: ++waitingT; break; } - if (task->is_blocked) ++blockedT; - if (task->is_blocking) ++blockingT; + if (task.is_blocked) ++blockedT; + if (task.is_blocking) ++blockingT; - time_t entry = strtol (task->get ("entry").c_str (), NULL, 10); + time_t entry = strtol (task.get ("entry").c_str (), NULL, 10); if (entry < earliest) earliest = entry; if (entry > latest) latest = entry; if (status == Task::completed) { - time_t end = strtol (task->get ("end").c_str (), NULL, 10); + time_t end = strtol (task.get ("end").c_str (), NULL, 10); daysPending += (end - entry) / 86400.0; } if (status == Task::pending) daysPending += (now.toEpoch () - entry) / 86400.0; - descLength += task->get ("description").length (); + descLength += task.get ("description").length (); std::map annotations; - task->getAnnotations (annotations); + task.getAnnotations (annotations); annotationsT += annotations.size (); std::vector tags; - task->getTags (tags); - if (tags.size ()) ++taggedT; + task.getTags (tags); + if (tags.size ()) + ++taggedT; - std::vector ::iterator t; - for (t = tags.begin (); t != tags.end (); ++t) - allTags[*t] = 0; + for (auto& tag : tags) + allTags[tag] = 0; - std::string project = task->get ("project"); + std::string project = task.get ("project"); if (project != "") allProjects[project] = 0; } @@ -231,47 +235,47 @@ if (filtered.size ()) { - Date e (earliest); + ISO8601d e (earliest); row = view.addRow (); view.set (row, 0, STRING_CMD_STATS_OLDEST); view.set (row, 1, e.toString (dateformat)); - Date l (latest); + ISO8601d l (latest); row = view.addRow (); view.set (row, 0, STRING_CMD_STATS_NEWEST); view.set (row, 1, l.toString (dateformat)); row = view.addRow (); view.set (row, 0, STRING_CMD_STATS_USED_FOR); - view.set (row, 1, Duration (latest - earliest).format ()); + view.set (row, 1, ISO8601p (latest - earliest).formatVague ()); } if (totalT) { row = view.addRow (); view.set (row, 0, STRING_CMD_STATS_ADD_EVERY); - view.set (row, 1, Duration (((latest - earliest) / totalT)).format ()); + view.set (row, 1, ISO8601p (((latest - earliest) / totalT)).formatVague ()); } if (completedT) { row = view.addRow (); view.set (row, 0, STRING_CMD_STATS_COMP_EVERY); - view.set (row, 1, Duration ((latest - earliest) / completedT).format ()); + view.set (row, 1, ISO8601p ((latest - earliest) / completedT).formatVague ()); } if (deletedT) { row = view.addRow (); view.set (row, 0, STRING_CMD_STATS_DEL_EVERY); - view.set (row, 1, Duration ((latest - earliest) / deletedT).format ()); + view.set (row, 1, ISO8601p ((latest - earliest) / deletedT).formatVague ()); } if (pendingT || completedT) { row = view.addRow (); view.set (row, 0, STRING_CMD_STATS_AVG_PEND); - view.set (row, 1, Duration ((int) ((daysPending / (pendingT + completedT)) * 86400)).format ()); + view.set (row, 1, ISO8601p ((int) ((daysPending / (pendingT + completedT)) * 86400)).formatVague ()); } if (totalT) @@ -281,14 +285,6 @@ view.set (row, 1, format (STRING_CMD_STATS_CHARS, (int) (descLength / totalT))); } -/* - // TODO Re-enable this when 2.3 has taskd support. Until then, it makes no - // sense to include this. - row = view.addRow (); - view.set (row, 0, STRING_CMD_STATS_LAST_SYNC); - view.set (row, 1, "-"); -*/ - // If an alternating row color is specified, notify the table. if (context.color ()) { diff -Nru task-2.4.4+dfsg/src/commands/CmdStop.cpp task-2.5.0+dfsg/src/commands/CmdStop.cpp --- task-2.4.4+dfsg/src/commands/CmdStop.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdStop.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -38,15 +38,21 @@ //////////////////////////////////////////////////////////////////////////////// CmdStop::CmdStop () { - _keyword = "stop"; - _usage = "task stop "; - _description = STRING_CMD_STOP_USAGE; - _read_only = false; - _displays_id = false; + _keyword = "stop"; + _usage = "task stop "; + _description = STRING_CMD_STOP_USAGE; + _read_only = false; + _displays_id = false; + _needs_gc = false; + _uses_context = true; + _accepts_filter = true; + _accepts_modifications = true; + _accepts_miscellaneous = false; + _category = Command::Category::operation; } //////////////////////////////////////////////////////////////////////////////// -int CmdStop::execute (std::string& output) +int CmdStop::execute (std::string&) { int rc = 0; int count = 0; @@ -64,33 +70,32 @@ // Accumulated project change notifications. std::map projectChanges; - std::vector ::iterator task; - for (task = filtered.begin (); task != filtered.end (); ++task) + for (auto& task : filtered) { - if (task->has ("start")) + if (task.has ("start")) { - Task before (*task); + Task before (task); // Stop the specified task. std::string question = format (STRING_CMD_STOP_CONFIRM, - task->id, - task->get ("description")); + task.id, + task.get ("description")); - task->modify (Task::modAnnotate); - task->remove ("start"); + task.modify (Task::modAnnotate); + task.remove ("start"); if (context.config.getBoolean ("journal.time")) - task->addAnnotation (context.config.get ("journal.time.stop.annotation")); + task.addAnnotation (context.config.get ("journal.time.stop.annotation")); - if (permission (*task, taskDifferences (before, *task) + question, filtered.size ())) + if (permission (taskDifferences (before, task) + question, filtered.size ())) { - updateRecurrenceMask (*task); - context.tdb2.modify (*task); + updateRecurrenceMask (task); + context.tdb2.modify (task); ++count; - feedback_affected (STRING_CMD_STOP_TASK, *task); - dependencyChainOnStart (*task); + feedback_affected (STRING_CMD_STOP_TASK, task); + dependencyChainOnStart (task); if (context.verbose ("project")) - projectChanges[task->get ("project")] = onProjectChange (*task, false); + projectChanges[task.get ("project")] = onProjectChange (task, false); } else { @@ -103,18 +108,17 @@ else { std::cout << format (STRING_CMD_STOP_ALREADY, - task->id, - task->get ("description")) + task.id, + task.get ("description")) << "\n"; rc = 1; } } // Now list the project changes. - std::map ::iterator i; - for (i = projectChanges.begin (); i != projectChanges.end (); ++i) - if (i->first != "") - context.footnote (i->second); + for (auto& change : projectChanges) + if (change.first != "") + context.footnote (change.second); feedback_affected (count == 1 ? STRING_CMD_STOP_1 : STRING_CMD_STOP_N, count); return rc; diff -Nru task-2.4.4+dfsg/src/commands/CmdSummary.cpp task-2.5.0+dfsg/src/commands/CmdSummary.cpp --- task-2.4.4+dfsg/src/commands/CmdSummary.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdSummary.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include #include @@ -43,11 +43,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdSummary::CmdSummary () { - _keyword = "summary"; - _usage = "task summary"; - _description = STRING_CMD_SUMMARY_USAGE; - _read_only = true; - _displays_id = false; + _keyword = "summary"; + _usage = "task summary"; + _description = STRING_CMD_SUMMARY_USAGE; + _read_only = true; + _displays_id = false; + _needs_gc = true; + _uses_context = true; + _accepts_filter = true; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::graphs; } //////////////////////////////////////////////////////////////////////////////// @@ -67,10 +73,9 @@ // Generate unique list of project names from all pending tasks. std::map allProjects; - std::vector ::iterator task; - for (task = filtered.begin (); task != filtered.end (); ++task) - if (showAllProjects || task->getStatus () == Task::pending) - allProjects[task->get ("project")] = false; + for (auto& task : filtered) + if (showAllProjects || task.getStatus () == Task::pending) + allProjects[task.get ("project")] = false; // Initialize counts, sum. std::map countPending; @@ -80,47 +85,49 @@ time_t now = time (NULL); // Initialize counters. - std::map ::iterator project; - for (project = allProjects.begin (); project != allProjects.end (); ++project) + for (auto& project : allProjects) { - countPending [project->first] = 0; - countCompleted [project->first] = 0; - sumEntry [project->first] = 0.0; - counter [project->first] = 0; + countPending [project.first] = 0; + countCompleted [project.first] = 0; + sumEntry [project.first] = 0.0; + counter [project.first] = 0; } // Count the various tasks. - for (task = filtered.begin (); task != filtered.end (); ++task) + for (auto& task : filtered) { - std::string project = task->get ("project"); + std::string project = task.get ("project"); std::vector projects = extractParents (project); projects.push_back (project); - std::vector ::const_iterator parent; - for (parent = projects.begin (); parent != projects.end (); ++parent) - ++counter[*parent]; - - if (task->getStatus () == Task::pending || - task->getStatus () == Task::waiting) - for (parent = projects.begin (); parent != projects.end (); ++parent) + for (auto& parent : projects) + ++counter[parent]; + + if (task.getStatus () == Task::pending || + task.getStatus () == Task::waiting) + { + for (auto& parent : projects) { - ++countPending[*parent]; + ++countPending[parent]; - time_t entry = strtol (task->get ("entry").c_str (), NULL, 10); + time_t entry = strtol (task.get ("entry").c_str (), NULL, 10); if (entry) - sumEntry[*parent] = sumEntry[*parent] + (double) (now - entry); + sumEntry[parent] = sumEntry[parent] + (double) (now - entry); } + } - else if (task->getStatus () == Task::completed) - for (parent = projects.begin (); parent != projects.end (); ++parent) + else if (task.getStatus () == Task::completed) + { + for (auto& parent : projects) { - ++countCompleted[*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); + 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); + sumEntry[parent] = sumEntry[parent] + (double) (end - entry); } + } } // Create a table for output. @@ -140,35 +147,33 @@ int barWidth = 30; std::vector processed; - std::map ::iterator i; - for (i = allProjects.begin (); i != allProjects.end (); ++i) + for (auto& i : allProjects) { - if (showAllProjects || countPending[i->first] > 0) + if (showAllProjects || countPending[i.first] > 0) { - const std::vector parents = extractParents (i->first); - std::vector ::const_iterator parent; - for (parent = parents.begin (); parent != parents.end (); parent++) + const std::vector parents = extractParents (i.first); + for (auto& parent : parents) { - if (std::find (processed.begin (), processed.end (), *parent) + if (std::find (processed.begin (), processed.end (), parent) == processed.end ()) { int row = view.addRow (); - view.set (row, 0, indentProject (*parent)); - processed.push_back (*parent); + view.set (row, 0, indentProject (parent)); + processed.push_back (parent); } } int row = view.addRow (); - view.set (row, 0, (i->first == "" + view.set (row, 0, (i.first == "" ? STRING_CMD_SUMMARY_NONE - : indentProject (i->first, " ", '.'))); + : indentProject (i.first, " ", '.'))); - view.set (row, 1, countPending[i->first]); - if (counter[i->first]) - view.set (row, 2, Duration ((int) (sumEntry[i->first] / (double)counter[i->first])).format ()); + view.set (row, 1, countPending[i.first]); + if (counter[i.first]) + view.set (row, 2, ISO8601p ((int) (sumEntry[i.first] / (double)counter[i.first])).formatVague ()); - int c = countCompleted[i->first]; - int p = countPending[i->first]; + int c = countCompleted[i.first]; + int p = countPending[i.first]; int completedBar = 0; if (c + p) completedBar = (c * barWidth) / (c + p); @@ -191,7 +196,7 @@ if (c + p) sprintf (percent, "%d%%", 100 * c / (c + p)); view.set (row, 3, percent); - processed.push_back (i->first); + processed.push_back (i.first); } } diff -Nru task-2.4.4+dfsg/src/commands/CmdSync.cpp task-2.5.0+dfsg/src/commands/CmdSync.cpp --- task-2.4.4+dfsg/src/commands/CmdSync.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdSync.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -40,11 +41,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdSync::CmdSync () { - _keyword = "synchronize"; - _usage = "task synchronize [initialize]"; - _description = STRING_CMD_SYNC_USAGE; - _read_only = false; - _displays_id = false; + _keyword = "synchronize"; + _usage = "task synchronize [initialize]"; + _description = STRING_CMD_SYNC_USAGE; + _read_only = false; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = false; + _accepts_modifications = false; + _accepts_miscellaneous = true; + _category = Command::Category::migration; } //////////////////////////////////////////////////////////////////////////////// @@ -54,13 +61,16 @@ #ifdef HAVE_LIBGNUTLS std::stringstream out; + Filter filter; + if (filter.hasFilter ()) + throw std::string (STRING_ERROR_NO_FILTER); + // Loog for the 'init' keyword to indicate one-time pending.data upload. bool first_time_init = false; - std::vector words = context.cli.getWords (); - std::vector ::iterator word; - for (word = words.begin (); word != words.end (); ++word) + std::vector words = context.cli2.getWords (); + for (auto& word : words) { - if (closeEnough ("initialize", *word, 4)) + if (closeEnough ("initialize", word, 4)) { if (!context.config.getBoolean ("confirmation") || confirm (STRING_CMD_SYNC_INIT)) @@ -125,24 +135,22 @@ // deltas is meaningless. context.tdb2.backlog._file.truncate (); - std::vector pending = context.tdb2.pending.get_tasks (); - std::vector ::iterator i; - for (i = pending.begin (); i != pending.end (); ++i) + auto pending = context.tdb2.pending.get_tasks (); + for (auto& i : pending) { - payload += i->composeJSON () + "\n"; + payload += i.composeJSON () + "\n"; ++upload_count; } } else { std::vector lines = context.tdb2.backlog.get_lines (); - std::vector ::iterator i; - for (i = lines.begin (); i != lines.end (); ++i) + for (auto& i : lines) { - if ((*i)[0] == '{') + if (i[0] == '{') ++upload_count; - payload += *i + "\n"; + payload += i + "\n"; } } @@ -163,7 +171,6 @@ // Ignore harmful signals. signal (SIGHUP, SIG_IGN); signal (SIGINT, SIG_IGN); - signal (SIGKILL, SIG_IGN); signal (SIGPIPE, SIG_IGN); signal (SIGTERM, SIG_IGN); signal (SIGUSR1, SIG_IGN); @@ -190,14 +197,13 @@ context.tdb2.all_tasks (); std::string sync_key = ""; - std::vector ::iterator line; - for (line = lines.begin (); line != lines.end (); ++line) + for (auto& line : lines) { - if ((*line)[0] == '{') + if (line[0] == '{') { ++download_count; - Task from_server (*line); + Task from_server (line); std::string uuid = from_server.get ("uuid"); // Is it a new task from the server, or an update to an existing one? @@ -225,9 +231,9 @@ context.tdb2.add (from_server, false); } } - else if (*line != "") + else if (line != "") { - sync_key = *line; + sync_key = line; context.debug ("Sync key " + sync_key); } @@ -315,7 +321,6 @@ // Restore signal handling. signal (SIGHUP, SIG_DFL); signal (SIGINT, SIG_DFL); - signal (SIGKILL, SIG_DFL); signal (SIGPIPE, SIG_DFL); signal (SIGTERM, SIG_DFL); signal (SIGUSR1, SIG_DFL); @@ -341,7 +346,7 @@ { // It is important that the ':' be the *last* colon, in order to support // IPv6 addresses. - std::string::size_type colon = to.rfind (':'); + auto colon = to.rfind (':'); if (colon == std::string::npos) throw format (STRING_CMD_SYNC_BAD_SERVER, to); diff -Nru task-2.4.4+dfsg/src/commands/CmdTags.cpp task-2.5.0+dfsg/src/commands/CmdTags.cpp --- task-2.4.4+dfsg/src/commands/CmdTags.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdTags.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -40,11 +40,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdTags::CmdTags () { - _keyword = "tags"; - _usage = "task tags"; - _description = STRING_CMD_TAGS_USAGE; - _read_only = true; - _displays_id = false; + _keyword = "tags"; + _usage = "task tags"; + _description = STRING_CMD_TAGS_USAGE; + _read_only = true; + _displays_id = false; + _needs_gc = true; + _uses_context = true; + _accepts_filter = true; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::metadata; } //////////////////////////////////////////////////////////////////////////////// @@ -54,15 +60,11 @@ std::stringstream out; // Get all the tasks. - std::vector tasks = context.tdb2.pending.get_tasks (); + auto tasks = context.tdb2.pending.get_tasks (); if (context.config.getBoolean ("list.all.tags")) - { - std::vector extra = context.tdb2.completed.get_tasks (); - std::vector ::iterator task; - for (task = extra.begin (); task != extra.end (); ++task) - tasks.push_back (*task); - } + for (auto& task : context.tdb2.completed.get_tasks ()) + tasks.push_back (task); int quantity = tasks.size (); @@ -74,18 +76,16 @@ // Scan all the tasks for their project name, building a map using project // names as keys. std::map unique; - std::vector ::iterator task; - for (task = filtered.begin (); task != filtered.end (); ++task) + for (auto& task : filtered) { std::vector tags; - task->getTags (tags); + task.getTags (tags); - std::vector ::iterator tag; - for (tag = tags.begin (); tag != tags.end (); ++tag) - if (unique.find (*tag) != unique.end ()) - unique[*tag]++; + for (auto& tag : tags) + if (unique.find (tag) != unique.end ()) + unique[tag]++; else - unique[*tag] = 1; + unique[tag] = 1; } if (unique.size ()) @@ -101,19 +101,18 @@ Color bold ("bold"); bool special = false; - std::map ::iterator i; - for (i = unique.begin (); i != unique.end (); ++i) + for (auto& i : unique) { // Highlight the special tags. special = (context.color () && - (i->first == "nocolor" || - i->first == "nonag" || - i->first == "nocal" || - i->first == "next")) ? true : false; + (i.first == "nocolor" || + i.first == "nonag" || + i.first == "nocal" || + i.first == "next")) ? true : false; int row = view.addRow (); - view.set (row, 0, i->first, special ? bold : Color ()); - view.set (row, 1, i->second, special ? bold : Color ()); + view.set (row, 0, i.first, special ? bold : Color ()); + view.set (row, 1, i.second, special ? bold : Color ()); } out << optionalBlankLine () @@ -145,26 +144,28 @@ //////////////////////////////////////////////////////////////////////////////// CmdCompletionTags::CmdCompletionTags () { - _keyword = "_tags"; - _usage = "task _tags"; - _description = STRING_CMD_COMTAGS_USAGE; - _read_only = true; - _displays_id = false; + _keyword = "_tags"; + _usage = "task _tags"; + _description = STRING_CMD_COMTAGS_USAGE; + _read_only = true; + _displays_id = false; + _needs_gc = true; + _uses_context = false; + _accepts_filter = true; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::internal; } //////////////////////////////////////////////////////////////////////////////// int CmdCompletionTags::execute (std::string& output) { // Get all the tasks. - std::vector tasks = context.tdb2.pending.get_tasks (); + auto tasks = context.tdb2.pending.get_tasks (); if (context.config.getBoolean ("complete.all.tags")) - { - std::vector extra = context.tdb2.completed.get_tasks (); - std::vector ::iterator task; - for (task = extra.begin (); task != extra.end (); ++task) - tasks.push_back (*task); - } + for (auto& task : context.tdb2.completed.get_tasks ()) + tasks.push_back (task); // Apply filter. Filter filter; @@ -174,27 +175,51 @@ // Scan all the tasks for their tags, building a map using tag // names as keys. std::map unique; - std::vector ::iterator task; - for (task = filtered.begin (); task != filtered.end (); ++task) + for (auto& task : filtered) { std::vector tags; - task->getTags (tags); + task.getTags (tags); - std::vector ::iterator tag; - for (tag = tags.begin (); tag != tags.end (); ++tag) - unique[*tag] = 0; + for (auto& tag : tags) + unique[tag] = 0; } - // add built-in tags to map - unique["nocolor"] = 0; - unique["nonag"] = 0; - unique["nocal"] = 0; - unique["next"] = 0; + // Add built-in tags to map. + unique["nocolor"] = 0; + unique["nonag"] = 0; + unique["nocal"] = 0; + unique["next"] = 0; + unique["ACTIVE"] = 0; + unique["ANNOTATED"] = 0; + unique["BLOCKED"] = 0; + unique["BLOCKING"] = 0; + unique["CHILD"] = 0; + unique["COMPLETED"] = 0; + unique["DELETED"] = 0; + unique["DUE"] = 0; + unique["DUETODAY"] = 0; + unique["MONTH"] = 0; + unique["ORPHAN"] = 0; + unique["OVERDUE"] = 0; + unique["PARENT"] = 0; + unique["PENDING"] = 0; + unique["READY"] = 0; + unique["SCHEDULED"] = 0; + unique["TAGGED"] = 0; + unique["TODAY"] = 0; + unique["TOMORROW"] = 0; + unique["UDA"] = 0; + unique["UNBLOCKED"] = 0; + unique["UNTIL"] = 0; + unique["WAITING"] = 0; + unique["WEEK"] = 0; + unique["YEAR"] = 0; + unique["YESTERDAY"] = 0; + // If you update the above list, update src/commands/CmdInfo.cpp and src/commands/CmdTags.cpp as well. std::stringstream out; - std::map ::iterator it; - for (it = unique.begin (); it != unique.end (); ++it) - out << it->first << "\n"; + for (auto& it : unique) + out << it.first << "\n"; output = out.str (); return 0; diff -Nru task-2.4.4+dfsg/src/commands/CmdTimesheet.cpp task-2.5.0+dfsg/src/commands/CmdTimesheet.cpp --- task-2.4.4+dfsg/src/commands/CmdTimesheet.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdTimesheet.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -28,8 +28,9 @@ #include #include #include +#include #include -#include +#include #include #include #include @@ -40,11 +41,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdTimesheet::CmdTimesheet () { - _keyword = "timesheet"; - _usage = "task timesheet [weeks]"; - _description = STRING_CMD_TIMESHEET_USAGE; - _read_only = true; - _displays_id = false; + _keyword = "timesheet"; + _usage = "task timesheet [weeks]"; + _description = STRING_CMD_TIMESHEET_USAGE; + _read_only = true; + _displays_id = false; + _needs_gc = true; + _uses_context = false; + _accepts_filter = false; + _accepts_modifications = false; + _accepts_miscellaneous = true; + _category = Command::Category::graphs; } //////////////////////////////////////////////////////////////////////////////// @@ -57,29 +64,29 @@ std::vector all = context.tdb2.all_tasks (); // What day of the week does the user consider the first? - int weekStart = Date::dayOfWeek (context.config.get ("weekstart")); + int weekStart = ISO8601d::dayOfWeek (context.config.get ("weekstart")); if (weekStart != 0 && weekStart != 1) throw std::string (STRING_DATE_BAD_WEEKSTART); // Determine the date of the first day of the most recent report. - Date today; - Date start; + ISO8601d today; + ISO8601d start; start -= (((today.dayOfWeek () - weekStart) + 7) % 7) * 86400; // Roll back to midnight. - start = Date (start.month (), start.day (), start.year ()); - Date end = start + (7 * 86400); + start = ISO8601d (start.month (), start.day (), start.year ()); + ISO8601d end = start + (7 * 86400); // Determine how many reports to run. int quantity = 1; - std::vector words = context.cli.getWords (); + std::vector words = context.cli2.getWords (); if (words.size () == 1) quantity = strtol (words[0].c_str (), NULL, 10);; std::stringstream out; for (int week = 0; week < quantity; ++week) { - Date endString (end); + ISO8601d endString (end); endString -= 86400; std::string title = start.toString (context.config.get ("dateformat")) @@ -102,43 +109,41 @@ Color label (context.config.get ("color.label")); completed.colorHeader (label); - std::vector ::iterator task; - for (task = all.begin (); task != all.end (); ++task) + for (auto& task : all) { // If task completed within range. - if (task->getStatus () == Task::completed) + if (task.getStatus () == Task::completed) { - Date compDate (task->get_date ("end")); + ISO8601d compDate (task.get_date ("end")); if (compDate >= start && compDate < end) { Color c; if (context.color ()) - autoColorize (*task, c); + autoColorize (task, c); int row = completed.addRow (); std::string format = context.config.get ("dateformat.report"); if (format == "") format = context.config.get ("dateformat"); - completed.set (row, 1, task->get ("project"), c); + completed.set (row, 1, task.get ("project"), c); - if(task->has ("due")) + if(task.has ("due")) { - Date dt (task->get_date ("due")); + ISO8601d dt (task.get_date ("due")); completed.set (row, 2, dt.toString (format)); } - std::string description = task->get ("description"); + std::string description = task.get ("description"); int indent = context.config.getInteger ("indent.annotation"); std::map annotations; - task->getAnnotations (annotations); - std::map ::iterator ann; - for (ann = annotations.begin (); ann != annotations.end (); ++ann) + task.getAnnotations (annotations); + for (auto& ann : annotations) description += "\n" + std::string (indent, ' ') - + Date (ann->first.substr (11)).toString (context.config.get ("dateformat")) + + ISO8601d (ann.first.substr (11)).toString (context.config.get ("dateformat")) + " " - + ann->second; + + ann.second; completed.set (row, 3, description, c); } @@ -160,43 +165,42 @@ started.add (Column::factory ("string", STRING_COLUMN_LABEL_DESC)); started.colorHeader (label); - for (task = all.begin (); task != all.end (); ++task) + for (auto& task : all) { // If task started within range, but not completed withing range. - if (task->getStatus () == Task::pending && - task->has ("start")) + if (task.getStatus () == Task::pending && + task.has ("start")) { - Date startDate (task->get_date ("start")); + ISO8601d startDate (task.get_date ("start")); if (startDate >= start && startDate < end) { Color c; if (context.color ()) - autoColorize (*task, c); + autoColorize (task, c); int row = started.addRow (); std::string format = context.config.get ("dateformat.report"); if (format == "") format = context.config.get ("dateformat"); - started.set (row, 1, task->get ("project"), c); + started.set (row, 1, task.get ("project"), c); - if(task->has ("due")) + if (task.has ("due")) { - Date dt (task->get_date ("due")); + ISO8601d dt (task.get_date ("due")); started.set (row, 2, dt.toString (format)); } - std::string description = task->get ("description"); + std::string description = task.get ("description"); int indent = context.config.getInteger ("indent.annotation"); std::map annotations; - task->getAnnotations (annotations); - std::map ::iterator ann; - for (ann = annotations.begin (); ann != annotations.end (); ++ann) + task.getAnnotations (annotations); + for (auto& ann : annotations) description += "\n" + std::string (indent, ' ') - + Date (ann->first.substr (11)).toString (context.config.get ("dateformat")) + + ISO8601d (ann.first.substr (11)).toString (context.config.get ("dateformat")) + " " - + ann->second; + + ann.second; started.set (row, 3, description, c); } diff -Nru task-2.4.4+dfsg/src/commands/CmdUDAs.cpp task-2.5.0+dfsg/src/commands/CmdUDAs.cpp --- task-2.4.4+dfsg/src/commands/CmdUDAs.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdUDAs.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -41,11 +41,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdUDAs::CmdUDAs () { - _keyword = "udas"; - _usage = "task udas"; - _description = STRING_CMD_UDAS_USAGE; - _read_only = true; - _displays_id = false; + _keyword = "udas"; + _usage = "task udas"; + _description = STRING_CMD_UDAS_USAGE; + _read_only = true; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = false; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::config; } //////////////////////////////////////////////////////////////////////////////// @@ -55,15 +61,14 @@ std::stringstream out; std::vector udas; - Config::const_iterator name; - for (name = context.config.begin (); name != context.config.end (); ++name) + for (auto& name : context.config) { - if (name->first.substr (0, 4) == "uda." && - name->first.find (".type") != std::string::npos) + if (name.first.substr (0, 4) == "uda." && + name.first.find (".type") != std::string::npos) { - std::string::size_type period = name->first.find ('.', 4); + auto period = name.first.find ('.', 4); if (period != std::string::npos) - udas.push_back (name->first.substr (4, period - 4)); + udas.push_back (name.first.substr (4, period - 4)); } } @@ -90,25 +95,23 @@ Color label (context.config.get ("color.label")); view.colorHeader (label); - std::vector ::iterator uda; - for (uda = udas.begin (); uda != udas.end (); ++uda) + for (auto& uda : udas) { - std::string type = context.config.get ("uda." + *uda + ".type"); - std::string label = context.config.get ("uda." + *uda + ".label"); - std::string values = context.config.get ("uda." + *uda + ".values"); - std::string defval = context.config.get ("uda." + *uda + ".default"); + std::string type = context.config.get ("uda." + uda + ".type"); + std::string label = context.config.get ("uda." + uda + ".label"); + std::string values = context.config.get ("uda." + uda + ".values"); + std::string defval = context.config.get ("uda." + uda + ".default"); if (label == "") - label = *uda; + label = uda; // Count UDA usage by UDA. int count = 0; - std::vector ::iterator i; - for (i = filtered.begin (); i != filtered.end (); ++i) - if (i->has (*uda)) + for (auto& i : filtered) + if (i.has (uda)) ++count; int row = view.addRow (); - view.set (row, 0, *uda); + view.set (row, 0, uda); view.set (row, 1, type); view.set (row, 2, label); view.set (row, 3, values); @@ -132,14 +135,12 @@ // Orphans are task attributes that are not represented in context.columns. std::map orphans; - std::vector ::iterator i; - for (i = filtered.begin (); i != filtered.end (); ++i) + for (auto& i : filtered) { - std::map ::iterator att; - for (att = i->begin (); att != i->end (); ++att) - if (att->first.substr (0, 11) != "annotation_" && - context.columns.find (att->first) == context.columns.end ()) - orphans[att->first]++; + for (auto& att : i) + if (att.first.substr (0, 11) != "annotation_" && + context.columns.find (att.first) == context.columns.end ()) + orphans[att.first]++; } if (orphans.size ()) @@ -153,12 +154,11 @@ Color label (context.config.get ("color.label")); orphanView.colorHeader (label); - std::map ::iterator o; - for (o = orphans.begin (); o != orphans.end (); ++o) + for (auto& o : orphans) { int row = orphanView.addRow (); - orphanView.set (row, 0, o->first); - orphanView.set (row, 1, o->second); + orphanView.set (row, 0, o.first); + orphanView.set (row, 1, o.second); } out << optionalBlankLine () @@ -177,26 +177,31 @@ /////////////////////////////////////////////////////////////////////////////// CmdCompletionUDAs::CmdCompletionUDAs () { - _keyword = "_udas"; - _usage = "task _udas"; - _description = STRING_CMD_UDAS_COMPL_USAGE; - _read_only = true; - _displays_id = false; + _keyword = "_udas"; + _usage = "task _udas"; + _description = STRING_CMD_UDAS_COMPL_USAGE; + _read_only = true; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = false; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::internal; } //////////////////////////////////////////////////////////////////////////////// int CmdCompletionUDAs::execute (std::string& output) { std::vector udas; - Config::const_iterator name; - for (name = context.config.begin (); name != context.config.end (); ++name) + for (auto& name : context.config) { - if (name->first.substr (0, 4) == "uda." && - name->first.find (".type") != std::string::npos) + if (name.first.substr (0, 4) == "uda." && + name.first.find (".type") != std::string::npos) { - std::string::size_type period = name->first.find ('.', 4); + auto period = name.first.find ('.', 4); if (period != std::string::npos) - udas.push_back (name->first.substr (4, period - 4)); + udas.push_back (name.first.substr (4, period - 4)); } } diff -Nru task-2.4.4+dfsg/src/commands/CmdUndo.cpp task-2.5.0+dfsg/src/commands/CmdUndo.cpp --- task-2.4.4+dfsg/src/commands/CmdUndo.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdUndo.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -34,22 +35,22 @@ //////////////////////////////////////////////////////////////////////////////// CmdUndo::CmdUndo () { - _keyword = "undo"; - _usage = "task undo"; - _description = STRING_CMD_UNDO_USAGE; - _read_only = false; - _displays_id = false; + _keyword = "undo"; + _usage = "task undo"; + _description = STRING_CMD_UNDO_USAGE; + _read_only = false; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = false; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::operation; } //////////////////////////////////////////////////////////////////////////////// -int CmdUndo::execute (std::string& output) +int CmdUndo::execute (std::string&) { - // Detect attempts to modify the task. - std::vector ::iterator a; - for (a = context.cli._args.begin (); a != context.cli._args.end (); ++a) - if (a->hasTag ("MODIFICATION")) - throw std::string (STRING_CMD_UNDO_MODS); - context.tdb2.revert (); return 0; } diff -Nru task-2.4.4+dfsg/src/commands/CmdUnique.cpp task-2.5.0+dfsg/src/commands/CmdUnique.cpp --- task-2.4.4+dfsg/src/commands/CmdUnique.cpp 1970-01-01 00:00:00.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdUnique.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -0,0 +1,96 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern Context context; + +//////////////////////////////////////////////////////////////////////////////// +CmdUnique::CmdUnique () +{ + _keyword = "_unique"; + _usage = "task _unique "; + _description = STRING_CMD_UNIQUE_USAGE; + _read_only = true; + _displays_id = true; + _needs_gc = true; + _uses_context = false; + _accepts_filter = true; + _accepts_modifications = false; + _accepts_miscellaneous = true; + _category = Command::Category::internal; +} + +//////////////////////////////////////////////////////////////////////////////// +int CmdUnique::execute (std::string& output) +{ + // Apply filter. + Filter filter; + filter.disableSafety (); + std::vector filtered; + filter.subset (filtered); + + // Find . + std::string attribute = ""; + + // Just the first arg. + auto words = context.cli2.getWords (); + if (words.size () == 0) + throw std::string (STRING_CMD_UNIQUE_MISSING); + attribute = words[0]; + + std::string canonical; + if (! context.cli2.canonicalize (canonical, "attribute", attribute)) + throw std::string (STRING_CMD_UNIQUE_VALID); + + // Find number of matching tasks. + std::set values; + for (auto& task : filtered) + if (task.has (canonical)) + values.insert (task.get (canonical)); + else if (canonical == "id" && + task.getStatus () != Task::deleted && + task.getStatus () != Task::completed) + values.insert (format (task.id)); + + // Generate list of unique values. + for (auto& value : values) + output += value + "\n"; + + context.headers.clear (); + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/commands/CmdUnique.h task-2.5.0+dfsg/src/commands/CmdUnique.h --- task-2.4.4+dfsg/src/commands/CmdUnique.h 1970-01-01 00:00:00.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdUnique.h 2015-10-21 21:18:15.000000000 +0000 @@ -0,0 +1,41 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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 +// +//////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDED_CMDUNIQUE +#define INCLUDED_CMDUNIQUE + +#include +#include + +class CmdUnique : public Command +{ +public: + CmdUnique (); + int execute (std::string&); +}; + +#endif +//////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/commands/CmdUrgency.cpp task-2.5.0+dfsg/src/commands/CmdUrgency.cpp --- task-2.4.4+dfsg/src/commands/CmdUrgency.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdUrgency.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -39,11 +39,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdUrgency::CmdUrgency () { - _keyword = "_urgency"; - _usage = "task _urgency"; - _description = STRING_CMD_URGENCY_USAGE; - _read_only = true; - _displays_id = false; + _keyword = "_urgency"; + _usage = "task _urgency"; + _description = STRING_CMD_URGENCY_USAGE; + _read_only = true; + _displays_id = false; + _needs_gc = true; + _uses_context = true; + _accepts_filter = true; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::internal; } //////////////////////////////////////////////////////////////////////////////// @@ -62,20 +68,19 @@ // Display urgency for the selected tasks. std::stringstream out; - std::vector ::iterator task; - for (task = filtered.begin (); task != filtered.end (); ++task) + for (auto& task : filtered) { - if (task->id) + if (task.id) { out << format (STRING_CMD_URGENCY_RESULT, - task->id, task->urgency ()) + task.id, trim (format (task.urgency (), 6, 3))) << "\n"; } else { out << format (STRING_CMD_URGENCY_RESULT, - task->get ("uuid"), - task->urgency ()) + task.get ("uuid"), + trim (format (task.urgency (), 6, 3))) << "\n"; } } diff -Nru task-2.4.4+dfsg/src/commands/CmdVersion.cpp task-2.5.0+dfsg/src/commands/CmdVersion.cpp --- task-2.4.4+dfsg/src/commands/CmdVersion.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/CmdVersion.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -41,11 +41,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdVersion::CmdVersion () { - _keyword = "version"; - _usage = "task version"; - _description = STRING_CMD_VERSION_USAGE; - _read_only = true; - _displays_id = false; + _keyword = "version"; + _usage = "task version"; + _description = STRING_CMD_VERSION_USAGE; + _read_only = true; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = false; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::misc; } //////////////////////////////////////////////////////////////////////////////// @@ -124,11 +130,17 @@ //////////////////////////////////////////////////////////////////////////////// CmdCompletionVersion::CmdCompletionVersion () { - _keyword = "_version"; - _usage = "task _version"; - _description = STRING_CMD_VERSION_USAGE2; - _read_only = true; - _displays_id = false; + _keyword = "_version"; + _usage = "task _version"; + _description = STRING_CMD_VERSION_USAGE2; + _read_only = true; + _displays_id = false; + _needs_gc = false; + _uses_context = false; + _accepts_filter = false; + _accepts_modifications = false; + _accepts_miscellaneous = false; + _category = Command::Category::internal; } //////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/commands/Command.cpp task-2.5.0+dfsg/src/commands/Command.cpp --- task-2.4.4+dfsg/src/commands/Command.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/Command.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -81,6 +81,7 @@ #include #include #include +#include #include #include @@ -105,6 +106,7 @@ c = new CmdCalendar (); all[c->keyword ()] = c; c = new CmdColor (); all[c->keyword ()] = c; c = new CmdColumns (); all[c->keyword ()] = c; + c = new CmdCommands (); all[c->keyword ()] = c; c = new CmdCompletionAliases (); all[c->keyword ()] = c; c = new CmdCompletionColumns (); all[c->keyword ()] = c; c = new CmdCompletionCommands (); all[c->keyword ()] = c; @@ -155,6 +157,7 @@ c = new CmdTimesheet (); all[c->keyword ()] = c; c = new CmdUDAs (); all[c->keyword ()] = c; c = new CmdUndo (); all[c->keyword ()] = c; + c = new CmdUnique (); all[c->keyword ()] = c; c = new CmdUrgency (); all[c->keyword ()] = c; c = new CmdUUIDs (); all[c->keyword ()] = c; c = new CmdVersion (); all[c->keyword ()] = c; @@ -170,7 +173,7 @@ if (i.first.substr (0, 7) == "report.") { std::string report = i.first.substr (7); - std::string::size_type columns = report.find (".columns"); + auto columns = report.find (".columns"); if (columns != std::string::npos) reports.push_back (report.substr (0, columns)); } @@ -192,12 +195,36 @@ } //////////////////////////////////////////////////////////////////////////////// +const std::map Command::categoryNames = +{ + // These strings are intentionally not l10n'd: they are used as identifiers. + {Command::Category::unassigned, "unassigned"} // should never happen + ,{Command::Category::metadata, "metadata"} + ,{Command::Category::report, "report"} + ,{Command::Category::operation, "operation"} + ,{Command::Category::context, "context"} + ,{Command::Category::graphs, "graphs" } + ,{Command::Category::config, "config" } + ,{Command::Category::migration, "migration"} + ,{Command::Category::misc, "misc" } + ,{Command::Category::internal, "internal"} + ,{Command::Category::UNDOCUMENTED, "undocumented"} +}; + +//////////////////////////////////////////////////////////////////////////////// Command::Command () -: _usage ("") +: _keyword ("") +, _usage ("") , _description ("") , _read_only (true) , _displays_id (true) , _needs_confirm (false) +, _needs_gc (true) +, _uses_context (false) +, _accepts_filter (false) +, _accepts_modifications (false) +, _accepts_miscellaneous (false) +, _category(Category::unassigned) , _permission_quit (false) , _permission_all (false) , _first_iteration (true) @@ -205,79 +232,74 @@ } //////////////////////////////////////////////////////////////////////////////// -Command::Command (const Command& other) +Command::~Command () { - _usage = other._usage; - _description = other._description; - _read_only = other._read_only; - _displays_id = other._displays_id; - _needs_confirm = other._needs_confirm; - _permission_quit = other._permission_quit; - _permission_all = other._permission_all; - _first_iteration = other._first_iteration; } //////////////////////////////////////////////////////////////////////////////// -Command& Command::operator= (const Command& other) +std::string Command::keyword () const { - if (this != &other) - { - _usage = other._usage; - _description = other._description; - _read_only = other._read_only; - _displays_id = other._displays_id; - _needs_confirm = other._needs_confirm; - _permission_quit = other._permission_quit; - _permission_all = other._permission_all; - _first_iteration = other._first_iteration; - } + return _keyword; +} - return *this; +//////////////////////////////////////////////////////////////////////////////// +std::string Command::usage () const +{ + return _usage; } //////////////////////////////////////////////////////////////////////////////// -bool Command::operator== (const Command& other) const +std::string Command::description () const { - return _usage == other._usage && - _description == other._description && - _read_only == other._read_only && - _displays_id == other._displays_id && - _needs_confirm == other._needs_confirm; + return _description; } //////////////////////////////////////////////////////////////////////////////// -Command::~Command () +bool Command::read_only () const { + return _read_only; } //////////////////////////////////////////////////////////////////////////////// -std::string Command::keyword () const +bool Command::displays_id () const { - return _keyword; + return _displays_id; } //////////////////////////////////////////////////////////////////////////////// -std::string Command::usage () const +bool Command::needs_gc () const { - return _usage; + return _needs_gc; } //////////////////////////////////////////////////////////////////////////////// -std::string Command::description () const +bool Command::uses_context () const { - return _description; + return _uses_context; } //////////////////////////////////////////////////////////////////////////////// -bool Command::read_only () const +bool Command::accepts_filter () const { - return _read_only; + return _accepts_filter; } //////////////////////////////////////////////////////////////////////////////// -bool Command::displays_id () const +bool Command::accepts_modifications () const { - return _displays_id; + return _accepts_modifications; +} + +//////////////////////////////////////////////////////////////////////////////// +bool Command::accepts_miscellaneous () const +{ + return _accepts_miscellaneous; +} + +//////////////////////////////////////////////////////////////////////////////// +Command::Category Command::category () const +{ + return _category; } //////////////////////////////////////////////////////////////////////////////// @@ -290,7 +312,6 @@ // rc.confirmation // this->_read_only bool Command::permission ( - const Task& task, const std::string& question, unsigned int quantity) { diff -Nru task-2.4.4+dfsg/src/commands/Command.h task-2.5.0+dfsg/src/commands/Command.h --- task-2.4.4+dfsg/src/commands/Command.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/commands/Command.h 2015-10-21 21:18:15.000000000 +0000 @@ -35,10 +35,24 @@ class Command { public: + enum class Category + { + unassigned, + // In presentation ("usefulness") order: frequently-used categories first. + metadata, + report, + operation, + context, + graphs, + config, + migration, + misc, + internal, + UNDOCUMENTED, + // Whenever you extend this enum, update categoryNames. + }; + Command (); - Command (const Command&); - Command& operator= (const Command&); - bool operator== (const Command&) const; // TODO Is this necessary? virtual ~Command (); static void factory (std::map &); @@ -48,10 +62,17 @@ std::string description () const; bool read_only () const; bool displays_id () const; + bool needs_gc () const; + bool uses_context () const; + bool accepts_filter () const; + bool accepts_modifications () const; + bool accepts_miscellaneous () const; + Category category () const; virtual int execute (std::string&) = 0; protected: - bool permission (const Task&, const std::string&, unsigned int); + bool permission (const std::string&, unsigned int); + static const std::map categoryNames; protected: std::string _keyword; @@ -60,6 +81,12 @@ bool _read_only; bool _displays_id; bool _needs_confirm; + bool _needs_gc; + bool _uses_context; + bool _accepts_filter; + bool _accepts_modifications; + bool _accepts_miscellaneous; + Category _category; // Permission support bool _permission_quit; diff -Nru task-2.4.4+dfsg/src/Config.cpp task-2.5.0+dfsg/src/Config.cpp --- task-2.4.4+dfsg/src/Config.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/Config.cpp 2015-10-21 21:18:14.000000000 +0000 @@ -33,9 +33,8 @@ #include #include #include -#include -#include -#include +#include +#include #include #include #include @@ -76,11 +75,8 @@ "reserved.lines=1 # Assume a 1-line prompt\n" "\n" "# Miscellaneous\n" - "verbose=yes # Provide maximal feedback\n" - "#verbose=no # Provide regular feedback\n" - "#verbose=nothing # Provide no feedback\n" "# # Comma-separated list. May contain any subset of:\n" - "#verbose=blank,header,footnote,label,new-id,new-uuid,affected,edit,special,project,sync,filter\n" + "verbose=blank,header,footnote,label,new-id,new-uuid,affected,edit,special,project,sync,unwait,recur\n" "confirmation=yes # Confirmation on delete, big changes\n" "recurrence=yes # Enable recurrence\n" "recurrence.confirmation=prompt # Confirmation for propagating changes among recurring tasks (yes/no/prompt)\n" @@ -91,11 +87,7 @@ "column.padding=1 # Spaces between each column in a report\n" "bulk=3 # 3 or more tasks considered a bulk change and is confirmed\n" "nag=You have more urgent tasks. # Nag message to keep you honest\n" // TODO -#ifdef CYGWIN - "search.case.sensitive=no # Case-insensitive regex searches are broken under Cygwin\n" -#else "search.case.sensitive=yes # Setting to no allows case insensitive searches\n" -#endif "active.indicator=* # What to show as an active task indicator\n" "tag.indicator=+ # What to show as a tag indicator\n" "dependency.indicator=D # What to show as a dependency indicator\n" @@ -107,7 +99,8 @@ "xterm.title=no # Sets xterm title for some commands\n" "expressions=infix # Prefer infix over postfix expressions\n" "dom=on # Support DOM access\n" - "json.array=off # Enclose JSON output in [ ]\n" + "json.array=on # Enclose JSON output in [ ]\n" + "json.depends.array=on # Encode dependencies as a JSON array\n" "abbreviation.minimum=2 # Shortest allowed abbreviation\n" "\n" "# Dates\n" @@ -119,7 +112,7 @@ "dateformat.annotation= # Preferred display date format for annotations\n" "date.iso=yes # Enable ISO date support\n" "weekstart=" - STRING_DATE_SUNDAY_LONG + STRING_DATE_SUNDAY " # Sunday or Monday only\n" "displayweeknumber=yes # Show week numbers on calendar\n" "due=7 # Task is considered due in 7 days\n" @@ -144,7 +137,7 @@ "dependency.confirmation=on # Should dependency chain repair be confirmed?\n" "\n" "# Urgency Coefficients\n" - "urgency.next.coefficient=15.0 # Urgency coefficient for 'next' special tag\n" + "urgency.user.tag.next.coefficient=15.0 # Urgency coefficient for 'next' special tag\n" "urgency.due.coefficient=12.0 # Urgency coefficient for due dates\n" "urgency.blocking.coefficient=8.0 # Urgency coefficient for blocking tasks\n" "urgency.active.coefficient=4.0 # Urgency coefficient for active tasks\n" @@ -154,8 +147,8 @@ "urgency.tags.coefficient=1.0 # Urgency coefficient for tags\n" "urgency.project.coefficient=1.0 # Urgency coefficient for projects\n" "urgency.blocked.coefficient=-5.0 # Urgency coefficient for blocked tasks\n" - "urgency.inherit.coefficient=0.0 # Urgency coefficient for blocked tasks inheriting from blocking tasks\n" "urgency.waiting.coefficient=-3.0 # Urgency coefficient for waiting status\n" + "urgency.inherit=off # Recursively inherit highest urgency value from blocked tasks\n" "urgency.age.max=365 # Maximum age in days\n" "\n" "#urgency.user.project.foo.coefficient=5.0 # Urgency coefficients for 'foo' project\n" @@ -169,6 +162,7 @@ "rule.precedence.color=deleted,completed,active,keyword.,tag.,project.,overdue,scheduled,due.today,due,blocked,blocking,recurring,tagged,uda.\n" "\n" "# General decoration\n" + "rule.color.merge=yes\n" "color.label=\n" "color.label.sort=\n" "color.alternate=on gray2\n" @@ -243,6 +237,7 @@ "rule.precedence.color=deleted,completed,active,keyword.,tag.,project.,overdue,scheduled,due.today,due,blocked,blocking,recurring,tagged,uda.\n" "\n" "# General decoration\n" + "rule.color.merge=yes\n" "color.label=\n" "color.label.sort=\n" "color.alternate=\n" @@ -342,6 +337,7 @@ "list.all.tags=no # Include old tag names in 'tags' command\n" "print.empty.columns=no # Print columns which have no data for any task\n" "debug=no # Display diagnostics\n" + "sugar=yes # Syntactic sugar\n" "obfuscate=no # Obfuscate data for error reporting\n" "fontunderline=yes # Uses underlines rather than -------\n" "shell.prompt=task> # Prompt used by the shell command\n" @@ -387,19 +383,19 @@ "report.minimal.description=Minimal details of tasks\n" "report.minimal.labels=ID,Project,Tags,Description\n" "report.minimal.columns=id,project,tags.count,description.count\n" - "report.minimal.filter=(status:pending or status:waiting)\n" + "report.minimal.filter=status:pending or status:waiting\n" "report.minimal.sort=project+/,description+\n" "\n" "report.newest.description=Newest tasks\n" "report.newest.labels=ID,Active,Created,Age,Mod,D,P,Project,Tags,R,Wait,Sch,Due,Until,Description\n" "report.newest.columns=id,start.age,entry,entry.age,modified.age,depends.indicator,priority,project,tags,recur.indicator,wait.remaining,scheduled.countdown,due,until.age,description\n" - "report.newest.filter=(status:pending or status:waiting)\n" + "report.newest.filter=status:pending or status:waiting\n" "report.newest.sort=entry-\n" "\n" "report.oldest.description=Oldest tasks\n" "report.oldest.labels=ID,Active,Created,Age,Mod,D,P,Project,Tags,R,Wait,Sch,Due,Until,Description\n" "report.oldest.columns=id,start.age,entry,entry.age,modified.age,depends.indicator,priority,project,tags,recur.indicator,wait.remaining,scheduled.countdown,due,until.age,description\n" - "report.oldest.filter=(status:pending or status:waiting)\n" + "report.oldest.filter=status:pending or status:waiting\n" "report.oldest.sort=entry+\n" "\n" "report.overdue.description=Overdue tasks\n" @@ -410,12 +406,12 @@ "\n" "report.active.description=Active tasks\n" "report.active.labels=ID,Started,Active,Age,D,P,Project,Tags,Recur,W,Sch,Due,Until,Description\n" - "report.active.columns=id,start,start.age,entry.age,depends.indicator,priority,project,tags,recur,wait.indicator,scheduled.remaining,due,until,description\n" + "report.active.columns=id,start,start.age,entry.age,depends.indicator,priority,project,tags,recur,wait,scheduled.remaining,due,until,description\n" "report.active.filter=status:pending and +ACTIVE\n" "report.active.sort=project+,start+\n" "\n" "report.completed.description=Completed tasks\n" - "report.completed.labels=ID,UUID,Created,Completed,took,Deps,P,Project,Tags,R,Due,Description\n" + "report.completed.labels=ID,UUID,Created,Completed,Age,Deps,P,Project,Tags,R,Due,Description\n" "report.completed.columns=id,uuid.short,entry,end,entry.age,depends,priority,project,tags,recur.indicator,due,description\n" "report.completed.filter=status:completed\n" "report.completed.sort=end+\n" @@ -427,7 +423,7 @@ "report.recurring.sort=due+,urgency-,entry+\n" "\n" "report.waiting.description=Waiting (hidden) tasks\n" - "report.waiting.labels=ID,A,Age,D,P,Project,Tags,R,Wait,for,Sched,Due,Until,Description\n" + "report.waiting.labels=ID,A,Age,D,P,Project,Tags,R,Wait,Remaining,Sched,Due,Until,Description\n" "report.waiting.columns=id,start.active,entry.age,depends.indicator,priority,project,tags,recur.indicator,wait,wait.remaining,scheduled,due,until,description\n" "report.waiting.filter=+WAITING\n" "report.waiting.sort=due+,wait+,entry+\n" @@ -463,7 +459,7 @@ "\n" "report.blocking.description=Blocking tasks\n" "report.blocking.labels=ID,UUID,A,Deps,Project,Tags,R,W,Sch,Due,Until,Description,Urg\n" - "report.blocking.columns=id,uuid.short,start.active,depends,project,tags,recur,wait.indicator,scheduled.remaining,due.remaining,until.remaining,description.count,urgency\n" + "report.blocking.columns=id,uuid.short,start.active,depends,project,tags,recur,wait,scheduled.remaining,due.remaining,until.remaining,description.count,urgency\n" "report.blocking.sort=urgency-,due+,entry+\n" "report.blocking.filter= status:pending +BLOCKING\n" "\n"; @@ -528,13 +524,10 @@ split (lines, input, "\n"); // Parse each line. - std::vector ::iterator it; - for (it = lines.begin (); it != lines.end (); ++it) + for (auto& line : lines) { - std::string line = *it; - // Remove comments. - std::string::size_type pound = line.find ("#"); // no i18n + auto pound = line.find ("#"); // no i18n if (pound != std::string::npos) line = line.substr (0, pound); @@ -543,7 +536,7 @@ // Skip empty lines. if (line.length () > 0) { - std::string::size_type equal = line.find ("="); // no i18n + auto equal = line.find ("="); // no i18n if (equal != std::string::npos) { std::string key = trim (line.substr (0, equal), " \t"); // no i18n @@ -553,7 +546,7 @@ } else { - std::string::size_type include = line.find ("include"); // no i18n. + auto include = line.find ("include"); // no i18n. if (include != std::string::npos) { Path included (trim (line.substr (include + 7), " \t")); @@ -578,10 +571,10 @@ void Config::createDefaultRC (const std::string& rc, const std::string& data) { // Override data.location in the defaults. - std::string::size_type loc = _defaults.find ("data.location=~/.task"); + auto loc = _defaults.find ("data.location=~/.task"); // loc+0^ +14^ +21^ - Date now; + ISO8601d now; std::stringstream contents; contents << "# [Created by " << PACKAGE_STRING @@ -641,20 +634,20 @@ } //////////////////////////////////////////////////////////////////////////////// -const bool Config::has (const std::string& key) +bool Config::has (const std::string& key) { return (*this).find (key) != (*this).end (); } //////////////////////////////////////////////////////////////////////////////// // Return the configuration value given the specified key. -const std::string Config::get (const std::string& key) +std::string Config::get (const std::string& key) { return (*this)[key]; } //////////////////////////////////////////////////////////////////////////////// -const int Config::getInteger (const std::string& key) +int Config::getInteger (const std::string& key) { if ((*this).find (key) != (*this).end ()) return strtoimax ((*this)[key].c_str (), NULL, 10); @@ -663,8 +656,13 @@ } //////////////////////////////////////////////////////////////////////////////// -const double Config::getReal (const std::string& key) +double Config::getReal (const std::string& key) { + //NOTE: Backwards compatible handling of next coefficient. + //TODO: Remove. + if (key == "urgency.user.tag.next.coefficient" and has("urgency.next.coefficient")) + return getReal("urgency.next.coefficient"); + if ((*this).find (key) != (*this).end ()) return strtod ((*this)[key].c_str (), NULL); @@ -672,7 +670,7 @@ } //////////////////////////////////////////////////////////////////////////////// -const bool Config::getBoolean (const std::string& key) +bool Config::getBoolean (const std::string& key) { if ((*this).find (key) != (*this).end ()) { @@ -714,9 +712,8 @@ // Provide a vector of all configuration keys. void Config::all (std::vector& items) const { - std::map ::const_iterator it; - for (it = this->begin (); it != this->end (); ++it) - items.push_back (it->first); + for (auto& it : *this) + items.push_back (it.first); } //////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/Config.h task-2.5.0+dfsg/src/Config.h --- task-2.4.4+dfsg/src/Config.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/Config.h 2015-10-21 21:18:14.000000000 +0000 @@ -30,7 +30,7 @@ #include #include #include -#include +#include class Config : public std::map { @@ -49,11 +49,11 @@ void setDefaults (); void clear (); - const bool has (const std::string&); - const std::string get (const std::string&); - const int getInteger (const std::string&); - const double getReal (const std::string&); - const bool getBoolean (const std::string&); + bool has (const std::string&); + std::string get (const std::string&); + int getInteger (const std::string&); + double getReal (const std::string&); + bool getBoolean (const std::string&); void set (const std::string&, const int); void set (const std::string&, const double); diff -Nru task-2.4.4+dfsg/src/Context.cpp task-2.5.0+dfsg/src/Context.cpp --- task-2.4.4+dfsg/src/Context.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/Context.cpp 2015-10-21 21:18:14.000000000 +0000 @@ -34,10 +34,10 @@ #include #include #include -#include -#include +#include #include #include +#include #include #include #include @@ -84,18 +84,17 @@ //////////////////////////////////////////////////////////////////////////////// Context::~Context () { - std::map::iterator com; - for (com = commands.begin (); com != commands.end (); ++com) - delete com->second; - - std::map::iterator col; - for (col = columns.begin (); col != columns.end (); ++col) - delete col->second; + for (auto& com : commands) + delete com.second; + + for (auto& col : columns) + delete col.second; } //////////////////////////////////////////////////////////////////////////////// int Context::initialize (int argc, const char** argv) { + timer_total.start (); timer_init.start (); int rc = 0; @@ -112,7 +111,7 @@ // //////////////////////////////////////////////////////////////////////////// - CLI::getOverride (argc, argv, home_dir, rc_file); + CLI2::getOverride (argc, argv, home_dir, rc_file); char* override = getenv ("TASKRC"); if (override) @@ -123,7 +122,7 @@ config.clear (); config.load (rc_file); - CLI::applyOverrides (argc, argv); + CLI2::applyOverrides (argc, argv); //////////////////////////////////////////////////////////////////////////// // @@ -136,7 +135,7 @@ // //////////////////////////////////////////////////////////////////////////// - CLI::getDataLocation (argc, argv, data_dir); + CLI2::getDataLocation (argc, argv, data_dir); override = getenv ("TASKDATA"); if (override) @@ -151,33 +150,25 @@ //////////////////////////////////////////////////////////////////////////// // - // [3] Instantiate Command objects and capture entities. + // [3] Instantiate Command objects and capture command entities. // //////////////////////////////////////////////////////////////////////////// Command::factory (commands); - std::map ::iterator cmd; - for (cmd = commands.begin (); cmd != commands.end (); ++cmd) - { - cli.entity ("cmd", cmd->first); - cli.entity ((cmd->second->read_only () ? "readcmd" : "writecmd"), cmd->first); - - if (cmd->first[0] == '_') - cli.entity ("helper", cmd->first); - } + for (auto& cmd : commands) + cli2.entity ("cmd", cmd.first); //////////////////////////////////////////////////////////////////////////// // - // [4] Instantiate Column objects and capture entities. + // [4] Instantiate Column objects and capture column entities. // //////////////////////////////////////////////////////////////////////////// Column::factory (columns); - std::map ::iterator col; - for (col = columns.begin (); col != columns.end (); ++col) - cli.entity ("attribute", col->first); + for (auto& col : columns) + cli2.entity ("attribute", col.first); - cli.entity ("pseudo", "limit"); + cli2.entity ("pseudo", "limit"); //////////////////////////////////////////////////////////////////////////// // @@ -186,17 +177,13 @@ //////////////////////////////////////////////////////////////////////////// for (unsigned int i = 0; i < NUM_MODIFIER_NAMES; ++i) - cli.entity ("modifier", modifierNames[i]); + cli2.entity ("modifier", modifierNames[i]); + + for (auto& op : Eval::getOperators ()) + cli2.entity ("operator", op); - std::vector operators; - Eval::getOperators (operators); - std::vector ::iterator op; - for (op = operators.begin (); op != operators.end (); ++op) - cli.entity ("operator", *op); - - Eval::getBinaryOperators (operators); - for (op = operators.begin (); op != operators.end (); ++op) - cli.entity ("binary_operator", *op); + for (auto& op : Eval::getBinaryOperators ()) + cli2.entity ("binary_operator", op); //////////////////////////////////////////////////////////////////////////// // @@ -215,29 +202,26 @@ // //////////////////////////////////////////////////////////////////////////// - // Scan command line for 'rc:' only. - cli.initialize (argc, argv); - cli.analyze (true, true); + for (int i = 0; i < argc; i++) + cli2.add (argv[i]); + + cli2.analyze (); // Extract a recomposed command line. bool foundDefault = false; bool foundAssumed = false; std::string combined; - std::vector ::const_iterator a; - for (a = cli._args.begin (); a != cli._args.end (); ++a) + for (auto& a : cli2._args) { if (combined.length ()) combined += ' '; - if (a->attribute ("canonical") != "") - combined += a->attribute ("canonical"); - else - combined += a->attribute ("raw"); + combined += a.attribute ("raw"); - if (a->hasTag ("DEFAULT")) + if (a.hasTag ("DEFAULT")) foundDefault = true; - if (a->hasTag ("ASSUMED")) + if (a.hasTag ("ASSUMED")) foundAssumed = true; } @@ -280,44 +264,40 @@ // Dump all debug messages, controlled by rc.debug. if (config.getBoolean ("debug")) { - std::vector ::iterator d; - for (d = debugMessages.begin (); d != debugMessages.end (); ++d) + for (auto& d : debugMessages) if (color ()) - std::cerr << colorizeDebug (*d) << "\n"; + std::cerr << colorizeDebug (d) << "\n"; else - std::cerr << *d << "\n"; + std::cerr << d << "\n"; } // Dump all headers, controlled by 'header' verbosity token. if (verbose ("header")) { - std::vector ::iterator h; - for (h = headers.begin (); h != headers.end (); ++h) + for (auto& h : headers) if (color ()) - std::cerr << colorizeHeader (*h) << "\n"; + std::cerr << colorizeHeader (h) << "\n"; else - std::cerr << *h << "\n"; + std::cerr << h << "\n"; } // Dump all footnotes, controlled by 'footnote' verbosity token. if (verbose ("footnote")) { - std::vector ::iterator f; - for (f = footnotes.begin (); f != footnotes.end (); ++f) + for (auto& f : footnotes) if (color ()) - std::cerr << colorizeFootnote (*f) << "\n"; + std::cerr << colorizeFootnote (f) << "\n"; else - std::cerr << *f << "\n"; + std::cerr << f << "\n"; } // Dump all errors, non-maskable. // Colorized as footnotes. - std::vector ::iterator e; - for (e = errors.begin (); e != errors.end (); ++e) + for (auto& e : errors) if (color ()) - std::cerr << colorizeFootnote (*e) << "\n"; + std::cerr << colorizeFootnote (e) << "\n"; else - std::cerr << *e << "\n"; + std::cerr << e << "\n"; } timer_init.stop (); @@ -337,6 +317,8 @@ tdb2.commit (); // Harmless if called when nothing changed. hooks.onExit (); // No chance to update data. + timer_total.stop (); + std::stringstream s; s << "Perf " << PACKAGE_STRING @@ -347,7 +329,7 @@ << "-" #endif << " " - << Date ().toISO () + << ISO8601d ().toISO () << " init:" << timer_init.total () << " load:" << timer_load.total () @@ -357,7 +339,8 @@ << " sort:" << timer_sort.total () << " render:" << timer_render.total () << " hooks:" << timer_hooks.total () - << " total:" << (timer_init.total () + + << " other:" << timer_total.total () - + (timer_init.total () + timer_load.total () + timer_gc.total () + timer_filter.total () + @@ -365,6 +348,7 @@ timer_sort.total () + timer_render.total () + timer_hooks.total ()) + << " total:" << timer_total.total () << "\n"; debug (s.str ()); } @@ -390,23 +374,21 @@ // Dump all debug messages, controlled by rc.debug. if (config.getBoolean ("debug")) { - std::vector ::iterator d; - for (d = debugMessages.begin (); d != debugMessages.end (); ++d) + for (auto& d : debugMessages) if (color ()) - std::cerr << colorizeDebug (*d) << "\n"; + std::cerr << colorizeDebug (d) << "\n"; else - std::cerr << *d << "\n"; + std::cerr << d << "\n"; } // Dump all headers, controlled by 'header' verbosity token. if (verbose ("header")) { - std::vector ::iterator h; - for (h = headers.begin (); h != headers.end (); ++h) + for (auto& h : headers) if (color ()) - std::cerr << colorizeHeader (*h) << "\n"; + std::cerr << colorizeHeader (h) << "\n"; else - std::cerr << *h << "\n"; + std::cerr << h << "\n"; } // Dump the report output. @@ -415,22 +397,20 @@ // Dump all footnotes, controlled by 'footnote' verbosity token. if (verbose ("footnote")) { - std::vector ::iterator f; - for (f = footnotes.begin (); f != footnotes.end (); ++f) + for (auto& f : footnotes) if (color ()) - std::cerr << colorizeFootnote (*f) << "\n"; + std::cerr << colorizeFootnote (f) << "\n"; else - std::cerr << *f << "\n"; + std::cerr << f << "\n"; } // Dump all errors, non-maskable. // Colorized as footnotes. - std::vector ::iterator e; - for (e = errors.begin (); e != errors.end (); ++e) + for (auto& e : errors) if (color ()) - std::cerr << colorizeError (*e) << "\n"; + std::cerr << colorizeError (e) << "\n"; else - std::cerr << *e << "\n"; + std::cerr << e << "\n"; return rc; } @@ -440,7 +420,7 @@ int Context::dispatch (std::string &out) { // Autocomplete args against keywords. - std::string command = cli.getCommand (); + std::string command = cli2.getCommand (); if (command != "") { updateXtermTitle (); @@ -449,9 +429,9 @@ Command* c = commands[command]; assert (c); - // GC is invoked prior to running any command that displays task IDs, if - // possible. - if (c->displays_id () && !tdb2.read_only ()) + // The command know whether they need a GC. + if (c->needs_gc () && + ! tdb2.read_only ()) { run_gc = config.getBoolean ("gc"); tdb2.gc (); @@ -468,6 +448,21 @@ throw std::string (""); */ + // This is something that is only needed for write commands with no other + // filter processing. + if (c->accepts_modifications () && + ! c->accepts_filter ()) + { + cli2.prepareFilter (); + } + + // With rc.debug.parser == 2, there are more tree dumps than you might want, + // but we need the rc.debug.parser == 1 case covered also, with the final + // tree. + if (config.getBoolean ("debug") && + config.getInteger ("debug.parser") == 1) + debug (cli2.dump ("Parse Tree (before command-specifіc processing)")); + return c->execute (out); } @@ -478,7 +473,6 @@ //////////////////////////////////////////////////////////////////////////////// bool Context::color () { -#ifdef FEATURE_COLOR if (determine_color_use) { // What the config says. @@ -508,9 +502,6 @@ // Cached result. return use_color; -#else - return false; -#endif } //////////////////////////////////////////////////////////////////////////////// @@ -526,7 +517,7 @@ // take the place of '0'. bool Context::verbose (const std::string& token) { - if (! verbosity.size ()) + if (verbosity.empty ()) { verbosity_legacy = config.getBoolean ("verbose"); split (verbosity, config.get ("verbose"), ','); @@ -535,29 +526,42 @@ // This odd test is to see if a Boolean-false value is a real one, which // means it is not 1/true/T/yes/on, but also should not be one of the // valid tokens either. - if (!verbosity_legacy && - verbosity.size () && - verbosity[0] != "nothing" && - verbosity[0] != "blank" && // This list must be complete. - verbosity[0] != "header" && // - verbosity[0] != "footnote" && // - verbosity[0] != "label" && // - verbosity[0] != "new-id" && // - verbosity[0] != "new-uuid" && // - verbosity[0] != "affected" && // - verbosity[0] != "edit" && // - verbosity[0] != "special" && // - verbosity[0] != "project" && // - verbosity[0] != "sync" && // - verbosity[0] != "filter") // - { - verbosity.clear (); - - // This list emulates rc.verbose=off in version 1.9.4. - verbosity.push_back ("blank"); - verbosity.push_back ("label"); - verbosity.push_back ("new-id"); - verbosity.push_back ("edit"); + if (! verbosity_legacy && ! verbosity.empty ()) + { + std::string v = *(verbosity.begin ()); + if (v != "nothing" && + v != "blank" && // This list must be complete. + v != "header" && // + v != "footnote" && // + v != "label" && // + v != "new-id" && // + v != "new-uuid" && // + v != "affected" && // + v != "edit" && // + v != "special" && // + v != "project" && // + v != "sync" && // + v != "filter" && // + v != "unwait" && // + v != "recur") // + { + // This list emulates rc.verbose=off in version 1.9.4. + verbosity = {"blank", "label", "new-id", "edit"}; + } + } + + // Some flags imply "footnote" verbosity being active. Make it so. + if (! verbosity.count ("footnote")) + { + // TODO: Some of these may not use footnotes yet. They should. + for (auto flag : {"affected", "new-id", "new-uuid", "project", "unwait", "recur"}) + { + if (verbosity.count (flag)) + { + verbosity.insert ("footnote"); + break; + } + } } } @@ -567,11 +571,11 @@ // rc.verbose=nothing overrides all. if (verbosity.size () == 1 && - verbosity[0] == "nothing") + *(verbosity.begin ()) == "nothing") return false; // Specific token match. - if (std::find (verbosity.begin (), verbosity.end (), token) != verbosity.end ()) + if (verbosity.count (token)) return true; return false; @@ -581,20 +585,8 @@ const std::vector Context::getColumns () const { std::vector output; - std::map ::const_iterator i; - for (i = columns.begin (); i != columns.end (); ++i) - output.push_back (i->first); - - return output; -} - -//////////////////////////////////////////////////////////////////////////////// -const std::vector Context::getCommands () const -{ - std::vector output; - std::map ::const_iterator i; - for (i = commands.begin (); i != commands.end (); ++i) - output.push_back (i->first); + for (auto& col : columns) + output.push_back (col.first); return output; } @@ -609,7 +601,7 @@ lines = 0; // This is an integer specified as a filter (limit:10). - std::string limit = cli.getLimit (); + std::string limit = config.get ("limit"); if (limit != "") { if (limit == "page") @@ -630,7 +622,9 @@ // easier, it has been decoupled from Context. void Context::staticInitialization () { - CLI::minimumMatchLength = config.getInteger ("abbreviation.minimum"); + CLI2::minimumMatchLength = config.getInteger ("abbreviation.minimum"); + Lexer::minimumMatchLength = config.getInteger ("abbreviation.minimum"); + ISO8601d::minimumMatchLength = config.getInteger ("abbreviation.minimum"); Task::defaultProject = config.get ("default.project"); Task::defaultDue = config.get ("default.due"); @@ -638,36 +632,39 @@ Task::searchCaseSensitive = Variant::searchCaseSensitive = config.getBoolean ("search.case.sensitive"); Task::regex = Variant::searchUsingRegex = config.getBoolean ("regex"); Lexer::dateFormat = Variant::dateFormat = config.get ("dateformat"); - Lexer::isoEnabled = Variant::isoEnabled = config.getBoolean ("date.iso"); + ISO8601p::isoEnabled = ISO8601d::isoEnabled = config.getBoolean ("date.iso"); + + TDB2::debug_mode = config.getBoolean ("debug"); - Config::const_iterator rc; - for (rc = config.begin (); rc != config.end (); ++rc) + ISO8601d::weekstart = config.get ("weekstart"); + + for (auto& rc : config) { - if (rc->first.substr (0, 4) == "uda." && - rc->first.substr (rc->first.length () - 7, 7) == ".values") + if (rc.first.substr (0, 4) == "uda." && + rc.first.substr (rc.first.length () - 7, 7) == ".values") { - std::string name = rc->first.substr (4, rc->first.length () - 7 - 4); + std::string name = rc.first.substr (4, rc.first.length () - 7 - 4); std::vector values; - split (values, rc->second, ','); + split (values, rc.second, ','); for (auto r = values.rbegin(); r != values.rend (); ++r) Task::customOrder[name].push_back (*r); } } - std::map ::iterator i; - for (i = columns.begin (); i != columns.end (); ++i) - Task::attributes[i->first] = i->second->type (); + for (auto& col : columns) + { + Task::attributes[col.first] = col.second->type (); + Lexer::attributes[col.first] = col.second->type (); + } Task::urgencyProjectCoefficient = config.getReal ("urgency.project.coefficient"); Task::urgencyActiveCoefficient = config.getReal ("urgency.active.coefficient"); Task::urgencyScheduledCoefficient = config.getReal ("urgency.scheduled.coefficient"); Task::urgencyWaitingCoefficient = config.getReal ("urgency.waiting.coefficient"); Task::urgencyBlockedCoefficient = config.getReal ("urgency.blocked.coefficient"); - Task::urgencyInheritCoefficient = config.getReal ("urgency.inherit.coefficient"); Task::urgencyAnnotationsCoefficient = config.getReal ("urgency.annotations.coefficient"); Task::urgencyTagsCoefficient = config.getReal ("urgency.tags.coefficient"); - Task::urgencyNextCoefficient = config.getReal ("urgency.next.coefficient"); Task::urgencyDueCoefficient = config.getReal ("urgency.due.coefficient"); Task::urgencyBlockingCoefficient = config.getReal ("urgency.blocking.coefficient"); Task::urgencyAgeCoefficient = config.getReal ("urgency.age.coefficient"); @@ -676,11 +673,10 @@ // Tag- and project-specific coefficients. std::vector all; config.all (all); - std::vector ::iterator var; - for (var = all.begin (); var != all.end (); ++var) - if (var->substr (0, 13) == "urgency.user." || - var->substr (0, 12) == "urgency.uda.") - Task::coefficients[*var] = config.getReal (*var); + for (auto& var : all) + if (var.substr (0, 13) == "urgency.user." || + var.substr (0, 12) == "urgency.uda.") + Task::coefficients[var] = config.getReal (var); } //////////////////////////////////////////////////////////////////////////////// @@ -735,45 +731,18 @@ } //////////////////////////////////////////////////////////////////////////////// -// Note: The reason some of these are commented out is because the ::clear -// method is not really "clear" but "clear_some". Some members do not need to -// be initialized. That makes this method something of a misnomer. So be it. -// -// TODO Is this method used anywhere? -void Context::clear () -{ - tdb2.clear (); - - // Eliminate the command objects. - std::map ::iterator com; - for (com = commands.begin (); com != commands.end (); ++com) - delete com->second; - - commands.clear (); - - // Eliminate the column objects. - std::map ::iterator col; - for (col = columns.begin (); col != columns.end (); ++col) - delete col->second; - - columns.clear (); - clearMessages (); -} - -//////////////////////////////////////////////////////////////////////////////// // This capability is to answer the question of 'what did I just do to generate // this output?'. void Context::updateXtermTitle () { if (config.getBoolean ("xterm.title") && isatty (STDOUT_FILENO)) { - std::string command = cli.getCommand (); + std::string command = cli2.getCommand (); std::string title; - std::vector ::const_iterator a; - for (a = cli._args.begin (); a != cli._args.end (); ++a) + for (auto a = cli2._args.begin (); a != cli2._args.end (); ++a) { - if (a != cli._args.begin ()) + if (a != cli2._args.begin ()) title += ' '; title += a->attribute ("raw"); @@ -787,22 +756,20 @@ // This function allows a clean output if the command is a helper subcommand. void Context::updateVerbosity () { - std::string command = cli.getCommand (); + std::string command = cli2.getCommand (); if (command != "" && command[0] == '_') { - verbosity.clear (); - verbosity.push_back ("nothing"); + verbosity = {"nothing"}; } } //////////////////////////////////////////////////////////////////////////////// void Context::loadAliases () { - std::map ::iterator i; - for (i = config.begin (); i != config.end (); ++i) - if (i->first.substr (0, 6) == "alias.") - cli.alias (i->first.substr (6), i->second); + for (auto& i : config) + if (i.first.substr (0, 6) == "alias.") + cli2.alias (i.first.substr (6), i.second); } //////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/Context.h task-2.5.0+dfsg/src/Context.h --- task-2.4.4+dfsg/src/Context.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/Context.h 2015-10-21 21:18:14.000000000 +0000 @@ -34,11 +34,10 @@ #include #include #include -#include -#include -#include -#include +#include +#include #include +#include class Context { @@ -57,7 +56,6 @@ int getHeight (); // determine terminal height const std::vector getColumns () const; - const std::vector getCommands () const; void getLimits (int&, int&); bool color (); // TTY or ? @@ -68,7 +66,6 @@ void debug (const std::string&); // Debug message sink void error (const std::string&); // Error message sink - non-maskable void clearMessages (); - void clear (); void decomposeSortField (const std::string&, std::string&, bool&, bool&); @@ -81,7 +78,7 @@ void propagateDebug (); public: - CLI cli; + CLI2 cli2; std::string home_dir; File rc_file; Path data_dir; @@ -97,7 +94,7 @@ bool run_gc; bool verbosity_legacy; - std::vector verbosity; + std::set verbosity; std::vector headers; std::vector footnotes; std::vector errors; @@ -109,6 +106,7 @@ int terminal_width; int terminal_height; + Timer timer_total; Timer timer_init; Timer timer_load; Timer timer_gc; diff -Nru task-2.4.4+dfsg/src/Date.cpp task-2.5.0+dfsg/src/Date.cpp --- task-2.4.4+dfsg/src/Date.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/Date.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,836 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern Context context; - -//////////////////////////////////////////////////////////////////////////////// -// Defaults to "now". -Date::Date () -{ - _t = time (NULL); -} - -//////////////////////////////////////////////////////////////////////////////// -Date::Date (const time_t t) -{ - _t = t; -} - -//////////////////////////////////////////////////////////////////////////////// -Date::Date (const int m, const int d, const int y) -{ - // Error if not valid. - struct tm t = {0}; - t.tm_isdst = -1; // Requests that mktime determine summer time effect. - t.tm_mday = d; - t.tm_mon = m - 1; - t.tm_year = y - 1900; - - _t = mktime (&t); -} - -//////////////////////////////////////////////////////////////////////////////// -Date::Date (const int m, const int d, const int y, - const int hr, const int mi, const int se) -{ - // Error if not valid. - struct tm t = {0}; - t.tm_isdst = -1; // Requests that mktime determine summer time effect. - t.tm_mday = d; - t.tm_mon = m - 1; - t.tm_year = y - 1900; - t.tm_hour = hr; - t.tm_min = mi; - t.tm_sec = se; - - _t = mktime (&t); -} - -//////////////////////////////////////////////////////////////////////////////// -Date::Date ( - const std::string& input, - const std::string& format /* = "m/d/Y" */, - const bool iso /* = true */, - const bool epoch /* = true */) -{ - // Check first to see if this is supported as a named date. - Variant v; - if (namedDates (input, v)) - { - _t = v.get_date (); - return; - } - - // Parse a formatted date. - Nibbler n (input); - n.save (); -#ifdef NIBBLER_FEATURE_DATE - if (n.getDate (format, _t) && n.depleted ()) - return; -#endif - - // Parse an ISO date. - n.restore (); - if (iso && n.getDateISO (_t) && n.depleted ()) - return; - - // Perhaps it is an epoch date, in string form? - n.restore (); - if (epoch && isEpoch (input)) - return; - - throw ::format (STRING_DATE_INVALID_FORMAT, input, format); -} - -//////////////////////////////////////////////////////////////////////////////// -Date::Date ( - const std::string& input, - std::string::size_type& i, - const std::string& format /* = "m/d/Y" */, - const bool iso /* = true */, - const bool epoch /* = true */) -{ - // Check first to see if this is supported as a named date. - Variant v; - if (namedDates (input, v)) - { - i = v.source ().length (); - _t = v.get_date (); - return; - } - - // Parse a formatted date. - Nibbler n (input); - n.save (); -#ifdef NIBBLER_FEATURE_DATE - if (n.getDate (format, _t)) - { - i = n.cursor (); - return; - } -#endif - - // Parse an ISO date. - n.restore (); - if (iso && n.getDateISO (_t)) - { - i = n.cursor (); - return; - } - - // Perhaps it is an epoch date, in string form? - n.restore (); - if (epoch && isEpoch (input)) - { - i = 10; - return; - } - - throw ::format (STRING_DATE_INVALID_FORMAT, input, format); -} - -//////////////////////////////////////////////////////////////////////////////// -Date::Date (const Date& rhs) -{ - _t = rhs._t; -} - -//////////////////////////////////////////////////////////////////////////////// -Date::~Date () -{ -} - -//////////////////////////////////////////////////////////////////////////////// -time_t Date::toEpoch () -{ - return _t; -} - -//////////////////////////////////////////////////////////////////////////////// -std::string Date::toEpochString () -{ - std::stringstream epoch; - epoch << _t; - return epoch.str (); -} - -//////////////////////////////////////////////////////////////////////////////// -// 19980119T070000Z = YYYYMMDDThhmmssZ -std::string Date::toISO () -{ - struct tm* t = gmtime (&_t); - - std::stringstream iso; - iso << std::setw (4) << std::setfill ('0') << t->tm_year + 1900 - << std::setw (2) << std::setfill ('0') << t->tm_mon + 1 - << std::setw (2) << std::setfill ('0') << t->tm_mday - << "T" - << std::setw (2) << std::setfill ('0') << t->tm_hour - << std::setw (2) << std::setfill ('0') << t->tm_min - << std::setw (2) << std::setfill ('0') << t->tm_sec - << "Z"; - - return iso.str (); -} - -//////////////////////////////////////////////////////////////////////////////// -double Date::toJulian () -{ - return (_t / 86400.0) + 2440587.5; -} - -//////////////////////////////////////////////////////////////////////////////// -void Date::toEpoch (time_t& epoch) -{ - epoch = _t; -} - -//////////////////////////////////////////////////////////////////////////////// -void Date::toMDY (int& m, int& d, int& y) -{ - struct tm* t = localtime (&_t); - - m = t->tm_mon + 1; - d = t->tm_mday; - y = t->tm_year + 1900; -} - -//////////////////////////////////////////////////////////////////////////////// -const std::string Date::toString ( - const std::string& format /*= "m/d/Y" */) const -{ - // Making this local copy seems to fix a bug. Remove the local copy and - // you'll see segmentation faults and all kinds of gibberish. - std::string localFormat = format; - - char buffer[12]; - std::string formatted; - for (unsigned int i = 0; i < localFormat.length (); ++i) - { - int c = localFormat[i]; - switch (c) - { - case 'm': sprintf (buffer, "%d", this->month ()); break; - case 'M': sprintf (buffer, "%02d", this->month ()); break; - case 'd': sprintf (buffer, "%d", this->day ()); break; - case 'D': sprintf (buffer, "%02d", this->day ()); break; - case 'y': sprintf (buffer, "%02d", this->year () % 100); break; - case 'Y': sprintf (buffer, "%d", this->year ()); break; - case 'a': sprintf (buffer, "%.3s", Date::dayName (dayOfWeek ()).c_str ()); break; - case 'A': sprintf (buffer, "%.10s", Date::dayName (dayOfWeek ()).c_str ()); break; - case 'b': sprintf (buffer, "%.3s", Date::monthName (month ()).c_str ()); break; - case 'B': sprintf (buffer, "%.10s", Date::monthName (month ()).c_str ()); break; - case 'v': sprintf (buffer, "%d", Date::weekOfYear (Date::dayOfWeek (context.config.get ("weekstart")))); break; - case 'V': sprintf (buffer, "%02d", Date::weekOfYear (Date::dayOfWeek (context.config.get ("weekstart")))); break; - case 'h': sprintf (buffer, "%d", this->hour ()); break; - case 'H': sprintf (buffer, "%02d", this->hour ()); break; - case 'n': sprintf (buffer, "%d", this->minute ()); break; - case 'N': sprintf (buffer, "%02d", this->minute ()); break; - case 's': sprintf (buffer, "%d", this->second ()); break; - case 'S': sprintf (buffer, "%02d", this->second ()); break; - case 'j': sprintf (buffer, "%d", this->dayOfYear ()); break; - case 'J': sprintf (buffer, "%03d", this->dayOfYear ()); break; - default: sprintf (buffer, "%c", c); break; - } - - formatted += buffer; - } - - return formatted; -} - -//////////////////////////////////////////////////////////////////////////////// -Date Date::startOfDay () const -{ - return Date (month (), day (), year ()); -} - -//////////////////////////////////////////////////////////////////////////////// -Date Date::startOfWeek () const -{ - Date sow (_t); - sow -= (dayOfWeek () * 86400); - return Date (sow.month (), sow.day (), sow.year ()); -} - -//////////////////////////////////////////////////////////////////////////////// -Date Date::startOfMonth () const -{ - return Date (month (), 1, year ()); -} - -//////////////////////////////////////////////////////////////////////////////// -Date Date::startOfYear () const -{ - return Date (1, 1, year ()); -} - -//////////////////////////////////////////////////////////////////////////////// -bool Date::valid (const std::string& input, const std::string& format) -{ - try - { - Date test (input, format); - } - - catch (...) - { - return false; - } - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Date::valid (const int m, const int d, const int y, const int hr, - const int mi, const int se) -{ - if (hr < 0 || hr > 23) - return false; - - if (mi < 0 || mi > 59) - return false; - - if (se < 0 || se > 59) - return false; - - return Date::valid (m, d, y); -} - -//////////////////////////////////////////////////////////////////////////////// -bool Date::valid (const int m, const int d, const int y) -{ - // Check that the year is valid. - if (y < 0) - return false; - - // Check that the month is valid. - if (m < 1 || m > 12) - return false; - - // Finally check that the days fall within the acceptable range for this - // month, and whether or not this is a leap year. - if (d < 1 || d > Date::daysInMonth (m, y)) - return false; - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// Julian -bool Date::valid (const int d, const int y) -{ - // Check that the year is valid. - if (y < 0) - return false; - - if (d < 1 || d > Date::daysInYear (y)) - return false; - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Date::leapYear (int year) -{ - bool ly = false; - - // (year % 4 == 0) && (year % 100 !=0) OR - // (year % 400 == 0) - // are leapyears - - if (((!(year % 4)) && (year % 100)) || (!(year % 400))) ly = true; - - return ly; -} - -//////////////////////////////////////////////////////////////////////////////// -int Date::daysInMonth (int month, int year) -{ - static int days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - - if (month == 2 && Date::leapYear (year)) - return 29; - - return days[month - 1]; -} - -//////////////////////////////////////////////////////////////////////////////// -int Date::daysInYear (int year) -{ - return Date::leapYear (year) ? 366 : 365; -} - -//////////////////////////////////////////////////////////////////////////////// -std::string Date::monthName (int month) -{ - static const char* months[12] = - { - STRING_DATE_JANUARY_LONG, - STRING_DATE_FEBRUARY_LONG, - STRING_DATE_MARCH_LONG, - STRING_DATE_APRIL_LONG, - STRING_DATE_MAY_LONG, - STRING_DATE_JUNE_LONG, - STRING_DATE_JULY_LONG, - STRING_DATE_AUGUST_LONG, - STRING_DATE_SEPTEMBER_LONG, - STRING_DATE_OCTOBER_LONG, - STRING_DATE_NOVEMBER_LONG, - STRING_DATE_DECEMBER_LONG, - }; - - assert (month > 0); - assert (month <= 12); - return ucFirst (months[month - 1]); -} - -//////////////////////////////////////////////////////////////////////////////// -void Date::dayName (int dow, std::string& name) -{ - static const char* days[7] = - { - STRING_DATE_SUNDAY_LONG, - STRING_DATE_MONDAY_LONG, - STRING_DATE_TUESDAY_LONG, - STRING_DATE_WEDNESDAY_LONG, - STRING_DATE_THURSDAY_LONG, - STRING_DATE_FRIDAY_LONG, - STRING_DATE_SATURDAY_LONG, - }; - - name = ucFirst (days[dow]); -} - -//////////////////////////////////////////////////////////////////////////////// -std::string Date::dayName (int dow) -{ - static const char* days[7] = - { - STRING_DATE_SUNDAY_LONG, - STRING_DATE_MONDAY_LONG, - STRING_DATE_TUESDAY_LONG, - STRING_DATE_WEDNESDAY_LONG, - STRING_DATE_THURSDAY_LONG, - STRING_DATE_FRIDAY_LONG, - STRING_DATE_SATURDAY_LONG, - }; - - return ucFirst (days[dow]); -} - -//////////////////////////////////////////////////////////////////////////////// -int Date::weekOfYear (int weekStart) const -{ - struct tm* t = localtime (&_t); - char weekStr[3]; - - if (weekStart == 0) - strftime(weekStr, sizeof(weekStr), "%U", t); - else if (weekStart == 1) - strftime(weekStr, sizeof(weekStr), "%V", t); - else - throw std::string (STRING_DATE_BAD_WEEKSTART); - - int weekNumber = atoi (weekStr); - - if (weekStart == 0) - weekNumber += 1; - - return weekNumber; -} - -//////////////////////////////////////////////////////////////////////////////// -int Date::dayOfWeek () const -{ - struct tm* t = localtime (&_t); - return t->tm_wday; -} - -//////////////////////////////////////////////////////////////////////////////// -int Date::dayOfWeek (const std::string& input) -{ - std::string in = lowerCase (input); - - if (in == STRING_DATE_SUNDAY_LONG || in == STRING_DATE_SUNDAY_SHORT) return 0; - if (in == STRING_DATE_MONDAY_LONG || in == STRING_DATE_MONDAY_SHORT) return 1; - if (in == STRING_DATE_TUESDAY_LONG || in == STRING_DATE_TUESDAY_SHORT) return 2; - if (in == STRING_DATE_WEDNESDAY_LONG || in == STRING_DATE_WEDNESDAY_SHORT) return 3; - if (in == STRING_DATE_THURSDAY_LONG || in == STRING_DATE_THURSDAY_SHORT) return 4; - if (in == STRING_DATE_FRIDAY_LONG || in == STRING_DATE_FRIDAY_SHORT) return 5; - if (in == STRING_DATE_SATURDAY_LONG || in == STRING_DATE_SATURDAY_SHORT) return 6; - - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// -int Date::dayOfYear () const -{ - struct tm* t = localtime (&_t); - return t->tm_yday + 1; -} - -//////////////////////////////////////////////////////////////////////////////// -int Date::monthOfYear (const std::string& input) -{ - std::string in = lowerCase (input); - - if (in == STRING_DATE_JANUARY_LONG || in == STRING_DATE_JANUARY_SHORT ) return 1; - if (in == STRING_DATE_FEBRUARY_LONG || in == STRING_DATE_FEBRUARY_SHORT ) return 2; - if (in == STRING_DATE_MARCH_LONG || in == STRING_DATE_MARCH_SHORT ) return 3; - if (in == STRING_DATE_APRIL_LONG || in == STRING_DATE_APRIL_SHORT ) return 4; - if (in == STRING_DATE_MAY_LONG || in == STRING_DATE_MAY_SHORT ) return 5; - if (in == STRING_DATE_JUNE_LONG || in == STRING_DATE_JUNE_SHORT ) return 6; - if (in == STRING_DATE_JULY_LONG || in == STRING_DATE_JULY_SHORT ) return 7; - if (in == STRING_DATE_AUGUST_LONG || in == STRING_DATE_AUGUST_SHORT ) return 8; - if (in == STRING_DATE_SEPTEMBER_LONG || in == STRING_DATE_SEPTEMBER_SHORT) return 9; - if (in == STRING_DATE_OCTOBER_LONG || in == STRING_DATE_OCTOBER_SHORT ) return 10; - if (in == STRING_DATE_NOVEMBER_LONG || in == STRING_DATE_NOVEMBER_SHORT ) return 11; - if (in == STRING_DATE_DECEMBER_LONG || in == STRING_DATE_DECEMBER_SHORT ) return 12; - - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// -int Date::length (const std::string& format) -{ - int total = 0; - - std::string::const_iterator i; - for (i = format.begin (); i != format.end (); ++i) - { - switch (*i) - { - case 'm': - case 'M': - case 'd': - case 'D': - case 'y': - case 'v': - case 'V': - case 'h': - case 'H': - case 'n': - case 'N': - case 's': - case 'S': total += 2; break; - case 'b': - case 'j': - case 'J': - case 'a': total += 3; break; - case 'Y': total += 4; break; - case 'A': - case 'B': total += 10; break; - - // Calculate the width, don't assume a single character width. - default: total += mk_wcwidth (*i); break; - } - } - - return total; -} - -//////////////////////////////////////////////////////////////////////////////// -time_t Date::easter (int year) -{ - int Y = year; - int a = Y % 19; - int b = Y / 100; - int c = Y % 100; - int d = b / 4; - int e = b % 4; - int f = (b + 8) / 25; - int g = (b - f + 1) / 3; - int h = (19 * a + b - d - g + 15) % 30; - int i = c / 4; - int k = c % 4; - int L = (32 + 2 * e + 2 * i - h - k) % 7; - int m = (a + 11 * h + 22 * L) / 451; - int month = (h + L - 7 * m + 114) / 31; - int day = ((h + L - 7 * m + 114) % 31) + 1; - struct tm t = {0}; - t.tm_isdst = -1; // Requests that mktime determine summer time effect. - t.tm_mday = day; - t.tm_mon = month - 1; - t.tm_year = year - 1900; - return mktime (&t); -} - -//////////////////////////////////////////////////////////////////////////////// -int Date::month () const -{ - struct tm* t = localtime (&_t); - return t->tm_mon + 1; -} - -//////////////////////////////////////////////////////////////////////////////// -int Date::week () const -{ - return Date::weekOfYear (Date::dayOfWeek (context.config.get ("weekstart"))); -} - -//////////////////////////////////////////////////////////////////////////////// -int Date::day () const -{ - struct tm* t = localtime (&_t); - return t->tm_mday; -} - -//////////////////////////////////////////////////////////////////////////////// -int Date::year () const -{ - struct tm* t = localtime (&_t); - return t->tm_year + 1900; -} - -//////////////////////////////////////////////////////////////////////////////// -int Date::hour () const -{ - struct tm* t = localtime (&_t); - return t->tm_hour; -} - -//////////////////////////////////////////////////////////////////////////////// -int Date::minute () const -{ - struct tm* t = localtime (&_t); - return t->tm_min; -} - -//////////////////////////////////////////////////////////////////////////////// -int Date::second () const -{ - struct tm* t = localtime (&_t); - return t->tm_sec; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Date::operator== (const Date& rhs) const -{ - return rhs._t == _t; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Date::operator!= (const Date& rhs) const -{ - return rhs._t != _t; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Date::operator< (const Date& rhs) const -{ - return _t < rhs._t; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Date::operator> (const Date& rhs) const -{ - return _t > rhs._t; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Date::operator<= (const Date& rhs) const -{ - return _t <= rhs._t; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Date::operator>= (const Date& rhs) const -{ - return _t >= rhs._t; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Date::sameHour (const Date& rhs) const -{ - if (this->year () == rhs.year () && - this->month () == rhs.month () && - this->day () == rhs.day () && - this->hour () == rhs.hour ()) - return true; - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Date::sameDay (const Date& rhs) const -{ - if (this->year () == rhs.year () && - this->month () == rhs.month () && - this->day () == rhs.day ()) - return true; - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Date::sameWeek (const Date& rhs) const -{ - if (this->year () == rhs.year () && - this->week () == rhs.week ()) - return true; - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Date::sameMonth (const Date& rhs) const -{ - if (this->year () == rhs.year () && - this->month () == rhs.month ()) - return true; - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Date::sameYear (const Date& rhs) const -{ - if (this->year () == rhs.year ()) - return true; - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -Date Date::operator- (const int delta) -{ - return Date (_t - delta); -} - -//////////////////////////////////////////////////////////////////////////////// -Date Date::operator+ (const int delta) -{ - return Date (_t + delta); -} - -//////////////////////////////////////////////////////////////////////////////// -Date& Date::operator+= (const int delta) -{ - _t += (time_t) delta; - return *this; -} - -//////////////////////////////////////////////////////////////////////////////// -Date& Date::operator-= (const int delta) -{ - _t -= (time_t) delta; - return *this; -} - -//////////////////////////////////////////////////////////////////////////////// -time_t Date::operator- (const Date& rhs) -{ - return _t - rhs._t; -} - -//////////////////////////////////////////////////////////////////////////////// -// Prefix decrement by one day. -void Date::operator-- () -{ - Date yesterday = startOfDay () - 1; - yesterday = Date (yesterday.month (), - yesterday.day (), - yesterday.year (), - hour (), - minute (), - second ()); - _t = yesterday._t; -} - -//////////////////////////////////////////////////////////////////////////////// -// Postfix decrement by one day. -void Date::operator-- (int) -{ - Date yesterday = startOfDay () - 1; - yesterday = Date (yesterday.month (), - yesterday.day (), - yesterday.year (), - hour (), - minute (), - second ()); - _t = yesterday._t; -} - -//////////////////////////////////////////////////////////////////////////////// -// Prefix increment by one day. -void Date::operator++ () -{ - Date tomorrow = (startOfDay () + 90001).startOfDay (); - tomorrow = Date (tomorrow.month (), - tomorrow.day (), - tomorrow.year (), - hour (), - minute (), - second ()); - _t = tomorrow._t; -} - -//////////////////////////////////////////////////////////////////////////////// -// Postfix increment by one day. -void Date::operator++ (int) -{ - Date tomorrow = (startOfDay () + 90001).startOfDay (); - tomorrow = Date (tomorrow.month (), - tomorrow.day (), - tomorrow.year (), - hour (), - minute (), - second ()); - _t = tomorrow._t; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Date::isEpoch (const std::string& input) -{ - if (Lexer::isAllDigits (input) && - input.length () <= 10 ) - { - _t = (time_t) atoi (input.c_str ()); - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/Date.h task-2.5.0+dfsg/src/Date.h --- task-2.4.4+dfsg/src/Date.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/Date.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,129 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// 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 -// -//////////////////////////////////////////////////////////////////////////////// - -#ifndef INCLUDED_DATE -#define INCLUDED_DATE - -#include -#include -#include - -class Date; - -class Date -{ -public: - Date (); - Date (time_t); - Date (const int, const int, const int); - Date (const int, const int, const int, const int, const int, const int); - Date (const std::string&, - const std::string& format = "m/d/Y", - const bool iso = true, - const bool epoch = true); - Date (const std::string&, - std::string::size_type&, - const std::string& format = "m/d/Y", - const bool iso = true, - const bool epoch = true); - Date (const Date&); - virtual ~Date (); - - void toEpoch (time_t&); - time_t toEpoch (); - std::string toEpochString (); - std::string toISO (); - double toJulian (); - void toMDY (int&, int&, int&); - const std::string toString (const std::string& format = "m/d/Y") const; - - Date startOfDay () const; - Date startOfWeek () const; - Date startOfMonth () const; - Date startOfYear () const; - - static bool valid (const std::string&, const std::string& format = "m/d/Y"); - static bool valid (const int, const int, const int, const int, const int, const int); - static bool valid (const int, const int, const int); - static bool valid (const int, const int); - - static time_t easter (int year); - static bool leapYear (int); - static int daysInMonth (int, int); - static int daysInYear (int); - static std::string monthName (int); - static void dayName (int, std::string&); - static std::string dayName (int); - static int weekOfYear (const std::string&); - static int dayOfWeek (const std::string&); - static int monthOfYear (const std::string&); - static int length (const std::string&); - - int month () const; - int week () const; - int day () const; - int year () const; - int weekOfYear (int) const; - int dayOfWeek () const; - int dayOfYear () const; - int hour () const; - int minute () const; - int second () const; - - bool operator== (const Date&) const; - bool operator!= (const Date&) const; - bool operator< (const Date&) const; - bool operator> (const Date&) const; - bool operator<= (const Date&) const; - bool operator>= (const Date&) const; - bool sameHour (const Date&) const; - bool sameDay (const Date&) const; - bool sameWeek (const Date&) const; - bool sameMonth (const Date&) const; - bool sameYear (const Date&) const; - - Date operator+ (const int); - Date operator- (const int); - Date& operator+= (const int); - Date& operator-= (const int); - - time_t operator- (const Date&); - - void operator-- (); // Prefix - void operator-- (int); // Postfix - void operator++ (); // Prefix - void operator++ (int); // Postfix - -private: - bool isEpoch (const std::string&); - -protected: - time_t _t; -}; - -#endif - -//////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/Dates.cpp task-2.5.0+dfsg/src/Dates.cpp --- task-2.4.4+dfsg/src/Dates.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/Dates.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -25,25 +25,27 @@ //////////////////////////////////////////////////////////////////////////////// #include +#include #include #include #include #include -#include +#include #include +#include #include //////////////////////////////////////////////////////////////////////////////// static bool isMonth (const std::string& name, int& i) { - i = Date::monthOfYear (name) - 1; + i = ISO8601d::monthOfYear (name) - 1; return i != -2 ? true : false; } //////////////////////////////////////////////////////////////////////////////// static bool isDay (const std::string& name, int& i) { - i = Date::dayOfWeek (name); + i = ISO8601d::dayOfWeek (name); return i != -1 ? true : false; } @@ -101,32 +103,33 @@ } //////////////////////////////////////////////////////////////////////////////// -// -// -// - Nth -// - socy, eocy -// - socq, eocq -// socm, eocm -// som, eom -// soq, eoq -// soy, eoy -// socw, eocw -// sow, eow -// soww, eoww -// sod, eod -// yesterday -// today -// now -// tomorrow -// later = midnight, Jan 18th, 2038. -// someday = midnight, Jan 18th, 2038. -// - easter -// - eastermonday -// - ascension -// - pentecost -// - goodfriday -// - midsommar = midnight, 1st Saturday after 20th June -// - midsommarafton = midnight, 1st Friday after 19th June +// Note how these are all single words: +// +// +// Nth +// socy, eocy +// socq, eocq +// socm, eocm +// som, eom +// soq, eoq +// soy, eoy +// socw, eocw +// sow, eow +// soww, eoww +// sod, eod +// yesterday +// today +// now +// tomorrow +// later = midnight, Jan 18th, 2038. +// someday = midnight, Jan 18th, 2038. +// easter +// eastermonday +// ascension +// pentecost +// goodfriday +// midsommar = midnight, 1st Saturday after 20th June +// midsommarafton = midnight, 1st Friday after 19th June // bool namedDates (const std::string& name, Variant& value) { @@ -134,20 +137,24 @@ struct tm* t = localtime (&now); int i; + int minimum = CLI2::minimumMatchLength; + if (minimum == 0) + minimum = 3; + // Dynamics. - if (name == "now") + if (closeEnough ("now", name, minimum)) { value = Variant (now, Variant::type_date); } - else if (name == "today") + else if (closeEnough ("today", name, minimum)) { t->tm_hour = t->tm_min = t->tm_sec = 0; t->tm_isdst = -1; value = Variant (mktime (t), Variant::type_date); } - else if (name == "sod") + else if (closeEnough ("sod", name, minimum)) { t->tm_mday++; t->tm_hour = t->tm_min = t->tm_sec = 0; @@ -155,7 +162,7 @@ value = Variant (mktime (t), Variant::type_date); } - else if (name == "eod") + else if (closeEnough ("eod", name, minimum)) { t->tm_mday++; t->tm_hour = t->tm_min = 0; @@ -164,7 +171,7 @@ value = Variant (mktime (t), Variant::type_date); } - else if (name == "tomorrow") + else if (closeEnough ("tomorrow", name, minimum)) { t->tm_mday++; t->tm_hour = t->tm_min = t->tm_sec = 0; @@ -172,7 +179,7 @@ value = Variant (mktime (t), Variant::type_date); } - else if (name == "yesterday") + else if (closeEnough ("yesterday", name, minimum)) { t->tm_hour = t->tm_min = t->tm_sec = 0; t->tm_isdst = -1; @@ -203,7 +210,8 @@ value = Variant (mktime (t), Variant::type_date); } - else if (name == "later" || name == "someday") + else if (closeEnough ("later", name, minimum) || + closeEnough ("someday", name, std::max (minimum, 4))) { t->tm_hour = t->tm_min = t->tm_sec = 0; t->tm_year = 138; @@ -213,7 +221,7 @@ value = Variant (mktime (t), Variant::type_date); } - else if (name == "eoy") + else if (closeEnough ("eoy", name, minimum)) { t->tm_hour = t->tm_min = 0; t->tm_sec = -1; @@ -224,7 +232,7 @@ value = Variant (mktime (t), Variant::type_date); } - else if (name == "soy") + else if (closeEnough ("soy", name, minimum)) { t->tm_hour = t->tm_min = t->tm_sec = 0; t->tm_mon = 0; @@ -234,7 +242,7 @@ value = Variant (mktime (t), Variant::type_date); } - else if (name == "eoq") + else if (closeEnough ("eoq", name, minimum)) { t->tm_hour = t->tm_min = 0; t->tm_sec = -1; @@ -250,7 +258,7 @@ value = Variant (mktime (t), Variant::type_date); } - else if (name == "soq") + else if (closeEnough ("soq", name, minimum)) { t->tm_hour = t->tm_min = t->tm_sec = 0; t->tm_mon += 3 - (t->tm_mon % 3); @@ -265,7 +273,7 @@ value = Variant (mktime (t), Variant::type_date); } - else if (name == "socm") + else if (closeEnough ("socm", name, minimum)) { t->tm_hour = t->tm_min = t->tm_sec = 0; t->tm_mday = 1; @@ -273,7 +281,7 @@ value = Variant (mktime (t), Variant::type_date); } - else if (name == "som") + else if (closeEnough ("som", name, minimum)) { t->tm_hour = t->tm_min = t->tm_sec = 0; @@ -289,17 +297,18 @@ value = Variant (mktime (t), Variant::type_date); } - else if (name == "eom" || name == "eocm") + else if (closeEnough ("eom", name, minimum) || + closeEnough ("eocm", name, minimum)) { t->tm_hour = 24; t->tm_min = 0; t->tm_sec = -1; - t->tm_mday = Date::daysInMonth (t->tm_mon + 1, t->tm_year + 1900); + t->tm_mday = ISO8601d::daysInMonth (t->tm_mon + 1, t->tm_year + 1900); t->tm_isdst = -1; value = Variant (mktime (t), Variant::type_date); } - else if (name == "socw") + else if (closeEnough ("socw", name, minimum)) { t->tm_hour = t->tm_min = t->tm_sec = 0; int extra = t->tm_wday * 86400; @@ -307,7 +316,8 @@ value = Variant (mktime (t) - extra, Variant::type_date); } - else if (name == "eow" || name == "eocw") + else if (closeEnough ("eow", name, minimum) || + closeEnough ("eocw", name, minimum)) { t->tm_hour = t->tm_min = 0; t->tm_sec = -1; @@ -316,7 +326,7 @@ value = Variant (mktime (t) + extra, Variant::type_date); } - else if (name == "sow") + else if (closeEnough ("sow", name, minimum)) { t->tm_hour = t->tm_min = t->tm_sec = 0; int extra = (7 - t->tm_wday) * 86400; @@ -324,18 +334,16 @@ value = Variant (mktime (t) + extra, Variant::type_date); } - else if (name == "soww") + else if (closeEnough ("soww", name, minimum)) { t->tm_hour = t->tm_min = t->tm_sec = 0; - int extra = (t->tm_wday - 1) * 86400; - if (extra > 0) - extra += 7 * 86400; - + int days = (8 - t->tm_wday) % 7; + int extra = days * 86400; t->tm_isdst = -1; - value = Variant (mktime (t) - extra, Variant::type_date); + value = Variant (mktime (t) + extra, Variant::type_date); } - else if (name == "eoww") + else if (closeEnough ("eoww", name, minimum)) { t->tm_hour = 24; t->tm_min = 0; @@ -407,7 +415,7 @@ // If it is this month. if (d < number && - number <= Date::daysInMonth (m, y)) + number <= ISO8601d::daysInMonth (m, y)) { t->tm_hour = t->tm_min = t->tm_sec = 0; t->tm_mon = m - 1; @@ -439,11 +447,11 @@ throw std::string (STRING_DATES_MONTH_31); } - else if (name == "easter" || - name == "eastermonday" || - name == "ascension" || - name == "pentecost" || - name == "goodfriday") + else if (closeEnough ("easter", name, minimum) || + closeEnough ("eastermonday", name, minimum) || + closeEnough ("ascension", name, minimum) || + closeEnough ("pentecost", name, minimum) || + closeEnough ("goodfriday", name, minimum)) { Variant valueNow = Variant (mktime (t), Variant::type_date); easter (t); @@ -457,15 +465,20 @@ easter (t); } - if (name == "goodfriday") t->tm_mday -= 2; - else if (name == "eastermonday") t->tm_mday += 1; - else if (name == "ascension") t->tm_mday += 39; - else if (name == "pentecost") t->tm_mday += 49; + if (closeEnough ("goodfriday", name, minimum)) t->tm_mday -= 2; + + // DO NOT REMOVE THIS USELESS-LOOKING LINE. + // It is here to capture an exact match for 'easter', to prevent 'easter' + // being a partial match for 'eastermonday'. + else if (closeEnough ("easter", name, minimum)) ; + else if (closeEnough ("eastermonday", name, minimum)) t->tm_mday += 1; + else if (closeEnough ("ascension", name, minimum)) t->tm_mday += 39; + else if (closeEnough ("pentecost", name, minimum)) t->tm_mday += 49; value = Variant (mktime (t), Variant::type_date); } - else if (name == "midsommar") + else if (closeEnough ("midsommar", name, minimum)) { Variant valueNow = Variant (mktime (t), Variant::type_date); midsommar (t); @@ -482,7 +495,7 @@ value = Variant (mktime (t), Variant::type_date); } - else if (name == "midsommarafton") + else if (closeEnough ("midsommarafton", name, minimum)) { Variant valueNow = Variant (mktime (t), Variant::type_date); midsommarafton (t); diff -Nru task-2.4.4+dfsg/src/dependency.cpp task-2.5.0+dfsg/src/dependency.cpp --- task-2.4.4+dfsg/src/dependency.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/dependency.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -42,14 +42,13 @@ { std::string uuid = task.get ("uuid"); - const std::vector & all = context.tdb2.pending.get_tasks (); - std::vector ::const_iterator it; - for (it = all.begin (); it != all.end (); ++it) - if ((it->getStatus () == Task::pending || - it->getStatus () == Task::waiting) && - it->has ("depends") && - it->get ("depends").find (uuid) != std::string::npos) - blocked.push_back (*it); + auto all = context.tdb2.pending.get_tasks (); + for (auto& it : all) + if ((it.getStatus () == Task::pending || + it.getStatus () == Task::waiting) && + it.has ("depends") && + it.get ("depends").find (uuid) != std::string::npos) + blocked.push_back (it); } //////////////////////////////////////////////////////////////////////////////// @@ -57,30 +56,25 @@ { std::string depends = task.get ("depends"); if (depends != "") - { - const std::vector & all = context.tdb2.pending.get_tasks (); - std::vector ::const_iterator it; - for (it = all.begin (); it != all.end (); ++it) - if ((it->getStatus () == Task::pending || - it->getStatus () == Task::waiting) && - depends.find (it->get ("uuid")) != std::string::npos) - blocking.push_back (*it); - } + for (auto& it : context.tdb2.pending.get_tasks ()) + if ((it.getStatus () == Task::pending || + it.getStatus () == Task::waiting) && + depends.find (it.get ("uuid")) != std::string::npos) + blocking.push_back (it); } //////////////////////////////////////////////////////////////////////////////// // Returns true if the supplied task adds a cycle to the dependency chain. bool dependencyIsCircular (const Task& task) { - std::stack s; - std::vector deps_current; - std::string task_uuid = task.get ("uuid"); + std::stack s; s.push (task); - while (!s.empty ()) + while (! s.empty ()) { Task& current = s.top (); + std::vector deps_current; current.getDependencies (deps_current); // This is a basic depth first search that always terminates given the @@ -90,16 +84,18 @@ // function, this is a reasonable assumption. for (unsigned int i = 0; i < deps_current.size (); i++) { - context.tdb2.get (deps_current[i], current); - - if (task_uuid == current.get ("uuid")) + if (context.tdb2.get (deps_current[i], current)) + { + if (task_uuid == current.get ("uuid")) { // Cycle found, initial task reached for the second time! return true; } - s.push (current); + s.push (current); + } } + s.pop (); } @@ -152,9 +148,8 @@ std::cout << format (STRING_DEPEND_BLOCKED, task.id) << "\n"; - std::vector ::iterator b; - for (b = blocking.begin (); b != blocking.end (); ++b) - std::cout << " " << b->id << " " << b->get ("description") << "\n"; + for (auto& b : blocking) + std::cout << " " << b.id << " " << b.get ("description") << "\n"; } // If there are both blocking and blocked tasks, the chain is broken. @@ -165,9 +160,8 @@ std::cout << STRING_DEPEND_BLOCKING << "\n"; - std::vector ::iterator b; - for (b = blocked.begin (); b != blocked.end (); ++b) - std::cout << " " << b->id << " " << b->get ("description") << "\n"; + for (auto& b : blocked) + std::cout << " " << b.id << " " << b.get ("description") << "\n"; } if (!context.config.getBoolean ("dependency.confirmation") || @@ -175,22 +169,20 @@ { // Repair the chain - everything in blocked should now depend on // everything in blocking, instead of task.id. - std::vector ::iterator left; - std::vector ::iterator right; - for (left = blocked.begin (); left != blocked.end (); ++left) + for (auto& left : blocked) { - left->removeDependency (task.id); + left.removeDependency (task.id); - for (right = blocking.begin (); right != blocking.end (); ++right) - left->addDependency (right->id); + for (auto& right : blocking) + left.addDependency (right.id); } // Now update TDB2, now that the updates have all occurred. - for (left = blocked.begin (); left != blocked.end (); ++left) - context.tdb2.modify (*left); + for (auto& left : blocked) + context.tdb2.modify (left); - for (right = blocking.begin (); right != blocking.end (); ++right) - context.tdb2.modify (*right); + for (auto& right : blocking) + context.tdb2.modify (right); } } } @@ -211,56 +203,10 @@ std::cout << format (STRING_DEPEND_BLOCKED, task.id) << "\n"; - std::vector ::iterator b; - for (b = blocking.begin (); b != blocking.end (); ++b) - std::cout << " " << b->id << " " << b->get ("description") << "\n"; - } - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Iff a dependency is being removed, is there something to do. -void dependencyChainOnModify (Task& before, Task& after) -{ - // TODO It is not clear that this should even happen. TBD. -/* - // Get the dependencies from before. - std::string depends = before.get ("depends"); - std::vector before_depends; - split (before_depends, depends, ','); - std::cout << "# dependencyChainOnModify before has " << before_depends.size () << "\n"; - - // Get the dependencies from after. - depends = after.get ("depends"); - std::vector after_depends; - split (after_depends, depends, ','); - std::cout << "# dependencyChainOnModify after has " << after_depends.size () << "\n"; - - // listDiff - std::vector before_only; - std::vector after_only; - listDiff (before_depends, after_depends, before_only, after_only); - - // Any dependencies in before_only indicates that a dependency was removed. - if (before_only.size ()) - { - std::cout << "# dependencyChainOnModify detected a dependency removal\n"; - - // before dep:2,3 - // after dep:2 - // - // any tasks blocked by after might should be repaired to depend on 3. - - std::vector blocked; - dependencyGetBlocked (after, blocked); - - std::vector ::iterator b; - for (b = blocked.begin (); b != blocked.end (); ++b) - { - std::cout << "# dependencyChainOnModify\n"; + for (auto& b : blocking) + std::cout << " " << b.id << " " << b.get ("description") << "\n"; } } -*/ } //////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/Directory.cpp task-2.5.0+dfsg/src/Directory.cpp --- task-2.4.4+dfsg/src/Directory.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/Directory.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,241 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// 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 -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined SOLARIS || defined NETBSD || defined FREEBSD -#include -#endif - -//////////////////////////////////////////////////////////////////////////////// -Directory::Directory () -{ -} - -//////////////////////////////////////////////////////////////////////////////// -Directory::Directory (const Directory& other) -: File::File (other) -{ -} - -//////////////////////////////////////////////////////////////////////////////// -Directory::Directory (const File& other) -: File::File (other) -{ -} - -//////////////////////////////////////////////////////////////////////////////// -Directory::Directory (const Path& other) -: File::File (other) -{ -} - -//////////////////////////////////////////////////////////////////////////////// -Directory::Directory (const std::string& in) -: File::File (in) -{ -} - -//////////////////////////////////////////////////////////////////////////////// -Directory::~Directory () -{ -} - -//////////////////////////////////////////////////////////////////////////////// -Directory& Directory::operator= (const Directory& other) -{ - if (this != &other) - { - File::operator= (other); - } - - return *this; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Directory::create (int mode /* = 0755 */) -{ - return mkdir (_data.c_str (), mode) == 0 ? true : false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Directory::remove () const -{ - return remove_directory (_data); -} - -//////////////////////////////////////////////////////////////////////////////// -bool Directory::remove_directory (const std::string& dir) const -{ - DIR* dp = opendir (dir.c_str ()); - if (dp != NULL) - { - struct dirent* de; - while ((de = readdir (dp)) != NULL) - { - if (!strcmp (de->d_name, ".") || - !strcmp (de->d_name, "..")) - continue; - -#if defined (SOLARIS) || defined (HAIKU) - struct stat s; - lstat ((dir + "/" + de->d_name).c_str (), &s); - if (S_ISDIR (s.st_mode)) - remove_directory (dir + "/" + de->d_name); - else - unlink ((dir + "/" + de->d_name).c_str ()); -#else - if (de->d_type == DT_UNKNOWN) - { - struct stat s; - lstat ((dir + "/" + de->d_name).c_str (), &s); - if (S_ISDIR (s.st_mode)) - de->d_type = DT_DIR; - } - if (de->d_type == DT_DIR) - remove_directory (dir + "/" + de->d_name); - else - unlink ((dir + "/" + de->d_name).c_str ()); -#endif - } - - closedir (dp); - } - - return rmdir (dir.c_str ()) ? false : true; -} - -//////////////////////////////////////////////////////////////////////////////// -std::vector Directory::list () -{ - std::vector files; - list (_data, files, false); - return files; -} - -//////////////////////////////////////////////////////////////////////////////// -std::vector Directory::listRecursive () -{ - std::vector files; - list (_data, files, true); - return files; -} - -//////////////////////////////////////////////////////////////////////////////// -std::string Directory::cwd () -{ -#ifdef HAVE_GET_CURRENT_DIR_NAME - char *buf = get_current_dir_name (); - if (buf == NULL) - throw std::bad_alloc (); - std::string result (buf); - free (buf); - return result; -#else - char buf[PATH_MAX]; - getcwd (buf, PATH_MAX - 1); - return std::string (buf); -#endif -} - -//////////////////////////////////////////////////////////////////////////////// -bool Directory::up () -{ - if (_data == "/") - return false; - - std::string::size_type slash = _data.rfind ('/'); - if (slash == 0) - { - _data = "/"; // Root dir should retain the slash. - return true; - } - else if (slash != std::string::npos) - { - _data = _data.substr (0, slash); - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Directory::cd () const -{ - return chdir (_data.c_str ()) == 0 ? true : false; -} - -//////////////////////////////////////////////////////////////////////////////// -void Directory::list ( - const std::string& base, - std::vector & results, - bool recursive) -{ - DIR* dp = opendir (base.c_str ()); - if (dp != NULL) - { - struct dirent* de; - while ((de = readdir (dp)) != NULL) - { - if (!strcmp (de->d_name, ".") || - !strcmp (de->d_name, "..")) - continue; - -#if defined (SOLARIS) || defined (HAIKU) - struct stat s; - stat ((base + "/" + de->d_name).c_str (), &s); - if (recursive && S_ISDIR (s.st_mode)) - list (base + "/" + de->d_name, results, recursive); - else - results.push_back (base + "/" + de->d_name); -#else - if (recursive && de->d_type == DT_UNKNOWN) - { - struct stat s; - lstat ((base + "/" + de->d_name).c_str (), &s); - if (S_ISDIR (s.st_mode)) - de->d_type = DT_DIR; - } - if (recursive && de->d_type == DT_DIR) - list (base + "/" + de->d_name, results, recursive); - else - results.push_back (base + "/" + de->d_name); -#endif - } - - closedir (dp); - } -} - -//////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/Directory.h task-2.5.0+dfsg/src/Directory.h --- task-2.4.4+dfsg/src/Directory.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/Directory.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// 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 -// -//////////////////////////////////////////////////////////////////////////////// - -#ifndef INCLUDED_DIRECTORY -#define INCLUDED_DIRECTORY - -#include - -class Directory : public File -{ -public: - Directory (); - Directory (const Directory&); - Directory (const File&); - Directory (const Path&); - Directory (const std::string&); - virtual ~Directory (); - - Directory& operator= (const Directory&); - - virtual bool create (int mode = 0755); - virtual bool remove () const; - - std::vector list (); - std::vector listRecursive (); - - static std::string cwd (); - bool up (); - bool cd () const; - -private: - void list (const std::string&, std::vector &, bool); - bool remove_directory (const std::string&) const; -}; - -#endif -//////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/DOM.cpp task-2.5.0+dfsg/src/DOM.cpp --- task-2.4.4+dfsg/src/DOM.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/DOM.cpp 2015-10-21 21:18:14.000000000 +0000 @@ -29,10 +29,9 @@ #include #include #include -#include #include #include -#include +#include #include #include #include @@ -50,36 +49,25 @@ } //////////////////////////////////////////////////////////////////////////////// -const std::vector DOM::get_references () const -{ - std::vector refs; - - refs.push_back ("context.program"); - refs.push_back ("context.args"); - refs.push_back ("context.width"); - refs.push_back ("context.height"); - refs.push_back ("system.version"); - refs.push_back ("system.os"); - - return refs; -} - -//////////////////////////////////////////////////////////////////////////////// // DOM Supported References: +// +// Configuration: // rc. // +// System: // context.program // context.args // context.width // context.height -// -// TODO stats. <-- context.stats -// // system.version // system.os // bool DOM::get (const std::string& name, Variant& value) { + // Special case, blank refs cause problems. + if (name == "") + return false; + int len = name.length (); Nibbler n (name); @@ -88,7 +76,7 @@ name.substr (0, 3) == "rc.") { std::string key = name.substr (3); - std::map ::iterator c = context.config.find (key); + auto c = context.config.find (key); if (c != context.config.end ()) { value = Variant (c->second); @@ -104,13 +92,20 @@ { if (name == "context.program") { - value = Variant (context.cli.getBinary ()); + value = Variant (context.cli2.getBinary ()); return true; } else if (name == "context.args") { std::string commandLine; - join (commandLine, " ", context.cli._original_args); + for (auto& arg : context.cli2._original_args) + { + if (commandLine != "") + commandLine += " "; + + commandLine += arg.attribute("raw"); + } + value = Variant (commandLine); return true; } @@ -184,11 +179,15 @@ //////////////////////////////////////////////////////////////////////////////// // DOM Supported References: // +// Relative or absolute attribute: // // . // . // -// For certain attributes: +// Single tag: +// tags. +// +// Date type: // .year // .month // .day @@ -199,23 +198,19 @@ // .minute // .second // -// tags. Includes virtual tags -// +// Annotations (entry is a date): // annotations..entry -// annotations..entry.year -// annotations..entry.month -// annotations..entry.day -// annotations..entry.week -// annotations..entry.weekday -// annotations..entry.julian -// annotations..entry.hour -// annotations..entry.minute -// annotations..entry.second // annotations..description // +// This code emphasizes speed, hence 'id' and 'urgecny' being evaluated first +// as special cases. bool DOM::get (const std::string& name, const Task& task, Variant& value) { - // + // Special case, blank refs cause problems. + if (name == "") + return false; + + // Quickly deal with the most common cases. if (task.size () && name == "id") { value = Variant (static_cast (task.id)); @@ -232,229 +227,178 @@ std::vector elements; split (elements, name, '.'); - if (elements.size () == 1) - { - std::string canonical; - if (task.size () && context.cli.canonicalize (canonical, "attribute", name)) - { - Column* column = context.columns[canonical]; - if (column) - { - if (column->is_uda () && ! task.has (canonical)) - { - value = Variant ("''"); - return true; - } + Task ref (task); + Nibbler n (elements[0]); + n.save (); + int id; + std::string uuid; - if (column->type () == "date") - value = Variant (task.get_date (canonical), Variant::type_date); - else if (column->type () == "duration" || canonical == "recur") - value = Variant ((time_t) Duration (task.get (canonical)), Variant::type_duration); - else if (column->type () == "numeric") - value = Variant (task.get_float (canonical)); - else // string - value = Variant (task.get (canonical)); + // If elements[0] is a UUID, load that task (if necessary), and clobber ref. + if (n.getPartialUUID (uuid) && n.depleted ()) + { + if (uuid != ref.get ("uuid")) + context.tdb2.get (uuid, ref); - return true; - } - } + // Eat elements[0]/UUID. + elements.erase (elements.begin ()); } - else if (elements.size () > 1) + else { - Task ref; - - Nibbler n (elements[0]); - n.save (); - int id; - std::string uuid; - bool proceed = false; - + // If elements[0] is a ID, load that task (if necessary), and clobber ref. if (n.getInt (id) && n.depleted ()) { - if (id == task.id) - ref = task; - else + if (id != ref.id) context.tdb2.get (id, ref); - proceed = true; + // Eat elements[0]/ID. + elements.erase (elements.begin ()); } - else + } + + auto size = elements.size (); + + std::string canonical; + if ((size == 1 || size == 2) && context.cli2.canonicalize (canonical, "attribute", elements[0])) + { + // Now that 'ref' is the contextual task, and any ID/UUID is chopped off the + // elements vector, DOM resolution is now simple. + if (ref.size () && size == 1 && canonical == "id") { - n.restore (); - if (n.getUUID (uuid) && n.depleted ()) - { - if (uuid == task.get ("uuid")) - ref = task; - else - context.tdb2.get (uuid, ref); + value = Variant (static_cast (ref.id)); + return true; + } - proceed = true; - } + if (ref.size () && size == 1 && canonical == "urgency") + { + value = Variant (ref.urgency_c ()); + return true; } - if (proceed) + Column* column = context.columns[canonical]; + + if (ref.size () && size == 1 && column) { - if (elements[1] == "id") + if (column->is_uda () && ! ref.has (canonical)) { - value = Variant (static_cast (ref.id)); + value = Variant (""); return true; } - else if (elements[1] == "urgency") + + if (column->type () == "date") { - value = Variant (ref.urgency_c ()); - return true; + auto numeric = ref.get_date (canonical); + if (numeric == 0) + value = Variant (""); + else + value = Variant (numeric, Variant::type_date); } - - std::string canonical; - if (context.cli.canonicalize (canonical, "attribute", elements[1])) + else if (column->type () == "duration" || canonical == "recur") { - if (elements.size () == 2) - { - Column* column = context.columns[canonical]; - if (column) - { - if (column->is_uda () && ! ref.has (canonical)) - { - value = Variant ("''"); - return true; - } - - if (column->type () == "date") - value = Variant (ref.get_date (canonical), Variant::type_date); - else if (column->type () == "duration") - value = Variant ((time_t) Duration (ref.get (canonical)), Variant::type_duration); - else if (column->type () == "numeric") - value = Variant (ref.get_float (canonical)); - else - value = Variant (ref.get (canonical)); + auto period = ref.get (canonical); - return true; - } - } - else if (elements.size () == 3) - { - // tags. - if (canonical == "tags") - { - value = Variant (ref.hasTag (elements[2]) ? elements[2] : ""); - return true; - } - - Column* column = context.columns[canonical]; - if (column && column->type () == "date") - { - // .year - // .month - // .day - // .week - // .weekday - // .julian - // .hour - // .minute - // .second - Date date (ref.get_date (canonical)); - if (elements[2] == "year") { value = Variant (static_cast (date.year ())); return true; } - else if (elements[2] == "month") { value = Variant (static_cast (date.month ())); return true; } - else if (elements[2] == "day") { value = Variant (static_cast (date.day ())); return true; } - else if (elements[2] == "week") { value = Variant (static_cast (date.week ())); return true; } - else if (elements[2] == "weekday") { value = Variant (static_cast (date.dayOfWeek ())); return true; } - else if (elements[2] == "julian") { value = Variant (static_cast (date.dayOfYear ())); return true; } - else if (elements[2] == "hour") { value = Variant (static_cast (date.hour ())); return true; } - else if (elements[2] == "minute") { value = Variant (static_cast (date.minute ())); return true; } - else if (elements[2] == "second") { value = Variant (static_cast (date.second ())); return true; } - } - } + ISO8601p iso; + std::string::size_type cursor = 0; + if (iso.parse (period, cursor)) + value = Variant ((time_t) iso, Variant::type_duration); + else + value = Variant ((time_t) ISO8601p (ref.get (canonical)), Variant::type_duration); } - else if (elements[1] == "annotations") - { - if (elements.size () == 4) - { - std::map annos; - ref.getAnnotations (annos); + else if (column->type () == "numeric") + value = Variant (ref.get_float (canonical)); + else + value = Variant (ref.get (canonical)); + + return true; + } - int a = strtol (elements[2].c_str (), NULL, 10); - int count = 0; + if (ref.size () && size == 2 && canonical == "tags") + { + value = Variant (ref.hasTag (elements[1]) ? elements[1] : ""); + return true; + } - // Count off the 'a'th annotation. - std::map ::iterator i; - for (i = annos.begin (); i != annos.end (); ++i) - { - if (++count == a) - { - if (elements[3] == "entry") - { - // annotation_1234567890 - // 0 ^11 - value = Variant ((time_t) strtol (i->first.substr (11).c_str (), NULL, 10), Variant::type_date); - return true; - } - else if (elements[3] == "description") - { - value = Variant (i->second); - return true; - } - } - } - } - else if (elements.size () == 5) - { - std::map annos; - ref.getAnnotations (annos); + if (ref.size () && size == 2 && column && column->type () == "date") + { + ISO8601d date (ref.get_date (canonical)); + if (elements[1] == "year") { value = Variant (static_cast (date.year ())); return true; } + else if (elements[1] == "month") { value = Variant (static_cast (date.month ())); return true; } + else if (elements[1] == "day") { value = Variant (static_cast (date.day ())); return true; } + else if (elements[1] == "week") { value = Variant (static_cast (date.week ())); return true; } + else if (elements[1] == "weekday") { value = Variant (static_cast (date.dayOfWeek ())); return true; } + else if (elements[1] == "julian") { value = Variant (static_cast (date.dayOfYear ())); return true; } + else if (elements[1] == "hour") { value = Variant (static_cast (date.hour ())); return true; } + else if (elements[1] == "minute") { value = Variant (static_cast (date.minute ())); return true; } + else if (elements[1] == "second") { value = Variant (static_cast (date.second ())); return true; } + } + } - int a = strtol (elements[2].c_str (), NULL, 10); - int count = 0; + if (ref.size () && size == 3 && elements[0] == "annotations") + { + std::map annos; + ref.getAnnotations (annos); + + int a = strtol (elements[1].c_str (), NULL, 10); + int count = 0; - // Count off the 'a'th annotation. - std::map ::iterator i; - for (i = annos.begin (); i != annos.end (); ++i) - { - if (++count == a) - { - // ..entry.year - // ..entry.month - // ..entry.day - // ..entry.week - // ..entry.weekday - // ..entry.julian - // ..entry.hour - // ..entry.minute - // ..entry.second - Date date (i->first.substr (11)); - if (elements[4] == "year") { value = Variant (static_cast (date.year ())); return true; } - else if (elements[4] == "month") { value = Variant (static_cast (date.month ())); return true; } - else if (elements[4] == "day") { value = Variant (static_cast (date.day ())); return true; } - else if (elements[4] == "week") { value = Variant (static_cast (date.week ())); return true; } - else if (elements[4] == "weekday") { value = Variant (static_cast (date.dayOfWeek ())); return true; } - else if (elements[4] == "julian") { value = Variant (static_cast (date.dayOfYear ())); return true; } - else if (elements[4] == "hour") { value = Variant (static_cast (date.hour ())); return true; } - else if (elements[4] == "minute") { value = Variant (static_cast (date.minute ())); return true; } - else if (elements[4] == "second") { value = Variant (static_cast (date.second ())); return true; } - } - } + // Count off the 'a'th annotation. + for (auto& i : annos) + { + if (++count == a) + { + if (elements[2] == "entry") + { + // annotation_1234567890 + // 0 ^11 + value = Variant ((time_t) strtol (i.first.substr (11).c_str (), NULL, 10), Variant::type_date); + return true; + } + else if (elements[2] == "description") + { + value = Variant (i.second); + return true; } } } } - // Delegate to the context-free version of DOM::get. - return this->get (name, value); -} + if (ref.size () && size == 4 && elements[0] == "annotations" && elements[2] == "entry") + { + std::map annos; + ref.getAnnotations (annos); -//////////////////////////////////////////////////////////////////////////////// -void DOM::set (const std::string& name, const Variant& value) -{ - int len = name.length (); + int a = strtol (elements[1].c_str (), NULL, 10); + int count = 0; - // rc. --> context.config - if (len > 3 && - name.substr (0, 3) == "rc.") - { - context.config.set (name.substr (3), (std::string) value); + // Count off the 'a'th annotation. + for (auto& i : annos) + { + if (++count == a) + { + // ..entry.year + // ..entry.month + // ..entry.day + // ..entry.week + // ..entry.weekday + // ..entry.julian + // ..entry.hour + // ..entry.minute + // ..entry.second + ISO8601d date (i.first.substr (11)); + if (elements[3] == "year") { value = Variant (static_cast (date.year ())); return true; } + else if (elements[3] == "month") { value = Variant (static_cast (date.month ())); return true; } + else if (elements[3] == "day") { value = Variant (static_cast (date.day ())); return true; } + else if (elements[3] == "week") { value = Variant (static_cast (date.week ())); return true; } + else if (elements[3] == "weekday") { value = Variant (static_cast (date.dayOfWeek ())); return true; } + else if (elements[3] == "julian") { value = Variant (static_cast (date.dayOfYear ())); return true; } + else if (elements[3] == "hour") { value = Variant (static_cast (date.hour ())); return true; } + else if (elements[3] == "minute") { value = Variant (static_cast (date.minute ())); return true; } + else if (elements[3] == "second") { value = Variant (static_cast (date.second ())); return true; } + } + } } - // Unrecognized --> error. - else - throw format (STRING_DOM_CANNOT_SET, name); + // Delegate to the context-free version of DOM::get. + return this->get (name, value); } //////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/DOM.h task-2.5.0+dfsg/src/DOM.h --- task-2.4.4+dfsg/src/DOM.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/DOM.h 2015-10-21 21:18:14.000000000 +0000 @@ -38,10 +38,8 @@ DOM (); ~DOM (); - const std::vector get_references () const; bool get (const std::string&, Variant&); bool get (const std::string&, const Task&, Variant&); - void set (const std::string&, const Variant&); private: }; diff -Nru task-2.4.4+dfsg/src/Duration.cpp task-2.5.0+dfsg/src/Duration.cpp --- task-2.4.4+dfsg/src/Duration.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/Duration.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,369 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DAY 86400 -#define HOUR 3600 -#define MINUTE 60 -#define SECOND 1 - -static struct -{ - std::string unit; - int seconds; - bool standalone; -} durations[] = -{ - // These are sorted by first character, then length, so that Nibbler::getOneOf - // returns a maximal match. - {"annual", 365 * DAY, true}, - {"biannual", 730 * DAY, true}, - {"bimonthly", 61 * DAY, true}, - {"biweekly", 14 * DAY, true}, - {"biyearly", 730 * DAY, true}, - {"daily", 1 * DAY, true}, - {"days", 1 * DAY, false}, - {"day", 1 * DAY, true}, - {"d", 1 * DAY, false}, - {"fortnight", 14 * DAY, true}, - {"hours", 1 * HOUR, false}, - {"hour", 1 * HOUR, true}, - {"hrs", 1 * HOUR, false}, - {"hr", 1 * HOUR, true}, - {"h", 1 * HOUR, false}, - {"minutes", 1 * MINUTE, false}, - {"minute", 1 * MINUTE, true}, - {"mins", 1 * MINUTE, false}, - {"min", 1 * MINUTE, true}, - {"monthly", 30 * DAY, true}, - {"months", 30 * DAY, false}, - {"month", 30 * DAY, true}, - {"mnths", 30 * DAY, false}, - {"mths", 30 * DAY, false}, - {"mth", 30 * DAY, true}, - {"mos", 30 * DAY, false}, - {"mo", 30 * DAY, true}, - {"m", 30 * DAY, false}, - {"quarterly", 91 * DAY, true}, - {"quarters", 91 * DAY, false}, - {"quarter", 91 * DAY, true}, - {"qrtrs", 91 * DAY, false}, - {"qrtr", 91 * DAY, true}, - {"qtrs", 91 * DAY, false}, - {"qtr", 91 * DAY, true}, - {"q", 91 * DAY, false}, - {"semiannual", 183 * DAY, true}, - {"sennight", 14 * DAY, false}, - {"seconds", 1 * SECOND, false}, - {"second", 1 * SECOND, true}, - {"secs", 1 * SECOND, false}, - {"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, false}, - {"wk", 7 * DAY, true}, - {"w", 7 * DAY, false}, - {"yearly", 365 * DAY, true}, - {"years", 365 * DAY, false}, - {"year", 365 * DAY, true}, - {"yrs", 365 * DAY, false}, - {"yr", 365 * DAY, true}, - {"y", 365 * DAY, false}, -}; - -#define NUM_DURATIONS (sizeof (durations) / sizeof (durations[0])) - -//////////////////////////////////////////////////////////////////////////////// -Duration::Duration () -: _secs (0) -{ -} - -//////////////////////////////////////////////////////////////////////////////// -Duration::Duration (time_t input) -: _secs (input) -{ -} - -//////////////////////////////////////////////////////////////////////////////// -Duration::Duration (const std::string& input) -: _secs (0) -{ - if (Lexer::isAllDigits (input)) - { - time_t value = (time_t) strtol (input.c_str (), NULL, 10); - if (value == 0 || value > 60) - { - _secs = value; - return; - } - } - - std::string::size_type idx = 0; - parse (input, idx); -} - -//////////////////////////////////////////////////////////////////////////////// -Duration::~Duration () -{ -} - -//////////////////////////////////////////////////////////////////////////////// -bool Duration::operator< (const Duration& other) -{ - return _secs < other._secs; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Duration::operator> (const Duration& other) -{ - return _secs > other._secs; -} - -//////////////////////////////////////////////////////////////////////////////// -Duration& Duration::operator= (const Duration& other) -{ - if (this != &other) - _secs = other._secs; - - return *this; -} - -//////////////////////////////////////////////////////////////////////////////// -Duration::operator time_t () const -{ - return _secs; -} - -//////////////////////////////////////////////////////////////////////////////// -Duration::operator std::string () const -{ - std::stringstream s; - s << _secs; - return s.str (); -} - -//////////////////////////////////////////////////////////////////////////////// -std::string Duration::format () const -{ - char formatted[24]; - float days = (float) _secs / 86400.0; - - if (_secs >= 86400 * 365) - sprintf (formatted, "%.1f year%s", - (days / 365), - ((int) (float) (days / 365) == 1 ? "" : "s")); - else if (_secs > 86400 * 84) - sprintf (formatted, "%1d month%s", - (int) (float) (days / 30), - ((int) (float) (days / 30) == 1 ? "" : "s")); - else if (_secs > 86400 * 13) - sprintf (formatted, "%d week%s", - (int) (float) (days / 7.0), - ((int) (float) (days / 7.0) == 1 ? "" : "s")); - else if (_secs >= 86400) - sprintf (formatted, "%d day%s", - (int) days, - ((int) days == 1 ? "" : "s")); - else if (_secs >= 3600) - sprintf (formatted, "%d hour%s", - (int) (float) (_secs / 3600), - ((int) (float) (_secs / 3600) == 1 ? "" : "s")); - else if (_secs >= 60) - sprintf (formatted, "%d minute%s", - (int) (float) (_secs / 60), - ((int) (float) (_secs / 60) == 1 ? "" : "s")); - else if (_secs >= 1) - sprintf (formatted, "%d second%s", - (int) _secs, - ((int) _secs == 1 ? "" : "s")); - else - strcpy (formatted, "-"); // no i18n - - return std::string (formatted); -} - -//////////////////////////////////////////////////////////////////////////////// -std::string Duration::formatCompact () const -{ - char formatted[24]; - float days = (float) _secs / 86400.0; - - if (_secs >= 86400 * 365) sprintf (formatted, "%.1fy", (days / 365.0)); - else if (_secs >= 86400 * 84) sprintf (formatted, "%1dmo", (int) (days / 30)); - else if (_secs >= 86400 * 13) sprintf (formatted, "%dw", (int) (float) (days / 7.0)); - else if (_secs >= 86400) sprintf (formatted, "%dd", (int) days); - else if (_secs >= 3600) sprintf (formatted, "%dh", (int) (_secs / 3600)); - else if (_secs >= 60) sprintf (formatted, "%dmin", (int) (_secs / 60)); - else if (_secs >= 1) sprintf (formatted, "%ds", (int) _secs); - else formatted[0] = '\0'; - - return std::string (formatted); -} - -//////////////////////////////////////////////////////////////////////////////// -std::string Duration::formatPrecise () const -{ - char formatted[24]; - - int days = _secs / 86400; - int hours = (_secs % 86400) / 3600; - int minutes = (_secs % 3600) / 60; - int seconds = _secs % 60; - - if (days > 0) sprintf (formatted, "%dd %d:%02d:%02d", days, hours, minutes, seconds); - else sprintf (formatted, "%d:%02d:%02d", hours, minutes, seconds); - - return std::string (formatted); -} - -//////////////////////////////////////////////////////////////////////////////// -std::string Duration::formatSeconds () const -{ - char formatted[24]; - sprintf (formatted, "%llus", (unsigned long long)_secs); - return std::string (formatted); -} - -//////////////////////////////////////////////////////////////////////////////// -std::string Duration::formatISO () const -{ - if (_secs) - { - time_t t = _secs; - int seconds = t % 60; t /= 60; - int minutes = t % 60; t /= 60; - int hours = t % 24; t /= 24; - int days = t % 30; t /= 30; - int months = t % 12; t /= 12; - int years = t; - - std::stringstream s; - s << 'P'; - if (years) s << years << 'Y'; - if (months) s << months << 'M'; - if (days) s << days << 'D'; - - if (hours || minutes || seconds) - { - s << 'T'; - if (hours) s << hours << 'H'; - if (minutes) s << minutes << 'M'; - if (seconds) s << seconds << 'S'; - } - - return s.str (); - } - else - { - return "P0S"; - } -} - -//////////////////////////////////////////////////////////////////////////////// -bool Duration::parse (const std::string& input, std::string::size_type& start) -{ - std::string::size_type original_start = start; - Nibbler n (input.substr (start)); - - // Static and so preserved between calls. - static std::vector units; - if (units.size () == 0) - for (unsigned int i = 0; i < NUM_DURATIONS; i++) - units.push_back (durations[i].unit); - - std::string number; - std::string unit; - - if (n.getOneOf (units, unit)) - { - if (n.depleted () || - Lexer::isWhitespace (n.next ())) - { - start = original_start + n.cursor (); - - // Linear lookup - should be logarithmic. - for (unsigned int i = 0; i < NUM_DURATIONS; i++) - { - if (durations[i].unit == unit && - durations[i].standalone == true) - { - _secs = static_cast (durations[i].seconds); - return true; - } - } - } - } - - else if (n.getNumber (number)) - { - n.skipWS (); - if (n.getOneOf (units, unit)) - { - if (n.depleted () || - Lexer::isWhitespace (n.next ())) - { - start = original_start + n.cursor (); - double quantity = strtod (number.c_str (), NULL); - - // Linear lookup - should be logarithmic. - double seconds = 1; - for (unsigned int i = 0; i < NUM_DURATIONS; i++) - { - if (durations[i].unit == unit) - { - seconds = durations[i].seconds; - _secs = static_cast (quantity * static_cast (seconds)); - return true; - } - } - } - } - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -void Duration::clear () -{ - _secs = 0; -} - -//////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/Duration.h task-2.5.0+dfsg/src/Duration.h --- task-2.4.4+dfsg/src/Duration.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/Duration.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// 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 -// -//////////////////////////////////////////////////////////////////////////////// - -#ifndef INCLUDED_DURATION -#define INCLUDED_DURATION - -#include -#include - -class Duration -{ -public: - Duration (); // Default constructor - Duration (time_t); // Constructor - Duration (const std::string&); // Parse - ~Duration (); // Destructor - Duration (const Duration&); // Unimplemented - bool operator< (const Duration&); - bool operator> (const Duration&); - Duration& operator= (const Duration&); - operator time_t () const; - operator std::string () const; - std::string format () const; - std::string formatCompact () const; - std::string formatPrecise () const; - std::string formatSeconds () const; - std::string formatISO () const; - - bool parse (const std::string&, std::string::size_type&); - void clear (); - -protected: - time_t _secs; -}; - -#endif -//////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/Eval.cpp task-2.5.0+dfsg/src/Eval.cpp --- task-2.4.4+dfsg/src/Eval.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/Eval.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -104,8 +104,7 @@ //////////////////////////////////////////////////////////////////////////////// Eval::Eval () -: _ambiguity (true) -, _debug (false) +: _debug (false) { addSource (namedConstants); } @@ -126,7 +125,6 @@ { // Reduce e to a vector of tokens. Lexer l (e); - l.ambiguity (_ambiguity); std::vector > tokens; std::string token; Lexer::Type type; @@ -154,7 +152,6 @@ { // Reduce e to a vector of tokens. Lexer l (e); - l.ambiguity (_ambiguity); std::vector > tokens; std::string token; Lexer::Type type; @@ -173,7 +170,6 @@ { // Reduce e to a vector of tokens. Lexer l (e); - l.ambiguity (_ambiguity); std::string token; Lexer::Type type; while (l.token (token, type)) @@ -197,16 +193,29 @@ } //////////////////////////////////////////////////////////////////////////////// -void Eval::evaluateCompiledExpression (Variant& v) +void Eval::compileExpression ( + const std::vector >& precompiled) { - // Call the postfix evaluator. - evaluatePostfixStack (_compiled, v); + _compiled = precompiled; + + // Parse for syntax checking and operator replacement. + if (_debug) + context.debug ("FILTER Infix " + dump (_compiled)); + infixParse (_compiled); + if (_debug) + context.debug ("FILTER Infix parsed " + dump (_compiled)); + + // Convert infix --> postfix. + infixToPostfix (_compiled); + if (_debug) + context.debug ("FILTER Postfix " + dump (_compiled)); } //////////////////////////////////////////////////////////////////////////////// -void Eval::ambiguity (bool value) +void Eval::evaluateCompiledExpression (Variant& v) { - _ambiguity = value; + // Call the postfix evaluator. + evaluatePostfixStack (_compiled, v); } //////////////////////////////////////////////////////////////////////////////// @@ -217,21 +226,25 @@ //////////////////////////////////////////////////////////////////////////////// // Static. -void Eval::getOperators (std::vector & all) +std::vector Eval::getOperators () { - all.clear (); + std::vector all; for (unsigned int i = 0; i < NUM_OPERATORS; ++i) all.push_back (operators[i].op); + + return all; } //////////////////////////////////////////////////////////////////////////////// // Static. -void Eval::getBinaryOperators (std::vector & all) +std::vector Eval::getBinaryOperators () { - all.clear (); + std::vector all; for (unsigned int i = 0; i < NUM_OPERATORS; ++i) if (operators[i].type == 'b') all.push_back (operators[i].op); + + return all; } //////////////////////////////////////////////////////////////////////////////// @@ -245,12 +258,11 @@ // This is stack used by the postfix evaluator. std::vector values; - std::vector >::const_iterator token; - for (token = tokens.begin (); token != tokens.end (); ++token) + for (auto& token : tokens) { // Unary operators. - if (token->second == Lexer::Type::op && - token->first == "!") + if (token.second == Lexer::Type::op && + token.first == "!") { if (values.size () < 1) throw std::string (STRING_EVAL_NO_EVAL); @@ -260,10 +272,10 @@ Variant result = ! right; values.push_back (result); if (_debug) - context.debug (format ("Eval {1} ↓'{2}' → ↑'{3}'", token->first, (std::string) right, (std::string) result)); + context.debug (format ("Eval {1} ↓'{2}' → ↑'{3}'", token.first, (std::string) right, (std::string) result)); } - else if (token->second == Lexer::Type::op && - token->first == "_neg_") + else if (token.second == Lexer::Type::op && + token.first == "_neg_") { if (values.size () < 1) throw std::string (STRING_EVAL_NO_EVAL); @@ -276,18 +288,18 @@ values.push_back (result); if (_debug) - context.debug (format ("Eval {1} ↓'{2}' → ↑'{3}'", token->first, (std::string) right, (std::string) result)); + context.debug (format ("Eval {1} ↓'{2}' → ↑'{3}'", token.first, (std::string) right, (std::string) result)); } - else if (token->second == Lexer::Type::op && - token->first == "_pos_") + else if (token.second == Lexer::Type::op && + token.first == "_pos_") { // The _pos_ operator is a NOP. if (_debug) - context.debug (format ("[{1}] eval op {2} NOP", values.size (), token->first)); + context.debug (format ("[{1}] eval op {2} NOP", values.size (), token.first)); } // Binary operators. - else if (token->second == Lexer::Type::op) + else if (token.second == Lexer::Type::op) { if (values.size () < 2) throw std::string (STRING_EVAL_NO_EVAL); @@ -300,46 +312,46 @@ // Ordering these by anticipation frequency of use is a good idea. Variant result; - if (token->first == "and") result = left && right; - else if (token->first == "or") result = left || right; - else if (token->first == "&&") result = left && right; - else if (token->first == "||") result = left || right; - else if (token->first == "<") result = left < right; - else if (token->first == "<=") result = left <= right; - else if (token->first == ">") result = left > right; - else if (token->first == ">=") result = left >= right; - else if (token->first == "==") result = left.operator== (right); - else if (token->first == "!==") result = left.operator!= (right); - else if (token->first == "=") result = left.operator_partial (right); - else if (token->first == "!=") result = left.operator_nopartial (right); - else if (token->first == "+") result = left + right; - else if (token->first == "-") result = left - right; - else if (token->first == "*") result = left * right; - else if (token->first == "/") result = left / right; - else if (token->first == "^") result = left ^ right; - else if (token->first == "%") result = left % right; - else if (token->first == "xor") result = left.operator_xor (right); - else if (token->first == "~") result = left.operator_match (right, contextTask); - else if (token->first == "!~") result = left.operator_nomatch (right, contextTask); - else if (token->first == "_hastag_") result = left.operator_hastag (right, contextTask); - else if (token->first == "_notag_") result = left.operator_notag (right, contextTask); + if (token.first == "and") result = left && right; + else if (token.first == "or") result = left || right; + else if (token.first == "&&") result = left && right; + else if (token.first == "||") result = left || right; + else if (token.first == "<") result = left < right; + else if (token.first == "<=") result = left <= right; + else if (token.first == ">") result = left > right; + else if (token.first == ">=") result = left >= right; + else if (token.first == "==") result = left.operator== (right); + else if (token.first == "!==") result = left.operator!= (right); + else if (token.first == "=") result = left.operator_partial (right); + else if (token.first == "!=") result = left.operator_nopartial (right); + else if (token.first == "+") result = left + right; + else if (token.first == "-") result = left - right; + else if (token.first == "*") result = left * right; + else if (token.first == "/") result = left / right; + else if (token.first == "^") result = left ^ right; + else if (token.first == "%") result = left % right; + else if (token.first == "xor") result = left.operator_xor (right); + else if (token.first == "~") result = left.operator_match (right, contextTask); + else if (token.first == "!~") result = left.operator_nomatch (right, contextTask); + else if (token.first == "_hastag_") result = left.operator_hastag (right, contextTask); + else if (token.first == "_notag_") result = left.operator_notag (right, contextTask); else - throw format (STRING_EVAL_UNSUPPORTED, token->first); + throw format (STRING_EVAL_UNSUPPORTED, token.first); values.push_back (result); if (_debug) - context.debug (format ("Eval ↓'{1}' {2} ↓'{3}' → ↑'{4}'", (std::string) left, token->first, (std::string) right, (std::string) result)); + context.debug (format ("Eval ↓'{1}' {2} ↓'{3}' → ↑'{4}'", (std::string) left, token.first, (std::string) right, (std::string) result)); } // Literals and identifiers. else { - Variant v (token->first); - switch (token->second) + Variant v (token.first); + switch (token.second) { case Lexer::Type::number: - if (Lexer::isAllDigits (token->first)) + if (Lexer::isAllDigits (token.first)) { v.cast (Variant::type_integer); if (_debug) @@ -353,7 +365,6 @@ } break; - case Lexer::Type::op: throw std::string (STRING_EVAL_OP_EXPECTED); break; @@ -362,13 +373,12 @@ case Lexer::Type::identifier: { bool found = false; - std::vector ::const_iterator source; - for (source = _sources.begin (); source != _sources.end (); ++source) + for (auto source = _sources.begin (); source != _sources.end (); ++source) { - if ((*source) (token->first, v)) + if ((*source) (token.first, v)) { if (_debug) - context.debug (format ("Eval identifier source '{1}' → ↑'{2}'", token->first, (std::string) v)); + context.debug (format ("Eval identifier source '{1}' → ↑'{2}'", token.first, (std::string) v)); found = true; break; } @@ -379,7 +389,7 @@ { v.cast (Variant::type_string); if (_debug) - context.debug (format ("Eval identifier source failed '{1}'", token->first)); + context.debug (format ("Eval identifier source failed '{1}'", token.first)); } } break; @@ -397,19 +407,6 @@ break; // Nothing to do. -/* - case Lexer::Type::uuid: - case Lexer::Type::hex: - case Lexer::Type::list: - case Lexer::Type::url: - case Lexer::Type::pair: - case Lexer::Type::separator: - case Lexer::Type::tag: - case Lexer::Type::path: - case Lexer::Type::substitution: - case Lexer::Type::pattern: - case Lexer::Type::word: -*/ case Lexer::Type::string: default: if (_debug) @@ -707,8 +704,7 @@ else { bool found = false; - std::vector ::const_iterator source; - for (source = _sources.begin (); source != _sources.end (); ++source) + for (auto source = _sources.begin (); source != _sources.end (); ++source) { Variant v; if ((*source) (infix[i].first, v)) @@ -784,16 +780,15 @@ unsigned int precedence; char associativity; - std::vector >::iterator token; - for (token = infix.begin (); token != infix.end (); ++token) + for (auto& token : infix) { - if (token->second == Lexer::Type::op && - token->first == "(") + if (token.second == Lexer::Type::op && + token.first == "(") { - op_stack.push_back (*token); + op_stack.push_back (token); } - else if (token->second == Lexer::Type::op && - token->first == ")") + else if (token.second == Lexer::Type::op && + token.first == ")") { while (op_stack.size () && op_stack.back ().first != "(") @@ -807,8 +802,8 @@ else throw std::string ("Mismatched parentheses in expression"); } - else if (token->second == Lexer::Type::op && - identifyOperator (token->first, type, precedence, associativity)) + else if (token.second == Lexer::Type::op && + identifyOperator (token.first, type, precedence, associativity)) { char type2; unsigned int precedence2; @@ -822,11 +817,11 @@ op_stack.pop_back (); } - op_stack.push_back (*token); + op_stack.push_back (token); } else { - postfix.push_back (*token); + postfix.push_back (token); } } @@ -880,8 +875,7 @@ color_map[Lexer::Type::duration] = Color ("rgb531 on gray6"); std::string output; - std::vector >::const_iterator i; - for (i = tokens.begin (); i != tokens.end (); ++i) + for (auto i = tokens.begin (); i != tokens.end (); ++i) { if (i != tokens.begin ()) output += ' '; diff -Nru task-2.4.4+dfsg/src/Eval.h task-2.5.0+dfsg/src/Eval.h --- task-2.4.4+dfsg/src/Eval.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/Eval.h 2015-10-21 21:18:15.000000000 +0000 @@ -45,12 +45,12 @@ void evaluateInfixExpression (const std::string&, Variant&) const; void evaluatePostfixExpression (const std::string&, Variant&) const; void compileExpression (const std::string&); + void compileExpression (const std::vector >&); void evaluateCompiledExpression (Variant&); - void ambiguity (bool); void debug (bool); - static void getOperators (std::vector &); - static void getBinaryOperators (std::vector &); + static std::vector getOperators (); + static std::vector getBinaryOperators (); private: void evaluatePostfixStack (const std::vector >&, Variant&) const; @@ -72,7 +72,6 @@ private: std::vector _sources; - bool _ambiguity; bool _debug; std::vector > _compiled; }; diff -Nru task-2.4.4+dfsg/src/feedback.cpp task-2.5.0+dfsg/src/feedback.cpp --- task-2.4.4+dfsg/src/feedback.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/feedback.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include #include @@ -44,49 +44,17 @@ static void countTasks (const std::vector &, const std::string&, int&, int&); //////////////////////////////////////////////////////////////////////////////// -bool taskDiff (const Task& before, const Task& after) -{ - // Attributes are all there is, so figure the different attribute names - // between before and after. - std::vector beforeAtts; - Task::const_iterator att; - for (att = before.begin (); att != before.end (); ++att) - beforeAtts.push_back (att->first); - - std::vector afterAtts; - for (att = after.begin (); att != after.end (); ++att) - afterAtts.push_back (att->first); - - std::vector beforeOnly; - std::vector afterOnly; - listDiff (beforeAtts, afterAtts, beforeOnly, afterOnly); - - if (beforeOnly.size () != - afterOnly.size ()) - return true; - - std::vector ::iterator name; - for (name = beforeAtts.begin (); name != beforeAtts.end (); ++name) - if (*name != "uuid" && - before.get (*name) != after.get (*name)) - return true; - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// std::string taskDifferences (const Task& before, const Task& after) { // Attributes are all there is, so figure the different attribute names // between before and after. std::vector beforeAtts; - Task::const_iterator att; - for (att = before.begin (); att != before.end (); ++att) - beforeAtts.push_back (att->first); + for (auto& att : before) + beforeAtts.push_back (att.first); std::vector afterAtts; - for (att = after.begin (); att != after.end (); ++att) - afterAtts.push_back (att->first); + for (auto& att : after) + afterAtts.push_back (att.first); std::vector beforeOnly; std::vector afterOnly; @@ -94,15 +62,14 @@ // Now start generating a description of the differences. std::stringstream out; - std::vector ::iterator name; - for (name = beforeOnly.begin (); name != beforeOnly.end (); ++name) + for (auto& name : beforeOnly) out << " - " - << format (STRING_FEEDBACK_DELETED, ucFirst (*name)) + << format (STRING_FEEDBACK_DELETED, ucFirst (name)) << "\n"; - for (name = afterOnly.begin (); name != afterOnly.end (); ++name) + for (auto& name : afterOnly) { - if (*name == "depends") + if (name == "depends") { std::vector deps_after; after.getDependencies (deps_after); @@ -116,21 +83,21 @@ else out << " - " << format (STRING_FEEDBACK_ATT_SET, - ucFirst (*name), - renderAttribute (*name, after.get (*name))) + ucFirst (name), + renderAttribute (name, after.get (name))) << "\n"; } - for (name = beforeAtts.begin (); name != beforeAtts.end (); ++name) + for (auto& name : beforeAtts) { // Ignore UUID differences, and find values that changed, but are not also // in the beforeOnly and afterOnly lists, which have been handled above.. - if (*name != "uuid" && - before.get (*name) != after.get (*name) && - std::find (beforeOnly.begin (), beforeOnly.end (), *name) == beforeOnly.end () && - std::find (afterOnly.begin (), afterOnly.end (), *name) == afterOnly.end ()) + if (name != "uuid" && + before.get (name) != after.get (name) && + std::find (beforeOnly.begin (), beforeOnly.end (), name) == beforeOnly.end () && + std::find (afterOnly.begin (), afterOnly.end (), name) == afterOnly.end ()) { - if (*name == "depends") + if (name == "depends") { std::vector deps_before; before.getDependencies (deps_before); @@ -149,9 +116,9 @@ else out << " - " << format (STRING_FEEDBACK_ATT_MOD, - ucFirst (*name), - renderAttribute (*name, before.get (*name)), - renderAttribute (*name, after.get (*name))) + ucFirst (name), + renderAttribute (name, before.get (name)), + renderAttribute (name, after.get (name))) << "\n"; } } @@ -176,13 +143,12 @@ // Attributes are all there is, so figure the different attribute names // between before and after. std::vector beforeAtts; - Task::const_iterator att; - for (att = before.begin (); att != before.end (); ++att) - beforeAtts.push_back (att->first); + for (auto& att : before) + beforeAtts.push_back (att.first); std::vector afterAtts; - for (att = after.begin (); att != after.end (); ++att) - afterAtts.push_back (att->first); + for (auto& att : after) + afterAtts.push_back (att.first); std::vector beforeOnly; std::vector afterOnly; @@ -190,10 +156,9 @@ // Now start generating a description of the differences. std::stringstream out; - std::vector ::iterator name; - for (name = beforeOnly.begin (); name != beforeOnly.end (); ++name) + for (auto& name : beforeOnly) { - if (*name == "depends") + if (name == "depends") { std::vector deps_before; before.getDependencies (deps_before); @@ -203,27 +168,27 @@ out << format (STRING_FEEDBACK_DEP_DEL, from) << "\n"; } - else if (name->substr (0, 11) == "annotation_") + else if (name.substr (0, 11) == "annotation_") { - out << format (STRING_FEEDBACK_ANN_DEL, before.get (*name)) + out << format (STRING_FEEDBACK_ANN_DEL, before.get (name)) << "\n"; } - else if (*name == "start") + else if (name == "start") { - out << format (STRING_FEEDBACK_ATT_DEL_DUR, ucFirst (*name), - Duration (current_timestamp - last_timestamp).formatPrecise ()) + out << format (STRING_FEEDBACK_ATT_DEL_DUR, ucFirst (name), + ISO8601p (current_timestamp - last_timestamp).format ()) << "\n"; } else { - out << format (STRING_FEEDBACK_ATT_DEL, ucFirst (*name)) + out << format (STRING_FEEDBACK_ATT_DEL, ucFirst (name)) << "\n"; } } - for (name = afterOnly.begin (); name != afterOnly.end (); ++name) + for (auto& name : afterOnly) { - if (*name == "depends") + if (name == "depends") { std::vector deps_after; after.getDependencies (deps_after); @@ -233,30 +198,31 @@ out << format (STRING_FEEDBACK_DEP_WAS_SET, to) << "\n"; } - else if (name->substr (0, 11) == "annotation_") + else if (name.substr (0, 11) == "annotation_") { - out << format (STRING_FEEDBACK_ANN_ADD, after.get (*name)) + out << format (STRING_FEEDBACK_ANN_ADD, after.get (name)) << "\n"; } else { - if (*name == "start") + if (name == "start") last_timestamp = current_timestamp; out << format (STRING_FEEDBACK_ATT_WAS_SET, - ucFirst (*name), - renderAttribute (*name, after.get (*name), dateformat)) + ucFirst (name), + renderAttribute (name, after.get (name), dateformat)) << "\n"; } } - for (name = beforeAtts.begin (); name != beforeAtts.end (); ++name) - if (*name != "uuid" && - *name != "modified" && - before.get (*name) != after.get (*name) && - before.get (*name) != "" && after.get (*name) != "") + for (auto& name : beforeAtts) + if (name != "uuid" && + name != "modified" && + before.get (name) != after.get (name) && + before.get (name) != "" && + after.get (name) != "") { - if (*name == "depends") + if (name == "depends") { std::vector deps_before; before.getDependencies (deps_before); @@ -271,16 +237,16 @@ out << format (STRING_FEEDBACK_DEP_WAS_MOD, from, to) << "\n"; } - else if (name->substr (0, 11) == "annotation_") + else if (name.substr (0, 11) == "annotation_") { - out << format (STRING_FEEDBACK_ANN_WAS_MOD, after.get (*name)) + out << format (STRING_FEEDBACK_ANN_WAS_MOD, after.get (name)) << "\n"; } else out << format (STRING_FEEDBACK_ATT_WAS_MOD, - ucFirst (*name), - renderAttribute (*name, before.get (*name), dateformat), - renderAttribute (*name, after.get (*name), dateformat)) + ucFirst (name), + renderAttribute (name, before.get (name), dateformat), + renderAttribute (name, after.get (name), dateformat)) << "\n"; } @@ -300,15 +266,11 @@ col->type () == "date" && value != "") { - Date d ((time_t)strtol (value.c_str (), NULL, 10)); + ISO8601d d ((time_t)strtol (value.c_str (), NULL, 10)); if (format == "") - { return d.toString (context.config.get ("dateformat")); - } - else - { - return d.toString (format); - } + + return d.toString (format); } return value; @@ -357,6 +319,46 @@ } //////////////////////////////////////////////////////////////////////////////// +// Implements feedback and error when adding a reserved tag name. +void feedback_reserved_tags (const std::string& tag) +{ + // Note: This list must match that in Task::hasTag. + // Note: This list must match that in CmdInfo::execute. + if (tag == "ACTIVE" || + tag == "ANNOTATED" || + tag == "BLOCKED" || + tag == "BLOCKING" || + tag == "CHILD" || + tag == "COMPLETED" || + tag == "DELETED" || + tag == "DUE" || + tag == "DUETODAY" || + tag == "LATEST" || + tag == "MONTH" || + tag == "ORPHAN" || + tag == "OVERDUE" || + tag == "PARENT" || + tag == "PENDING" || + tag == "PRIORITY" || + tag == "PROJECT" || + tag == "READY" || + tag == "SCHEDULED" || + tag == "TAGGED" || + tag == "TODAY" || + tag == "TOMORROW" || + tag == "UDA" || + tag == "UNBLOCKED" || + tag == "UNTIL" || + tag == "WAITING" || + tag == "WEEK" || + tag == "YEAR" || + tag == "YESTERDAY") + { + throw format (STRING_FEEDBACK_TAG_VIRTUAL, tag); + } +} + +//////////////////////////////////////////////////////////////////////////////// // Implements feedback when adding special tags to a task. void feedback_special_tags (const Task& task, const std::string& tag) { @@ -397,24 +399,23 @@ dependencyGetBlocked (task, blocked); // Scan all the tasks that were blocked by this task - std::vector ::iterator i; - for (i = blocked.begin (); i != blocked.end (); ++i) + for (auto& i : blocked) { std::vector blocking; - dependencyGetBlocking (*i, blocking); + dependencyGetBlocking (i, blocking); if (blocking.size () == 0) { - if (i->id) + if (i.id) std::cout << format (STRING_FEEDBACK_UNBLOCKED, - i->id, - i->get ("description")) + i.id, + i.get ("description")) << "\n"; else { - std::string uuid = i->get ("uuid"); + std::string uuid = i.get ("uuid"); std::cout << format (STRING_FEEDBACK_UNBLOCKED, - i->get ("uuid"), - i->get ("description")) + i.get ("uuid"), + i.get ("description")) << "\n"; } } @@ -429,10 +430,9 @@ context.verbose ("sync")) { std::vector lines = context.tdb2.backlog.get_lines (); - std::vector ::iterator line; - for (line = lines.begin (); line != lines.end (); ++line) + for (auto& line : lines) { - if ((*line)[0] == '{') + if ((line)[0] == '{') { context.footnote (STRING_FEEDBACK_BACKLOG); break; @@ -518,12 +518,11 @@ int& count_pending, int& count_done) { - std::vector ::const_iterator it; - for (it = all.begin (); it != all.end (); ++it) + for (auto& it : all) { - if (it->get ("project") == project) + if (it.get ("project") == project) { - switch (it->getStatus ()) + switch (it.getStatus ()) { case Task::pending: case Task::waiting: diff -Nru task-2.4.4+dfsg/src/File.cpp task-2.5.0+dfsg/src/File.cpp --- task-2.4.4+dfsg/src/File.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/File.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,525 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//////////////////////////////////////////////////////////////////////////////// -File::File () -: Path::Path () -, _fh (NULL) -, _h (-1) -, _locked (false) -{ -} - -//////////////////////////////////////////////////////////////////////////////// -File::File (const Path& other) -: Path::Path (other) -, _fh (NULL) -, _h (-1) -, _locked (false) -{ -} - -//////////////////////////////////////////////////////////////////////////////// -File::File (const File& other) -: Path::Path (other) -, _fh (NULL) -, _h (-1) -, _locked (false) -{ -} - -//////////////////////////////////////////////////////////////////////////////// -File::File (const std::string& in) -: Path::Path (in) -, _fh (NULL) -, _h (-1) -, _locked (false) -{ -} - -//////////////////////////////////////////////////////////////////////////////// -File::~File () -{ - if (_fh) - close (); -} - -//////////////////////////////////////////////////////////////////////////////// -File& File::operator= (const File& other) -{ - if (this != &other) - Path::operator= (other); - - _locked = false; - return *this; -} - -//////////////////////////////////////////////////////////////////////////////// -bool File::create (int mode /* = 0640 */) -{ - if (open ()) - { - fchmod (_h, mode); - close (); - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool File::remove () const -{ - return unlink (_data.c_str ()) == 0 ? true : false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool File::open () -{ - if (_data != "") - { - if (! _fh) - { - bool already_exists = exists (); - if (already_exists) - if (!readable () || !writable ()) - throw std::string (format (STRING_FILE_PERMS, _data)); - - _fh = fopen (_data.c_str (), (already_exists ? "r+" : "w+")); - if (_fh) - { - _h = fileno (_fh); - _locked = false; - return true; - } - } - else - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool File::openAndLock () -{ - return open () && lock (); -} - -//////////////////////////////////////////////////////////////////////////////// -void File::close () -{ - if (_fh) - { - if (_locked) - unlock (); - - fclose (_fh); - _fh = NULL; - _h = -1; - _locked = false; - } -} - -//////////////////////////////////////////////////////////////////////////////// -bool File::lock () -{ - _locked = false; - if (_fh && _h != -1) - { - // l_type l_whence l_start l_len l_pid - struct flock fl = {F_WRLCK, SEEK_SET, 0, 0, 0 }; - fl.l_pid = getpid (); - if (fcntl (_h, F_SETLKW, &fl) == 0) - _locked = true; - } - - return _locked; -} - -//////////////////////////////////////////////////////////////////////////////// -void File::unlock () -{ - if (_locked) - { - // l_type l_whence l_start l_len l_pid - struct flock fl = {F_UNLCK, SEEK_SET, 0, 0, 0 }; - fl.l_pid = getpid (); - - fcntl (_h, F_SETLK, &fl); - _locked = false; - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Opens if necessary. -void File::read (std::string& contents) -{ - contents = ""; - contents.reserve (size ()); - - std::ifstream in (_data.c_str ()); - if (in.good ()) - { - std::string line; - line.reserve (512 * 1024); - while (getline (in, line)) - contents += line + "\n"; - - in.close (); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Opens if necessary. -void File::read (std::vector & contents) -{ - contents.clear (); - - std::ifstream in (_data.c_str ()); - if (in.good ()) - { - std::string line; - line.reserve (512 * 1024); - while (getline (in, line)) - contents.push_back (line); - - in.close (); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Opens if necessary. -void File::write (const std::string& line) -{ - if (!_fh) - open (); - - if (_fh) - fputs (line.c_str (), _fh); -} - -//////////////////////////////////////////////////////////////////////////////// -// Opens if necessary. -void File::write (const std::vector & lines) -{ - if (!_fh) - open (); - - if (_fh) - { - std::vector ::const_iterator it; - for (it = lines.begin (); it != lines.end (); ++it) - fputs (it->c_str (), _fh); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Opens if necessary. -void File::append (const std::string& line) -{ - if (!_fh) - open (); - - if (_fh) - { - fseek (_fh, 0, SEEK_END); - fputs (line.c_str (), _fh); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Opens if necessary. -void File::append (const std::vector & lines) -{ - if (!_fh) - open (); - - if (_fh) - { - fseek (_fh, 0, SEEK_END); - std::vector ::const_iterator it; - for (it = lines.begin (); it != lines.end (); ++it) - fputs (((*it) + "\n").c_str (), _fh); - } -} - -//////////////////////////////////////////////////////////////////////////////// -void File::truncate () -{ - if (!_fh) - open (); - - if (_fh) - ftruncate (_h, 0); -} - -//////////////////////////////////////////////////////////////////////////////// -// S_IFMT 0170000 type of file -// S_IFIFO 0010000 named pipe (fifo) -// S_IFCHR 0020000 character special -// S_IFDIR 0040000 directory -// S_IFBLK 0060000 block special -// S_IFREG 0100000 regular -// S_IFLNK 0120000 symbolic link -// S_IFSOCK 0140000 socket -// S_IFWHT 0160000 whiteout -// S_ISUID 0004000 set user id on execution -// S_ISGID 0002000 set group id on execution -// S_ISVTX 0001000 save swapped text even after use -// S_IRUSR 0000400 read permission, owner -// S_IWUSR 0000200 write permission, owner -// S_IXUSR 0000100 execute/search permission, owner -mode_t File::mode () -{ - struct stat s; - if (!stat (_data.c_str (), &s)) - return s.st_mode; - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -size_t File::size () const -{ - struct stat s; - if (!stat (_data.c_str (), &s)) - return s.st_size; - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -time_t File::mtime () const -{ - struct stat s; - if (!stat (_data.c_str (), &s)) - return s.st_mtime; - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -time_t File::ctime () const -{ - struct stat s; - if (!stat (_data.c_str (), &s)) - return s.st_ctime; - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -time_t File::btime () const -{ - struct stat s; - if (!stat (_data.c_str (), &s)) -#ifdef HAVE_ST_BIRTHTIME - return s.st_birthtime; -#else - return s.st_ctime; -#endif - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -bool File::create (const std::string& name, int mode /* = 0640 */) -{ - std::string full_name = expand (name); - std::ofstream out (full_name.c_str ()); - if (out.good ()) - { - out.close (); - chmod (full_name.c_str (), mode); - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -std::string File::read (const std::string& name) -{ - std::string contents = ""; - - std::ifstream in (name.c_str ()); - if (in.good ()) - { - std::string line; - line.reserve (1024); - while (getline (in, line)) - contents += line + "\n"; - - in.close (); - } - - return contents; -} - -//////////////////////////////////////////////////////////////////////////////// -bool File::read (const std::string& name, std::string& contents) -{ - contents = ""; - - std::ifstream in (name.c_str ()); - if (in.good ()) - { - std::string line; - line.reserve (1024); - while (getline (in, line)) - contents += line + "\n"; - - in.close (); - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool File::read (const std::string& name, std::vector & contents) -{ - contents.clear (); - - std::ifstream in (name.c_str ()); - if (in.good ()) - { - std::string line; - line.reserve (1024); - while (getline (in, line)) - contents.push_back (line); - - in.close (); - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool File::write (const std::string& name, const std::string& contents) -{ - std::ofstream out (expand (name).c_str (), - std::ios_base::out | std::ios_base::trunc); - if (out.good ()) - { - out << contents; - out.close (); - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool File::write ( - const std::string& name, - const std::vector & lines, - bool addNewlines /* = true */) -{ - std::ofstream out (expand (name).c_str (), - std::ios_base::out | std::ios_base::trunc); - if (out.good ()) - { - std::vector ::const_iterator it; - for (it = lines.begin (); it != lines.end (); ++it) - { - out << *it; - - if (addNewlines) - out << "\n"; - } - - out.close (); - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool File::append (const std::string& name, const std::string& contents) -{ - std::ofstream out (expand (name).c_str (), - std::ios_base::out | std::ios_base::app); - if (out.good ()) - { - out << contents; - out.close (); - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool File::append ( - const std::string& name, - const std::vector & lines, - bool addNewlines /* = true */) -{ - std::ofstream out (expand (name).c_str (), - std::ios_base::out | std::ios_base::app); - if (out.good ()) - { - std::vector ::const_iterator it; - for (it = lines.begin (); it != lines.end (); ++it) - { - out << *it; - - if (addNewlines) - out << "\n"; - } - - out.close (); - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool File::remove (const std::string& name) -{ - return unlink (expand (name).c_str ()) == 0 ? true : false; -} - -//////////////////////////////////////////////////////////////////////////////// - diff -Nru task-2.4.4+dfsg/src/File.h task-2.5.0+dfsg/src/File.h --- task-2.4.4+dfsg/src/File.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/File.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,91 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// 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 -// -//////////////////////////////////////////////////////////////////////////////// - -#ifndef INCLUDED_FILE -#define INCLUDED_FILE - -#include -#include -#include -#include -#include - -class File : public Path -{ -public: - File (); - File (const Path&); - File (const File&); - File (const std::string&); - virtual ~File (); - - File& operator= (const File&); - - virtual bool create (int mode = 0640); - virtual bool remove () const; - - bool open (); - bool openAndLock (); - void close (); - - bool lock (); - void unlock (); - - void read (std::string&); - void read (std::vector &); - - void write (const std::string&); - void write (const std::vector &); - - void append (const std::string&); - void append (const std::vector &); - - void truncate (); - - virtual mode_t mode (); - virtual size_t size () const; - virtual time_t mtime () const; - virtual time_t ctime () const; - virtual time_t btime () const; - - static bool create (const std::string&, int mode = 0640); - static std::string read (const std::string&); - static bool read (const std::string&, std::string&); - static bool read (const std::string&, std::vector &); - static bool write (const std::string&, const std::string&); - static bool write (const std::string&, const std::vector &, bool addNewlines = true); - static bool append (const std::string&, const std::string&); - static bool append (const std::string&, const std::vector &, bool addNewlines = true); - static bool remove (const std::string&); - -private: - FILE* _fh; - int _h; - bool _locked; -}; - -#endif -//////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/Filter.cpp task-2.5.0+dfsg/src/Filter.cpp --- task-2.4.4+dfsg/src/Filter.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/Filter.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -25,6 +25,7 @@ //////////////////////////////////////////////////////////////////////////////// #include +#include #include #include #include @@ -57,6 +58,7 @@ Filter::Filter () : _startCount (0) , _endCount (0) +, _safety (true) { } @@ -67,39 +69,41 @@ //////////////////////////////////////////////////////////////////////////////// // Take an input set of tasks and filter into a subset. -void Filter::subset (const std::vector & input, std::vector & output, bool applyContext /* = true */) +void Filter::subset (const std::vector & input, std::vector & output) { context.timer_filter.start (); _startCount = (int) input.size (); - if (context.config.getInteger ("debug.parser") >= 1) - context.debug (context.cli.dump ("Filter::subset")); + context.cli2.prepareFilter (); - std::string filterExpr = context.cli.getFilter (applyContext); - if (filterExpr.length ()) + std::vector > precompiled; + for (auto& a : context.cli2._args) + if (a.hasTag ("FILTER")) + precompiled.push_back (std::pair (a.getToken (), a._lextype)); + + if (precompiled.size ()) { Eval eval; - eval.ambiguity (false); eval.addSource (domSource); eval.addSource (namedDates); // Debug output from Eval during compilation is useful. During evaluation // it is mostly noise. - eval.debug (context.config.getInteger ("debug.parser") >= 2 ? true : false); - eval.compileExpression (filterExpr); - eval.debug (false); + eval.debug (context.config.getInteger ("debug.parser") >= 3 ? true : false); + eval.compileExpression (precompiled); - std::vector ::const_iterator task; - for (task = input.begin (); task != input.end (); ++task) + for (auto& task : input) { // Set up context for any DOM references. - contextTask = *task; + contextTask = task; Variant var; eval.evaluateCompiledExpression (var); if (var.get_bool ()) - output.push_back (*task); + output.push_back (task); } + + eval.debug (false); } else output = input; @@ -111,86 +115,82 @@ //////////////////////////////////////////////////////////////////////////////// // Take the set of all tasks and filter into a subset. -void Filter::subset (std::vector & output, bool applyContext /* = true */) +void Filter::subset (std::vector & output) { context.timer_filter.start (); - if (context.config.getInteger ("debug.parser") >= 1) - context.debug (context.cli.dump ("Filter::subset")); + context.cli2.prepareFilter (); + + std::vector > precompiled; + for (auto& a : context.cli2._args) + if (a.hasTag ("FILTER")) + precompiled.push_back (std::pair (a.getToken (), a._lextype)); + // Shortcut indicates that only pending.data needs to be loaded. bool shortcut = false; - std::string filterExpr = context.cli.getFilter (applyContext); - if (filterExpr.length ()) + + if (precompiled.size ()) { context.timer_filter.stop (); - const std::vector & pending = context.tdb2.pending.get_tasks (); + auto pending = context.tdb2.pending.get_tasks (); context.timer_filter.start (); _startCount = (int) pending.size (); Eval eval; - eval.ambiguity (false); eval.addSource (domSource); eval.addSource (namedDates); // Debug output from Eval during compilation is useful. During evaluation // it is mostly noise. - eval.debug (context.config.getInteger ("debug.parser") >= 2 ? true : false); - eval.compileExpression (filterExpr); - eval.debug (false); + eval.debug (context.config.getInteger ("debug.parser") >= 3 ? true : false); + eval.compileExpression (precompiled); output.clear (); - std::vector ::const_iterator task; - - for (task = pending.begin (); task != pending.end (); ++task) + for (auto& task : pending) { // Set up context for any DOM references. - contextTask = *task; + contextTask = task; Variant var; - eval.debug (context.config.getInteger ("debug.parser") >= 2 ? true : false); eval.evaluateCompiledExpression (var); - eval.debug (false); if (var.get_bool ()) - output.push_back (*task); + output.push_back (task); } shortcut = pendingOnly (); if (! shortcut) { context.timer_filter.stop (); - const std::vector & completed = context.tdb2.completed.get_tasks (); + auto completed = context.tdb2.completed.get_tasks (); context.timer_filter.start (); _startCount += (int) completed.size (); - for (task = completed.begin (); task != completed.end (); ++task) + for (auto& task : completed) { // Set up context for any DOM references. - contextTask = *task; + contextTask = task; Variant var; - eval.debug (context.config.getInteger ("debug.parser") >= 2 ? true : false); eval.evaluateCompiledExpression (var); - eval.debug (false); if (var.get_bool ()) - output.push_back (*task); + output.push_back (task); } } + + eval.debug (false); } else { safety (); - context.timer_filter.stop (); - const std::vector & pending = context.tdb2.pending.get_tasks (); - const std::vector & completed = context.tdb2.completed.get_tasks (); - context.timer_filter.start (); - std::vector ::const_iterator task; - for (task = pending.begin (); task != pending.end (); ++task) - output.push_back (*task); + for (auto& task : context.tdb2.pending.get_tasks ()) + output.push_back (task); - for (task = completed.begin (); task != completed.end (); ++task) - output.push_back (*task); + for (auto& task : context.tdb2.completed.get_tasks ()) + output.push_back (task); + + context.timer_filter.start (); } _endCount = (int) output.size (); @@ -199,10 +199,45 @@ } //////////////////////////////////////////////////////////////////////////////// -// If the filter contains the restriction "status:pending", as the first filter -// term, then completed.data does not need to be loaded. +bool Filter::hasFilter () +{ + for (auto& a : context.cli2._args) + if (a.hasTag ("FILTER")) + return true; + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +bool Filter::hasModifications () +{ + for (auto& a : context.cli2._args) + if (a.hasTag ("MODIFICATION")) + return true; + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +bool Filter::hasMiscellaneous () +{ + for (auto& a : context.cli2._args) + if (a.hasTag ("MISCELLANEOUS")) + return true; + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +// If the filter contains no 'or', 'xor' or 'not' operators, and only includes +// status values 'pending', 'waiting' or 'recurring', then the filter is +// guaranteed to only need data from pending.data. bool Filter::pendingOnly () { + // When GC is off, there are no shortcuts. + if (! context.config.getBoolean ("gc")) + return false; + // To skip loading completed.data, there should be: // - 'status' in filter // - no 'completed' @@ -213,27 +248,32 @@ int countPending = 0; int countWaiting = 0; int countRecurring = 0; - int countId = 0; + int countId = (int) context.cli2._id_ranges.size (); + int countUUID = (int) context.cli2._uuid_list.size (); int countOr = 0; int countXor = 0; int countNot = 0; - std::vector ::iterator a; - for (a = context.cli._args.begin (); a != context.cli._args.end (); ++a) + for (auto& a : context.cli2._args) { - if (a->hasTag ("FILTER")) + if (a.hasTag ("FILTER")) { - if (a->hasTag ("ID")) ++countId; - if (a->hasTag ("OP") && a->attribute ("raw") == "or") ++countOr; - if (a->hasTag ("OP") && a->attribute ("raw") == "xor") ++countXor; - if (a->hasTag ("OP") && a->attribute ("raw") == "not") ++countNot; - if (a->hasTag ("ATTRIBUTE") && a->attribute ("name") == "status") ++countStatus; - if ( a->attribute ("raw") == "pending") ++countPending; - if ( a->attribute ("raw") == "waiting") ++countWaiting; - if ( a->attribute ("raw") == "recurring") ++countRecurring; + std::string raw = a.attribute ("raw"); + std::string canonical = a.attribute ("canonical"); + + if (a._lextype == Lexer::Type::op && raw == "or") ++countOr; + if (a._lextype == Lexer::Type::op && raw == "xor") ++countXor; + if (a._lextype == Lexer::Type::op && raw == "not") ++countNot; + if (a._lextype == Lexer::Type::dom && canonical == "status") ++countStatus; + if ( raw == "pending") ++countPending; + if ( raw == "waiting") ++countPending; + if ( raw == "recurring") ++countPending; } } + if (countUUID) + return false; + if (countOr || countXor || countNot) return false; @@ -246,26 +286,23 @@ } if (countId) - { return true; - } return false; } //////////////////////////////////////////////////////////////////////////////// -// Disaster avoidance mechanism. If a WRITECMD has no filter, then it can cause +// Disaster avoidance mechanism. If a !READONLY has no filter, then it can cause // all tasks to be modified. This is usually not intended. void Filter::safety () { - std::vector ::iterator a; - for (a = context.cli._args.begin (); a != context.cli._args.end (); ++a) + if (_safety) { - if (a->hasTag ("CMD")) + for (auto& a : context.cli2._args) { - if (a->hasTag ("WRITECMD")) + if (a.hasTag ("CMD")) { - if (context.cli.getFilter () == "") + if (! a.hasTag ("READONLY")) { if (! context.config.getBoolean ("allow.empty.filter")) throw std::string (STRING_TASK_SAFETY_ALLOW); @@ -278,12 +315,18 @@ // Sounds the alarm. throw std::string (STRING_TASK_SAFETY_FAIL); } - } - // CMD was found. - return; + // CMD was found. + return; + } } } } //////////////////////////////////////////////////////////////////////////////// +void Filter::disableSafety () +{ + _safety = false; +} + +//////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/Filter.h task-2.5.0+dfsg/src/Filter.h --- task-2.4.4+dfsg/src/Filter.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/Filter.h 2015-10-21 21:18:15.000000000 +0000 @@ -40,14 +40,19 @@ Filter (); ~Filter (); - void subset (const std::vector &, std::vector &, bool applyContext = true); - void subset (std::vector &, bool applyContext = true); + void subset (const std::vector &, std::vector &); + void subset (std::vector &); + bool hasFilter (); + bool hasModifications (); + bool hasMiscellaneous (); bool pendingOnly (); void safety (); + void disableSafety (); private: - int _startCount; - int _endCount; + int _startCount; + int _endCount; + bool _safety; }; #endif diff -Nru task-2.4.4+dfsg/src/FS.cpp task-2.5.0+dfsg/src/FS.cpp --- task-2.4.4+dfsg/src/FS.cpp 1970-01-01 00:00:00.000000000 +0000 +++ task-2.5.0+dfsg/src/FS.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -0,0 +1,990 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined SOLARIS || defined NETBSD || defined FREEBSD +#include +#endif + +// Fixes build with musl libc. +#ifndef GLOB_TILDE +#define GLOB_TILDE 0 +#endif + +#ifndef GLOB_BRACE +#define GLOB_BRACE 0 +#endif + +//////////////////////////////////////////////////////////////////////////////// +std::ostream& operator<< (std::ostream& out, const Path& path) +{ + out << path._data; + return out; +} + +//////////////////////////////////////////////////////////////////////////////// +Path::Path () +{ +} + +//////////////////////////////////////////////////////////////////////////////// +Path::Path (const Path& other) +{ + if (this != &other) + { + _original = other._original; + _data = other._data; + } +} + +//////////////////////////////////////////////////////////////////////////////// +Path::Path (const std::string& in) +{ + _original = in; + _data = expand (in); +} + +//////////////////////////////////////////////////////////////////////////////// +Path::~Path () +{ +} + +//////////////////////////////////////////////////////////////////////////////// +Path& Path::operator= (const Path& other) +{ + if (this != &other) + { + this->_original = other._original; + this->_data = other._data; + } + + return *this; +} + +//////////////////////////////////////////////////////////////////////////////// +bool Path::operator== (const Path& other) +{ + return _data == other._data; +} + +//////////////////////////////////////////////////////////////////////////////// +Path& Path::operator+= (const std::string& dir) +{ + _data += "/" + dir; + return *this; +} + +//////////////////////////////////////////////////////////////////////////////// +Path::operator std::string () const +{ + return _data; +} + +//////////////////////////////////////////////////////////////////////////////// +std::string Path::name () const +{ + if (_data.length ()) + { + auto slash = _data.rfind ('/'); + if (slash != std::string::npos) + return _data.substr (slash + 1, std::string::npos); + } + + return _data; +} + +//////////////////////////////////////////////////////////////////////////////// +std::string Path::parent () const +{ + if (_data.length ()) + { + auto slash = _data.rfind ('/'); + if (slash != std::string::npos) + return _data.substr (0, slash); + } + + return ""; +} + +//////////////////////////////////////////////////////////////////////////////// +std::string Path::extension () const +{ + if (_data.length ()) + { + auto dot = _data.rfind ('.'); + if (dot != std::string::npos) + return _data.substr (dot + 1, std::string::npos); + } + + return ""; +} + +//////////////////////////////////////////////////////////////////////////////// +bool Path::exists () const +{ + return access (_data.c_str (), F_OK) ? false : true; +} + +//////////////////////////////////////////////////////////////////////////////// +bool Path::is_directory () const +{ + struct stat s {}; + if (! stat (_data.c_str (), &s) && + S_ISDIR (s.st_mode)) + return true; + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +bool Path::is_absolute () const +{ + if (_data.length () && _data[0] == '/') + return true; + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +bool Path::is_link () const +{ + struct stat s {}; + if (! lstat (_data.c_str (), &s) && + S_ISLNK (s.st_mode)) + return true; + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +bool Path::readable () const +{ + return access (_data.c_str (), R_OK) ? false : true; +} + +//////////////////////////////////////////////////////////////////////////////// +bool Path::writable () const +{ + return access (_data.c_str (), W_OK) ? false : true; +} + +//////////////////////////////////////////////////////////////////////////////// +bool Path::executable () const +{ + return access (_data.c_str (), X_OK) ? false : true; +} + +//////////////////////////////////////////////////////////////////////////////// +bool Path::rename (const std::string& new_name) +{ + std::string expanded = expand (new_name); + if (_data != expanded) + { + if (::rename (_data.c_str (), expanded.c_str ()) == 0) + { + _data = expanded; + return true; + } + } + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +// ~ --> /home/user +// ~foo/x --> /home/foo/s +// ~/x --> /home/foo/x +// ./x --> $PWD/x +// x --> $PWD/x +std::string Path::expand (const std::string& in) +{ + std::string copy = in; + + auto tilde = copy.find ("~"); + std::string::size_type slash; + + if (tilde != std::string::npos) + { + const char *home = getenv("HOME"); + if (home == NULL) + { + struct passwd* pw = getpwuid (getuid ()); + home = pw->pw_dir; + } + + // Convert: ~ --> /home/user + if (copy.length () == 1) + copy = home; + + // Convert: ~/x --> /home/user/x + else if (copy.length () > tilde + 1 && + copy[tilde + 1] == '/') + { + copy.replace (tilde, 1, home); + } + + // Convert: ~foo/x --> /home/foo/x + else if ((slash = copy.find ("/", tilde)) != std::string::npos) + { + std::string name = copy.substr (tilde + 1, slash - tilde - 1); + struct passwd* pw = getpwnam (name.c_str ()); + if (pw) + copy.replace (tilde, slash - tilde, pw->pw_dir); + } + } + + // Relative paths + else if (in.length () > 2 && + in.substr (0, 2) == "./") + { + copy = Directory::cwd () + "/" + in.substr (2); + } + else if (in.length () > 1 && + in[0] != '.' && + in[0] != '/') + { + copy = Directory::cwd () + "/" + in; + } + + return copy; +} + +//////////////////////////////////////////////////////////////////////////////// +std::vector Path::glob (const std::string& pattern) +{ + std::vector results; + + glob_t g; +#ifdef SOLARIS + if (!::glob (pattern.c_str (), GLOB_ERR, NULL, &g)) +#else + if (!::glob (pattern.c_str (), GLOB_ERR | GLOB_BRACE | GLOB_TILDE, NULL, &g)) +#endif + for (int i = 0; i < (int) g.gl_pathc; ++i) + results.push_back (g.gl_pathv[i]); + + globfree (&g); + return results; +} + +//////////////////////////////////////////////////////////////////////////////// +File::File () +: Path::Path () +, _fh (NULL) +, _h (-1) +, _locked (false) +{ +} + +//////////////////////////////////////////////////////////////////////////////// +File::File (const Path& other) +: Path::Path (other) +, _fh (NULL) +, _h (-1) +, _locked (false) +{ +} + +//////////////////////////////////////////////////////////////////////////////// +File::File (const File& other) +: Path::Path (other) +, _fh (NULL) +, _h (-1) +, _locked (false) +{ +} + +//////////////////////////////////////////////////////////////////////////////// +File::File (const std::string& in) +: Path::Path (in) +, _fh (NULL) +, _h (-1) +, _locked (false) +{ +} + +//////////////////////////////////////////////////////////////////////////////// +File::~File () +{ + if (_fh) + close (); +} + +//////////////////////////////////////////////////////////////////////////////// +File& File::operator= (const File& other) +{ + if (this != &other) + Path::operator= (other); + + _locked = false; + return *this; +} + +//////////////////////////////////////////////////////////////////////////////// +bool File::create (int mode /* = 0640 */) +{ + if (open ()) + { + fchmod (_h, mode); + close (); + return true; + } + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +bool File::remove () const +{ + return unlink (_data.c_str ()) == 0 ? true : false; +} + +//////////////////////////////////////////////////////////////////////////////// +bool File::open () +{ + if (_data != "") + { + if (! _fh) + { + bool already_exists = exists (); + if (already_exists) + if (!readable () || !writable ()) + throw std::string (format (STRING_FILE_PERMS, _data)); + + _fh = fopen (_data.c_str (), (already_exists ? "r+" : "w+")); + if (_fh) + { + _h = fileno (_fh); + _locked = false; + return true; + } + } + else + return true; + } + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +bool File::openAndLock () +{ + return open () && lock (); +} + +//////////////////////////////////////////////////////////////////////////////// +void File::close () +{ + if (_fh) + { + if (_locked) + unlock (); + + fclose (_fh); + _fh = NULL; + _h = -1; + _locked = false; + } +} + +//////////////////////////////////////////////////////////////////////////////// +bool File::lock () +{ + _locked = false; + if (_fh && _h != -1) + { + // l_type l_whence l_start l_len l_pid + struct flock fl = {F_WRLCK, SEEK_SET, 0, 0, 0 }; + fl.l_pid = getpid (); + if (fcntl (_h, F_SETLKW, &fl) == 0) + _locked = true; + } + + return _locked; +} + +//////////////////////////////////////////////////////////////////////////////// +void File::unlock () +{ + if (_locked) + { + // l_type l_whence l_start l_len l_pid + struct flock fl = {F_UNLCK, SEEK_SET, 0, 0, 0 }; + fl.l_pid = getpid (); + + fcntl (_h, F_SETLK, &fl); + _locked = false; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Opens if necessary. +void File::read (std::string& contents) +{ + contents = ""; + contents.reserve (size ()); + + std::ifstream in (_data.c_str ()); + if (in.good ()) + { + std::string line; + line.reserve (512 * 1024); + while (getline (in, line)) + contents += line + "\n"; + + in.close (); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Opens if necessary. +void File::read (std::vector & contents) +{ + contents.clear (); + + std::ifstream in (_data.c_str ()); + if (in.good ()) + { + std::string line; + line.reserve (512 * 1024); + while (getline (in, line)) + contents.push_back (line); + + in.close (); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Opens if necessary. +void File::write (const std::string& line) +{ + if (!_fh) + open (); + + if (_fh) + fputs (line.c_str (), _fh); +} + +//////////////////////////////////////////////////////////////////////////////// +// Opens if necessary. +void File::write (const std::vector & lines) +{ + if (!_fh) + open (); + + if (_fh) + { + for (auto& line : lines) + fputs (line.c_str (), _fh); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Opens if necessary. +void File::append (const std::string& line) +{ + if (!_fh) + open (); + + if (_fh) + { + fseek (_fh, 0, SEEK_END); + fputs (line.c_str (), _fh); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Opens if necessary. +void File::append (const std::vector & lines) +{ + if (!_fh) + open (); + + if (_fh) + { + fseek (_fh, 0, SEEK_END); + for (auto& line : lines) + fputs ((line + "\n").c_str (), _fh); + } +} + +//////////////////////////////////////////////////////////////////////////////// +void File::truncate () +{ + if (!_fh) + open (); + + if (_fh) + ftruncate (_h, 0); +} + +//////////////////////////////////////////////////////////////////////////////// +// S_IFMT 0170000 type of file +// S_IFIFO 0010000 named pipe (fifo) +// S_IFCHR 0020000 character special +// S_IFDIR 0040000 directory +// S_IFBLK 0060000 block special +// S_IFREG 0100000 regular +// S_IFLNK 0120000 symbolic link +// S_IFSOCK 0140000 socket +// S_IFWHT 0160000 whiteout +// S_ISUID 0004000 set user id on execution +// S_ISGID 0002000 set group id on execution +// S_ISVTX 0001000 save swapped text even after use +// S_IRUSR 0000400 read permission, owner +// S_IWUSR 0000200 write permission, owner +// S_IXUSR 0000100 execute/search permission, owner +mode_t File::mode () +{ + struct stat s; + if (!stat (_data.c_str (), &s)) + return s.st_mode; + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +size_t File::size () const +{ + struct stat s; + if (!stat (_data.c_str (), &s)) + return s.st_size; + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +time_t File::mtime () const +{ + struct stat s; + if (!stat (_data.c_str (), &s)) + return s.st_mtime; + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +time_t File::ctime () const +{ + struct stat s; + if (!stat (_data.c_str (), &s)) + return s.st_ctime; + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +time_t File::btime () const +{ + struct stat s; + if (!stat (_data.c_str (), &s)) +#ifdef HAVE_ST_BIRTHTIME + return s.st_birthtime; +#else + return s.st_ctime; +#endif + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +bool File::create (const std::string& name, int mode /* = 0640 */) +{ + std::string full_name = expand (name); + std::ofstream out (full_name.c_str ()); + if (out.good ()) + { + out.close (); + chmod (full_name.c_str (), mode); + return true; + } + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +std::string File::read (const std::string& name) +{ + std::string contents = ""; + + std::ifstream in (name.c_str ()); + if (in.good ()) + { + std::string line; + line.reserve (1024); + while (getline (in, line)) + contents += line + "\n"; + + in.close (); + } + + return contents; +} + +//////////////////////////////////////////////////////////////////////////////// +bool File::read (const std::string& name, std::string& contents) +{ + contents = ""; + + std::ifstream in (name.c_str ()); + if (in.good ()) + { + std::string line; + line.reserve (1024); + while (getline (in, line)) + contents += line + "\n"; + + in.close (); + return true; + } + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +bool File::read (const std::string& name, std::vector & contents) +{ + contents.clear (); + + std::ifstream in (name.c_str ()); + if (in.good ()) + { + std::string line; + line.reserve (1024); + while (getline (in, line)) + contents.push_back (line); + + in.close (); + return true; + } + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +bool File::write (const std::string& name, const std::string& contents) +{ + std::ofstream out (expand (name).c_str (), + std::ios_base::out | std::ios_base::trunc); + if (out.good ()) + { + out << contents; + out.close (); + return true; + } + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +bool File::write ( + const std::string& name, + const std::vector & lines, + bool addNewlines /* = true */) +{ + std::ofstream out (expand (name).c_str (), + std::ios_base::out | std::ios_base::trunc); + if (out.good ()) + { + for (auto& line : lines) + { + out << line; + + if (addNewlines) + out << "\n"; + } + + out.close (); + return true; + } + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +bool File::append (const std::string& name, const std::string& contents) +{ + std::ofstream out (expand (name).c_str (), + std::ios_base::out | std::ios_base::app); + if (out.good ()) + { + out << contents; + out.close (); + return true; + } + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +bool File::append ( + const std::string& name, + const std::vector & lines, + bool addNewlines /* = true */) +{ + std::ofstream out (expand (name).c_str (), + std::ios_base::out | std::ios_base::app); + if (out.good ()) + { + for (auto& line : lines) + { + out << line; + + if (addNewlines) + out << "\n"; + } + + out.close (); + return true; + } + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +bool File::remove (const std::string& name) +{ + return unlink (expand (name).c_str ()) == 0 ? true : false; +} + +//////////////////////////////////////////////////////////////////////////////// +Directory::Directory () +{ +} + +//////////////////////////////////////////////////////////////////////////////// +Directory::Directory (const Directory& other) +: File::File (other) +{ +} + +//////////////////////////////////////////////////////////////////////////////// +Directory::Directory (const File& other) +: File::File (other) +{ +} + +//////////////////////////////////////////////////////////////////////////////// +Directory::Directory (const Path& other) +: File::File (other) +{ +} + +//////////////////////////////////////////////////////////////////////////////// +Directory::Directory (const std::string& in) +: File::File (in) +{ +} + +//////////////////////////////////////////////////////////////////////////////// +Directory::~Directory () +{ +} + +//////////////////////////////////////////////////////////////////////////////// +Directory& Directory::operator= (const Directory& other) +{ + if (this != &other) + { + File::operator= (other); + } + + return *this; +} + +//////////////////////////////////////////////////////////////////////////////// +bool Directory::create (int mode /* = 0755 */) +{ + return mkdir (_data.c_str (), mode) == 0 ? true : false; +} + +//////////////////////////////////////////////////////////////////////////////// +bool Directory::remove () const +{ + return remove_directory (_data); +} + +//////////////////////////////////////////////////////////////////////////////// +bool Directory::remove_directory (const std::string& dir) const +{ + DIR* dp = opendir (dir.c_str ()); + if (dp != NULL) + { + struct dirent* de; + while ((de = readdir (dp)) != NULL) + { + if (!strcmp (de->d_name, ".") || + !strcmp (de->d_name, "..")) + continue; + +#if defined (SOLARIS) || defined (HAIKU) + struct stat s; + lstat ((dir + "/" + de->d_name).c_str (), &s); + if (S_ISDIR (s.st_mode)) + remove_directory (dir + "/" + de->d_name); + else + unlink ((dir + "/" + de->d_name).c_str ()); +#else + if (de->d_type == DT_UNKNOWN) + { + struct stat s; + lstat ((dir + "/" + de->d_name).c_str (), &s); + if (S_ISDIR (s.st_mode)) + de->d_type = DT_DIR; + } + if (de->d_type == DT_DIR) + remove_directory (dir + "/" + de->d_name); + else + unlink ((dir + "/" + de->d_name).c_str ()); +#endif + } + + closedir (dp); + } + + return rmdir (dir.c_str ()) ? false : true; +} + +//////////////////////////////////////////////////////////////////////////////// +std::vector Directory::list () +{ + std::vector files; + list (_data, files, false); + return files; +} + +//////////////////////////////////////////////////////////////////////////////// +std::vector Directory::listRecursive () +{ + std::vector files; + list (_data, files, true); + return files; +} + +//////////////////////////////////////////////////////////////////////////////// +std::string Directory::cwd () +{ +#ifdef HAVE_GET_CURRENT_DIR_NAME + char *buf = get_current_dir_name (); + if (buf == NULL) + throw std::bad_alloc (); + std::string result (buf); + free (buf); + return result; +#else + char buf[PATH_MAX]; + getcwd (buf, PATH_MAX - 1); + return std::string (buf); +#endif +} + +//////////////////////////////////////////////////////////////////////////////// +bool Directory::up () +{ + if (_data == "/") + return false; + + auto slash = _data.rfind ('/'); + if (slash == 0) + { + _data = "/"; // Root dir should retain the slash. + return true; + } + else if (slash != std::string::npos) + { + _data = _data.substr (0, slash); + return true; + } + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +bool Directory::cd () const +{ + return chdir (_data.c_str ()) == 0 ? true : false; +} + +//////////////////////////////////////////////////////////////////////////////// +void Directory::list ( + const std::string& base, + std::vector & results, + bool recursive) +{ + DIR* dp = opendir (base.c_str ()); + if (dp != NULL) + { + struct dirent* de; + while ((de = readdir (dp)) != NULL) + { + if (!strcmp (de->d_name, ".") || + !strcmp (de->d_name, "..")) + continue; + +#if defined (SOLARIS) || defined (HAIKU) + struct stat s; + stat ((base + "/" + de->d_name).c_str (), &s); + if (recursive && S_ISDIR (s.st_mode)) + list (base + "/" + de->d_name, results, recursive); + else + results.push_back (base + "/" + de->d_name); +#else + if (recursive && de->d_type == DT_UNKNOWN) + { + struct stat s; + lstat ((base + "/" + de->d_name).c_str (), &s); + if (S_ISDIR (s.st_mode)) + de->d_type = DT_DIR; + } + if (recursive && de->d_type == DT_DIR) + list (base + "/" + de->d_name, results, recursive); + else + results.push_back (base + "/" + de->d_name); +#endif + } + + closedir (dp); + } +} + +//////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/FS.h task-2.5.0+dfsg/src/FS.h --- task-2.4.4+dfsg/src/FS.h 1970-01-01 00:00:00.000000000 +0000 +++ task-2.5.0+dfsg/src/FS.h 2015-10-21 21:18:15.000000000 +0000 @@ -0,0 +1,154 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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 +// +//////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDED_FS +#define INCLUDED_FS + +#include +#include +#include +#include + +class Path +{ +public: + Path (); + Path (const Path&); + Path (const std::string&); + virtual ~Path (); + + Path& operator= (const Path&); + bool operator== (const Path&); + Path& operator+= (const std::string&); + operator std::string () const; + + std::string name () const; + std::string parent () const; + std::string extension () const; + bool exists () const; + bool is_directory () const; + bool is_absolute () const; + bool is_link () const; + bool readable () const; + bool writable () const; + bool executable () const; + bool rename (const std::string&); + + // Statics + static std::string expand (const std::string&); + static std::vector glob (const std::string&); + +public: + std::string _original; + std::string _data; +}; + +class File : public Path +{ +public: + File (); + File (const Path&); + File (const File&); + File (const std::string&); + virtual ~File (); + + File& operator= (const File&); + + virtual bool create (int mode = 0640); + virtual bool remove () const; + + bool open (); + bool openAndLock (); + void close (); + + bool lock (); + void unlock (); + + void read (std::string&); + void read (std::vector &); + + void write (const std::string&); + void write (const std::vector &); + + void append (const std::string&); + void append (const std::vector &); + + void truncate (); + + virtual mode_t mode (); + virtual size_t size () const; + virtual time_t mtime () const; + virtual time_t ctime () const; + virtual time_t btime () const; + + static bool create (const std::string&, int mode = 0640); + static std::string read (const std::string&); + static bool read (const std::string&, std::string&); + static bool read (const std::string&, std::vector &); + static bool write (const std::string&, const std::string&); + static bool write (const std::string&, const std::vector &, bool addNewlines = true); + static bool append (const std::string&, const std::string&); + static bool append (const std::string&, const std::vector &, bool addNewlines = true); + static bool remove (const std::string&); + +private: + FILE* _fh; + int _h; + bool _locked; +}; + +class Directory : public File +{ +public: + Directory (); + Directory (const Directory&); + Directory (const File&); + Directory (const Path&); + Directory (const std::string&); + virtual ~Directory (); + + Directory& operator= (const Directory&); + + virtual bool create (int mode = 0755); + virtual bool remove () const; + + std::vector list (); + std::vector listRecursive (); + + static std::string cwd (); + bool up (); + bool cd () const; + +private: + void list (const std::string&, std::vector &, bool); + bool remove_directory (const std::string&) const; +}; + +std::ostream& operator<< (std::ostream&, const Path&); + +#endif +//////////////////////////////////////////////////////////////////////////////// + diff -Nru task-2.4.4+dfsg/src/Hooks.cpp task-2.5.0+dfsg/src/Hooks.cpp --- task-2.4.4+dfsg/src/Hooks.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/Hooks.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -73,18 +73,17 @@ if (_debug >= 1) { - std::vector ::iterator i; - for (i = _scripts.begin (); i != _scripts.end (); ++i) + for (auto& i : _scripts) { - Path p (*i); + Path p (i); std::string name = p.name (); if (name.substr (0, 6) == "on-add" || name.substr (0, 9) == "on-modify" || name.substr (0, 9) == "on-launch" || name.substr (0, 7) == "on-exit") - context.debug ("Found hook script " + *i); + context.debug ("Found hook script " + i); else - context.debug ("Found misnamed hook script " + *i); + context.debug ("Found misnamed hook script " + i); } } } @@ -124,12 +123,11 @@ std::vector matchingScripts = scripts ("on-launch"); if (matchingScripts.size ()) { - std::vector ::iterator script; - for (script = matchingScripts.begin (); script != matchingScripts.end (); ++script) + for (auto& script : matchingScripts) { std::vector input; std::vector output; - int status = callHookScript (*script, input, output); + int status = callHookScript (script, input, output); std::vector outputJSON; std::vector outputFeedback; @@ -139,17 +137,14 @@ if (status == 0) { - std::vector ::iterator message; - for (message = outputFeedback.begin (); message != outputFeedback.end (); ++message) - context.footnote (*message); + for (auto& message : outputFeedback) + context.footnote (message); } else { assertFeedback (outputFeedback); - - std::vector ::iterator message; - for (message = outputFeedback.begin (); message != outputFeedback.end (); ++message) - context.error (*message); + for (auto& message : outputFeedback) + context.error (message); throw 0; // This is how hooks silently terminate processing. } @@ -187,16 +182,14 @@ // Convert to a vector of strings. std::vector input; - std::vector ::const_iterator t; - for (t = tasks.begin (); t != tasks.end (); ++t) - input.push_back (t->composeJSON ()); + for (auto& t : tasks) + input.push_back (t.composeJSON ()); // Call the hook scripts, with the invariant input. - std::vector ::iterator script; - for (script = matchingScripts.begin (); script != matchingScripts.end (); ++script) + for (auto& script : matchingScripts) { std::vector output; - int status = callHookScript (*script, input, output); + int status = callHookScript (script, input, output); std::vector outputJSON; std::vector outputFeedback; @@ -206,17 +199,14 @@ if (status == 0) { - std::vector ::iterator message; - for (message = outputFeedback.begin (); message != outputFeedback.end (); ++message) - context.footnote (*message); + for (auto& message : outputFeedback) + context.footnote (message); } else { assertFeedback (outputFeedback); - - std::vector ::iterator message; - for (message = outputFeedback.begin (); message != outputFeedback.end (); ++message) - context.error (*message); + for (auto& message : outputFeedback) + context.error (message); throw 0; // This is how hooks silently terminate processing. } @@ -253,11 +243,10 @@ input.push_back (task.composeJSON ()); // Call the hook scripts. - std::vector ::iterator script; - for (script = matchingScripts.begin (); script != matchingScripts.end (); ++script) + for (auto& script : matchingScripts) { std::vector output; - int status = callHookScript (*script, input, output); + int status = callHookScript (script, input, output); std::vector outputJSON; std::vector outputFeedback; @@ -272,17 +261,14 @@ // Propagate forward to the next script. input[0] = outputJSON[0]; - std::vector ::iterator message; - for (message = outputFeedback.begin (); message != outputFeedback.end (); ++message) - context.footnote (*message); + for (auto& message : outputFeedback) + context.footnote (message); } else { assertFeedback (outputFeedback); - - std::vector ::iterator message; - for (message = outputFeedback.begin (); message != outputFeedback.end (); ++message) - context.error (*message); + for (auto& message : outputFeedback) + context.error (message); throw 0; // This is how hooks silently terminate processing. } @@ -324,11 +310,10 @@ input.push_back (after.composeJSON ()); // [line 1] modified // Call the hook scripts. - std::vector ::iterator script; - for (script = matchingScripts.begin (); script != matchingScripts.end (); ++script) + for (auto& script : matchingScripts) { std::vector output; - int status = callHookScript (*script, input, output); + int status = callHookScript (script, input, output); std::vector outputJSON; std::vector outputFeedback; @@ -343,17 +328,14 @@ // Propagate accepted changes forward to the next script. input[1] = outputJSON[0]; - std::vector ::iterator message; - for (message = outputFeedback.begin (); message != outputFeedback.end (); ++message) - context.footnote (*message); + for (auto& message : outputFeedback) + context.footnote (message); } else { assertFeedback (outputFeedback); - - std::vector ::iterator message; - for (message = outputFeedback.begin (); message != outputFeedback.end (); ++message) - context.error (*message); + for (auto& message : outputFeedback) + context.error (message); throw 0; // This is how hooks silently terminate processing. } @@ -375,14 +357,13 @@ std::vector Hooks::scripts (const std::string& event) { std::vector matching; - std::vector ::iterator i; - for (i = _scripts.begin (); i != _scripts.end (); ++i) + for (auto& i : _scripts) { - if (i->find ("/" + event) != std::string::npos) + if (i.find ("/" + event) != std::string::npos) { - File script (*i); + File script (i); if (script.executable ()) - matching.push_back (*i); + matching.push_back (i); } } @@ -395,13 +376,12 @@ std::vector & json, std::vector & feedback) const { - std::vector ::const_iterator i; - for (i = output.begin (); i != output.end (); ++i) + for (auto& i : output) { - if (isJSON (*i)) - json.push_back (*i); + if (isJSON (i)) + json.push_back (i); else - feedback.push_back (*i); + feedback.push_back (i); } } @@ -416,12 +396,11 @@ //////////////////////////////////////////////////////////////////////////////// void Hooks::assertValidJSON (const std::vector & input) const { - std::vector ::const_iterator i; - for (i = input.begin (); i != input.end (); i++) + for (auto& i : input) { - if (i->length () < 3 || - (*i)[0] != '{' || - (*i)[i->length () - 1] != '}') + if (i.length () < 3 || + i[0] != '{' || + i[i.length () - 1] != '}') { context.error (STRING_HOOK_ERROR_OBJECT); throw 0; @@ -429,7 +408,7 @@ try { - json::value* root = json::parse (*i); + json::value* root = json::parse (i); if (root->type () != json::j_object) { context.error (STRING_HOOK_ERROR_OBJECT); @@ -447,11 +426,13 @@ context.error (STRING_HOOK_ERROR_NOUUID); throw 0; } + + delete root; } catch (const std::string& e) { - context.error (format (STRING_HOOK_ERROR_SYNTAX, *i)); + context.error (format (STRING_HOOK_ERROR_SYNTAX, i)); if (_debug) context.error (STRING_HOOK_ERROR_JSON + e); throw 0; @@ -459,7 +440,7 @@ catch (...) { - context.error (STRING_HOOK_ERROR_NOPARSE + *i); + context.error (STRING_HOOK_ERROR_NOPARSE + i); throw 0; } } @@ -480,13 +461,12 @@ { std::string uuid = task.get ("uuid"); - std::vector ::const_iterator i; - for (i = input.begin (); i != input.end (); i++) + for (auto& i : input) { - json::object* root_obj = (json::object*)json::parse (*i); + json::object* root_obj = (json::object*)json::parse (i); // If there is no UUID at all. - json_object_iter u = root_obj->_data.find ("uuid"); + auto u = root_obj->_data.find ("uuid"); if (u == root_obj->_data.end () || u->second->type () != json::j_string) { @@ -501,6 +481,8 @@ context.error (format (STRING_HOOK_ERROR_SAME2, uuid, json_uuid)); throw 0; } + + delete root_obj; } } @@ -508,9 +490,8 @@ void Hooks::assertFeedback (const std::vector & input) const { bool foundSomething = false; - std::vector ::const_iterator i; - for (i = input.begin (); i != input.end (); ++i) - if (nontrivial (*i)) + for (auto& i : input) + if (nontrivial (i)) foundSomething = true; if (! foundSomething) @@ -533,7 +514,7 @@ args.push_back ("args:" + std::string (v)); // Command to be executed. - args.push_back ("command:" + context.cli.getCommand ()); + args.push_back ("command:" + context.cli2.getCommand ()); // rc file used after applying all overrides. args.push_back ("rc:" + context.rc_file._data); @@ -559,22 +540,20 @@ if (_debug >= 2) { context.debug ("Hook: input"); - std::vector ::const_iterator i; - for (i = input.begin (); i != input.end (); ++i) - context.debug (" " + *i); + for (auto& i : input) + context.debug (" " + i); } std::string inputStr; - std::vector ::const_iterator i; - for (i = input.begin (); i != input.end (); ++i) - inputStr += *i + "\n"; + for (auto& i : input) + inputStr += i + "\n"; std::vector args; buildHookScriptArgs (args); if (_debug >= 2) { context.debug ("Hooks: args"); - for (auto arg: args) + for (auto& arg: args) context.debug (" " + arg); } @@ -596,10 +575,9 @@ if (_debug >= 2) { context.debug ("Hook: output"); - std::vector ::iterator i; - for (i = output.begin (); i != output.end (); ++i) - if (*i != "") - context.debug (" " + *i); + for (auto& i : output) + if (i != "") + context.debug (" " + i); context.debug (format ("Hook: Completed with status {1}", status)); context.debug (" "); // Blank line diff -Nru task-2.4.4+dfsg/src/interactive.cpp task-2.5.0+dfsg/src/interactive.cpp --- task-2.4.4+dfsg/src/interactive.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/interactive.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -65,7 +65,7 @@ // Ncurses does this, and perhaps we need to as well, to avoid a problem on // Cygwin where the display goes right up to the terminal width, and causes - // and odd color wrapping problem. + // an odd color wrapping problem. if (config.getBoolean ("avoidlastcolumn")) --width; } diff -Nru task-2.4.4+dfsg/src/ISO8601.cpp task-2.5.0+dfsg/src/ISO8601.cpp --- task-2.4.4+dfsg/src/ISO8601.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/ISO8601.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -25,52 +25,177 @@ //////////////////////////////////////////////////////////////////////////////// #include +#include +#include +#include +#include #include +#include #include +#include +#include +#include +#include + +#define DAY 86400 +#define HOUR 3600 +#define MINUTE 60 +#define SECOND 1 + +static struct +{ + std::string unit; + int seconds; + bool standalone; +} durations[] = +{ + // These are sorted by first character, then length, so that Nibbler::getOneOf + // returns a maximal match. + {"annual", 365 * DAY, true}, + {"biannual", 730 * DAY, true}, + {"bimonthly", 61 * DAY, true}, + {"biweekly", 14 * DAY, true}, + {"biyearly", 730 * DAY, true}, + {"daily", 1 * DAY, true}, + {"days", 1 * DAY, false}, + {"day", 1 * DAY, true}, + {"d", 1 * DAY, false}, + {"fortnight", 14 * DAY, true}, + {"hours", 1 * HOUR, false}, + {"hour", 1 * HOUR, true}, + {"hrs", 1 * HOUR, false}, + {"hr", 1 * HOUR, true}, + {"h", 1 * HOUR, false}, + {"minutes", 1 * MINUTE, false}, + {"minute", 1 * MINUTE, true}, + {"mins", 1 * MINUTE, false}, + {"min", 1 * MINUTE, true}, + {"monthly", 30 * DAY, true}, + {"months", 30 * DAY, false}, + {"month", 30 * DAY, true}, + {"mnths", 30 * DAY, false}, + {"mths", 30 * DAY, false}, + {"mth", 30 * DAY, true}, + {"mos", 30 * DAY, false}, + {"mo", 30 * DAY, true}, + {"m", 30 * DAY, false}, + {"quarterly", 91 * DAY, true}, + {"quarters", 91 * DAY, false}, + {"quarter", 91 * DAY, true}, + {"qrtrs", 91 * DAY, false}, + {"qrtr", 91 * DAY, true}, + {"qtrs", 91 * DAY, false}, + {"qtr", 91 * DAY, true}, + {"q", 91 * DAY, false}, + {"semiannual", 183 * DAY, true}, + {"sennight", 14 * DAY, false}, + {"seconds", 1 * SECOND, false}, + {"second", 1 * SECOND, true}, + {"secs", 1 * SECOND, false}, + {"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, false}, + {"wk", 7 * DAY, true}, + {"w", 7 * DAY, false}, + {"yearly", 365 * DAY, true}, + {"years", 365 * DAY, false}, + {"year", 365 * DAY, true}, + {"yrs", 365 * DAY, false}, + {"yr", 365 * DAY, true}, + {"y", 365 * DAY, false}, +}; + +#define NUM_DURATIONS (sizeof (durations) / sizeof (durations[0])) + +std::string ISO8601d::weekstart = STRING_DATE_SUNDAY; +int ISO8601d::minimumMatchLength = 3; +bool ISO8601d::isoEnabled = true; +bool ISO8601p::isoEnabled = true; //////////////////////////////////////////////////////////////////////////////// ISO8601d::ISO8601d () { clear (); + _date = time (NULL); } //////////////////////////////////////////////////////////////////////////////// -ISO8601d::~ISO8601d () +ISO8601d::ISO8601d (const std::string& input, const std::string& format /*= ""*/) { + clear (); + std::string::size_type start = 0; + if (! parse (input, start, format)) + throw ::format (STRING_DATE_INVALID_FORMAT, input, format); } //////////////////////////////////////////////////////////////////////////////// -ISO8601d::operator time_t () const +ISO8601d::ISO8601d (const time_t t) +{ + clear (); + _date = t; +} + +//////////////////////////////////////////////////////////////////////////////// +ISO8601d::ISO8601d (const int m, const int d, const int y) +{ + clear (); + + // Error if not valid. + struct tm t {}; + t.tm_isdst = -1; // Requests that mktime determine summer time effect. + t.tm_mday = d; + t.tm_mon = m - 1; + t.tm_year = y - 1900; + + _date = mktime (&t); +} + +//////////////////////////////////////////////////////////////////////////////// +ISO8601d::ISO8601d (const int m, const int d, const int y, + const int hr, const int mi, const int se) +{ + clear (); + + // Error if not valid. + struct tm t {}; + t.tm_isdst = -1; // Requests that mktime determine summer time effect. + t.tm_mday = d; + t.tm_mon = m - 1; + t.tm_year = y - 1900; + t.tm_hour = hr; + t.tm_min = mi; + t.tm_sec = se; + + _date = mktime (&t); +} + +//////////////////////////////////////////////////////////////////////////////// +ISO8601d::~ISO8601d () { - return _value; } //////////////////////////////////////////////////////////////////////////////// -// By default, ISO8601d allows ambiguous dates, such as YYYY, YYYYMMDD, HHMMSS. -// These are also valid numbers. Setting ambiguity to false inhibites the -// parsing of these as dates. -void ISO8601d::ambiguity (bool value) +ISO8601d::operator time_t () const { - _ambiguity = value; + return _date; } //////////////////////////////////////////////////////////////////////////////// // Supported: // -// result ::= date-ext 'T' time-ext 'Z' # UTC +// result ::= date 'T' time 'Z' # UTC +// | date 'T' time # Local +// | date-ext 'T' time-ext 'Z' # UTC // | date-ext 'T' time-ext offset-ext # Specified TZ // | date-ext 'T' time-ext # Local // | date-ext # Local -// | date 'T' time 'Z' -// | date 'T' time offset-ext -// | date 'T' time -// | date // | time-ext 'Z' -// | time-ext offset-ext +// | time-ext offset-ext Not needed // | time-ext -// | time 'Z' -// | time offset -// | time // ; // // date-ext ::= ±YYYYY-MM-DD Νot needed @@ -83,37 +208,14 @@ // | YYYY-Www // ; // -// date ::= ±YYYYYMMDD Νot needed -// | ±YYYYYWwwD Νot needed -// | ±YYYYYWww Νot needed -// | ±YYYYYDDD Νot needed -// | ±YYYYYMM Νot needed -// | ±YYYYY Νot needed -// | ±YYY Νot needed -// | YYYYMMDD Ambiguous (number) -// | YYYYWwwD -// | YYYYWww -// | YYYYDDD Ambiguous (number) -// | YYYY-MM -// | YYYY Ambiguous (number) -// | YY Ambiguous (number) -// ; -// // time-ext ::= hh:mm:ss[,ss] // | hh:mm[,mm] // | hh[,hh] Ambiguous (number) // ; // -// time ::= hhmmss[,ss] Ambiguous (number) -// | hhmm[,mm] Ambiguous (number) -// | hh[,hh] Ambiguous (number) -// ; -// // time-utc-ext ::= hh:mm[:ss] 'Z' ; -// time-utc ::= hh[mm[ss]] 'Z' ; // // offset-ext ::= ±hh[:mm] ; -// offset ::= ±hh[mm] ; // // Not yet supported: // @@ -127,40 +229,60 @@ // | 'R' [n] '/' datetime '/' datetime # start end // ; // -bool ISO8601d::parse (const std::string& input, std::string::size_type& start) +bool ISO8601d::parse ( + const std::string& input, + std::string::size_type& start, + const std::string& format /* = "" */) { - std::string::size_type i = start; + auto i = start; Nibbler n (input.substr (i)); - - if (parse_date_time_ext (n) || // Most complex first. - parse_date_ext (n) || - parse_time_utc_ext (n) || - parse_time_off_ext (n) || - parse_date_time (n) || - parse_date (n, _ambiguity) || - parse_time_utc (n) || - parse_time_off (n) || - parse_time_ext (n) || // Time last, as it is the most permissive. - parse_time (n, _ambiguity)) + if (parse_formatted (n, format)) { // Check the values and determine time_t. if (validate ()) { - // Record cursor position. start = n.cursor (); + resolve (); + return true; + } + } + // Allow parse_date_time and parse_date_time_ext regardless of + // ISO8601d::isoEnabled setting, because these formats are relied upon by + // the 'import' command, JSON parser and hook system. + else if (parse_date_time (n) || // Strictest first. + parse_date_time_ext (n) || + (ISO8601d::isoEnabled && + (parse_date_time (n) || + parse_date_time_ext (n) || + parse_date_ext (n) || + parse_time_utc_ext (n) || + parse_time_off_ext (n) || + parse_time_ext (n)))) // Time last, as it is the most permissive. + { + // Check the values and determine time_t. + if (validate ()) + { + start = n.cursor (); resolve (); return true; } } + else if (parse_epoch (n) || + parse_named (n)) + { + // ::validate and ::resolve are not needed in this case. + start = n.cursor (); + return true; + } + return false; } //////////////////////////////////////////////////////////////////////////////// void ISO8601d::clear () { - _ambiguity = true; _year = 0; _month = 0; _week = 0; @@ -170,44 +292,364 @@ _seconds = 0; _offset = 0; _utc = false; - _value = 0; - _default_seconds = 0; + _date = 0; } //////////////////////////////////////////////////////////////////////////////// -void ISO8601d::set_default_time (int hours, int minutes, int seconds) +bool ISO8601d::parse_formatted (Nibbler& n, const std::string& format) { - _default_seconds = (hours * 3600) + (minutes * 60) + seconds; + // Short-circuit on missing format. + if (format == "") + return false; + + n.save (); + + int month = -1; // So we can check later. + int day = -1; + int year = -1; + int hour = -1; + int minute = -1; + int second = -1; + + // For parsing, unused. + int wday = -1; + int week = -1; + + for (unsigned int f = 0; f < format.length (); ++f) + { + switch (format[f]) + { + case 'm': + if (n.getDigit (month)) + { + if (month == 0) + n.getDigit (month); + + if (month == 1) + if (n.getDigit (month)) + month += 10; + } + else + { + n.restore (); + return false; + } + break; + + case 'M': + if (! n.getDigit2 (month)) + { + n.restore (); + return false; + } + break; + + case 'd': + if (n.getDigit (day)) + { + if (day == 0) + n.getDigit (day); + + if (day == 1 || day == 2 || day == 3) + { + int tens = day; + if (n.getDigit (day)) + day += 10 * tens; + } + } + else + { + n.restore (); + return false; + } + break; + + case 'D': + if (! n.getDigit2 (day)) + { + n.restore (); + return false; + } + break; + + case 'y': + if (! n.getDigit2 (year)) + { + n.restore (); + return false; + } + year += 2000; + break; + + case 'Y': + if (! n.getDigit4 (year)) + { + n.restore (); + return false; + } + break; + + case 'h': + if (n.getDigit (hour)) + { + if (hour == 0) + n.getDigit (hour); + + if (hour == 1 || hour == 2) + { + int tens = hour; + if (n.getDigit (hour)) + hour += 10 * tens; + } + } + else + { + n.restore (); + return false; + } + break; + + case 'H': + if (! n.getDigit2 (hour)) + { + n.restore (); + return false; + } + break; + + case 'n': + if (n.getDigit (minute)) + { + if (minute == 0) + n.getDigit (minute); + + if (minute < 6) + { + int tens = minute; + if (n.getDigit (minute)) + minute += 10 * tens; + } + } + else + { + n.restore (); + return false; + } + break; + + case 'N': + if (! n.getDigit2 (minute)) + { + n.restore (); + return false; + } + break; + + case 's': + if (n.getDigit (second)) + { + if (second == 0) + n.getDigit (second); + + if (second < 6) + { + int tens = second; + if (n.getDigit (second)) + second += 10 * tens; + } + } + else + { + n.restore (); + return false; + } + break; + + case 'S': + if (! n.getDigit2 (second)) + { + n.restore (); + return false; + } + break; + + case 'v': + if (n.getDigit (week)) + { + if (week == 0) + n.getDigit (week); + + if (week < 6) + { + int tens = week; + if (n.getDigit (week)) + week += 10 * tens; + } + } + else + { + n.restore (); + return false; + } + break; + + case 'V': + if (! n.getDigit2 (week)) + { + n.restore (); + return false; + } + break; + + case 'a': + { + auto cursor = n.cursor (); + wday = ISO8601d::dayOfWeek (n.str ().substr (cursor, 3)); + if (wday == -1) + { + n.restore (); + return false; + } + + n.skipN (3); + } + break; + + case 'A': + { + std::string dayName; + if (n.getUntil (format[f + 1], dayName)) + { + wday = ISO8601d::dayOfWeek (lowerCase (dayName)); + if (wday == -1) + { + n.restore (); + return false; + } + } + } + break; + + case 'b': + { + auto cursor = n.cursor (); + month = ISO8601d::monthOfYear (n.str ().substr (cursor, 3)); + if (month == -1) + { + n.restore (); + return false; + } + + n.skipN (3); + } + break; + + case 'B': + { + std::string monthName; + if (n.getUntil (format[f + 1], monthName)) + { + month = ISO8601d::monthOfYear (lowerCase (monthName)); + if (month == -1) + { + n.restore (); + return false; + } + } + } + break; + + default: + if (! n.skip (format[f])) + { + n.restore (); + return false; + } + break; + } + } + + // It is possible that the format='Y-M-D', and the input is Y-M-DTH:N:SZ, and + // this should not be considered a match. + if (! n.depleted () && ! Lexer::isWhitespace (n.next ())) + { + n.restore (); + return false; + } + + // Missing values are filled in from the current date. + if (year == -1) + { + ISO8601d now; + year = now.year (); + if (month == -1) + { + month = now.month (); + if (day == -1) + { + day = now.day (); + if (hour == -1) + { + hour = now.hour (); + if (minute == -1) + { + minute = now.minute (); + if (second == -1) + second = now.second (); + } + } + } + } + } + + // Any remaining undefined values are assigned defaults. + if (month == -1) month = 1; + if (day == -1) day = 1; + if (hour == -1) hour = 0; + if (minute == -1) minute = 0; + if (second == -1) second = 0; + + _year = year; + _month = month; + _day = day; + _seconds = (hour * 3600) + (minute * 60) + second; + + return true; } //////////////////////////////////////////////////////////////////////////////// -// date-ext 'T' time-ext 'Z' -// date-ext 'T' time-ext offset-ext -// date-ext 'T' time-ext -bool ISO8601d::parse_date_time_ext (Nibbler& n) +bool ISO8601d::parse_named (Nibbler& n) { n.save (); - if (parse_date_ext (n)) + std::string token; + if (n.getUntilWS (token)) { - if (n.skip ('T') && - parse_time_ext (n)) + Variant v; + if (namedDates (token, v)) { - if (n.skip ('Z')) - _utc = true; - else if (parse_off_ext (n)) - ; - - if (! Lexer::isDigit (n.next ())) - return true; + _date = v.get_date (); + return true; } + } - // Restore date_ext - _year = 0; - _month = 0; - _week = 0; - _weekday = 0; - _julian = 0; - _day = 0; + n.restore (); + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +// Valid epoch values are unsigned integers after 1980-01-01T00:00:00Z. This +// restriction means that '12' will not be identified as an epoch date. +bool ISO8601d::parse_epoch (Nibbler& n) +{ + n.save (); + + int epoch; + if (n.getUnsignedInt (epoch) && + n.depleted () && + epoch >= 315532800) + { + _date = static_cast (epoch); + return true; } n.restore (); @@ -215,34 +657,60 @@ } //////////////////////////////////////////////////////////////////////////////// -// date 'T' time 'Z' -// date 'T' time offset -// date 'T' time bool ISO8601d::parse_date_time (Nibbler& n) { - Nibbler backup (n); - if (parse_date (n, true)) + n.save (); + int year, month, day, hour, minute, second; + if (n.getDigit4 (year) && + n.getDigit2 (month) && month && + n.getDigit2 (day) && day && + n.skip ('T') && + n.getDigit2 (hour) && + n.getDigit2 (minute) && minute < 60 && + n.getDigit2 (second) && second < 60) + { + if (n.skip ('Z')) + _utc = true; + + _year = year; + _month = month; + _day = day; + _seconds = (((hour * 60) + minute) * 60) + second; + + return true; + } + + _year = 0; + _month = 0; + _day = 0; + _seconds = 0; + + n.restore (); + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +// date-ext 'T' time-ext 'Z' +// date-ext 'T' time-ext offset-ext +// date-ext 'T' time-ext +bool ISO8601d::parse_date_time_ext (Nibbler& n) +{ + n.save (); + if (parse_date_ext (n)) { if (n.skip ('T') && - parse_time (n, true)) + parse_time_ext (n)) { if (n.skip ('Z')) - { _utc = true; - if (!Lexer::isDigit (n.next ())) - return true; - } - else if (parse_off (n)) - { - if (!Lexer::isDigit (n.next ())) - return true; - } + else if (parse_off_ext (n)) + ; - if (!Lexer::isDigit (n.next ())) + if (! Lexer::isDigit (n.next ())) return true; } - // Restore date + // Restore date_ext _year = 0; _month = 0; _week = 0; @@ -251,7 +719,7 @@ _day = 0; } - n = backup; + n.restore (); return false; } @@ -270,7 +738,7 @@ int month; int day; if (n.skip ('W') && - n.getDigit2 (_week)) + n.getDigit2 (_week) && _week) { if (n.skip ('-') && n.getDigit (_weekday)) @@ -281,15 +749,15 @@ if (!Lexer::isDigit (n.next ())) return true; } - else if (n.getDigit3 (_julian)) + else if (n.getDigit3 (_julian) && _julian) { _year = year; if (!Lexer::isDigit (n.next ())) return true; } - else if (n.getDigit2 (month) && + else if (n.getDigit2 (month) && month && n.skip ('-') && - n.getDigit2 (day)) + n.getDigit2 (day) && day) { _year = year; _month = month; @@ -304,54 +772,35 @@ } //////////////////////////////////////////////////////////////////////////////// -// YYYYMMDD Ambiguous (number) -// YYYYWwwD -// YYYYWww -// YYYYDDD Ambiguous (number) -// YYYY-MM -bool ISO8601d::parse_date (Nibbler& n, bool ambiguous) +// ±hh[:mm] +bool ISO8601d::parse_off_ext (Nibbler& n) { Nibbler backup (n); - int year; - if (n.getDigit4 (year)) + std::string sign; + if (n.getN (1, sign) && (sign == "+" || sign == "-")) { - int month; - if (n.skip ('W')) + int offset; + int hh; + int mm; + if (n.getDigit2 (hh) && hh <= 12 && + !n.getDigit (mm)) { - int week; - if (n.getDigit2 (week)) - { - _week = week; - - int day; - if (n.getDigit (day)) - _weekday = day; + offset = hh * 3600; - _year = year; - if (!Lexer::isDigit (n.next ())) - return true; - } - } - else if (n.skip ('-')) - { - if (n.getDigit2 (_month)) + if (n.skip (':')) { - _year = year; - if (!Lexer::isDigit (n.next ())) - return true; + if (n.getDigit2 (mm) && mm < 60) + { + offset += mm * 60; + } + else + { + n = backup; + return false; + } } - } - else if (n.getDigit4 (month)) - { - _year = year; - _month = month / 100; - _day = month % 100; - if (!Lexer::isDigit (n.next ())) - return true; - } - else if (ambiguous && n.getDigit3 (_julian)) - { - _year = year; + + _offset = (sign == "-") ? -offset : offset; if (!Lexer::isDigit (n.next ())) return true; } @@ -362,31 +811,38 @@ } //////////////////////////////////////////////////////////////////////////////// -// ±hh[:mm] -bool ISO8601d::parse_off_ext (Nibbler& n) +// hh:mm[:ss] +bool ISO8601d::parse_time_ext (Nibbler& n) { Nibbler backup (n); - std::string sign; - if (n.getN (1, sign)) + int seconds = 0; + int hh; + int mm; + int ss; + if (n.getDigit2 (hh) && hh <= 24 && + n.skip (':') && + n.getDigit2 (mm) && mm < 60) { - if (sign == "+" || sign == "-") + seconds = (hh * 3600) + (mm * 60); + + if (n.skip (':')) { - int offset; - int hh; - int mm; - if (n.getDigit2 (hh) && - !n.getDigit (mm)) - { - offset = hh * 3600; - if (n.skip (':') && - n.getDigit2 (mm)) - offset += mm * 60; + if (n.getDigit2 (ss) && ss < 60) + { + seconds += ss; + _seconds = seconds; - _offset = (sign == "-") ? -offset : offset; if (!Lexer::isDigit (n.next ())) return true; } + + n = backup; + return false; } + + _seconds = seconds; + if (!Lexer::isDigit (n.next ())) + return true; } n = backup; @@ -394,29 +850,32 @@ } //////////////////////////////////////////////////////////////////////////////// -// ±hh[mm] -bool ISO8601d::parse_off (Nibbler& n) +// time-ext 'Z' +bool ISO8601d::parse_time_utc_ext (Nibbler& n) { - Nibbler backup (n); - std::string sign; - if (n.getN (1, sign)) + n.save (); + if (parse_time_ext (n) && + n.skip ('Z')) { - if (sign == "+" || sign == "-") - { - int offset; - int hh; - if (n.getDigit2 (hh)) - { - offset = hh * 3600; - int mm; - if (n.getDigit2 (mm)) - offset += mm * 60; + _utc = true; + if (!Lexer::isDigit (n.next ())) + return true; + } - _offset = (sign == "-") ? -offset : offset; - if (!Lexer::isDigit (n.next ())) - return true; - } - } + n.restore (); + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +// time-ext offset-ext +bool ISO8601d::parse_time_off_ext (Nibbler& n) +{ + Nibbler backup (n); + if (parse_time_ext (n) && + parse_off_ext (n)) + { + if (!Lexer::isDigit (n.next ())) + return true; } n = backup; @@ -424,303 +883,849 @@ } //////////////////////////////////////////////////////////////////////////////// -// hh[:mm[:ss]] -bool ISO8601d::parse_time_ext (Nibbler& n) +// Validation via simple range checking. +bool ISO8601d::validate () { - Nibbler backup (n); - int seconds = 0; - int hh; - int mm; - int ss; - if (n.getDigit2 (hh) && - !n.getDigit (mm)) + // _year; + if ((_year && (_year < 1900 || _year > 2200)) || + (_month && (_month < 1 || _month > 12)) || + (_week && (_week < 1 || _week > 53)) || + (_weekday && (_weekday < 0 || _weekday > 6)) || + (_julian && (_julian < 1 || _julian > ISO8601d::daysInYear (_year))) || + (_day && (_day < 1 || _day > ISO8601d::daysInMonth (_month, _year))) || + (_seconds && (_seconds < 1 || _seconds > 86400)) || + (_offset && (_offset < -86400 || _offset > 86400))) + return false; + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// int tm_sec; seconds (0 - 60) +// int tm_min; minutes (0 - 59) +// int tm_hour; hours (0 - 23) +// int tm_mday; day of month (1 - 31) +// int tm_mon; month of year (0 - 11) +// int tm_year; year - 1900 +// int tm_wday; day of week (Sunday = 0) +// int tm_yday; day of year (0 - 365) +// int tm_isdst; is summer time in effect? +// char *tm_zone; abbreviation of timezone name +// long tm_gmtoff; offset from UTC in seconds +void ISO8601d::resolve () +{ + // Don't touch the original values. + int year = _year; + int month = _month; + int week = _week; + int weekday = _weekday; + int julian = _julian; + int day = _day; + int seconds = _seconds; + int offset = _offset; + bool utc = _utc; + + // Get current time. + time_t now = time (NULL); + + // A UTC offset needs to be accommodated. Once the offset is subtracted, + // only local and UTC times remain. + if (offset) { - seconds = hh * 3600; + seconds -= offset; + now -= offset; + utc = true; + } - if (n.skip (':') && - n.getDigit2 (mm) && - !n.getDigit (ss)) + // Get 'now' in the relevant location. + struct tm* t_now = utc ? gmtime (&now) : localtime (&now); + + int seconds_now = (t_now->tm_hour * 3600) + + (t_now->tm_min * 60) + + t_now->tm_sec; + + // Project forward one day if the specified seconds are earlier in the day + // than the current seconds. + if (year == 0 && + month == 0 && + day == 0 && + week == 0 && + weekday == 0 && + seconds < seconds_now) + { + seconds += 86400; + } + + // Convert week + weekday --> julian. + if (week) + { + julian = (week * 7) + weekday - dayOfWeek (year, 1, 4) - 3; + } + + // Provide default values for year, month, day. + else + { + // Default values for year, month, day: + // + // y m d --> y m d + // y m - --> y m 1 + // y - - --> y 1 1 + // - - - --> now now now + // + if (year == 0) + { + year = t_now->tm_year + 1900; + month = t_now->tm_mon + 1; + day = t_now->tm_mday; + } + else { - seconds += mm * 60; + if (month == 0) + { + month = 1; + day = 1; + } + else if (day == 0) + day = 1; + } + } - if (n.skip (':') && - n.getDigit2 (ss)) - seconds += ss; + if (julian) + { + month = 1; + day = julian; + } - _seconds = seconds; - return true; + struct tm t {}; + t.tm_isdst = -1; // Requests that mktime/gmtime determine summer time effect. + t.tm_year = year - 1900; + t.tm_mon = month - 1; + t.tm_mday = day; + + if (seconds > 86400) + { + int days = seconds / 86400; + t.tm_mday += days; + seconds %= 86400; + } + + t.tm_hour = seconds / 3600; + t.tm_min = (seconds % 3600) / 60; + t.tm_sec = seconds % 60; + + _date = utc ? timegm (&t) : mktime (&t); +} + +//////////////////////////////////////////////////////////////////////////////// +time_t ISO8601d::toEpoch () const +{ + return _date; +} + +//////////////////////////////////////////////////////////////////////////////// +std::string ISO8601d::toEpochString () const +{ + std::stringstream epoch; + epoch << _date; + return epoch.str (); +} + +//////////////////////////////////////////////////////////////////////////////// +// 19980119T070000Z = YYYYMMDDThhmmssZ +std::string ISO8601d::toISO () const +{ + struct tm* t = gmtime (&_date); + + std::stringstream iso; + iso << std::setw (4) << std::setfill ('0') << t->tm_year + 1900 + << std::setw (2) << std::setfill ('0') << t->tm_mon + 1 + << std::setw (2) << std::setfill ('0') << t->tm_mday + << "T" + << std::setw (2) << std::setfill ('0') << t->tm_hour + << std::setw (2) << std::setfill ('0') << t->tm_min + << std::setw (2) << std::setfill ('0') << t->tm_sec + << "Z"; + + return iso.str (); +} + +//////////////////////////////////////////////////////////////////////////////// +double ISO8601d::toJulian () const +{ + return (_date / 86400.0) + 2440587.5; +} + +//////////////////////////////////////////////////////////////////////////////// +void ISO8601d::toMDY (int& m, int& d, int& y) const +{ + struct tm* t = localtime (&_date); + + m = t->tm_mon + 1; + d = t->tm_mday; + y = t->tm_year + 1900; +} + +//////////////////////////////////////////////////////////////////////////////// +const std::string ISO8601d::toString ( + const std::string& format /*= "m/d/Y" */) const +{ + // Making this local copy seems to fix a bug. Remove the local copy and + // you'll see segmentation faults and all kinds of gibberish. + std::string localFormat = format; + + char buffer[12]; + std::string formatted; + for (unsigned int i = 0; i < localFormat.length (); ++i) + { + int c = localFormat[i]; + switch (c) + { + case 'm': sprintf (buffer, "%d", this->month ()); break; + case 'M': sprintf (buffer, "%02d", this->month ()); break; + case 'd': sprintf (buffer, "%d", this->day ()); break; + case 'D': sprintf (buffer, "%02d", this->day ()); break; + case 'y': sprintf (buffer, "%02d", this->year () % 100); break; + case 'Y': sprintf (buffer, "%d", this->year ()); break; + case 'a': sprintf (buffer, "%.3s", ISO8601d::dayName (dayOfWeek ()).c_str ()); break; + case 'A': sprintf (buffer, "%.10s", ISO8601d::dayName (dayOfWeek ()).c_str ()); break; + case 'b': sprintf (buffer, "%.3s", ISO8601d::monthName (month ()).c_str ()); break; + case 'B': sprintf (buffer, "%.10s", ISO8601d::monthName (month ()).c_str ()); break; + case 'v': sprintf (buffer, "%d", ISO8601d::weekOfYear (ISO8601d::dayOfWeek (ISO8601d::weekstart))); break; + case 'V': sprintf (buffer, "%02d", ISO8601d::weekOfYear (ISO8601d::dayOfWeek (ISO8601d::weekstart))); break; + case 'h': sprintf (buffer, "%d", this->hour ()); break; + case 'H': sprintf (buffer, "%02d", this->hour ()); break; + case 'n': sprintf (buffer, "%d", this->minute ()); break; + case 'N': sprintf (buffer, "%02d", this->minute ()); break; + case 's': sprintf (buffer, "%d", this->second ()); break; + case 'S': sprintf (buffer, "%02d", this->second ()); break; + case 'j': sprintf (buffer, "%d", this->dayOfYear ()); break; + case 'J': sprintf (buffer, "%03d", this->dayOfYear ()); break; + default: sprintf (buffer, "%c", c); break; } - if (_ambiguity) + formatted += buffer; + } + + return formatted; +} + +//////////////////////////////////////////////////////////////////////////////// +ISO8601d ISO8601d::startOfDay () const +{ + return ISO8601d (month (), day (), year ()); +} + +//////////////////////////////////////////////////////////////////////////////// +ISO8601d ISO8601d::startOfWeek () const +{ + ISO8601d sow (_date); + sow -= (dayOfWeek () * 86400); + return ISO8601d (sow.month (), sow.day (), sow.year ()); +} + +//////////////////////////////////////////////////////////////////////////////// +ISO8601d ISO8601d::startOfMonth () const +{ + return ISO8601d (month (), 1, year ()); +} + +//////////////////////////////////////////////////////////////////////////////// +ISO8601d ISO8601d::startOfYear () const +{ + return ISO8601d (1, 1, year ()); +} + +//////////////////////////////////////////////////////////////////////////////// +bool ISO8601d::valid (const std::string& input, const std::string& format /*= ""*/) +{ + try + { + ISO8601d test (input, format); + } + + catch (...) + { + return false; + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +bool ISO8601d::valid (const int m, const int d, const int y, const int hr, + const int mi, const int se) +{ + if (hr < 0 || hr > 23) + return false; + + if (mi < 0 || mi > 59) + return false; + + if (se < 0 || se > 59) + return false; + + return ISO8601d::valid (m, d, y); +} + +//////////////////////////////////////////////////////////////////////////////// +bool ISO8601d::valid (const int m, const int d, const int y) +{ + // Check that the year is valid. + if (y < 0) + return false; + + // Check that the month is valid. + if (m < 1 || m > 12) + return false; + + // Finally check that the days fall within the acceptable range for this + // month, and whether or not this is a leap year. + if (d < 1 || d > ISO8601d::daysInMonth (m, y)) + return false; + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// Julian +bool ISO8601d::valid (const int d, const int y) +{ + // Check that the year is valid. + if (y < 0) + return false; + + if (d < 1 || d > ISO8601d::daysInYear (y)) + return false; + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// Static +bool ISO8601d::leapYear (int year) +{ + return ((! (year % 4)) && (year % 100)) || + ! (year % 400); +} + +//////////////////////////////////////////////////////////////////////////////// +// Static +int ISO8601d::daysInMonth (int month, int year) +{ + static int days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + + if (month == 2 && ISO8601d::leapYear (year)) + return 29; + + return days[month - 1]; +} + +//////////////////////////////////////////////////////////////////////////////// +// Static +int ISO8601d::daysInYear (int year) +{ + return ISO8601d::leapYear (year) ? 366 : 365; +} + +//////////////////////////////////////////////////////////////////////////////// +// Static +std::string ISO8601d::monthName (int month) +{ + static const char* months[12] = + { + STRING_DATE_JANUARY, + STRING_DATE_FEBRUARY, + STRING_DATE_MARCH, + STRING_DATE_APRIL, + STRING_DATE_MAY, + STRING_DATE_JUNE, + STRING_DATE_JULY, + STRING_DATE_AUGUST, + STRING_DATE_SEPTEMBER, + STRING_DATE_OCTOBER, + STRING_DATE_NOVEMBER, + STRING_DATE_DECEMBER, + }; + + assert (month > 0); + assert (month <= 12); + return ucFirst (months[month - 1]); +} + +//////////////////////////////////////////////////////////////////////////////// +// Static +void ISO8601d::dayName (int dow, std::string& name) +{ + static const char* days[7] = + { + STRING_DATE_SUNDAY, + STRING_DATE_MONDAY, + STRING_DATE_TUESDAY, + STRING_DATE_WEDNESDAY, + STRING_DATE_THURSDAY, + STRING_DATE_FRIDAY, + STRING_DATE_SATURDAY, + }; + + name = ucFirst (days[dow]); +} + +//////////////////////////////////////////////////////////////////////////////// +// Static +std::string ISO8601d::dayName (int dow) +{ + static const char* days[7] = + { + STRING_DATE_SUNDAY, + STRING_DATE_MONDAY, + STRING_DATE_TUESDAY, + STRING_DATE_WEDNESDAY, + STRING_DATE_THURSDAY, + STRING_DATE_FRIDAY, + STRING_DATE_SATURDAY, + }; + + return ucFirst (days[dow]); +} + +//////////////////////////////////////////////////////////////////////////////// +// Static +int ISO8601d::dayOfWeek (const std::string& input) +{ + if (ISO8601d::minimumMatchLength== 0) + ISO8601d::minimumMatchLength = 3; + + if (closeEnough (STRING_DATE_SUNDAY, input, ISO8601d::minimumMatchLength)) return 0; + else if (closeEnough (STRING_DATE_MONDAY, input, ISO8601d::minimumMatchLength)) return 1; + else if (closeEnough (STRING_DATE_TUESDAY, input, ISO8601d::minimumMatchLength)) return 2; + else if (closeEnough (STRING_DATE_WEDNESDAY, input, ISO8601d::minimumMatchLength)) return 3; + else if (closeEnough (STRING_DATE_THURSDAY, input, ISO8601d::minimumMatchLength)) return 4; + else if (closeEnough (STRING_DATE_FRIDAY, input, ISO8601d::minimumMatchLength)) return 5; + else if (closeEnough (STRING_DATE_SATURDAY, input, ISO8601d::minimumMatchLength)) return 6; + + return -1; +} + +//////////////////////////////////////////////////////////////////////////////// +// Using Zeller's Congruence. +// Static +int ISO8601d::dayOfWeek (int year, int month, int day) +{ + int adj = (14 - month) / 12; + int m = month + 12 * adj - 2; + int y = year - adj; + return (day + (13 * m - 1) / 5 + y + y / 4 - y / 100 + y / 400) % 7; +} + +//////////////////////////////////////////////////////////////////////////////// +// Static +int ISO8601d::monthOfYear (const std::string& input) +{ + if (ISO8601d::minimumMatchLength== 0) + ISO8601d::minimumMatchLength= 3; + + if (closeEnough (STRING_DATE_JANUARY, input, ISO8601d::minimumMatchLength)) return 1; + else if (closeEnough (STRING_DATE_FEBRUARY, input, ISO8601d::minimumMatchLength)) return 2; + else if (closeEnough (STRING_DATE_MARCH, input, ISO8601d::minimumMatchLength)) return 3; + else if (closeEnough (STRING_DATE_APRIL, input, ISO8601d::minimumMatchLength)) return 4; + else if (closeEnough (STRING_DATE_MAY, input, ISO8601d::minimumMatchLength)) return 5; + else if (closeEnough (STRING_DATE_JUNE, input, ISO8601d::minimumMatchLength)) return 6; + else if (closeEnough (STRING_DATE_JULY, input, ISO8601d::minimumMatchLength)) return 7; + else if (closeEnough (STRING_DATE_AUGUST, input, ISO8601d::minimumMatchLength)) return 8; + else if (closeEnough (STRING_DATE_SEPTEMBER, input, ISO8601d::minimumMatchLength)) return 9; + else if (closeEnough (STRING_DATE_OCTOBER, input, ISO8601d::minimumMatchLength)) return 10; + else if (closeEnough (STRING_DATE_NOVEMBER, input, ISO8601d::minimumMatchLength)) return 11; + else if (closeEnough (STRING_DATE_DECEMBER, input, ISO8601d::minimumMatchLength)) return 12; + + return -1; +} + +//////////////////////////////////////////////////////////////////////////////// +// Static +int ISO8601d::length (const std::string& format) +{ + int len = 0; + for (auto& i : format) + { + switch (i) { - _seconds = seconds; - if (!Lexer::isDigit (n.next ())) - return true; + case 'm': + case 'M': + case 'd': + case 'D': + case 'y': + case 'v': + case 'V': + case 'h': + case 'H': + case 'n': + case 'N': + case 's': + case 'S': len += 2; break; + case 'b': + case 'j': + case 'J': + case 'a': len += 3; break; + case 'Y': len += 4; break; + case 'A': + case 'B': len += 10; break; + + // Calculate the width, don't assume a single character width. + default: len += mk_wcwidth (i); break; } } - n = backup; - return false; + return len; +} + +//////////////////////////////////////////////////////////////////////////////// +int ISO8601d::month () const +{ + struct tm* t = localtime (&_date); + return t->tm_mon + 1; +} + +//////////////////////////////////////////////////////////////////////////////// +int ISO8601d::week () const +{ + return ISO8601d::weekOfYear (ISO8601d::dayOfWeek (ISO8601d::weekstart)); +} + +//////////////////////////////////////////////////////////////////////////////// +int ISO8601d::day () const +{ + struct tm* t = localtime (&_date); + return t->tm_mday; +} + +//////////////////////////////////////////////////////////////////////////////// +int ISO8601d::year () const +{ + struct tm* t = localtime (&_date); + return t->tm_year + 1900; +} + +//////////////////////////////////////////////////////////////////////////////// +int ISO8601d::weekOfYear (int weekStart) const +{ + struct tm* t = localtime (&_date); + char weekStr[3]; + + if (weekStart == 0) + strftime(weekStr, sizeof(weekStr), "%U", t); + else if (weekStart == 1) + strftime(weekStr, sizeof(weekStr), "%V", t); + else + throw std::string (STRING_DATE_BAD_WEEKSTART); + + int weekNumber = atoi (weekStr); + + if (weekStart == 0) + weekNumber += 1; + + return weekNumber; +} + +//////////////////////////////////////////////////////////////////////////////// +int ISO8601d::dayOfWeek () const +{ + struct tm* t = localtime (&_date); + return t->tm_wday; +} + +//////////////////////////////////////////////////////////////////////////////// +int ISO8601d::dayOfYear () const +{ + struct tm* t = localtime (&_date); + return t->tm_yday + 1; +} + +//////////////////////////////////////////////////////////////////////////////// +int ISO8601d::hour () const +{ + struct tm* t = localtime (&_date); + return t->tm_hour; +} + +//////////////////////////////////////////////////////////////////////////////// +int ISO8601d::minute () const +{ + struct tm* t = localtime (&_date); + return t->tm_min; +} + +//////////////////////////////////////////////////////////////////////////////// +int ISO8601d::second () const +{ + struct tm* t = localtime (&_date); + return t->tm_sec; +} + +//////////////////////////////////////////////////////////////////////////////// +bool ISO8601d::operator== (const ISO8601d& rhs) const +{ + return rhs._date == _date; +} + +//////////////////////////////////////////////////////////////////////////////// +bool ISO8601d::operator!= (const ISO8601d& rhs) const +{ + return rhs._date != _date; +} + +//////////////////////////////////////////////////////////////////////////////// +bool ISO8601d::operator< (const ISO8601d& rhs) const +{ + return _date < rhs._date; +} + +//////////////////////////////////////////////////////////////////////////////// +bool ISO8601d::operator> (const ISO8601d& rhs) const +{ + return _date > rhs._date; } //////////////////////////////////////////////////////////////////////////////// -// hh[mm[ss]] -bool ISO8601d::parse_time (Nibbler& n, bool ambiguous) +bool ISO8601d::operator<= (const ISO8601d& rhs) const { - if (!ambiguous) - return false; - - Nibbler backup (n); - int seconds = 0; - int hh; - if (n.getDigit2 (hh)) - { - seconds = hh * 3600; - - int mm; - if (n.getDigit2 (mm)) - { - seconds += mm * 60; + return _date <= rhs._date; +} - int ss; - if (n.getDigit2 (ss)) - seconds += ss; - } +//////////////////////////////////////////////////////////////////////////////// +bool ISO8601d::operator>= (const ISO8601d& rhs) const +{ + return _date >= rhs._date; +} - _seconds = seconds; - if (!Lexer::isDigit (n.next ())) - return true; - } +//////////////////////////////////////////////////////////////////////////////// +bool ISO8601d::sameHour (const ISO8601d& rhs) const +{ + return this->year () == rhs.year () && + this->month () == rhs.month () && + this->day () == rhs.day () && + this->hour () == rhs.hour (); +} - n = backup; - return false; +//////////////////////////////////////////////////////////////////////////////// +bool ISO8601d::sameDay (const ISO8601d& rhs) const +{ + return this->year () == rhs.year () && + this->month () == rhs.month () && + this->day () == rhs.day (); } //////////////////////////////////////////////////////////////////////////////// -// time-ext 'Z' -bool ISO8601d::parse_time_utc_ext (Nibbler& n) +bool ISO8601d::sameWeek (const ISO8601d& rhs) const { - n.save (); - if (parse_time_ext (n) && - n.skip ('Z')) - { - _utc = true; - if (!Lexer::isDigit (n.next ())) - return true; - } + return this->year () == rhs.year () && + this->week () == rhs.week (); +} - n.restore (); - return false; +//////////////////////////////////////////////////////////////////////////////// +bool ISO8601d::sameMonth (const ISO8601d& rhs) const +{ + return this->year () == rhs.year () && + this->month () == rhs.month (); } //////////////////////////////////////////////////////////////////////////////// -// time 'Z' -bool ISO8601d::parse_time_utc (Nibbler& n) +bool ISO8601d::sameYear (const ISO8601d& rhs) const { - n.save (); - if (parse_time (n, true) && - n.skip ('Z')) - { - _utc = true; - if (!Lexer::isDigit (n.next ())) - return true; - } + return this->year () == rhs.year (); +} - n.restore (); - return false; +//////////////////////////////////////////////////////////////////////////////// +ISO8601d ISO8601d::operator+ (time_t delta) +{ + return ISO8601d (_date + delta); } //////////////////////////////////////////////////////////////////////////////// -// time-ext offset-ext -bool ISO8601d::parse_time_off_ext (Nibbler& n) +ISO8601d ISO8601d::operator+ (const int delta) { - Nibbler backup (n); - if (parse_time_ext (n) && - parse_off_ext (n)) - { - if (!Lexer::isDigit (n.next ())) - return true; - } + return ISO8601d (_date + delta); +} - n = backup; - return false; +//////////////////////////////////////////////////////////////////////////////// +ISO8601d ISO8601d::operator- (const int delta) +{ + return ISO8601d (_date - delta); } //////////////////////////////////////////////////////////////////////////////// -// time offset -bool ISO8601d::parse_time_off (Nibbler& n) +ISO8601d& ISO8601d::operator+= (const int delta) { - Nibbler backup (n); - if (parse_time (n, true) && - parse_off (n)) - { - if (!Lexer::isDigit (n.next ())) - return true; - } + _date += (time_t) delta; + return *this; +} - n = backup; - return false; +//////////////////////////////////////////////////////////////////////////////// +ISO8601d& ISO8601d::operator-= (const int delta) +{ + _date -= (time_t) delta; + return *this; } //////////////////////////////////////////////////////////////////////////////// -// Using Zeller's Congruence. -int ISO8601d::dayOfWeek (int year, int month, int day) +time_t ISO8601d::operator- (const ISO8601d& rhs) { - int adj = (14 - month) / 12; - int m = month + 12 * adj - 2; - int y = year - adj; - return (day + (13 * m - 1) / 5 + y + y / 4 - y / 100 + y / 400) % 7; + return _date - rhs._date; } //////////////////////////////////////////////////////////////////////////////// -// Validation via simple range checking. -bool ISO8601d::validate () +// Prefix decrement by one day. +void ISO8601d::operator-- () { - // _year; - if ((_year && (_year < 1900 || _year > 2100)) || - (_month && (_month < 1 || _month > 12)) || - (_week && (_week < 1 || _week > 53)) || - (_weekday && (_weekday < 0 || _weekday > 6)) || - (_julian && (_julian < 0 || _julian > 366)) || - (_day && (_day < 1 || _day > 31)) || - (_seconds && (_seconds < 1 || _seconds > 86400)) || - (_offset && (_offset < -86400 || _offset > 86400))) - return false; + ISO8601d yesterday = startOfDay () - 1; + yesterday = ISO8601d (yesterday.month (), + yesterday.day (), + yesterday.year (), + hour (), + minute (), + second ()); + _date = yesterday._date; +} - return true; +//////////////////////////////////////////////////////////////////////////////// +// Postfix decrement by one day. +void ISO8601d::operator-- (int) +{ + ISO8601d yesterday = startOfDay () - 1; + yesterday = ISO8601d (yesterday.month (), + yesterday.day (), + yesterday.year (), + hour (), + minute (), + second ()); + _date = yesterday._date; } //////////////////////////////////////////////////////////////////////////////// -// int tm_sec; seconds (0 - 60) -// int tm_min; minutes (0 - 59) -// int tm_hour; hours (0 - 23) -// int tm_mday; day of month (1 - 31) -// int tm_mon; month of year (0 - 11) -// int tm_year; year - 1900 -// int tm_wday; day of week (Sunday = 0) -// int tm_yday; day of year (0 - 365) -// int tm_isdst; is summer time in effect? -// char *tm_zone; abbreviation of timezone name -// long tm_gmtoff; offset from UTC in seconds -void ISO8601d::resolve () +// Prefix increment by one day. +void ISO8601d::operator++ () { - // Don't touch the original values. - int year = _year; - int month = _month; - int week = _week; - int weekday = _weekday; - int julian = _julian; - int day = _day; - int seconds = _seconds; - int offset = _offset; - bool utc = _utc; + ISO8601d tomorrow = (startOfDay () + 90001).startOfDay (); + tomorrow = ISO8601d (tomorrow.month (), + tomorrow.day (), + tomorrow.year (), + hour (), + minute (), + second ()); + _date = tomorrow._date; +} - // Get current time. - time_t now = time (NULL); +//////////////////////////////////////////////////////////////////////////////// +// Postfix increment by one day. +void ISO8601d::operator++ (int) +{ + ISO8601d tomorrow = (startOfDay () + 90001).startOfDay (); + tomorrow = ISO8601d (tomorrow.month (), + tomorrow.day (), + tomorrow.year (), + hour (), + minute (), + second ()); + _date = tomorrow._date; +} - // A UTC offset needs to be accommodated. Once the offset is subtracted, - // only local and UTC times remain. - if (offset) - { - seconds -= offset; - now -= offset; - utc = true; - } +//////////////////////////////////////////////////////////////////////////////// +std::string ISO8601d::dump () const +{ + std::stringstream s; + s << "ISO8601d" + << " y" << _year + << " m" << _month + << " w" << _week + << " wd" << _weekday + << " j" << _julian + << " d" << _day + << " s" << _seconds + << " off" << _offset + << " utc" << _utc + << " =" << _date + << " " << (_date ? toISO () : ""); - // Get 'now' in the relevant location. - struct tm* t_now = utc ? gmtime (&now) : localtime (&now); + return s.str (); +} - int seconds_now = (t_now->tm_hour * 3600) + - (t_now->tm_min * 60) + - t_now->tm_sec; +//////////////////////////////////////////////////////////////////////////////// +ISO8601p::ISO8601p () +{ + clear (); +} - // Project forward one day if the specified seconds are earlier in the day - // than the current seconds. - if (year == 0 && - month == 0 && - day == 0 && - week == 0 && - weekday == 0 && - seconds < seconds_now) - { - seconds += 86400; - } +//////////////////////////////////////////////////////////////////////////////// +ISO8601p::ISO8601p (time_t input) +{ + clear (); + _period = input; +} - // Convert week + weekday --> julian. - if (week) - { - julian = (week * 7) + weekday - dayOfWeek (year, 1, 4) - 3; - } +//////////////////////////////////////////////////////////////////////////////// +ISO8601p::ISO8601p (const std::string& input) +{ + clear (); - // Provide default values for year, month, day. - else + if (Lexer::isAllDigits (input)) { - // Default values for year, month, day: - // - // y m d --> y m d - // y m - --> y m 1 - // y - - --> y 1 1 - // - - - --> now now now - // - if (year == 0) - { - year = t_now->tm_year + 1900; - month = t_now->tm_mon + 1; - day = t_now->tm_mday; - } - else + time_t value = (time_t) strtol (input.c_str (), NULL, 10); + if (value == 0 || value > 60) { - if (month == 0) - { - month = 1; - day = 1; - } - else if (day == 0) - day = 1; + _period = value; + return; } } - if (julian) - { - month = 1; - day = julian; - } + std::string::size_type idx = 0; + parse (input, idx); +} - struct tm t = {0}; - t.tm_isdst = -1; // Requests that mktime/gmtime determine summer time effect. - t.tm_year = year - 1900; - t.tm_mon = month - 1; - t.tm_mday = day; +//////////////////////////////////////////////////////////////////////////////// +ISO8601p::~ISO8601p () +{ +} - if (seconds > 86400) +//////////////////////////////////////////////////////////////////////////////// +ISO8601p& ISO8601p::operator= (const ISO8601p& other) +{ + if (this != &other) { - int days = seconds / 86400; - t.tm_mday += days; - seconds %= 86400; + _year = other._year; + _month = other._month; + _day = other._day; + _hours = other._hours; + _minutes = other._minutes; + _seconds = other._seconds; + _period = other._period; } - t.tm_hour = seconds / 3600; - t.tm_min = (seconds % 3600) / 60; - t.tm_sec = seconds % 60; + return *this; +} - _value = utc ? timegm (&t) : mktime (&t); +//////////////////////////////////////////////////////////////////////////////// +bool ISO8601p::operator< (const ISO8601p& other) +{ + return _period < other._period; } //////////////////////////////////////////////////////////////////////////////// -ISO8601p::ISO8601p () +bool ISO8601p::operator> (const ISO8601p& other) { - clear (); + return _period > other._period; } //////////////////////////////////////////////////////////////////////////////// -ISO8601p::~ISO8601p () +ISO8601p::operator std::string () const { + std::stringstream s; + s << _period; + return s.str (); } //////////////////////////////////////////////////////////////////////////////// ISO8601p::operator time_t () const { - return _value; + return _period; } //////////////////////////////////////////////////////////////////////////////// @@ -749,8 +1754,10 @@ // bool ISO8601p::parse (const std::string& input, std::string::size_type& start) { - std::string::size_type i = start; - Nibbler n (input.substr (i)); + // Attempt and ISO parse first. + auto original_start = start; + Nibbler n (input.substr (original_start)); + n.save (); if (parse_designated (n)) { @@ -765,6 +1772,89 @@ } } + // Attempt a legacy format parse next. + n.restore (); + + // Static and so preserved between calls. + static std::vector units; + if (units.size () == 0) + for (unsigned int i = 0; i < NUM_DURATIONS; i++) + units.push_back (durations[i].unit); + + std::string number; + std::string unit; + + if (n.getOneOf (units, unit)) + { + if (n.depleted () || + Lexer::isWhitespace (n.next ()) || + Lexer::isSingleCharOperator (n.next ())) + { + start = original_start + n.cursor (); + + // Linear lookup - should instead be logarithmic. + for (unsigned int i = 0; i < NUM_DURATIONS; i++) + { + if (durations[i].unit == unit && + durations[i].standalone == true) + { + _period = static_cast (durations[i].seconds); + return true; + } + } + } + } + + else if (n.getNumber (number) && + number.find ('e') == std::string::npos && + number.find ('E') == std::string::npos && + (number.find ('+') == std::string::npos || number.find ('+') == 0) && + (number.find ('-') == std::string::npos || number.find ('-') == 0)) + { + n.skipWS (); + if (n.getOneOf (units, unit)) + { + // The "d" unit is a special case, because it is the only one that can + // legitimately occur at the beginning of a UUID, and be followed by an + // operator: + // + // 1111111d-0000-0000-0000-000000000000 + // + // Because Lexer::isDuration is higher precedence than Lexer::isUUID, + // the above UUID looks like: + // + // <1111111d> <-> ... + // duration op ... + // + // So as a special case, durations, with units of "d" are rejected if the + // quantity exceeds 10000. + // + if (unit == "d" && + strtol (number.c_str (), NULL, 10) > 10000) + return false; + + if (n.depleted () || + Lexer::isWhitespace (n.next ()) || + Lexer::isSingleCharOperator (n.next ())) + { + start = original_start + n.cursor (); + double quantity = strtod (number.c_str (), NULL); + + // Linear lookup - should instead be logarithmic. + double seconds = 1; + for (unsigned int i = 0; i < NUM_DURATIONS; i++) + { + if (durations[i].unit == unit) + { + seconds = durations[i].seconds; + _period = static_cast (quantity * static_cast (seconds)); + return true; + } + } + } + } + } + return false; } @@ -777,7 +1867,56 @@ _hours = 0; _minutes = 0; _seconds = 0; - _value = 0; + _period = 0; +} + +//////////////////////////////////////////////////////////////////////////////// +const std::string ISO8601p::format () const +{ + if (_period) + { + time_t t = _period; + int seconds = t % 60; t /= 60; + int minutes = t % 60; t /= 60; + int hours = t % 24; t /= 24; + int days = t; + + std::stringstream s; + s << 'P'; + if (days) s << days << 'D'; + + if (hours || minutes || seconds) + { + s << 'T'; + if (hours) s << hours << 'H'; + if (minutes) s << minutes << 'M'; + if (seconds) s << seconds << 'S'; + } + + return s.str (); + } + else + { + return "PT0S"; + } +} + +//////////////////////////////////////////////////////////////////////////////// +const std::string ISO8601p::formatVague () const +{ + char formatted[24]; + float days = (float) _period / 86400.0; + + if (_period >= 86400 * 365) sprintf (formatted, "%.1fy", (days / 365.0)); + else if (_period >= 86400 * 84) sprintf (formatted, "%1dmo", (int) (days / 30)); + else if (_period >= 86400 * 13) sprintf (formatted, "%dw", (int) (float) (days / 7.0)); + else if (_period >= 86400) sprintf (formatted, "%dd", (int) days); + else if (_period >= 3600) sprintf (formatted, "%dh", (int) (_period / 3600)); + else if (_period >= 60) sprintf (formatted, "%dmin", (int) (_period / 60)); + else if (_period >= 1) sprintf (formatted, "%ds", (int) _period); + else formatted[0] = '\0'; + + return std::string (formatted); } //////////////////////////////////////////////////////////////////////////////// @@ -850,12 +1989,29 @@ // Allow un-normalized values. void ISO8601p::resolve () { - _value = (_year * 365 * 86400) + - (_month * 30 * 86400) + - (_day * 86400) + - (_hours * 3600) + - (_minutes * 60) + - _seconds; + _period = (_year * 365 * 86400) + + (_month * 30 * 86400) + + (_day * 86400) + + (_hours * 3600) + + (_minutes * 60) + + _seconds; +} + +//////////////////////////////////////////////////////////////////////////////// +std::string ISO8601p::dump () const +{ + std::stringstream s; + s << "ISO8601p" + << " y" << _year + << " mo" << _month + << " d" << _day + << " h" << _hours + << " mi" << _minutes + << " s" << _seconds + << " =" << _period + << " " << (_period ? format () : ""); + + return s.str (); } //////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/ISO8601.h task-2.5.0+dfsg/src/ISO8601.h --- task-2.4.4+dfsg/src/ISO8601.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/ISO8601.h 2015-10-21 21:18:15.000000000 +0000 @@ -23,6 +23,7 @@ // http://www.opensource.org/licenses/mit-license.php // //////////////////////////////////////////////////////////////////////////////// + #ifndef INCLUDED_ISO8601 #define INCLUDED_ISO8601 @@ -33,35 +34,96 @@ class ISO8601d { public: + static std::string weekstart; + static int minimumMatchLength; + static bool isoEnabled; + ISO8601d (); + ISO8601d (const std::string&, const std::string& format = ""); + ISO8601d (time_t); + ISO8601d (const int, const int, const int); + ISO8601d (const int, const int, const int, const int, const int, const int); ~ISO8601d (); - ISO8601d (const ISO8601d&); // Unimplemented - ISO8601d& operator= (const ISO8601d&); // Unimplemented operator time_t () const; - void ambiguity (bool); - bool parse (const std::string&, std::string::size_type&); - void clear (); - void set_default_time (int, int, int); + bool parse (const std::string&, std::string::size_type&, const std::string& format = ""); + + time_t toEpoch () const; + std::string toEpochString () const; + std::string toISO () const; + double toJulian () const; + void toMDY (int&, int&, int&) const; + const std::string toString (const std::string& format = "m/d/Y") const; + + ISO8601d startOfDay () const; + ISO8601d startOfWeek () const; + ISO8601d startOfMonth () const; + ISO8601d startOfYear () const; + + static bool valid (const std::string&, const std::string& format = ""); + static bool valid (const int, const int, const int, const int, const int, const int); + static bool valid (const int, const int, const int); + static bool valid (const int, const int); + static bool leapYear (int); + static int daysInMonth (int, int); + static int daysInYear (int); + static std::string monthName (int); + static void dayName (int, std::string&); + static std::string dayName (int); + static int dayOfWeek (const std::string&); + static int dayOfWeek (int, int, int); + static int monthOfYear (const std::string&); + static int length (const std::string&); + + int month () const; + int week () const; + int day () const; + int year () const; + int weekOfYear (int) const; + int dayOfWeek () const; + int dayOfYear () const; + int hour () const; + int minute () const; + int second () const; + + bool operator== (const ISO8601d&) const; + bool operator!= (const ISO8601d&) const; + bool operator< (const ISO8601d&) const; + bool operator> (const ISO8601d&) const; + bool operator<= (const ISO8601d&) const; + bool operator>= (const ISO8601d&) const; + bool sameHour (const ISO8601d&) const; + bool sameDay (const ISO8601d&) const; + bool sameWeek (const ISO8601d&) const; + bool sameMonth (const ISO8601d&) const; + bool sameYear (const ISO8601d&) const; + ISO8601d operator+ (time_t); + ISO8601d operator+ (const int); + ISO8601d operator- (const int); + ISO8601d& operator+= (const int); + ISO8601d& operator-= (const int); + time_t operator- (const ISO8601d&); + void operator-- (); // Prefix + void operator-- (int); // Postfix + void operator++ (); // Prefix + void operator++ (int); // Postfix private: - bool parse_date_time_ext (Nibbler&); + void clear (); + bool parse_formatted (Nibbler&, const std::string&); + bool parse_named (Nibbler&); + bool parse_epoch (Nibbler&); bool parse_date_time (Nibbler&); + bool parse_date_time_ext (Nibbler&); bool parse_date_ext (Nibbler&); - bool parse_date (Nibbler&, bool); bool parse_off_ext (Nibbler&); - bool parse_off (Nibbler&); bool parse_time_ext (Nibbler&); - bool parse_time (Nibbler&, bool); bool parse_time_utc_ext (Nibbler&); - bool parse_time_utc (Nibbler&); bool parse_time_off_ext (Nibbler&); - bool parse_time_off (Nibbler&); - int dayOfWeek (int, int, int); bool validate (); void resolve (); + std::string dump () const; public: - bool _ambiguity; int _year; int _month; int _week; @@ -71,27 +133,35 @@ int _seconds; int _offset; bool _utc; - time_t _value; - - int _default_seconds; + time_t _date; }; // Period class ISO8601p { public: + static bool isoEnabled; + ISO8601p (); + ISO8601p (time_t); + ISO8601p (const std::string&); ~ISO8601p (); - ISO8601p (const ISO8601p&); // Unimplemented - ISO8601p& operator= (const ISO8601p&); // Unimplemented + ISO8601p (const ISO8601p&); // Unimplemented + ISO8601p& operator= (const ISO8601p&); + bool operator< (const ISO8601p&); + bool operator> (const ISO8601p&); + operator std::string () const; operator time_t () const; bool parse (const std::string&, std::string::size_type&); - void clear (); + const std::string format () const; + const std::string formatVague () const; private: + void clear (); bool parse_designated (Nibbler&); bool validate (); void resolve (); + std::string dump () const; public: int _year; @@ -100,11 +170,9 @@ int _hours; int _minutes; int _seconds; - time_t _value; + time_t _period; }; -// TODO Recurrence - #endif //////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/JSON.cpp task-2.5.0+dfsg/src/JSON.cpp --- task-2.4.4+dfsg/src/JSON.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/JSON.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -51,7 +51,7 @@ } //////////////////////////////////////////////////////////////////////////////// -std::string json::value::dump () +std::string json::value::dump () const { return ""; } @@ -83,7 +83,7 @@ } //////////////////////////////////////////////////////////////////////////////// -std::string json::string::dump () +std::string json::string::dump () const { return std::string ("\"") + _data + "\""; } @@ -109,7 +109,7 @@ } //////////////////////////////////////////////////////////////////////////////// -std::string json::number::dump () +std::string json::number::dump () const { return format (_dvalue); } @@ -152,7 +152,7 @@ } //////////////////////////////////////////////////////////////////////////////// -std::string json::literal::dump () +std::string json::literal::dump () const { if (_lvalue == nullvalue) return "null"; else if (_lvalue == falsevalue) return "false"; @@ -162,9 +162,8 @@ //////////////////////////////////////////////////////////////////////////////// json::array::~array () { - std::vector ::iterator i; - for (i = _data.begin (); i != _data.end (); ++i) - delete *i; + for (auto& i : _data) + delete i; } //////////////////////////////////////////////////////////////////////////////// @@ -222,15 +221,12 @@ } //////////////////////////////////////////////////////////////////////////////// -std::string json::array::dump () +std::string json::array::dump () const { std::string output; output += "["; - std::vector ::iterator i; - for (i = _data.begin (); - i != _data.end (); - ++i) + for (auto i = _data.begin (); i != _data.end (); ++i) { if (i != _data.begin ()) output += ","; @@ -245,9 +241,8 @@ //////////////////////////////////////////////////////////////////////////////// json::object::~object () { - std::map ::iterator i; - for (i = _data.begin (); i != _data.end (); ++i) - delete i->second; + for (auto& i : _data) + delete i.second; } //////////////////////////////////////////////////////////////////////////////// @@ -336,13 +331,12 @@ } //////////////////////////////////////////////////////////////////////////////// -std::string json::object::dump () +std::string json::object::dump () const { std::string output; output += "{"; - std::map ::iterator i; - for (i = _data.begin (); i != _data.end (); ++i) + for (auto i = _data.begin (); i != _data.end (); ++i) { if (i != _data.begin ()) output += ","; @@ -384,9 +378,9 @@ { std::string output; - for (std::string::size_type i = 0; i < input.length (); ++i) + for (auto& i : input) { - switch (input[i]) + switch (i) { // Simple translations. case '"': output += "\\\""; break; @@ -399,7 +393,7 @@ case '\t': output += "\\t"; break; // Default NOP. - default: output += input[i]; break; + default: output += i; break; } } diff -Nru task-2.4.4+dfsg/src/JSON.h task-2.5.0+dfsg/src/JSON.h --- task-2.4.4+dfsg/src/JSON.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/JSON.h 2015-10-21 21:18:15.000000000 +0000 @@ -51,7 +51,7 @@ virtual ~value () {} static value* parse (Nibbler&); virtual jtype type (); - virtual std::string dump (); + virtual std::string dump () const; }; class string : public value @@ -62,7 +62,7 @@ ~string () {} static string* parse (Nibbler&); jtype type (); - std::string dump (); + std::string dump () const; public: std::string _data; @@ -75,7 +75,7 @@ ~number () {} static number* parse (Nibbler&); jtype type (); - std::string dump (); + std::string dump () const; operator double () const; public: @@ -89,7 +89,7 @@ ~literal () {} static literal* parse (Nibbler&); jtype type (); - std::string dump (); + std::string dump () const; public: enum literal_value {none, nullvalue, falsevalue, truevalue}; @@ -103,7 +103,7 @@ ~array (); static array* parse (Nibbler&); jtype type (); - std::string dump (); + std::string dump () const; public: std::vector _data; @@ -117,7 +117,7 @@ static object* parse (Nibbler&); static bool parse_pair (Nibbler&, std::string&, value*&); jtype type (); - std::string dump (); + std::string dump () const; public: std::map _data; @@ -131,8 +131,5 @@ std::string decode (const std::string&); } -typedef std::vector ::iterator json_array_iter; -typedef std::map ::iterator json_object_iter; - #endif //////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/l10n/deu-DEU.h task-2.5.0+dfsg/src/l10n/deu-DEU.h --- task-2.4.4+dfsg/src/l10n/deu-DEU.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/l10n/deu-DEU.h 2015-10-21 21:18:15.000000000 +0000 @@ -105,9 +105,9 @@ #define STRING_PARSER_ALIAS_NEST "Maximale Alias-Schachteltiefe von {1} erreicht." #define STRING_PARSER_OVERRIDE_RC "Konfigurations außer Kraft gesetzt durch: rc.{1}:{2}" #define STRING_PARSER_UNKNOWN_ATTMOD "Fehler: Nicht erkannter Attribut-Operator '{1}'." -#define STRING_PARSER_UUID_AFTER_COMMA "UUID nach Komma nicht erkannt." #define STRING_PARSER_ALTERNATE_RC "Verwende alternative .taskrc-Datei {1}" #define STRING_PARSER_ALTERNATE_DATA "Verwende alternative data.location {1}" +#define STRING_PARSER_UNEXPECTED_ARG "The '{1}' command does not allow '{2}'." // Variant // @@ -115,22 +115,16 @@ // mostly concerned with how various operators interact with the different // data types. #define STRING_VARIANT_TIME_T "Dieser Typ kann nicht mit einem time_t-Wert initialisiert werden." -#define STRING_VARIANT_CMP_UNKNOWN "Unbekannter Typ kann nicht verglichen werden" -#define STRING_VARIANT_EQ_UNKNOWN "Unbekannter Typ kann nicht verglichen werden" -#define STRING_VARIANT_EXP_UNKNOWN "Unbekannter Typ kann nicht potenziert werden" #define STRING_VARIANT_EXP_BOOL "Boolesche Werte können nicht potenziert werden" #define STRING_VARIANT_EXP_NON_INT "Potenzieren ist nur mit Ganzzahlen möglich" #define STRING_VARIANT_EXP_STRING "Zeichenketten können nicht potenziert werden" #define STRING_VARIANT_EXP_DATE "Datumsangaben können nicht potenziert werden" #define STRING_VARIANT_EXP_DURATION "Zeitspannen können nicht potenziert werden" -#define STRING_VARIANT_SUB_UNKNOWN "Unbekannter Typ kann nicht abgezogen werden" #define STRING_VARIANT_SUB_BOOL "Kann nicht von booleschem Wert abziehen" #define STRING_VARIANT_SUB_STRING "Zeichenketten können nicht abgezogen werden" #define STRING_VARIANT_SUB_DATE "Datumsangaben können nicht abgezogen werden" -#define STRING_VARIANT_ADD_UNKNOWN "Unbekannter Typ kann nicht addiert werden" #define STRING_VARIANT_ADD_BOOL "Boolesche Werte können nicht addiert werden" #define STRING_VARIANT_ADD_DATE "Datumsangaben können nicht addiert werden" -#define STRING_VARIANT_MUL_UNKNOWN "Unbekannter Typ kann nicht multipliziert werden" #define STRING_VARIANT_MUL_BOOL "Boolesche Werte können nicht multipliziert werden" #define STRING_VARIANT_MUL_DATE "Datumsangaben können nicht multipliziert werden" #define STRING_VARIANT_MUL_REAL_STR "Reelle Zahlen können nicht mit Zeichenketten multipliziert werden" @@ -141,7 +135,6 @@ #define STRING_VARIANT_MUL_DUR_STR "Zeitangaben können nicht mit Zeichenketten multipliziert werden" #define STRING_VARIANT_MUL_DUR_DATE "Zeitangaben können nicht mit Datumsangaben multipliziert werden" #define STRING_VARIANT_MUL_DUR_DUR "Zeitangaben können nicht mit Zeitangaben multipliziert werden" -#define STRING_VARIANT_DIV_UNKNOWN "Unbekannte Typen können nicht geteilt werden" #define STRING_VARIANT_DIV_BOOL "Boolesche Werte können nicht geteilt werden" #define STRING_VARIANT_DIV_INT_BOOL "Ganzzahlen können nicht durch boolesche Werte geteilt werden" #define STRING_VARIANT_DIV_ZERO "Kann nicht durch null teilen" @@ -166,11 +159,8 @@ #define STRING_VARIANT_MOD_REAL_DATE "Divisionsrest von reellen Zahlen durch Datumsangaben kann nicht berechnet werden" #define STRING_VARIANT_MOD_REAL_STR "Divisionsrest von reellen Zahlen durch Zeichenketten kann nicht berechnet werden" #define STRING_VARIANT_MOD_STR "Divisionsrest von Zeichenketten kan nicht berechnet werden" -#define STRING_VARIANT_MOD_UNKNOWN "Divisionsrest von unbekannten Typen kann nicht berechnet werden" #define STRING_VARIANT_MOD_ZERO "Divisionsrest von null kann nicht berechnet werden" -#define STRING_VARIANT_RENDER_UNK "Unbekannter Typ kann nicht dargestellt werden." #define STRING_VARIANT_SQRT_NEG "Quadratwurzel einer negativen Zahl kann nicht berechnet werden." -#define STRING_VARIANT_COERCE_UNK "Kann nicht in oder von einem unbekannten Typ konvertieren" // Dates // @@ -240,6 +230,16 @@ #define STRING_COLUMN_LABEL_UDACOUNT "Nutzungshäufigkeit" #define STRING_COLUMN_LABEL_ORPHAN "Verwaiste UDA" +#define STRING_COLUMN_LABEL_COMMAND "Command" +#define STRING_COLUMN_LABEL_CATEGORY "Category" +#define STRING_COLUMN_LABEL_RO "R/W" +#define STRING_COLUMN_LABEL_SHOWS_ID "ID" +#define STRING_COLUMN_LABEL_GC "GC" +#define STRING_COLUMN_LABEL_CONTEXT "Context" +#define STRING_COLUMN_LABEL_FILTER "Filter" +#define STRING_COLUMN_LABEL_MODS "Mods" +#define STRING_COLUMN_LABEL_MISC "Misc" + // Column Examples #define STRING_COLUMN_EXAMPLES_TAGS "Haus @Hausarbeit next" #define STRING_COLUMN_EXAMPLES_PROJ "Haus.Garten" @@ -271,7 +271,10 @@ #define STRING_CMD_LOG_USAGE "Protokolliert eine Aufgabe" #define STRING_CMD_LOG_NO_RECUR "Wiederholende Aufgaben können nicht protokolliert werden." #define STRING_CMD_LOG_NO_WAITING "Aufgeschobene Aufgaben können nicht protokolliert werden." -#define STRING_CMD_LOG_LOGGED "Aufgabe protokolliert." + +//#define STRING_CMD_LOG_LOGGED "Aufgabe protokolliert." +#define STRING_CMD_LOG_LOGGED "Logged task {1}." + #define STRING_CMD_IDS_USAGE_RANGE "Zeigt die IDs passender Aufgaben als Folge" #define STRING_CMD_IDS_USAGE_LIST "Zeigt die IDs passender Aufgaben als Liste" #define STRING_CMD_IDS_USAGE_ZSH "Zeigt die IDs und Beschreibungen passender Aufgaben" @@ -289,7 +292,6 @@ #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" #define STRING_CMD_STATS_CATEGORY "Kategorie" #define STRING_CMD_STATS_DATA "Daten" @@ -310,7 +312,6 @@ #define STRING_CMD_STATS_AVG_PEND "Durchschnittliche Zeit im Offen-Status" #define STRING_CMD_STATS_DESC_LEN "Durchschnittliche Beschreibungslänge" #define STRING_CMD_STATS_CHARS "{1} Zeichen" -#define STRING_CMD_STATS_LAST_SYNC "Letzte Server-Synchronisation" #define STRING_CMD_STATS_BLOCKED "Blockierte Aufgaben" #define STRING_CMD_STATS_BLOCKING "Blockierende Aufgaben" #define STRING_CMD_REPORTS_USAGE "Zeigt alle unterstützten Reports" @@ -338,6 +339,9 @@ #define STRING_CMD_GHISTORY_YEAR "Jahr" #define STRING_CMD_GHISTORY_MONTH "Monat" #define STRING_CMD_GHISTORY_NUMBER "Anzahl Hinzugefügt/Erledigt/Gelöscht" +#define STRING_CMD_UNIQUE_USAGE "Generates lists of unique attribute values" +#define STRING_CMD_UNIQUE_MISSING "An attribute must be specified. See 'task _columns'." +#define STRING_CMD_UNIQUE_VALID "You must specify an attribute or UDA." #define STRING_CMD_DONE_USAGE "Kennzeichnet die gewählte Aufgabe als erledigt" #define STRING_CMD_DONE_CONFIRM "Aufgabe {1} '{2}' als erledigt kennzeichnen?" @@ -364,6 +368,7 @@ #define STRING_CMD_COUNT_USAGE "Zählt gewählte Aufgaben" #define STRING_CMD_GET_USAGE "DOM-Accessor" #define STRING_CMD_GET_NO_DOM "Keine DOM-Referenz spezifiziert." +#define STRING_CMD_GET_BAD_REF "'{1}' is not a DOM reference." #define STRING_CMD_UDAS_NO "Keine UDAs festgelegt." #define STRING_CMD_UDAS_SUMMARY "{1} UDA festgelegt" @@ -449,9 +454,9 @@ #define STRING_CMD_IMPORT_USAGE "Importiert eine JSON-Datei" #define STRING_CMD_IMPORT_SUMMARY "{1} Aufgabe importiert." -#define STRING_CMD_IMPORT_NOFILE "Sie müssen eine zu importierende Datei angeben." #define STRING_CMD_IMPORT_FILE "Importiere '{1}'" #define STRING_CMD_IMPORT_MISSING "Datei '{1}' nicht gefunden." +#define STRING_CMD_IMPORT_UUID_BAD "Not a valid UUID '{1}'." #define STRING_TASK_NO_DESC "Kommentar fehlt Beschreibung: {1}" #define STRING_TASK_NO_ENTRY "Kommentar fehlt Erfassungsdatum: {1}" #define STRING_CMD_SYNC_USAGE "Gleicht Daten mit dem Task-Server ab" @@ -511,11 +516,11 @@ #define STRING_CMD_DIAG_HOOK_ENABLE "Enabled" #define STRING_CMD_DIAG_HOOK_DISABLE "Disabled" +#define STRING_CMD_COMMANDS_USAGE "Generates a list of all commands, with behavior details" #define STRING_CMD_HCOMMANDS_USAGE "Erzeugt eine Liste aller Befehle zur Auto-Vervollständigung" #define STRING_CMD_ZSHCOMMANDS_USAGE "Erzeugt eine Liste aller Befehle zur ZSH-Auto-Verfollständigung" #define STRING_CMD_ZSHATTS_USAGE "Erzeugt eine Liste Eigenschaften zur ZSH-Auto-Vervollständigung" #define STRING_CMD_ALIASES_USAGE "Erzeugt eine Liste aller Aliase zur Auto-Vervollständigung" -#define STRING_CMD_INSTALL_USAGE "Installiert Erweiterungen und externe Skripte" #define STRING_CMD_MODIFY_USAGE1 "Ändert eine bestehende Aufgabe mit den übergebenen Parametern" #define STRING_CMD_MODIFY_NO_DUE "Wiederholende Aufgaben können nicht ohne Fälligkeitsdatum angelegt werden." @@ -554,7 +559,7 @@ #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_SUCC "Context '{1}' defined. Use 'task context {1}' to activate." #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." @@ -585,6 +590,7 @@ #define STRING_CMD_BURN_USAGE_D "Zeigt ein Burn-Down-Diagramm, per Tag" #define STRING_CMD_BURN_TITLE "Burn-Down" #define STRING_CMD_BURN_TOO_SMALL "Terminal-Fenster zu klein um Graph zu zeichnen" +#define STRING_CMD_BURN_TOO_LARGE "Terminal window too large to draw a graph." #define STRING_CMD_BURN_DAILY "Tägliches" #define STRING_CMD_BURN_WEEKLY "Wöchentliches" #define STRING_CMD_BURN_MONTHLY "Monatliches" @@ -624,47 +630,26 @@ #define STRING_DATE_INVALID_FORMAT "'{1}' ist kein gültiges Datum im '{2}'-Format." #define STRING_DATE_BAD_WEEKSTART "Die 'weekstart'-Konfigurationsoption darf nur 'Sunday' oder 'Monday' lauten." -#define STRING_DATE_JANUARY_LONG "Januar" -#define STRING_DATE_FEBRUARY_LONG "Februar" -#define STRING_DATE_MARCH_LONG "März" -#define STRING_DATE_APRIL_LONG "April" -#define STRING_DATE_MAY_LONG "Mai" -#define STRING_DATE_JUNE_LONG "Juni" -#define STRING_DATE_JULY_LONG "Juli" -#define STRING_DATE_AUGUST_LONG "August" -#define STRING_DATE_SEPTEMBER_LONG "September" -#define STRING_DATE_OCTOBER_LONG "Oktober" -#define STRING_DATE_NOVEMBER_LONG "November" -#define STRING_DATE_DECEMBER_LONG "Dezember" - -#define STRING_DATE_JANUARY_SHORT "Jan" -#define STRING_DATE_FEBRUARY_SHORT "Feb" -#define STRING_DATE_MARCH_SHORT "Mär" -#define STRING_DATE_APRIL_SHORT "Apr" -#define STRING_DATE_MAY_SHORT "Mai" -#define STRING_DATE_JUNE_SHORT "Jun" -#define STRING_DATE_JULY_SHORT "Jul" -#define STRING_DATE_AUGUST_SHORT "Aug" -#define STRING_DATE_SEPTEMBER_SHORT "Sep" -#define STRING_DATE_OCTOBER_SHORT "Okt" -#define STRING_DATE_NOVEMBER_SHORT "Nov" -#define STRING_DATE_DECEMBER_SHORT "Dez" - -#define STRING_DATE_SUNDAY_LONG "Sonntag" -#define STRING_DATE_MONDAY_LONG "Montag" -#define STRING_DATE_TUESDAY_LONG "Dienstag" -#define STRING_DATE_WEDNESDAY_LONG "Mittwoch" -#define STRING_DATE_THURSDAY_LONG "Donnerstag" -#define STRING_DATE_FRIDAY_LONG "Freitag" -#define STRING_DATE_SATURDAY_LONG "Samstag" - -#define STRING_DATE_SUNDAY_SHORT "So" -#define STRING_DATE_MONDAY_SHORT "Mo" -#define STRING_DATE_TUESDAY_SHORT "Di" -#define STRING_DATE_WEDNESDAY_SHORT "Mi" -#define STRING_DATE_THURSDAY_SHORT "Do" -#define STRING_DATE_FRIDAY_SHORT "Fr" -#define STRING_DATE_SATURDAY_SHORT "Sa" +#define STRING_DATE_JANUARY "Januar" +#define STRING_DATE_FEBRUARY "Februar" +#define STRING_DATE_MARCH "März" +#define STRING_DATE_APRIL "April" +#define STRING_DATE_MAY "Mai" +#define STRING_DATE_JUNE "Juni" +#define STRING_DATE_JULY "Juli" +#define STRING_DATE_AUGUST "August" +#define STRING_DATE_SEPTEMBER "September" +#define STRING_DATE_OCTOBER "Oktober" +#define STRING_DATE_NOVEMBER "November" +#define STRING_DATE_DECEMBER "Dezember" + +#define STRING_DATE_SUNDAY "Sonntag" +#define STRING_DATE_MONDAY "Montag" +#define STRING_DATE_TUESDAY "Dienstag" +#define STRING_DATE_WEDNESDAY "Mittwoch" +#define STRING_DATE_THURSDAY "Donnerstag" +#define STRING_DATE_FRIDAY "Freitag" +#define STRING_DATE_SATURDAY "Samstag" // dependency #define STRING_DEPEND_BLOCKED "Aufgabe {1} wird blockiert durch:" @@ -674,7 +659,6 @@ // DOM #define STRING_DOM_UNKNOWN "" #define STRING_DOM_UNREC "DOM: Unbekannten Namen nicht erkannt '{1}'." -#define STRING_DOM_CANNOT_SET "DOM: Kann '{1}' nicht setzen." // Eval #define STRING_EVAL_NO_EXPRESSION "Kein Ausdruck auszuwerten." @@ -685,8 +669,9 @@ // edit #define STRING_EDIT_NO_CHANGES "Keine Änderungen entdeckt." -#define STRING_EDIT_NO_EDITS "Keine Änderungen ausgeführt." +#define STRING_EDIT_FAILED "Editing failed with exit code {1}." #define STRING_EDIT_COMPLETE "Bearbeitung abgeschlossen." +#define STRING_EDIT_IN_PROGRESS "Task is already being edited." #define STRING_EDIT_LAUNCHING "Starte jetzt '{1}'..." #define STRING_EDIT_CHANGES "Änderungen entdeckt." #define STRING_EDIT_UNPARSEABLE "Taskwarrior konnte Ihre Änderungen nicht verarbeiten. Möchten Sie es erneut probieren?" @@ -765,6 +750,9 @@ #define STRING_INVALID_SORT_COL "Nach Spalte '{1}' kann nicht sortiert weden." #define STRING_TLS_INIT_FAIL "Fehler bei der TLS-Initialisierung. {1}" #define STRING_ERROR_DETAILS "Die Option 'calendar.details.report' muss einen einzelnen Report-Namen enthalten." +#define STRING_ERROR_NO_FILTER "Command line filters are not supported by this command." +#define STRING_ERROR_CONFIRM_SIGINT "Interrupted: No changes made." +#define STRING_ERROR_BAD_STATUS "The status '{1}' is not valid." // Feedback #define STRING_FEEDBACK_NO_TASKS "Keine Aufgaben." @@ -793,6 +781,7 @@ #define STRING_FEEDBACK_TAG_NONAG "Das besondere Schlagwort 'nonag' verhindert Nachfragen, wenn diese Aufgabe geändert wird." #define STRING_FEEDBACK_TAG_NOCAL "Das besondere Schlagwort 'nocal' verhindert, dass diese Aufgabe im 'calendar'-Report erscheint." #define STRING_FEEDBACK_TAG_NEXT "Das besondere Schlagwort 'next' erhöht die Dringlichkeit dieser Aufgabe, sodass sie im 'next'-Report erscheint." +#define STRING_FEEDBACK_TAG_VIRTUAL "Virtual tags (including '{1}') are reserved and may not be added or removed." #define STRING_FEEDBACK_UNBLOCKED "Aufgabe {1} '{2}' entsperrt." #define STRING_FEEDBACK_EXPIRED "Aufgabe {1} '{2}' ist abgelaufen und wurde gelöscht." #define STRING_FEEDBACK_BACKLOG "Lokale Änderungen. Datenabgleich erforderlich." @@ -888,6 +877,10 @@ #define STRING_TDB2_UNDO_COMPLETE "Rückgängig machen abgeschlossen." #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}" +#define STRING_TDB2_UNWAIT "Un-waiting task '{1}'" + +// recur.cpp +#define STRING_RECUR_CREATE "Creating recurring task instance '{1}'" // View #define STRING_VIEW_TOO_SMALL "Dieser Report hat eine Mindestbreite von {1} und passt nicht in die Bildschirmbreite von {2}." @@ -946,21 +939,27 @@ " end: Datum, zu welchem die Aufgabe abgeschlossen/gelöscht wurde\n" \ " start: Startdatum der Aufgabe\n" \ " scheduled: Geplantes Datum der Aufgabe\n" \ + " modified: Date task was last modified\n" \ " depends: Andere Aufgaben, von denen die Aufgabe abhängt\n" \ "\n" \ "Eigenschaften-Operatoren präzisieren Filter. Unterstützt werden:\n" \ - " before (Synonyme: under, below)\n" \ - " after (Synonyme: over, above)\n" \ - " none\n" \ - " any\n" \ - " is (Synonym: equals)\n" \ - " isnt (Synonym: not)\n" \ - " has (Synonym: contains)\n" \ - " hasnt\n" \ - " startswith (Synonym: left)\n" \ - " endswith (Synonym: right)\n" \ - " word\n" \ - " noword\n" \ + "\n" \ + " Modifiers Example Equivalent Meaning\n" \ + " ---------------- ----------------- ------------------- -------------------------\n" \ + " due:today due = today Fuzzy match\n" \ + " not due.not:today due != today Fuzzy non-match\n" \ + " before, below due.before:today due < tomorrow Exact date comparison\n" \ + " after, above due.after:today due > tomorrow Exact date comparison\n" \ + " none project.none: project == '' Empty\n" \ + " any project.any: project !== '' Not empty\n" \ + " is, equals project.is:x project == x Exact match\n" \ + " isnt project.isnt:x project !== x Exact non-match\n" \ + " has, contains desc.has:Hello desc ~ Hello Pattern match\n" \ + " hasnt, desc.hasnt:Hello desc !~ Hello Pattern non-match\n" \ + " startswith, left desc.left:Hel desc ~ '^Hel' Beginning match\n" \ + " endswith, right desc.right:llo desc ~ 'llo$' End match\n" \ + " word desc.word:Hello desc ~ '\\bHello\\b' Boundaried word match\n" \ + " noword desc.noword:Hello desc !~ '\\bHello\\b' Boundaried word non-match\n" \ "\n" \ "Alternativ können folgende algebraische Operatoren genutzt werden:\n" \ " and or xor Logische Operatoren\n" \ diff -Nru task-2.4.4+dfsg/src/l10n/eng-USA.h task-2.5.0+dfsg/src/l10n/eng-USA.h --- task-2.4.4+dfsg/src/l10n/eng-USA.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/l10n/eng-USA.h 2015-10-21 21:18:15.000000000 +0000 @@ -105,9 +105,9 @@ #define STRING_PARSER_ALIAS_NEST "Nested alias limit of {1} reached." #define STRING_PARSER_OVERRIDE_RC "Configuration override rc.{1}:{2}" #define STRING_PARSER_UNKNOWN_ATTMOD "Error: unrecognized attribute modifier '{1}'." -#define STRING_PARSER_UUID_AFTER_COMMA "Unrecognized UUID after comma." #define STRING_PARSER_ALTERNATE_RC "Using alternate .taskrc file {1}" #define STRING_PARSER_ALTERNATE_DATA "Using alternate data.location {1}" +#define STRING_PARSER_UNEXPECTED_ARG "The '{1}' command does not allow '{2}'." // Variant // @@ -115,22 +115,16 @@ // mostly concerned with how various operators interact with the different // data types. #define STRING_VARIANT_TIME_T "Cannot instantiate this type with a time_t value." -#define STRING_VARIANT_CMP_UNKNOWN "Cannot compare unknown type" -#define STRING_VARIANT_EQ_UNKNOWN "Cannot equate unknown type" -#define STRING_VARIANT_EXP_UNKNOWN "Cannot exponentiate unknown type" #define STRING_VARIANT_EXP_BOOL "Cannot exponentiate Booleans" #define STRING_VARIANT_EXP_NON_INT "Cannot exponentiate to a non-integer power" #define STRING_VARIANT_EXP_STRING "Cannot exponentiate strings" #define STRING_VARIANT_EXP_DATE "Cannot exponentiate dates" #define STRING_VARIANT_EXP_DURATION "Cannot exponentiate durations" -#define STRING_VARIANT_SUB_UNKNOWN "Cannot subtract unknown type" #define STRING_VARIANT_SUB_BOOL "Cannot subtract from a Boolean value" #define STRING_VARIANT_SUB_STRING "Cannot subtract strings" #define STRING_VARIANT_SUB_DATE "Cannot subtract a date" -#define STRING_VARIANT_ADD_UNKNOWN "Cannot add unknown type" #define STRING_VARIANT_ADD_BOOL "Cannot add two Boolean values" #define STRING_VARIANT_ADD_DATE "Cannot add two date values" -#define STRING_VARIANT_MUL_UNKNOWN "Cannot multiply unknown type" #define STRING_VARIANT_MUL_BOOL "Cannot multiply Boolean values" #define STRING_VARIANT_MUL_DATE "Cannot multiply date values" #define STRING_VARIANT_MUL_REAL_STR "Cannot multiply real numbers by strings" @@ -141,7 +135,6 @@ #define STRING_VARIANT_MUL_DUR_STR "Cannot multiply durations by strings" #define STRING_VARIANT_MUL_DUR_DATE "Cannot multiply durations by dates" #define STRING_VARIANT_MUL_DUR_DUR "Cannot multiply durations by durations" -#define STRING_VARIANT_DIV_UNKNOWN "Cannot divide unknown type" #define STRING_VARIANT_DIV_BOOL "Cannot divide Boolean values" #define STRING_VARIANT_DIV_INT_BOOL "Cannot divide integers by Boolean values" #define STRING_VARIANT_DIV_ZERO "Cannot divide by zero" @@ -166,11 +159,8 @@ #define STRING_VARIANT_MOD_REAL_DATE "Cannot modulo real numbers by dates" #define STRING_VARIANT_MOD_REAL_STR "Cannot modulo real numbers by strings" #define STRING_VARIANT_MOD_STR "Cannot modulo string values" -#define STRING_VARIANT_MOD_UNKNOWN "Cannot modulo unknown type" #define STRING_VARIANT_MOD_ZERO "Cannot modulo zero" -#define STRING_VARIANT_RENDER_UNK "Cannot render an unknown type." #define STRING_VARIANT_SQRT_NEG "Cannot take the square root of a negative number." -#define STRING_VARIANT_COERCE_UNK "Cannot coerce data either to or from an unknown type" // Dates // @@ -240,6 +230,16 @@ #define STRING_COLUMN_LABEL_UDACOUNT "Usage Count" #define STRING_COLUMN_LABEL_ORPHAN "Orphan UDA" +#define STRING_COLUMN_LABEL_COMMAND "Command" +#define STRING_COLUMN_LABEL_CATEGORY "Category" +#define STRING_COLUMN_LABEL_RO "R/W" +#define STRING_COLUMN_LABEL_SHOWS_ID "ID" +#define STRING_COLUMN_LABEL_GC "GC" +#define STRING_COLUMN_LABEL_CONTEXT "Context" +#define STRING_COLUMN_LABEL_FILTER "Filter" +#define STRING_COLUMN_LABEL_MODS "Mods" +#define STRING_COLUMN_LABEL_MISC "Misc" + // Column Examples #define STRING_COLUMN_EXAMPLES_TAGS "home @chore next" #define STRING_COLUMN_EXAMPLES_PROJ "home.garden" @@ -271,7 +271,7 @@ #define STRING_CMD_LOG_USAGE "Adds a new task that is already completed" #define STRING_CMD_LOG_NO_RECUR "You cannot log recurring tasks." #define STRING_CMD_LOG_NO_WAITING "You cannot log waiting tasks." -#define STRING_CMD_LOG_LOGGED "Logged task." +#define STRING_CMD_LOG_LOGGED "Logged task {1}." #define STRING_CMD_IDS_USAGE_RANGE "Shows the IDs of matching tasks, as a range" #define STRING_CMD_IDS_USAGE_LIST "Shows the IDs of matching tasks, in the form of a list" #define STRING_CMD_IDS_USAGE_ZSH "Shows the IDs and descriptions of matching tasks" @@ -289,7 +289,6 @@ #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" #define STRING_CMD_STATS_CATEGORY "Category" #define STRING_CMD_STATS_DATA "Data" @@ -310,7 +309,6 @@ #define STRING_CMD_STATS_AVG_PEND "Average time pending" #define STRING_CMD_STATS_DESC_LEN "Average desc length" #define STRING_CMD_STATS_CHARS "{1} characters" -#define STRING_CMD_STATS_LAST_SYNC "Last server synchronization" #define STRING_CMD_STATS_BLOCKED "Blocked tasks" #define STRING_CMD_STATS_BLOCKING "Blocking tasks" #define STRING_CMD_REPORTS_USAGE "Lists all supported reports" @@ -338,6 +336,9 @@ #define STRING_CMD_GHISTORY_YEAR "Year" #define STRING_CMD_GHISTORY_MONTH "Month" #define STRING_CMD_GHISTORY_NUMBER "Number Added/Completed/Deleted" +#define STRING_CMD_UNIQUE_USAGE "Generates lists of unique attribute values" +#define STRING_CMD_UNIQUE_MISSING "An attribute must be specified. See 'task _columns'." +#define STRING_CMD_UNIQUE_VALID "You must specify an attribute or UDA." #define STRING_CMD_DONE_USAGE "Marks the specified task as completed" #define STRING_CMD_DONE_CONFIRM "Complete task {1} '{2}'?" @@ -364,6 +365,7 @@ #define STRING_CMD_COUNT_USAGE "Counts matching tasks" #define STRING_CMD_GET_USAGE "DOM Accessor" #define STRING_CMD_GET_NO_DOM "No DOM reference specified." +#define STRING_CMD_GET_BAD_REF "'{1}' is not a DOM reference." #define STRING_CMD_UDAS_NO "No UDAs defined." #define STRING_CMD_UDAS_SUMMARY "{1} UDA defined" @@ -372,7 +374,7 @@ #define STRING_CMD_UDAS_ORPHANS "{1} Orphan UDAs" #define STRING_CMD_DELETE_USAGE "Deletes the specified task" -#define STRING_CMD_DELETE_CONFIRM "Permanently delete task {1} '{2}'?" +#define STRING_CMD_DELETE_CONFIRM "Delete task {1} '{2}'?" #define STRING_CMD_DELETE_TASK "Deleting task {1} '{2}'." #define STRING_CMD_DELETE_TASK_R "Deleting recurring task {1} '{2}'." #define STRING_CMD_DELETE_CONFIRM_R "This is a recurring task. Do you want to delete all pending recurrences of this same task?" @@ -381,6 +383,7 @@ #define STRING_CMD_DELETE_1 "Deleted {1} task." #define STRING_CMD_DELETE_N "Deleted {1} tasks." + #define STRING_CMD_DUPLICATE_USAGE "Duplicates the specified tasks" #define STRING_CMD_DUPLICATE_REC "Note: task {1} was a parent recurring task. The duplicated task is too." #define STRING_CMD_DUPLICATE_NON_REC "Note: task {1} was a recurring task. The duplicated task is not." @@ -449,9 +452,9 @@ #define STRING_CMD_IMPORT_USAGE "Imports JSON files" #define STRING_CMD_IMPORT_SUMMARY "Imported {1} tasks." -#define STRING_CMD_IMPORT_NOFILE "You must specify a file to import." #define STRING_CMD_IMPORT_FILE "Importing '{1}'" #define STRING_CMD_IMPORT_MISSING "File '{1}' not found." +#define STRING_CMD_IMPORT_UUID_BAD "Not a valid UUID '{1}'." #define STRING_TASK_NO_DESC "Annotation is missing a description: {1}" #define STRING_TASK_NO_ENTRY "Annotation is missing an entry date: {1}" #define STRING_CMD_SYNC_USAGE "Synchronizes data with the Taskserver" @@ -467,7 +470,7 @@ #define STRING_CMD_SYNC_SUCCESS2 "Sync successful. {1} changes downloaded." #define STRING_CMD_SYNC_SUCCESS3 "Sync successful. {1} changes uploaded, {2} changes downloaded." #define STRING_CMD_SYNC_SUCCESS_NOP "Sync successful. No changes." -#define STRING_CMD_SYNC_FAIL_ACCOUNT "Sync failed. Either your credentials are incorrect, or your Taskserver account is not enabled." +#define STRING_CMD_SYNC_FAIL_ACCOUNT "Sync failed. Either your credentials are incorrect, or your account doesn't exist on the Taskserver." #define STRING_CMD_SYNC_FAIL_ERROR "Sync failed. The Taskserver returned error: {1} {2}" #define STRING_CMD_SYNC_FAIL_CONNECT "Sync failed. Could not connect to the Taskserver." #define STRING_CMD_SYNC_BAD_SERVER "Sync failed. Malformed configuration setting '{1}'" @@ -511,11 +514,11 @@ #define STRING_CMD_DIAG_HOOK_ENABLE "Enabled" #define STRING_CMD_DIAG_HOOK_DISABLE "Disabled" +#define STRING_CMD_COMMANDS_USAGE "Generates a list of all commands, with behavior details" #define STRING_CMD_HCOMMANDS_USAGE "Generates a list of all commands, for autocompletion purposes" #define STRING_CMD_ZSHCOMMANDS_USAGE "Generates a list of all commands, for zsh autocompletion purposes" #define STRING_CMD_ZSHATTS_USAGE "Generates a list of all attributes, for zsh autocompletion purposes" #define STRING_CMD_ALIASES_USAGE "Generates a list of all aliases, for autocompletion purposes" -#define STRING_CMD_INSTALL_USAGE "Installs extensions and external scripts" #define STRING_CMD_MODIFY_USAGE1 "Modifies the existing task with provided arguments." #define STRING_CMD_MODIFY_NO_DUE "You cannot specify a recurring task without a due date." @@ -554,7 +557,7 @@ #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_SUCC "Context '{1}' defined. Use 'task context {1}' to activate." #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 definition aborted." @@ -585,6 +588,7 @@ #define STRING_CMD_BURN_USAGE_D "Shows a graphical burndown chart, by day" #define STRING_CMD_BURN_TITLE "Burndown" #define STRING_CMD_BURN_TOO_SMALL "Terminal window too small to draw a graph." +#define STRING_CMD_BURN_TOO_LARGE "Terminal window too large to draw a graph." #define STRING_CMD_BURN_DAILY "Daily" #define STRING_CMD_BURN_WEEKLY "Weekly" #define STRING_CMD_BURN_MONTHLY "Monthly" @@ -624,47 +628,26 @@ #define STRING_DATE_INVALID_FORMAT "'{1}' is not a valid date in the '{2}' format." #define STRING_DATE_BAD_WEEKSTART "The 'weekstart' configuration variable may only contain 'Sunday' or 'Monday'." -#define STRING_DATE_JANUARY_LONG "january" -#define STRING_DATE_FEBRUARY_LONG "february" -#define STRING_DATE_MARCH_LONG "march" -#define STRING_DATE_APRIL_LONG "april" -#define STRING_DATE_MAY_LONG "may" -#define STRING_DATE_JUNE_LONG "june" -#define STRING_DATE_JULY_LONG "july" -#define STRING_DATE_AUGUST_LONG "august" -#define STRING_DATE_SEPTEMBER_LONG "september" -#define STRING_DATE_OCTOBER_LONG "october" -#define STRING_DATE_NOVEMBER_LONG "november" -#define STRING_DATE_DECEMBER_LONG "december" - -#define STRING_DATE_JANUARY_SHORT "jan" -#define STRING_DATE_FEBRUARY_SHORT "feb" -#define STRING_DATE_MARCH_SHORT "mar" -#define STRING_DATE_APRIL_SHORT "apr" -#define STRING_DATE_MAY_SHORT "may" -#define STRING_DATE_JUNE_SHORT "jun" -#define STRING_DATE_JULY_SHORT "jul" -#define STRING_DATE_AUGUST_SHORT "aug" -#define STRING_DATE_SEPTEMBER_SHORT "sep" -#define STRING_DATE_OCTOBER_SHORT "oct" -#define STRING_DATE_NOVEMBER_SHORT "nov" -#define STRING_DATE_DECEMBER_SHORT "dec" - -#define STRING_DATE_SUNDAY_LONG "sunday" -#define STRING_DATE_MONDAY_LONG "monday" -#define STRING_DATE_TUESDAY_LONG "tuesday" -#define STRING_DATE_WEDNESDAY_LONG "wednesday" -#define STRING_DATE_THURSDAY_LONG "thursday" -#define STRING_DATE_FRIDAY_LONG "friday" -#define STRING_DATE_SATURDAY_LONG "saturday" - -#define STRING_DATE_SUNDAY_SHORT "sun" -#define STRING_DATE_MONDAY_SHORT "mon" -#define STRING_DATE_TUESDAY_SHORT "tue" -#define STRING_DATE_WEDNESDAY_SHORT "wed" -#define STRING_DATE_THURSDAY_SHORT "thu" -#define STRING_DATE_FRIDAY_SHORT "fri" -#define STRING_DATE_SATURDAY_SHORT "sat" +#define STRING_DATE_JANUARY "january" +#define STRING_DATE_FEBRUARY "february" +#define STRING_DATE_MARCH "march" +#define STRING_DATE_APRIL "april" +#define STRING_DATE_MAY "may" +#define STRING_DATE_JUNE "june" +#define STRING_DATE_JULY "july" +#define STRING_DATE_AUGUST "august" +#define STRING_DATE_SEPTEMBER "september" +#define STRING_DATE_OCTOBER "october" +#define STRING_DATE_NOVEMBER "november" +#define STRING_DATE_DECEMBER "december" + +#define STRING_DATE_SUNDAY "sunday" +#define STRING_DATE_MONDAY "monday" +#define STRING_DATE_TUESDAY "tuesday" +#define STRING_DATE_WEDNESDAY "wednesday" +#define STRING_DATE_THURSDAY "thursday" +#define STRING_DATE_FRIDAY "friday" +#define STRING_DATE_SATURDAY "saturday" // dependency #define STRING_DEPEND_BLOCKED "Task {1} is blocked by:" @@ -674,7 +657,6 @@ // DOM #define STRING_DOM_UNKNOWN "" #define STRING_DOM_UNREC "DOM: Cannot get unrecognized name '{1}'." -#define STRING_DOM_CANNOT_SET "DOM: Cannot set '{1}'." // Eval #define STRING_EVAL_NO_EXPRESSION "No expression to evaluate." @@ -685,8 +667,9 @@ // edit #define STRING_EDIT_NO_CHANGES "No edits were detected." -#define STRING_EDIT_NO_EDITS "No editing performed." +#define STRING_EDIT_FAILED "Editing failed with exit code {1}." #define STRING_EDIT_COMPLETE "Editing complete." +#define STRING_EDIT_IN_PROGRESS "Task is already being edited." #define STRING_EDIT_LAUNCHING "Launching '{1}' now..." #define STRING_EDIT_CHANGES "Edits were detected." #define STRING_EDIT_UNPARSEABLE "Taskwarrior couldn't handle your edits. Would you like to try again?" @@ -753,7 +736,7 @@ // Errors // TODO Move each of these to appropriate section. #define STRING_ERROR_PREFIX "Error: " -#define STRING_UNKNOWN_ERROR "Unknown error." +#define STRING_UNKNOWN_ERROR "Unknown error. Please report." #define STRING_TRIVIAL_INPUT "You must specify a command or a task to modify." #define STRING_ASSUME_INFO "No command specified - assuming 'information'." #define STRING_INFINITE_LOOP "Terminated substitution because more than {1} changes were made - infinite loop protection." @@ -765,6 +748,9 @@ #define STRING_INVALID_SORT_COL "The '{1}' column is not a valid sort field." #define STRING_TLS_INIT_FAIL "Error initializing TLS. {1}" #define STRING_ERROR_DETAILS "The setting 'calendar.details.report' must contain a single report name." +#define STRING_ERROR_NO_FILTER "Command line filters are not supported by this command." +#define STRING_ERROR_CONFIRM_SIGINT "Interrupted: No changes made." +#define STRING_ERROR_BAD_STATUS "The status '{1}' is not valid." // Feedback #define STRING_FEEDBACK_NO_TASKS "No tasks." @@ -793,6 +779,7 @@ #define STRING_FEEDBACK_TAG_NONAG "The 'nonag' special tag will prevent nagging when this task is modified." #define STRING_FEEDBACK_TAG_NOCAL "The 'nocal' special tag will keep this task off the 'calendar' report." #define STRING_FEEDBACK_TAG_NEXT "The 'next' special tag will boost the urgency of this task so it appears on the 'next' report." +#define STRING_FEEDBACK_TAG_VIRTUAL "Virtual tags (including '{1}') are reserved and may not be added or removed." #define STRING_FEEDBACK_UNBLOCKED "Unblocked {1} '{2}'." #define STRING_FEEDBACK_EXPIRED "Task {1} '{2}' expired and was deleted." #define STRING_FEEDBACK_BACKLOG "There are local changes. Sync required." @@ -888,6 +875,10 @@ #define STRING_TDB2_UNDO_COMPLETE "Undo complete." #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}" +#define STRING_TDB2_UNWAIT "Un-waiting task '{1}'" + +// recur.cpp +#define STRING_RECUR_CREATE "Creating recurring task instance '{1}'" // View #define STRING_VIEW_TOO_SMALL "The report has a minimum width of {1} and does not fit in the available width of {2}." @@ -895,7 +886,7 @@ // Usage text. This is an exception, and contains \n characters and formatting. #define STRING_CMD_HELP_TEXT \ "Documentation for Taskwarrior can be found using 'man task', 'man taskrc', 'man " \ - "task-color', 'man task-sync or at http://taskwarrior.org\n" \ + "task-color', 'man task-sync' or at http://taskwarrior.org\n" \ "\n" \ "The general form of commands is:\n" \ " task [] []\n" \ @@ -945,21 +936,27 @@ " end: Date task was completed/deleted\n" \ " start: Date task was started\n" \ " scheduled: Date task is scheduled to start\n" \ + " modified: Date task was last modified\n" \ " depends: Other tasks that this task depends upon\n" \ "\n" \ "Attribute modifiers make filters more precise. Supported modifiers are:\n" \ - " before (synonyms under, below)\n" \ - " after (synonyms over, above)\n" \ - " none\n" \ - " any\n" \ - " is (synonym equals)\n" \ - " isnt (synonym not)\n" \ - " has (synonym contains)\n" \ - " hasnt\n" \ - " startswith (synonym left)\n" \ - " endswith (synonym right)\n" \ - " word\n" \ - " noword\n" \ + "\n" \ + " Modifiers Example Equivalent Meaning\n" \ + " ---------------- ----------------- ------------------- -------------------------\n" \ + " due:today due = today Fuzzy match\n" \ + " not due.not:today due != today Fuzzy non-match\n" \ + " before, below due.before:today due < tomorrow Exact date comparison\n" \ + " after, above due.after:today due > tomorrow Exact date comparison\n" \ + " none project.none: project == '' Empty\n" \ + " any project.any: project !== '' Not empty\n" \ + " is, equals project.is:x project == x Exact match\n" \ + " isnt project.isnt:x project !== x Exact non-match\n" \ + " has, contains desc.has:Hello desc ~ Hello Pattern match\n" \ + " hasnt, desc.hasnt:Hello desc !~ Hello Pattern non-match\n" \ + " startswith, left desc.left:Hel desc ~ '^Hel' Beginning match\n" \ + " endswith, right desc.right:llo desc ~ 'llo$' End match\n" \ + " word desc.word:Hello desc ~ '\\bHello\\b' Boundaried word match\n" \ + " noword desc.noword:Hello desc !~ '\\bHello\\b' Boundaried word non-match\n" \ "\n" \ "Alternately algebraic expressions support:\n" \ " and or xor Logical operators\n" \ diff -Nru task-2.4.4+dfsg/src/l10n/epo-RUS.h task-2.5.0+dfsg/src/l10n/epo-RUS.h --- task-2.4.4+dfsg/src/l10n/epo-RUS.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/l10n/epo-RUS.h 2015-10-21 21:18:15.000000000 +0000 @@ -105,9 +105,9 @@ #define STRING_PARSER_ALIAS_NEST "Atingis la limon de {1} nest-niveloj de alinomoj." #define STRING_PARSER_OVERRIDE_RC "Agorda superrego rc.{1}:{2}" #define STRING_PARSER_UNKNOWN_ATTMOD "Eraro: nekonata atributa modifanto '{1}'." -#define STRING_PARSER_UUID_AFTER_COMMA "Nekonata UUID-identigilo post komo." #define STRING_PARSER_ALTERNATE_RC "Uzanta alterna .taskrc-dosiero {1}" #define STRING_PARSER_ALTERNATE_DATA "Uzanta alterna data.location {1}" +#define STRING_PARSER_UNEXPECTED_ARG "The '{1}' command does not allow '{2}'." // Variant // @@ -115,22 +115,16 @@ // mostly concerned with how various operators interact with the different // data types. #define STRING_VARIANT_TIME_T "Ne povas aperaĵigi tiun tipon kun valoro de tipo 'time_t'." -#define STRING_VARIANT_CMP_UNKNOWN "Ne povas kompari nekonatan tipon" -#define STRING_VARIANT_EQ_UNKNOWN "Ne povas egaligi nekonatan tipon" -#define STRING_VARIANT_EXP_UNKNOWN "Ne povas potencigi nekonatan tipon" #define STRING_VARIANT_EXP_BOOL "Ne povas potencigi buleon" #define STRING_VARIANT_EXP_NON_INT "Ne povas potencigi kun malentjera eksponento" #define STRING_VARIANT_EXP_STRING "Ne povas potencigi ĉenon" #define STRING_VARIANT_EXP_DATE "Ne povas potencigi daton" #define STRING_VARIANT_EXP_DURATION "Ne povas potencigi daŭron" -#define STRING_VARIANT_SUB_UNKNOWN "Ne povas subtrahi nekonatan tipon" #define STRING_VARIANT_SUB_BOOL "Ne povas subtrahi el buleo" #define STRING_VARIANT_SUB_STRING "Ne povas subtrahi ĉenon" #define STRING_VARIANT_SUB_DATE "Ne povas subtrahi daton" -#define STRING_VARIANT_ADD_UNKNOWN "Ne povas adicii nekonatan tipon" #define STRING_VARIANT_ADD_BOOL "Ne povas adicii du buleojn" #define STRING_VARIANT_ADD_DATE "Ne povas adicii du datojn" -#define STRING_VARIANT_MUL_UNKNOWN "Ne povas multipliki nekonatan tipon" #define STRING_VARIANT_MUL_BOOL "Ne povas multipliki buleon" #define STRING_VARIANT_MUL_DATE "Ne povas multipliki daton" #define STRING_VARIANT_MUL_REAL_STR "Ne povas multipliki reelon per ĉeno" @@ -141,7 +135,6 @@ #define STRING_VARIANT_MUL_DUR_STR "Ne povas multipliki daŭron per ĉeno" #define STRING_VARIANT_MUL_DUR_DATE "Ne povas multipliki daŭron per dato" #define STRING_VARIANT_MUL_DUR_DUR "Ne povas multipliki daŭron per daŭro" -#define STRING_VARIANT_DIV_UNKNOWN "Ne povas dividi nekonatan tipon" #define STRING_VARIANT_DIV_BOOL "Ne povas dividi buleon" #define STRING_VARIANT_DIV_INT_BOOL "Ne povas dividi entjeron per buleo" #define STRING_VARIANT_DIV_ZERO "Ne povas dividi per nulo" @@ -166,11 +159,8 @@ #define STRING_VARIANT_MOD_REAL_DATE "Ne povas moduli reelon per dato" #define STRING_VARIANT_MOD_REAL_STR "Ne povas moduli reelon per ĉeno" #define STRING_VARIANT_MOD_STR "Ne povas moduli ĉenon" -#define STRING_VARIANT_MOD_UNKNOWN "Ne povas moduli nekonatan tipon" #define STRING_VARIANT_MOD_ZERO "Ne povas moduli nulon" -#define STRING_VARIANT_RENDER_UNK "Ne povas bildigi nekonatan tipon." #define STRING_VARIANT_SQRT_NEG "Ne povas kalkuli kvadratan radikon de negativa nombro." -#define STRING_VARIANT_COERCE_UNK "Ne povas konverta datumon ni el ni al nekonata tipo" // Dates // @@ -240,6 +230,16 @@ #define STRING_COLUMN_LABEL_UDACOUNT "Nombro de uzoj" #define STRING_COLUMN_LABEL_ORPHAN "Orfa UDA" +#define STRING_COLUMN_LABEL_COMMAND "Command" +#define STRING_COLUMN_LABEL_CATEGORY "Category" +#define STRING_COLUMN_LABEL_RO "R/W" +#define STRING_COLUMN_LABEL_SHOWS_ID "ID" +#define STRING_COLUMN_LABEL_GC "GC" +#define STRING_COLUMN_LABEL_CONTEXT "Context" +#define STRING_COLUMN_LABEL_FILTER "Filter" +#define STRING_COLUMN_LABEL_MODS "Mods" +#define STRING_COLUMN_LABEL_MISC "Misc" + // Column Examples #define STRING_COLUMN_EXAMPLES_TAGS "domo @aĉo next" #define STRING_COLUMN_EXAMPLES_PROJ "domo.ĝardeno" @@ -271,7 +271,10 @@ #define STRING_CMD_LOG_USAGE "Kreas novan jamfinitan taskon" #define STRING_CMD_LOG_NO_RECUR "Oni ne povas fari taskojn reokazantajn kun 'log'." #define STRING_CMD_LOG_NO_WAITING "Oni ne povas fari taskojn atendantajn kun 'log'." -#define STRING_CMD_LOG_LOGGED "Registris taskon." + +//#define STRING_CMD_LOG_LOGGED "Registris taskon." +#define STRING_CMD_LOG_LOGGED "Logged task {1}." + #define STRING_CMD_IDS_USAGE_RANGE "Montras la identigilon de ĉia kongruanta tasko, kiel atingopovo" #define STRING_CMD_IDS_USAGE_LIST "Montras la identigilon de ĉia kongruanta tasko, kiel listo" #define STRING_CMD_IDS_USAGE_ZSH "Montras la identigilon kaj la priskribon de ĉia kongruanta tasko" @@ -289,7 +292,6 @@ #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" #define STRING_CMD_STATS_CATEGORY "Kategorio" #define STRING_CMD_STATS_DATA "datumoj" @@ -310,7 +312,6 @@ #define STRING_CMD_STATS_AVG_PEND "Meznª pendtempo" #define STRING_CMD_STATS_DESC_LEN "Meznª priskriblongeco" #define STRING_CMD_STATS_CHARS "{1} signojn" -#define STRING_CMD_STATS_LAST_SYNC "Lasta sinkronigado" #define STRING_CMD_STATS_BLOCKED "Taskoj blokataj" #define STRING_CMD_STATS_BLOCKING "Taskoj blokantaj" #define STRING_CMD_REPORTS_USAGE "Listigas ĉian raporton subtenatan" @@ -338,6 +339,9 @@ #define STRING_CMD_GHISTORY_YEAR "Jaro" #define STRING_CMD_GHISTORY_MONTH "Monato" #define STRING_CMD_GHISTORY_NUMBER "Nombro Kreitaj/Finitaj/Viŝitaj" +#define STRING_CMD_UNIQUE_USAGE "Generates lists of unique attribute values" +#define STRING_CMD_UNIQUE_MISSING "An attribute must be specified. See 'task _columns'." +#define STRING_CMD_UNIQUE_VALID "You must specify an attribute or UDA." #define STRING_CMD_DONE_USAGE "Markas la specifatan taskon kiel finita" #define STRING_CMD_DONE_CONFIRM "Fini taskon {1} '{2}'?" @@ -364,6 +368,7 @@ #define STRING_CMD_COUNT_USAGE "Nombras kongruantajn taskojn" #define STRING_CMD_GET_USAGE "DOM-enirilo" #define STRING_CMD_GET_NO_DOM "Nenia DOM-referenco specifata." +#define STRING_CMD_GET_BAD_REF "'{1}' is not a DOM reference." #define STRING_CMD_UDAS_NO "Nenia UDA definita." #define STRING_CMD_UDAS_SUMMARY "{1} UDA definita" @@ -449,9 +454,9 @@ #define STRING_CMD_IMPORT_USAGE "Importas JSON-dosierojn" #define STRING_CMD_IMPORT_SUMMARY "Importis {1} taskojn." -#define STRING_CMD_IMPORT_NOFILE "Vi devas specifi kiu dosieron import." #define STRING_CMD_IMPORT_FILE "Importanta '{1}'" #define STRING_CMD_IMPORT_MISSING "File '{1}' not found." +#define STRING_CMD_IMPORT_UUID_BAD "Not a valid UUID '{1}'." #define STRING_TASK_NO_DESC "Komento havas mankon de priskribo: {1}" #define STRING_TASK_NO_ENTRY "Komento havas mankon de enskrib-dato: {1}" #define STRING_CMD_SYNC_USAGE "Sinkronigas datumojn kun la Taskserver" @@ -511,11 +516,11 @@ #define STRING_CMD_DIAG_HOOK_ENABLE "Enabled" #define STRING_CMD_DIAG_HOOK_DISABLE "Disabled" +#define STRING_CMD_COMMANDS_USAGE "Generates a list of all commands, with behavior details" #define STRING_CMD_HCOMMANDS_USAGE "Generates a list of all commands, for autocompletion purposes" #define STRING_CMD_ZSHCOMMANDS_USAGE "Generates a list of all commands, for zsh autocompletion purposes" #define STRING_CMD_ZSHATTS_USAGE "Generates a list of all attributes, for zsh autocompletion purposes" #define STRING_CMD_ALIASES_USAGE "Generates a list of all aliases, for autocompletion purposes" -#define STRING_CMD_INSTALL_USAGE "Installs extensions and external scripts" #define STRING_CMD_MODIFY_USAGE1 "Modifies the existing task with provided arguments." #define STRING_CMD_MODIFY_NO_DUE "You cannot specify a recurring task without a due date." @@ -554,7 +559,7 @@ #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_SUCC "Context '{1}' defined. Use 'task context {1}' to activate." #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." @@ -585,6 +590,7 @@ #define STRING_CMD_BURN_USAGE_D "Montras ĉiutagan abakon de taskbrulo" #define STRING_CMD_BURN_TITLE "Brulo" #define STRING_CMD_BURN_TOO_SMALL "Terminala fenestro tro malgranda por vidigi grafeon." +#define STRING_CMD_BURN_TOO_LARGE "Terminal window too large to draw a graph." #define STRING_CMD_BURN_DAILY "Ĉiutaga" #define STRING_CMD_BURN_WEEKLY "Ĉiusemajna" #define STRING_CMD_BURN_MONTHLY "Ĉiumonata" @@ -624,47 +630,26 @@ #define STRING_DATE_INVALID_FORMAT "'{1}' ne estas valida dato laŭ stilo '{2}'." #define STRING_DATE_BAD_WEEKSTART "Argorda variablo 'weekstart' devas esti 'Sunday' aŭ 'Monday'." -#define STRING_DATE_JANUARY_LONG "januaro" -#define STRING_DATE_FEBRUARY_LONG "febrero" -#define STRING_DATE_MARCH_LONG "marto" -#define STRING_DATE_APRIL_LONG "aprilo" -#define STRING_DATE_MAY_LONG "majo" -#define STRING_DATE_JUNE_LONG "junio" -#define STRING_DATE_JULY_LONG "julio" -#define STRING_DATE_AUGUST_LONG "aŭgusto" -#define STRING_DATE_SEPTEMBER_LONG "septembro" -#define STRING_DATE_OCTOBER_LONG "oktobro" -#define STRING_DATE_NOVEMBER_LONG "novembro" -#define STRING_DATE_DECEMBER_LONG "decembro" - -#define STRING_DATE_JANUARY_SHORT "jan" -#define STRING_DATE_FEBRUARY_SHORT "feb" -#define STRING_DATE_MARCH_SHORT "mar" -#define STRING_DATE_APRIL_SHORT "apr" -#define STRING_DATE_MAY_SHORT "maj" -#define STRING_DATE_JUNE_SHORT "jun" -#define STRING_DATE_JULY_SHORT "jul" -#define STRING_DATE_AUGUST_SHORT "aŭg" -#define STRING_DATE_SEPTEMBER_SHORT "sep" -#define STRING_DATE_OCTOBER_SHORT "okt" -#define STRING_DATE_NOVEMBER_SHORT "nov" -#define STRING_DATE_DECEMBER_SHORT "dec" - -#define STRING_DATE_SUNDAY_LONG "dimanĉo" -#define STRING_DATE_MONDAY_LONG "lundo" -#define STRING_DATE_TUESDAY_LONG "mardo" -#define STRING_DATE_WEDNESDAY_LONG "merkredo" -#define STRING_DATE_THURSDAY_LONG "ĵaŭdo" -#define STRING_DATE_FRIDAY_LONG "vendredo" -#define STRING_DATE_SATURDAY_LONG "sabato" - -#define STRING_DATE_SUNDAY_SHORT "di" -#define STRING_DATE_MONDAY_SHORT "lu" -#define STRING_DATE_TUESDAY_SHORT "ma" -#define STRING_DATE_WEDNESDAY_SHORT "me" -#define STRING_DATE_THURSDAY_SHORT "ĵa" -#define STRING_DATE_FRIDAY_SHORT "ve" -#define STRING_DATE_SATURDAY_SHORT "sa" +#define STRING_DATE_JANUARY "januaro" +#define STRING_DATE_FEBRUARY "febrero" +#define STRING_DATE_MARCH "marto" +#define STRING_DATE_APRIL "aprilo" +#define STRING_DATE_MAY "majo" +#define STRING_DATE_JUNE "junio" +#define STRING_DATE_JULY "julio" +#define STRING_DATE_AUGUST "aŭgusto" +#define STRING_DATE_SEPTEMBER "septembro" +#define STRING_DATE_OCTOBER "oktobro" +#define STRING_DATE_NOVEMBER "novembro" +#define STRING_DATE_DECEMBER "decembro" + +#define STRING_DATE_SUNDAY "dimanĉo" +#define STRING_DATE_MONDAY "lundo" +#define STRING_DATE_TUESDAY "mardo" +#define STRING_DATE_WEDNESDAY "merkredo" +#define STRING_DATE_THURSDAY "ĵaŭdo" +#define STRING_DATE_FRIDAY "vendredo" +#define STRING_DATE_SATURDAY "sabato" // dependency #define STRING_DEPEND_BLOCKED "Tasko {1} estas blokata per:" @@ -674,7 +659,6 @@ // DOM #define STRING_DOM_UNKNOWN "" #define STRING_DOM_UNREC "DOM: Ne povis inspekti nekonatan nomon '{1}'." -#define STRING_DOM_CANNOT_SET "DOM: Ne povis ŝanĝi '{1}'." // Eval #define STRING_EVAL_NO_EXPRESSION "Nenia esprimo por kalkuli." @@ -685,8 +669,9 @@ // edit #define STRING_EDIT_NO_CHANGES "Ne detektis nenian redakton." -#define STRING_EDIT_NO_EDITS "Ne redaktis nenion." +#define STRING_EDIT_FAILED "Editing failed with exit code {1}." #define STRING_EDIT_COMPLETE "Redaktis komplete." +#define STRING_EDIT_IN_PROGRESS "Task is already being edited." #define STRING_EDIT_LAUNCHING "Lanĉanta nun '{1}'..." #define STRING_EDIT_CHANGES "Detektis redaktojn." #define STRING_EDIT_UNPARSEABLE "Taskwarrior ne povis trakti viaj redaktojn. Ĉu vi volas ripovi?" @@ -765,6 +750,9 @@ #define STRING_INVALID_SORT_COL "Kolumno '{1}' ne estas valida kampo por ordigi." #define STRING_TLS_INIT_FAIL "Erara eko de TLS. {1}" #define STRING_ERROR_DETAILS "Agordo 'calendar.details.report' devas enhavi sole unu raportnomon." +#define STRING_ERROR_NO_FILTER "Command line filters are not supported by this command." +#define STRING_ERROR_CONFIRM_SIGINT "Interrupted: No changes made." +#define STRING_ERROR_BAD_STATUS "The status '{1}' is not valid." // Feedback #define STRING_FEEDBACK_NO_TASKS "Nenia tasko." @@ -793,6 +781,7 @@ #define STRING_FEEDBACK_TAG_NONAG "Speciala etikedo 'nonag' antaŭmalebligitos molestojn, kiam oni modifus tiun taskon." #define STRING_FEEDBACK_TAG_NOCAL "Speciala etikedo 'nocal' ekskluzivos tiun taskon ĉe raporto 'calendar'." #define STRING_FEEDBACK_TAG_NEXT "Speciala etikedo 'next' pligrandigos la urĝecon de tiu tasko por ke ĝi aperus ĉe raporto 'next'." +#define STRING_FEEDBACK_TAG_VIRTUAL "Virtual tags (including '{1}') are reserved and may not be added or removed." #define STRING_FEEDBACK_UNBLOCKED "Malblokis {1} '{2}'." #define STRING_FEEDBACK_EXPIRED "Tasko {1} '{2}' fortempiĝis do estis viŝata." #define STRING_FEEDBACK_BACKLOG "Estas lokaj ŝanĝoj. Sinkronigo devita." @@ -888,6 +877,10 @@ #define STRING_TDB2_UNDO_COMPLETE "Malfaris komplete." #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}" +#define STRING_TDB2_UNWAIT "Un-waiting task '{1}'" + +// recur.cpp +#define STRING_RECUR_CREATE "Creating recurring task instance '{1}'" // View #define STRING_VIEW_TOO_SMALL "La raporto havas larĝecminimumon {1}, al kio ne konformas la disponebla larĝeco {2}." @@ -895,7 +888,7 @@ // Usage text. This is an exception, and contains \n characters and formatting. #define STRING_CMD_HELP_TEXT \ "Oni povas trovi dokumentojn por Taskwarrior uzante 'man task', 'man taskrc', 'man " \ - "task-color', 'man task-synch, aŭ ĉe http://taskwarrior.org\n" \ + "task-color', 'man task-sync', aŭ ĉe http://taskwarrior.org\n" \ "\n" \ "La ĝenerala formo de komandoj estas:\n" \ " task [] []\n" \ @@ -945,21 +938,27 @@ " end: Dato kiam la tasko estis finata/viŝata\n" \ " start: Dato kiam la tasko estis ekita\n" \ " scheduled: Fiksa dato kiam vi projektas eki la taskon\n" \ + " modified: Date task was last modified\n" \ " depends: Aliaj taskoj, de kioj ĉi tiu tasko dependas\n" \ "\n" \ "Atributaj modifantoj igas filtrilojn pli precizaj. La subtenataj modifantoj estas:\n" \ - " before (antaŭ; samsencaĵoj under, below)\n" \ - " after (post; samsencaĵoj over, above)\n" \ - " none (nenio)\n" \ - " any (ajno)\n" \ - " is (estas; samsencaĵo equals)\n" \ - " isnt (neestas; samsencaĵo not)\n" \ - " has (havas; samsencaĵo contains)\n" \ - " hasnt (nehavas)\n" \ - " startswith (kunekas; samsencaĵo left)\n" \ - " endswith (kunfiniĝas; samsencaĵo right)\n" \ - " word (vorto)\n" \ - " noword (nevorto)\n" \ + "\n" \ + " Modifiers Example Equivalent Meaning\n" \ + " ---------------- ----------------- ------------------- -------------------------\n" \ + " due:today due = today Fuzzy match\n" \ + " not due.not:today due != today Fuzzy non-match\n" \ + " before, below due.before:today due < tomorrow Exact date comparison\n" \ + " after, above due.after:today due > tomorrow Exact date comparison\n" \ + " none project.none: project == '' Empty\n" \ + " any project.any: project !== '' Not empty\n" \ + " is, equals project.is:x project == x Exact match\n" \ + " isnt project.isnt:x project !== x Exact non-match\n" \ + " has, contains desc.has:Hello desc ~ Hello Pattern match\n" \ + " hasnt, desc.hasnt:Hello desc !~ Hello Pattern non-match\n" \ + " startswith, left desc.left:Hel desc ~ '^Hel' Beginning match\n" \ + " endswith, right desc.right:llo desc ~ 'llo$' End match\n" \ + " word desc.word:Hello desc ~ '\\bHello\\b' Boundaried word match\n" \ + " noword desc.noword:Hello desc !~ '\\bHello\\b' Boundaried word non-match\n" \ "\n" \ "Alterne, algebraj esprimoj subtenas:\n" \ " and or xor Logical operators\n" \ diff -Nru task-2.4.4+dfsg/src/l10n/esp-ESP.h task-2.5.0+dfsg/src/l10n/esp-ESP.h --- task-2.4.4+dfsg/src/l10n/esp-ESP.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/l10n/esp-ESP.h 2015-10-21 21:18:15.000000000 +0000 @@ -76,7 +76,7 @@ // // 5. Add your new language to task.git/cmake.h.in: // -// #define LANGUAGE_DEU_DEU ${LANGUAGE_DEU_DEU} +// #define LANGUAGE_DEU_DEU ${LANGUAGE_DEU_DEU} // // 6. Build your localized Taskwarrior with these commands: // @@ -105,9 +105,9 @@ #define STRING_PARSER_ALIAS_NEST "Límite de alias anidados ({1}) alcanzado." #define STRING_PARSER_OVERRIDE_RC "Sobrescritura de configuración rc.{1}:{2}" #define STRING_PARSER_UNKNOWN_ATTMOD "Error: modificador de atributo no reconocido '{1}'." -#define STRING_PARSER_UUID_AFTER_COMMA "UUID no reconocido tras coma." #define STRING_PARSER_ALTERNATE_RC "Usando el archivo .taskrc alternativo {1}" #define STRING_PARSER_ALTERNATE_DATA "Usando data.location alternativa {1}" +#define STRING_PARSER_UNEXPECTED_ARG "The '{1}' command does not allow '{2}'." // Variant // @@ -115,22 +115,16 @@ // mostly concerned with how various operators interact with the different // data types. #define STRING_VARIANT_TIME_T "No se puede instanciar este tipo con un valor de naturaleza time_t." -#define STRING_VARIANT_CMP_UNKNOWN "No se puede comparar un tipo desconocido" -#define STRING_VARIANT_EQ_UNKNOWN "No se puede equiparar un tipo desconocido" -#define STRING_VARIANT_EXP_UNKNOWN "No se puede exponenciar un tipo desconocido" #define STRING_VARIANT_EXP_BOOL "No se puede exponenciar un booleano" #define STRING_VARIANT_EXP_NON_INT "No se puede exponenciar a una potencia no entera" #define STRING_VARIANT_EXP_STRING "No se puede exponenciar una cadena de caracteres" #define STRING_VARIANT_EXP_DATE "No se puede exponenciar una fecha" #define STRING_VARIANT_EXP_DURATION "No se puede exponenciar una duración" -#define STRING_VARIANT_SUB_UNKNOWN "No se puede sustraer un tipo desconocido" #define STRING_VARIANT_SUB_BOOL "No se puede sustraer de un booleano" #define STRING_VARIANT_SUB_STRING "No se puede sustraer una cadenas de caracteres" #define STRING_VARIANT_SUB_DATE "No se puede sustraer una fecha" -#define STRING_VARIANT_ADD_UNKNOWN "No se puede sumar un tipo desconocido" #define STRING_VARIANT_ADD_BOOL "No se puede sumar dos booleanos" #define STRING_VARIANT_ADD_DATE "No se puede sumar dos fechas" -#define STRING_VARIANT_MUL_UNKNOWN "No se puede multiplicar un tipo desconocido" #define STRING_VARIANT_MUL_BOOL "No se puede multiplicar un booleano" #define STRING_VARIANT_MUL_DATE "No se puede multiplicar una fecha" #define STRING_VARIANT_MUL_REAL_STR "No se puede multiplicar un número real por una cadena de caracteres" @@ -141,7 +135,6 @@ #define STRING_VARIANT_MUL_DUR_STR "No se puede multiplicar una duración por una cadena de caracteres" #define STRING_VARIANT_MUL_DUR_DATE "No se puede multiplicar una duración por una fecha" #define STRING_VARIANT_MUL_DUR_DUR "No se puede multiplicar una duración por otra" -#define STRING_VARIANT_DIV_UNKNOWN "No se puede dividir un tipo desconocido" #define STRING_VARIANT_DIV_BOOL "No se puede dividir un booleano" #define STRING_VARIANT_DIV_INT_BOOL "No se puede dividir un entero por un booleano" #define STRING_VARIANT_DIV_ZERO "No se puede dividir por cero" @@ -166,11 +159,8 @@ #define STRING_VARIANT_MOD_REAL_DATE "No se puede modular un real por una fecha" #define STRING_VARIANT_MOD_REAL_STR "No se puede modular un real por una cadena de caracteres" #define STRING_VARIANT_MOD_STR "No se puede modular una cadena de caracteres" -#define STRING_VARIANT_MOD_UNKNOWN "No se puede modular un tipo desconocido" #define STRING_VARIANT_MOD_ZERO "No se puede modular cero" -#define STRING_VARIANT_RENDER_UNK "No se puede dibujar un tipo desconocido." #define STRING_VARIANT_SQRT_NEG "No se puede calcular la raíz cuadrada de un tipo desconocido" -#define STRING_VARIANT_COERCE_UNK "No se puede convertir un dato ni a un tipo desconocido ni desde el mismo" // Dates // @@ -241,6 +231,16 @@ #define STRING_COLUMN_LABEL_UDACOUNT "Recuento de uso" #define STRING_COLUMN_LABEL_ORPHAN "UDA huérfano" +#define STRING_COLUMN_LABEL_COMMAND "Command" +#define STRING_COLUMN_LABEL_CATEGORY "Category" +#define STRING_COLUMN_LABEL_RO "R/W" +#define STRING_COLUMN_LABEL_SHOWS_ID "ID" +#define STRING_COLUMN_LABEL_GC "GC" +#define STRING_COLUMN_LABEL_CONTEXT "Context" +#define STRING_COLUMN_LABEL_FILTER "Filter" +#define STRING_COLUMN_LABEL_MODS "Mods" +#define STRING_COLUMN_LABEL_MISC "Misc" + // Column Examples #define STRING_COLUMN_EXAMPLES_TAGS "casa @tarea" #define STRING_COLUMN_EXAMPLES_PROJ "casa.jardín" @@ -272,7 +272,10 @@ #define STRING_CMD_LOG_USAGE "Añade una nueva tarea que ya ha sido completada" #define STRING_CMD_LOG_NO_RECUR "No puede registrar tareas recurrentes." #define STRING_CMD_LOG_NO_WAITING "No puede registrar tareas en espera." -#define STRING_CMD_LOG_LOGGED "Tarea registrada." + +//#define STRING_CMD_LOG_LOGGED "Tarea registrada." +#define STRING_CMD_LOG_LOGGED "Logged task {1}." + #define STRING_CMD_IDS_USAGE_RANGE "Muestra los IDs de las tareas coincidentes, como un rango" #define STRING_CMD_IDS_USAGE_LIST "Muestra los IDs de las tareas coincidentes, en forma de lista" #define STRING_CMD_IDS_USAGE_ZSH "Muestra los IDs y descripciones de las tareas coincidentes" @@ -291,7 +294,6 @@ #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" #define STRING_CMD_STATS_CATEGORY "Categoría" #define STRING_CMD_STATS_DATA "Datos" @@ -314,7 +316,6 @@ #define STRING_CMD_STATS_DESC_LEN "Longitud media de desc" #define STRING_CMD_STATS_CHARS "{1} caracteres" -#define STRING_CMD_STATS_LAST_SYNC "Ültima sincronización del servidor" #define STRING_CMD_STATS_BLOCKED "Tareas bloqueadas" #define STRING_CMD_STATS_BLOCKING "Tareas bloqueantes" #define STRING_CMD_REPORTS_USAGE "Lista todos los informes soportados" @@ -345,6 +346,9 @@ #define STRING_CMD_GHISTORY_YEAR "Año" #define STRING_CMD_GHISTORY_MONTH "Mes" #define STRING_CMD_GHISTORY_NUMBER "Número Añadidas/Completadas/Suprimidas" +#define STRING_CMD_UNIQUE_USAGE "Generates lists of unique attribute values" +#define STRING_CMD_UNIQUE_MISSING "An attribute must be specified. See 'task _columns'." +#define STRING_CMD_UNIQUE_VALID "You must specify an attribute or UDA." #define STRING_CMD_DONE_USAGE "Marca la tarea especificada como completada" #define STRING_CMD_DONE_CONFIRM "¿Completar tarea {1} '{2}'?" @@ -371,6 +375,7 @@ #define STRING_CMD_COUNT_USAGE "Cuenta tareas que coinciden" #define STRING_CMD_GET_USAGE "Método de acceso al DOM" #define STRING_CMD_GET_NO_DOM "Referencia a DOM no especificada." +#define STRING_CMD_GET_BAD_REF "'{1}' is not a DOM reference." #define STRING_CMD_UDAS_NO "Ningún UDA definido." #define STRING_CMD_UDAS_SUMMARY "{1} UDA definido" @@ -457,9 +462,9 @@ #define STRING_CMD_IMPORT_USAGE "Importa archivos JSON" #define STRING_CMD_IMPORT_SUMMARY "Importadas {1} tareas." -#define STRING_CMD_IMPORT_NOFILE "Debe especificar un archivo a importar." #define STRING_CMD_IMPORT_FILE "Importando '{1}'" #define STRING_CMD_IMPORT_MISSING "Archivo '{1}' no encontrado." +#define STRING_CMD_IMPORT_UUID_BAD "Not a valid UUID '{1}'." #define STRING_TASK_NO_DESC "La anotación carece de descripción: {1}" #define STRING_TASK_NO_ENTRY "La anotación carece de fecha de entrada: {1}" @@ -477,7 +482,7 @@ #define STRING_CMD_SYNC_SUCCESS2 "Sincronización correcta. {1} cambios recibidos." #define STRING_CMD_SYNC_SUCCESS3 "Sincronización correcta. {1} cambios enviados, {2} cambios recibidos." #define STRING_CMD_SYNC_SUCCESS_NOP "Sincronización correcta. No hay cambios" -#define STRING_CMD_SYNC_FAIL_ACCOUNT "Sincronización fallida. O bien sus credenciales son incorrectas, o su cuenta de Servidor Task no está habilitada." +#define STRING_CMD_SYNC_FAIL_ACCOUNT "Sincronización fallida. O bien sus credenciales son incorrectas, o su cuenta en el servidor Task no existe." #define STRING_CMD_SYNC_FAIL_ERROR "Sincronización fallida. El Servidor Task devolvió error: {1} {2}" #define STRING_CMD_SYNC_FAIL_CONNECT "Sincronización fallida. No se pudo conectar con el Servidor Task." #define STRING_CMD_SYNC_BAD_SERVER "Sincronización fallida. Ajuste de configuración '{1}' incorrecto" @@ -519,12 +524,12 @@ #define STRING_CMD_DIAG_HOOK_ENABLE "Habilitado" #define STRING_CMD_DIAG_HOOK_DISABLE "Inhabilitado" +#define STRING_CMD_COMMANDS_USAGE "Generates a list of all commands, with behavior details" #define STRING_CMD_HCOMMANDS_USAGE "Genera una lista de todos los comandos, con fines de auto-completado" #define STRING_CMD_ZSHCOMMANDS_USAGE "Genera una lista de todos los comandos, con fines de auto-completado zsh" #define STRING_CMD_ZSHATTS_USAGE "Genera una lista de todos los atributos, con fines de auto-completado zsh" #define STRING_CMD_ALIASES_USAGE "Genera una lista de todos los alias, con fines de auto-completado" -#define STRING_CMD_INSTALL_USAGE "Instala extensiones y scripts externos" #define STRING_CMD_MODIFY_USAGE1 "Modifica la tarea existente con los argumentos provistos." //#define STRING_CMD_MODIFY_USAGE1 "Modifies the existing task with provided arguments." @@ -597,6 +602,7 @@ #define STRING_CMD_BURN_USAGE_D "Muestra un diagrama burndown, por días" #define STRING_CMD_BURN_TITLE "Burndown" // |esp-ESP|==|eng-USA| #define STRING_CMD_BURN_TOO_SMALL "Ventana de terminal demasiado pequeña para dibujar una gráfica." +#define STRING_CMD_BURN_TOO_LARGE "Terminal window too large to draw a graph." #define STRING_CMD_BURN_DAILY "Diario" #define STRING_CMD_BURN_WEEKLY "Semanal" #define STRING_CMD_BURN_MONTHLY "Mensual" @@ -636,47 +642,26 @@ #define STRING_DATE_INVALID_FORMAT "'{1}' no es una fecha válida según el formato '{2}'." #define STRING_DATE_BAD_WEEKSTART "La variable de configuración 'weekstart' solamente puede contener 'Sunday' (domingo) o 'Monday' (lunes)." -#define STRING_DATE_JANUARY_LONG "enero" -#define STRING_DATE_FEBRUARY_LONG "febrero" -#define STRING_DATE_MARCH_LONG "marzo" -#define STRING_DATE_APRIL_LONG "abril" -#define STRING_DATE_MAY_LONG "mayo" -#define STRING_DATE_JUNE_LONG "junio" -#define STRING_DATE_JULY_LONG "julio" -#define STRING_DATE_AUGUST_LONG "agosto" -#define STRING_DATE_SEPTEMBER_LONG "septiembre" -#define STRING_DATE_OCTOBER_LONG "octubre" -#define STRING_DATE_NOVEMBER_LONG "noviembre" -#define STRING_DATE_DECEMBER_LONG "diciembre" - -#define STRING_DATE_JANUARY_SHORT "ene" -#define STRING_DATE_FEBRUARY_SHORT "feb" // |esp-ESP|==|eng-USA| -#define STRING_DATE_MARCH_SHORT "mar" // |esp-ESP|==|eng-USA| -#define STRING_DATE_APRIL_SHORT "abr" -#define STRING_DATE_MAY_SHORT "may" // |esp-ESP|==|eng-USA| -#define STRING_DATE_JUNE_SHORT "jun" // |esp-ESP|==|eng-USA| -#define STRING_DATE_JULY_SHORT "jul" // |esp-ESP|==|eng-USA| -#define STRING_DATE_AUGUST_SHORT "ago" -#define STRING_DATE_SEPTEMBER_SHORT "sep" // |esp-ESP|==|eng-USA| -#define STRING_DATE_OCTOBER_SHORT "oct" // |esp-ESP|==|eng-USA| -#define STRING_DATE_NOVEMBER_SHORT "nov" // |esp-ESP|==|eng-USA| -#define STRING_DATE_DECEMBER_SHORT "dic" - -#define STRING_DATE_SUNDAY_LONG "domingo" -#define STRING_DATE_MONDAY_LONG "lunes" -#define STRING_DATE_TUESDAY_LONG "martes" -#define STRING_DATE_WEDNESDAY_LONG "miércoles" -#define STRING_DATE_THURSDAY_LONG "jueves" -#define STRING_DATE_FRIDAY_LONG "viernes" -#define STRING_DATE_SATURDAY_LONG "sábado" - -#define STRING_DATE_SUNDAY_SHORT "dom" -#define STRING_DATE_MONDAY_SHORT "lun" -#define STRING_DATE_TUESDAY_SHORT "mar" -#define STRING_DATE_WEDNESDAY_SHORT "mie" -#define STRING_DATE_THURSDAY_SHORT "jue" -#define STRING_DATE_FRIDAY_SHORT "vie" -#define STRING_DATE_SATURDAY_SHORT "sab" +#define STRING_DATE_JANUARY "enero" +#define STRING_DATE_FEBRUARY "febrero" +#define STRING_DATE_MARCH "marzo" +#define STRING_DATE_APRIL "abril" +#define STRING_DATE_MAY "mayo" +#define STRING_DATE_JUNE "junio" +#define STRING_DATE_JULY "julio" +#define STRING_DATE_AUGUST "agosto" +#define STRING_DATE_SEPTEMBER "septiembre" +#define STRING_DATE_OCTOBER "octubre" +#define STRING_DATE_NOVEMBER "noviembre" +#define STRING_DATE_DECEMBER "diciembre" + +#define STRING_DATE_SUNDAY "domingo" +#define STRING_DATE_MONDAY "lunes" +#define STRING_DATE_TUESDAY "martes" +#define STRING_DATE_WEDNESDAY "miércoles" +#define STRING_DATE_THURSDAY "jueves" +#define STRING_DATE_FRIDAY "viernes" +#define STRING_DATE_SATURDAY "sábado" // dependency #define STRING_DEPEND_BLOCKED "La tarea {1} está bloqueada por:" @@ -686,7 +671,6 @@ // DOM #define STRING_DOM_UNKNOWN "" #define STRING_DOM_UNREC "DOM: No se pudo obtener el nombre no reconocido '{1}'." -#define STRING_DOM_CANNOT_SET "DOM: No se pudo establecer '{1}'." // Eval #define STRING_EVAL_NO_EXPRESSION "Ninguna expresión para evaluar." @@ -697,8 +681,9 @@ // edit #define STRING_EDIT_NO_CHANGES "No se detectaron modificaciones." -#define STRING_EDIT_NO_EDITS "No se realizó edición." +#define STRING_EDIT_FAILED "Editing failed with exit code {1}." #define STRING_EDIT_COMPLETE "Edición completada." +#define STRING_EDIT_IN_PROGRESS "Task is already being edited." #define STRING_EDIT_LAUNCHING "Lanzando '{1}' ahora..." #define STRING_EDIT_CHANGES "Se detectaron modificaciones." #define STRING_EDIT_UNPARSEABLE "Taskwarrior no pudo manejar sus modificaciones. ¿Quiere intentarlo de nuevo?" @@ -777,6 +762,9 @@ #define STRING_INVALID_SORT_COL "La columna '{1}' no es un campo de ordenación válido." #define STRING_TLS_INIT_FAIL "Error inicializando TLS. {1}" #define STRING_ERROR_DETAILS "El ajuste 'calendar.details.report' debe contener un único nombre de informe." +#define STRING_ERROR_NO_FILTER "Command line filters are not supported by this command." +#define STRING_ERROR_CONFIRM_SIGINT "Interrupted: No changes made." +#define STRING_ERROR_BAD_STATUS "The status '{1}' is not valid." // Feedback #define STRING_FEEDBACK_NO_TASKS "Ninguna tarea." @@ -805,6 +793,7 @@ #define STRING_FEEDBACK_TAG_NONAG "La marca especial 'nonag' evitará el recuerdo fastidioso cuando la tarea sea modificada." #define STRING_FEEDBACK_TAG_NOCAL "La marca especial 'nocal' mantendrá esta tarea fuera del informe 'calendar'." #define STRING_FEEDBACK_TAG_NEXT "La etiqueta especial 'next' aumentará la urgencia de esta tarea para que aparezca en el informe 'next'." +#define STRING_FEEDBACK_TAG_VIRTUAL "Virtual tags (including '{1}') are reserved and may not be added or removed." #define STRING_FEEDBACK_UNBLOCKED "Desbloqueada {1} '{2}'." #define STRING_FEEDBACK_EXPIRED "La tarea {1} '{2}' caducó y fue eliminada." #define STRING_FEEDBACK_BACKLOG "Hay modificaciones locales. Se require una sincronización." @@ -901,6 +890,10 @@ #define STRING_TDB2_UNDO_COMPLETE "Deshacer completado." #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 "Saliendo con cambios sin escribir a {1}" +#define STRING_TDB2_UNWAIT "Un-waiting task '{1}'" + +// recur.cpp +#define STRING_RECUR_CREATE "Creating recurring task instance '{1}'" // View #define STRING_VIEW_TOO_SMALL "El informe tiene una anchura mínima de {1} y no cabe en la disponible, que es {2}." @@ -923,7 +916,7 @@ " task add -- project:Home needs scheduling\n" */ #define STRING_CMD_HELP_TEXT \ "La documentación de Taskwarrior se puede consultar usando 'man task', 'man taskrc'" \ - "man task-color', 'man task-synch o en http://taskwarrior.org\n" \ + "man task-color', 'man task-sync' o en http://taskwarrior.org\n" \ "\n" \ "La forma general para los comandos es:\n" \ " task [] []\n" \ @@ -973,21 +966,27 @@ " end: Fecha en la que la tarea fue completada/eliminada\n" \ " start: Fecha en la que la tarea fue comenzada\n" \ " scheduled: Fecha programada para que la tarea comience\n" \ + " modified: Date task was last modified\n" \ " depends: Otras tareas de las que esta tarea depende\n" \ "\n" \ "Los modificadores de atributos hacen a los filtros más precisos. Modificadores soportados son:\n" \ - " before (antes de; sinónimos under, below)\n" \ - " after (después de; sinónimos over, above)\n" \ - " none (nada)\n" \ - " any (cualquiera)\n" \ - " is (es; sinónimo equals)\n" \ - " isnt (no es; sinónimo not)\n" \ - " has (tiene; sinónimo contains)\n" \ - " hasnt (no tiene)\n" \ - " startswith (comienza con; sinónimo left)\n" \ - " endswith (se termina con; sinónimo right)\n" \ - " word (contiene palabra)\n" \ - " noword (no contiene palabra)\n" \ + "\n" \ + " Modifiers Example Equivalent Meaning\n" \ + " ---------------- ----------------- ------------------- -------------------------\n" \ + " due:today due = today Fuzzy match\n" \ + " not due.not:today due != today Fuzzy non-match\n" \ + " before, below due.before:today due < tomorrow Exact date comparison\n" \ + " after, above due.after:today due > tomorrow Exact date comparison\n" \ + " none project.none: project == '' Empty\n" \ + " any project.any: project !== '' Not empty\n" \ + " is, equals project.is:x project == x Exact match\n" \ + " isnt project.isnt:x project !== x Exact non-match\n" \ + " has, contains desc.has:Hello desc ~ Hello Pattern match\n" \ + " hasnt, desc.hasnt:Hello desc !~ Hello Pattern non-match\n" \ + " startswith, left desc.left:Hel desc ~ '^Hel' Beginning match\n" \ + " endswith, right desc.right:llo desc ~ 'llo$' End match\n" \ + " word desc.word:Hello desc ~ '\\bHello\\b' Boundaried word match\n" \ + " noword desc.noword:Hello desc !~ '\\bHello\\b' Boundaried word non-match\n" \ "\n" \ "Soporte de expresiones algebraicas alternativas:\n" \ " and or xor Operadores lógicos\n" \ diff -Nru task-2.4.4+dfsg/src/l10n/fra-FRA.h task-2.5.0+dfsg/src/l10n/fra-FRA.h --- task-2.4.4+dfsg/src/l10n/fra-FRA.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/l10n/fra-FRA.h 2015-10-21 21:18:15.000000000 +0000 @@ -105,9 +105,9 @@ #define STRING_PARSER_ALIAS_NEST "Atteignit la limite d'amboîtage des pseudonymes, {1}." #define STRING_PARSER_OVERRIDE_RC "Configuration écrasée : rc.{1}:{2}" #define STRING_PARSER_UNKNOWN_ATTMOD "Erreur : attribut de modification non reconnu '{1}'." -#define STRING_PARSER_UUID_AFTER_COMMA "UUID non reconnu après la virgule." #define STRING_PARSER_ALTERNATE_RC "Utilise un fichier .taskrc alternatif : {1}" #define STRING_PARSER_ALTERNATE_DATA "Utilise une data.location alternative : {1}" +#define STRING_PARSER_UNEXPECTED_ARG "The '{1}' command does not allow '{2}'." // Variant // @@ -115,22 +115,16 @@ // mostly concerned with how various operators interact with the different // data types. #define STRING_VARIANT_TIME_T "Ne peut pas initier ce type avec un valeur time_t." -#define STRING_VARIANT_CMP_UNKNOWN "Ne peut pas comparer type inconnu" -#define STRING_VARIANT_EQ_UNKNOWN "Cannot equate unknown type" -#define STRING_VARIANT_EXP_UNKNOWN "Cannot exponentiate unknown type" #define STRING_VARIANT_EXP_BOOL "Cannot exponentiate Booleans" #define STRING_VARIANT_EXP_NON_INT "Cannot exponentiate to a non-integer power" #define STRING_VARIANT_EXP_STRING "Cannot exponentiate strings" #define STRING_VARIANT_EXP_DATE "Cannot exponentiate dates" #define STRING_VARIANT_EXP_DURATION "Cannot exponentiate durations" -#define STRING_VARIANT_SUB_UNKNOWN "Ne peut pas soustraire un type inconnu" #define STRING_VARIANT_SUB_BOOL "Ne peut pas soustraire d'un booléen" #define STRING_VARIANT_SUB_STRING "Ne peut pas soustraire une chaine" #define STRING_VARIANT_SUB_DATE "Ne peut pas soustraire une date" -#define STRING_VARIANT_ADD_UNKNOWN "Ne peut pas ajouter un type inconnu" #define STRING_VARIANT_ADD_BOOL "Ne peut pas ajouter deux booléens" #define STRING_VARIANT_ADD_DATE "Ne peut pas ajouter deux dates" -#define STRING_VARIANT_MUL_UNKNOWN "Ne peut pas multiplier un type inconnu" #define STRING_VARIANT_MUL_BOOL "Ne peut pas multiplier un booléen" #define STRING_VARIANT_MUL_DATE "Ne peut pas multiplier une date" #define STRING_VARIANT_MUL_REAL_STR "Ne peut pas multiplier un nombre réel par une chaine" @@ -141,7 +135,6 @@ #define STRING_VARIANT_MUL_DUR_STR "Ne peut pas multiplier une durée par une chaine" #define STRING_VARIANT_MUL_DUR_DATE "Ne peut pas multiplier une durée par une date" #define STRING_VARIANT_MUL_DUR_DUR "Ne peut pas multiplier une durée par une durée" -#define STRING_VARIANT_DIV_UNKNOWN "Ne peut pas diviser un type inconnu" #define STRING_VARIANT_DIV_BOOL "Ne peut pas diviser un booléen" #define STRING_VARIANT_DIV_INT_BOOL "Ne peut pas diviser un nombre entier par un booléen" #define STRING_VARIANT_DIV_ZERO "Ne peut pas diviser par zéro" @@ -166,11 +159,8 @@ #define STRING_VARIANT_MOD_REAL_DATE "Ne peut pas moduler un nombre réel par une date" #define STRING_VARIANT_MOD_REAL_STR "Ne peut pas moduler un nombre réel par une chaine" #define STRING_VARIANT_MOD_STR "Ne peut pas moduler une chaine" -#define STRING_VARIANT_MOD_UNKNOWN "Ne peut pas moduler un type inconnu" #define STRING_VARIANT_MOD_ZERO "Ne peut pas moduler zéro" -#define STRING_VARIANT_RENDER_UNK "Ne peut pas rendre un type inconnu." #define STRING_VARIANT_SQRT_NEG "Ne peut pas calculer la racine carrée d'un nombre négatif." -#define STRING_VARIANT_COERCE_UNK "Cannot coerce data either to or from an unknown type" // Dates // @@ -240,6 +230,16 @@ #define STRING_COLUMN_LABEL_UDACOUNT "Compte d’utilisation" #define STRING_COLUMN_LABEL_ORPHAN "ADU orphelins" +#define STRING_COLUMN_LABEL_COMMAND "Command" +#define STRING_COLUMN_LABEL_CATEGORY "Category" +#define STRING_COLUMN_LABEL_RO "R/W" +#define STRING_COLUMN_LABEL_SHOWS_ID "ID" +#define STRING_COLUMN_LABEL_GC "GC" +#define STRING_COLUMN_LABEL_CONTEXT "Context" +#define STRING_COLUMN_LABEL_FILTER "Filter" +#define STRING_COLUMN_LABEL_MODS "Mods" +#define STRING_COLUMN_LABEL_MISC "Misc" + // Column Examples #define STRING_COLUMN_EXAMPLES_TAGS "maison @routine next" #define STRING_COLUMN_EXAMPLES_PROJ "maison.jardin" @@ -271,7 +271,10 @@ #define STRING_CMD_LOG_USAGE "Adds a new task that is already completed" #define STRING_CMD_LOG_NO_RECUR "Vous ne pouvez pas journaliser une tâche récurrente." #define STRING_CMD_LOG_NO_WAITING "Vous ne pouvez pas journaliser une tâche en attente." -#define STRING_CMD_LOG_LOGGED "Tâche journalisée." + +//#define STRING_CMD_LOG_LOGGED "Tâche journalisée." +#define STRING_CMD_LOG_LOGGED "Logged task {1}." + #define STRING_CMD_IDS_USAGE_RANGE "Affiche les IDs des tâches correspondantes, comme une plage" #define STRING_CMD_IDS_USAGE_LIST "Affiche les IDs des tâches correspondantes, sous forme de liste" #define STRING_CMD_IDS_USAGE_ZSH "Affiche les IDs et les descriptions des tâches correspondantes" @@ -289,7 +292,6 @@ #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" #define STRING_CMD_STATS_CATEGORY "Catégorie" #define STRING_CMD_STATS_DATA "Données" @@ -310,7 +312,6 @@ #define STRING_CMD_STATS_AVG_PEND "Durée moyenne d'activité" #define STRING_CMD_STATS_DESC_LEN "Longueur moyenne des descriptions" #define STRING_CMD_STATS_CHARS "{1} caractères" -#define STRING_CMD_STATS_LAST_SYNC "Dernière synchronisation avec le serveur" #define STRING_CMD_STATS_BLOCKED "Tâches bloquées" #define STRING_CMD_STATS_BLOCKING "Tâches bloquantes" #define STRING_CMD_REPORTS_USAGE "Liste tous les rapports supportés" @@ -338,6 +339,9 @@ #define STRING_CMD_GHISTORY_YEAR "An" #define STRING_CMD_GHISTORY_MONTH "Mois" #define STRING_CMD_GHISTORY_NUMBER "Number Added/Completed/Deleted" +#define STRING_CMD_UNIQUE_USAGE "Generates lists of unique attribute values" +#define STRING_CMD_UNIQUE_MISSING "An attribute must be specified. See 'task _columns'." +#define STRING_CMD_UNIQUE_VALID "You must specify an attribute or UDA." #define STRING_CMD_DONE_USAGE "Marque la tâche spécifiée comme terminée" #define STRING_CMD_DONE_CONFIRM "Terminer la tâche {1} '{2}'?" @@ -364,6 +368,7 @@ #define STRING_CMD_COUNT_USAGE "Compte les taches correspondantes" #define STRING_CMD_GET_USAGE "Accesseur au DOM" #define STRING_CMD_GET_NO_DOM "Aucune référence de DOM spécifié." +#define STRING_CMD_GET_BAD_REF "'{1}' is not a DOM reference." #define STRING_CMD_UDAS_NO "Aucuns ADUs définies." #define STRING_CMD_UDAS_SUMMARY "{1} ADU définie" @@ -449,9 +454,9 @@ #define STRING_CMD_IMPORT_USAGE "Imports JSON files" #define STRING_CMD_IMPORT_SUMMARY "Imported {1} tasks." -#define STRING_CMD_IMPORT_NOFILE "You must specify a file to import." #define STRING_CMD_IMPORT_FILE "Importing '{1}'" #define STRING_CMD_IMPORT_MISSING "File '{1}' not found." +#define STRING_CMD_IMPORT_UUID_BAD "Not a valid UUID '{1}'." #define STRING_TASK_NO_DESC "Annotation is missing a description: {1}" #define STRING_TASK_NO_ENTRY "Annotation is missing an entry date: {1}" #define STRING_CMD_SYNC_USAGE "Synchronizes data with the Taskserver" @@ -467,7 +472,7 @@ #define STRING_CMD_SYNC_SUCCESS2 "Sync successful. {1} changes downloaded." #define STRING_CMD_SYNC_SUCCESS3 "Sync successful. {1} changes uploaded, {2} changes downloaded." #define STRING_CMD_SYNC_SUCCESS_NOP "Sync successful. No changes." -#define STRING_CMD_SYNC_FAIL_ACCOUNT "Sync failed. Either your credentials are incorrect, or your Taskserver account is not enabled." +#define STRING_CMD_SYNC_FAIL_ACCOUNT "Sync failed. Either your credentials are incorrect, or your account doesn't exist on the Taskserver." #define STRING_CMD_SYNC_FAIL_ERROR "La synchrniqation a échouée. Taskserver a renvoyé l'erreur: {1} {2}" #define STRING_CMD_SYNC_FAIL_CONNECT "Sync failed. Could not connect to the Taskserver." #define STRING_CMD_SYNC_BAD_SERVER "Sync failed. Malformed configuration setting '{1}'" @@ -511,11 +516,11 @@ #define STRING_CMD_DIAG_HOOK_ENABLE "Enabled" #define STRING_CMD_DIAG_HOOK_DISABLE "Disabled" +#define STRING_CMD_COMMANDS_USAGE "Generates a list of all commands, with behavior details" #define STRING_CMD_HCOMMANDS_USAGE "Generates a list of all commands, for autocompletion purposes" #define STRING_CMD_ZSHCOMMANDS_USAGE "Generates a list of all commands, for zsh autocompletion purposes" #define STRING_CMD_ZSHATTS_USAGE "Generates a list of all attributes, for zsh autocompletion purposes" #define STRING_CMD_ALIASES_USAGE "Generates a list of all aliases, for autocompletion purposes" -#define STRING_CMD_INSTALL_USAGE "Installs extensions and external scripts" #define STRING_CMD_MODIFY_USAGE1 "Modifies the existing task with provided arguments." #define STRING_CMD_MODIFY_NO_DUE "You cannot specify a recurring task without a due date." @@ -554,7 +559,7 @@ #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_SUCC "Context '{1}' defined. Use 'task context {1}' to activate." #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." @@ -585,6 +590,7 @@ #define STRING_CMD_BURN_USAGE_D "Affiche un graphique d'avancement, par jour" #define STRING_CMD_BURN_TITLE "Burndown" #define STRING_CMD_BURN_TOO_SMALL "Terminal window too small to draw a graph." +#define STRING_CMD_BURN_TOO_LARGE "Terminal window too large to draw a graph." #define STRING_CMD_BURN_DAILY "Daily" #define STRING_CMD_BURN_WEEKLY "Weekly" #define STRING_CMD_BURN_MONTHLY "Monthly" @@ -624,47 +630,26 @@ #define STRING_DATE_INVALID_FORMAT "'{1}' n'est pas une date au format '{2}'." #define STRING_DATE_BAD_WEEKSTART "La variable de configuration 'weekstart' ne peut contenir que 'dimanche' ou 'lundi'." -#define STRING_DATE_JANUARY_LONG "janvier" -#define STRING_DATE_FEBRUARY_LONG "février" -#define STRING_DATE_MARCH_LONG "mars" -#define STRING_DATE_APRIL_LONG "avril" -#define STRING_DATE_MAY_LONG "mai" -#define STRING_DATE_JUNE_LONG "juin" -#define STRING_DATE_JULY_LONG "juillet" -#define STRING_DATE_AUGUST_LONG "août" -#define STRING_DATE_SEPTEMBER_LONG "septembre" -#define STRING_DATE_OCTOBER_LONG "octobre" -#define STRING_DATE_NOVEMBER_LONG "novembre" -#define STRING_DATE_DECEMBER_LONG "décembre" - -#define STRING_DATE_JANUARY_SHORT "jan" -#define STRING_DATE_FEBRUARY_SHORT "fév" -#define STRING_DATE_MARCH_SHORT "mar" -#define STRING_DATE_APRIL_SHORT "avr" -#define STRING_DATE_MAY_SHORT "mai" -#define STRING_DATE_JUNE_SHORT "jun" -#define STRING_DATE_JULY_SHORT "jul" -#define STRING_DATE_AUGUST_SHORT "aoû" -#define STRING_DATE_SEPTEMBER_SHORT "sep" -#define STRING_DATE_OCTOBER_SHORT "oct" -#define STRING_DATE_NOVEMBER_SHORT "nov" -#define STRING_DATE_DECEMBER_SHORT "déc" - -#define STRING_DATE_SUNDAY_LONG "dimanche" -#define STRING_DATE_MONDAY_LONG "lundi" -#define STRING_DATE_TUESDAY_LONG "mardi" -#define STRING_DATE_WEDNESDAY_LONG "mercredi" -#define STRING_DATE_THURSDAY_LONG "jeudi" -#define STRING_DATE_FRIDAY_LONG "vendredi" -#define STRING_DATE_SATURDAY_LONG "samedi" - -#define STRING_DATE_SUNDAY_SHORT "dim" -#define STRING_DATE_MONDAY_SHORT "lun" -#define STRING_DATE_TUESDAY_SHORT "mar" -#define STRING_DATE_WEDNESDAY_SHORT "mer" -#define STRING_DATE_THURSDAY_SHORT "jeu" -#define STRING_DATE_FRIDAY_SHORT "ven" -#define STRING_DATE_SATURDAY_SHORT "sam" +#define STRING_DATE_JANUARY "janvier" +#define STRING_DATE_FEBRUARY "février" +#define STRING_DATE_MARCH "mars" +#define STRING_DATE_APRIL "avril" +#define STRING_DATE_MAY "mai" +#define STRING_DATE_JUNE "juin" +#define STRING_DATE_JULY "juillet" +#define STRING_DATE_AUGUST "août" +#define STRING_DATE_SEPTEMBER "septembre" +#define STRING_DATE_OCTOBER "octobre" +#define STRING_DATE_NOVEMBER "novembre" +#define STRING_DATE_DECEMBER "décembre" + +#define STRING_DATE_SUNDAY "dimanche" +#define STRING_DATE_MONDAY "lundi" +#define STRING_DATE_TUESDAY "mardi" +#define STRING_DATE_WEDNESDAY "mercredi" +#define STRING_DATE_THURSDAY "jeudi" +#define STRING_DATE_FRIDAY "vendredi" +#define STRING_DATE_SATURDAY "samedi" // dependency #define STRING_DEPEND_BLOCKED "Tâche {1} est bloquée par :" @@ -674,7 +659,6 @@ // DOM #define STRING_DOM_UNKNOWN "" #define STRING_DOM_UNREC "DOM: Cannot get unrecognized name '{1}'." -#define STRING_DOM_CANNOT_SET "DOM: Cannot set '{1}'." // Eval #define STRING_EVAL_NO_EXPRESSION "No expression to evaluate." @@ -685,8 +669,9 @@ // edit #define STRING_EDIT_NO_CHANGES "Aucunes modifications détectées." -#define STRING_EDIT_NO_EDITS "Aucune modification appliquée." +#define STRING_EDIT_FAILED "Editing failed with exit code {1}." #define STRING_EDIT_COMPLETE "Édition terminée." +#define STRING_EDIT_IN_PROGRESS "Task is already being edited." #define STRING_EDIT_LAUNCHING "Lancement de '{1}' maintenant..." #define STRING_EDIT_CHANGES "Des modifications ont été détectées." #define STRING_EDIT_UNPARSEABLE "Taskwarrior n'a pas pu appliquer vos modifications. Désirez-vous essayer à nouveau ?" @@ -765,6 +750,9 @@ #define STRING_INVALID_SORT_COL "The '{1}' column is not a valid sort field." #define STRING_TLS_INIT_FAIL "Erreur en initialisant TLS. {1}" #define STRING_ERROR_DETAILS "The setting 'calendar.details.report' must contain a single report name." +#define STRING_ERROR_NO_FILTER "Command line filters are not supported by this command." +#define STRING_ERROR_CONFIRM_SIGINT "Interrupted: No changes made." +#define STRING_ERROR_BAD_STATUS "The status '{1}' is not valid." // Feedback #define STRING_FEEDBACK_NO_TASKS "No tasks." @@ -793,6 +781,7 @@ #define STRING_FEEDBACK_TAG_NONAG "The 'nonag' special tag will prevent nagging when this task is modified." #define STRING_FEEDBACK_TAG_NOCAL "The 'nocal' special tag will keep this task off the 'calendar' report." #define STRING_FEEDBACK_TAG_NEXT "The 'next' special tag will boost the urgency of this task so it appears on the 'next' report." +#define STRING_FEEDBACK_TAG_VIRTUAL "Virtual tags (including '{1}') are reserved and may not be added or removed." #define STRING_FEEDBACK_UNBLOCKED "Unblocked {1} '{2}'." #define STRING_FEEDBACK_EXPIRED "Tâche {1} '{2}' a expiré et a été supprimée." #define STRING_FEEDBACK_BACKLOG "Il y a des changements locaux. Synchronisation requise." @@ -888,6 +877,10 @@ #define STRING_TDB2_UNDO_COMPLETE "Annulation terminée." #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}" +#define STRING_TDB2_UNWAIT "Un-waiting task '{1}'" + +// recur.cpp +#define STRING_RECUR_CREATE "Creating recurring task instance '{1}'" // View #define STRING_VIEW_TOO_SMALL "The report has a minimum width of {1} and does not fit in the available width of {2}." @@ -895,7 +888,7 @@ // Usage text. This is an exception, and contains \n characters and formatting. #define STRING_CMD_HELP_TEXT \ "Documentation for Taskwarrior can be found using 'man task', 'man taskrc', 'man " \ - "task-color', 'man task-synch or at http://taskwarrior.org\n" \ + "task-color', 'man task-sync' or at http://taskwarrior.org\n" \ "\n" \ "The general form of commands is:\n" \ " task [] []\n" \ @@ -945,21 +938,27 @@ " end: Date task was completed/deleted\n" \ " start: Date task was started\n" \ " scheduled: Date task is scheduled to start\n" \ + " modified: Date task was last modified\n" \ " depends: Other tasks that this task depends upon\n" \ "\n" \ "Attribute modifiers make filters more precise. Supported modifiers are:\n" \ - " before (synonyms under, below)\n" \ - " after (synonyms over, above)\n" \ - " none\n" \ - " any\n" \ - " is (synonym equals)\n" \ - " isnt (synonym not)\n" \ - " has (synonym contains)\n" \ - " hasnt\n" \ - " startswith (synonym left)\n" \ - " endswith (synonym right)\n" \ - " word\n" \ - " noword\n" \ + "\n" \ + " Modifiers Example Equivalent Meaning\n" \ + " ---------------- ----------------- ------------------- -------------------------\n" \ + " due:today due = today Fuzzy match\n" \ + " not due.not:today due != today Fuzzy non-match\n" \ + " before, below due.before:today due < tomorrow Exact date comparison\n" \ + " after, above due.after:today due > tomorrow Exact date comparison\n" \ + " none project.none: project == '' Empty\n" \ + " any project.any: project !== '' Not empty\n" \ + " is, equals project.is:x project == x Exact match\n" \ + " isnt project.isnt:x project !== x Exact non-match\n" \ + " has, contains desc.has:Hello desc ~ Hello Pattern match\n" \ + " hasnt, desc.hasnt:Hello desc !~ Hello Pattern non-match\n" \ + " startswith, left desc.left:Hel desc ~ '^Hel' Beginning match\n" \ + " endswith, right desc.right:llo desc ~ 'llo$' End match\n" \ + " word desc.word:Hello desc ~ '\\bHello\\b' Boundaried word match\n" \ + " noword desc.noword:Hello desc !~ '\\bHello\\b' Boundaried word non-match\n" \ "\n" \ "Alternately algebraic expressions support:\n" \ " and or xor Logical operators\n" \ diff -Nru task-2.4.4+dfsg/src/l10n/ita-ITA.h task-2.5.0+dfsg/src/l10n/ita-ITA.h --- task-2.4.4+dfsg/src/l10n/ita-ITA.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/l10n/ita-ITA.h 2015-10-21 21:18:15.000000000 +0000 @@ -105,9 +105,9 @@ #define STRING_PARSER_ALIAS_NEST "Nested alias limit of {1} reached." #define STRING_PARSER_OVERRIDE_RC "Modifica configurazione rc.{1}:{2}" #define STRING_PARSER_UNKNOWN_ATTMOD "Errore: modificatore di attributo non riconosciuto '{1}'." -#define STRING_PARSER_UUID_AFTER_COMMA "UUID non riconosciuto dopo la virgola." #define STRING_PARSER_ALTERNATE_RC "Uso del file .taskrc alternativo {1}" #define STRING_PARSER_ALTERNATE_DATA "Uso di data.location alternativa {1}" +#define STRING_PARSER_UNEXPECTED_ARG "The '{1}' command does not allow '{2}'." // Variant // @@ -115,22 +115,16 @@ // mostly concerned with how various operators interact with the different // data types. #define STRING_VARIANT_TIME_T "Cannot instantiate this type with a time_t value." -#define STRING_VARIANT_CMP_UNKNOWN "Cannot compare unknown type" -#define STRING_VARIANT_EQ_UNKNOWN "Cannot equate unknown type" -#define STRING_VARIANT_EXP_UNKNOWN "Cannot exponentiate unknown type" #define STRING_VARIANT_EXP_BOOL "Cannot exponentiate Booleans" #define STRING_VARIANT_EXP_NON_INT "Cannot exponentiate to a non-integer power" #define STRING_VARIANT_EXP_STRING "Cannot exponentiate strings" #define STRING_VARIANT_EXP_DATE "Cannot exponentiate dates" #define STRING_VARIANT_EXP_DURATION "Cannot exponentiate durations" -#define STRING_VARIANT_SUB_UNKNOWN "Cannot subtract unknown type" #define STRING_VARIANT_SUB_BOOL "Cannot subtract from a Boolean value" #define STRING_VARIANT_SUB_STRING "Cannot subtract strings" #define STRING_VARIANT_SUB_DATE "Cannot subtract a date" -#define STRING_VARIANT_ADD_UNKNOWN "Cannot add unknown type" #define STRING_VARIANT_ADD_BOOL "Cannot add two Boolean values" #define STRING_VARIANT_ADD_DATE "Cannot add two date values" -#define STRING_VARIANT_MUL_UNKNOWN "Cannot multiply unknown type" #define STRING_VARIANT_MUL_BOOL "Cannot multiply Boolean values" #define STRING_VARIANT_MUL_DATE "Cannot multiply date values" #define STRING_VARIANT_MUL_REAL_STR "Cannot multiply real numbers by strings" @@ -141,7 +135,6 @@ #define STRING_VARIANT_MUL_DUR_STR "Cannot multiply durations by strings" #define STRING_VARIANT_MUL_DUR_DATE "Cannot multiply durations by dates" #define STRING_VARIANT_MUL_DUR_DUR "Cannot multiply durations by durations" -#define STRING_VARIANT_DIV_UNKNOWN "Cannot divide unknown type" #define STRING_VARIANT_DIV_BOOL "Cannot divide Boolean values" #define STRING_VARIANT_DIV_INT_BOOL "Cannot divide integers by Boolean values" #define STRING_VARIANT_DIV_ZERO "Cannot divide by zero" @@ -166,11 +159,8 @@ #define STRING_VARIANT_MOD_REAL_DATE "Cannot modulo real numbers by dates" #define STRING_VARIANT_MOD_REAL_STR "Cannot modulo real numbers by strings" #define STRING_VARIANT_MOD_STR "Cannot modulo string values" -#define STRING_VARIANT_MOD_UNKNOWN "Cannot modulo unknown type" #define STRING_VARIANT_MOD_ZERO "Cannot modulo zero" -#define STRING_VARIANT_RENDER_UNK "Cannot render an unknown type." #define STRING_VARIANT_SQRT_NEG "Cannot take the square root of a negative number." -#define STRING_VARIANT_COERCE_UNK "Cannot coerce data either to or from an unknown type" // Dates // @@ -240,6 +230,16 @@ #define STRING_COLUMN_LABEL_UDACOUNT "Conteggio Uso" #define STRING_COLUMN_LABEL_ORPHAN "UDA Orfano" +#define STRING_COLUMN_LABEL_COMMAND "Command" +#define STRING_COLUMN_LABEL_CATEGORY "Category" +#define STRING_COLUMN_LABEL_RO "R/W" +#define STRING_COLUMN_LABEL_SHOWS_ID "ID" +#define STRING_COLUMN_LABEL_GC "GC" +#define STRING_COLUMN_LABEL_CONTEXT "Context" +#define STRING_COLUMN_LABEL_FILTER "Filter" +#define STRING_COLUMN_LABEL_MODS "Mods" +#define STRING_COLUMN_LABEL_MISC "Misc" + // Column Examples #define STRING_COLUMN_EXAMPLES_TAGS "casa @faccende next" #define STRING_COLUMN_EXAMPLES_PROJ "casa.giardino" @@ -270,7 +270,10 @@ #define STRING_CMD_LOG_USAGE "Aggiunge un nuovo task già completato" #define STRING_CMD_LOG_NO_RECUR "Task periodici non possono essere registrati." #define STRING_CMD_LOG_NO_WAITING "Task in attesa non possono essere registrati." -#define STRING_CMD_LOG_LOGGED "Task registrato." + +//#define STRING_CMD_LOG_LOGGED "Task registrato." +#define STRING_CMD_LOG_LOGGED "Logged task {1}." + #define STRING_CMD_IDS_USAGE_RANGE "Mostra gli ID dei task corrispondenti, come intervallo" #define STRING_CMD_IDS_USAGE_LIST "Mostra gli ID dei task corrispondenti, in forma di lista" #define STRING_CMD_IDS_USAGE_ZSH "Mostra gli ID e le descrizioni dei task corrispondenti" @@ -288,7 +291,6 @@ #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" #define STRING_CMD_STATS_CATEGORY "Categoria" #define STRING_CMD_STATS_DATA "Dati" @@ -309,7 +311,6 @@ #define STRING_CMD_STATS_AVG_PEND "Tempo medio di attesa" #define STRING_CMD_STATS_DESC_LEN "Lunghezza media delle descrizioni" #define STRING_CMD_STATS_CHARS "{1} caratteri" -#define STRING_CMD_STATS_LAST_SYNC "Ultima sincronizzazione" #define STRING_CMD_STATS_BLOCKED "Task bloccati" #define STRING_CMD_STATS_BLOCKING "Task bloccanti" #define STRING_CMD_REPORTS_USAGE "Lista dei report supportati" @@ -337,6 +338,9 @@ #define STRING_CMD_GHISTORY_YEAR "Anno" #define STRING_CMD_GHISTORY_MONTH "Mese" #define STRING_CMD_GHISTORY_NUMBER "Aggiunti/Completati/Cancellati" +#define STRING_CMD_UNIQUE_USAGE "Generates lists of unique attribute values" +#define STRING_CMD_UNIQUE_MISSING "An attribute must be specified. See 'task _columns'." +#define STRING_CMD_UNIQUE_VALID "You must specify an attribute or UDA." #define STRING_CMD_DONE_USAGE "Contrassegna il task specificato come completato" #define STRING_CMD_DONE_CONFIRM "Completare il task {1} '{2}'?" @@ -363,6 +367,7 @@ #define STRING_CMD_COUNT_USAGE "Conteggia task corrispondenti" #define STRING_CMD_GET_USAGE "DOM Accessor" #define STRING_CMD_GET_NO_DOM "No DOM reference specified." +#define STRING_CMD_GET_BAD_REF "'{1}' is not a DOM reference." #define STRING_CMD_UDAS_NO "Nessun UDA definito." #define STRING_CMD_UDAS_SUMMARY "{1} UDA definito" @@ -448,9 +453,9 @@ #define STRING_CMD_IMPORT_USAGE "Importa file JSON" #define STRING_CMD_IMPORT_SUMMARY "Importati {1} task." -#define STRING_CMD_IMPORT_NOFILE "Specificare il file da importare." #define STRING_CMD_IMPORT_FILE "Importazione di '{1}'" #define STRING_CMD_IMPORT_MISSING "File '{1}' not found." +#define STRING_CMD_IMPORT_UUID_BAD "Not a valid UUID '{1}'." #define STRING_TASK_NO_DESC "Annotazione senza descrizione: {1}" #define STRING_TASK_NO_ENTRY "Annotazione senza data di immissione: {1}" #define STRING_CMD_SYNC_USAGE "Sincronizza i dati con il Taskserver" @@ -510,11 +515,11 @@ #define STRING_CMD_DIAG_HOOK_ENABLE "Enabled" #define STRING_CMD_DIAG_HOOK_DISABLE "Disabled" +#define STRING_CMD_COMMANDS_USAGE "Generates a list of all commands, with behavior details" #define STRING_CMD_HCOMMANDS_USAGE "Genera la lista di tutti i comandi, per autocompletamento" #define STRING_CMD_ZSHCOMMANDS_USAGE "Genera la lista di tutti i comandi, per autocompletamento in zsh" #define STRING_CMD_ZSHATTS_USAGE "Generates a list of all attributes, for zsh autocompletion purposes" #define STRING_CMD_ALIASES_USAGE "Genera la lista di tutti gli alias, per autocompletamento" -#define STRING_CMD_INSTALL_USAGE "Installa estensioni e script esterni" #define STRING_CMD_MODIFY_USAGE1 "Modifica il task esistente usando gli argomenti specificati." #define STRING_CMD_MODIFY_NO_DUE "Impossibile specificare un task periodico senza una data di scadenza." @@ -553,7 +558,7 @@ #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_SUCC "Context '{1}' defined. Use 'task context {1}' to activate." #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." @@ -584,6 +589,7 @@ #define STRING_CMD_BURN_USAGE_D "Mostra un grafico del lavoro da svolgere, per giorno" #define STRING_CMD_BURN_TITLE "Lavoro da svolgere" #define STRING_CMD_BURN_TOO_SMALL "Finestra troppo piccola per mostrare il grafico." +#define STRING_CMD_BURN_TOO_LARGE "Terminal window too large to draw a graph." #define STRING_CMD_BURN_DAILY "Giornaliero" #define STRING_CMD_BURN_WEEKLY "Settimanale" #define STRING_CMD_BURN_MONTHLY "Mensile" @@ -623,47 +629,26 @@ #define STRING_DATE_INVALID_FORMAT "'{1}' non è una data valida nel formato '{2}'." #define STRING_DATE_BAD_WEEKSTART "La variabile di configurazione 'weekstart' può solo contenere 'Domenica' o 'Lunedì'." -#define STRING_DATE_JANUARY_LONG "gennaio" -#define STRING_DATE_FEBRUARY_LONG "febbraio" -#define STRING_DATE_MARCH_LONG "marzo" -#define STRING_DATE_APRIL_LONG "aprile" -#define STRING_DATE_MAY_LONG "maggio" -#define STRING_DATE_JUNE_LONG "giugno" -#define STRING_DATE_JULY_LONG "luglio" -#define STRING_DATE_AUGUST_LONG "agosto" -#define STRING_DATE_SEPTEMBER_LONG "settembre" -#define STRING_DATE_OCTOBER_LONG "ottobre" -#define STRING_DATE_NOVEMBER_LONG "novembre" -#define STRING_DATE_DECEMBER_LONG "decembre" - -#define STRING_DATE_JANUARY_SHORT "gen" -#define STRING_DATE_FEBRUARY_SHORT "feb" -#define STRING_DATE_MARCH_SHORT "mar" -#define STRING_DATE_APRIL_SHORT "apr" -#define STRING_DATE_MAY_SHORT "mag" -#define STRING_DATE_JUNE_SHORT "giu" -#define STRING_DATE_JULY_SHORT "lug" -#define STRING_DATE_AUGUST_SHORT "ago" -#define STRING_DATE_SEPTEMBER_SHORT "set" -#define STRING_DATE_OCTOBER_SHORT "ott" -#define STRING_DATE_NOVEMBER_SHORT "nov" -#define STRING_DATE_DECEMBER_SHORT "dic" - -#define STRING_DATE_SUNDAY_LONG "domenica" -#define STRING_DATE_MONDAY_LONG "lunedì" -#define STRING_DATE_TUESDAY_LONG "martedì" -#define STRING_DATE_WEDNESDAY_LONG "mercoledì" -#define STRING_DATE_THURSDAY_LONG "giovedì" -#define STRING_DATE_FRIDAY_LONG "venerdì" -#define STRING_DATE_SATURDAY_LONG "sabato" - -#define STRING_DATE_SUNDAY_SHORT "dom" -#define STRING_DATE_MONDAY_SHORT "lun" -#define STRING_DATE_TUESDAY_SHORT "mar" -#define STRING_DATE_WEDNESDAY_SHORT "mer" -#define STRING_DATE_THURSDAY_SHORT "gio" -#define STRING_DATE_FRIDAY_SHORT "ven" -#define STRING_DATE_SATURDAY_SHORT "sab" +#define STRING_DATE_JANUARY "gennaio" +#define STRING_DATE_FEBRUARY "febbraio" +#define STRING_DATE_MARCH "marzo" +#define STRING_DATE_APRIL "aprile" +#define STRING_DATE_MAY "maggio" +#define STRING_DATE_JUNE "giugno" +#define STRING_DATE_JULY "luglio" +#define STRING_DATE_AUGUST "agosto" +#define STRING_DATE_SEPTEMBER "settembre" +#define STRING_DATE_OCTOBER "ottobre" +#define STRING_DATE_NOVEMBER "novembre" +#define STRING_DATE_DECEMBER "decembre" + +#define STRING_DATE_SUNDAY "domenica" +#define STRING_DATE_MONDAY "lunedì" +#define STRING_DATE_TUESDAY "martedì" +#define STRING_DATE_WEDNESDAY "mercoledì" +#define STRING_DATE_THURSDAY "giovedì" +#define STRING_DATE_FRIDAY "venerdì" +#define STRING_DATE_SATURDAY "sabato" // dependency #define STRING_DEPEND_BLOCKED "Il task {1} è bloccato da:" @@ -673,7 +658,6 @@ // DOM #define STRING_DOM_UNKNOWN "" #define STRING_DOM_UNREC "DOM: Impossibile ottenere il nome non riconosciuto '{1}'." -#define STRING_DOM_CANNOT_SET "DOM: Impossibile impostare '{1}'." // Eval #define STRING_EVAL_NO_EXPRESSION "No expression to evaluate." @@ -684,8 +668,9 @@ // edit #define STRING_EDIT_NO_CHANGES "Nessuna modifica riscontrata." -#define STRING_EDIT_NO_EDITS "Nessuna modifica effettuata." +#define STRING_EDIT_FAILED "Editing failed with exit code {1}." #define STRING_EDIT_COMPLETE "Modifica completa." +#define STRING_EDIT_IN_PROGRESS "Task is already being edited." #define STRING_EDIT_LAUNCHING "Esecuzione di '{1}' ora..." #define STRING_EDIT_CHANGES "Modifiche rilevate." #define STRING_EDIT_UNPARSEABLE "Taskwarrior non può gestire le modifiche. Provare di nuovo?" @@ -764,6 +749,9 @@ #define STRING_INVALID_SORT_COL "La colonna '{1}' non è un campo di ordinamento valido." #define STRING_TLS_INIT_FAIL "Error initializing TLS. {1}" #define STRING_ERROR_DETAILS "The setting 'calendar.details.report' must contain a single report name." +#define STRING_ERROR_NO_FILTER "Command line filters are not supported by this command." +#define STRING_ERROR_CONFIRM_SIGINT "Interrupted: No changes made." +#define STRING_ERROR_BAD_STATUS "The status '{1}' is not valid." // Feedback #define STRING_FEEDBACK_NO_TASKS "Nessun task." @@ -792,6 +780,7 @@ #define STRING_FEEDBACK_TAG_NONAG "Il tag speciale 'nonag' eviterà problemi quando il task è modificato." #define STRING_FEEDBACK_TAG_NOCAL "Il tag speciale 'nocal' manterrà il task fuori dal report 'calendar'." #define STRING_FEEDBACK_TAG_NEXT "Il tag speciale 'next' aumenterà l'urgenza di questo task in modo che appaia nel report 'next'." +#define STRING_FEEDBACK_TAG_VIRTUAL "Virtual tags (including '{1}') are reserved and may not be added or removed." #define STRING_FEEDBACK_UNBLOCKED "Sbloccato {1} '{2}'." #define STRING_FEEDBACK_EXPIRED "Il task {1} '{2}' è scaduto ed è stato eliminato" #define STRING_FEEDBACK_BACKLOG "There are local changes. Sync required." @@ -887,6 +876,10 @@ #define STRING_TDB2_UNDO_COMPLETE "Undo completato." #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}" +#define STRING_TDB2_UNWAIT "Un-waiting task '{1}'" + +// recur.cpp +#define STRING_RECUR_CREATE "Creating recurring task instance '{1}'" // View #define STRING_VIEW_TOO_SMALL "Il report ha larghezza minima di {1} e non entra nella larghezza disponibile di {2}." @@ -894,7 +887,7 @@ // Usage text. This is an exception, and contains \n characters and formatting. #define STRING_CMD_HELP_TEXT \ "La documentazione di Taskwarrior può essere consultata con 'man task', 'man taskrc', 'man " \ - "task-color', 'man task-synch o presso http://taskwarrior.org\n" \ + "task-color', 'man task-sync' o presso http://taskwarrior.org\n" \ "\n" \ "La forma generale del comando è:\n" \ " task [] []\n" \ @@ -944,21 +937,27 @@ " end: Data di completamento/cancellazione del task\n" \ " start: Data di inizio del task\n" \ " scheduled: Data prevista per l'avvio del task\n" \ + " modified: Date task was last modified\n" \ " depends: Altri task dai quali dipende il task\n" \ "\n" \ "I modificatori rendono i filtri più precisi. Modificatori supportati sono:\n" \ - " before (sinomimi: under, below)\n" \ - " after (sinomimi: over, above)\n" \ - " none\n" \ - " any\n" \ - " is (sinomimo: equals)\n" \ - " isnt (sinomimo: not)\n" \ - " has (sinomimo: contains)\n" \ - " hasnt\n" \ - " startswith (sinomimo: left)\n" \ - " endswith (sinomimo: right)\n" \ - " word\n" \ - " noword\n" \ + "\n" \ + " Modifiers Example Equivalent Meaning\n" \ + " ---------------- ----------------- ------------------- -------------------------\n" \ + " due:today due = today Fuzzy match\n" \ + " not due.not:today due != today Fuzzy non-match\n" \ + " before, below due.before:today due < tomorrow Exact date comparison\n" \ + " after, above due.after:today due > tomorrow Exact date comparison\n" \ + " none project.none: project == '' Empty\n" \ + " any project.any: project !== '' Not empty\n" \ + " is, equals project.is:x project == x Exact match\n" \ + " isnt project.isnt:x project !== x Exact non-match\n" \ + " has, contains desc.has:Hello desc ~ Hello Pattern match\n" \ + " hasnt, desc.hasnt:Hello desc !~ Hello Pattern non-match\n" \ + " startswith, left desc.left:Hel desc ~ '^Hel' Beginning match\n" \ + " endswith, right desc.right:llo desc ~ 'llo$' End match\n" \ + " word desc.word:Hello desc ~ '\\bHello\\b' Boundaried word match\n" \ + " noword desc.noword:Hello desc !~ '\\bHello\\b' Boundaried word non-match\n" \ "\n" \ "Sono supportati i seguenti operatori:\n" \ " and or xor Operatori logici\n" \ diff -Nru task-2.4.4+dfsg/src/l10n/jpn-JPN.h task-2.5.0+dfsg/src/l10n/jpn-JPN.h --- task-2.4.4+dfsg/src/l10n/jpn-JPN.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/l10n/jpn-JPN.h 2015-10-21 21:18:15.000000000 +0000 @@ -105,9 +105,9 @@ #define STRING_PARSER_ALIAS_NEST "ネストされたエイリアスの制限 {1} に到達した。" #define STRING_PARSER_OVERRIDE_RC "設定は上書きされた rc.{1}:{2}" #define STRING_PARSER_UNKNOWN_ATTMOD "エラー: 不明な属性変更子 '{1}'." -#define STRING_PARSER_UUID_AFTER_COMMA "カンマのあとの不明な UUID." #define STRING_PARSER_ALTERNATE_RC "代替の .taskrc ファイル {1} を使用" #define STRING_PARSER_ALTERNATE_DATA "代替の data.location {1} を使用" +#define STRING_PARSER_UNEXPECTED_ARG "The '{1}' command does not allow '{2}'." // Variant // @@ -115,22 +115,16 @@ // mostly concerned with how various operators interact with the different // data types. #define STRING_VARIANT_TIME_T "Cannot instantiate this type with a time_t value." -#define STRING_VARIANT_CMP_UNKNOWN "不明なタイプを比較できない" -#define STRING_VARIANT_EQ_UNKNOWN "不明なタイプを同一視は出来ません" -#define STRING_VARIANT_EXP_UNKNOWN "不明なタイプをべき乗する事は出来ません" #define STRING_VARIANT_EXP_BOOL "論理型はべき乗出来ません" #define STRING_VARIANT_EXP_NON_INT "Cannot exponentiate to a non-integer power" #define STRING_VARIANT_EXP_STRING "文字列はべき乗できません" #define STRING_VARIANT_EXP_DATE "日付はべき乗できません" #define STRING_VARIANT_EXP_DURATION "期間はべき乗できません" -#define STRING_VARIANT_SUB_UNKNOWN "不明なタイプは減算できません" #define STRING_VARIANT_SUB_BOOL "論理型からは減算できません" #define STRING_VARIANT_SUB_STRING "文字列は減算できません" #define STRING_VARIANT_SUB_DATE "日付は減算できません" -#define STRING_VARIANT_ADD_UNKNOWN "不明なタイプは追加できません" #define STRING_VARIANT_ADD_BOOL "2つの論理値は加算できません" #define STRING_VARIANT_ADD_DATE "2つの日付値は加算できません" -#define STRING_VARIANT_MUL_UNKNOWN "不明なタイプは乗算できません" #define STRING_VARIANT_MUL_BOOL "論理値は乗算できません" #define STRING_VARIANT_MUL_DATE "日付は乗算できません" #define STRING_VARIANT_MUL_REAL_STR "実数を文字列では乗算できません" @@ -141,7 +135,6 @@ #define STRING_VARIANT_MUL_DUR_STR "期間を文字列では乗算できません" #define STRING_VARIANT_MUL_DUR_DATE "文字列を日付では乗算できません" #define STRING_VARIANT_MUL_DUR_DUR "期間を期間では乗算できません" -#define STRING_VARIANT_DIV_UNKNOWN "不明なタイプは除算できません" #define STRING_VARIANT_DIV_BOOL "論理値は除算できません" #define STRING_VARIANT_DIV_INT_BOOL "整数値を論理値では除算できません" #define STRING_VARIANT_DIV_ZERO "零では除算できません" @@ -155,22 +148,19 @@ #define STRING_VARIANT_DIV_DUR_DATE "期間を日付では除算出来ません" #define STRING_VARIANT_DIV_DUR_DUR "期間を期間では除算出来ません" #define STRING_VARIANT_MOD_BOOL "Cannot modulo Booleans" -#define STRING_VARIANT_MOD_DATE "Cannot modulo date values" +#define STRING_VARIANT_MOD_DATE "日付は剰余を計算できません。" #define STRING_VARIANT_MOD_DUR "Cannot modulo duration values" -#define STRING_VARIANT_MOD_INT_BOOL "Cannot modulo integer by Boolean" -#define STRING_VARIANT_MOD_INT_DATE "Cannot modulo integer by date values" +#define STRING_VARIANT_MOD_INT_BOOL "整数値を論理値で剰余を取ることは出来ません。" +#define STRING_VARIANT_MOD_INT_DATE "整数値を日付で剰余を取ることは出来ません。" #define STRING_VARIANT_MOD_INT_DUR "Cannot modulo integer by duration values" -#define STRING_VARIANT_MOD_INT_STR "Cannot modulo integer by string" -#define STRING_VARIANT_MOD_REAL_BOOL "Cannot modulo real by Boolean" +#define STRING_VARIANT_MOD_INT_STR "整数値を文字列で剰余を取ることは出来ません。" +#define STRING_VARIANT_MOD_REAL_BOOL "実数値を論理値で剰余を取ることは出来ません。" #define STRING_VARIANT_MOD_REAL_DUR "Cannot modulo real by duration values" -#define STRING_VARIANT_MOD_REAL_DATE "Cannot modulo real numbers by dates" -#define STRING_VARIANT_MOD_REAL_STR "Cannot modulo real numbers by strings" +#define STRING_VARIANT_MOD_REAL_DATE "実数値を日付で剰余を取ることは出来ません。" +#define STRING_VARIANT_MOD_REAL_STR "実数値を文字列で剰余を取ることは出来ません。" #define STRING_VARIANT_MOD_STR "Cannot modulo string values" -#define STRING_VARIANT_MOD_UNKNOWN "Cannot modulo unknown type" -#define STRING_VARIANT_MOD_ZERO "Cannot modulo zero" -#define STRING_VARIANT_RENDER_UNK "不明なタイプは描画できません。" +#define STRING_VARIANT_MOD_ZERO "零で剰余を取ることは出来ません。" #define STRING_VARIANT_SQRT_NEG "負の数は平方根を計算できません。" -#define STRING_VARIANT_COERCE_UNK "Cannot coerce data either to or from an unknown type" // Dates // @@ -183,7 +173,7 @@ // columns/Col* #define STRING_COLUMN_BAD_NAME "認識できないカラム名 '{1}'。" -#define STRING_COLUMN_BAD_FORMAT "Unrecognized column format '{1}.{2}'" +#define STRING_COLUMN_BAD_FORMAT "認識出来ないカラム形式 '{1}.{2}'" #define STRING_COLUMN_LABEL_TASKS "Tasks" #define STRING_COLUMN_LABEL_DEP "Depends" #define STRING_COLUMN_LABEL_DEP_S "Dep" @@ -240,6 +230,16 @@ #define STRING_COLUMN_LABEL_UDACOUNT "Usage Count" #define STRING_COLUMN_LABEL_ORPHAN "Orphan UDA" +#define STRING_COLUMN_LABEL_COMMAND "Command" +#define STRING_COLUMN_LABEL_CATEGORY "Category" +#define STRING_COLUMN_LABEL_RO "R/W" +#define STRING_COLUMN_LABEL_SHOWS_ID "ID" +#define STRING_COLUMN_LABEL_GC "GC" +#define STRING_COLUMN_LABEL_CONTEXT "Context" +#define STRING_COLUMN_LABEL_FILTER "Filter" +#define STRING_COLUMN_LABEL_MODS "Mods" +#define STRING_COLUMN_LABEL_MISC "Misc" + // Column Examples #define STRING_COLUMN_EXAMPLES_TAGS "home @chore next" #define STRING_COLUMN_EXAMPLES_PROJ "home.garden" @@ -267,11 +267,14 @@ #define STRING_CMD_URGENCY_USAGE "Displays the urgency measure of a task" #define STRING_CMD_URGENCY_RESULT "task {1} urgency {2}" #define STRING_CMD_ADD_USAGE "新しいタスクの追加" -#define STRING_CMD_ADD_FEEDBACK "task {1} が生成されました。" +#define STRING_CMD_ADD_FEEDBACK "タスク {1} が生成されました。" #define STRING_CMD_LOG_USAGE "Adds a new task that is already completed" #define STRING_CMD_LOG_NO_RECUR "You cannot log recurring tasks." -#define STRING_CMD_LOG_NO_WAITING "保留のtaskはログできません。" -#define STRING_CMD_LOG_LOGGED "Logged task." +#define STRING_CMD_LOG_NO_WAITING "保留のタスクはログできません。" + +//#define STRING_CMD_LOG_LOGGED "Logged task {1}." +#define STRING_CMD_LOG_LOGGED "Logged task {1}." + #define STRING_CMD_IDS_USAGE_RANGE "Shows the IDs of matching tasks, as a range" #define STRING_CMD_IDS_USAGE_LIST "Shows the IDs of matching tasks, in the form of a list" #define STRING_CMD_IDS_USAGE_ZSH "Shows the IDs and descriptions of matching tasks" @@ -280,7 +283,7 @@ #define STRING_CMD_UUIDS_USAGE_RANGE "Shows the UUIDs of matching tasks, as a comma-separated list" #define STRING_CMD_UUIDS_USAGE_LIST "Shows the UUIDs of matching tasks, as a list" #define STRING_CMD_UUIDS_USAGE_ZSH "Shows the UUIDs and descriptions of matching tasks" -#define STRING_CMD_EXPORT_USAGE "JSON 形式で task をエクスポート" +#define STRING_CMD_EXPORT_USAGE "JSON 形式で タスク をエクスポート" #define STRING_CMD_INFO_USAGE "すべてのデータとメタデータを表示" #define STRING_CMD_INFO_BLOCKED "This task blocked by" #define STRING_CMD_INFO_BLOCKING "This task is blocking" @@ -289,8 +292,7 @@ #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 "task データベース情報を表示" +#define STRING_CMD_STATS_USAGE "タスク データベース情報を表示" #define STRING_CMD_STATS_CATEGORY "Category" #define STRING_CMD_STATS_DATA "Data" #define STRING_CMD_STATS_TOTAL "Total" @@ -301,8 +303,8 @@ #define STRING_CMD_STATS_UNDO_TXNS "Undo transactions" #define STRING_CMD_STATS_BACKLOG "Sync backlog transactions" #define STRING_CMD_STATS_TAGGED "Tasks tagged" -#define STRING_CMD_STATS_OLDEST "最古の task" -#define STRING_CMD_STATS_NEWEST "最新の task" +#define STRING_CMD_STATS_OLDEST "最古の タスク" +#define STRING_CMD_STATS_NEWEST "最新の タスク" #define STRING_CMD_STATS_USED_FOR "Task used for" #define STRING_CMD_STATS_ADD_EVERY "Task added every" #define STRING_CMD_STATS_COMP_EVERY "Task completed every" @@ -310,8 +312,7 @@ #define STRING_CMD_STATS_AVG_PEND "Average time pending" #define STRING_CMD_STATS_DESC_LEN "Average desc length" #define STRING_CMD_STATS_CHARS "{1} 文字" -#define STRING_CMD_STATS_LAST_SYNC "Last server synchronization" -#define STRING_CMD_STATS_BLOCKED "Blocked tasks" +#define STRING_CMD_STATS_BLOCKED "ブロックされたタスク" #define STRING_CMD_STATS_BLOCKING "Blocking tasks" #define STRING_CMD_REPORTS_USAGE "Lists all supported reports" #define STRING_CMD_REPORTS_REPORT "Report" @@ -337,15 +338,18 @@ #define STRING_CMD_GHISTORY_USAGE_A "Shows a graphical report of task history, by year" #define STRING_CMD_GHISTORY_YEAR "Year" #define STRING_CMD_GHISTORY_MONTH "Month" -#define STRING_CMD_GHISTORY_NUMBER "Number Added/Completed/Deleted" +#define STRING_CMD_GHISTORY_NUMBER "追加/完了/削除されたタスク数" +#define STRING_CMD_UNIQUE_USAGE "Generates lists of unique attribute values" +#define STRING_CMD_UNIQUE_MISSING "An attribute must be specified. See 'task _columns'." +#define STRING_CMD_UNIQUE_VALID "You must specify an attribute or UDA." #define STRING_CMD_DONE_USAGE "Marks the specified task as completed" -#define STRING_CMD_DONE_CONFIRM "task {1} '{2}' を完了?" -#define STRING_CMD_DONE_TASK "完了した task {1} '{2}'." -#define STRING_CMD_DONE_NO "Task は完了しなかった。" +#define STRING_CMD_DONE_CONFIRM "タスク {1} '{2}' を完了?" +#define STRING_CMD_DONE_TASK "タスク {1} '{2}' を完了します。" +#define STRING_CMD_DONE_NO "タスク は完了しなかった。" #define STRING_CMD_DONE_NOTPEND "Task {1} '{2}' is neither pending nor waiting." -#define STRING_CMD_DONE_1 "完了した {1} task。" -#define STRING_CMD_DONE_N "完了した {1} task。" +#define STRING_CMD_DONE_1 "{1} task を完了。" +#define STRING_CMD_DONE_N "{1} task を完了。" #define STRING_CMD_PROJECTS_USAGE "Shows all project names used" #define STRING_CMD_PROJECTS_USAGE_2 "Shows only a list of all project names used" @@ -361,9 +365,10 @@ #define STRING_CMD_SUMMARY_AVG_AGE "Avg age" #define STRING_CMD_SUMMARY_COMPLETE "Complete" #define STRING_CMD_SUMMARY_NONE "(none)" -#define STRING_CMD_COUNT_USAGE "Counts matching tasks" +#define STRING_CMD_COUNT_USAGE "一致した タスク をカウント" #define STRING_CMD_GET_USAGE "DOM Accessor" #define STRING_CMD_GET_NO_DOM "No DOM reference specified." +#define STRING_CMD_GET_BAD_REF "'{1}' is not a DOM reference." #define STRING_CMD_UDAS_NO "UDAが一つも定義されていません。" #define STRING_CMD_UDAS_SUMMARY "{1} UDA が定義されました。" @@ -371,49 +376,49 @@ #define STRING_CMD_UDAS_ORPHAN "{1} Orphan UDA" #define STRING_CMD_UDAS_ORPHANS "{1} Orphan UDAs" -#define STRING_CMD_DELETE_USAGE "指定されたtaskの削除" -#define STRING_CMD_DELETE_CONFIRM "完全に task {1} '{2}' を削除して良いですか?" -#define STRING_CMD_DELETE_TASK "task {1} '{2}' を削除中。" +#define STRING_CMD_DELETE_USAGE "指定されたタスクの削除" +#define STRING_CMD_DELETE_CONFIRM "完全にタスク {1} '{2}' を削除して良いですか?" +#define STRING_CMD_DELETE_TASK "タスク {1} '{2}' を削除中。" #define STRING_CMD_DELETE_TASK_R "Deleting recurring task {1} '{2}'." #define STRING_CMD_DELETE_CONFIRM_R "This is a recurring task. Do you want to delete all pending recurrences of this same task?" -#define STRING_CMD_DELETE_NO "タスクは削除されませんでした。" -#define STRING_CMD_DELETE_NOT_DEL "Task {1} '{2}' は削除できません。" -#define STRING_CMD_DELETE_1 " {1} task を削除しました。" -#define STRING_CMD_DELETE_N " {1} task を削除しました。" +#define STRING_CMD_DELETE_NO "タスク は削除されませんでした。" +#define STRING_CMD_DELETE_NOT_DEL "タスク {1} '{2}' は削除できません。" +#define STRING_CMD_DELETE_1 " {1} タスク を削除しました。" +#define STRING_CMD_DELETE_N " {1} タスク を削除しました。" #define STRING_CMD_DUPLICATE_USAGE "指定したタスクが重複しています" #define STRING_CMD_DUPLICATE_REC "Note: task {1} was a parent recurring task. The duplicated task is too." #define STRING_CMD_DUPLICATE_NON_REC "Note: task {1} was a recurring task. The duplicated task is not." -#define STRING_CMD_DUPLICATE_CONFIRM "task {1} '{2}' が重複?" -#define STRING_CMD_DUPLICATE_TASK "task {1} '{2}' が重複。" -#define STRING_CMD_DUPLICATE_NO "Task は重複していません。" -#define STRING_CMD_DUPLICATE_1 "重複した {1} task。" -#define STRING_CMD_DUPLICATE_N "重複した {1} task。" +#define STRING_CMD_DUPLICATE_CONFIRM "タスク {1} '{2}' が重複?" +#define STRING_CMD_DUPLICATE_TASK "タスク {1} '{2}' が重複。" +#define STRING_CMD_DUPLICATE_NO "タスク は重複していません。" +#define STRING_CMD_DUPLICATE_1 "重複した {1} タスク。" +#define STRING_CMD_DUPLICATE_N "重複した {1} タスク。" #define STRING_CMD_START_USAGE "Marks specified task as started" -#define STRING_CMD_START_NO "Task は開始していません。" -#define STRING_CMD_START_ALREADY "Task {1} '{2}' は既に開始しています。" -#define STRING_CMD_START_TASK "task {1} '{2}' を開始。" -#define STRING_CMD_START_CONFIRM "Start task {1} '{2}'?" -#define STRING_CMD_START_1 " {1} task を開始しました。" -#define STRING_CMD_START_N " {1} task を開始しました。" +#define STRING_CMD_START_NO "タスク は開始していません。" +#define STRING_CMD_START_ALREADY "タスク {1} '{2}' は既に開始しています。" +#define STRING_CMD_START_TASK "タスク {1} '{2}' を開始。" +#define STRING_CMD_START_CONFIRM "タスク {1} '{2}' を開始?" +#define STRING_CMD_START_1 " {1} タスク を開始しました。" +#define STRING_CMD_START_N " {1} タスク を開始しました。" #define STRING_CMD_STOP_USAGE "Removes the 'start' time from a task" #define STRING_CMD_STOP_NO "Task は停止できません。" #define STRING_CMD_STOP_ALREADY "Task {1} '{2}' は停止できません。" #define STRING_CMD_STOP_TASK "task {1} '{2}' を停止中。" #define STRING_CMD_STOP_CONFIRM "task {1} '{2}' を停止?" -#define STRING_CMD_STOP_1 "{1} task を停止。" -#define STRING_CMD_STOP_N "{1} task を停止。" +#define STRING_CMD_STOP_1 "{1} タスク を停止。" +#define STRING_CMD_STOP_N "{1} タスク を停止。" #define STRING_CMD_APPEND_USAGE "存在する task 説明文にテキストを追加" -#define STRING_CMD_APPEND_1 "{1} task を追加。" -#define STRING_CMD_APPEND_N "{1} task を追加。" -#define STRING_CMD_APPEND_TASK "task {1} '{2}' を追加中。" +#define STRING_CMD_APPEND_1 "{1} タスク を追加。" +#define STRING_CMD_APPEND_N "{1} タスク を追加。" +#define STRING_CMD_APPEND_TASK "タスク {1} '{2}' を追加中。" #define STRING_CMD_APPEND_TASK_R "Appending to recurring task {1} '{2}'." #define STRING_CMD_APPEND_CONFIRM_R "This is a recurring task. Do you want to append to all pending recurrences of this same task?" -#define STRING_CMD_APPEND_CONFIRM "task {1} '{2}' を追加?" -#define STRING_CMD_APPEND_NO "Task を追加できませんでした。" +#define STRING_CMD_APPEND_CONFIRM "タスク {1} '{2}' を追加?" +#define STRING_CMD_APPEND_NO "タスク を追加できませんでした。" #define STRING_CMD_PREPEND_USAGE "Prepends text to an existing task description" #define STRING_CMD_PREPEND_1 "Prepended {1} task." @@ -424,14 +429,14 @@ #define STRING_CMD_PREPEND_CONFIRM "Prepend to task {1} '{2}'?" #define STRING_CMD_PREPEND_NO "Task not prepended." -#define STRING_CMD_ANNO_USAGE "Adds an annotation to an existing task" +#define STRING_CMD_ANNO_USAGE "既存のタスクに注釈を追加" #define STRING_CMD_ANNO_CONFIRM "Annotate task {1} '{2}'?" -#define STRING_CMD_ANNO_TASK "Annotating task {1} '{2}'." +#define STRING_CMD_ANNO_TASK "タスク{1} に注釈 '{2}' を追加" #define STRING_CMD_ANNO_TASK_R "Annotating recurring task {1} '{2}'." #define STRING_CMD_ANNO_CONFIRM_R "This is a recurring task. Do you want to annotate all pending recurrences of this same task?" #define STRING_CMD_ANNO_NO "Task not annotated." -#define STRING_CMD_ANNO_1 "Annotated {1} task." -#define STRING_CMD_ANNO_N "Annotated {1} tasks." +#define STRING_CMD_ANNO_1 "{1} task に注釈付加." +#define STRING_CMD_ANNO_N "{1} task に注釈付加." #define STRING_CMD_COLUMNS_USAGE "All supported columns and formatting styles" #define STRING_CMD_COLUMNS_NOTE "* Means default format, and therefore optional. For example, 'due' and 'due.formatted' are equivalent." @@ -439,19 +444,19 @@ #define STRING_CMD_COLUMNS_ARGS "You can only specify one search string." #define STRING_CMD_DENO_USAGE "Deletes an annotation" -#define STRING_CMD_DENO_NONE "The specified task has no annotations that can be deleted." -#define STRING_CMD_DENO_CONFIRM "Denotate task {1} '{2}'?" -#define STRING_CMD_DENO_FOUND "Found annotation '{1}' and deleted it." -#define STRING_CMD_DENO_NOMATCH "Did not find any matching annotation to be deleted for '{1}'." +#define STRING_CMD_DENO_NONE "指定されたtaskには注釈がないので削除できません。" +#define STRING_CMD_DENO_CONFIRM "タスク {1} から注釈 '{2}' を削除しますか?" +#define STRING_CMD_DENO_FOUND "注釈 '{1}' が見つかったので削除します。" +#define STRING_CMD_DENO_NOMATCH "'{1}' に一致する注釈が見つからなかったので削除できません。" #define STRING_CMD_DENO_NO "Task not denotated." #define STRING_CMD_DENO_1 "Denotated {1} task." #define STRING_CMD_DENO_N "Denotated {1} tasks." #define STRING_CMD_IMPORT_USAGE "JSON ファイルをインポート" #define STRING_CMD_IMPORT_SUMMARY "{1} task をインポートしました。" -#define STRING_CMD_IMPORT_NOFILE "インポートするファイルを指定してください。" #define STRING_CMD_IMPORT_FILE "'{1}' をインポート中" #define STRING_CMD_IMPORT_MISSING "ファイル '{1}' が見つかりません。" +#define STRING_CMD_IMPORT_UUID_BAD "Not a valid UUID '{1}'." #define STRING_TASK_NO_DESC "Annotation is missing a description: {1}" #define STRING_TASK_NO_ENTRY "Annotation is missing an entry date: {1}" #define STRING_CMD_SYNC_USAGE "Taskserver とデータを同期" @@ -511,22 +516,22 @@ #define STRING_CMD_DIAG_HOOK_ENABLE "Enabled" #define STRING_CMD_DIAG_HOOK_DISABLE "Disabled" +#define STRING_CMD_COMMANDS_USAGE "Generates a list of all commands, with behavior details" #define STRING_CMD_HCOMMANDS_USAGE "Generates a list of all commands, for autocompletion purposes" #define STRING_CMD_ZSHCOMMANDS_USAGE "Generates a list of all commands, for zsh autocompletion purposes" #define STRING_CMD_ZSHATTS_USAGE "Generates a list of all attributes, for zsh autocompletion purposes" #define STRING_CMD_ALIASES_USAGE "Generates a list of all aliases, for autocompletion purposes" -#define STRING_CMD_INSTALL_USAGE "Installs extensions and external scripts" #define STRING_CMD_MODIFY_USAGE1 "Modifies the existing task with provided arguments." #define STRING_CMD_MODIFY_NO_DUE "You cannot specify a recurring task without a due date." #define STRING_CMD_MODIFY_REM_DUE "You cannot remove the due date from a recurring task." #define STRING_CMD_MODIFY_REC_ALWAYS "You cannot remove the recurrence from a recurring task." -#define STRING_CMD_MODIFY_TASK "Modifying task {1} '{2}'." +#define STRING_CMD_MODIFY_TASK "タスク {1} '{2}' を変更します。" #define STRING_CMD_MODIFY_TASK_R "Modifying recurring task {1} '{2}'." -#define STRING_CMD_MODIFY_1 "Modified {1} task." -#define STRING_CMD_MODIFY_N "Modified {1} tasks." -#define STRING_CMD_MODIFY_NO "Task not modified." -#define STRING_CMD_MODIFY_CONFIRM "Modify task {1} '{2}'?" +#define STRING_CMD_MODIFY_1 "{1} タスク を変更。" +#define STRING_CMD_MODIFY_N "{1} タスク を変更。" +#define STRING_CMD_MODIFY_NO "タスク は変更されませんでした。" +#define STRING_CMD_MODIFY_CONFIRM "タスク {1} '{2}' を変更しますか?" #define STRING_CMD_MODIFY_RECUR "This is a recurring task. Do you want to modify all pending recurrences of this same task?" #define STRING_CMD_MODIFY_NEED_TEXT "Additional text must be provided." @@ -554,7 +559,7 @@ #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_SUCC "Context '{1}' defined. Use 'task context {1}' to activate." #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." @@ -585,6 +590,7 @@ #define STRING_CMD_BURN_USAGE_D "Shows a graphical burndown chart, by day" #define STRING_CMD_BURN_TITLE "Burndown" #define STRING_CMD_BURN_TOO_SMALL "Terminal window too small to draw a graph." +#define STRING_CMD_BURN_TOO_LARGE "Terminal window too large to draw a graph." #define STRING_CMD_BURN_DAILY "Daily" #define STRING_CMD_BURN_WEEKLY "Weekly" #define STRING_CMD_BURN_MONTHLY "Monthly" @@ -603,19 +609,19 @@ #define STRING_CMD_CAL_LABEL_HOL "Holiday" #define STRING_CMD_CAL_SUN_MON "'weekstart' 設定変数は 'Sunday' または 'Monday' のみが使えます。" #define STRING_CMD_EDIT_USAGE "task を直接変更するためにエディタを起動します" -#define STRING_CMD_CALC_USAGE "Calculator" +#define STRING_CMD_CALC_USAGE "電卓" // Config #define STRING_CONFIG_OVERNEST "構成ファイルのネストが10以上になっています - これは間違いです。" #define STRING_CONFIG_READ_INCLUDE "インクルードファイル '{1}' が読み込めません。" #define STRING_CONFIG_INCLUDE_PATH "Can only include files with absolute paths, not '{1}'" #define STRING_CONFIG_BAD_ENTRY "Malformed entry '{1}' in config file." -#define STRING_CONFIG_BAD_WRITE "Could not write to '{1}'." +#define STRING_CONFIG_BAD_WRITE "'{1}' へ書き込みできません。" #define STRING_CONFIG_DEPRECATED_COL "Your .taskrc file contains reports with deprecated columns. Please check for entry_time, start_time or end_time in:" #define STRING_CONFIG_DEPRECATED_VAR "Your .taskrc file contains variables that are deprecated:" // Context -#define STRING_CONTEXT_CREATE_RC "A configuration file could not be found in {1}\n\nWould you like a sample {2} created, so taskwarrior can proceed?" +#define STRING_CONTEXT_CREATE_RC "設定ファイルが {1} 中で見つけられませんでした。\n\nサンプルの {2} を作って taskwarrior が処理できるようにして良いですか?" #define STRING_CONTEXT_NEED_RC "Cannot proceed without rc file." #define STRING_CONTEXT_RC_OVERRIDE "TASKRC override: {1}" #define STRING_CONTEXT_DATA_OVERRIDE "TASKDATA override: {1}" @@ -624,47 +630,26 @@ #define STRING_DATE_INVALID_FORMAT "'{1}' is not a valid date in the '{2}' format." #define STRING_DATE_BAD_WEEKSTART "The 'weekstart' configuration variable may only contain 'Sunday' or 'Monday'." -#define STRING_DATE_JANUARY_LONG "january" -#define STRING_DATE_FEBRUARY_LONG "february" -#define STRING_DATE_MARCH_LONG "march" -#define STRING_DATE_APRIL_LONG "april" -#define STRING_DATE_MAY_LONG "may" -#define STRING_DATE_JUNE_LONG "june" -#define STRING_DATE_JULY_LONG "july" -#define STRING_DATE_AUGUST_LONG "august" -#define STRING_DATE_SEPTEMBER_LONG "september" -#define STRING_DATE_OCTOBER_LONG "october" -#define STRING_DATE_NOVEMBER_LONG "november" -#define STRING_DATE_DECEMBER_LONG "december" - -#define STRING_DATE_JANUARY_SHORT "jan" -#define STRING_DATE_FEBRUARY_SHORT "feb" -#define STRING_DATE_MARCH_SHORT "mar" -#define STRING_DATE_APRIL_SHORT "apr" -#define STRING_DATE_MAY_SHORT "may" -#define STRING_DATE_JUNE_SHORT "jun" -#define STRING_DATE_JULY_SHORT "jul" -#define STRING_DATE_AUGUST_SHORT "aug" -#define STRING_DATE_SEPTEMBER_SHORT "sep" -#define STRING_DATE_OCTOBER_SHORT "oct" -#define STRING_DATE_NOVEMBER_SHORT "nov" -#define STRING_DATE_DECEMBER_SHORT "dec" - -#define STRING_DATE_SUNDAY_LONG "sunday" -#define STRING_DATE_MONDAY_LONG "monday" -#define STRING_DATE_TUESDAY_LONG "tuesday" -#define STRING_DATE_WEDNESDAY_LONG "wednesday" -#define STRING_DATE_THURSDAY_LONG "thursday" -#define STRING_DATE_FRIDAY_LONG "friday" -#define STRING_DATE_SATURDAY_LONG "saturday" - -#define STRING_DATE_SUNDAY_SHORT "sun" -#define STRING_DATE_MONDAY_SHORT "mon" -#define STRING_DATE_TUESDAY_SHORT "tue" -#define STRING_DATE_WEDNESDAY_SHORT "wed" -#define STRING_DATE_THURSDAY_SHORT "thu" -#define STRING_DATE_FRIDAY_SHORT "fri" -#define STRING_DATE_SATURDAY_SHORT "sat" +#define STRING_DATE_JANUARY "january" +#define STRING_DATE_FEBRUARY "february" +#define STRING_DATE_MARCH "march" +#define STRING_DATE_APRIL "april" +#define STRING_DATE_MAY "may" +#define STRING_DATE_JUNE "june" +#define STRING_DATE_JULY "july" +#define STRING_DATE_AUGUST "august" +#define STRING_DATE_SEPTEMBER "september" +#define STRING_DATE_OCTOBER "october" +#define STRING_DATE_NOVEMBER "november" +#define STRING_DATE_DECEMBER "december" + +#define STRING_DATE_SUNDAY "sunday" +#define STRING_DATE_MONDAY "monday" +#define STRING_DATE_TUESDAY "tuesday" +#define STRING_DATE_WEDNESDAY "wednesday" +#define STRING_DATE_THURSDAY "thursday" +#define STRING_DATE_FRIDAY "friday" +#define STRING_DATE_SATURDAY "saturday" // dependency #define STRING_DEPEND_BLOCKED "Task {1} is blocked by:" @@ -674,19 +659,19 @@ // DOM #define STRING_DOM_UNKNOWN "" #define STRING_DOM_UNREC "DOM: Cannot get unrecognized name '{1}'." -#define STRING_DOM_CANNOT_SET "DOM: Cannot set '{1}'." // Eval #define STRING_EVAL_NO_EXPRESSION "No expression to evaluate." #define STRING_EVAL_UNSUPPORTED "Unsupported operator '{1}'." #define STRING_EVAL_OP_EXPECTED "Operator expected." -#define STRING_EVAL_NO_EVAL "The expression could not be evaluated." +#define STRING_EVAL_NO_EVAL "式を評価出来ません。" #define STRING_PAREN_MISMATCH "Mismatched parentheses in expression" // edit #define STRING_EDIT_NO_CHANGES "No edits were detected." -#define STRING_EDIT_NO_EDITS "No editing performed." +#define STRING_EDIT_FAILED "Editing failed with exit code {1}." #define STRING_EDIT_COMPLETE "Editing complete." +#define STRING_EDIT_IN_PROGRESS "Task is already being edited." #define STRING_EDIT_LAUNCHING "Launching '{1}' now..." #define STRING_EDIT_CHANGES "Edits were detected." #define STRING_EDIT_UNPARSEABLE "Taskwarrior couldn't handle your edits. Would you like to try again?" @@ -755,7 +740,7 @@ #define STRING_ERROR_PREFIX "エラー: " #define STRING_UNKNOWN_ERROR "不明なエラー。" #define STRING_TRIVIAL_INPUT "変更したいコマンドまたはタスクを指定しなければなりません。" -#define STRING_ASSUME_INFO "No command specified - assuming 'information'." +#define STRING_ASSUME_INFO "コマンドが指定されていません - 'information' を仮定します。" #define STRING_INFINITE_LOOP "Terminated substitution because more than {1} changes were made - infinite loop protection." #define STRING_UDA_TYPE "User defined attributes may only be of type 'string', 'date', 'duration' or 'numeric'." #define STRING_UDA_TYPE_MISSING "uda.{1}.type not found. The UDA '{1}' must have a type specified." @@ -763,13 +748,16 @@ #define STRING_UDA_COLLISION "The UDA named '{1}' is the same as a core attribute, and is not permitted." #define STRING_INVALID_MOD "The '{1}' attribute does not allow a value of '{2}'." #define STRING_INVALID_SORT_COL "The '{1}' column is not a valid sort field." -#define STRING_TLS_INIT_FAIL "Error initializing TLS. {1}" +#define STRING_TLS_INIT_FAIL "TLS初期化でエラー。 {1}" #define STRING_ERROR_DETAILS "The setting 'calendar.details.report' must contain a single report name." +#define STRING_ERROR_NO_FILTER "Command line filters are not supported by this command." +#define STRING_ERROR_CONFIRM_SIGINT "Interrupted: No changes made." +#define STRING_ERROR_BAD_STATUS "The status '{1}' is not valid." // Feedback #define STRING_FEEDBACK_NO_TASKS "タスクがない。" -#define STRING_FEEDBACK_NO_TASKS_SP "No tasks specified." -#define STRING_FEEDBACK_NO_MATCH "一致したものはない。" +#define STRING_FEEDBACK_NO_TASKS_SP "タスクが1つも指定されていません。" +#define STRING_FEEDBACK_NO_MATCH "一致したものはありません。" #define STRING_FEEDBACK_TASKS_SINGLE "(1 タスク)" #define STRING_FEEDBACK_TASKS_PLURAL "({1} タスク)" #define STRING_FEEDBACK_DELETED "{1} will be deleted." @@ -793,6 +781,7 @@ #define STRING_FEEDBACK_TAG_NONAG "The 'nonag' special tag will prevent nagging when this task is modified." #define STRING_FEEDBACK_TAG_NOCAL "The 'nocal' special tag will keep this task off the 'calendar' report." #define STRING_FEEDBACK_TAG_NEXT "The 'next' special tag will boost the urgency of this task so it appears on the 'next' report." +#define STRING_FEEDBACK_TAG_VIRTUAL "Virtual tags (including '{1}') are reserved and may not be added or removed." #define STRING_FEEDBACK_UNBLOCKED "Unblocked {1} '{2}'." #define STRING_FEEDBACK_EXPIRED "Task {1} '{2}' expired and was deleted." #define STRING_FEEDBACK_BACKLOG "There are local changes. Sync required." @@ -863,7 +852,7 @@ #define STRING_TASK_VALID_BEFORE "Warning: You have specified that the '{1}' date is after the '{2}' date." #define STRING_TASK_VALID_REC_DUE "A recurring task must also have a 'due' date." #define STRING_TASK_VALID_RECUR "The recurrence value '{1}' is not valid." -#define STRING_TASK_SAFETY_VALVE "This command has no filter, and will modify all tasks. Are you sure?" +#define STRING_TASK_SAFETY_VALVE "このコマンドにはフィルタが設定されていないため全タスクが変更されます。よいですか?" #define STRING_TASK_SAFETY_FAIL "コマンドの実行は中止された。" #define STRING_TASK_SAFETY_ALLOW "You did not specify a filter, and with the 'allow.empty.filter' value, no action is taken." #define STRING_TASK_INVALID_DUR "The duration value '{1}' is not supported." @@ -888,6 +877,10 @@ #define STRING_TDB2_UNDO_COMPLETE "Undo complete." #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}" +#define STRING_TDB2_UNWAIT "Un-waiting task '{1}'" + +// recur.cpp +#define STRING_RECUR_CREATE "Creating recurring task instance '{1}'" // View #define STRING_VIEW_TOO_SMALL "The report has a minimum width of {1} and does not fit in the available width of {2}." @@ -895,7 +888,7 @@ // Usage text. This is an exception, and contains \n characters and formatting. #define STRING_CMD_HELP_TEXT \ "Taskwarrior のドキュメンテーションは、'man task', 'man taskrc', 'man " \ - "task-color', 'man task-sync または http://taskwarrior.org にあります。\n" \ + "task-color', 'man task-sync' または http://taskwarrior.org にあります。\n" \ "\n" \ "一般的なコマンド形式は以下の通りです:\n" \ " task [] []\n" \ @@ -945,21 +938,27 @@ " end: タスク完了/削除日" \ " start: タスク開始日\n" \ " scheduled: タスク開始をスケジュールした日\n" \ + " modified: Date task was last modified\n" \ " depends: このタスクが依存する他のタスク\n" \ "\n" \ "属性修飾子はフィルタの効果をより正確にします。使える変更子は以下の通りです:\n" \ - " before (同義語は under, below)\n" \ - " after (同義語は over, above)\n" \ - " none\n" \ - " any\n" \ - " is (同義語は equals)\n" \ - " isnt (同義語は not)\n" \ - " has (同義語は contains)\n" \ - " hasnt\n" \ - " startswith (同義語は left)\n" \ - " endswith (同義語は right)\n" \ - " word\n" \ - " noword\n" \ + "\n" \ + " Modifiers Example Equivalent Meaning\n" \ + " ---------------- ----------------- ------------------- -------------------------\n" \ + " due:today due = today Fuzzy match\n" \ + " not due.not:today due != today Fuzzy non-match\n" \ + " before, below due.before:today due < tomorrow Exact date comparison\n" \ + " after, above due.after:today due > tomorrow Exact date comparison\n" \ + " none project.none: project == '' Empty\n" \ + " any project.any: project !== '' Not empty\n" \ + " is, equals project.is:x project == x Exact match\n" \ + " isnt project.isnt:x project !== x Exact non-match\n" \ + " has, contains desc.has:Hello desc ~ Hello Pattern match\n" \ + " hasnt, desc.hasnt:Hello desc !~ Hello Pattern non-match\n" \ + " startswith, left desc.left:Hel desc ~ '^Hel' Beginning match\n" \ + " endswith, right desc.right:llo desc ~ 'llo$' End match\n" \ + " word desc.word:Hello desc ~ '\\bHello\\b' Boundaried word match\n" \ + " noword desc.noword:Hello desc !~ '\\bHello\\b' Boundaried word non-match\n" \ "\n" \ "さらに、代数演算もサポートします:\n" \ " and or xor 論理演算子\n" \ diff -Nru task-2.4.4+dfsg/src/l10n/pol-POL.h task-2.5.0+dfsg/src/l10n/pol-POL.h --- task-2.4.4+dfsg/src/l10n/pol-POL.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/l10n/pol-POL.h 2015-10-21 21:18:15.000000000 +0000 @@ -105,9 +105,9 @@ #define STRING_PARSER_ALIAS_NEST "Limit {1} zagnieżdżonych aliasów osiągnięty" #define STRING_PARSER_OVERRIDE_RC "Nadpisanie konfiguracji rc.{1}:{2}" #define STRING_PARSER_UNKNOWN_ATTMOD "Błąd: nierozpoznany atrybut '{1}'." -#define STRING_PARSER_UUID_AFTER_COMMA "Nierozpoznany UUID po przecinku." #define STRING_PARSER_ALTERNATE_RC "Wczytanie alternatywnego pliku .taskrc {1}" #define STRING_PARSER_ALTERNATE_DATA "Alternatywne data.location {1}" +#define STRING_PARSER_UNEXPECTED_ARG "The '{1}' command does not allow '{2}'." // Variant // @@ -115,22 +115,16 @@ // mostly concerned with how various operators interact with the different // data types. #define STRING_VARIANT_TIME_T "Nie można utworzyć tego typu z wartością time_t." -#define STRING_VARIANT_CMP_UNKNOWN "Nie można porównać nieznanych typów" -#define STRING_VARIANT_EQ_UNKNOWN "Nie można powiązać nieznanych typów" -#define STRING_VARIANT_EXP_UNKNOWN "Nie można potęgować nieznanych typów" #define STRING_VARIANT_EXP_BOOL "Nie można potęgować wartości Boolowskich" #define STRING_VARIANT_EXP_NON_INT "Nie można potęgować z wykłanikiem nie numerycznym" #define STRING_VARIANT_EXP_STRING "Nie można potęgować ciągów znaków" #define STRING_VARIANT_EXP_DATE "Nie można potęgować dat" #define STRING_VARIANT_EXP_DURATION "Nie można potęgować okresów" -#define STRING_VARIANT_SUB_UNKNOWN "Nie można odejmować nieznanch typów" #define STRING_VARIANT_SUB_BOOL "Nie można odejmować od wartości Boolowskich" #define STRING_VARIANT_SUB_STRING "Nie można odejmować ciągów znaków" #define STRING_VARIANT_SUB_DATE "Nie można odejmować dat" -#define STRING_VARIANT_ADD_UNKNOWN "Nie można sumować nieznanch typów" #define STRING_VARIANT_ADD_BOOL "Nie można sumować wartości Boolowskich" #define STRING_VARIANT_ADD_DATE "Nie można sumować dat" -#define STRING_VARIANT_MUL_UNKNOWN "Nie można mnożyć nieznanch typów" #define STRING_VARIANT_MUL_BOOL "Nie można mnożyć wartości Boolowskich" #define STRING_VARIANT_MUL_DATE "Nie można mnożyć dat" #define STRING_VARIANT_MUL_REAL_STR "Nie można mnożyć wartości rzeczywistych przez ciągi" @@ -141,7 +135,6 @@ #define STRING_VARIANT_MUL_DUR_STR "Nie można mnożyć okresu przez ciąg" #define STRING_VARIANT_MUL_DUR_DATE "Nie można mnożyć okresu przez datę" #define STRING_VARIANT_MUL_DUR_DUR "Nie można mnożyć okresu przez okres" -#define STRING_VARIANT_DIV_UNKNOWN "Nie można dzielić nieznanch typów" #define STRING_VARIANT_DIV_BOOL "Nie można dzielić wartości Boolowskich" #define STRING_VARIANT_DIV_INT_BOOL "Nie można dzielić liczb przez wartości Boolowskie" #define STRING_VARIANT_DIV_ZERO "Nie można dzielić przez zero" @@ -166,11 +159,8 @@ #define STRING_VARIANT_MOD_REAL_DATE "Nie można uzyskać modulo z wartości rzeczywistych przez datę" #define STRING_VARIANT_MOD_REAL_STR "Nie można uzyskać modulo z wartości rzeczywistych przez ciąg" #define STRING_VARIANT_MOD_STR "Nie można uzyskać modulo z ciągów" -#define STRING_VARIANT_MOD_UNKNOWN "Nie można uzyskać modulo z nieznanych typów" #define STRING_VARIANT_MOD_ZERO "Nie można uzyskać modulo z zera" -#define STRING_VARIANT_RENDER_UNK "Nie można wypisać wartości nieznanego typu." #define STRING_VARIANT_SQRT_NEG "Nie można wyciągnąć pierwiastka kwadratowego z wartości ujemnej." -#define STRING_VARIANT_COERCE_UNK "Nie można rzutować danych z/na nieznaney typ" // Dates // @@ -240,6 +230,16 @@ #define STRING_COLUMN_LABEL_UDACOUNT "Licznik Użycia" #define STRING_COLUMN_LABEL_ORPHAN "Osierocone UDA" +#define STRING_COLUMN_LABEL_COMMAND "Command" +#define STRING_COLUMN_LABEL_CATEGORY "Category" +#define STRING_COLUMN_LABEL_RO "R/W" +#define STRING_COLUMN_LABEL_SHOWS_ID "ID" +#define STRING_COLUMN_LABEL_GC "GC" +#define STRING_COLUMN_LABEL_CONTEXT "Context" +#define STRING_COLUMN_LABEL_FILTER "Filter" +#define STRING_COLUMN_LABEL_MODS "Mods" +#define STRING_COLUMN_LABEL_MISC "Misc" + // Column Examples #define STRING_COLUMN_EXAMPLES_TAGS "home @chore next" #define STRING_COLUMN_EXAMPLES_PROJ "dom.ogród" @@ -271,7 +271,10 @@ #define STRING_CMD_LOG_USAGE "Dodaje nowe, ukończone zadanie" #define STRING_CMD_LOG_NO_RECUR "Nie możesz logować zadania cyklicznego." #define STRING_CMD_LOG_NO_WAITING "Nie możesz logować zadania czekającego." -#define STRING_CMD_LOG_LOGGED "Zadanie w logu." + +//#define STRING_CMD_LOG_LOGGED "Zadanie w logu." +#define STRING_CMD_LOG_LOGGED "Logged task {1}." + #define STRING_CMD_IDS_USAGE_RANGE "Pokazuje IDki pasujących zadań, w formie zakresu" #define STRING_CMD_IDS_USAGE_LIST "Pokazuje IDki pasujących zadań, w formie listy" #define STRING_CMD_IDS_USAGE_ZSH "Pokazuje IDki i opisy pasujących zadań" @@ -289,7 +292,6 @@ #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ń" #define STRING_CMD_STATS_CATEGORY "Kategoria" #define STRING_CMD_STATS_DATA "Data" @@ -310,7 +312,6 @@ #define STRING_CMD_STATS_AVG_PEND "Średni czas w toku" #define STRING_CMD_STATS_DESC_LEN "Średnia długość opisu" #define STRING_CMD_STATS_CHARS "{1} znaków" -#define STRING_CMD_STATS_LAST_SYNC "Ostatnia synchronizacja z serwerem" #define STRING_CMD_STATS_BLOCKED "Zadania blokowane" #define STRING_CMD_STATS_BLOCKING "Zadania blokujące" #define STRING_CMD_REPORTS_USAGE "Lista wszystkich wspieranych raportów" @@ -338,6 +339,9 @@ #define STRING_CMD_GHISTORY_YEAR "Rok" #define STRING_CMD_GHISTORY_MONTH "Miesiąc" #define STRING_CMD_GHISTORY_NUMBER "Liczba Dodanych/Ukończonych/Usuniętych" +#define STRING_CMD_UNIQUE_USAGE "Generates lists of unique attribute values" +#define STRING_CMD_UNIQUE_MISSING "An attribute must be specified. See 'task _columns'." +#define STRING_CMD_UNIQUE_VALID "You must specify an attribute or UDA." #define STRING_CMD_DONE_USAGE "Oznacza wybrane zadanie jako zakończone" #define STRING_CMD_DONE_CONFIRM "Zakończyć zadanie {1} '{2}'?" @@ -364,6 +368,7 @@ #define STRING_CMD_COUNT_USAGE "Zlicza pasujące zadania" #define STRING_CMD_GET_USAGE "DOM Akcesor" #define STRING_CMD_GET_NO_DOM "Brak zdefiniowanej referencji do DOM." +#define STRING_CMD_GET_BAD_REF "'{1}' is not a DOM reference." #define STRING_CMD_UDAS_NO "Nie zdefiniowano UDA" #define STRING_CMD_UDAS_SUMMARY "{1} zdefiniowane UDA" @@ -449,9 +454,9 @@ #define STRING_CMD_IMPORT_USAGE "Importuje pliki JSON" #define STRING_CMD_IMPORT_SUMMARY "Zaimportowano {1} zadań." -#define STRING_CMD_IMPORT_NOFILE "Musisz podać plik do zaimportowania." #define STRING_CMD_IMPORT_FILE "Importowanie '{1}'" #define STRING_CMD_IMPORT_MISSING "File '{1}' not found." +#define STRING_CMD_IMPORT_UUID_BAD "Not a valid UUID '{1}'." #define STRING_TASK_NO_DESC "Komentarz nie posiada treści: {1}" #define STRING_TASK_NO_ENTRY "Komentarz nie posiada daty utworzenia: {1}" #define STRING_CMD_SYNC_USAGE "Synchronizuje dane z serwerem zadań" @@ -511,11 +516,11 @@ #define STRING_CMD_DIAG_HOOK_ENABLE "Enabled" #define STRING_CMD_DIAG_HOOK_DISABLE "Disabled" +#define STRING_CMD_COMMANDS_USAGE "Generates a list of all commands, with behavior details" #define STRING_CMD_HCOMMANDS_USAGE "Generuje listę wszystkich poleceń dla funkcji autouzupełniania" #define STRING_CMD_ZSHCOMMANDS_USAGE "Generuje listę wszystkich poleceń dla funkcji autouzupełniania w powłoce zsh" #define STRING_CMD_ZSHATTS_USAGE "Generates a list of all attributes, for zsh autocompletion purposes" #define STRING_CMD_ALIASES_USAGE "Generuje listę wszystkich aliasów dla funkcji autouzupełniania" -#define STRING_CMD_INSTALL_USAGE "Instaluje dodatki i zewnętrzne skrypty" #define STRING_CMD_MODIFY_USAGE1 "Modyfikuje istniejące zadanie pod kątem podanych argumentów." #define STRING_CMD_MODIFY_NO_DUE "Nie możesz specyfikować rekurencyjnego zadania bez podania terminu." @@ -554,7 +559,7 @@ #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_SUCC "Context '{1}' defined. Use 'task context {1}' to activate." #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." @@ -585,6 +590,7 @@ #define STRING_CMD_BURN_USAGE_D "Wyświetla dzienny postęp w postaci wykresu." #define STRING_CMD_BURN_TITLE "Postęp" #define STRING_CMD_BURN_TOO_SMALL "Okno terminal jest za małe do wyświetlenia wykresu." +#define STRING_CMD_BURN_TOO_LARGE "Terminal window too large to draw a graph." #define STRING_CMD_BURN_DAILY "Dzienny" #define STRING_CMD_BURN_WEEKLY "Tygodniowy" #define STRING_CMD_BURN_MONTHLY "Miesięczny" @@ -624,47 +630,26 @@ #define STRING_DATE_INVALID_FORMAT "'{1}' nie jest poprawną wartością daty w formacie '{2}'." #define STRING_DATE_BAD_WEEKSTART "Zmienna konfiguracji 'weekstart' może przyjmować tylko wartość 'Sunday' lub 'Monday'." -#define STRING_DATE_JANUARY_LONG "styczeń" -#define STRING_DATE_FEBRUARY_LONG "luty" -#define STRING_DATE_MARCH_LONG "marzec" -#define STRING_DATE_APRIL_LONG "kwiecień" -#define STRING_DATE_MAY_LONG "maj" -#define STRING_DATE_JUNE_LONG "czerwiec" -#define STRING_DATE_JULY_LONG "lipiec" -#define STRING_DATE_AUGUST_LONG "sierpień" -#define STRING_DATE_SEPTEMBER_LONG "wrzesień" -#define STRING_DATE_OCTOBER_LONG "październik" -#define STRING_DATE_NOVEMBER_LONG "listopad" -#define STRING_DATE_DECEMBER_LONG "grudzień" - -#define STRING_DATE_JANUARY_SHORT "sty" -#define STRING_DATE_FEBRUARY_SHORT "lut" -#define STRING_DATE_MARCH_SHORT "mar" -#define STRING_DATE_APRIL_SHORT "kwi" -#define STRING_DATE_MAY_SHORT "maj" -#define STRING_DATE_JUNE_SHORT "cze" -#define STRING_DATE_JULY_SHORT "lip" -#define STRING_DATE_AUGUST_SHORT "sie" -#define STRING_DATE_SEPTEMBER_SHORT "wrz" -#define STRING_DATE_OCTOBER_SHORT "paź" -#define STRING_DATE_NOVEMBER_SHORT "lis" -#define STRING_DATE_DECEMBER_SHORT "gru" - -#define STRING_DATE_SUNDAY_LONG "niedziela" -#define STRING_DATE_MONDAY_LONG "poniedziałek" -#define STRING_DATE_TUESDAY_LONG "wtorek" -#define STRING_DATE_WEDNESDAY_LONG "środa" -#define STRING_DATE_THURSDAY_LONG "czwartek" -#define STRING_DATE_FRIDAY_LONG "piątek" -#define STRING_DATE_SATURDAY_LONG "sobota" - -#define STRING_DATE_SUNDAY_SHORT "nie" -#define STRING_DATE_MONDAY_SHORT "pon" -#define STRING_DATE_TUESDAY_SHORT "wto" -#define STRING_DATE_WEDNESDAY_SHORT "śro" -#define STRING_DATE_THURSDAY_SHORT "czw" -#define STRING_DATE_FRIDAY_SHORT "pią" -#define STRING_DATE_SATURDAY_SHORT "sob" +#define STRING_DATE_JANUARY "styczeń" +#define STRING_DATE_FEBRUARY "luty" +#define STRING_DATE_MARCH "marzec" +#define STRING_DATE_APRIL "kwiecień" +#define STRING_DATE_MAY "maj" +#define STRING_DATE_JUNE "czerwiec" +#define STRING_DATE_JULY "lipiec" +#define STRING_DATE_AUGUST "sierpień" +#define STRING_DATE_SEPTEMBER "wrzesień" +#define STRING_DATE_OCTOBER "październik" +#define STRING_DATE_NOVEMBER "listopad" +#define STRING_DATE_DECEMBER "grudzień" + +#define STRING_DATE_SUNDAY "niedziela" +#define STRING_DATE_MONDAY "poniedziałek" +#define STRING_DATE_TUESDAY "wtorek" +#define STRING_DATE_WEDNESDAY "środa" +#define STRING_DATE_THURSDAY "czwartek" +#define STRING_DATE_FRIDAY "piątek" +#define STRING_DATE_SATURDAY "sobota" // dependency #define STRING_DEPEND_BLOCKED "Zadanie {1} jest blokowane przez:" @@ -674,7 +659,6 @@ // DOM #define STRING_DOM_UNKNOWN "" #define STRING_DOM_UNREC "DOM: Nie mogę pobrać nierozpoznanej nazwy '{1}'." -#define STRING_DOM_CANNOT_SET "DOM: Nie mogę ustawić '{1}'." // Eval #define STRING_EVAL_NO_EXPRESSION "Brak wyrażenia do przetworzenia." @@ -685,8 +669,9 @@ // edit #define STRING_EDIT_NO_CHANGES "Nie znaleziono żadnych edycji." -#define STRING_EDIT_NO_EDITS "Nie wykonano żadnych edycji" +#define STRING_EDIT_FAILED "Editing failed with exit code {1}." #define STRING_EDIT_COMPLETE "Edycja zakończona." +#define STRING_EDIT_IN_PROGRESS "Task is already being edited." #define STRING_EDIT_LAUNCHING "Uruchamianie '{1}'..." #define STRING_EDIT_CHANGES "Zmiany wykryte." #define STRING_EDIT_UNPARSEABLE "Taskwarrior nie może wprowadzić twoich zmian. Czy chcesz spróbować jeszcze raz?" @@ -765,6 +750,9 @@ #define STRING_INVALID_SORT_COL "Kolumna '{1}' nie jest poprawnym parametrem sortowania." #define STRING_TLS_INIT_FAIL "Błąd inicjalizacji TLS." #define STRING_ERROR_DETAILS "Zmienna 'calendar.details.report' musi zawierać nazwę raportu." +#define STRING_ERROR_NO_FILTER "Command line filters are not supported by this command." +#define STRING_ERROR_CONFIRM_SIGINT "Interrupted: No changes made." +#define STRING_ERROR_BAD_STATUS "The status '{1}' is not valid." // Feedback #define STRING_FEEDBACK_NO_TASKS "Brak zadań." @@ -793,6 +781,7 @@ #define STRING_FEEDBACK_TAG_NONAG "Specjalny tag 'nonag' uchroni przed upierdliwością kiedy zadanie jest modyfikowane." #define STRING_FEEDBACK_TAG_NOCAL "Specjalny tag 'nocal' spowoduje nie dodawanie zadania do kalendarza." #define STRING_FEEDBACK_TAG_NEXT "Specjalny tag 'next' podniesie pilność tego zadania co spowoduje wyświetlenie go w raporcie 'next'." +#define STRING_FEEDBACK_TAG_VIRTUAL "Virtual tags (including '{1}') are reserved and may not be added or removed." #define STRING_FEEDBACK_UNBLOCKED "Odblokowane {1} '{2}'." #define STRING_FEEDBACK_EXPIRED "Zadanie {1} '{2}' jest przedawnione i zostało usunięte." #define STRING_FEEDBACK_BACKLOG "Wykryto lokalne zmiany. Wymagana synchronizacja." @@ -888,6 +877,10 @@ #define STRING_TDB2_UNDO_COMPLETE "Operacja cofnięcia zakończona." #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}" +#define STRING_TDB2_UNWAIT "Un-waiting task '{1}'" + +// recur.cpp +#define STRING_RECUR_CREATE "Creating recurring task instance '{1}'" // View #define STRING_VIEW_TOO_SMALL "Raport ma minimalną szerokość {1} i nie mieści się w dostępnej przestrzeni {2}." @@ -945,21 +938,27 @@ " end: Data ukończenia/usunięcia zadania\n" \ " start: Data wystartowania zadania\n" \ " scheduled: Data zaplanowanego startu zadania\n" \ + " modified: Date task was last modified\n" \ " depends: Inne zadania od których zależy dane zadanie\n" \ "\n" \ "Modyfikatory atrybutów zwiększają precyzję filtrów. Dostępne modyfikatory:\n" \ - " before (synonimy pod, poniżej)\n" \ - " after (synonimy nad, powyżej)\n" \ - " none\n" \ - " any\n" \ - " is (synonim równe)\n" \ - " isnt (synonim nierówne)\n" \ - " has (synonim zawiera)\n" \ - " hasnt\n" \ - " startswith (synonim od lewej)\n" \ - " endswith (synonim od prawej)\n" \ - " word\n" \ - " noword\n" \ + "\n" \ + " Modifiers Example Equivalent Meaning\n" \ + " ---------------- ----------------- ------------------- -------------------------\n" \ + " due:today due = today Fuzzy match\n" \ + " not due.not:today due != today Fuzzy non-match\n" \ + " before, below due.before:today due < tomorrow Exact date comparison\n" \ + " after, above due.after:today due > tomorrow Exact date comparison\n" \ + " none project.none: project == '' Empty\n" \ + " any project.any: project !== '' Not empty\n" \ + " is, equals project.is:x project == x Exact match\n" \ + " isnt project.isnt:x project !== x Exact non-match\n" \ + " has, contains desc.has:Hello desc ~ Hello Pattern match\n" \ + " hasnt, desc.hasnt:Hello desc !~ Hello Pattern non-match\n" \ + " startswith, left desc.left:Hel desc ~ '^Hel' Beginning match\n" \ + " endswith, right desc.right:llo desc ~ 'llo$' End match\n" \ + " word desc.word:Hello desc ~ '\\bHello\\b' Boundaried word match\n" \ + " noword desc.noword:Hello desc !~ '\\bHello\\b' Boundaried word non-match\n" \ "\n" \ "Dostępne wyrażenia algebraiczne:\n" \ " and or xor Operatory logiczne\n" \ diff -Nru task-2.4.4+dfsg/src/l10n/por-PRT.h task-2.5.0+dfsg/src/l10n/por-PRT.h --- task-2.4.4+dfsg/src/l10n/por-PRT.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/l10n/por-PRT.h 2015-10-21 21:18:15.000000000 +0000 @@ -105,9 +105,9 @@ #define STRING_PARSER_ALIAS_NEST "Limite de 'alias' em cascata atingido: {1}" #define STRING_PARSER_OVERRIDE_RC "Alteração de configuração rc.{1}:{2}" #define STRING_PARSER_UNKNOWN_ATTMOD "Erro: modificador de atributo não reconhecido '{1}'." -#define STRING_PARSER_UUID_AFTER_COMMA "UUID não reconhecido após a vírgula." #define STRING_PARSER_ALTERNATE_RC "Usando o ficheiro .taskrc alternativo {1}" #define STRING_PARSER_ALTERNATE_DATA "Usando data.location alternativa {1}" +#define STRING_PARSER_UNEXPECTED_ARG "The '{1}' command does not allow '{2}'." // Variant // @@ -115,22 +115,16 @@ // mostly concerned with how various operators interact with the different // data types. #define STRING_VARIANT_TIME_T "Impossível inicializar este tipo com um valor time_t." -#define STRING_VARIANT_CMP_UNKNOWN "Impossível comparar tipo desconhecido" -#define STRING_VARIANT_EQ_UNKNOWN "Impossível equiparar tipo desconhecido" -#define STRING_VARIANT_EXP_UNKNOWN "Impossivel exponenciar tipo desconhecido" #define STRING_VARIANT_EXP_BOOL "Impossível exponenciar booleanos" #define STRING_VARIANT_EXP_NON_INT "Impossível exponenciar a uma potencia não inteira" #define STRING_VARIANT_EXP_STRING "Impossível exponenciar texto" #define STRING_VARIANT_EXP_DATE "Impossível exponenciar datas" #define STRING_VARIANT_EXP_DURATION "Impossível exponenciar durações" -#define STRING_VARIANT_SUB_UNKNOWN "Impossível subtrair tipo desconhecido" #define STRING_VARIANT_SUB_BOOL "Impossível subtrair de um valor booleano" #define STRING_VARIANT_SUB_STRING "Impossível subtrair texto" #define STRING_VARIANT_SUB_DATE "Impossível subtrair uma data" -#define STRING_VARIANT_ADD_UNKNOWN "Impossível somar tipo desconhecido" #define STRING_VARIANT_ADD_BOOL "Impossível somar dois valores booleanos" #define STRING_VARIANT_ADD_DATE "Impossível somar duas datas" -#define STRING_VARIANT_MUL_UNKNOWN "Impossível multiplicar tipo desconhecido" #define STRING_VARIANT_MUL_BOOL "Impossível multiplicar valores booleanos" #define STRING_VARIANT_MUL_DATE "Impossível multiplicar datas" #define STRING_VARIANT_MUL_REAL_STR "Impossível multiplicar números reais por texto" @@ -141,7 +135,6 @@ #define STRING_VARIANT_MUL_DUR_STR "Impossível multiplicar durações por texto" #define STRING_VARIANT_MUL_DUR_DATE "Impossível multiplicar durações por datas" #define STRING_VARIANT_MUL_DUR_DUR "Impossível multiplicar durações por durações" -#define STRING_VARIANT_DIV_UNKNOWN "Impossível dividir tipo desconhecido" #define STRING_VARIANT_DIV_BOOL "Impossível dividir booleano" #define STRING_VARIANT_DIV_INT_BOOL "Impossível dividir inteiros por booleanos" #define STRING_VARIANT_DIV_ZERO "Impossível dividir por zero" @@ -166,11 +159,8 @@ #define STRING_VARIANT_MOD_REAL_DATE "Impossível calcular módulo de reais por datas" #define STRING_VARIANT_MOD_REAL_STR "Impossível calcular módulo de reais por texto" #define STRING_VARIANT_MOD_STR "Impossível calcular módulo de texto" -#define STRING_VARIANT_MOD_UNKNOWN "Impossível calcular módulo tipo desconhecido" #define STRING_VARIANT_MOD_ZERO "Impossível calcular módulo de zero" -#define STRING_VARIANT_RENDER_UNK "Impossível mostrar um tipo desconhecido." #define STRING_VARIANT_SQRT_NEG "Impossível calcular a raiz quadrada de um número negativo." -#define STRING_VARIANT_COERCE_UNK "Impossível converter dados de ou para um tipo desconhecido" // Dates // @@ -241,6 +231,16 @@ #define STRING_COLUMN_LABEL_UDACOUNT "Contagem de Uso" #define STRING_COLUMN_LABEL_ORPHAN "UDA Orfão" +#define STRING_COLUMN_LABEL_COMMAND "Command" +#define STRING_COLUMN_LABEL_CATEGORY "Category" +#define STRING_COLUMN_LABEL_RO "R/W" +#define STRING_COLUMN_LABEL_SHOWS_ID "ID" +#define STRING_COLUMN_LABEL_GC "GC" +#define STRING_COLUMN_LABEL_CONTEXT "Context" +#define STRING_COLUMN_LABEL_FILTER "Filter" +#define STRING_COLUMN_LABEL_MODS "Mods" +#define STRING_COLUMN_LABEL_MISC "Misc" + // Column Examples #define STRING_COLUMN_EXAMPLES_TAGS "casa @contas próxima" #define STRING_COLUMN_EXAMPLES_PROJ "casa.jardim" @@ -271,7 +271,10 @@ #define STRING_CMD_LOG_USAGE "Adiciona uma nova tarefa que já está concluída" #define STRING_CMD_LOG_NO_RECUR "Não pode usar o comando 'log' para tarefas recorrentes." #define STRING_CMD_LOG_NO_WAITING "Não pode usar o comando 'log' para tarefas adiadas." -#define STRING_CMD_LOG_LOGGED "Tarefa registada." + +//#define STRING_CMD_LOG_LOGGED "Tarefa registada." +#define STRING_CMD_LOG_LOGGED "Logged task {1}." + #define STRING_CMD_IDS_USAGE_RANGE "Exibe como intervalo, os IDs das tarefas correspondentes" #define STRING_CMD_IDS_USAGE_LIST "Exibe em formato de lista, os IDs das tarefas correspondentes" #define STRING_CMD_IDS_USAGE_ZSH "Exibe os IDs e descrições das tarefas correspondentes" @@ -289,7 +292,6 @@ #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" #define STRING_CMD_STATS_CATEGORY "Categoria" #define STRING_CMD_STATS_DATA "Dados" @@ -310,7 +312,6 @@ #define STRING_CMD_STATS_AVG_PEND "Tempo médio pendente" #define STRING_CMD_STATS_DESC_LEN "Tamanho médio de descrição" #define STRING_CMD_STATS_CHARS "{1} caracteres" -#define STRING_CMD_STATS_LAST_SYNC "Última sincronização com servidor" #define STRING_CMD_STATS_BLOCKED "Tarefas bloqueadas" #define STRING_CMD_STATS_BLOCKING "Tarefas a bloquear" #define STRING_CMD_REPORTS_USAGE "Lista todos os relatórios suportados" @@ -338,6 +339,9 @@ #define STRING_CMD_GHISTORY_YEAR "Ano" #define STRING_CMD_GHISTORY_MONTH "Mês" #define STRING_CMD_GHISTORY_NUMBER "Número de Adicionadas/Concluídas/Eliminadas" +#define STRING_CMD_UNIQUE_USAGE "Generates lists of unique attribute values" +#define STRING_CMD_UNIQUE_MISSING "An attribute must be specified. See 'task _columns'." +#define STRING_CMD_UNIQUE_VALID "You must specify an attribute or UDA." #define STRING_CMD_DONE_USAGE "Concluí a tarefa indicada" #define STRING_CMD_DONE_CONFIRM "Concluír tarefa {1} '{2}'?" @@ -364,6 +368,7 @@ #define STRING_CMD_COUNT_USAGE "Conta tarefas correspondentes" #define STRING_CMD_GET_USAGE "Método de acesso ao DOM" #define STRING_CMD_GET_NO_DOM "Referência DOM não especificada." +#define STRING_CMD_GET_BAD_REF "'{1}' is not a DOM reference." #define STRING_CMD_UDAS_NO "Nenhum UDA definido." #define STRING_CMD_UDAS_SUMMARY "{1} UDA definido" @@ -449,9 +454,9 @@ #define STRING_CMD_IMPORT_USAGE "Importa ficheiros JSON" #define STRING_CMD_IMPORT_SUMMARY "Importadas {1} tarefas." -#define STRING_CMD_IMPORT_NOFILE "Necessita especificar o ficheiro a importar." #define STRING_CMD_IMPORT_FILE "A importar '{1}'" #define STRING_CMD_IMPORT_MISSING "File '{1}' not found." +#define STRING_CMD_IMPORT_UUID_BAD "Not a valid UUID '{1}'." #define STRING_TASK_NO_DESC "Descrição da anotação em falta: {1}" #define STRING_TASK_NO_ENTRY "Data de entrada da anotação em falta: {1}" #define STRING_CMD_SYNC_USAGE "Sincroniza dados com o Taskserver" @@ -467,7 +472,7 @@ #define STRING_CMD_SYNC_SUCCESS2 "Sincronizado com sucesso. {1} alterações recebidas." #define STRING_CMD_SYNC_SUCCESS3 "Sincronizado com sucesso. {1} alterações enviadas, {2} alterações recebidas." #define STRING_CMD_SYNC_SUCCESS_NOP "Sincronizado com sucesso. Sem alterações." -#define STRING_CMD_SYNC_FAIL_ACCOUNT "Sincronização falhou. As suas credenciais estão incorretas, ou a sua conta no Taskserver não está ativa." +#define STRING_CMD_SYNC_FAIL_ACCOUNT "Sincronização falhou. As suas credenciais estão incorretas ou a sua conta não existe no Taskserver." #define STRING_CMD_SYNC_FAIL_ERROR "Sincronização falhou. O Taskserver devolveu o seguinte erro: {1} {2}" #define STRING_CMD_SYNC_FAIL_CONNECT "Sincronização falhou. Não foi possível contactar ao Taskserver." #define STRING_CMD_SYNC_BAD_SERVER "Sincronização falhou. Erro no parametro de configuração '{1}'" @@ -511,11 +516,11 @@ #define STRING_CMD_DIAG_HOOK_ENABLE "Enabled" #define STRING_CMD_DIAG_HOOK_DISABLE "Disabled" +#define STRING_CMD_COMMANDS_USAGE "Generates a list of all commands, with behavior details" #define STRING_CMD_HCOMMANDS_USAGE "Gera uma lista com todos os comandos, para fins de terminação automática" #define STRING_CMD_ZSHCOMMANDS_USAGE "Gera uma lista com todos os comandos, para terminação automática em zsh" #define STRING_CMD_ZSHATTS_USAGE "Gera uma lista de todos os atributos, para terminação automática em zsh" #define STRING_CMD_ALIASES_USAGE "Gera uma lista com todos os 'alias', para fins de terminação automática" -#define STRING_CMD_INSTALL_USAGE "Instala extensões e scripts externos" #define STRING_CMD_MODIFY_USAGE1 "Modifica a tarefa existente com os argumentos indicados." #define STRING_CMD_MODIFY_NO_DUE "Não pode criar tarefas recorrentes sem uma data de vencimento." @@ -554,7 +559,7 @@ #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_SUCC "Context '{1}' defined. Use 'task context {1}' to activate." #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." @@ -585,6 +590,7 @@ #define STRING_CMD_BURN_USAGE_D "Mostra um gráfico de burndown, por dia" #define STRING_CMD_BURN_TITLE "Burndown" // |por-PRT|==|eng-USA| #define STRING_CMD_BURN_TOO_SMALL "Janela do terminal demasiado pequena para desenhar o gráfico." +#define STRING_CMD_BURN_TOO_LARGE "Terminal window too large to draw a graph." #define STRING_CMD_BURN_DAILY "Diário" #define STRING_CMD_BURN_WEEKLY "Semanal" #define STRING_CMD_BURN_MONTHLY "Mensal" @@ -624,47 +630,26 @@ #define STRING_DATE_INVALID_FORMAT "'{1}' não é uma data válida no formato '{2}'." #define STRING_DATE_BAD_WEEKSTART "A variável de configuração 'weekstart' apenas pode conter 'domingo' ou 'segunda-feira'." -#define STRING_DATE_JANUARY_LONG "janeiro" -#define STRING_DATE_FEBRUARY_LONG "fevereiro" -#define STRING_DATE_MARCH_LONG "março" -#define STRING_DATE_APRIL_LONG "abril" -#define STRING_DATE_MAY_LONG "maio" -#define STRING_DATE_JUNE_LONG "junho" -#define STRING_DATE_JULY_LONG "julho" -#define STRING_DATE_AUGUST_LONG "agosto" -#define STRING_DATE_SEPTEMBER_LONG "setembro" -#define STRING_DATE_OCTOBER_LONG "outubro" -#define STRING_DATE_NOVEMBER_LONG "novembro" -#define STRING_DATE_DECEMBER_LONG "dezembro" - -#define STRING_DATE_JANUARY_SHORT "jan" // |por-PRT|==|eng-USA| -#define STRING_DATE_FEBRUARY_SHORT "fev" -#define STRING_DATE_MARCH_SHORT "mar" // |por-PRT|==|eng-USA| -#define STRING_DATE_APRIL_SHORT "abr" -#define STRING_DATE_MAY_SHORT "mai" -#define STRING_DATE_JUNE_SHORT "jun" // |por-PRT|==|eng-USA| -#define STRING_DATE_JULY_SHORT "jul" // |por-PRT|==|eng-USA| -#define STRING_DATE_AUGUST_SHORT "ago" -#define STRING_DATE_SEPTEMBER_SHORT "set" -#define STRING_DATE_OCTOBER_SHORT "out" -#define STRING_DATE_NOVEMBER_SHORT "nov" // |por-PRT|==|eng-USA| -#define STRING_DATE_DECEMBER_SHORT "dez" - -#define STRING_DATE_SUNDAY_LONG "domingo" -#define STRING_DATE_MONDAY_LONG "segunda-feira" -#define STRING_DATE_TUESDAY_LONG "terça-feira" -#define STRING_DATE_WEDNESDAY_LONG "quarta-feira" -#define STRING_DATE_THURSDAY_LONG "quinta-feira" -#define STRING_DATE_FRIDAY_LONG "sexta-feira" -#define STRING_DATE_SATURDAY_LONG "sábado" - -#define STRING_DATE_SUNDAY_SHORT "dom" -#define STRING_DATE_MONDAY_SHORT "seg" -#define STRING_DATE_TUESDAY_SHORT "ter" -#define STRING_DATE_WEDNESDAY_SHORT "qua" -#define STRING_DATE_THURSDAY_SHORT "qui" -#define STRING_DATE_FRIDAY_SHORT "sex" -#define STRING_DATE_SATURDAY_SHORT "sáb" +#define STRING_DATE_JANUARY "janeiro" +#define STRING_DATE_FEBRUARY "fevereiro" +#define STRING_DATE_MARCH "março" +#define STRING_DATE_APRIL "abril" +#define STRING_DATE_MAY "maio" +#define STRING_DATE_JUNE "junho" +#define STRING_DATE_JULY "julho" +#define STRING_DATE_AUGUST "agosto" +#define STRING_DATE_SEPTEMBER "setembro" +#define STRING_DATE_OCTOBER "outubro" +#define STRING_DATE_NOVEMBER "novembro" +#define STRING_DATE_DECEMBER "dezembro" + +#define STRING_DATE_SUNDAY "domingo" +#define STRING_DATE_MONDAY "segunda-feira" +#define STRING_DATE_TUESDAY "terça-feira" +#define STRING_DATE_WEDNESDAY "quarta-feira" +#define STRING_DATE_THURSDAY "quinta-feira" +#define STRING_DATE_FRIDAY "sexta-feira" +#define STRING_DATE_SATURDAY "sábado" // dependency #define STRING_DEPEND_BLOCKED "Tarefa {1} encontra-se bloqueada por:" @@ -674,7 +659,6 @@ // DOM #define STRING_DOM_UNKNOWN "" #define STRING_DOM_UNREC "DOM: Não foi possível obter nome não reconhecido '{1}'." -#define STRING_DOM_CANNOT_SET "DOM: Não foi possível definir '{1}'." // Eval #define STRING_EVAL_NO_EXPRESSION "Nenhuma expressão a calcular." @@ -685,8 +669,9 @@ // edit #define STRING_EDIT_NO_CHANGES "Não foram detetadas alterações." -#define STRING_EDIT_NO_EDITS "Nada editado." +#define STRING_EDIT_FAILED "Editing failed with exit code {1}." #define STRING_EDIT_COMPLETE "Edição concluída." +#define STRING_EDIT_IN_PROGRESS "Task is already being edited." #define STRING_EDIT_LAUNCHING "A iniciar '{1}' ..." #define STRING_EDIT_CHANGES "Alterações detetadas." #define STRING_EDIT_UNPARSEABLE "O taskwarrior não conseguiu processar as suas alterações. Deseja tentar novamente?" @@ -765,6 +750,9 @@ #define STRING_INVALID_SORT_COL "A coluna '{1}' não pode ser ordenada." #define STRING_TLS_INIT_FAIL "Erro a iniciar componente TLS. {1}" #define STRING_ERROR_DETAILS "A definição 'calendar.details.report' pode apenas indicar um nome de relatório." +#define STRING_ERROR_NO_FILTER "Command line filters are not supported by this command." +#define STRING_ERROR_CONFIRM_SIGINT "Interrupted: No changes made." +#define STRING_ERROR_BAD_STATUS "The status '{1}' is not valid." // Feedback #define STRING_FEEDBACK_NO_TASKS "Nenhuma tarefa." @@ -793,6 +781,7 @@ #define STRING_FEEDBACK_TAG_NONAG "A marca especial 'nonag' irá prevenir avisos quando a tarefa é modificada." #define STRING_FEEDBACK_TAG_NOCAL "A marca especial 'nocal' irá manter esta tarefa ausente do relatório de 'calendário'." #define STRING_FEEDBACK_TAG_NEXT "A marca especial 'next' irá aumentar a urgência desta tarefa de modo a que apareça no relatório 'next'." +#define STRING_FEEDBACK_TAG_VIRTUAL "Virtual tags (including '{1}') are reserved and may not be added or removed." #define STRING_FEEDBACK_UNBLOCKED "Desbloqueada {1} '{2}'." #define STRING_FEEDBACK_EXPIRED "Tarefa {1} '{2}' expirou e foi eliminada." #define STRING_FEEDBACK_BACKLOG "Há modificações locais. Necessário sincronizar (sync)." @@ -888,6 +877,10 @@ #define STRING_TDB2_UNDO_COMPLETE "Reversão concluída." #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}" +#define STRING_TDB2_UNWAIT "Un-waiting task '{1}'" + +// recur.cpp +#define STRING_RECUR_CREATE "Creating recurring task instance '{1}'" // 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}." @@ -895,7 +888,7 @@ // Usage text. This is an exception, and contains \n characters and formatting. #define STRING_CMD_HELP_TEXT \ "A documentação do Taskwarrior pode ser encontrada usando 'man task', 'man taskrc', 'man " \ - "task-color', 'man task-synch' ou em http://taskwarrior.org\n" \ + "task-color', 'man task-sync' ou em http://taskwarrior.org\n" \ "\n" \ "A forma geral dos comandos é:\n" \ " task [] []\n" \ @@ -945,21 +938,27 @@ " end: Data de conclusão/remoção da tarefa\n" \ " start: Data de início da tarefa\n" \ " scheduled: Data de agendamento de início de tarefa\n" \ + " modified: Date task was last modified\n" \ " depends: Outras tarefas das quais esta depende\n" \ "\n" \ "Os modificadores de atributos tornam os filtros mais precisos. Modificados suportados são:\n" \ - " before (sinónimos under, below)\n" \ - " after (sinónimos over, above)\n" \ - " none\n" \ - " any\n" \ - " is (sinónimos equals)\n" \ - " isnt (sinónimos not)\n" \ - " has (sinónimos contains)\n" \ - " hasnt\n" \ - " startswith (sinónimos left)\n" \ - " endswith (sinónimos right)\n" \ - " word\n" \ - " noword\n" \ + "\n" \ + " Modifiers Example Equivalent Meaning\n" \ + " ---------------- ----------------- ------------------- -------------------------\n" \ + " due:today due = today Fuzzy match\n" \ + " not due.not:today due != today Fuzzy non-match\n" \ + " before, below due.before:today due < tomorrow Exact date comparison\n" \ + " after, above due.after:today due > tomorrow Exact date comparison\n" \ + " none project.none: project == '' Empty\n" \ + " any project.any: project !== '' Not empty\n" \ + " is, equals project.is:x project == x Exact match\n" \ + " isnt project.isnt:x project !== x Exact non-match\n" \ + " has, contains desc.has:Hello desc ~ Hello Pattern match\n" \ + " hasnt, desc.hasnt:Hello desc !~ Hello Pattern non-match\n" \ + " startswith, left desc.left:Hel desc ~ '^Hel' Beginning match\n" \ + " endswith, right desc.right:llo desc ~ 'llo$' End match\n" \ + " word desc.word:Hello desc ~ '\\bHello\\b' Boundaried word match\n" \ + " noword desc.noword:Hello desc !~ '\\bHello\\b' Boundaried word non-match\n" \ "\n" \ "Em alternativa, as seguintes operações algebraicas são suportadas:\n" \ " and or xor Operadores lógicos\n" \ diff -Nru task-2.4.4+dfsg/src/legacy.cpp task-2.5.0+dfsg/src/legacy.cpp --- task-2.4.4+dfsg/src/legacy.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/legacy.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -34,12 +34,6 @@ extern Context context; //////////////////////////////////////////////////////////////////////////////// -void legacyAttributeCheck (const std::string& name) -{ - // 2013-07-25: Deprecated "fg" and "bg" removed. -} - -//////////////////////////////////////////////////////////////////////////////// void legacyColumnMap (std::string& name) { // 2014-01-26: priority_long --> priority.long Mapping removed @@ -63,7 +57,7 @@ } // If a legacy column was used, complain about it, but modify it anyway. - std::map ::iterator found = legacyMap.find (name); + auto found = legacyMap.find (name); if (found != legacyMap.end ()) { context.footnote (format (STRING_LEGACY_PRIORITY, name, found->second)); @@ -95,7 +89,7 @@ } // If a legacy column was used, complain about it, but modify it anyway. - std::map ::iterator found = legacyMap.find (name); + auto found = legacyMap.find (name); if (found != legacyMap.end ()) { context.footnote (format (STRING_LEGACY_PRIORITY, name, found->second)); @@ -104,36 +98,31 @@ } //////////////////////////////////////////////////////////////////////////////// -std::string legacyCheckForDeprecatedColor () -{ - // 2014-01-26: Color defs containing '_' removed. - - return ""; -} - -//////////////////////////////////////////////////////////////////////////////// std::string legacyCheckForDeprecatedVariables () { std::vector deprecated; - std::map ::const_iterator it; - for (it = context.config.begin (); it != context.config.end (); ++it) + for (auto& it : context.config) { // 2014-07-04: report.*.limit removed. // report.*.annotations - if (it->first.length () > 19 && - it->first.substr (0, 7) == "report." && - it->first.substr (it->first.length () - 12) == ".annotations") - deprecated.push_back (it->first); - - if (it->first == "next" || - it->first == "annotations" || - it->first == "export.ical.class") - deprecated.push_back (it->first); + if (it.first.length () > 19 && + it.first.substr (0, 7) == "report." && + it.first.substr (it.first.length () - 12) == ".annotations") + deprecated.push_back (it.first); + + if (it.first == "next" || + it.first == "annotations" || + it.first == "export.ical.class") + deprecated.push_back (it.first); // Deprecated іn 2.4.0. - if (it->first == "alias._query") - deprecated.push_back (it->first); + if (it.first == "alias._query") + deprecated.push_back (it.first); + + // Deprecated in 2.5.0. + if (it.first == "urgency.inherit.coefficient") + deprecated.push_back (it.first); } std::stringstream out; @@ -142,9 +131,8 @@ out << STRING_CONFIG_DEPRECATED_VAR << "\n"; - std::vector ::iterator it2; - for (it2 = deprecated.begin (); it2 != deprecated.end (); ++it2) - out << " " << *it2 << "\n"; + for (auto& dep : deprecated) + out << " " << dep << "\n"; out << "\n"; } @@ -156,16 +144,15 @@ std::string legacyCheckForDeprecatedColumns () { std::vector deprecated; - std::map ::const_iterator it; - for (it = context.config.begin (); it != context.config.end (); ++it) + for (auto& it : context.config) { - if (it->first.find ("report") == 0) + if (it.first.find ("report") == 0) { - std::string value = context.config.get (it->first); + std::string value = context.config.get (it.first); if (value.find ("entry_time") != std::string::npos || value.find ("start_time") != std::string::npos || value.find ("end_time") != std::string::npos) - deprecated.push_back (it->first); + deprecated.push_back (it.first); } } @@ -177,9 +164,8 @@ out << STRING_CONFIG_DEPRECATED_COL << "\n"; - std::vector ::iterator it2; - for (it2 = deprecated.begin (); it2 != deprecated.end (); ++it2) - out << " " << *it2 << "=" << context.config.get (*it2) << "\n"; + for (auto& dep : deprecated) + out << " " << dep << "=" << context.config.get (dep) << "\n"; out << "\n"; } diff -Nru task-2.4.4+dfsg/src/lex.cpp task-2.5.0+dfsg/src/lex.cpp --- task-2.4.4+dfsg/src/lex.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/lex.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -12,19 +12,11 @@ { std::cout << "argument '" << argv[i] << "'\n"; - // Low-level tokens. - Lexer lexer (argv[i]); + Lexer l (argv[i]); std::string token; Lexer::Type type; - while (lexer.token (token, type)) + while (l.token (token, type)) std::cout << " token '" << token << "' " << Lexer::typeToString (type) << "\n"; - -/* - // High-level tokens. - auto all = Lexer::tokens (argv[i]); - for (auto token : Lexer::tokens (argv[i])) - std::cout << " token '" << token.first << "' " << Lexer::typeToString (token.second) << "\n"; -*/ } } diff -Nru task-2.4.4+dfsg/src/Lexer.cpp task-2.5.0+dfsg/src/Lexer.cpp --- task-2.4.4+dfsg/src/Lexer.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/Lexer.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -28,22 +28,21 @@ #include #include #include -#include -#include #include static const std::string uuid_pattern = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; static const unsigned int uuid_min_length = 8; std::string Lexer::dateFormat = ""; -bool Lexer::isoEnabled = true; +std::string::size_type Lexer::minimumMatchLength = 3; +std::map Lexer::attributes; + //////////////////////////////////////////////////////////////////////////////// Lexer::Lexer (const std::string& text) : _text (text) , _cursor (0) , _eos (text.size ()) -, _ambiguity (false) { } @@ -53,12 +52,6 @@ } //////////////////////////////////////////////////////////////////////////////// -void Lexer::ambiguity (bool value) -{ - _ambiguity = value; -} - -//////////////////////////////////////////////////////////////////////////////// // When a Lexer object is constructed with a string, this method walks through // the stream of low-level tokens. bool Lexer::token (std::string& token, Lexer::Type& type) @@ -72,31 +65,32 @@ return false; // The sequence is specific, and must follow these rules: - // - date < duration < uuid < identifier - // - uuid < hex < number - // - url < pair < identifier - // - hex < number - // - separator < tag < operator - // - path < substitution < pattern - // - word last - if (isString (token, type, '\'') || - isString (token, type, '"') || - isDate (token, type) || - isDuration (token, type) || - isURL (token, type) || - isPair (token, type) || - isDOM (token, type) || - isUUID (token, type) || - isHexNumber (token, type) || - isNumber (token, type) || - isSeparator (token, type) || - isList (token, type) || - isTag (token, type) || - isPath (token, type) || - isSubstitution (token, type) || - isPattern (token, type) || - isOperator (token, type) || - isIdentifier (token, type) || + // - date < duration < uuid < identifier + // - dom < uuid + // - uuid < hex < number + // - url < pair < identifier + // - hex < number + // - separator < tag < operator + // - path < substitution < pattern + // - set < number + // - word last + if (isString (token, type, "'\"") || + isDate (token, type) || + isDuration (token, type) || + isURL (token, type) || + isPair (token, type) || + isUUID (token, type, true) || + isSet (token, type) || + isDOM (token, type) || + isHexNumber (token, type) || + isNumber (token, type) || + isSeparator (token, type) || + isTag (token, type) || + isPath (token, type) || + isSubstitution (token, type) || + isPattern (token, type) || + isOperator (token, type) || + isIdentifier (token, type) || isWord (token, type)) return true; @@ -104,22 +98,6 @@ } //////////////////////////////////////////////////////////////////////////////// -// This static method tokenizes the input and provides a vector of token/type -// results from a high-level lex. -std::vector > Lexer::tokens ( - const std::string& text) -{ - std::vector > all; - std::string token; - Lexer::Type type; - Lexer l (text); - while (l.token (token, type)) - all.push_back (std::pair (token, type)); - - return all; -} - -//////////////////////////////////////////////////////////////////////////////// // This static method tokenizes the input, but discards the type information. std::vector Lexer::split (const std::string& text) { @@ -143,9 +121,9 @@ case Lexer::Type::number: return "number"; case Lexer::Type::hex: return "hex"; case Lexer::Type::string: return "string"; - case Lexer::Type::list: return "list"; case Lexer::Type::url: return "url"; case Lexer::Type::pair: return "pair"; + case Lexer::Type::set: return "set"; case Lexer::Type::separator: return "separator"; case Lexer::Type::tag: return "tag"; case Lexer::Type::path: return "path"; @@ -166,8 +144,10 @@ // Complete Unicode whitespace list. // // http://en.wikipedia.org/wiki/Whitespace_character -// Updated 2013-11-18 +// Updated 2015-09-13 // Static +// +// TODO This list should be derived from the Unicode database. bool Lexer::isWhitespace (int c) { return (c == 0x0020 || // space Common Separator, space @@ -191,10 +171,14 @@ c == 0x2008 || // punctuation space Common Separator, space c == 0x2009 || // thin space Common Separator, space c == 0x200A || // hair space Common Separator, space + c == 0x200B || // zero width space + c == 0x200C || // zero width non-joiner + c == 0x200D || // zero width joiner c == 0x2028 || // line separator Common Separator, line c == 0x2029 || // paragraph separator Common Separator, paragraph c == 0x202F || // narrow no-break space Common Separator, space c == 0x205F || // medium mathematical space Common Separator, space + c == 0x2060 || // word joiner c == 0x3000); // ideographic space Common Separator, space } @@ -207,6 +191,8 @@ //////////////////////////////////////////////////////////////////////////////// // Digits 0-9. +// +// TODO This list should be derived from the Unicode database. bool Lexer::isDigit (int c) { return c >= 0x30 && c <= 0x39; @@ -236,6 +222,7 @@ { return c && // Include null character check. c != ':' && // Used in isPair. + c != '=' && // Used in isPair. ! isWhitespace (c) && ! isSingleCharOperator (c); } @@ -297,6 +284,22 @@ } //////////////////////////////////////////////////////////////////////////////// +bool Lexer::isHardBoundary (int left, int right) +{ + // EOS + if (right == '\0') return true; + + // FILTER operators that don't need to be surrounded by whitespace. + if (left == '(' || + left == ')' || + right == '(' || + right == ')') + return true; + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// bool Lexer::isPunctuation (int c) { return isprint (c) && @@ -310,18 +313,31 @@ } //////////////////////////////////////////////////////////////////////////////// -void Lexer::dequote (std::string& input) +// Assumes that quotes is a string containing a non-trivial set of quote +// characters. +void Lexer::dequote (std::string& input, const std::string& quotes) { int quote = input[0]; - size_t len = input.length (); - if ((quote == '\'' || quote == '"') && - quote == input[len - 1]) + if (quotes.find (quote) != std::string::npos) { - input = input.substr (1, len - 2); + size_t len = input.length (); + if (quote == input[len - 1]) + input = input.substr (1, len - 2); } } //////////////////////////////////////////////////////////////////////////////// +// Detects characters in an input string that indicate quotes were required, or +// escapes, to get them past the shell. +bool Lexer::wasQuoted (const std::string& input) +{ + if (input.find_first_of (" \t()<>&~") != std::string::npos) + return true; + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// bool Lexer::isEOS () const { return _cursor >= _eos; @@ -332,7 +348,7 @@ // '9' -> 9 // 'a'/'A' -> 10 // 'f'/'F' -> 15 -int Lexer::hexToInt (int c) const +int Lexer::hexToInt (int c) { if (c >= '0' && c <= '9') return (c - '0'); else if (c >= 'a' && c <= 'f') return (c - 'a' + 10); @@ -340,13 +356,13 @@ } //////////////////////////////////////////////////////////////////////////////// -int Lexer::hexToInt (int c0, int c1) const +int Lexer::hexToInt (int c0, int c1) { return (hexToInt (c0) << 4) + hexToInt (c1); } //////////////////////////////////////////////////////////////////////////////// -int Lexer::hexToInt (int c0, int c1, int c2, int c3) const +int Lexer::hexToInt (int c0, int c1, int c2, int c3) { return (hexToInt (c0) << 12) + (hexToInt (c1) << 8) + @@ -355,79 +371,60 @@ } //////////////////////////////////////////////////////////////////////////////// +// Compares two strings, and returns the number bytes in common. +// +// left: wonderful +// right: wonderbread +// returns: ^ 6 +std::string::size_type Lexer::commonLength ( + const std::string& left, + const std::string& right) +{ + std::string::size_type l = 0; + std::string::size_type r = 0; + while (left[l] == right[r] && + utf8_next_char (left, l) && + utf8_next_char (right, r)) + ; + + return l; +} + +//////////////////////////////////////////////////////////////////////////////// +// Compares two strings with offsets, and returns the number bytes in common. +// +// left: wonderful +// l: ^ +// right: prowonderbread +// r: ^ +// returns: ^ 6 +std::string::size_type Lexer::commonLength ( + const std::string& left, + std::string::size_type l, + const std::string& right, + std::string::size_type r) +{ + while (left[l] == right[r] && + utf8_next_char (left, l) && + utf8_next_char (right, r)) + ; + + return l; +} + +//////////////////////////////////////////////////////////////////////////////// // Lexer::Type::string // '|" // [ U+XXXX | \uXXXX | \" | \' | \\ | \/ | \b | \f | \n | \r | \t | . ] // '|" -bool Lexer::isString (std::string& token, Lexer::Type& type, int quote) +bool Lexer::isString (std::string& token, Lexer::Type& type, const std::string& quotes) { std::size_t marker = _cursor; - - if (_text[marker] == quote) + if (readWord (_text, quotes, marker, token)) { - token = _text.substr (marker++, 1); - - int c; - while ((c = _text[marker])) - { - // EOS. - if (c == quote) - break; - - // Unicode U+XXXX or \uXXXX codepoint. - else if (_eos - marker >= 6 && - ((_text[marker + 0] == 'U' && _text[marker + 1] == '+') || - (_text[marker + 0] == '\\' && _text[marker + 1] == 'u')) && - isHexDigit (_text[marker + 2]) && - isHexDigit (_text[marker + 3]) && - isHexDigit (_text[marker + 4]) && - isHexDigit (_text[marker + 5])) - { - token += utf8_character ( - hexToInt ( - _text[marker + 2], - _text[marker + 3], - _text[marker + 4], - _text[marker + 5])); - marker += 6; - } - - // An escaped thing. - else if (c == '\\') - { - c = _text[++marker]; - - switch (c) - { - case '"': token += (char) 0x22; ++marker; break; - case '\'': token += (char) 0x27; ++marker; break; - case '\\': token += (char) 0x5C; ++marker; break; - case 'b': token += (char) 0x08; ++marker; break; - case 'f': token += (char) 0x0C; ++marker; break; - case 'n': token += (char) 0x0A; ++marker; break; - case 'r': token += (char) 0x0D; ++marker; break; - case 't': token += (char) 0x09; ++marker; break; - case 'v': token += (char) 0x0B; ++marker; break; - - // This pass-through default case means that anythign can be escaped - // harmlessly. In particular 'quote' is included, if it not one of the - // above characters. - default: token += (char) c; ++marker; break; - } - } - - // Ordinary character. - else - token += utf8_character (utf8_next_char (_text, marker)); - } - - if (_text[marker] == quote) - { - token += _text.substr (marker++, 1); - type = Lexer::Type::string; - _cursor = marker; - return true; - } + type = Lexer::Type::string; + _cursor = marker; + return true; } return false; @@ -435,39 +432,18 @@ //////////////////////////////////////////////////////////////////////////////// // Lexer::Type::date -// | +// bool Lexer::isDate (std::string& token, Lexer::Type& type) { // Try an ISO date parse. - if (Lexer::isoEnabled) - { - std::size_t iso_i = 0; - ISO8601d iso; - iso.ambiguity (_ambiguity); - if (iso.parse (_text.substr (_cursor), iso_i)) - { - type = Lexer::Type::date; - token = _text.substr (_cursor, iso_i); - _cursor += iso_i; - return true; - } - } - - // Try a legacy rc.dateformat parse here. - if (Lexer::dateFormat != "") - { - try - { - std::size_t legacy_i = 0; - Date legacyDate (_text.substr (_cursor), legacy_i, Lexer::dateFormat, false, false); - - type = Lexer::Type::date; - token = _text.substr (_cursor, legacy_i); - _cursor += legacy_i; - return true; - } - - catch (...) { /* Never mind. */ } + std::size_t iso_i = 0; + ISO8601d iso; + if (iso.parse (_text.substr (_cursor), iso_i, Lexer::dateFormat)) + { + type = Lexer::Type::date; + token = _text.substr (_cursor, iso_i); + _cursor += iso_i; + return true; } return false; @@ -479,7 +455,6 @@ bool Lexer::isDuration (std::string& token, Lexer::Type& type) { std::size_t marker = _cursor; - ISO8601p iso; std::string extractedToken; Lexer::Type extractedType; @@ -490,6 +465,7 @@ } marker = 0; + ISO8601p iso; if (iso.parse (_text.substr (_cursor), marker)) { type = Lexer::Type::duration; @@ -498,15 +474,6 @@ return true; } - Duration dur; - if (dur.parse (_text.substr (_cursor), marker)) - { - type = Lexer::Type::duration; - token = _text.substr (_cursor, marker); - _cursor += marker; - return true; - } - return false; } @@ -521,11 +488,12 @@ // XXXXXXXX-X // XXXXXXXX- // XXXXXXXX -// Followed only by EOS, whitespace, operator or list. -bool Lexer::isUUID (std::string& token, Lexer::Type& type) +// Followed only by EOS, whitespace, or single character operator. +bool Lexer::isUUID (std::string& token, Lexer::Type& type, bool endBoundary) { std::size_t marker = _cursor; + // Greedy. std::size_t i = 0; for (; i < 36 && marker + i < _eos; i++) { @@ -538,15 +506,16 @@ break; } - if (i >= uuid_min_length) + if (i >= uuid_min_length && + (! endBoundary || + ! _text[marker + i] || + isWhitespace (_text[marker + i]) || + isSingleCharOperator (_text[marker + i]))) { token = _text.substr (_cursor, i); - if (! isAllDigits (token)) - { - type = Lexer::Type::uuid; - _cursor += i; - return true; - } + type = Lexer::Type::uuid; + _cursor += i; + return true; } return false; @@ -652,6 +621,28 @@ } //////////////////////////////////////////////////////////////////////////////// +// Lexer::Type::number +// \d+ +bool Lexer::isInteger (std::string& token, Lexer::Type& type) +{ + std::size_t marker = _cursor; + + if (isDigit (_text[marker])) + { + ++marker; + while (isDigit (_text[marker])) + utf8_next_char (_text, marker); + + token = _text.substr (_cursor, marker - _cursor); + type = Lexer::Type::number; + _cursor = marker; + return true; + } + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// // Lexer::Type::separator // -- bool Lexer::isSeparator (std::string& token, Lexer::Type& type) @@ -670,23 +661,6 @@ } //////////////////////////////////////////////////////////////////////////////// -// Lexer::Type::list -// , -bool Lexer::isList (std::string& token, Lexer::Type& type) -{ - if (_eos - _cursor > 1 && - _text[_cursor] == ',') - { - ++_cursor; - type = Lexer::Type::list; - token = ","; - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// // Lexer::Type::url // http [s] :// ... bool Lexer::isURL (std::string& token, Lexer::Type& type) @@ -725,7 +699,8 @@ //////////////////////////////////////////////////////////////////////////////// // Lexer::Type::pair -// :|= [ | ] +// [ | ] +// separator '::' | ':=' | ':' | '=' bool Lexer::isPair (std::string& token, Lexer::Type& type) { std::size_t marker = _cursor; @@ -734,57 +709,98 @@ Lexer::Type ignoredType; if (isIdentifier (ignoredToken, ignoredType)) { - // Look for rc.name[:=]value first, because '=' is allowed. - if (ignoredToken == "rc" || - ignoredToken.substr (0, 3) == "rc.") + // Look for a valid separator. + std::string separator = _text.substr (_cursor, 2); + if (separator == "::" || separator == ":=") + _cursor += 2; + else if (separator[0] == ':' || separator[0] == '=') + _cursor++; + else { - if (_eos - _cursor > 1 && - (_text[_cursor] == ':' || _text[_cursor] == '=')) - { - _cursor++; - - if (isString (ignoredToken, ignoredType, '\'') || - isString (ignoredToken, ignoredType, '"') || - isWord (ignoredToken, ignoredType)) - { - token = _text.substr (marker, _cursor - marker); - type = Lexer::Type::pair; - return true; - } - } + _cursor = marker; + return false; } - if (_eos - _cursor >= 1 && - _text[_cursor] == ':') + // String, word or nothing are all valid. + if (readWord (_text, "'\"", _cursor, ignoredToken) || + readWord (_text, _cursor, ignoredToken) || + isEOS () || + isWhitespace (_text[_cursor])) { - _cursor++; + token = _text.substr (marker, _cursor - marker); + type = Lexer::Type::pair; + return true; + } + } + + _cursor = marker; + return false; +} - if (isString (ignoredToken, ignoredType, '\'') || - isString (ignoredToken, ignoredType, '"') || - isWord (ignoredToken, ignoredType) || - _eos == _cursor || - _text[_cursor] == ' ') +//////////////////////////////////////////////////////////////////////////////// +// Lexer::Type::set +// a single number: 1 +// a list of numbers: 1,3,5 +// a range: 5-10 +// or a combination: 1,3,5-10 +// +// [ - ] [ , [ - ] ] ... +bool Lexer::isSet (std::string& token, Lexer::Type& type) +{ + std::size_t marker = _cursor; + int count = 0; + std::string dummyToken; + Lexer::Type dummyType; + + do + { + if (isInteger (dummyToken, dummyType)) + { + ++count; + if (isLiteral ("-", false, false)) { - token = _text.substr (marker, _cursor - marker); - type = Lexer::Type::pair; - return true; + if (isInteger (dummyToken, dummyType)) + ++count; + else + { + _cursor = marker; + return false; + } } } + else + { + _cursor = marker; + return false; + } + } + while (isLiteral (",", false, false)); + + // Success is multiple numbers, matching the pattern. + if (count > 1 && + (isEOS () || + isWhitespace (_text[_cursor]) || + isHardBoundary (_text[_cursor], _text[_cursor + 1]))) + { + token = _text.substr (marker, _cursor - marker); + type = Lexer::Type::set; + return true; } _cursor = marker; return false; + } //////////////////////////////////////////////////////////////////////////////// // Lexer::Type::tag -// ^ | '(' | ')' | +// ^ | '(' | ')' | // [ +|- ] [ ]* bool Lexer::isTag (std::string& token, Lexer::Type& type) { std::size_t marker = _cursor; - // Lookbehind: ^ | '(' | ')' | + // Lookbehind: Assert ^ or preceded by whitespace, (, or ). if (marker > 0 && ! isWhitespace (_text[marker - 1]) && _text[marker - 1] != '(' && @@ -859,18 +875,17 @@ //////////////////////////////////////////////////////////////////////////////// // Lexer::Type::substitution -// / / / [g] | +// / / / [g] | bool Lexer::isSubstitution (std::string& token, Lexer::Type& type) { std::size_t marker = _cursor; - std::string extractedToken; - Lexer::Type extractedType; - if (isString (extractedToken, extractedType, '/')) + std::string word; + if (readWord (_text, "/", _cursor, word)) { - --_cursor; // Step back over the '/'. + --_cursor; // Step backwards over the '/'. - if (isString (extractedToken, extractedType, '/')) + if (readWord (_text, "/", _cursor, word)) { if (_text[_cursor] == 'g') ++_cursor; @@ -892,15 +907,14 @@ //////////////////////////////////////////////////////////////////////////////// // Lexer::Type::pattern -// / / | +// / / | bool Lexer::isPattern (std::string& token, Lexer::Type& type) { std::size_t marker = _cursor; - std::string extractedToken; - Lexer::Type extractedType; - if (isString (extractedToken, extractedType, '/') && - (_text[_cursor] == '\0' || + std::string word; + if (readWord (_text, "/", _cursor, word) && + (isEOS () || isWhitespace (_text[_cursor]))) { token = _text.substr (marker, _cursor - marker); @@ -992,61 +1006,169 @@ //////////////////////////////////////////////////////////////////////////////// // Lexer::Type::dom // [ | + . ] [ . ]* +// +// Configuration: +// rc. +// +// System: +// context.program +// context.args +// context.width +// context.height +// system.version +// system.os +// +// Relative or absolute attribute: +// +// . +// . +// +// Single tag: +// tags. +// +// Date type: +// .year +// .month +// .day +// .week +// .weekday +// .julian +// .hour +// .minute +// .second +// +// Annotations (entry is a date): +// annotations..entry +// annotations..description +// bool Lexer::isDOM (std::string& token, Lexer::Type& type) { std::size_t marker = _cursor; + std::string partialToken; + Lexer::Type partialType; + if (isLiteral ("rc.", false, false) && + isWord (partialToken, partialType)) + { + token = _text.substr (marker, _cursor - marker); + type = Lexer::Type::dom; + return true; + } + else + _cursor = marker; + + if (isOneOf ({"context.program", + "context.args", + "context.width", + "context.height", + "system.version", + "system.os"}, false, true)) + { + token = _text.substr (marker, _cursor - marker); + type = Lexer::Type::dom; + return true; + } + + // Optional: + // . + // . std::string extractedToken; Lexer::Type extractedType; - if (isUUID (extractedToken, extractedType)) + if (isUUID (extractedToken, extractedType, false) || + isInteger (extractedToken, extractedType)) { - if (_text[_cursor] == '.') - ++_cursor; - else + if (! isLiteral (".", false, false)) { _cursor = marker; return false; } } + + // Any failure after this line should rollback to the checkpoint. + std::size_t checkpoint = _cursor; + + // [prefix]tags. + if (isLiteral ("tags", false, false) && + isLiteral (".", false, false) && + isWord (partialToken, partialType)) + { + token = _text.substr (marker, _cursor - marker); + type = Lexer::Type::dom; + return true; + } else + _cursor = checkpoint; + + // [prefix]attribute + if (isOneOf (attributes, false, true)) + { + token = _text.substr (marker, _cursor - marker); + type = Lexer::Type::dom; + return true; + } + + // [prefix]attribute. + if (isOneOf (attributes, false, false)) { - if (isDigit (_text[_cursor])) + if (isLiteral (".", false, false)) { - ++_cursor; - while (isDigit (_text[_cursor])) - ++_cursor; + std::string attribute = _text.substr (checkpoint, _cursor - checkpoint - 1); - if (_text[_cursor] == '.') - ++_cursor; - else + // if attribute type is 'date', then it has sub-elements. + if (attributes[attribute] == "date" && + isOneOf ({"year", "month", "day", + "week", "weekday", + "julian", + "hour", "minute", "second"}, false, true)) { - _cursor = marker; - return false; + token = _text.substr (marker, _cursor - marker); + type = Lexer::Type::dom; + return true; } } + else + { + token = _text.substr (marker, _cursor - marker); + type = Lexer::Type::dom; + return true; + } } - if (! isOperator (extractedToken, extractedType) && - isIdentifier (extractedToken, extractedType)) - { - while (1) + // [prefix]annotations. + if (isLiteral ("annotations", true, false) && + isLiteral (".", false, false)) + { + std::string extractedToken; + Lexer::Type extractedType; + if (isInteger (extractedToken, extractedType)) { - if (_text[_cursor] == '.') - ++_cursor; - else - break; - - if (isOperator (extractedToken, extractedType) || - ! isIdentifier (extractedToken, extractedType)) + if (isLiteral (".", false, false)) { - _cursor = marker; - return false; + if (isLiteral ("description", false, true)) + { + token = _text.substr (marker, _cursor - marker); + type = Lexer::Type::dom; + return true; + } + else if (isLiteral ("entry", false, true)) + { + token = _text.substr (marker, _cursor - marker); + type = Lexer::Type::dom; + return true; + } + else if (isLiteral ("entry", false, false) && + isLiteral (".", false, false) && + isOneOf ({"year", "month", "day", + "week", "weekday", + "julian", + "hour", "minute", "second"}, false, true)) + { + token = _text.substr (marker, _cursor - marker); + type = Lexer::Type::dom; + return true; + } } } - - type = Lexer::Type::dom; - token = _text.substr (marker, _cursor - marker); - return true; } _cursor = marker; @@ -1100,6 +1222,61 @@ } //////////////////////////////////////////////////////////////////////////////// +bool Lexer::isLiteral ( + const std::string& literal, + bool allowAbbreviations, + bool endBoundary) +{ + auto common = commonLength (literal, 0, _text, _cursor); + + // Without abbreviations, common must equal literal length. + if (! allowAbbreviations && + common < literal.length ()) + return false; + + // Abbreviations must meet the minimum size. + if (allowAbbreviations && + common < minimumMatchLength) + return false; + + // End boundary conditions must be met. + if (endBoundary && + _text[_cursor + common] && + ! Lexer::isWhitespace (_text[_cursor + common]) && + ! Lexer::isSingleCharOperator (_text[_cursor + common])) + return false; + + _cursor += common; + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +bool Lexer::isOneOf ( + const std::vector & options, + bool allowAbbreviations, + bool endBoundary) +{ + for (auto& item : options) + if (isLiteral (item, allowAbbreviations, endBoundary)) + return true; + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +bool Lexer::isOneOf ( + const std::map & options, + bool allowAbbreviations, + bool endBoundary) +{ + for (auto& item : options) + if (isLiteral (item.first, allowAbbreviations, endBoundary)) + return true; + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// // Static std::string Lexer::typeToString (Lexer::Type type) { @@ -1108,9 +1285,9 @@ else if (type == Lexer::Type::hex) return std::string ("\033[38;5;7m\033[48;5;14m") + "hex" + "\033[0m"; else if (type == Lexer::Type::number) return std::string ("\033[38;5;7m\033[48;5;6m") + "number" + "\033[0m"; else if (type == Lexer::Type::separator) return std::string ("\033[38;5;7m\033[48;5;4m") + "separator" + "\033[0m"; - else if (type == Lexer::Type::list) return std::string ("\033[38;5;7m\033[48;5;4m") + "list" + "\033[0m"; else if (type == Lexer::Type::url) return std::string ("\033[38;5;7m\033[48;5;4m") + "url" + "\033[0m"; else if (type == Lexer::Type::pair) return std::string ("\033[38;5;7m\033[48;5;1m") + "pair" + "\033[0m"; + else if (type == Lexer::Type::set) return std::string ("\033[38;5;15m\033[48;5;208m") + "set" + "\033[0m"; else if (type == Lexer::Type::tag) return std::string ("\033[37;45m") + "tag" + "\033[0m"; else if (type == Lexer::Type::path) return std::string ("\033[37;102m") + "path" + "\033[0m"; else if (type == Lexer::Type::substitution) return std::string ("\033[37;102m") + "substitution" + "\033[0m"; @@ -1121,25 +1298,332 @@ else if (type == Lexer::Type::word) return std::string ("\033[38;5;15m\033[48;5;236m") + "word" + "\033[0m"; else if (type == Lexer::Type::date) return std::string ("\033[38;5;15m\033[48;5;34m") + "date" + "\033[0m"; else if (type == Lexer::Type::duration) return std::string ("\033[38;5;15m\033[48;5;34m") + "duration" + "\033[0m"; - else return std::string ("\033[37;41m") + "unknown" + "\033[0m"; + else return std::string ("\033[37;41m") + "unknown" + "\033[0m"; } //////////////////////////////////////////////////////////////////////////////// bool Lexer::isAllDigits (const std::string& text) { - return text.find_first_not_of ("0123456789") == std::string::npos; + return text.length () && + text.find_first_not_of ("0123456789") == std::string::npos; } //////////////////////////////////////////////////////////////////////////////// -bool Lexer::isOneWord (const std::string& text) +bool Lexer::isDOM (const std::string& text) { - std::string::size_type i = 0; - int character; - while ((character = utf8_next_char (text, i))) - if (Lexer::isWhitespace (character)) - return false; + Lexer lex (text); + int count = 0; + std::string token; + Lexer::Type type; + while (lex.token (token, type)) + ++count; - return true; + return count == 1 && + type == Lexer::Type::dom; +} + +//////////////////////////////////////////////////////////////////////////////// +// Full implementation of a quoted word. Includes: +// '\'' +// '"' +// "'" +// "\"" +// 'one two' +// Result includes the quotes. +bool Lexer::readWord ( + const std::string& text, + const std::string& quotes, + std::string::size_type& cursor, + std::string& word) +{ + if (quotes.find (text[cursor]) == std::string::npos) + return false; + + std::string::size_type eos = text.length (); + int quote = text[cursor++]; + word = quote; + + int c; + while ((c = text[cursor])) + { + // Quoted word ends on a quote. + if (quote && quote == c) + { + word += utf8_character (utf8_next_char (text, cursor)); + break; + } + + // Unicode U+XXXX or \uXXXX codepoint. + else if (eos - cursor >= 6 && + ((text[cursor + 0] == 'U' && text[cursor + 1] == '+') || + (text[cursor + 0] == '\\' && text[cursor + 1] == 'u')) && + isHexDigit (text[cursor + 2]) && + isHexDigit (text[cursor + 3]) && + isHexDigit (text[cursor + 4]) && + isHexDigit (text[cursor + 5])) + { + word += utf8_character ( + hexToInt ( + text[cursor + 2], + text[cursor + 3], + text[cursor + 4], + text[cursor + 5])); + cursor += 6; + } + + // An escaped thing. + else if (c == '\\') + { + c = text[++cursor]; + + switch (c) + { + case '"': word += (char) 0x22; ++cursor; break; + case '\'': word += (char) 0x27; ++cursor; break; + case '\\': word += (char) 0x5C; ++cursor; break; + case 'b': word += (char) 0x08; ++cursor; break; + case 'f': word += (char) 0x0C; ++cursor; break; + case 'n': word += (char) 0x0A; ++cursor; break; + case 'r': word += (char) 0x0D; ++cursor; break; + case 't': word += (char) 0x09; ++cursor; break; + case 'v': word += (char) 0x0B; ++cursor; break; + + // This pass-through default case means that anything can be escaped + // harmlessly. In particular 'quote' is included, if it not one of the + // above characters. + default: word += (char) c; ++cursor; break; + } + } + + // Ordinary character. + else + word += utf8_character (utf8_next_char (text, cursor)); + } + + // Verify termination. + return word[0] == quote && + word[word.length () - 1] == quote && + word.length () >= 2; +} + +//////////////////////////////////////////////////////////////////////////////// +// Full implementation of an unquoted word. Includes: +// one\ two +// abcU+0020def +// abc\u0020def +// a\tb +// +// Ends at: +// Lexer::isEOS +// Lexer::isWhitespace +// Lexer::isHardBoundary +bool Lexer::readWord ( + const std::string& text, + std::string::size_type& cursor, + std::string& word) +{ + std::string::size_type eos = text.length (); + + word = ""; + int c; + int prev = 0; + while ((c = text[cursor])) // Handles EOS. + { + // Unquoted word ends on white space. + if (Lexer::isWhitespace (c)) + break; + + // Parentheses mostly. + if (prev && Lexer::isHardBoundary (prev, c)) + break; + + // Unicode U+XXXX or \uXXXX codepoint. + else if (eos - cursor >= 6 && + ((text[cursor + 0] == 'U' && text[cursor + 1] == '+') || + (text[cursor + 0] == '\\' && text[cursor + 1] == 'u')) && + isHexDigit (text[cursor + 2]) && + isHexDigit (text[cursor + 3]) && + isHexDigit (text[cursor + 4]) && + isHexDigit (text[cursor + 5])) + { + word += utf8_character ( + hexToInt ( + text[cursor + 2], + text[cursor + 3], + text[cursor + 4], + text[cursor + 5])); + cursor += 6; + } + + // An escaped thing. + else if (c == '\\') + { + c = text[++cursor]; + + switch (c) + { + case '"': word += (char) 0x22; ++cursor; break; + case '\'': word += (char) 0x27; ++cursor; break; + case '\\': word += (char) 0x5C; ++cursor; break; + case 'b': word += (char) 0x08; ++cursor; break; + case 'f': word += (char) 0x0C; ++cursor; break; + case 'n': word += (char) 0x0A; ++cursor; break; + case 'r': word += (char) 0x0D; ++cursor; break; + case 't': word += (char) 0x09; ++cursor; break; + case 'v': word += (char) 0x0B; ++cursor; break; + + // This pass-through default case means that anything can be escaped + // harmlessly. In particular 'quote' is included, if it not one of the + // above characters. + default: word += (char) c; ++cursor; break; + } + } + + // Ordinary character. + else + word += utf8_character (utf8_next_char (text, cursor)); + + prev = c; + } + + return word.length () > 0 ? true : false; +} + +//////////////////////////////////////////////////////////////////////////////// +// [. ] <: | = | :: | :=> [] +bool Lexer::decomposePair ( + const std::string& text, + std::string& name, + std::string& modifier, + std::string& separator, + std::string& value) +{ + // Look for the required elements. + std::string::size_type dot = text.find ('.'); + std::string::size_type sep_defer = text.find ("::"); + std::string::size_type sep_eval = text.find (":="); + std::string::size_type sep_colon = text.find (':'); + std::string::size_type sep_equal = text.find ('='); + + // Determine which separator is dominant, which would be the first one seen, + // taking into consideration the overlapping : characters. + std::string::size_type sep = std::string::npos; + std::string::size_type sep_end = std::string::npos; + if (sep_defer != std::string::npos && + (sep_eval == std::string::npos || sep_defer <= sep_eval) && + (sep_colon == std::string::npos || sep_defer <= sep_colon) && + (sep_equal == std::string::npos || sep_defer <= sep_equal)) + { + sep = sep_defer; + sep_end = sep_defer + 2; + } + else if (sep_eval != std::string::npos && + (sep_defer == std::string::npos || sep_eval <= sep_defer) && + (sep_colon == std::string::npos || sep_eval <= sep_colon) && + (sep_equal == std::string::npos || sep_eval <= sep_equal)) + { + sep = sep_eval; + sep_end = sep_eval + 2; + } + else if (sep_colon != std::string::npos && + (sep_defer == std::string::npos || sep_colon <= sep_defer) && + (sep_eval == std::string::npos || sep_colon <= sep_eval) && + (sep_equal == std::string::npos || sep_colon <= sep_equal)) + { + sep = sep_colon; + sep_end = sep_colon + 1; + } + else if (sep_equal != std::string::npos && + (sep_defer == std::string::npos || sep_equal <= sep_defer) && + (sep_eval == std::string::npos || sep_equal <= sep_eval) && + (sep_colon == std::string::npos || sep_equal <= sep_colon)) + { + sep = sep_equal; + sep_end = sep_equal + 1; + } + + // If sep is known, all is well. + if (sep != std::string::npos) + { + // Now the only unknown is whethere there is a modifier. + if (dot != std::string::npos && dot < sep) + { + name = text.substr (0, dot); + modifier = text.substr (dot + 1, sep - dot - 1); + } + else + { + name = text.substr (0, sep); + modifier = ""; + } + + separator = text.substr (sep, sep_end - sep); + value = text.substr (sep_end); + + // An empty name is an error. + if (name.length ()) + return true; + } + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +// / / / [] +bool Lexer::decomposeSubstitution ( + const std::string& text, + std::string& from, + std::string& to, + std::string& flags) +{ + std::string parsed_from; + std::string::size_type cursor = 0; + if (readWord (text, "/", cursor, parsed_from) && + parsed_from.length ()) + { + --cursor; + std::string parsed_to; + if (readWord (text, "/", cursor, parsed_to)) + { + std::string parsed_flags = text.substr (cursor); + if (parsed_flags.find ("/") == std::string::npos) + { + dequote (parsed_from, "/"); + dequote (parsed_to, "/"); + + from = parsed_from; + to = parsed_to; + flags = parsed_flags; + return true; + } + } + } + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +// / / [] +bool Lexer::decomposePattern ( + const std::string& text, + std::string& pattern, + std::string& flags) +{ + std::string ignored; + std::string::size_type cursor = 0; + if (readWord (text, "/", cursor, ignored) && + ignored.length ()) + { + auto parsed_flags = text.substr (cursor); + if (parsed_flags.find ("/") == std::string::npos) + { + flags = parsed_flags; + pattern = text.substr (1, cursor - 2 - flags.length ()); + return true; + } + } + + return false; } //////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/Lexer.h task-2.5.0+dfsg/src/Lexer.h --- task-2.4.4+dfsg/src/Lexer.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/Lexer.h 2015-10-21 21:18:15.000000000 +0000 @@ -28,6 +28,7 @@ #define INCLUDED_LEXER #include +#include #include #include @@ -39,11 +40,12 @@ public: // These are overridable. static std::string dateFormat; - static bool isoEnabled; + static std::string::size_type minimumMatchLength; + static std::map attributes; enum class Type { uuid, number, hex, string, - list, url, pair, separator, + url, pair, set, separator, tag, path, substitution, pattern, @@ -53,46 +55,52 @@ Lexer (const std::string&); ~Lexer (); - void ambiguity (bool); bool token (std::string&, Lexer::Type&); - static std::vector > tokens (const std::string&); static std::vector split (const std::string&); static std::string typeToString (Lexer::Type); - static bool isAllDigits (const std::string&); - static bool isOneWord (const std::string&); // Static helpers. - static const std::string typeName (const Lexer::Type&); - static bool isWhitespace (int); - static bool isAlpha (int); - static bool isDigit (int); - static bool isHexDigit (int); - static bool isIdentifierStart (int); - static bool isIdentifierNext (int); - static bool isSingleCharOperator (int); - static bool isDoubleCharOperator (int, int, int); - static bool isTripleCharOperator (int, int, int, int); - static bool isBoundary (int, int); - static bool isPunctuation (int); - static void dequote (std::string&); - - // Helpers. - bool isEOS () const; - int hexToInt (int) const; - int hexToInt (int, int) const; - int hexToInt (int, int, int, int) const; - - // Classifiers. - bool isString (std::string&, Lexer::Type&, int quote); + static const std::string typeName (const Lexer::Type&); + static bool isWhitespace (int); + static bool isAlpha (int); + static bool isDigit (int); + static bool isHexDigit (int); + static bool isIdentifierStart (int); + static bool isIdentifierNext (int); + static bool isSingleCharOperator (int); + static bool isDoubleCharOperator (int, int, int); + static bool isTripleCharOperator (int, int, int, int); + static bool isBoundary (int, int); + static bool isHardBoundary (int, int); + static bool isPunctuation (int); + static bool isAllDigits (const std::string&); + static bool isDOM (const std::string&); + static void dequote (std::string&, const std::string& quotes = "'\""); + static bool wasQuoted (const std::string&); + static bool readWord (const std::string&, const std::string&, std::string::size_type&, std::string&); + static bool readWord (const std::string&, std::string::size_type&, std::string&); + static bool decomposePair (const std::string&, std::string&, std::string&, std::string&, std::string&); + static bool decomposeSubstitution (const std::string&, std::string&, std::string&, std::string&); + static bool decomposePattern (const std::string&, std::string&, std::string&); + static int hexToInt (int); + static int hexToInt (int, int); + static int hexToInt (int, int, int, int); + static std::string::size_type commonLength (const std::string&, const std::string&); + static std::string::size_type commonLength (const std::string&, std::string::size_type, const std::string&, std::string::size_type); + + // Stream Classifiers. + bool isEOS () const; + bool isString (std::string&, Lexer::Type&, const std::string&); bool isDate (std::string&, Lexer::Type&); bool isDuration (std::string&, Lexer::Type&); - bool isUUID (std::string&, Lexer::Type&); + bool isUUID (std::string&, Lexer::Type&, bool); bool isNumber (std::string&, Lexer::Type&); + bool isInteger (std::string&, Lexer::Type&); bool isHexNumber (std::string&, Lexer::Type&); bool isSeparator (std::string&, Lexer::Type&); - bool isList (std::string&, Lexer::Type&); bool isURL (std::string&, Lexer::Type&); bool isPair (std::string&, Lexer::Type&); + bool isSet (std::string&, Lexer::Type&); bool isTag (std::string&, Lexer::Type&); bool isPath (std::string&, Lexer::Type&); bool isSubstitution (std::string&, Lexer::Type&); @@ -101,12 +109,14 @@ bool isDOM (std::string&, Lexer::Type&); bool isIdentifier (std::string&, Lexer::Type&); bool isWord (std::string&, Lexer::Type&); + bool isLiteral (const std::string&, bool, bool); + bool isOneOf (const std::vector &, bool, bool); + bool isOneOf (const std::map &, bool, bool); private: std::string _text; std::size_t _cursor; std::size_t _eos; - bool _ambiguity; }; #endif diff -Nru task-2.4.4+dfsg/src/main.h task-2.5.0+dfsg/src/main.h --- task-2.4.4+dfsg/src/main.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/main.h 2015-10-21 21:18:15.000000000 +0000 @@ -27,20 +27,18 @@ #ifndef INCLUDED_MAIN #define INCLUDED_MAIN -#define FEATURE_COLOR 1 // Enable color. - #include #include #include #include #include -#include +#include #include // recur.cpp void handleRecurrence (); -Date getNextRecurrence (Date&, std::string&); -bool generateDueDates (Task&, std::vector &); +ISO8601d getNextRecurrence (ISO8601d&, std::string&); +bool generateDueDates (Task&, std::vector &); void updateRecurrenceMask (Task&); bool nag (Task&); @@ -58,16 +56,15 @@ bool dependencyIsCircular (const Task&); void dependencyChainOnComplete (Task&); void dependencyChainOnStart (Task&); -void dependencyChainOnModify (Task&, Task&); // feedback.cpp -bool taskDiff (const Task&, const Task&); std::string taskDifferences (const Task&, const Task&); std::string taskInfoDifferences (const Task&, const Task&, const std::string&, long&, const long); std::string renderAttribute (const std::string&, const std::string&, const std::string& format = ""); void feedback_affected (const std::string&); void feedback_affected (const std::string&, int); void feedback_affected (const std::string&, const Task&); +void feedback_reserved_tags (const std::string&); void feedback_special_tags (const Task&, const std::string&); void feedback_unblocked (const Task&); void feedback_backlog (); @@ -79,10 +76,8 @@ void sort_tasks (std::vector &, std::vector &, const std::string&); // legacy.cpp -void legacyAttributeCheck (const std::string&); void legacyColumnMap (std::string&); void legacySortColumnMap (std::string&); -std::string legacyCheckForDeprecatedColor (); std::string legacyCheckForDeprecatedVariables (); std::string legacyCheckForDeprecatedColumns (); void legacyAttributeMap (std::string&); diff -Nru task-2.4.4+dfsg/src/Msg.cpp task-2.5.0+dfsg/src/Msg.cpp --- task-2.4.4+dfsg/src/Msg.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/Msg.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -38,62 +38,17 @@ } //////////////////////////////////////////////////////////////////////////////// -Msg::Msg (const Msg& other) -: _header (other._header) -, _payload (other._payload) -{ -} - -//////////////////////////////////////////////////////////////////////////////// -Msg& Msg::operator= (const Msg& other) -{ - if (this != &other) - { - _header = other._header; - _payload = other._payload; - } - - return *this; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Msg::operator== (const Msg& other) const -{ - return _header == other._header && - _payload == other._payload; -} - -//////////////////////////////////////////////////////////////////////////////// Msg::~Msg () { } //////////////////////////////////////////////////////////////////////////////// -void Msg::clear () -{ - _header.clear (); - _payload = ""; -} - -//////////////////////////////////////////////////////////////////////////////// -void Msg::set (const std::string& name, const int value) -{ - _header[name] = format (value); -} - -//////////////////////////////////////////////////////////////////////////////// void Msg::set (const std::string& name, const std::string& value) { _header[name] = value; } //////////////////////////////////////////////////////////////////////////////// -void Msg::set (const std::string& name, const double value) -{ - _header[name] = format (value); -} - -//////////////////////////////////////////////////////////////////////////////// void Msg::setPayload (const std::string& payload) { _payload = payload; @@ -102,8 +57,7 @@ //////////////////////////////////////////////////////////////////////////////// std::string Msg::get (const std::string& name) const { - std::map ::const_iterator i; - i = _header.find (name); + auto i = _header.find (name); if (i != _header.end ()) return i->second; @@ -119,9 +73,8 @@ //////////////////////////////////////////////////////////////////////////////// void Msg::all (std::vector & names) const { - std::map ::const_iterator i; - for (i = _header.begin (); i != _header.end (); ++i) - names.push_back (i->first); + for (auto& i : _header) + names.push_back (i.first); } //////////////////////////////////////////////////////////////////////////////// @@ -129,9 +82,8 @@ { std::string output; - std::map ::const_iterator i; - for (i = _header.begin (); i != _header.end (); ++i) - output += i->first + ": " + i->second + "\n"; + for (auto& i : _header) + output += i.first + ": " + i.second + "\n"; output += "\n" + _payload + "\n"; @@ -144,21 +96,20 @@ _header.clear (); _payload = ""; - std::string::size_type separator = input.find ("\n\n"); + auto separator = input.find ("\n\n"); if (separator == std::string::npos) throw std::string ("ERROR: Malformed message"); // Parse header. std::vector lines; split (lines, input.substr (0, separator), '\n'); - std::vector ::iterator i; - for (i = lines.begin (); i != lines.end (); ++i) + for (auto& i : lines) { - std::string::size_type delimiter = i->find (':'); + auto delimiter = i.find (':'); if (delimiter == std::string::npos) - throw std::string ("ERROR: Malformed message header '") + *i + "'"; + throw std::string ("ERROR: Malformed message header '") + i + "'"; - _header[trim (i->substr (0, delimiter))] = trim (i->substr (delimiter + 1)); + _header[trim (i.substr (0, delimiter))] = trim (i.substr (delimiter + 1)); } // Parse payload. diff -Nru task-2.4.4+dfsg/src/Msg.h task-2.5.0+dfsg/src/Msg.h --- task-2.4.4+dfsg/src/Msg.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/Msg.h 2015-10-21 21:18:15.000000000 +0000 @@ -35,16 +35,9 @@ { public: Msg (); - Msg (const Msg&); - Msg& operator= (const Msg&); - bool operator== (const Msg&) const; ~Msg (); - void clear (); - - void set (const std::string&, const int); void set (const std::string&, const std::string&); - void set (const std::string&, const double); void setPayload (const std::string&); std::string get (const std::string&) const; std::string getPayload () const; diff -Nru task-2.4.4+dfsg/src/Nibbler.cpp task-2.5.0+dfsg/src/Nibbler.cpp --- task-2.4.4+dfsg/src/Nibbler.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/Nibbler.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -31,21 +31,23 @@ #include #include #include +#include #ifdef NIBBLER_FEATURE_DATE -#include +#include #endif #ifdef NIBBLER_FEATURE_REGEX #include #endif #include +#include +#include static const char* _uuid_pattern = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; static const unsigned int _uuid_min_length = 8; //////////////////////////////////////////////////////////////////////////////// Nibbler::Nibbler () -: _input ("") -, _length (0) +: _length (0) , _cursor (0) , _saved (0) { @@ -53,7 +55,7 @@ //////////////////////////////////////////////////////////////////////////////// Nibbler::Nibbler (const std::string& input) -: _input (input) +: _input (std::make_shared (input)) , _length (input.length ()) , _cursor (0) { @@ -91,15 +93,15 @@ { if (_cursor < _length) { - std::string::size_type i = _input.find (c, _cursor); + auto i = _input->find (c, _cursor); if (i != std::string::npos) { - result = _input.substr (_cursor, i - _cursor); + result = _input->substr (_cursor, i - _cursor); _cursor = i; } else { - result = _input.substr (_cursor); + result = _input->substr (_cursor); _cursor = _length; } @@ -114,15 +116,15 @@ { if (_cursor < _length) { - std::string::size_type i = _input.find (terminator, _cursor); + auto i = _input->find (terminator, _cursor); if (i != std::string::npos) { - result = _input.substr (_cursor, i - _cursor); + result = _input->substr (_cursor, i - _cursor); _cursor = i; } else { - result = _input.substr (_cursor); + result = _input->substr (_cursor); _cursor = _length; } @@ -141,14 +143,14 @@ RX r (regex, true); std::vector start; std::vector end; - if (r.match (start, end, _input.substr (_cursor))) + if (r.match (start, end, _input->substr (_cursor))) { - result = _input.substr (_cursor, start[0]); + result = _input->substr (_cursor, start[0]); _cursor += start[0]; } else { - result = _input.substr (_cursor); + result = _input->substr (_cursor); _cursor = _length; } @@ -164,15 +166,15 @@ { if (_cursor < _length) { - std::string::size_type i = _input.find_first_of (chars, _cursor); + auto i = _input->find_first_of (chars, _cursor); if (i != std::string::npos) { - result = _input.substr (_cursor, i - _cursor); + result = _input->substr (_cursor, i - _cursor); _cursor = i; } else { - result = _input.substr (_cursor); + result = _input->substr (_cursor); _cursor = _length; } @@ -199,7 +201,7 @@ { if (_cursor < _length) { - result = _input.substr (_cursor); + result = _input->substr (_cursor); _cursor = _length; return true; } @@ -212,7 +214,7 @@ { if (_cursor + quantity <= _length) { - result = _input.substr (_cursor, quantity); + result = _input->substr (_cursor, quantity); _cursor += quantity; return true; } @@ -233,14 +235,14 @@ result = ""; if (_cursor >= _length || - _input[_cursor] != c) + (*_input)[_cursor] != c) { return false; } - for (std::string::size_type i = _cursor; i < _length; ++i) + for (auto i = _cursor; i < _length; ++i) { - current = _input[i]; + current = (*_input)[i]; if (current == '\\' && !inescape) { @@ -284,9 +286,9 @@ bool Nibbler::getDigit (int& result) { if (_cursor < _length && - Lexer::isDigit (_input[_cursor])) + Lexer::isDigit ((*_input)[_cursor])) { - result = _input[_cursor++] - '0'; + result = (*_input)[_cursor++] - '0'; return true; } @@ -296,18 +298,18 @@ //////////////////////////////////////////////////////////////////////////////// bool Nibbler::getDigit6 (int& result) { - std::string::size_type i = _cursor; + auto i = _cursor; if (i < _length && _length - i >= 6) { - if (Lexer::isDigit (_input[i + 0]) && - Lexer::isDigit (_input[i + 1]) && - Lexer::isDigit (_input[i + 2]) && - Lexer::isDigit (_input[i + 3]) && - Lexer::isDigit (_input[i + 4]) && - Lexer::isDigit (_input[i + 5])) + if (Lexer::isDigit ((*_input)[i + 0]) && + Lexer::isDigit ((*_input)[i + 1]) && + Lexer::isDigit ((*_input)[i + 2]) && + Lexer::isDigit ((*_input)[i + 3]) && + Lexer::isDigit ((*_input)[i + 4]) && + Lexer::isDigit ((*_input)[i + 5])) { - result = strtoimax (_input.substr (_cursor, 6).c_str (), NULL, 10); + result = strtoimax (_input->substr (_cursor, 6).c_str (), NULL, 10); _cursor += 6; return true; } @@ -319,16 +321,16 @@ //////////////////////////////////////////////////////////////////////////////// bool Nibbler::getDigit4 (int& result) { - std::string::size_type i = _cursor; + auto i = _cursor; if (i < _length && _length - i >= 4) { - if (Lexer::isDigit (_input[i + 0]) && - Lexer::isDigit (_input[i + 1]) && - Lexer::isDigit (_input[i + 2]) && - Lexer::isDigit (_input[i + 3])) + if (Lexer::isDigit ((*_input)[i + 0]) && + Lexer::isDigit ((*_input)[i + 1]) && + Lexer::isDigit ((*_input)[i + 2]) && + Lexer::isDigit ((*_input)[i + 3])) { - result = strtoimax (_input.substr (_cursor, 4).c_str (), NULL, 10); + result = strtoimax (_input->substr (_cursor, 4).c_str (), NULL, 10); _cursor += 4; return true; } @@ -340,15 +342,15 @@ //////////////////////////////////////////////////////////////////////////////// bool Nibbler::getDigit3 (int& result) { - std::string::size_type i = _cursor; + auto i = _cursor; if (i < _length && _length - i >= 3) { - if (Lexer::isDigit (_input[i + 0]) && - Lexer::isDigit (_input[i + 1]) && - Lexer::isDigit (_input[i + 2])) + if (Lexer::isDigit ((*_input)[i + 0]) && + Lexer::isDigit ((*_input)[i + 1]) && + Lexer::isDigit ((*_input)[i + 2])) { - result = strtoimax (_input.substr (_cursor, 3).c_str (), NULL, 10); + result = strtoimax (_input->substr (_cursor, 3).c_str (), NULL, 10); _cursor += 3; return true; } @@ -360,14 +362,14 @@ //////////////////////////////////////////////////////////////////////////////// bool Nibbler::getDigit2 (int& result) { - std::string::size_type i = _cursor; + auto i = _cursor; if (i < _length && _length - i >= 2) { - if (Lexer::isDigit (_input[i + 0]) && - Lexer::isDigit (_input[i + 1])) + if (Lexer::isDigit ((*_input)[i + 0]) && + Lexer::isDigit ((*_input)[i + 1])) { - result = strtoimax (_input.substr (_cursor, 2).c_str (), NULL, 10); + result = strtoimax (_input->substr (_cursor, 2).c_str (), NULL, 10); _cursor += 2; return true; } @@ -379,23 +381,23 @@ //////////////////////////////////////////////////////////////////////////////// bool Nibbler::getInt (int& result) { - std::string::size_type i = _cursor; + auto i = _cursor; if (i < _length) { - if (_input[i] == '-') + if ((*_input)[i] == '-') ++i; - else if (_input[i] == '+') + else if ((*_input)[i] == '+') ++i; } // TODO Potential for use of find_first_not_of - while (i < _length && Lexer::isDigit (_input[i])) + while (i < _length && Lexer::isDigit ((*_input)[i])) ++i; if (i > _cursor) { - result = strtoimax (_input.substr (_cursor, i - _cursor).c_str (), NULL, 10); + result = strtoimax (_input->substr (_cursor, i - _cursor).c_str (), NULL, 10); _cursor = i; return true; } @@ -406,14 +408,14 @@ //////////////////////////////////////////////////////////////////////////////// bool Nibbler::getUnsignedInt (int& result) { - std::string::size_type i = _cursor; + auto i = _cursor; // TODO Potential for use of find_first_not_of - while (i < _length && Lexer::isDigit (_input[i])) + while (i < _length && Lexer::isDigit ((*_input)[i])) ++i; if (i > _cursor) { - result = strtoimax (_input.substr (_cursor, i - _cursor).c_str (), NULL, 10); + result = strtoimax (_input->substr (_cursor, i - _cursor).c_str (), NULL, 10); _cursor = i; return true; } @@ -439,45 +441,45 @@ // bool Nibbler::getNumber (std::string& result) { - std::string::size_type i = _cursor; + auto i = _cursor; // [+-]? - if (i < _length && (_input[i] == '-' || _input[i] == '+')) + if (i < _length && ((*_input)[i] == '-' || (*_input)[i] == '+')) ++i; // digit+ - if (i < _length && Lexer::isDigit (_input[i])) + if (i < _length && Lexer::isDigit ((*_input)[i])) { ++i; - while (i < _length && Lexer::isDigit (_input[i])) + while (i < _length && Lexer::isDigit ((*_input)[i])) ++i; // ( . digit+ )? - if (i < _length && _input[i] == '.') + if (i < _length && (*_input)[i] == '.') { ++i; - while (i < _length && Lexer::isDigit (_input[i])) + while (i < _length && Lexer::isDigit ((*_input)[i])) ++i; } // ( [eE] [+-]? digit+ )? - if (i < _length && (_input[i] == 'e' || _input[i] == 'E')) + if (i < _length && ((*_input)[i] == 'e' || (*_input)[i] == 'E')) { ++i; - if (i < _length && (_input[i] == '+' || _input[i] == '-')) + if (i < _length && ((*_input)[i] == '+' || (*_input)[i] == '-')) ++i; - if (i < _length && Lexer::isDigit (_input[i])) + if (i < _length && Lexer::isDigit ((*_input)[i])) { ++i; - while (i < _length && Lexer::isDigit (_input[i])) + while (i < _length && Lexer::isDigit ((*_input)[i])) ++i; - result = _input.substr (_cursor, i - _cursor); + result = _input->substr (_cursor, i - _cursor); _cursor = i; return true; } @@ -485,7 +487,7 @@ return false; } - result = _input.substr (_cursor, i - _cursor); + result = _input->substr (_cursor, i - _cursor); _cursor = i; return true; } @@ -508,78 +510,10 @@ } //////////////////////////////////////////////////////////////////////////////// -// number: -// int frac? exp? -// -// int: -// digit+ -// -// frac: -// . digit+ -// -// exp: -// e digit+ -// -// e: -// e|E (+|-)? -// -bool Nibbler::getUnsignedNumber (double& result) -{ - std::string::size_type i = _cursor; - - // digit+ - if (i < _length && Lexer::isDigit (_input[i])) - { - ++i; - - while (i < _length && Lexer::isDigit (_input[i])) - ++i; - - // ( . digit+ )? - if (i < _length && _input[i] == '.') - { - ++i; - - while (i < _length && Lexer::isDigit (_input[i])) - ++i; - } - - // ( [eE] [+-]? digit+ )? - if (i < _length && (_input[i] == 'e' || _input[i] == 'E')) - { - ++i; - - if (i < _length && (_input[i] == '+' || _input[i] == '-')) - ++i; - - if (i < _length && Lexer::isDigit (_input[i])) - { - ++i; - - while (i < _length && Lexer::isDigit (_input[i])) - ++i; - - result = strtof (_input.substr (_cursor, i - _cursor).c_str (), NULL); - _cursor = i; - return true; - } - - return false; - } - - result = strtof (_input.substr (_cursor, i - _cursor).c_str (), NULL); - _cursor = i; - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// bool Nibbler::getLiteral (const std::string& literal) { if (_cursor < _length && - _input.find (literal, _cursor) == _cursor) + _input->find (literal, _cursor) == _cursor) { _cursor += literal.length (); return true; @@ -604,7 +538,7 @@ RX r (modified_regex, true); std::vector results; - if (r.match (results, _input.substr (_cursor))) + if (r.match (results, _input->substr (_cursor))) { result = results[0]; _cursor += result.length (); @@ -619,50 +553,50 @@ //////////////////////////////////////////////////////////////////////////////// bool Nibbler::getUUID (std::string& result) { - std::string::size_type i = _cursor; + auto i = _cursor; if (i < _length && _length - i >= 36) { // 88888888-4444-4444-4444-cccccccccccc - if (isxdigit (_input[i + 0]) && - isxdigit (_input[i + 1]) && - isxdigit (_input[i + 2]) && - isxdigit (_input[i + 3]) && - isxdigit (_input[i + 4]) && - isxdigit (_input[i + 5]) && - isxdigit (_input[i + 6]) && - isxdigit (_input[i + 7]) && - _input[i + 8] == '-' && - isxdigit (_input[i + 9]) && - isxdigit (_input[i + 10]) && - isxdigit (_input[i + 11]) && - isxdigit (_input[i + 12]) && - _input[i + 13] == '-' && - isxdigit (_input[i + 14]) && - isxdigit (_input[i + 15]) && - isxdigit (_input[i + 16]) && - isxdigit (_input[i + 17]) && - _input[i + 18] == '-' && - isxdigit (_input[i + 19]) && - isxdigit (_input[i + 20]) && - isxdigit (_input[i + 21]) && - isxdigit (_input[i + 22]) && - _input[i + 23] == '-' && - isxdigit (_input[i + 24]) && - isxdigit (_input[i + 25]) && - isxdigit (_input[i + 26]) && - isxdigit (_input[i + 27]) && - isxdigit (_input[i + 28]) && - isxdigit (_input[i + 29]) && - isxdigit (_input[i + 30]) && - isxdigit (_input[i + 31]) && - isxdigit (_input[i + 32]) && - isxdigit (_input[i + 33]) && - isxdigit (_input[i + 34]) && - isxdigit (_input[i + 35])) + if (isxdigit ((*_input)[i + 0]) && + isxdigit ((*_input)[i + 1]) && + isxdigit ((*_input)[i + 2]) && + isxdigit ((*_input)[i + 3]) && + isxdigit ((*_input)[i + 4]) && + isxdigit ((*_input)[i + 5]) && + isxdigit ((*_input)[i + 6]) && + isxdigit ((*_input)[i + 7]) && + (*_input)[i + 8] == '-' && + isxdigit ((*_input)[i + 9]) && + isxdigit ((*_input)[i + 10]) && + isxdigit ((*_input)[i + 11]) && + isxdigit ((*_input)[i + 12]) && + (*_input)[i + 13] == '-' && + isxdigit ((*_input)[i + 14]) && + isxdigit ((*_input)[i + 15]) && + isxdigit ((*_input)[i + 16]) && + isxdigit ((*_input)[i + 17]) && + (*_input)[i + 18] == '-' && + isxdigit ((*_input)[i + 19]) && + isxdigit ((*_input)[i + 20]) && + isxdigit ((*_input)[i + 21]) && + isxdigit ((*_input)[i + 22]) && + (*_input)[i + 23] == '-' && + isxdigit ((*_input)[i + 24]) && + isxdigit ((*_input)[i + 25]) && + isxdigit ((*_input)[i + 26]) && + isxdigit ((*_input)[i + 27]) && + isxdigit ((*_input)[i + 28]) && + isxdigit ((*_input)[i + 29]) && + isxdigit ((*_input)[i + 30]) && + isxdigit ((*_input)[i + 31]) && + isxdigit ((*_input)[i + 32]) && + isxdigit ((*_input)[i + 33]) && + isxdigit ((*_input)[i + 34]) && + isxdigit ((*_input)[i + 35])) { - result = _input.substr (_cursor, 36); + result = _input->substr (_cursor, 36); _cursor = i + 36; return true; } @@ -677,10 +611,10 @@ std::string::size_type i; for (i = 0; i < 36 && i < (_length - _cursor); i++) { - if (_uuid_pattern[i] == 'x' && !isxdigit (_input[_cursor + i])) + if (_uuid_pattern[i] == 'x' && !isxdigit ((*_input)[_cursor + i])) break; - else if (_uuid_pattern[i] == '-' && _input[_cursor + i] != '-') + else if (_uuid_pattern[i] == '-' && (*_input)[_cursor + i] != '-') break; } @@ -689,10 +623,10 @@ { // Fail if there is another hex digit. if (_cursor + i < _length && - isxdigit (_input[_cursor + i])) + isxdigit ((*_input)[_cursor + i])) return false; - result = _input.substr (_cursor, i); + result = _input->substr (_cursor, i); _cursor += i; return true; @@ -705,52 +639,52 @@ // 19980119T070000Z = YYYYMMDDThhmmssZ bool Nibbler::getDateISO (time_t& t) { - std::string::size_type i = _cursor; + auto i = _cursor; if (i < _length && _length - i >= 16) { - if (Lexer::isDigit (_input[i + 0]) && - Lexer::isDigit (_input[i + 1]) && - Lexer::isDigit (_input[i + 2]) && - Lexer::isDigit (_input[i + 3]) && - Lexer::isDigit (_input[i + 4]) && - Lexer::isDigit (_input[i + 5]) && - Lexer::isDigit (_input[i + 6]) && - Lexer::isDigit (_input[i + 7]) && - _input[i + 8] == 'T' && - Lexer::isDigit (_input[i + 9]) && - Lexer::isDigit (_input[i + 10]) && - Lexer::isDigit (_input[i + 11]) && - Lexer::isDigit (_input[i + 12]) && - Lexer::isDigit (_input[i + 13]) && - Lexer::isDigit (_input[i + 14]) && - _input[i + 15] == 'Z') + if (Lexer::isDigit ((*_input)[i + 0]) && + Lexer::isDigit ((*_input)[i + 1]) && + Lexer::isDigit ((*_input)[i + 2]) && + Lexer::isDigit ((*_input)[i + 3]) && + Lexer::isDigit ((*_input)[i + 4]) && + Lexer::isDigit ((*_input)[i + 5]) && + Lexer::isDigit ((*_input)[i + 6]) && + Lexer::isDigit ((*_input)[i + 7]) && + (*_input)[i + 8] == 'T' && + Lexer::isDigit ((*_input)[i + 9]) && + Lexer::isDigit ((*_input)[i + 10]) && + Lexer::isDigit ((*_input)[i + 11]) && + Lexer::isDigit ((*_input)[i + 12]) && + Lexer::isDigit ((*_input)[i + 13]) && + Lexer::isDigit ((*_input)[i + 14]) && + (*_input)[i + 15] == 'Z') { _cursor += 16; - int year = (_input[i + 0] - '0') * 1000 - + (_input[i + 1] - '0') * 100 - + (_input[i + 2] - '0') * 10 - + (_input[i + 3] - '0'); + int year = ((*_input)[i + 0] - '0') * 1000 + + ((*_input)[i + 1] - '0') * 100 + + ((*_input)[i + 2] - '0') * 10 + + ((*_input)[i + 3] - '0'); - int month = (_input[i + 4] - '0') * 10 - + (_input[i + 5] - '0'); + int month = ((*_input)[i + 4] - '0') * 10 + + ((*_input)[i + 5] - '0'); - int day = (_input[i + 6] - '0') * 10 - + (_input[i + 7] - '0'); + int day = ((*_input)[i + 6] - '0') * 10 + + ((*_input)[i + 7] - '0'); - int hour = (_input[i + 9] - '0') * 10 - + (_input[i + 10] - '0'); + int hour = ((*_input)[i + 9] - '0') * 10 + + ((*_input)[i + 10] - '0'); - int minute = (_input[i + 11] - '0') * 10 - + (_input[i + 12] - '0'); + int minute = ((*_input)[i + 11] - '0') * 10 + + ((*_input)[i + 12] - '0'); - int second = (_input[i + 13] - '0') * 10 - + (_input[i + 14] - '0'); + int second = ((*_input)[i + 13] - '0') * 10 + + ((*_input)[i + 14] - '0'); // Convert to epoch. - struct tm tms = {0}; + struct tm tms {}; tms.tm_isdst = -1; // Requests that mktime determine summer time effect. tms.tm_mon = month - 1; tms.tm_mday = day; @@ -774,7 +708,8 @@ // Parse the longest integer using the next 'limit' characters of 'result' // following position 'i' (when strict is true, the number of digits must be // equal to limit). -bool Nibbler::parseDigits(std::string::size_type& i, +bool Nibbler::parseDigits( + std::string::size_type& i, int& result, unsigned int limit, bool strict /* = true */) @@ -790,15 +725,15 @@ // Check that 'f' of them are digits unsigned int g; for (g = 0; g < f; g++) - if (! Lexer::isDigit (_input[i + g])) + if (! Lexer::isDigit ((*_input)[i + g])) break; // Parse the integer when it is the case if (g == f) { if (f == 1) - result = _input[i] - '0'; + result = (*_input)[i] - '0'; else - result = atoi (_input.substr (i, f).c_str ()); + result = atoi (_input->substr (i, f).c_str ()); // Update the global cursor before returning i += f; return true; @@ -815,7 +750,7 @@ #ifdef NIBBLER_FEATURE_DATE bool Nibbler::getDate (const std::string& format, time_t& t) { - std::string::size_type i = _cursor; + auto i = _cursor; int month = -1; // So we can check later. int day = -1; @@ -881,12 +816,12 @@ case 'a': case 'A': if (i + 3 <= _length && - ! Lexer::isDigit (_input[i + 0]) && - ! Lexer::isDigit (_input[i + 1]) && - ! Lexer::isDigit (_input[i + 2])) + ! Lexer::isDigit ((*_input)[i + 0]) && + ! Lexer::isDigit ((*_input)[i + 1]) && + ! Lexer::isDigit ((*_input)[i + 2])) { - wday = Date::dayOfWeek (_input.substr (i, 3).c_str ()); - i += (format[f] == 'a') ? 3 : Date::dayName (wday).size (); + wday = ISO8601d::dayOfWeek (_input->substr (i, 3).c_str ()); + i += (format[f] == 'a') ? 3 : ISO8601d::dayName (wday).size (); } else return false; @@ -895,14 +830,14 @@ case 'b': case 'B': if (i + 3 <= _length && - ! Lexer::isDigit (_input[i + 0]) && - ! Lexer::isDigit (_input[i + 1]) && - ! Lexer::isDigit (_input[i + 2])) + ! Lexer::isDigit ((*_input)[i + 0]) && + ! Lexer::isDigit ((*_input)[i + 1]) && + ! Lexer::isDigit ((*_input)[i + 2])) { if (month != -1) return false; - month = Date::monthOfYear (_input.substr (i, 3).c_str()); - i += (format[f] == 'b') ? 3 : Date::monthName (month).size (); + month = ISO8601d::monthOfYear (_input->substr (i, 3).c_str()); + i += (format[f] == 'b') ? 3 : ISO8601d::monthName (month).size (); } else return false; @@ -910,7 +845,7 @@ default: if (i + 1 <= _length && - _input[i] == format[f]) + (*_input)[i] == format[f]) ++i; else return false; @@ -924,7 +859,7 @@ // now. if (year == -1) { - Date now = Date (); + ISO8601d now; year = now.year (); if (month == -1) { @@ -955,11 +890,11 @@ second = (second == -1) ? 0 : second; // Check that values are correct - if (! Date::valid (month, day, year, hour, minute, second)) + if (! ISO8601d::valid (month, day, year, hour, minute, second)) return false; // Convert to epoch. - struct tm tms = {0}; + struct tm tms {}; tms.tm_isdst = -1; // Requests that mktime determine summer time effect. tms.tm_mon = month - 1; tms.tm_mday = day; @@ -982,12 +917,11 @@ const std::vector & options, std::string& found) { - std::vector ::const_iterator option; - for (option = options.begin (); option != options.end (); ++option) + for (auto& option : options) { - if (getLiteral (*option)) + if (getLiteral (option)) { - found = *option; + found = option; return true; } } @@ -999,18 +933,18 @@ // A name is a string of alpha-numeric characters. bool Nibbler::getName (std::string& result) { - std::string::size_type i = _cursor; + auto i = _cursor; if (i < _length) { - if (! Lexer::isDigit (_input[i]) && - ! ispunct (_input[i]) && - ! Lexer::isWhitespace (_input[i])) + if (! Lexer::isDigit ((*_input)[i]) && + ! ispunct ((*_input)[i]) && + ! Lexer::isWhitespace ((*_input)[i])) { ++i; while (i < _length && - (_input[i] == '_' || ! ispunct (_input[i])) && - ! Lexer::isWhitespace (_input[i])) + ((*_input)[i] == '_' || ! ispunct ((*_input)[i])) && + ! Lexer::isWhitespace ((*_input)[i])) { ++i; } @@ -1018,7 +952,7 @@ if (i > _cursor) { - result = _input.substr (_cursor, i - _cursor); + result = _input->substr (_cursor, i - _cursor); _cursor = i; return true; } @@ -1031,20 +965,20 @@ // A word is a contiguous string of non-space, non-digit, non-punct characters. bool Nibbler::getWord (std::string& result) { - std::string::size_type i = _cursor; + auto i = _cursor; if (i < _length) { - while (!Lexer::isDigit (_input[i]) && - !Lexer::isPunctuation (_input[i]) && - !Lexer::isWhitespace (_input[i])) + while (!Lexer::isDigit ((*_input)[i]) && + !Lexer::isPunctuation ((*_input)[i]) && + !Lexer::isWhitespace ((*_input)[i])) { ++i; } if (i > _cursor) { - result = _input.substr (_cursor, i - _cursor); + result = _input->substr (_cursor, i - _cursor); _cursor = i; return true; } @@ -1070,7 +1004,7 @@ bool Nibbler::skip (char c) { if (_cursor < _length && - _input[_cursor] == c) + (*_input)[_cursor] == c) { ++_cursor; return true; @@ -1084,7 +1018,7 @@ { if (_cursor < _length) { - std::string::size_type i = _input.find_first_not_of (c, _cursor); + auto i = _input->find_first_not_of (c, _cursor); if (i == _cursor) return false; @@ -1121,7 +1055,7 @@ RX r (modified_regex, true); std::vector results; - if (r.match (results, _input.substr (_cursor))) + if (r.match (results, _input->substr (_cursor))) { _cursor += results[0].length (); return true; @@ -1145,19 +1079,11 @@ } //////////////////////////////////////////////////////////////////////////////// -void Nibbler::getRemainder (std::string& result) -{ - if (_cursor < _length) - result = _input.substr (_cursor); -} - - -//////////////////////////////////////////////////////////////////////////////// bool Nibbler::skipAllOneOf (const std::string& chars) { if (_cursor < _length) { - std::string::size_type i = _input.find_first_not_of (chars, _cursor); + auto i = _input->find_first_not_of (chars, _cursor); if (i == _cursor) return false; @@ -1177,7 +1103,7 @@ char Nibbler::next () { if (_cursor < _length) - return _input[_cursor]; + return (*_input)[_cursor]; return '\0'; } @@ -1195,7 +1121,7 @@ if ( _cursor < _length && (unsigned) quantity <= _length && _cursor <= _length - quantity) - return _input.substr (_cursor, quantity); + return _input->substr (_cursor, quantity); return ""; } @@ -1215,7 +1141,7 @@ //////////////////////////////////////////////////////////////////////////////// const std::string& Nibbler::str () const { - return _input; + return *_input; } //////////////////////////////////////////////////////////////////////////////// @@ -1231,7 +1157,7 @@ std::string Nibbler::dump () { return std::string ("Nibbler ‹") - + _input.substr (_cursor) + + _input->substr (_cursor) + "›"; } diff -Nru task-2.4.4+dfsg/src/Nibbler.h task-2.5.0+dfsg/src/Nibbler.h --- task-2.4.4+dfsg/src/Nibbler.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/Nibbler.h 2015-10-21 21:18:15.000000000 +0000 @@ -36,6 +36,7 @@ #include #include #include +#include class Nibbler { @@ -56,10 +57,6 @@ bool getUntilEOL (std::string&); bool getUntilEOS (std::string&); -/* - bool getAllOneOf (const std::string&, std::string&); -*/ - bool getN (const int, std::string&); bool getQuoted (char, std::string&, bool quote = false); bool getDigit (int&); @@ -71,7 +68,6 @@ bool getUnsignedInt (int&); bool getNumber (std::string&); bool getNumber (double&); - bool getUnsignedNumber (double&); bool getLiteral (const std::string&); #ifdef NIBBLER_FEATURE_REGEX bool getRx (const std::string&, std::string&); @@ -98,8 +94,6 @@ bool backN (const int quantity = 1); - void getRemainder (std::string&); - char next (); std::string next (const int quantity); @@ -113,7 +107,7 @@ std::string dump (); private: - std::string _input; + std::shared_ptr _input; std::string::size_type _length; std::string::size_type _cursor; std::string::size_type _saved; diff -Nru task-2.4.4+dfsg/src/Path.cpp task-2.5.0+dfsg/src/Path.cpp --- task-2.4.4+dfsg/src/Path.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/Path.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,301 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// Fixes build with musl libc. -#ifndef GLOB_TILDE -#define GLOB_TILDE 0 -#endif - -#ifndef GLOB_BRACE -#define GLOB_BRACE 0 -#endif - -//////////////////////////////////////////////////////////////////////////////// -std::ostream& operator<< (std::ostream& out, const Path& path) -{ - out << path._data; - return out; -} - -//////////////////////////////////////////////////////////////////////////////// -Path::Path () -{ -} - -//////////////////////////////////////////////////////////////////////////////// -Path::Path (const Path& other) -{ - if (this != &other) - { - _original = other._original; - _data = other._data; - } -} - -//////////////////////////////////////////////////////////////////////////////// -Path::Path (const std::string& in) -{ - _original = in; - _data = expand (in); -} - -//////////////////////////////////////////////////////////////////////////////// -Path::~Path () -{ -} - -//////////////////////////////////////////////////////////////////////////////// -Path& Path::operator= (const Path& other) -{ - if (this != &other) - { - this->_original = other._original; - this->_data = other._data; - } - - return *this; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Path::operator== (const Path& other) -{ - return _data == other._data; -} - -//////////////////////////////////////////////////////////////////////////////// -Path& Path::operator+= (const std::string& dir) -{ - _data += "/" + dir; - return *this; -} - -//////////////////////////////////////////////////////////////////////////////// -Path::operator std::string () const -{ - return _data; -} - -//////////////////////////////////////////////////////////////////////////////// -std::string Path::name () const -{ - if (_data.length ()) - { - std::string::size_type slash = _data.rfind ('/'); - if (slash != std::string::npos) - return _data.substr (slash + 1, std::string::npos); - } - - return _data; -} - -//////////////////////////////////////////////////////////////////////////////// -std::string Path::parent () const -{ - if (_data.length ()) - { - std::string::size_type slash = _data.rfind ('/'); - if (slash != std::string::npos) - return _data.substr (0, slash); - } - - return ""; -} - -//////////////////////////////////////////////////////////////////////////////// -std::string Path::extension () const -{ - if (_data.length ()) - { - std::string::size_type dot = _data.rfind ('.'); - if (dot != std::string::npos) - return _data.substr (dot + 1, std::string::npos); - } - - return ""; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Path::exists () const -{ - return access (_data.c_str (), F_OK) ? false : true; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Path::is_directory () const -{ - struct stat s = {0}; - if (! stat (_data.c_str (), &s) && - S_ISDIR (s.st_mode)) - return true; - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Path::is_absolute () const -{ - if (_data.length () && _data[0] == '/') - return true; - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Path::is_link () const -{ - struct stat s = {0}; - if (! lstat (_data.c_str (), &s) && - S_ISLNK (s.st_mode)) - return true; - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Path::readable () const -{ - return access (_data.c_str (), R_OK) ? false : true; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Path::writable () const -{ - return access (_data.c_str (), W_OK) ? false : true; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Path::executable () const -{ - return access (_data.c_str (), X_OK) ? false : true; -} - -//////////////////////////////////////////////////////////////////////////////// -bool Path::rename (const std::string& new_name) -{ - std::string expanded = expand (new_name); - if (_data != expanded) - { - if (::rename (_data.c_str (), expanded.c_str ()) == 0) - { - _data = expanded; - return true; - } - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// ~ --> /home/user -// ~foo/x --> /home/foo/s -// ~/x --> /home/foo/x -// ./x --> $PWD/x -// x --> $PWD/x -std::string Path::expand (const std::string& in) -{ - std::string copy = in; - - std::string::size_type tilde = copy.find ("~"); - std::string::size_type slash; - - if (tilde != std::string::npos) - { - const char *home = getenv("HOME"); - if (home == NULL) - { - struct passwd* pw = getpwuid (getuid ()); - home = pw->pw_dir; - } - - // Convert: ~ --> /home/user - if (copy.length () == 1) - copy = home; - - // Convert: ~/x --> /home/user/x - else if (copy.length () > tilde + 1 && - copy[tilde + 1] == '/') - { - copy.replace (tilde, 1, home); - } - - // Convert: ~foo/x --> /home/foo/x - else if ((slash = copy.find ("/", tilde)) != std::string::npos) - { - std::string name = copy.substr (tilde + 1, slash - tilde - 1); - struct passwd* pw = getpwnam (name.c_str ()); - if (pw) - copy.replace (tilde, slash - tilde, pw->pw_dir); - } - } - - // Relative paths - else if (in.length () > 2 && - in.substr (0, 2) == "./") - { - copy = Directory::cwd () + "/" + in.substr (2); - } - else if (in.length () > 1 && - in[0] != '.' && - in[0] != '/') - { - copy = Directory::cwd () + "/" + in; - } - - return copy; -} - -//////////////////////////////////////////////////////////////////////////////// -std::vector Path::glob (const std::string& pattern) -{ - std::vector results; - - glob_t g; -#ifdef SOLARIS - if (!::glob (pattern.c_str (), GLOB_ERR, NULL, &g)) -#else - if (!::glob (pattern.c_str (), GLOB_ERR | GLOB_BRACE | GLOB_TILDE, NULL, &g)) -#endif - for (int i = 0; i < (int) g.gl_pathc; ++i) - results.push_back (g.gl_pathv[i]); - - globfree (&g); - return results; -} - -//////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/Path.h task-2.5.0+dfsg/src/Path.h --- task-2.4.4+dfsg/src/Path.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/Path.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,70 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// 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 -// -//////////////////////////////////////////////////////////////////////////////// - -#ifndef INCLUDED_PATH -#define INCLUDED_PATH - -#include -#include - -class Path -{ -public: - Path (); - Path (const Path&); - Path (const std::string&); - virtual ~Path (); - - Path& operator= (const Path&); - bool operator== (const Path&); - Path& operator+= (const std::string&); - operator std::string () const; - - std::string name () const; - std::string parent () const; - std::string extension () const; - bool exists () const; - bool is_directory () const; - bool is_absolute () const; - bool is_link () const; - bool readable () const; - bool writable () const; - bool executable () const; - bool rename (const std::string&); - - // Statics - static std::string expand (const std::string&); - static std::vector glob (const std::string&); - -public: - std::string _original; - std::string _data; -}; - -std::ostream& operator<< (std::ostream&, const Path&); - -#endif -//////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/recur.cpp task-2.5.0+dfsg/src/recur.cpp --- task-2.4.4+dfsg/src/recur.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/recur.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -38,8 +39,6 @@ #include #include -#include -#include #include #include #include @@ -60,56 +59,54 @@ if (! context.config.getBoolean ("recurrence")) return; - std::vector tasks = context.tdb2.pending.get_tasks (); - Date now; + auto tasks = context.tdb2.pending.get_tasks (); + ISO8601d now; // Look at all tasks and find any recurring ones. - std::vector ::iterator t; - for (t = tasks.begin (); t != tasks.end (); ++t) + for (auto& t : tasks) { - if (t->getStatus () == Task::recurring) + if (t.getStatus () == Task::recurring) { // Generate a list of due dates for this recurring task, regardless of // the mask. - std::vector due; - if (!generateDueDates (*t, due)) + std::vector due; + if (!generateDueDates (t, due)) { // Determine the end date. - t->setStatus (Task::deleted); - context.tdb2.modify (*t); - context.footnote (onExpiration (*t)); + t.setStatus (Task::deleted); + context.tdb2.modify (t); + context.footnote (onExpiration (t)); continue; } // Get the mask from the parent task. - std::string mask = t->get ("mask"); + std::string mask = t.get ("mask"); // Iterate over the due dates, and check each against the mask. bool changed = false; unsigned int i = 0; - std::vector ::iterator d; - for (d = due.begin (); d != due.end (); ++d) + for (auto& d : due) { if (mask.length () <= i) { changed = true; - Task rec (*t); // Clone the parent. + Task rec (t); // Clone the parent. rec.setStatus (Task::pending); // Change the status. rec.id = context.tdb2.next_id (); // New ID. rec.set ("uuid", uuid ()); // New UUID. - rec.set ("parent", t->get ("uuid")); // Remember mom. + rec.set ("parent", t.get ("uuid")); // Remember mom. rec.setAsNow ("entry"); // New entry date. char dueDate[16]; - sprintf (dueDate, "%u", (unsigned int) d->toEpoch ()); + sprintf (dueDate, "%u", (unsigned int) d.toEpoch ()); rec.set ("due", dueDate); // Store generated due date. - if (t->has ("wait")) + if (t.has ("wait")) { - Date old_wait (t->get_date ("wait")); - Date old_due (t->get_date ("due")); - Date due (*d); + ISO8601d old_wait (t.get_date ("wait")); + ISO8601d old_due (t.get_date ("due")); + ISO8601d due (d); sprintf (dueDate, "%u", (unsigned int) (due + (old_wait - old_due)).toEpoch ()); rec.set ("wait", dueDate); rec.setStatus (Task::waiting); @@ -137,20 +134,23 @@ // Only modify the parent if necessary. if (changed) { - t->set ("mask", mask); - context.tdb2.modify (*t); + t.set ("mask", mask); + context.tdb2.modify (t); + + if (context.verbose ("recur")) + context.footnote (format (STRING_RECUR_CREATE, t.get ("description"))); } } // Non-recurring tasks expire too. else { - if (t->has ("until") && - Date (t->get_date ("until")) < now) + if (t.has ("until") && + ISO8601d (t.get_date ("until")) < now) { - t->setStatus (Task::deleted); - context.tdb2.modify(*t); - context.footnote (onExpiration (*t)); + t.setStatus (Task::deleted); + context.tdb2.modify(t); + context.footnote (onExpiration (t)); } } } @@ -161,28 +161,28 @@ // period (recur). Then generate a set of corresponding dates. // // Returns false if the parent recurring task is depleted. -bool generateDueDates (Task& parent, std::vector & allDue) +bool generateDueDates (Task& parent, std::vector & allDue) { // Determine due date, recur period and until date. - Date due (parent.get_date ("due")); - if (due == 0) + ISO8601d due (parent.get_date ("due")); + if (due._date == 0) { return false; } std::string recur = parent.get ("recur"); bool specificEnd = false; - Date until; + ISO8601d until; if (parent.get ("until") != "") { - until = Date (parent.get ("until")); + until = ISO8601d (parent.get ("until")); specificEnd = true; } int recurrence_limit = context.config.getInteger ("recurrence.limit"); int recurrence_counter = 0; - Date now; - for (Date i = due; ; i = getNextRecurrence (i, recur)) + ISO8601d now; + for (ISO8601d i = due; ; i = getNextRecurrence (i, recur)) { allDue.push_back (i); @@ -210,14 +210,15 @@ } //////////////////////////////////////////////////////////////////////////////// -Date getNextRecurrence (Date& current, std::string& period) +ISO8601d getNextRecurrence (ISO8601d& current, std::string& period) { int m = current.month (); int d = current.day (); int y = current.year (); // Some periods are difficult, because they can be vague. - if (period == "monthly") + if (period == "monthly" || + period == "P1M") { if (++m > 12) { @@ -225,10 +226,10 @@ ++y; } - while (! Date::valid (m, d, y)) + while (! ISO8601d::valid (m, d, y)) --d; - return Date (m, d, y); + return ISO8601d (m, d, y); } else if (period == "weekdays") @@ -243,10 +244,10 @@ return current + (days * 86400); } - else if (Lexer::isDigit (period[0]) && period[period.length () - 1] == 'm') + else if (Lexer::isDigit (period[0]) && + period[period.length () - 1] == 'm') { - std::string numeric = period.substr (0, period.length () - 1); - int increment = atoi (numeric.c_str ()); + int increment = strtol (period.substr (0, period.length () - 1).c_str (), NULL, 10); m += increment; while (m > 12) @@ -255,13 +256,33 @@ ++y; } - while (! Date::valid (m, d, y)) + while (! ISO8601d::valid (m, d, y)) --d; - return Date (m, d, y); + return ISO8601d (m, d, y); } - else if (period == "quarterly") + else if (period[0] == 'P' && + Lexer::isAllDigits (period.substr (1, period.length () - 2)) && + period[period.length () - 1] == 'M') + { + int increment = strtol (period.substr (0, period.length () - 1).c_str (), NULL, 10); + + m += increment; + while (m > 12) + { + m -= 12; + ++y; + } + + while (! ISO8601d::valid (m, d, y)) + --d; + + return ISO8601d (m, d, y); + } + + else if (period == "quarterly" || + period == "P3M") { m += 3; if (m > 12) @@ -270,16 +291,15 @@ ++y; } - while (! Date::valid (m, d, y)) + while (! ISO8601d::valid (m, d, y)) --d; - return Date (m, d, y); + return ISO8601d (m, d, y); } else if (Lexer::isDigit (period[0]) && period[period.length () - 1] == 'q') { - std::string numeric = period.substr (0, period.length () - 1); - int increment = atoi (numeric.c_str ()); + int increment = strtol (period.substr (0, period.length () - 1).c_str (), NULL, 10); m += 3 * increment; while (m > 12) @@ -288,13 +308,14 @@ ++y; } - while (! Date::valid (m, d, y)) + while (! ISO8601d::valid (m, d, y)) --d; - return Date (m, d, y); + return ISO8601d (m, d, y); } - else if (period == "semiannual") + else if (period == "semiannual" || + period == "P6M") { m += 6; if (m > 12) @@ -303,13 +324,14 @@ ++y; } - while (! Date::valid (m, d, y)) + while (! ISO8601d::valid (m, d, y)) --d; - return Date (m, d, y); + return ISO8601d (m, d, y); } - else if (period == "bimonthly") + else if (period == "bimonthly" || + period == "P2M") { m += 2; if (m > 12) @@ -318,22 +340,24 @@ ++y; } - while (! Date::valid (m, d, y)) + while (! ISO8601d::valid (m, d, y)) --d; - return Date (m, d, y); + return ISO8601d (m, d, y); } - else if (period == "biannual" || - period == "biyearly") + else if (period == "biannual" || + period == "biyearly" || + period == "P2Y") { y += 2; - return Date (m, d, y); + return ISO8601d (m, d, y); } else if (period == "annual" || - period == "yearly") + period == "yearly" || + period == "P1Y") { y += 1; @@ -342,30 +366,17 @@ if (m == 2 && d == 29) d = 28; - return Date (m, d, y); + return ISO8601d (m, d, y); } - // If the period is an 'easy' one, add it to current, and we're done. - // If it throws an error, the duration was not recognized. + // Add the period to current, and we're done. int secs = 0; std::string::size_type idx = 0; - Duration du; - if (du.parse (period, idx)) - { - secs = du; - } - else - { - idx = 0; - ISO8601p p; - if (p.parse (period, idx)) - { - secs = p; - } - else - throw std::string (format (STRING_TASK_VALID_RECUR, period)); - } + ISO8601p p; + if (! p.parse (period, idx)) + throw std::string (format (STRING_TASK_VALID_RECUR, period)); + secs = (time_t) p; return current + secs; } @@ -424,14 +435,13 @@ std::string nagMessage = context.config.get ("nag"); if (nagMessage != "") { - // Load all pending tasks. - std::vector tasks = context.tdb2.pending.get_tasks (); - - // Scan all pending tasks. - std::vector ::iterator t; - for (t = tasks.begin (); t != tasks.end (); ++t) - { - if (t->urgency () > task.urgency ()) + // Scan all pending, non-recurring tasks. + auto pending = context.tdb2.pending.get_tasks (); + for (auto& t : pending) + { + if ((t.getStatus () == Task::pending || + t.getStatus () == Task::waiting) && + t.urgency () > task.urgency ()) { context.footnote (nagMessage); return true; diff -Nru task-2.4.4+dfsg/src/rules.cpp task-2.5.0+dfsg/src/rules.cpp --- task-2.4.4+dfsg/src/rules.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/rules.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -36,7 +36,7 @@ static std::map gsColor; static std::vector gsPrecedence; -static Date now; +static ISO8601d now; //////////////////////////////////////////////////////////////////////////////// void initializeColorRules () @@ -53,15 +53,14 @@ // Load all the configuration values, filter to only the ones that begin with // "color.", then store name/value in gsColor, and name in rules. std::vector rules; - Config::const_iterator v; - for (v = context.config.begin (); v != context.config.end (); ++v) + for (auto& v : context.config) { - if (v->first.substr (0, 6) == "color.") + if (v.first.substr (0, 6) == "color.") { - Color c (v->second); - gsColor[v->first] = c; + Color c (v.second); + gsColor[v.first] = c; - rules.push_back (v->first); + rules.push_back (v.first); } } @@ -71,16 +70,14 @@ std::vector precedence; split (precedence, context.config.get ("rule.precedence.color"), ','); - std::vector ::iterator p; - for (p = precedence.begin (); p != precedence.end (); ++p) + for (auto& p : precedence) { // Add the leading "color." string. - std::string rule = "color." + *p; + std::string rule = "color." + p; autoComplete (rule, rules, results, 3); // Hard-coded 3. - std::vector ::iterator r; - for (r = results.begin (); r != results.end (); ++r) - gsPrecedence.push_back (*r); + for (auto& r : results) + gsPrecedence.push_back (r); } } @@ -91,58 +88,68 @@ } //////////////////////////////////////////////////////////////////////////////// -static void colorizeBlocked (Task& task, const Color& base, Color& c) +static void applyColor (const Color& base, Color& c, bool merge) +{ + if (merge) + c.blend (base); + else + c = base; +} + + +//////////////////////////////////////////////////////////////////////////////// +static void colorizeBlocked (Task& task, const Color& base, Color& c, bool merge) { if (task.is_blocked) - c.blend (base); + applyColor (base, c, merge); } //////////////////////////////////////////////////////////////////////////////// -static void colorizeBlocking (Task& task, const Color& base, Color& c) +static void colorizeBlocking (Task& task, const Color& base, Color& c, bool merge) { if (task.is_blocking) - c.blend (base); + applyColor (base, c, merge); } //////////////////////////////////////////////////////////////////////////////// -static void colorizeTagged (Task& task, const Color& base, Color& c) +static void colorizeTagged (Task& task, const Color& base, Color& c, bool merge) { if (task.getTagCount ()) - c.blend (base); + applyColor (base, c, merge); } //////////////////////////////////////////////////////////////////////////////// -static void colorizeActive (Task& task, const Color& base, Color& c) +static void colorizeActive (Task& task, const Color& base, Color& c, bool merge) { if (task.has ("start") && !task.has ("end")) - c.blend (base); + applyColor (base, c, merge); } //////////////////////////////////////////////////////////////////////////////// -static void colorizeScheduled (Task& task, const Color& base, Color& c) +static void colorizeScheduled (Task& task, const Color& base, Color& c, bool merge) { if (task.has ("scheduled") && - Date (task.get_date ("scheduled")) <= now) - c.blend (base); + ISO8601d (task.get_date ("scheduled")) <= now) + applyColor (base, c, merge); } //////////////////////////////////////////////////////////////////////////////// -static void colorizeUntil (Task& task, const Color& base, Color& c) +static void colorizeUntil (Task& task, const Color& base, Color& c, bool merge) { if (task.has ("until")) - c.blend (base); + applyColor (base, c, merge); } //////////////////////////////////////////////////////////////////////////////// -static void colorizeTag (Task& task, const std::string& rule, const Color& base, Color& c) +static void colorizeTag (Task& task, const std::string& rule, const Color& base, Color& c, bool merge) { if (task.hasTag (rule.substr (10))) - c.blend (base); + applyColor (base, c, merge); } //////////////////////////////////////////////////////////////////////////////// -static void colorizeProject (Task& task, const std::string& rule, const Color& base, Color& c) +static void colorizeProject (Task& task, const std::string& rule, const Color& base, Color& c, bool merge) { // Observe the case sensitivity setting. bool sensitive = context.config.getBoolean ("search.case.sensitive"); @@ -153,25 +160,25 @@ // Match project names leftmost. if (rule_trunc.length () <= project.length ()) if (compare (rule_trunc, project.substr (0, rule_trunc.length ()), sensitive)) - c.blend (base); + applyColor (base, c, merge); } //////////////////////////////////////////////////////////////////////////////// -static void colorizeProjectNone (Task& task, const Color& base, Color& c) +static void colorizeProjectNone (Task& task, const Color& base, Color& c, bool merge) { if (task.get ("project") == "") - c.blend (base); + applyColor (base, c, merge); } //////////////////////////////////////////////////////////////////////////////// -static void colorizeTagNone (Task& task, const Color& base, Color& c) +static void colorizeTagNone (Task& task, const Color& base, Color& c, bool merge) { if (task.getTagCount () == 0) - c.blend (base); + applyColor (base, c, merge); } //////////////////////////////////////////////////////////////////////////////// -static void colorizeKeyword (Task& task, const std::string& rule, const Color& base, Color& c) +static void colorizeKeyword (Task& task, const std::string& rule, const Color& base, Color& c, bool merge) { // Observe the case sensitivity setting. bool sensitive = context.config.getBoolean ("search.case.sensitive"); @@ -179,19 +186,18 @@ // The easiest thing to check is the description, because it is just one // attribute. if (find (task.get ("description"), rule.substr (14), sensitive) != std::string::npos) - c.blend (base); + applyColor (base, c, merge); // Failing the description check, look at all annotations, returning on the // first match. else { - Task::iterator it; - for (it = task.begin (); it != task.end (); ++it) + for (auto& it : task) { - if (it->first.substr (0, 11) == "annotation_" && - find (it->second, rule.substr (14), sensitive) != std::string::npos) + if (it.first.substr (0, 11) == "annotation_" && + find (it.second, rule.substr (14), sensitive) != std::string::npos) { - c.blend (base); + applyColor (base, c, merge); return; } } @@ -199,26 +205,27 @@ } //////////////////////////////////////////////////////////////////////////////// -static void colorizeUDA (Task& task, const std::string& rule, const Color& base, Color& c) +static void colorizeUDA (Task& task, const std::string& rule, const Color& base, Color& c, bool merge) { - // Is the rule uda.name.value or uda.name? + // Is the rule color.uda.name.value or color.uda.name? size_t pos = rule.find (".", 10); if (pos == std::string::npos) { if (task.has (rule.substr (10))) - c.blend (base); + applyColor (base, c, merge); } else { const std::string uda = rule.substr (10, pos - 10); const std::string val = rule.substr (pos + 1); - if (task.get (uda) == val) - c.blend (base); + if ((val == "none" && ! task.has (uda)) || + task.get (uda) == val) + applyColor (base, c, merge); } } //////////////////////////////////////////////////////////////////////////////// -static void colorizeDue (Task& task, const Color& base, Color& c) +static void colorizeDue (Task& task, const Color& base, Color& c, bool merge) { if (task.has ("due")) { @@ -226,12 +233,12 @@ if (status != Task::completed && status != Task::deleted && task.getDateState ("due") == Task::dateAfterToday) - c.blend (base); + applyColor (base, c, merge); } } //////////////////////////////////////////////////////////////////////////////// -static void colorizeDueToday (Task& task, const Color& base, Color& c) +static void colorizeDueToday (Task& task, const Color& base, Color& c, bool merge) { if (task.has ("due")) { @@ -240,12 +247,12 @@ if (status != Task::completed && status != Task::deleted && (dateState == Task::dateLaterToday || dateState == Task::dateEarlierToday)) - c.blend (base); + applyColor (base, c, merge); } } //////////////////////////////////////////////////////////////////////////////// -static void colorizeOverdue (Task& task, const Color& base, Color& c) +static void colorizeOverdue (Task& task, const Color& base, Color& c, bool merge) { if (task.has ("due")) { @@ -253,29 +260,29 @@ if (status != Task::completed && status != Task::deleted && task.getDateState ("due") == Task::dateBeforeToday) - c.blend (base); + applyColor (base, c, merge); } } //////////////////////////////////////////////////////////////////////////////// -static void colorizeRecurring (Task& task, const Color& base, Color& c) +static void colorizeRecurring (Task& task, const Color& base, Color& c, bool merge) { if (task.has ("recur")) - c.blend (base); + applyColor (base, c, merge); } //////////////////////////////////////////////////////////////////////////////// -static void colorizeCompleted (Task& task, const Color& base, Color& c) +static void colorizeCompleted (Task& task, const Color& base, Color& c, bool merge) { if (task.getStatus () == Task::completed) - c.blend (base); + applyColor (base, c, merge); } //////////////////////////////////////////////////////////////////////////////// -static void colorizeDeleted (Task& task, const Color& base, Color& c) +static void colorizeDeleted (Task& task, const Color& base, Color& c, bool merge) { if (task.getStatus () == Task::deleted) - c.blend (base); + applyColor (base, c, merge); } //////////////////////////////////////////////////////////////////////////////// @@ -289,37 +296,40 @@ return; } + bool merge = context.config.getBoolean ("rule.color.merge"); + // Note: c already contains colors specifically assigned via command. // Note: These rules form a hierarchy - the last rule is King, hence the // reverse iterator. - std::vector ::reverse_iterator r; - for (r = gsPrecedence.rbegin (); r != gsPrecedence.rend (); ++r) + + for (auto r = gsPrecedence.rbegin (); r != gsPrecedence.rend (); ++r) { Color base = gsColor[*r]; if (base.nontrivial ()) { - if (*r == "color.blocked") colorizeBlocked (task, base, c); - else if (*r == "color.blocking") colorizeBlocking (task, base, c); - else if (*r == "color.tagged") colorizeTagged (task, base, c); - else if (*r == "color.active") colorizeActive (task, base, c); - else if (*r == "color.scheduled") colorizeScheduled (task, base, c); - else if (*r == "color.until") colorizeUntil (task, base, c); - else if (*r == "color.project.none") colorizeProjectNone (task, base, c); - else if (*r == "color.tag.none") colorizeTagNone (task, base, c); - else if (*r == "color.due") colorizeDue (task, base, c); - else if (*r == "color.due.today") colorizeDueToday (task, base, c); - else if (*r == "color.overdue") colorizeOverdue (task, base, c); - else if (*r == "color.recurring") colorizeRecurring (task, base, c); - else if (*r == "color.completed") colorizeCompleted (task, base, c); - else if (*r == "color.deleted") colorizeDeleted (task, base, c); + if (*r == "color.blocked") colorizeBlocked (task, base, c, merge); + else if (*r == "color.blocking") colorizeBlocking (task, base, c, merge); + else if (*r == "color.tagged") colorizeTagged (task, base, c, merge); + else if (*r == "color.active") colorizeActive (task, base, c, merge); + else if (*r == "color.scheduled") colorizeScheduled (task, base, c, merge); + else if (*r == "color.until") colorizeUntil (task, base, c, merge); + else if (*r == "color.project.none") colorizeProjectNone (task, base, c, merge); + else if (*r == "color.tag.none") colorizeTagNone (task, base, c, merge); + else if (*r == "color.due") colorizeDue (task, base, c, merge); + else if (*r == "color.due.today") colorizeDueToday (task, base, c, merge); + else if (*r == "color.overdue") colorizeOverdue (task, base, c, merge); + else if (*r == "color.recurring") colorizeRecurring (task, base, c, merge); + else if (*r == "color.completed") colorizeCompleted (task, base, c, merge); + else if (*r == "color.deleted") colorizeDeleted (task, base, c, merge); // Wildcards - else if (r->substr (0, 10) == "color.tag.") colorizeTag (task, *r, base, c); - else if (r->substr (0, 14) == "color.project.") colorizeProject (task, *r, base, c); - else if (r->substr (0, 14) == "color.keyword.") colorizeKeyword (task, *r, base, c); - else if (r->substr (0, 10) == "color.uda.") colorizeUDA (task, *r, base, c); + else if (r->substr (0, 10) == "color.tag.") colorizeTag (task, *r, base, c, merge); + else if (r->substr (0, 14) == "color.project.") colorizeProject (task, *r, base, c, merge); + else if (r->substr (0, 14) == "color.keyword.") colorizeKeyword (task, *r, base, c, merge); + else if (r->substr (0, 10) == "color.uda.") colorizeUDA (task, *r, base, c, merge); } } + } //////////////////////////////////////////////////////////////////////////////// diff -Nru task-2.4.4+dfsg/src/RX.cpp task-2.5.0+dfsg/src/RX.cpp --- task-2.4.4+dfsg/src/RX.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/RX.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -33,7 +33,7 @@ RX::RX () : _compiled (false) , _pattern ("") -, _case_sensitive (true) +, _case_sensitive (false) { } @@ -50,10 +50,17 @@ //////////////////////////////////////////////////////////////////////////////// RX::RX (const RX& other) -: _compiled (false) -, _pattern (other._pattern) -, _case_sensitive (other._case_sensitive) { + _compiled = false; + _pattern = other._pattern; + _case_sensitive = other._case_sensitive; +} + +//////////////////////////////////////////////////////////////////////////////// +RX::~RX () +{ + if (_compiled) + regfree (&_regex); } //////////////////////////////////////////////////////////////////////////////// @@ -61,8 +68,8 @@ { if (this != &other) { - _compiled = false; - _pattern = other._pattern; + _compiled = false; + _pattern = other._pattern; _case_sensitive = other._case_sensitive; } @@ -70,29 +77,19 @@ } //////////////////////////////////////////////////////////////////////////////// -bool RX::operator== (const RX& other) const -{ - return _pattern == other._pattern && - _case_sensitive == other._case_sensitive; -} - -//////////////////////////////////////////////////////////////////////////////// -RX::~RX () -{ - if (_compiled) - regfree (&_regex); -} - -//////////////////////////////////////////////////////////////////////////////// void RX::compile () { - if (!_compiled) + if (! _compiled) { memset (&_regex, 0, sizeof (regex_t)); int result; if ((result = regcomp (&_regex, _pattern.c_str (), +#ifdef DARWIN + REG_ENHANCED | REG_EXTENDED | REG_NEWLINE | +#else REG_EXTENDED | REG_NEWLINE | +#endif (_case_sensitive ? 0 : REG_ICASE))) != 0) { char message[256]; @@ -107,7 +104,7 @@ //////////////////////////////////////////////////////////////////////////////// bool RX::match (const std::string& in) { - if (!_compiled) + if (! _compiled) compile (); return regexec (&_regex, in.c_str (), 0, NULL, 0) == 0 ? true : false; @@ -118,7 +115,7 @@ std::vector& matches, const std::string& in) { - if (!_compiled) + if (! _compiled) compile (); regmatch_t rm[2]; @@ -144,7 +141,7 @@ std::vector & end, const std::string& in) { - if (!_compiled) + if (! _compiled) compile (); regmatch_t rm[2]; diff -Nru task-2.4.4+dfsg/src/RX.h task-2.5.0+dfsg/src/RX.h --- task-2.4.4+dfsg/src/RX.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/RX.h 2015-10-21 21:18:15.000000000 +0000 @@ -37,9 +37,8 @@ RX (); RX (const std::string&, bool caseSensitive = true); RX (const RX&); - RX& operator= (const RX&); - bool operator== (const RX&) const; ~RX (); + RX& operator= (const RX&); bool match (const std::string&); bool match (std::vector&, const std::string&); diff -Nru task-2.4.4+dfsg/src/sort.cpp task-2.5.0+dfsg/src/sort.cpp --- task-2.4.4+dfsg/src/sort.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/sort.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -30,8 +30,7 @@ #include #include #include -#include -#include +#include #include #include #include @@ -68,7 +67,6 @@ // require re-parsing. // // Essentially a static implementation of a dynamic operator<. -// UDA string values delegate to Variant::operator<. static bool sort_compare (int left, int right) { std::string field; @@ -80,10 +78,9 @@ float left_real; float right_real; - std::vector ::iterator k; - for (k = global_keys.begin (); k != global_keys.end (); ++k) + for (auto& k : global_keys) { - context.decomposeSortField (*k, field, ascending, breakIndicator); + context.decomposeSortField (k, field, ascending, breakIndicator); // Urgency. if (field == "urgency") @@ -132,26 +129,8 @@ } // Due Date. - else if (field == "due") - { - const std::string& left_string = (*global_data)[left].get_ref (field); - const std::string& right_string = (*global_data)[right].get_ref (field); - - if (left_string != "" && right_string == "") - return true; - - if (left_string == "" && right_string != "") - return false; - - if (left_string == right_string) - continue; - - return ascending ? (left_string < right_string) - : (left_string > right_string); - } - - // Date. - else if (field == "end" || + else if (field == "due" || + field == "end" || field == "entry" || field == "start" || field == "until" || @@ -162,6 +141,12 @@ const std::string& left_string = (*global_data)[left].get_ref (field); const std::string& right_string = (*global_data)[right].get_ref (field); + if (left_string != "" && right_string == "") + return true; + + if (left_string == "" && right_string != "") + return false; + if (left_string == right_string) continue; @@ -205,8 +190,8 @@ if (left_string == right_string) continue; - Duration left_duration (left_string); - Duration right_duration (right_string); + ISO8601p left_duration (left_string); + ISO8601p right_duration (right_string); return ascending ? (left_duration < right_duration) : (left_duration > right_duration); } @@ -226,25 +211,47 @@ return ascending ? (left_real < right_real) : (left_real > right_real); } - // UDA values of type 'string' are sorted by Variant::operator<. - // By setting 'source' to the UDA name, the comparison operator can use - // the custom sort order, if defined. else if (type == "string") { - Variant l ((*global_data)[left].get_ref (field)); - Variant r ((*global_data)[right].get_ref (field)); - if (l == r) + const std::string left_string = (*global_data)[left].get_ref (field); + const std::string right_string = (*global_data)[right].get_ref (field); + + if (left_string == right_string) continue; - l.source (field); - r.source (field); - return ascending ? (l < r) : (r < l); + // UDAs of the type string can have custom sort orders, which need to be considered. + auto order = Task::customOrder.find (field); + if (order != Task::customOrder.end ()) + { + // Guaranteed to be found, because of ColUDA::validate (). + auto posLeft = std::find (order->second.begin (), order->second.end (), left_string); + auto posRight = std::find (order->second.begin (), order->second.end (), right_string); + return ascending ? (posLeft < posRight) : (posLeft > posRight); + } + else + { + // Empty values are unconditionally last, if no custom order was specified. + if (left_string == "") + return false; + else if (right_string == "") + return true; + + return ascending ? (left_string < right_string) + : (left_string > right_string); + } } + else if (type == "date") { const std::string& left_string = (*global_data)[left].get_ref (field); const std::string& right_string = (*global_data)[right].get_ref (field); + if (left_string != "" && right_string == "") + return true; + + if (left_string == "" && right_string != "") + return false; + if (left_string == right_string) continue; @@ -259,8 +266,8 @@ if (left_string == right_string) continue; - Duration left_duration (left_string); - Duration right_duration (right_string); + ISO8601p left_duration (left_string); + ISO8601p right_duration (right_string); return ascending ? (left_duration < right_duration) : (left_duration > right_duration); } diff -Nru task-2.4.4+dfsg/src/Task.cpp task-2.5.0+dfsg/src/Task.cpp --- task-2.4.4+dfsg/src/Task.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/Task.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -28,18 +28,20 @@ #include #include #include +#include #ifdef PRODUCT_TASKWARRIOR #include +#include +#include #endif #include #ifdef PRODUCT_TASKWARRIOR #include +#include #include #endif -#include -#include +#include #include -#include #ifdef PRODUCT_TASKWARRIOR #include #endif @@ -54,7 +56,6 @@ #include #include #include -#include #define APPROACHING_INFINITY 1000 // Close enough. This isn't rocket surgery. @@ -76,10 +77,8 @@ float Task::urgencyScheduledCoefficient = 0.0; float Task::urgencyWaitingCoefficient = 0.0; float Task::urgencyBlockedCoefficient = 0.0; -float Task::urgencyInheritCoefficient = 0.0; float Task::urgencyAnnotationsCoefficient = 0.0; float Task::urgencyTagsCoefficient = 0.0; -float Task::urgencyNextCoefficient = 0.0; float Task::urgencyDueCoefficient = 0.0; float Task::urgencyBlockingCoefficient = 0.0; float Task::urgencyAgeCoefficient = 0.0; @@ -125,15 +124,24 @@ //////////////////////////////////////////////////////////////////////////////// // The uuid and id attributes must be exempt from comparison. +// +// This performs two tests which are sufficient and necessary for Task +// object equality (neglecting uuid and id): +// - The attribute set sizes are the same +// - For each attribute in the first set, there exists a same +// attribute with a same value in the second set +// +// These two conditions are necessary. They are also sufficient, since there +// can be no extra data attribute in the second set, due to the same attribute +// set sizes. bool Task::operator== (const Task& other) { if (size () != other.size ()) return false; - Task::iterator i; - for (i = this->begin (); i != this->end (); ++i) - if (i->first != "uuid" && - i->second != other.get (i->first)) + for (auto& i : *this) + if (i.first != "uuid" && + i.second != other.get (i.first)) return false; return true; @@ -153,6 +161,19 @@ } //////////////////////////////////////////////////////////////////////////////// +Task::Task (const json::object* obj) +{ + id = 0; + urgency_value = 0.0; + recalc_urgency = true; + is_blocked = false; + is_blocking = false; + annotation_count = 0; + + parseJSON (obj); +} + +//////////////////////////////////////////////////////////////////////////////// Task::~Task () { } @@ -166,7 +187,7 @@ else if (input[0] == 'r') return Task::recurring; else if (input[0] == 'w') return Task::waiting; - return Task::pending; + throw format (STRING_ERROR_BAD_STATUS, input); } //////////////////////////////////////////////////////////////////////////////// @@ -194,7 +215,7 @@ //////////////////////////////////////////////////////////////////////////////// bool Task::has (const std::string& name) const { - Task::const_iterator i = this->find (name); + auto i = this->find (name); if (i != this->end ()) return true; @@ -205,8 +226,7 @@ std::vector Task::all () { std::vector all; - Task::iterator i; - for (i = this->begin (); i != this->end (); ++i) + for (auto i = this->begin (); i != this->end (); ++i) all.push_back (i->first); return all; @@ -215,7 +235,7 @@ //////////////////////////////////////////////////////////////////////////////// const std::string Task::get (const std::string& name) const { - Task::const_iterator i = this->find (name); + auto i = this->find (name); if (i != this->end ()) return i->second; @@ -225,7 +245,7 @@ //////////////////////////////////////////////////////////////////////////////// const std::string& Task::get_ref (const std::string& name) const { - Task::const_iterator i = this->find (name); + auto i = this->find (name); if (i != this->end ()) return i->second; @@ -235,7 +255,7 @@ //////////////////////////////////////////////////////////////////////////////// int Task::get_int (const std::string& name) const { - Task::const_iterator i = this->find (name); + auto i = this->find (name); if (i != this->end ()) return strtol (i->second.c_str (), NULL, 10); @@ -245,7 +265,7 @@ //////////////////////////////////////////////////////////////////////////////// unsigned long Task::get_ulong (const std::string& name) const { - Task::const_iterator i = this->find (name); + auto i = this->find (name); if (i != this->end ()) return strtoul (i->second.c_str (), NULL, 10); @@ -255,7 +275,7 @@ //////////////////////////////////////////////////////////////////////////////// float Task::get_float (const std::string& name) const { - Task::const_iterator i = this->find (name); + auto i = this->find (name); if (i != this->end ()) return strtof (i->second.c_str (), NULL); @@ -265,7 +285,7 @@ //////////////////////////////////////////////////////////////////////////////// time_t Task::get_date (const std::string& name) const { - Task::const_iterator i = this->find (name); + auto i = this->find (name); if (i != this->end ()) return (time_t) strtoul (i->second.c_str (), NULL, 10); @@ -291,8 +311,8 @@ //////////////////////////////////////////////////////////////////////////////// void Task::remove (const std::string& name) { - Task::iterator it; - if ((it = this->find (name)) != this->end ()) + auto it = this->find (name); + if (it != this->end ()) { this->erase (it); recalc_urgency = true; @@ -320,9 +340,9 @@ std::string value = get (name); if (value.length ()) { - Date reference (value); - Date now; - Date today ("today"); + ISO8601d reference (value); + ISO8601d now; + ISO8601d today ("today"); if (reference < today) return dateBeforeToday; @@ -339,7 +359,7 @@ if (imminentperiod == 0) return dateAfterToday; - Date imminentDay = today + imminentperiod * 86400; + ISO8601d imminentDay = today + imminentperiod * 86400; if (reference < imminentDay) return dateAfterToday; } @@ -354,9 +374,9 @@ bool Task::is_ready () const { return getStatus () == Task::pending && - !is_blocked && + ! is_blocked && (! has ("scheduled") || - Date ("now").operator> (get_date ("scheduled"))); + ISO8601d ("now").operator> (get_date ("scheduled"))); } //////////////////////////////////////////////////////////////////////////////// @@ -390,7 +410,7 @@ if (status != Task::completed && status != Task::deleted) { - if (Date ("yesterday").sameDay (get_date ("due"))) + if (ISO8601d ("yesterday").sameDay (get_date ("due"))) return true; } } @@ -428,7 +448,7 @@ if (status != Task::completed && status != Task::deleted) { - if (Date ("tomorrow").sameDay (get_date ("due"))) + if (ISO8601d ("tomorrow").sameDay (get_date ("due"))) return true; } } @@ -446,9 +466,9 @@ if (status != Task::completed && status != Task::deleted) { - Date due (get_date ("due")); - if (due >= Date ("socw") && - due <= Date ("eocw")) + ISO8601d due (get_date ("due")); + if (due >= ISO8601d ("socw") && + due <= ISO8601d ("eocw")) return true; } } @@ -466,9 +486,9 @@ if (status != Task::completed && status != Task::deleted) { - Date due (get_date ("due")); - if (due >= Date ("socm") && - due <= Date ("eocm")) + ISO8601d due (get_date ("due")); + if (due >= ISO8601d ("socm") && + due <= ISO8601d ("eocm")) return true; } } @@ -486,8 +506,8 @@ if (status != Task::completed && status != Task::deleted) { - Date now; - Date due (get_date ("due")); + ISO8601d now; + ISO8601d due (get_date ("due")); if (now.year () == due.year ()) return true; } @@ -497,6 +517,29 @@ } //////////////////////////////////////////////////////////////////////////////// +bool Task::is_udaPresent () const +{ + for (auto& col : context.columns) + if (col.first.substr (0, 11) != "annotation_") + if (col.second->is_uda () && + has (col.first)) + return true; + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +bool Task::is_orphanPresent () const +{ + for (auto& att : *this) + if (att.first.substr (0, 11) != "annotation_") + if (context.columns.find (att.first) == context.columns.end ()) + return true; + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// bool Task::is_overdue () const { if (has ("due")) @@ -504,7 +547,8 @@ Task::status status = getStatus (); if (status != Task::completed && - status != Task::deleted) + status != Task::deleted && + status != Task::recurring) { Task::dateState state = getDateState ("due"); if (state == dateEarlierToday || @@ -601,119 +645,127 @@ { // Parse the whole thing. json::value* root = json::parse (line); - if (root->type () == json::j_object) + if (root && + root->type () == json::j_object) + parseJSON ((json::object*) root); + + delete root; +} + +//////////////////////////////////////////////////////////////////////////////// +void Task::parseJSON (const json::object* root_obj) +{ + // For each object element... + for (auto& i : root_obj->_data) { - json::object* root_obj = (json::object*)root; + // If the attribute is a recognized column. + std::string type = Task::attributes[i.first]; + if (type != "") + { + // Any specified id is ignored. + if (i.first == "id") + ; - // For each object element... - json_object_iter i; - for (i = root_obj->_data.begin (); - i != root_obj->_data.end (); - ++i) - { - // If the attribute is a recognized column. - std::string type = Task::attributes[i->first]; - if (type != "") - { - // Any specified id is ignored. - if (i->first == "id") - ; - - // Urgency, if present, is ignored. - else if (i->first == "urgency") - ; + // Urgency, if present, is ignored. + else if (i.first == "urgency") + ; - // TW-1274 Standardization. - else if (i->first == "modification") - { - Date d (unquoteText (i->second->dump ())); - set ("modified", d.toEpochString ()); - } + // TW-1274 Standardization. + else if (i.first == "modification") + { + ISO8601d d (unquoteText (i.second->dump ())); + set ("modified", d.toEpochString ()); + } - // Dates are converted from ISO to epoch. - else if (type == "date") - { - std::string text = unquoteText (i->second->dump ()); - Date d (text); - set (i->first, text == "" ? "" : d.toEpochString ()); - } + // Dates are converted from ISO to epoch. + else if (type == "date") + { + std::string text = unquoteText (i.second->dump ()); + ISO8601d d (text); + set (i.first, text == "" ? "" : d.toEpochString ()); + } - // Tags are an array of JSON strings. - else if (i->first == "tags" && i->second->type() == json::j_array) - { - json::array* tags = (json::array*)i->second; - json_array_iter t; - for (t = tags->_data.begin (); - t != tags->_data.end (); - ++t) - { - json::string* tag = (json::string*)*t; - addTag (tag->_data); - } - } - // This is a temporary measure to allow Mirakel sync, and will be removed - // in a future release. - else if (i->first == "tags" && i->second->type() == json::j_string) + // Tags are an array of JSON strings. + else if (i.first == "tags" && i.second->type() == json::j_array) + { + json::array* tags = (json::array*)i.second; + for (auto& t : tags->_data) { - json::string* tag = (json::string*)i->second; + json::string* tag = (json::string*)t; addTag (tag->_data); } - - // Strings are decoded. - else if (type == "string") - set (i->first, json::decode (unquoteText (i->second->dump ()))); - - // Other types are simply added. - else - set (i->first, unquoteText (i->second->dump ())); + } + // This is a temporary measure to allow Mirakel sync, and will be removed + // in a future release. + else if (i.first == "tags" && i.second->type() == json::j_string) + { + json::string* tag = (json::string*)i.second; + addTag (tag->_data); } - // UDA orphans and annotations do not have columns. - else + // Dependencies can be exported as a single comma-separated string, or as + // an array of strings. + else if (i.first == "depends" && i.second->type() == json::j_array) { - // Annotations are an array of JSON objects with 'entry' and - // 'description' values and must be converted. - if (i->first == "annotations") + json::array* tags = (json::array*)i.second; + for (auto& t : tags->_data) { - std::map annos; + json::string* tag = (json::string*)t; + addDependency (tag->_data); + } + } - json::array* atts = (json::array*)i->second; - json_array_iter annotations; - for (annotations = atts->_data.begin (); - annotations != atts->_data.end (); - ++annotations) - { - json::object* annotation = (json::object*)*annotations; - json::string* when = (json::string*)annotation->_data["entry"]; - json::string* what = (json::string*)annotation->_data["description"]; + // Strings are decoded. + else if (type == "string") + set (i.first, json::decode (unquoteText (i.second->dump ()))); - if (! when) - throw format (STRING_TASK_NO_ENTRY, line); + // Other types are simply added. + else + set (i.first, unquoteText (i.second->dump ())); + } - if (! what) - throw format (STRING_TASK_NO_DESC, line); + // UDA orphans and annotations do not have columns. + else + { + // Annotations are an array of JSON objects with 'entry' and + // 'description' values and must be converted. + if (i.first == "annotations") + { + std::map annos; - std::string name = "annotation_" + Date (when->_data).toEpochString (); - annos.insert (std::make_pair (name, json::decode (what->_data))); - } + json::array* atts = (json::array*)i.second; + for (auto& annotations : atts->_data) + { + json::object* annotation = (json::object*)annotations; + json::string* when = (json::string*)annotation->_data["entry"]; + json::string* what = (json::string*)annotation->_data["description"]; - setAnnotations (annos); + if (! when) + throw format (STRING_TASK_NO_ENTRY, root_obj->dump ()); + + if (! what) + throw format (STRING_TASK_NO_DESC, root_obj->dump ()); + + std::string name = "annotation_" + ISO8601d (when->_data).toEpochString (); + annos.insert (std::make_pair (name, json::decode (what->_data))); } - // UDA Orphan - must be preserved. - else - { + setAnnotations (annos); + } + + // UDA Orphan - must be preserved. + else + { #ifdef PRODUCT_TASKWARRIOR - std::stringstream message; - message << "Task::parseJSON found orphan '" - << i->first - << "' with value '" - << i->second - << "' --> preserved\n"; - context.debug (message.str ()); + std::stringstream message; + message << "Task::parseJSON found orphan '" + << i.first + << "' with value '" + << i.second + << "' --> preserved\n"; + context.debug (message.str ()); #endif - set (i->first, json::decode (unquoteText (i->second->dump ()))); - } + set (i.first, json::decode (unquoteText (i.second->dump ()))); } } } @@ -761,15 +813,14 @@ std::string ff4 = "["; bool first = true; - Task::const_iterator it; - for (it = this->begin (); it != this->end (); ++it) + for (auto it : *this) { - if (it->second != "") + if (it.second != "") { ff4 += (first ? "" : " ") - + it->first + + it.first + ":\"" - + encode (json::encode (it->second)) + + encode (json::encode (it.second)) + "\""; first = false; @@ -793,58 +844,62 @@ // First the non-annotations. int attributes_written = 0; - Task::const_iterator i; - for (i = this->begin (); i != this->end (); ++i) + for (auto& i : *this) { // Annotations are not written out here. - if (i->first.substr (0, 11) == "annotation_") + if (i.first.substr (0, 11) == "annotation_") continue; // If value is an empty string, do not ever output it - if (i->second == "") + if (i.second == "") continue; if (attributes_written) out << ","; - std::string type = Task::attributes[i->first]; + std::string type = Task::attributes[i.first]; if (type == "") type = "string"; // Date fields are written as ISO 8601. if (type == "date") { - Date d (i->second); + ISO8601d d (i.second); out << "\"" - << (i->first == "modification" ? "modified" : i->first) + << (i.first == "modification" ? "modified" : i.first) << "\":\"" // Date was deleted, do not export parsed empty string - << (i->second == "" ? "" : d.toISO ()) + << (i.second == "" ? "" : d.toISO ()) << "\""; ++attributes_written; } +/* + else if (type == "duration") + { + // TODO Emit ISO8601d + } +*/ else if (type == "numeric") { out << "\"" - << i->first + << i.first << "\":" - << i->second; + << i.second; ++attributes_written; } // Tags are converted to an array. - else if (i->first == "tags") + else if (i.first == "tags") { std::vector tags; - split (tags, i->second, ','); + split (tags, i.second, ','); out << "\"tags\":["; - std::vector ::iterator i; - for (i = tags.begin (); i != tags.end (); ++i) + for (auto i = tags.begin (); i != tags.end (); ++i) { if (i != tags.begin ()) out << ","; @@ -853,7 +908,27 @@ } out << "]"; + ++attributes_written; + } + + // Dependencies are an array by default. + else if (i.first == "depends" && + context.config.getBoolean ("json.depends.array")) + { + std::vector deps; + split (deps, i.second, ','); + + out << "\"depends\":["; + for (auto i = deps.begin (); i != deps.end (); ++i) + { + if (i != deps.begin ()) + out << ","; + + out << "\"" << *i << "\""; + } + + out << "]"; ++attributes_written; } @@ -861,9 +936,9 @@ else { out << "\"" - << i->first + << i.first << "\":\"" - << json::encode (i->second) + << json::encode (i.second) << "\""; ++attributes_written; @@ -877,18 +952,18 @@ << "\"annotations\":["; int annotations_written = 0; - for (i = this->begin (); i != this->end (); ++i) + for (auto& i : *this) { - if (i->first.substr (0, 11) == "annotation_") + if (i.first.substr (0, 11) == "annotation_") { if (annotations_written) out << ","; - Date d (i->first.substr (11)); + ISO8601d d (i.first.substr (11)); out << "{\"entry\":\"" << d.toISO () << "\",\"description\":\"" - << json::encode (i->second) + << json::encode (i.second) << "\"}"; ++annotations_written; @@ -943,7 +1018,7 @@ void Task::removeAnnotations () { // Erase old annotations. - Task::iterator i = this->begin (); + auto i = this->begin (); while (i != this->end ()) { if (i->first.substr (0, 11) == "annotation_") @@ -963,10 +1038,9 @@ { annotations.clear (); - Task::const_iterator ci; - for (ci = this->begin (); ci != this->end (); ++ci) - if (ci->first.substr (0, 11) == "annotation_") - annotations.insert (*ci); + for (auto& ann : *this) + if (ann.first.substr (0, 11) == "annotation_") + annotations.insert (ann); } //////////////////////////////////////////////////////////////////////////////// @@ -975,9 +1049,8 @@ // Erase old annotations. removeAnnotations (); - std::map ::const_iterator ci; - for (ci = annotations.begin (); ci != annotations.end (); ++ci) - this->insert (*ci); + for (auto& anno : annotations) + this->insert (anno); annotation_count = annotations.size (); recalc_urgency = true; @@ -994,7 +1067,10 @@ std::string depends = get ("depends"); if (depends.find (uuid) != std::string::npos) - throw format (STRING_TASK_DEPEND_DUP, this->id, id); + { + context.footnote (format (STRING_TASK_DEPEND_DUP, this->id, id)); + return; + } addDependency(uuid); } @@ -1013,7 +1089,10 @@ if (depends.find (uuid) == std::string::npos) set ("depends", depends + "," + uuid); else - throw format (STRING_TASK_DEPEND_DUP, this->get ("uuid"), uuid); + { + context.footnote (format (STRING_TASK_DEPEND_DUP, this->get ("uuid"), uuid)); + return; + } } else set ("depends", uuid); @@ -1031,8 +1110,7 @@ std::vector deps; split (deps, get ("depends"), ','); - std::vector ::iterator i; - i = std::find (deps.begin (), deps.end (), uuid); + auto i = std::find (deps.begin (), deps.end (), uuid); if (i != deps.end ()) { deps.erase (i); @@ -1064,9 +1142,8 @@ all.clear (); - std::vector ::iterator i; - for (i = deps.begin (); i != deps.end (); ++i) - all.push_back (context.tdb2.pending.id (*i)); + for (auto& dep : deps) + all.push_back (context.tdb2.pending.id (dep)); } //////////////////////////////////////////////////////////////////////////////// @@ -1101,32 +1178,41 @@ { // 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; + // Note: This list must match that in ::feedback_reserved_tags. + if (isupper (tag[0])) + { + if (tag == "BLOCKED") return is_blocked; + if (tag == "UNBLOCKED") return !is_blocked; + if (tag == "BLOCKING") return is_blocking; #ifdef PRODUCT_TASKWARRIOR - if (tag == "READY") return is_ready (); - if (tag == "DUE") return is_due (); - if (tag == "DUETODAY") return is_duetoday (); - if (tag == "TODAY") return is_duetoday (); - if (tag == "YESTERDAY") return is_dueyesterday (); - if (tag == "TOMORROW") return is_duetomorrow (); - if (tag == "OVERDUE") return is_overdue (); - if (tag == "WEEK") return is_dueweek (); - if (tag == "MONTH") return is_duemonth (); - if (tag == "YEAR") return is_dueyear (); + if (tag == "READY") return is_ready (); + if (tag == "DUE") return is_due (); + if (tag == "DUETODAY") return is_duetoday (); + if (tag == "TODAY") return is_duetoday (); + if (tag == "YESTERDAY") return is_dueyesterday (); + if (tag == "TOMORROW") return is_duetomorrow (); + if (tag == "OVERDUE") return is_overdue (); + if (tag == "WEEK") return is_dueweek (); + if (tag == "MONTH") return is_duemonth (); + if (tag == "YEAR") return is_dueyear (); #endif - if (tag == "ACTIVE") return has ("start"); - if (tag == "SCHEDULED") return has ("scheduled"); - if (tag == "CHILD") return has ("parent"); - if (tag == "UNTIL") return has ("until"); - if (tag == "ANNOTATED") return hasAnnotations (); - if (tag == "TAGGED") return has ("tags"); - if (tag == "PARENT") return has ("mask"); - if (tag == "WAITING") return get ("status") == "waiting"; - if (tag == "PENDING") return get ("status") == "pending"; - if (tag == "COMPLETED") return get ("status") == "completed"; - if (tag == "DELETED") return get ("status") == "deleted"; + if (tag == "ACTIVE") return has ("start"); + if (tag == "SCHEDULED") return has ("scheduled"); + if (tag == "CHILD") return has ("parent"); + if (tag == "UNTIL") return has ("until"); + if (tag == "ANNOTATED") return hasAnnotations (); + if (tag == "TAGGED") return has ("tags"); + if (tag == "PARENT") return has ("mask"); + if (tag == "WAITING") return get ("status") == "waiting"; + if (tag == "PENDING") return get ("status") == "pending"; + if (tag == "COMPLETED") return get ("status") == "completed"; + if (tag == "DELETED") return get ("status") == "deleted"; + if (tag == "UDA") return is_udaPresent (); + if (tag == "ORPHAN") return is_orphanPresent (); + if (tag == "LATEST") return id == context.tdb2.latest_id (); + if (tag == "PROJECT") return has ("project"); + if (tag == "PRIORITY") return has ("priority"); + } // Concrete tags. std::vector tags; @@ -1160,9 +1246,8 @@ { remove ("tags"); - std::vector ::const_iterator it; - for (it = tags.begin (); it != tags.end (); ++it) - addTag (*it); + for (auto& tag : tags) + addTag (tag); recalc_urgency = true; } @@ -1179,8 +1264,7 @@ std::vector tags; split (tags, get ("tags"), ','); - std::vector ::iterator i; - i = std::find (tags.begin (), tags.end (), tag); + auto i = std::find (tags.begin (), tags.end (), tag); if (i != tags.end ()) { tags.erase (i); @@ -1194,33 +1278,23 @@ #ifdef PRODUCT_TASKWARRIOR //////////////////////////////////////////////////////////////////////////////// -// A UDA is an attribute that has supporting config entries such as a data type: -// 'uda..type' -void Task::getUDAs (std::vector & names) const -{ - Task::const_iterator it; - for (it = this->begin (); it != this->end (); ++it) - if (context.config.get ("uda." + it->first + ".type") != "") - names.push_back (it->first); -} - -//////////////////////////////////////////////////////////////////////////////// // A UDA Orphan is an attribute that is not represented in context.columns. void Task::getUDAOrphans (std::vector & names) const { - Task::const_iterator it; - for (it = this->begin (); it != this->end (); ++it) - if (it->first.substr (0, 11) != "annotation_") - if (context.columns.find (it->first) == context.columns.end ()) - names.push_back (it->first); + for (auto& it : *this) + if (it.first.substr (0, 11) != "annotation_") + if (context.columns.find (it.first) == context.columns.end ()) + names.push_back (it.first); } //////////////////////////////////////////////////////////////////////////////// void Task::substitute ( const std::string& from, const std::string& to, - bool global) + const std::string& flags) { + bool global = (flags.find ('g') != std::string::npos ? true : false); + // Get the data to modify. std::string description = get ("description"); std::map annotations; @@ -1257,17 +1331,16 @@ if (!done) { // Perform all subs on annotations. - std::map ::iterator it; - for (it = annotations.begin (); it != annotations.end () && !done; ++it) + for (auto& it : annotations) { start.clear (); end.clear (); - if (rx.match (start, end, it->second)) + if (rx.match (start, end, it.second)) { int skew = 0; for (unsigned int i = 0; i < start.size () && !done; ++i) { - it->second.replace (start[i + skew], end[i] - start[i], to); + it.second.replace (start[i + skew], end[i] - start[i], to); skew += to.length () - (end[i] - start[i]); ++changes; @@ -1304,14 +1377,13 @@ { // Perform all subs on annotations. counter = 0; - std::map ::iterator i; - for (i = annotations.begin (); i != annotations.end () && !done; ++i) + for (auto& anno : annotations) { pos = 0; skew = 0; - while ((pos = ::find (i->second, from, pos, Task::searchCaseSensitive)) != std::string::npos && !done) + while ((pos = ::find (anno.second, from, pos, Task::searchCaseSensitive)) != std::string::npos && !done) { - i->second.replace (pos + skew, from.length (), to); + anno.second.replace (pos + skew, from.length (), to); skew += to.length () - from.length (); pos += to.length (); @@ -1344,11 +1416,22 @@ // void Task::validate (bool applyDefault /* = true */) { - Task::status status = getStatus (); + Task::status status = Task::pending; + if (get ("status") != "") + status = getStatus (); // 1) Provide missing attributes where possible - // Provide a UUID if necessary. - if (! has ("uuid") || get ("uuid") == "") + // Provide a UUID if necessary. Validate if present. + std::string uid = get ("uuid"); + if (has ("uuid") && uid != "") + { + Lexer lex (uid); + std::string token; + Lexer::Type type; + if (! lex.isUUID (token, type, true)) + throw format (STRING_CMD_IMPORT_UUID_BAD, uid); + } + else set ("uuid", uuid ()); // Recurring tasks get a special status. @@ -1360,7 +1443,8 @@ // Tasks with a wait: date get a special status. else if (status == Task::pending && - has ("wait")) + has ("wait") && + get ("wait") != "") status = Task::waiting; // By default, tasks are pending. @@ -1372,7 +1456,7 @@ #ifdef PRODUCT_TASKWARRIOR // Provide an entry date unless user already specified one. - if (!has ("entry") || get ("entry") == "") + if (! has ("entry") || get ("entry") == "") setAsNow ("entry"); // Completed tasks need an end date, so inherit the entry date. @@ -1381,7 +1465,7 @@ setAsNow ("end"); // Provide an entry date unless user already specified one. - if (!has ("modified") || get ("modified") == "") + if (! has ("modified") || get ("modified") == "") setAsNow ("modified"); if (applyDefault && (! has ("parent") || get ("parent") == "")) @@ -1400,11 +1484,11 @@ { if (context.columns["due"]->validate (Task::defaultDue)) { - Duration dur (Task::defaultDue); + ISO8601p dur (Task::defaultDue); if ((time_t) dur != 0) - set ("due", (Date () + dur).toEpoch ()); + set ("due", (ISO8601d () + dur).toEpoch ()); else - set ("due", Date (Task::defaultDue).toEpoch ()); + set ("due", ISO8601d (Task::defaultDue).toEpoch ()); } } @@ -1412,15 +1496,14 @@ // override with uda.(uda).default, if not specified. // Gather a list of all UDAs with a .default value std::vector udas; - Config::const_iterator var; - for (var = context.config.begin (); var != context.config.end (); ++var) + for (auto& var : context.config) { - if (var->first.substr (0, 4) == "uda." && - var->first.find (".default") != std::string::npos) + if (var.first.substr (0, 4) == "uda." && + var.first.find (".default") != std::string::npos) { - std::string::size_type period = var->first.find ('.', 4); + auto period = var.first.find ('.', 4); if (period != std::string::npos) - udas.push_back (var->first.substr (4, period - 4)); + udas.push_back (var.first.substr (4, period - 4)); } } @@ -1428,14 +1511,13 @@ { // For each of those, setup the default value on the task now, // of course only if we don't have one on the command line already - std::vector ::iterator uda; - for (uda = udas.begin (); uda != udas.end (); ++uda) + for (auto& uda : udas) { - std::string defVal= context.config.get ("uda." + *uda + ".default"); + std::string defVal= context.config.get ("uda." + uda + ".default"); // If the default is empty, or we already have a value, skip it - if (defVal != "" && get (*uda) == "") - set (*uda, defVal); + if (defVal != "" && get (uda) == "") + set (uda, defVal); } } } @@ -1455,7 +1537,7 @@ // 3) To generate errors when the inconsistencies are not fixable // There is no fixing a missing description. - if (!has ("description")) + if (! has ("description")) throw std::string (STRING_TASK_VALID_DESC); else if (get ("description") == "") throw std::string (STRING_TASK_VALID_BLANK); @@ -1468,15 +1550,12 @@ if (has ("recur")) { std::string value = get ("recur"); - - Duration d; - std::string::size_type i = 0; - if (! d.parse (value, i)) + if (value != "") { - i = 0; ISO8601p p; + std::string::size_type i = 0; if (! p.parse (value, i)) - throw std::string (format (STRING_TASK_VALID_RECUR, value)); + throw format (STRING_TASK_VALID_RECUR, value); } } } @@ -1488,10 +1567,11 @@ if (has (left) && has (right)) { - Date date_left (get_date (left)); - Date date_right (get_date (right)); + ISO8601d date_left (get_date (left)); + ISO8601d date_right (get_date (right)); - if (date_left > date_right) + // if date is zero, then it is being removed (e.g. "due: wait:1day") + if (date_left > date_right && date_right.toEpoch () != 0) context.footnote (format (STRING_TASK_VALID_BEFORE, left, right)); } #endif @@ -1569,9 +1649,9 @@ // uuid status [tags] [attributes] [annotations] description\n // // Scan for the number of [] pairs. - std::string::size_type tagAtts = line.find ("] [", 0); - std::string::size_type attsAnno = line.find ("] [", tagAtts + 1); - std::string::size_type annoDesc = line.find ("] ", attsAnno + 1); + auto tagAtts = line.find ("] [", 0); + auto attsAnno = line.find ("] [", tagAtts + 1); + auto annoDesc = line.find ("] ", attsAnno + 1); if (tagAtts != std::string::npos && attsAnno != std::string::npos && annoDesc != std::string::npos) @@ -1643,76 +1723,84 @@ value += fabsf (Task::urgencyBlockedCoefficient) > epsilon ? (urgency_blocked () * Task::urgencyBlockedCoefficient) : 0.0; value += fabsf (Task::urgencyAnnotationsCoefficient) > epsilon ? (urgency_annotations () * Task::urgencyAnnotationsCoefficient) : 0.0; value += fabsf (Task::urgencyTagsCoefficient) > epsilon ? (urgency_tags () * Task::urgencyTagsCoefficient) : 0.0; - value += fabsf (Task::urgencyNextCoefficient) > epsilon ? (urgency_next () * Task::urgencyNextCoefficient) : 0.0; value += fabsf (Task::urgencyDueCoefficient) > epsilon ? (urgency_due () * Task::urgencyDueCoefficient) : 0.0; value += fabsf (Task::urgencyBlockingCoefficient) > epsilon ? (urgency_blocking () * Task::urgencyBlockingCoefficient) : 0.0; value += fabsf (Task::urgencyAgeCoefficient) > epsilon ? (urgency_age () * Task::urgencyAgeCoefficient) : 0.0; - value += fabsf (Task::urgencyInheritCoefficient) > epsilon ? (urgency_inherit () * Task::urgencyInheritCoefficient) : 0.0; // Tag- and project-specific coefficients. - std::map ::iterator var; - for (var = Task::coefficients.begin (); var != Task::coefficients.end (); ++var) + for (auto& var : Task::coefficients) { - if (fabs (var->second) > epsilon) + if (fabs (var.second) > epsilon) { - if (var->first.substr (0, 13) == "urgency.user.") + if (var.first.substr (0, 13) == "urgency.user.") { // urgency.user.project..coefficient - std::string::size_type end = std::string::npos; - if (var->first.substr (13, 8) == "project." && - (end = var->first.find (".coefficient")) != std::string::npos) + auto end = std::string::npos; + if (var.first.substr (13, 8) == "project." && + (end = var.first.find (".coefficient")) != std::string::npos) { - std::string project = var->first.substr (21, end - 21); + std::string project = var.first.substr (21, end - 21); if (get ("project").find (project) == 0) - value += var->second; + value += var.second; } // urgency.user.tag..coefficient - if (var->first.substr (13, 4) == "tag." && - (end = var->first.find (".coefficient")) != std::string::npos) + if (var.first.substr (13, 4) == "tag." && + (end = var.first.find (".coefficient")) != std::string::npos) { - std::string tag = var->first.substr (17, end - 17); + std::string tag = var.first.substr (17, end - 17); if (hasTag (tag)) - value += var->second; + value += var.second; } // urgency.user.keyword..coefficient - if (var->first.substr (13, 8) == "keyword." && - (end = var->first.find (".coefficient")) != std::string::npos) + if (var.first.substr (13, 8) == "keyword." && + (end = var.first.find (".coefficient")) != std::string::npos) { - std::string keyword = var->first.substr (21, end - 21); + std::string keyword = var.first.substr (21, end - 21); if (get ("description").find (keyword) != std::string::npos) - value += var->second; + value += var.second; } } - else if (var->first.substr (0, 12) == "urgency.uda.") + else if (var.first.substr (0, 12) == "urgency.uda.") { // urgency.uda..coefficient // urgency.uda...coefficient - std::string::size_type end = var->first.find (".coefficient"); + auto end = var.first.find (".coefficient"); if (end != std::string::npos) { - const std::string uda = var->first.substr (12, end - 12); - std::string::size_type dot = uda.find ("."); + const std::string uda = var.first.substr (12, end - 12); + auto dot = uda.find ("."); if (dot == std::string::npos) { // urgency.uda..coefficient if (has (uda)) - value += var->second; + value += var.second; } else { // urgency.uda...coefficient if (get (uda.substr(0, dot)) == uda.substr(dot+1)) - value += var->second; + value += var.second; } } } } } + + if (is_blocking && context.config.getBoolean ("urgency.inherit")) + { + float prev = value; + value = std::max (value, urgency_inherit ()); + + // This is a hackish way of making sure parent tasks are sorted above + // child tasks. For reports that hide blocked tasks, this is not needed. + if (prev < value) + value += 0.01; + } #endif return value; @@ -1735,29 +1823,16 @@ //////////////////////////////////////////////////////////////////////////////// float Task::urgency_inherit () const { - if (!is_blocking) - return 0.0; - // Calling dependencyGetBlocked is rather expensive. // It is called recursively for each dependency in the chain here. std::vector blocked; dependencyGetBlocked (*this, blocked); - float v = 0.0; - std::vector ::const_iterator it; - for (it = blocked.begin (); it != blocked.end (); ++it) - { - // urgency_blocked, _blocking, _project and _tags left out. - v += it->urgency_active (); - v += it->urgency_age (); - v += it->urgency_annotations (); - v += it->urgency_due (); - v += it->urgency_next (); - v += it->urgency_scheduled (); - v += it->urgency_waiting (); - - // Inherit from all parent tasks in the dependency chain recursively. - v += it->urgency_inherit (); + float v = FLT_MIN; + for (auto& task : blocked) + { + // Find highest urgency in all blocked tasks. + v = std::max (v, task.urgency ()); } return v; @@ -1833,15 +1908,6 @@ } //////////////////////////////////////////////////////////////////////////////// -float Task::urgency_next () const -{ - if (hasTag ("next")) - return 1.0; - - return 0.0; -} - -//////////////////////////////////////////////////////////////////////////////// // // Past Present Future // Overdue Due Due @@ -1856,8 +1922,8 @@ { if (has ("due")) { - Date now; - Date due (get_date ("due")); + ISO8601d now; + ISO8601d due (get_date ("due")); // Map a range of 21 days to the value 0.2 - 1.0 float days_overdue = (now - due) / 86400.0; @@ -1874,8 +1940,8 @@ { assert (has ("entry")); - Date now; - Date entry (get_date ("entry")); + ISO8601d now; + ISO8601d entry (get_date ("entry")); int age = (now - entry) / 86400; // in days if (Task::urgencyAgeMax == 0 || age > Task::urgencyAgeMax) @@ -1901,26 +1967,21 @@ // It came from the Command base object, but doesn't really belong there either. void Task::modify (modType type, bool text_required /* = false */) { - std::string text = ""; - - if (context.config.getInteger ("debug.parser") >= 1) - context.debug (context.cli.dump ()); - context.debug ("Task::modify"); std::string label = " MODIFICATION "; + std::string text = ""; int modCount = 0; - std::vector ::iterator a; - for (a = context.cli._args.begin (); a != context.cli._args.end (); ++a) + for (auto& a : context.cli2._args) { - if (a->hasTag ("MODIFICATION")) + if (a.hasTag ("MODIFICATION")) { - if (a->hasTag ("ATTRIBUTE")) + if (a._lextype == Lexer::Type::pair) { - // 'name' is canonical. + // 'canonical' is the canonical name. Needs to be said. // 'value' requires eval. - std::string name = a->attribute ("name"); - std::string value = a->attribute ("value"); + std::string name = a.attribute ("canonical"); + std::string value = a.attribute ("value"); if (value == "" || value == "''" || value == "\"\"") @@ -1933,13 +1994,39 @@ } else { - // Get the column info. - Column* column = context.columns[name]; + Lexer::dequote (value); - // Some columns are not modifiable. - if (! column->modifiable ()) + // Get the column info. Some columns are not modifiable. + Column* column = context.columns[name]; + if (! column || + ! column->modifiable ()) throw format (STRING_INVALID_MOD, name, value); + // String type attributes only get DOM resolution, no eval. + Variant evaluatedValue; + if (name != "project" || Lexer::isDOM (value)) + { + // Try to evaluate 'value'. It might work. + try + { + Eval e; + e.addSource (domSource); + e.addSource (namedDates); + contextTask = *this; + e.evaluateInfixExpression (value, evaluatedValue); + } + + // Ah, fuck it. + catch (...) + { + evaluatedValue = Variant (value); + } + } + else + { + evaluatedValue = Variant (value); + } + // Dependencies are specified as IDs. if (name == "depends") { @@ -1948,79 +2035,101 @@ split (deps, value, ','); // Apply or remove dendencies in turn. - std::vector ::iterator i; - for (i = deps.begin (); i != deps.end (); i++) + for (auto& dep : deps) { - if ((*i)[0] == '-') + if (dep[0] == '-') { - if ((*i).length () == 37) - removeDependency (context.tdb2.pending.id ((*i).substr (1))); + if (dep.length () == 37) + removeDependency (context.tdb2.pending.id (dep.substr (1))); else - removeDependency (strtol ((*i).substr (1).c_str (), NULL, 10)); + removeDependency (strtol (dep.substr (1).c_str (), NULL, 10)); } else { - if ((*i).length () == 36) - addDependency (context.tdb2.pending.id ((*i))); + if (dep.length () == 36) + addDependency (context.tdb2.pending.id (dep)); else - addDependency (strtol ((*i).c_str (), NULL, 10)); + addDependency (strtol (dep.c_str (), NULL, 10)); } } ++modCount; } - // Dates are special, maybe. - else if (column->type () == "date") + // For those using the "tags:..." attribute directly. + else if (name == "tags") { - Eval e; - e.addSource (domSource); - e.addSource (namedDates); - e.ambiguity (false); - contextTask = *this; + // TW-1701 + set ("tags", ""); - Variant v; - e.evaluateInfixExpression (value, v); + std::vector tags; + split (tags, value, ','); + for (auto& tag : tags) + { + // If it's a DOM ref, eval it first. + Lexer lexer (tag); + std::string domRef; + Lexer::Type type; + if (lexer.token (domRef, type) && + type == Lexer::Type::dom) + { + Eval e; + e.addSource (domSource); + e.addSource (namedDates); + contextTask = *this; + + Variant v; + e.evaluateInfixExpression (value, v); + addTag ((std::string) v); + context.debug (label + "tags <-- '" + (std::string) v + "' <-- '" + tag + "'"); + } + else + { + addTag (tag); + context.debug (label + "tags <-- '" + tag + "'"); + } + + feedback_special_tags (*this, tag); + } + + ++modCount; + } + + // Dates are special, maybe. + else if (column->type () == "date") + { // If v is duration, add 'now' to it, else store as date. - if (v.type () == Variant::type_duration) + if (evaluatedValue.type () == Variant::type_duration) { - context.debug (label + name + " <-- '" + format ("{1}", v.get_duration ()) + "' <-- '" + (std::string) v + "' <-- '" + value + "'"); + context.debug (label + name + " <-- '" + format ("{1}", format (evaluatedValue.get_duration ())) + "' <-- '" + (std::string) evaluatedValue + "' <-- '" + value + "'"); Variant now; if (namedDates ("now", now)) - v += now; + evaluatedValue += now; } else { - v.cast (Variant::type_date); - context.debug (label + name + " <-- '" + format ("{1}", v.get_date ()) + "' <-- '" + (std::string) v + "' <-- '" + value + "'"); + evaluatedValue.cast (Variant::type_date); + context.debug (label + name + " <-- '" + format ("{1}", evaluatedValue.get_date ()) + "' <-- '" + (std::string) evaluatedValue + "' <-- '" + value + "'"); } // If a date doesn't parse (2/29/2014) then it evaluates to zero. if (value != "" && - v.get_date () == 0) + evaluatedValue.get_date () == 0) throw format (STRING_DATE_INVALID_FORMAT, value, Variant::dateFormat); - set (name, v.get_date ()); + set (name, evaluatedValue.get_date ()); ++modCount; } // Special case: type duration. // Note: "recur" is marked as type "string" to force storage in raw form. - else if (name == "recur" || - column->type () == "duration") + else if (name == "recur") { // The duration is stored in raw form, but it must still be valid, // and therefore is parsed first. - Eval e; - e.addSource (domSource); - e.addSource (namedDates); - e.ambiguity (false); - contextTask = *this; - - Variant v; - e.evaluateInfixExpression (value, v); - if (v.type () == Variant::type_duration) + + if (evaluatedValue.type () == Variant::type_duration) { // Store the raw value, for 'recur'. context.debug (label + name + " <-- '" + value + "'"); @@ -2031,62 +2140,52 @@ throw format (STRING_TASK_INVALID_DUR, value); } + else if (column->type () == "duration") + { + // The duration is stored in raw form, but it must still be valid, + // and therefore is parsed first. + + if (evaluatedValue.type () == Variant::type_duration) + { + // Store the raw value, for 'recur'. + context.debug (label + name + " <-- " + (std::string) evaluatedValue + " <-- '" + value + "'"); + set (name, evaluatedValue); + ++modCount; + } + else + throw format (STRING_TASK_INVALID_DUR, value); + } + // Need handling for numeric types, used by UDAs. else if (column->type () == "numeric") { - Eval e; - e.addSource (domSource); - e.addSource (namedDates); - e.ambiguity (false); - contextTask = *this; - - Variant v; - e.evaluateInfixExpression (value, v); - context.debug (label + name + " <-- '" + v.get_string () + "' <-- '" + value + "'"); + context.debug (label + name + " <-- '" + evaluatedValue.get_string () + "' <-- '" + value + "'"); // If the result is not readily convertible to a numeric value, // then this is an error. - if (v.type () == Variant::type_string) - throw format (STRING_UDA_NUMERIC, v.get_string ()); + if (evaluatedValue.type () == Variant::type_string) + throw format (STRING_UDA_NUMERIC, evaluatedValue.get_string ()); - set (name, v); + set (name, evaluatedValue); ++modCount; } - // String type columns may eval, or may not make sense to eval, and - // the best way to determine this is to try. + // String type columns are not eval'd. Welll, not much. else if (column->type () == "string") { - std::string evaluated = value; - try - { - Eval e; - e.addSource (domSource); - e.addSource (namedDates); - e.ambiguity (false); - contextTask = *this; - - Variant v; - e.evaluateInfixExpression (value, v); - v.cast (Variant::type_string); - evaluated = v.get_string (); - } - - catch (...) { /* NOP */ } - - // Final default action - if (column->validate (evaluated)) + std::string strValue = (std::string) evaluatedValue; + if (column->validate (strValue)) { if (column->can_modify ()) { - std::string col_value = column->modify (evaluated); - context.debug (label + name + " <-- '" + col_value + "' <-- '" + evaluated + "' <-- '" + value + "'"); + std::string col_value = column->modify (strValue); + context.debug (label + name + " <-- '" + col_value + "' <-- '" + strValue + "' <-- '" + value + "'"); (*this).set (name, col_value); } else { - context.debug (label + name + " <-- '" + evaluated + "' <-- '" + value + "'"); - (*this).set (name, evaluated); + context.debug (label + name + " <-- '" + strValue + "' <-- '" + value + "'"); + (*this).set (name, strValue); } ++modCount; @@ -2097,33 +2196,32 @@ else throw format (STRING_TASK_INVALID_COL_TYPE, column->type (), name); - - // Warn about deprecated/obsolete attribute usage. - legacyAttributeCheck (name); } } - // arg7 from='from' global='1' raw='/from/to/g' to='to' ORIGINAL SUBSTITUTION MODIFICATION - else if (a->hasTag ("SUBSTITUTION")) + // Perform description/annotation substitution. + else if (a._lextype == Lexer::Type::substitution) { - context.debug (label + "substitute " + a->attribute ("raw")); - substitute (a->attribute ("from"), - a->attribute ("to"), - (a->attribute ("global") == "1")); + context.debug (label + "substitute " + a.attribute ("raw")); + substitute (a.attribute ("from"), + a.attribute ("to"), + a.attribute ("flags")); ++modCount; } // Tags need special handling because they are essentially a vector stored // in a single string, therefore Task::{add,remove}Tag must be called as // appropriate. - else if (a->hasTag ("TAG")) + else if (a._lextype == Lexer::Type::tag) { - std::string tag = a->attribute ("name"); - if (a->attribute ("sign") == "+") + std::string tag = a.attribute ("name"); + feedback_reserved_tags (tag); + + if (a.attribute ("sign") == "+") { context.debug (label + "tags <-- add '" + tag + "'"); addTag (tag); - feedback_special_tags ((*this), tag); + feedback_special_tags (*this, tag); } else { @@ -2134,21 +2232,12 @@ ++modCount; } - // WORD and TERMINATED args are accumulated. - else if (a->hasTag ("WORD") || - a->hasTag ("TERMINATED")) - { - if (text != "") - text += ' '; - text += a->attribute ("raw"); - } - // Unknown args are accumulated as though they were WORDs. else { if (text != "") text += ' '; - text += a->attribute ("raw"); + text += a.attribute ("raw"); } } } @@ -2157,6 +2246,8 @@ // any. if (text != "") { + Lexer::dequote (text); + switch (type) { case modReplace: diff -Nru task-2.4.4+dfsg/src/Task.h task-2.5.0+dfsg/src/Task.h --- task-2.4.4+dfsg/src/Task.h 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/Task.h 2015-10-21 21:18:15.000000000 +0000 @@ -32,6 +32,7 @@ #include #include #include +#include class Task : public std::map { @@ -48,10 +49,8 @@ static float urgencyScheduledCoefficient; static float urgencyWaitingCoefficient; static float urgencyBlockedCoefficient; - static float urgencyInheritCoefficient; static float urgencyAnnotationsCoefficient; static float urgencyTagsCoefficient; - static float urgencyNextCoefficient; static float urgencyDueCoefficient; static float urgencyBlockingCoefficient; static float urgencyAgeCoefficient; @@ -63,6 +62,7 @@ Task& operator= (const Task&); // Assignment operator bool operator== (const Task&); // Comparison operator Task (const std::string&); // Parse + Task (const json::object*); // Parse ~Task (); // Destructor void parse (const std::string&); @@ -112,6 +112,8 @@ bool is_duemonth () const; bool is_dueyear () const; bool is_overdue () const; + bool is_udaPresent () const; + bool is_orphanPresent () const; #endif status getStatus () const; @@ -140,10 +142,9 @@ void getDependencies (std::vector &) const; void getDependencies (std::vector &) const; - void getUDAs (std::vector &) const; void getUDAOrphans (std::vector &) const; - void substitute (const std::string&, const std::string&, bool); + void substitute (const std::string&, const std::string&, const std::string&); #endif void validate (bool applyDefault = true); @@ -157,6 +158,7 @@ private: int determineVersion (const std::string&); void parseJSON (const std::string&); + void parseJSON (const json::object*); void parseLegacy (const std::string&); void validate_before (const std::string&, const std::string&); const std::string encode (const std::string&) const; @@ -171,7 +173,6 @@ float urgency_inherit () const; float urgency_annotations () const; float urgency_tags () const; - float urgency_next () const; float urgency_due () const; float urgency_blocking () const; float urgency_age () const; diff -Nru task-2.4.4+dfsg/src/TDB2.cpp task-2.5.0+dfsg/src/TDB2.cpp --- task-2.4.4+dfsg/src/TDB2.cpp 2015-05-12 07:52:25.000000000 +0000 +++ task-2.5.0+dfsg/src/TDB2.cpp 2015-10-21 21:18:15.000000000 +0000 @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #include #include @@ -43,6 +43,8 @@ extern Context context; +bool TDB2::debug_mode = false; + //////////////////////////////////////////////////////////////////////////////// TF2::TF2 () : _read_only (false) @@ -57,8 +59,8 @@ //////////////////////////////////////////////////////////////////////////////// TF2::~TF2 () { - if (_dirty && context.verbose ("debug")) - std::cout << format (STRING_TDB2_DIRTY_EXIT, _file) + if (_dirty && TDB2::debug_mode) + std::cout << format (STRING_TDB2_DIRTY_EXIT, std::string (_file)) << "\n"; } @@ -115,21 +117,34 @@ } //////////////////////////////////////////////////////////////////////////////// -// Locate task by uuid. +// Locate task by uuid, which may be a partial UUID. bool TF2::get (const std::string& uuid, Task& task) { if (! _loaded_tasks) load_tasks (); - std::vector ::iterator i; - for (i = _tasks.begin (); i != _tasks.end (); ++i) + if (_tasks_map.size () > 0 && uuid.size () == 36) { - if (i->get ("uuid") == uuid) + // Fast lookup, same result as below. Only used during "task import". + auto i = _tasks_map.find (uuid); + if (i != _tasks_map.end ()) { - task = *i; + task = i->second; return true; } } + else + { + // Slow lookup, same result as above. + for (auto& i : _tasks) + { + if (closeEnough (i.get ("uuid"), uuid, uuid.length ())) + { + task = i; + return true; + } + } + } return false; } @@ -140,9 +155,8 @@ if (! _loaded_tasks) load_tasks (); - std::vector ::iterator i; - for (i = _tasks.begin (); i != _tasks.end (); ++i) - if (i->get ("uuid") == uuid) + for (auto& i : _tasks) + if (i.get ("uuid") == uuid) return true; return false; @@ -154,6 +168,10 @@ _tasks.push_back (task); // For subsequent queries _added_tasks.push_back (task); // For commit/synch + // For faster lookup + if (context.cli2.getCommand () == "import") + _tasks_map.insert (std::pair (task.get("uuid"), task)); + Task::status status = task.getStatus (); if (task.id == 0 && (status == Task::pending || @@ -172,14 +190,24 @@ //////////////////////////////////////////////////////////////////////////////// bool TF2::modify_task (const Task& task) { - // Modify in-place. std::string uuid = task.get ("uuid"); - std::vector ::iterator i; - for (i = _tasks.begin (); i != _tasks.end (); ++i) + + if (context.cli2.getCommand () == "import") { - if (i->get ("uuid") == uuid) + // Update map used for faster lookup + auto i = _tasks_map.find (uuid); + if (i != _tasks_map.end ()) { - *i = task; + i->second = task; + } + } + + for (auto& i : _tasks) + { + if (i.get ("uuid") == uuid) + { + // Modify in-place. + i = task; _modified_tasks.push_back (task); _dirty = true; @@ -229,24 +257,14 @@ _file.lock (); // Write out all the added tasks. - std::vector ::iterator task; - for (task = _added_tasks.begin (); - task != _added_tasks.end (); - ++task) - { - _file.append (task->composeF4 () + "\n"); - } + for (auto& task : _added_tasks) + _file.append (task.composeF4 () + "\n"); _added_tasks.clear (); // Write out all the added lines. - std::vector ::iterator line; - for (line = _added_lines.begin (); - line != _added_lines.end (); - ++line) - { - _file.append (*line); - } + for (auto& line : _added_lines) + _file.append (line); _added_lines.clear (); _file.close (); @@ -264,22 +282,12 @@ _file.truncate (); // Only write out _tasks, because any deltas have already been applied. - std::vector ::iterator task; - for (task = _tasks.begin (); - task != _tasks.end (); - ++task) - { - _file.append (task->composeF4 () + "\n"); - } + for (auto& task : _tasks) + _file.append (task.composeF4 () + "\n"); // Write out all the added lines. - std::vector ::iterator line; - for (line = _added_lines.begin (); - line != _added_lines.end (); - ++line) - { - _file.append (*line); - } + for (auto& line : _added_lines) + _file.append (line); _added_lines.clear (); _file.close (); @@ -299,9 +307,8 @@ load_lines (); // Apply previously added lines. - std::vector ::iterator i; - for (i = _added_lines.begin (); i != _added_lines.end (); ++i) - _lines.push_back (*i); + for (auto& line : _added_lines) + _lines.push_back (line); } int line_number = 0; @@ -310,23 +317,24 @@ // Reduce unnecessary allocations/copies. _tasks.reserve (_lines.size ()); - std::vector ::iterator i; - for (i = _lines.begin (); i != _lines.end (); ++i) + for (auto& line : _lines) { ++line_number; - Task task (*i); + Task task (line); // Some tasks get an ID. if (_has_ids) { Task::status status = task.getStatus (); // Completed / deleted tasks in pending.data get an ID if GC is off. - if (!context.run_gc || + if (! context.run_gc || (status != Task::completed && status != Task::deleted)) task.id = context.tdb2.next_id (); } _tasks.push_back (task); + if (context.cli2.getCommand () == "import") // For faster lookup only + _tasks_map.insert (std::pair (task.get("uuid"), task)); // Maintain mapping for ease of link/dependency resolution. // Note that this mapping is not restricted by the filter, and is @@ -374,13 +382,12 @@ load_tasks (); // Apply previously added tasks. - std::vector ::iterator i; - for (i = _added_tasks.begin (); i != _added_tasks.end (); ++i) - _tasks.push_back (*i); + for (auto& task : _added_tasks) + _tasks.push_back (task); } - std::map ::const_iterator i; - if ((i = _I2U.find (id)) != _I2U.end ()) + auto i = _I2U.find (id); + if (i != _I2U.end ()) return i->second; return ""; @@ -394,13 +401,12 @@ load_tasks (); // Apply previously added tasks. - std::vector ::iterator i; - for (i = _added_tasks.begin (); i != _added_tasks.end (); ++i) - _tasks.push_back (*i); + for (auto& task : _added_tasks) + _tasks.push_back (task); } - std::map ::const_iterator i; - if ((i = _U2I.find (uuid)) != _U2I.end ()) + auto i = _U2I.find (uuid); + if (i != _U2I.end ()) return i->second; return 0; @@ -448,38 +454,32 @@ void TF2::dependency_scan () { // Iterate and modify TDB2 in-place. Don't do this at home. - std::vector ::iterator left; - for (left = _tasks.begin (); - left != _tasks.end (); - ++left) + for (auto& left : _tasks) { - if (left->has ("depends")) + if (left.has ("depends")) { std::vector deps; - left->getDependencies (deps); + left.getDependencies (deps); - std::vector ::iterator d; - for (d = deps.begin (); d != deps.end (); ++d) + for (auto& dep : deps) { - std::vector ::iterator right; - for (right = _tasks.begin (); - right != _tasks.end (); - ++right) + for (auto& right : _tasks) { - if (right->get ("uuid") == *d) + if (right.get ("uuid") == dep) { // GC hasn't run yet, check both tasks for their current status - Task::status lstatus = left->getStatus (); - Task::status rstatus = right->getStatus (); + Task::status lstatus = left.getStatus (); + Task::status rstatus = right.getStatus (); if (lstatus != Task::completed && lstatus != Task::deleted && rstatus != Task::completed && rstatus != Task::deleted) { - left->is_blocked = true; - right->is_blocking = true; + left.is_blocked = true; + right.is_blocking = true; } + // Only want to break out of the "right" loop. break; } } @@ -497,7 +497,7 @@ // File label. std::string label; - std::string::size_type slash = _file._data.rfind ('/'); + auto slash = _file._data.rfind ('/'); if (slash != std::string::npos) label = rightJustify (_file._data.substr (slash + 1), 14); @@ -584,7 +584,7 @@ if (add_to_backlog) context.hooks.onAdd (task); - update (uuid, task, add_to_backlog, true); + update (task, add_to_backlog, true); } //////////////////////////////////////////////////////////////////////////////// @@ -602,12 +602,11 @@ context.hooks.onModify (original, task); } - update (uuid, task, add_to_backlog); + update (task, add_to_backlog); } //////////////////////////////////////////////////////////////////////////////// void TDB2::update ( - const std::string& uuid, Task& task, const bool add_to_backlog, const bool addition /* = false */) @@ -619,6 +618,10 @@ Task original; if (not addition && get (task.get ("uuid"), original)) { + // Update only if the tasks differ + if (task == original) + return; + if (add_to_backlog) { // All locally modified tasks are timestamped, implicitly overwriting any @@ -634,7 +637,7 @@ // old // new // --- - undo.add_line ("time " + Date ().toEpochString () + "\n"); + undo.add_line ("time " + ISO8601d ().toEpochString () + "\n"); undo.add_line ("old " + original.composeF4 () + "\n"); undo.add_line ("new " + task.composeF4 () + "\n"); undo.add_line ("---\n"); @@ -653,7 +656,7 @@ // time